Chinaunix首页 | 论坛 | 博客
  • 博客访问: 134380
  • 博文数量: 51
  • 博客积分: 2500
  • 博客等级: 少校
  • 技术积分: 540
  • 用 户 组: 普通用户
  • 注册时间: 2007-07-21 12:33
文章分类

全部博文(51)

文章存档

2011年(1)

2010年(5)

2009年(1)

2008年(12)

2007年(32)

我的朋友

分类: LINUX

2010-10-28 15:21:34

如果stack没有corruption的话,我们可以利用GDBbt命令得到functionbacktrace.

但如果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

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 :   push   %rbp

0x00000000004004b8 :   mov    %rsp,%rbp

0x00000000004004bb :   sub    $0x10,%rsp

0x00000000004004bf :   mov    %edi,0xfffffffffffffffc(%rbp)

0x00000000004004c2 :  mov    %esi,0xfffffffffffffff8(%rbp)

0x00000000004004c5 :  mov    0xfffffffffffffffc(%rbp),%esi

0x00000000004004c8 :  mov    $0x400658,%edi

0x00000000004004cd :  mov    $0x0,%eax

0x00000000004004d2 :  callq  0x400398

0x00000000004004d7 :  mov    0xfffffffffffffff8(%rbp),%edi

0x00000000004004da :  callq  0x400498

0x00000000004004df :  leaveq

0x00000000004004e0 :  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 :   push   %rbp

0x00000000004004e2 :   mov    %rsp,%rbp

0x00000000004004e5 :   sub    $0x10,%rsp

0x00000000004004e9 :   mov    %edi,0xfffffffffffffffc(%rbp)

0x00000000004004ec :  mov    %esi,0xfffffffffffffff8(%rbp)

0x00000000004004ef :  mov    %edx,0xfffffffffffffff4(%rbp)

0x00000000004004f2 :  mov    0xfffffffffffffffc(%rbp),%esi

0x00000000004004f5 :  mov    $0x400658,%edi

0x00000000004004fa :  mov    $0x0,%eax

0x00000000004004ff :  callq  0x400398

0x0000000000400504 :  mov    0xfffffffffffffff4(%rbp),%esi

0x0000000000400507 :  mov    0xfffffffffffffff8(%rbp),%edi

0x000000000040050a :  callq  0x4004b7

0x000000000040050f :  leaveq

0x0000000000400510 :  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 :    push   %rbp

0x0000000000400512 :    mov    %rsp,%rbp

0x0000000000400515 :    sub    $0x10,%rsp

0x0000000000400519 :    movl   $0x4,0xfffffffffffffff0(%rbp)

0x0000000000400520 :   movl   $0x3,0xfffffffffffffff4(%rbp)

0x0000000000400527 :   movl   $0x2,0xfffffffffffffff8(%rbp)

0x000000000040052e :   movl   $0x1,0xfffffffffffffffc(%rbp)

0x0000000000400535 :   mov    0xfffffffffffffff8(%rbp),%edx

0x0000000000400538 :   mov    0xfffffffffffffff4(%rbp),%esi

0x000000000040053b :   mov    0xfffffffffffffff0(%rbp),%edi

0x000000000040053e :   callq  0x4004e1

0x0000000000400543 :   mov    0xfffffffffffffffc(%rbp),%esi

0x0000000000400546 :   mov    $0x400658,%edi

0x000000000040054b :   mov    $0x0,%eax

0x0000000000400550 :   callq  0x400398

0x0000000000400555 :   leaveq

0x0000000000400556 :   retq

End of assembler dump.

 

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

阅读(2315) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-10-29 14:57:27

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com