Gera's Insecure Programming Advance Buffer Overflow #3

This exercise is compiled on Debian 2.6.32 with NX and ASLR enabled. However, those
protections do not effect the difficulty of the exercise. Exploiting this challenge could have been performed with or without those protections.

ABO #3 source code:
{% highlight c %}
/* abo3.c *

  • specially crafted to feed your brain by gera */

/* This'll prepare you for The Next Step */

int main(int argv,char **argc) {
extern system,puts;
void (fn)(char)=(void()(char))&system;
char buf[256];

fn=(void(*)(char*))&puts;
strcpy(buf,argc[1]);
fn(argc[2]);
exit(1);

}
{% endhighlight %}

It may seem that a straight-forward buffer overflow is possible; however, this is not the case due to exit(). The exercise takes two user arguments. The binary will display the second user argument using puts(). Exploiting this challenge requires the need to overwrite a function pointer to avoid the exit() "restriction." If the function pointer fn is overwritten with the address to system(), the second argument will be used as system()'s argument.

{% highlight bash %}
lixor@debian:~/InsecureProgramming/abo3$ ./abo3 AAAA BBBB
BBBB
{% endhighlight %}

The functions puts() and system() are compiled into the binary. Since the function pointers (puts()/system()) are declared (extern), the pointers to system() and puts() can be found in the disassemble during assignment or from within gdb.

Modified output of objdump -M intel -d abo3. The full dump can be found here
{% highlight bash %}
..snip..
8048480: c7 84 24 1c 01 00 00 mov DWORD PTR [esp+0x11c],0x8048364
8048487: 64 83 04 08
804848b: c7 84 24 1c 01 00 00 mov DWORD PTR [esp+0x11c],0x8048394
8048492: 94 83 04 08
..snip...
{% endhighlight %}

In the snippet above, the instructions are assigning system and puts to fn. The addresses 0x8048364 and 0x8048394 are system() and puts(), respectively. When you look at the source code, the function pointer fn was assigned two values; first assigned to system() followed by puts().

The next issue is to determine the offset between buf and fn.

This is a modified output of gdb (using mammon_'s .gdbinit) while stepping through the binary.
{% highlight bash %}
lixor@debian:~/InsecureProgramming/abo3$ gdb -q --args ./abo3 AAAA BBBB
..snip (stepped through program until function pointer is called)..


 eax:BFFFF669 ebx:B7FCCFF4  ecx:00000000  edx:00000005     eflags:00200282
 esi:00000000 edi:00000000  esp:BFFFF300  ebp:BFFFF428     eip:080484B9
 cs:0073  ds:007B  es:007B  fs:0000  gs:0033  ss:007B    o d I t S z a p c 

[007B:BFFFF300]---------------------------------------------------------[stack]
BFFFF330 : CA 00 00 00 06 00 00 00 - 78 F3 FF BF C4 ED E8 B7 ........x.......
BFFFF320 : 00 60 FE B7 24 F5 FF B7 - 00 00 00 00 33 00 00 00 .`..$.......3...
BFFFF310 : 9C F3 FF BF C6 BF FE B7 - F4 EF FF B7 41 41 41 41 ............AAAA
BFFFF300 : 69 F6 FF BF 64 F6 FF BF - B8 EB E8 B7 01 00 00 00 i...d...........
[007B:BFFFF669]---------------------------------------------------------[ data]
BFFFF669 : 42 42 42 42 00 4F 52 42 - 49 54 5F 53 4F 43 4B 45 BBBB.ORBIT_SOCKE
BFFFF679 : 54 44 49 52 3D 2F 74 6D - 70 2F 6F 72 62 69 74 2D TDIR=/tmp/orbit-
[0073:080484B9]---------------------------------------------------------[ code]
0x80484b9 <main+69>: mov 0x11c(%esp),%eax
0x80484c0 <main+76>: call *%eax
0x80484c2 <main+78>: movl $0x1,(%esp)
0x80484c9 <main+85>: call 0x80483a4 exit@plt
0x80484ce: nop
0x80484cf: nop