Here's part of a gdb session looking at 3.43 . $ gdb 3p43 ... (gdb) start Temporary breakpoint 1 at 0x80485f8 Starting program: .../buffer_overflow/3p43 Temporary breakpoint 1, 0x080485f8 in main () (gdb) disas my_getline Dump of assembler code for function my_getline: 0x080485b4 <+0>: push %ebp 0x080485b5 <+1>: mov %esp,%ebp 0x080485b7 <+3>: sub $0x28,%esp 0x080485ba <+6>: lea -0x18(%ebp),%eax 0x080485bd <+9>: mov %eax,(%esp) 0x080485c0 <+12>: call 0x8048408 0x080485c5 <+17>: mov %eax,-0x10(%ebp) 0x080485c8 <+20>: lea -0x18(%ebp),%eax 0x080485cb <+23>: mov %eax,(%esp) 0x080485ce <+26>: call 0x8048438 0x080485d3 <+31>: mov %eax,(%esp) 0x080485d6 <+34>: call 0x8048468 0x080485db <+39>: mov %eax,-0xc(%ebp) 0x080485de <+42>: lea -0x18(%ebp),%eax 0x080485e1 <+45>: mov %eax,0x4(%esp) 0x080485e5 <+49>: mov -0xc(%ebp),%eax 0x080485e8 <+52>: mov %eax,(%esp) 0x080485eb <+55>: call 0x8048448 0x080485f0 <+60>: mov -0xc(%ebp),%eax 0x080485f3 <+63>: leave 0x080485f4 <+64>: ret (gdb) disas main Dump of assembler code for function main: 0x080485f5 <+0>: push %ebp 0x080485f6 <+1>: mov %esp,%ebp => 0x080485f8 <+3>: and $0xfffffff0,%esp 0x080485fb <+6>: sub $0x20,%esp 0x080485fe <+9>: movl $0x80486f0,(%esp) 0x08048605 <+16>: call 0x8048478 0x0804860a <+21>: call 0x80485b4 0x0804860f <+26>: mov %eax,0x1c(%esp) 0x08048613 <+30>: mov $0x8048702,%eax 0x08048618 <+35>: mov 0x1c(%esp),%edx 0x0804861c <+39>: mov %edx,0x4(%esp) 0x08048620 <+43>: mov %eax,(%esp) 0x08048623 <+46>: call 0x8048458 0x08048628 <+51>: mov $0x0,%eax 0x0804862d <+56>: leave 0x0804862e <+57>: ret (gdb) break *(my_getline+9) # Set breakpoint before gets() Breakpoint 2 at 0x80485bd (gdb) continue Continuing. Type something. Breakpoint 2, 0x080485bd in my_getline () (gdb) x/a $esp # Examine address in stack pointer. 0xbffff840: 0xbffff868 # (or type "p /a $esp" ) (gdb) x/a $ebp 0xbffff868: 0xbffff898 # ... and in base pointer (gdb) p $ebp-$esp $1 = 40 # ... which are 40 bytes apart. (gdb) x/16xw $esp # Examine 16 hex words in stack. 0xbffff840: 0xbffff868 0xb7ecf9fb 0xb7fc74e0 0x0000000a 0xbffff850: 0x00000011 0xb7e718d0 0xb7fc74e0 0xb7fc6ff4 0xbffff860: 0x00000000 0x00000000 0xbffff898 0x0804860f 0xbffff870: 0x080486f0 0xb7fc6ff4 0x08048640 0xbffff898 Rearranging that to look like it does in our textbook (bigger on top) and annotating it a bit, that says that the stack looks like this : address 4 bytes ---------- ---------- 0xbffff87c 0xbffff898 0xbffff878 0x08048640 0xbffff874 0xb7fc6ff4 0xbffff870 0x080486f0 0xbffff86c 0x0804860f $ebp+4 = return address = main+26 0xbffff868 0xbffff898 <= $ebp = base pointer 0xbffff864 0x00000000 0xbffff860 0x00000000 0xbffff85c 0xb7fc6ff4 0xbffff858 0xb7fc74e0 0xbffff854 0xb7e718d0 0xbffff850 0x00000011 0xbffff84c 0xbffff898 0xbffff848 0x08048640 0xbffff844 0xb7fc6ff4 0xbffff840 0xbffff868 <= $esp = stack pointer = 'top' (smallest) stack So the next question is: where in here is the input buffer? * Method 1: use "nexti" (next instruction) to step through the code, typing just a couple of characters, and see where they go. * Method 2: look at the assembly before the gets() call and deduce what the buffer argument is. After finding that, the next job is to watch what happens when longer strings are input, and see the return address get overwritten ... which is the "buffer overflow" happening while you watch.