:: [etc] How i smashed the stack on fc4. ::
HOME


[Date Prev][Date Next][Date Index]

[etc] How i smashed the stack on fc4.




Below is the program (test.c) with the offset values set as shown.

--------------SNIP--------------------
#include <stdio.h>
int offset1 = 28;
int offset2 = 13;
void function(int a, int b, int c) {
  unsigned char buffer1[5] = "abcde";
  int *ret,i;

  ret = buffer1 + offset1;
  (*ret) += offset2;

}

int main() {
  int x;

  x = 5;
  function(1,2,3);
  x = 1;
  printf("x should be 1 but it is %d\n",x);
}
--------------SNIP--------------------


Program Compilation:

#> gcc -o test test.c


Executing the program: #> ./test x should be 1 but it is 5


Machine used: Linux mia.ece.uic.edu 2.6.12-1.1376_FC3 ... i686 i686 i386
GNU/Linux



Stack Layout is:

  Top of stack ==>   4 bytes  [int i]
                     4 bytes  [int *ret]
                     16 bytes [char buffer1[5]]
                     4 bytes  [* _libc_csu_init]
                     4 bytes  [* _GLOBAL_OFFSET_TABLE_]
                     4 bytes  [* Frame_pointer of prev Stack frame]
                     4 bytes  [ return address]
                     4 bytes  [ parameter 1]
                     4 bytes  [ parameter 2]
                     4 bytes  [ parameter 3]


To find out the stack layout, i proceeded as follows:

1: Compile the program using the -g option so that we can debug it using gdb.
#> gcc -g -o test test.c

2: Run gdb on it as:
#>gdb test
--snip--
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB  was configured as  "i386-redhat-linux-gnu"...Using host libthread_db
library "/lib/tls/libthread_db.so.1".

(gdb) start
Breakpoint 1 at 0x80483b7: file test.c, line 16.
Starting program: /home/shashank/ece594/test Reading symbols from shared object read from target memory...done.
Loaded system supplied DSO at 0xb7f82000
main () at test.c:16
16 x = 5;
(gdb)


3. Disassemble the main function and find out the possible return address of
the call function.
(gdb) disassemble main
(gdb) disassemble main
Dump of assembler code for function main:
0x0804839b <main+0>: push %ebp
0x0804839c <main+1>: mov %esp,%ebp
0x0804839e <main+3>: sub $0x8,%esp
0x080483a1 <main+6>: and $0xfffffff0,%esp
0x080483a4 <main+9>: mov $0x0,%eax
0x080483a9 <main+14>: add $0xf,%eax
0x080483ac <main+17>: add $0xf,%eax
0x080483af <main+20>: shr $0x4,%eax
0x080483b2 <main+23>: shl $0x4,%eax
0x080483b5 <main+26>: sub %eax,%esp
0x080483b7 <main+28>: movl $0x5,0xfffffffc(%ebp)
0x080483be <main+35>: sub $0x4,%esp
0x080483c1 <main+38>: push $0x3
0x080483c3 <main+40>: push $0x2
0x080483c5 <main+42>: push $0x1
0x080483c7 <main+44>: call 0x8048368 <function>
----------------------------------------------------
0x080483cc .... <== This is the return address after call.
----------------------------------------------------
0x080483cf <main+52>: movl $0x1,0xfffffffc(%ebp)
0x080483d6 <main+59>: sub $0x8,%esp
0x080483d9 <main+62>: pushl 0xfffffffc(%ebp)
0x080483dc <main+65>: push $0x80484d2
0x080483e1 <main+70>: call 0x80482b0 <_init+56>
0x080483e6 <main+75>: add $0x10,%esp
0x080483e9 <main+78>: leave 0x080483ea <main+79>: ret End of assembler dump.
(gdb)



4. Stepi till u reach the first instruction in "function".
--snip--
(gdb) s
17 function(1,2,3);
(gdb) s
function (a=1, b=2, c=3) at test.c:5
5 unsigned char buffer1[5] = "abcde";
(gdb) s
8 ret = buffer1 + offset1; ...


5. Now your  stackframe has been initialized. Take  a look at it.  you can use
gdb's "examine"  command for this  purpose.  Here I  had to do some  trial and
error. I knew that  "buffer1 will be allocated some space. But  I did not know
where the  "ret" and "i" will be  allocated. So i wrote  another small program
that initializes i=0xff and examined all 40 bytes before and after the pointer
to buffer1 as below:

  a. 40 bytes after buffer1
--snip--
gdb) x /40xb buffer1
0xbfd7fd60:     0x61    0x62    0x63    0x64    0x65    0x00    0x00    0x00
0xbfd7fd68:     0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0xbfd7fd70:     0xec    0x83    0x04    0x08    0xd4    0x95    0x04    0x08
0xbfd7fd78:     0xa8    0xfd    0xd7    0xbf    0xcc    0x83    0x04    0x08
0xbfd7fd80:     0x01    0x00    0x00    0x00    0x02    0x00    0x00    0x00
--snip--

Note  that  first five  bytes  represent  ascii values  of  "a,  b,  c, d,  e"
respectively.  From the  above I can see that 16 bytes  have been reserved for
buffer1 as below

0xbfd7fd60:     0x61    0x62    0x63    0x64    0x65    0x00    0x00    0x00
0xbfd7fd68:     0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00

The  next  4  bytes,  i.e.  "0xec  0x83  0x04  0x08"  represent  some  address
"0x080483ec". Looks like some pointer to some address.  To see where it points
to i do
(gdb) x 0x080483ec
0x80483ec <__libc_csu_init>:    0x55
Seems like it is a pointer to some internal routine of glibc.

The next 4  bytes i.e. "0xd4 0x95  0x04 0x08" again look like  some pointer to
something. Again
(gdb) x 0x080495d4
0x80495d4 <_GLOBAL_OFFSET_TABLE_>:      0x08
shows that its the global offset table.

The next  4 bytes again  are a  pointer "0xa8 0xfd  0xd7 0xbf" are  pointer to
somewhere in stack.  I conclude that it is the frame  pointer for the previous
frame.

The last four  bytes "0xcc 0x83 0x04  0x08" are the return address  in my main
function.

After this we have  the parameters 1 (0x01 0x00 0x00 0x00),  2 (0x02 0x00 0x00
0x00) and 3(not shown) which are integers and hence have 4 byte wide fields.


b. 20 bytes before buffer1. --snip-- (gdb) x /40xb &buffer1[-20] 0xbfd7fd4c: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xbfd7fd54: 0x00 0x00 0x00 0x00 0x8e 0xff 0x77 0x01 0xbfd7fd5c: 0xe0 0xfd 0xd7 0xbf [0x61 0x62 0x63 0x64 0xbfd7fd64: 0x65 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xbfd7fd6c: 0x00 0x00 0x00 0x00 ] 0xec 0x83 0x04 0x08

 Note:  buffer1  exists  between  the  square brackets  above.   The  4  bytes
(0xbfd7fde0) preceeding  buffer1 must be int  *ret and the  preceeding 4 bytes
(0x0177ff8e) must be  the interger i.  (you can actually  see that these bytes
are initialized to 0xff if that is done in the program).






Comments and corrections are appreciated and can be sent to papers@mia.ece.uic.edu. Click here for ©opyright information.