【转】根据EBP得到函数堆栈

【原文地址】http://blog.chinaunix.net/uid-8118579-id-2034131.html

 

如果stack没有corruption的话,我们可以利用GDB的bt命令得到function的backtrace.

但如果stack corruption了,gdb是不能帮我们得到backtrace的。本文介绍了根据EBP得到backtrace的方法,这种方法只适用于X86架构。

 

栈的基本模型

 

 

 

参数N

高地址

参数

函数参数入栈的顺序与具体的调用方式有关

参数 3

参数 2

参数 1

eip

返回本次调用后,下一条指令的地址

ebp

这里保存调用者的ebp,然后ebp寄存器会指向此时的栈顶。

临时变量1

 

临时变量2

 

临时变量3

 

临时变量

 

临时变量n

低地址

 

 

 

函数调用发生的时候,先把函数参数(从右往左顺序压)压入stack,再压入函数调用的下条指令的address. 接着进入调用函数体中先执行"pushl %ebp""movl %esp, %ebp"(一般已经由编译器加入到函数头中了),接着就是把函数体中的局部变量压入栈中。再遇到函数的调用的嵌套则依此类推。

 

这个方法的基本原理是先得到EBP中的地址,根据这个地址可以得到调用者的ebp的地址,然后我们可以根据调用者的EBP得到调用函数时的指令地址(ebp+4, 32-bit OS),然后利用gdbdisassem命令得到函数调用的地址。以此类推,我们可以得到整个函数调用的堆栈。

 

一个例子:

 

#include

 

void funcc(int c)

 

{

 

    printf("%d\n", c);

 

}

 

void funcb(int b, int c)

 

{

 

    printf("%d\n", b);

 

    funcc(c);

 

}

 

void funca(int a, int b, int c)

 

{

 

printf("%d\n", a);  

 

funcb(b, c);

 

}

 

main()

 

{

 

    int a = 4;

 

    int b = 3;

 

    int c = 2;

 

    int d = 1;

 

    funca(a, b, c);

 

    printf("%d\n", d);

 

}

 

Generating a binary with debug info using GCC.

 

gcc –g –o 12 12.c

 

Then using gdb to get the backtrace according to EBP.

 

gdb 12

 

(gdb) b funcc

 

Breakpoint 1 at 0x4004a3: file 12.c, line 5.

 

(gdb) r

 

Starting program: /home/jx/example/12

 

4

 

3

 

 

 

Breakpoint 1, funcc (c=2) at 12.c:5

 

5           printf("%d\n", c);

 

(gdb) info reg

 

rax            0x2      2

 

rbx            0x3a11c19bc0     249406004160

 

rcx            0x3a1214a760     249411446624

 

rdx            0x3a1214b920     249411451168

 

rsi            0x2aaaaaaac000   46912496123904

 

rdi            0x2      2

 

rbp            0x7fff60038730   0x7fff60038730 =è64bit OS, ebp has changed to rbp.

 

rsp            0x7fff60038720   0x7fff60038720

 

r8             0xffffffff       4294967295

 

r9             0x3a11f12a40     249409120832

 

r10            0x22     34

 

r11            0x246    582

 

r12            0x0      0

 

r13            0x7fff60038870   140734804232304

 

r14            0x0      0

 

r15            0x0      0

 

rip            0x4004a3 0x4004a3<funcc+11>

 

eflags         0x202    [ IF ]

 

cs             0x33     51

 

ss             0x2b     43

 

ds             0x0      0

 

es             0x0      0

 

fs             0x0      0

 

gs             0x0      0

 

(gdb) x /8x 0x7fff60038738(0x7fff60038730 + 8, 64bit OS, rbp + 8, eip)

 

(gdb) x /2x 0x7fff60038738

 

0x7fff60038738: 0x004004df      0x00000000

 

(gdb) disassem 0x004004df

 

Dump of assembler code for function funcb:

 

0x00000000004004b7 <funcb+0>:   push   %rbp

 

0x00000000004004b8 <funcb+1>:   mov    %rsp,%rbp

 

0x00000000004004bb <funcb+4>:   sub    $0x10,%rsp

 

0x00000000004004bf <funcb+8>:   mov    %edi,0xfffffffffffffffc(%rbp)

 

0x00000000004004c2 <funcb+11>:  mov    %esi,0xfffffffffffffff8(%rbp)

 

0x00000000004004c5 <funcb+14>:  mov    0xfffffffffffffffc(%rbp),%esi

 

