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反汇编代码分析堆栈内容相关推荐

  1. C++反汇编代码分析

    C++反汇编代码分析--函数调用 代码如下: #include "stdlib.h" int sum(int a,int b,int m,int n) {   return a+b ...

  2. c++反汇编代码分析--偷调函数

    注:不知道说"偷调函数"说法合不合适,在此也就这样一说了~ 主要有两点: 一.再说C++反汇编函数调用,重点是怎样通过堆栈实现由被调用函数转到调用者 二.在 1 的基础上,在Win ...

  3. 反汇编代码分析--函数调用

    C++反汇编代码分析--函数调用 代码如下: #include "stdlib.h" int sum(int a,int b,int m,int n) {   return a+b ...

  4. C++反汇编代码分析--函数调用

    推荐阅读: C++反汇编代码分析–函数调用 C++反汇编代码分析–循环结构 C++反汇编代码分析–偷调函数 走进内存,走进汇编指令来看C/C++指针 代码如下: #include "stdl ...

  5. 反汇编基础-数组和指针的反汇编代码分析

    程序源码如下: #include <stdio.h>int main(){const char c = 'A';char str[] = "Hello World!"; ...

  6. Cortex-M启动代码分析(以STM32F4为例)

    ARM Cortex-M系列MCU的启动代码(使用汇编语言编程则不需要)主要做3件事情: 1.初始化并正确放置异常/中断向量表: 2.分散加载: 3.初始化C语言运行环境(初始化堆栈以及C Libra ...

  7. Exp4 恶意代码分析 20164303 景圣

    Exp4 恶意代码分析 实验内容 实验点一:系统运行监控 (1)使用如计划任务,每隔一分钟记录自己的电脑有哪些程序在联网,连接的外部IP是哪里.运行一段时间并分析该文件,综述一下分析结果.目标就是找出 ...

  8. 控制元素显示和隐藏的方式及区别、内容溢出处理(区域滚动)、透明性、字体图标、常见字体、自定义字体设计、网站图标、CSS代码分析

    元素的显示与隐藏: 常见控制元素的显示和隐藏的属性有display.visibility.overflow,需要清楚的理解三者之间的区别. display显示: 当值为none时为销毁对象,不保留原位 ...

  9. 网安--第七章 恶意代码分析与防治

    第7章 恶意代码分析与防治 内容提要 ◎ 恶意代码的发展史和恶意代码长期存在的原因 ◎ 恶意代码实现机理.定义以及攻击方法 ◎ 恶意代码生存技术.隐藏技术,介绍网络蠕虫的定义以及结构 ◎ 恶意代码防范 ...

最新文章

  1. MathType在手,公式不求人!
  2. 使用MrBayes构建贝叶斯系统发育树【实践】
  3. Web端a标签跳转地图等链接(收藏)
  4. 【CIO说】转型SaaS,为什么Oracle、SAP的第一选择是人力资源软件
  5. MT7628/MT7688 修改串口2作为调试串口 所踩的坑
  6. python调用mysql中的自定义function并且返回结果
  7. 产生线程安全的原因(2)(操作系统)
  8. 10.11.5 brew mysql_mac os10.11下安装MySQLdb
  9. Eclipse中与CVS相连的工程中的文件,不显示版本信息时,如何处理(重启Eclipse)!
  10. Tip:创建SCOM 2012 R2报表服务器时的报错
  11. SQL Server 中的 JSON 数据
  12. 以编程方式管理IIS
  13. struts2的struts.properties配置文件详解 (转)
  14. 单片机C语言的编译模式,手把手教你学单片机的C语言程序设计六编译预处理.pdf...
  15. Power bi 3.6 百分比堆积柱形图
  16. 最全最新cpu显卡天梯图_CPU天梯图2020年-2020年最新CPU天梯图(高清大图) - 系统家园...
  17. 【OSS】使用Element实现图片上传到OSS
  18. android 360度视频播放器,Android开发VR实战之播放360度全景视频
  19. 2015互联网校招总结—一路走来
  20. 产品经理如何设计网页导航菜单

热门文章

  1. npm创建angular项目
  2. Linux Zram配置使用(特定平台个人使用,maybe不具普适性)
  3. 伯克利双专业 经济学和计算机专业,美国加州伯克利大学世界排名第几2021
  4. powerbi使用说明_powerBI步骤
  5. python爬虫,wallhaven热门壁纸多线程采集下载源码
  6. MT4电脑版下载和安装
  7. python读取txt中文乱码
  8. C语言 序列排序并去重
  9. 生命不息,折腾不止:Jetson Nano填坑之软件篇
  10. C语言基础教程 之 字符串