根据PPC反汇编代码分析堆栈内容
来源:互联网 发布:win10软件图标异常 编辑:程序博客网 时间:2024/05/16 05:10
1 栈帧
我们知道,发生函数调用时,通常被调用函数会保存调用函数的现场,然后才会继续执行被调用函数的指令,被调用函数执行完成之后,就会恢复调用函数的现场,继续执行调用函数的指令。栈帧就是在堆栈中保存每一次函数调用现场的一个基本单元。每一次函数调用都会在堆栈中记录函数的栈帧。
2 汇编指令
下面我们反汇编下DbugExcShowAll函数,得到如下的反汇编代码。
DbugExcShowAll:
0x103e48cc 9421ffd0 stwu r1,-48(r1)
0x103e48d0 7c0802a6 mfspr r0,LR
0x103e48d4 93810020 stw r28,32(r1)
0x103e48d8 93a10024 stw r29,36(r1)
0x103e48dc 93e1002c stw r31,44(r1)
0x103e48e0 90010034 stw r0,52(r1)
0x103e48e4 7c3f0b78 or r31,r1,r1
0x103e48e8 3d20108d lis r9,0x108d #4237------r9=0x108d0000
0x103e48ec 8009a690 lwz r0,-22896(r9)-----
0x103e48f0 901f0008 stw r0,8(r31)
Stwu指令将调用函数的栈帧地址r1,存储到(r1-48)字节处,并且r1=(r1-48),然后将调用函数的LR值写入到r0寄存器,然后将r0保存到堆栈中,也就是将调用函数的LR值保存到栈中,另外这里r1偏移了52个字节,但是,当前堆栈只扩展了48字节的空间,意味着此时已经到了上一层函数栈帧空间,也就是说上一层函数的lr的内容会保存在上一层栈帧空间中。也可以这么认为,在函数调用栈帧中,当前函数的堆栈地址,lr地址会保存到栈帧的栈顶(低地址)。
3 寄存器信息
下面是现场的寄存器信息:
name pid tid ppid PRI STATUS
---------------------------------------------------------
t287805096 90 90 39 64 T
esp:0x79dfdc10 eip :0x103e4920
vm_size:123196 KB vm_lock :0 KB
vm_data:97060 KB vm_stack :3076 KB
vm_rss :16280 KB vm_exe :8424 KB
task_size :0xaa50 resident :4070
start_code :0x10000000 end_code :0x108394d4
start_stack:0x79dffe20 stack_size :0x1fee20
stack_used:0x2210
r0:0x00000000 r1: 0x79dfdc10 r2: 0x79dffe20 r3: 0x0000003b
r4:0x00000001 r5: 0x00000000 r6: 0x0000003b r7: 0x1068ed94
r8:0x0000d032 r9: 0x00000000 r10: 0x00000001 r11: 0x79dfdc10
r12:0xc4c3c000 r13: 0x108d1a80 r14: 0x00000000 r15: 0x00000000
r16:0x111e02d0 r17: 0x00000000 r18: 0x11278ea8 r19: 0x10002040
r20:0x00000006 r21: 0x0000002a r22: 0x7efffe20 r23: 0x0000002d
r24:0x79c01000 r25: 0x79c00000 r26: 0x00000000 r27: 0x00000000
r28:0x00000000 r29: 0x00000000 r30: 0x10002040 r31: 0x79dfdc10
pc:0x103e4920 ps: 0x0000d032 cr: 0x22000088 lr: 0x103e4900
ctr:0x10677938 xer: 0x20000000 fpscr: 0x00000000
从寄存器信息可以看出,当前函数堆栈地址为0x79dfdc10,从上面的汇编可以看出,
该地址是通过上一层函数堆栈偏移48字节获取到的。那么上一层函数堆栈地址为0x79DFDC40。从上面的汇编上看,执行完调用函数本身的下一条指令应该保存到r1+52 = 0x79DFDC44这个地址处。
4 堆栈内容
根据上面的分析,栈顶应该保存的是调用函数的栈地址,栈顶之后的4字节应该保存的是调用函数的lr地址。以DbugExcShowAll的栈帧为例:
79DFDC10: 79 dfdc 40 10 3e 49 00 00 00 00 00 00 00 00 00 *y..@.>I.........*
79DFDC20: 79 dffe 20 00 00 00 00 11 27 8e a8 00 00 00 00 *y.. .....'......*
79DFDC30: 00 0000 00 00 00 00 00 10 00 20 40 79 df fc 50 *.......... @y..P*
79DFDC40: 79 dffd 60 10 00 24 ac 00 00 00 00 00 00 00 01 *y..`..$.........*
79DFDC50: 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 *................*
79DFDC60: 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 *................*
79DFDC70: 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 *................*
栈顶保存的内容为0x79dfdc40,根据之前的分析,该地址正是调用DbugExcShowAll函数的栈地址,接着栈顶的之后的4字节地址保存的正是LR的地址。从汇编上看不出DbugExcShowAll的lr地址是什么时候放入到0x79DFDC14中的。但是,从上面分析可以看出0x79DFDC44对应的内容为0x100024ac,正是task_wrapper对应的代码空间,也就是执行完DbugExcShowAll需要执行的下一条指令。
通过tt命令,可以看到函数的调用链正是task_wrapper=>DbugExcShowAll。
task:t287805096pid:90
task callfunc info:
0x106740f4 pthread_start_thread +0x000000e0 task_wrapper( 0 )
0x10002040 task_wrapper +0x00000468 DbugExcShowAll( )
0x103e48cc DbugExcShowAll
总结
Ppc的栈帧结构比较清晰,从堆栈内容中比较容易分析出函数的调用关系,在堆栈遭到破坏时,还可以通过汇编代码,从汇编代码的堆栈扩展已经堆栈中保存的lr地址,大致推断出破坏堆栈的函数。但是,要非常注意,排除栈中残留的历史堆栈的干扰。
- 根据PPC反汇编代码分析堆栈内容
- 反汇编代码分析
- 反汇编代码分析
- 反汇编及函数调用堆栈分析
- Linux内核分析-1/反汇编(堆栈)
- C++反汇编代码分析
- c代码反汇编,观察堆栈工作原理
- Symbian中反汇编代码分析
- 反汇编代码分析--函数调用
- C++反汇编代码分析--函数调用
- c++反汇编代码分析--循环结构
- C++反汇编代码分析--函数调用
- C++反汇编代码分析--函数调用
- C++反汇编代码分析--函数调用
- c++反汇编代码分析--循环结构
- 反汇编代码分析--函数调用
- C程序反汇编代码分析
- C++反汇编代码分析--函数调用
- QtQuick_1简述
- Apache服务器no_ssl和openssl两种类型的区别
- android 之自定义键盘 实现动态效果
- HDU 3549 Flow Problem(最大流入门)
- Servlet在web.xml文件中的部署
- 根据PPC反汇编代码分析堆栈内容
- [杂谈]脚本语言在游戏发展中的作用
- [Python]networkx入门
- python遇到‘\u’开头的unicode编码
- 快速排序
- Implement strStr() Java
- 收集的linux远程ssh连接putty失败解决办法!
- Exception from container-launch: org.apache.hadoop.util.Shell$ExitCodeException
- hdu1045