0x00000000004004c8 <funcb+17>:  mov    $0x400658,%edi

 

0x00000000004004cd <funcb+22>:  mov    $0x0,%eax

 

0x00000000004004d2 <funcb+27>:  callq  0x400398<printf@plt>

 

0x00000000004004d7 <funcb+32>:  mov    0xfffffffffffffff8(%rbp),%edi

 

0x00000000004004da <funcb+35>:  callq  0x400498

 

0x00000000004004df <funcb+40>:  leaveq

 

0x00000000004004e0 <funcb+41>:  retq

 

(gdb) x /2x 0x7fff60038730   ==========èget upper stack’s rbp

 

0x7fff60038730: 0x60038750      0x00007fff

 

(gdb) x /2x 0x7fff60038758   ========è upper stack’s rip

 

0x7fff60038758: 0x0040050f      0x00000000

 

(gdb) disassem 0x0040050f

 

Dump of assembler code for function funca:

 

0x00000000004004e1 <funca+0>:   push   %rbp

 

0x00000000004004e2 <funca+1>:   mov    %rsp,%rbp

 

0x00000000004004e5 <funca+4>:   sub    $0x10,%rsp

 

0x00000000004004e9 <funca+8>:   mov    %edi,0xfffffffffffffffc(%rbp)

 

0x00000000004004ec <funca+11>:  mov    %esi,0xfffffffffffffff8(%rbp)

 

0x00000000004004ef <funca+14>:  mov    %edx,0xfffffffffffffff4(%rbp)

 

0x00000000004004f2 <funca+17>:  mov    0xfffffffffffffffc(%rbp),%esi

 

0x00000000004004f5 <funca+20>:  mov    $0x400658,%edi

 

0x00000000004004fa <funca+25>:  mov    $0x0,%eax

 

0x00000000004004ff <funca+30>:  callq  0x400398<printf@plt>

 

0x0000000000400504 <funca+35>:  mov    0xfffffffffffffff4(%rbp),%esi

 

0x0000000000400507 <funca+38>:  mov    0xfffffffffffffff8(%rbp),%edi

 

0x000000000040050a <funca+41>:  callq  0x4004b7

 

0x000000000040050f <funca+46>:  leaveq

 

0x0000000000400510 <funca+47>:  retq

 

End of assembler dump.

 

(gdb) x /2x 0x7fff60038750  =èget upper upper ebp from upper ebp

 

0x7fff60038750: 0x60038770      0x00007fff

 

(gdb) x /2x 0x7fff60038778  =èeip from ebp

 

0x7fff60038778: 0x00400543      0x00000000

 

(gdb) disassem 0x00400543

 

Dump of assembler code for function main:

 

0x0000000000400511 <main+0>:    push   %rbp

 

0x0000000000400512 <main+1>:    mov    %rsp,%rbp

 

0x0000000000400515 <main+4>:    sub    $0x10,%rsp

 

0x0000000000400519 <main+8>:    movl   $0x4,0xfffffffffffffff0(%rbp)

 

0x0000000000400520 <main+15>:   movl   $0x3,0xfffffffffffffff4(%rbp)

 

0x0000000000400527 <main+22>:   movl   $0x2,0xfffffffffffffff8(%rbp)

 

0x000000000040052e <main+29>:   movl   $0x1,0xfffffffffffffffc(%rbp)

 

0x0000000000400535 <main+36>:   mov    0xfffffffffffffff8(%rbp),%edx

 

0x0000000000400538 <main+39>:   mov    0xfffffffffffffff4(%rbp),%esi

 

0x000000000040053b <main+42>:   mov    0xfffffffffffffff0(%rbp),%edi

 

0x000000000040053e <main+45>:   callq  0x4004e1

 

0x0000000000400543 <main+50>:   mov    0xfffffffffffffffc(%rbp),%esi

 

0x0000000000400546 <main+53>:   mov    $0x400658,%edi

 

0x000000000040054b <main+58>:   mov    $0x0,%eax

 

0x0000000000400550 <main+63>:   callq  0x400398<printf@plt>

 

0x0000000000400555 <main+68>:   leaveq

 

0x0000000000400556 <main+69>:   retq

 

End of assembler dump.

 

 

 

So we got the backtrace as main->funca->funcb->funcc

 

posted @ 2015-08-13 22:16  lijinlei  阅读(559)  评论(0编辑  收藏  举报