Meditation, The Art of Exploitation

Thinking? At last I have discovered it--thought; this alone is inseparable from me. I am, I exist--that is certain. But for how long? For as long as I am thinking. For it could be, that were I totally to cease from thinking, I should totally cease to exist....I am, then, in the strict sense only a thing that thinks.

Friday, February 23, 2007

Inline assembly with gcc on linux

Sometimes, it's useful to test/debug at assembly level. On linux gcc provides inline assembly to directly embed assembly code into your source code. I was chasing a wierd bug in a multi thread application, the program crashed with SIGSEGV with the following information:

(gdb) bt
#0 0x00d5f3dc in pthread_join () from /lib/libpthread.so.0
#1 0x0804b51b in main (argc=140055452, argv=0x3e8) at main.cpp:214
(gdb) x/20i 0x00d5f3c0
0xd5f3c0 : push %ebp
0xd5f3c1 : mov %esp,%ebp
0xd5f3c3 : push %edi
0xd5f3c4 : push %esi
0xd5f3c5 : push %ebx
0xd5f3c6 : sub $0x28,%esp
0xd5f3c9 : call 0xd5d4fa <__i686.get_pc_thunk.bx>
0xd5f3ce : add $0xac26,%ebx
0xd5f3d4 : mov $0x3,%edi
0xd5f3d9 : mov 0x8(%ebp),%eax
0xd5f3dc : mov 0x48(%eax),%ecx <------------- SIGSEGV
0xd5f3df : test %ecx,%ecx
0xd5f3e1 : js 0xd5f4aa
0xd5f3e7 : mov $0x16,%di
0xd5f3eb : cmp 0x200(%eax),%eax
0xd5f3f1 : je 0xd5f4aa
0xd5f3f7 : mov %gs:0x8,%edi
0xd5f3fe : add $0x200,%eax
0xd5f403 : mov %eax,0x8(%esp)
0xd5f407 : lea 0xffff53b8(%ebx),%eax

The prototype of pthread_join is this: int pthread_join(pthread_t thread, void **value_ptr); Now I couldn't remember how the parameters were passed into a subroutine on the stack, exactly what's in 0x08(%ebp)? Is it thread or value_ptr. Inline assembly to the rescue:

#include < stdio.h>

int foo(int x, int y){
unsigned long int ebp;
asm("movl %%ebp, %[ebp]" : [ebp] "=m" (ebp));
printf("$ebp=%x $x=%x $y=%x\n", ebp, &x, &y);
return x+y;
}
int main(){
int x = 3, y = 4;
foo(x, y);
}

$ ./addr_t
$ebp=bfb799c8 $x=bfb799d0 $y=bfb799d4

clearly, gcc on linux passes the paramter following the C argument passing convention, that is the arguments are pushed onto stack from right to left. The stack looks like this (top is higher memory address):
$y
$x
$ret_addr

And the prelog of pthread_join creates a stack like this:
$y
$x
$ret_addr
$ebp <--------- $ebp = $esp

It's clear now that 0x08(%ebp) is the address of argment 'thread', and apparently something went wrong and 'thread' contains an invalid memory address in the crashed application.