前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从IDA动态调试方法到ARM三级流水线的分析到实操

从IDA动态调试方法到ARM三级流水线的分析到实操

作者头像
FB客服
发布2021-10-11 15:29:23
1.9K0
发布2021-10-11 15:29:23
举报
文章被收录于专栏:FreeBuf

前言

交互式反汇编器,简称为IDA。是目前最棒的一个静态反编译软件,为众多0day世界的成员和ShellCode安全分析人士不可缺少的利器!此章节让我们熟悉通过IDA修改参数、函数、返回值,同时详细解读标志位的概念,熟悉堆栈及详细解读ARM三级流水线概念和ARM编码编译为二进制的全过程。

一、环境配置

首先配置IDA与安卓联动

IDA动态调用手机apk,请参考:安卓逆向-从环境搭建到动态调试apk IDA部分https://www.freebuf.com/articles/mobile/285861.html

1)加载server

2)端口转发+执行app(javandk1这个测试app)

代码语言:javascript
复制
adb install E:\IDA7.0\test\javandk1.apk    #安装app
adb shell am start -D -n com.example.javandk1/.MainActivity    #启动app
代码语言:javascript
复制
adb forward tcp:23946 tcp:23946    #端口转发

3)打开启动DDMS

代码语言:javascript
复制
DDMS

4)打开IDA 32并调试ndk运行

5)并勾选三项调试

6)F9启动+执行jdb调用DDMS

代码语言:javascript
复制
jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8600

此时可以看到加载的不是so,而是/arm/base.odex文件,那么此时怎么加载我们需要的so库,分析JNI_onload呢?

问题:解决方法无libjavandk1.so库

1)在Modules查询java:

2)选择libjavacore.so库-在搜索JNI_load选择

那么此时就进入了libjavacore.so的JNI_onload了

3)接下来下一个断点:点击或F2

4)F9运行后跳转到断点截断处,此时回到Modules继续搜索java:

此时就出现需要调试的so库文件:libjavandk1.so库文件

5)那么继续选择进入搜索JNI即可

此时问题就解决了

6)继续来到JNI_onload下断点,开始分析判断传参

二、参数分析

1、第一种方法

这里BLX传入了几个参数?

这里BLX中R3需要跳转,那么R3也是有规定给地址的,所以我们这里的有4个参数R0-R3

R0-R3:4个寄存器->参数寄存器

代码语言:javascript
复制
R0-R3:用于函数参数及返回值的传递
R4-R6,R8,R10-R11:普通的通用寄存器
R7:栈帧指针(Frame Pointer),指向前一个保存的栈帧(stack frame)和链接寄存器(link register,lr)在栈上的地址。
R9:操作系统保留
R12:IP(intra-procedure scratch)
R13:SP(stack pointer) 是栈顶指针
R14:LR(link register) 存放函数的返回地址
R15:PC (program counter),指向当前指令地址

如果R3作为一个地址的存放,当你把一个函数地址存放在R3里面,根据规定R3已经作为地址存放了,如果这个函数要传参,只能从R0-R2,这个三个寄存器里面进行传参。

注:如果想判断有几个参数,看这个BLX(指令)后面的值(是不是寄存器,如果是,Rn小于4,参数个数就是当前减1;大于等于4,参数寄存器就是R0-R3)

此时回到图中,BLX R3;三个参数,用了R0-R2后,只会依次使用下一个寄存器存放跳转的地址;

BLX R4(三个参数:R0,R1,R2,R3)

现在打开堆栈看看

在BLX R3处打桩,F9运行到下一个断点处

记住此时的栈顶是00000001,这时候SP:FF9ABBE0指向栈顶

这时候单步F7

这时候查看,SP的值还是FF9ABBE0是没有变化的

2、第二种方法

静态调试SO库,按F5查看伪代码

可以查看到伪c代码(int a1,int a2)就是查看参数个数

二、修改寄存器-返回值

我们随便找的几个BLX指令的地方。

BLX R3此时传入几个参数 ?三个

那么BLX R12传入几个参数?四个

按F5进入伪C代码

静态注册参数怎么修改呢?选择你要修改的参数,按Y

如何修改寄存器的值呢

这时候就可以修改寄存器的值了

例如:cmp R0,0,那么就执行BEN,意思就是修改了条件为0后,就不执行改条件,反调试会更深入演示

Y键修改C代码(退出C代码按ESC)

代码语言:javascript
复制
R0-R3:用于函数参数及返回值的传递
R4-R6,R8,R10-R11:普通的通用寄存器
R7:栈帧指针(Frame Pointer),指向前一个保存的栈帧(stack frame)和链接寄存器(link register,lr)在栈上的地址。
R9:操作系统保留
R12:IP(intra-procedure scratch)
R13:SP(stack pointer) 是栈顶指针
R14:LR(link register) 存放函数的返回地址
R15:PC (program counter),指向当前指令地址

三、修改寄存器-修改函数

1、方法1-修改Hex

如果我要改这条指令

根据三级流水线,需要在前三个代码断点

不想让程序执行怎么办?直接同步下PC寄存器

现在你想在HEX处找的PC的指令,当鼠标放在PC指令处,hex自动选择

然后在Hex View-1处快捷键F2操作,修改,

修改为00 00 00 00后,然后在快捷键F2保存下

这时候指令就没了

2、方法2-修改General

或者直接设置PC(只适合调试时候测试使用)

例如此刻需求是,跳过大红框内容,直接执行MOV R0, #0x10004这条指令,此刻PC在F42AA08C

只需要在General registers处修改PC值为MOV处的指令值即可,那么此时MOV出指令值为:

代码语言:javascript
复制
F42AA0A4

开始修改,双击General registers-PC处,修改为MOV的值:

直接跳转mov处

四、IDA配置堆栈信息

在PC窗口处配置出堆栈指针和Hex View对应的十六进制的值

五、IDA标志位详解

CPSR标志位详解

一边情况下标志位情况

断点后的情况

用最简单的理解,这些到底有什么用

通过图很好了解,例如BLX进行运算是正数还是负数,经过运算后值是不是为零,可以理解为条件标志位,帮我们记录一些状态! 标志位的结果内容可被算数或逻辑运算的结果所改变,并且可以决定某条指令是否被执行。 最重要的是N、Z、C、V、Q、T,那么T是什么意思? T标志位︰该为反应处理器的运行状态。当该位为1时,程序运行于THUMB状态,否则运行于ARM状态。该信号反映在外部引脚TBIT上。在程序中不得修改CPSR中的TBIT位,否则处理器工作状态不能确定。

ARM状态

arm处理器工作于32位指令的状态,所有指令均为32位

thumb状态

arm执行16位指令的状态,即16位状态

六、ARM汇编三级流水线详解

1、什么是三级流水线

前缀

代码语言:javascript
复制
ARM7处理器采用3级流水线来增加处理器指令流的速度,能提供0.9MIPS/MHz的指令处理速度。
MIPS(Million Instruction Per Second)表示每秒多少百万条指令。比如0.9MIPS,表示每秒九十万条指令。
MIPS/MHz表示CPU在每MHz的运行速度下可以执行多少个MIPS,如0.9MIPS/MHz则表示如果CPU运行在1MHz的频率下,每秒可执行90万条指令。

三级流水线使用3个阶段,因此指令分为3个阶段执行

代码语言:javascript
复制
1)取指从存储器装载一条指令
2)译码识别将要被执行的指令
3)执行处理指令并将结果写会寄存器

但是处理实际是这样的:ARM正在执行第一条指令的同时对第二条指令进行译码,并将第三条指令从存储器中取出

所以,ARM7流水线只能在取第4条指令时,第1条指令才算完成执行

无论处理器处于何种状态,程序计数器R15(PC)总是指向”正在取指“的指令,而不是指向”正在执行“的指令或者正在”译码“的指令。

人们一边会习惯性的将正在执行的指令作为参考点,即当前第一条指令,所以,pc总是指向第三条指令

或者说PC总是指向当前正在执行的指令在加2条指令的地址

2、三级流水线详解

处理器处于ARM状态是,每条指令为4个字节,所以PC指令为正在执行的指令地址加8个字节,即是:

PC值=当前程序执行位置+8字节

处理器处于Thumb状态时,每条指令为2字节,所以PC值为正在执行的指令地址加4字节,即是:

PC值=当前程序执行位置+4字节

下面一个列子很好的说明了这个问题

代码语言:javascript
复制
libjavandk1.so:F42AA090 010 00 C0 90 E5 LDR    R12, [R0]    #正在被执行的指令
libjavandk1.so:F42AA094 010 5C C3 9C E5 LDR    R12, [R12,#0x35C]  #正在被编码的指令
libjavandk1.so:F42AA098 010 3C FF 2F E1 BLX    R12   #正在被取指的指令 PC=F42AA098
libjavandk1.so:F42AA09C 010 00 00 50 E3 CMP    R0, #0    #PC+4=F42AA09C

另外补充说明就是根据以上描述,流水线只有被指令填满时才能发挥最大的效能,既每时钟周期完成一条指令的指向(仅单周期指令)

如果程序发送跳转,流水线会被清空,这将需要几个时钟才能使流水线被再次填满。因此,尽量地少使用跳转指令可以提高程序的指令效率

PC代表程序计数器,流水线使用三个阶段,因此指令为分为三个阶段执行:

代码语言:javascript
复制
1、取指(从存储器装载一条指令)
2、译码(识别将要被执行的指令)
3、执行(处理指令并将结果写回寄存器)

而R15(PC)总是指向”正在取指“的指令,而不是指向”正在执行“的指令或者正在”译码“的指令。一般来说,人习惯性约定将”正在执行“的指令作为参考点,称之为第一条指令,因此PC总是指向第三条指令,当ARM状态时,每条指令为4字节长,所以PC始终指向改指令地址加8字节的地址,既:PC值=当前程序执行位置+8;

ARM指令是三级流水线,取指、译指、执行是同时执行的,现在PC指向的是正在取值的地址,那么CPU正在译指的指令地址是PC-4(假设ARM状态下,一个指令占4个字节),cpu正在执行的指令地址是cpu-8,也就是说PC所指向的地址和现在所执行的指令地址相差8。

当突然发生中断的时候,保存的是PC的地址

这样你就知道了,如果返回的时候返回PC,那么中间就有一个指令没有执行,所以用SUB pc lr-irq#4。

这个需要参考《ARM指令》来学习

3、案例-ARM指令转换为机器码

下面我们将一个ARM指令转换为机器码试试

代码语言:javascript
复制
00001BD0 BEQ lc04
BEQ lc04;跳转指令,执行条件EQ,即相等跳转到lc04

来计算这条指令

1)首先ARM指令是32位的,因为这里是BEQ的B的跳转指令,32位可以拆分为格式如下

2)前四位:31-28就是cond,这里的意思就是条件码,例如EQ、NE

代码语言:javascript
复制
0000

3)紧接着3位:27-25(这里由于B指令是101固定的)

代码语言:javascript
复制
0000 101

4)在往下24位:(1或者0,具体判断:带有连接的如果是BL指 令对应的二进制操作数就是1 无条件跳转B指令就是0。)

代码语言:javascript
复制
0000 1010

5)0-23位:偏移地址:目标地址与该指令的相对偏移

偏移的计算公式:

代码语言:javascript
复制
(目标跳转的地址-(当前这条指令的地址+8))/4
(1c04-(1bd0+8))/4=1011
1c04:要跳转的地址
1bd0:此指令所在的地址
+8:arm指令有3级流水线的原因,如果执行1c04地址指令,需要加8
/4:因为要做对 其处理

我们拼接一下计算出来的二进制ARM指令机器码,因为0-23位算出来的是1011,

1011对应0-3位置

4-23用0补齐

结果

代码语言:javascript
复制
0000 1010 0000 0000 0000 0000 0000 1011

转换为16进制就是

代码语言:javascript
复制
0A 00 00 0B

因为是小端模式,需要换一下位置结果就是

代码语言:javascript
复制
0B 00 00 0A

我们在IDA中测试一下

将IDA中hex中随便一个地方改为0B 00 00 0A

我们看到指令变为了BEQ loc_F42AA0D4

我们计算利用偏移公式计算F42AA0D4(目标地址)和F42AA0A0(当前地址)结果是不是1011

代码语言:javascript
复制
(A0D4-(A0A0+8))/4=1011

我们这里就简单了解到了ARM指令如何计算为ARM指令机器码

七、总结

此章节我们详细学习了使用IDA在静态注册和动态注册下分析和修改参数,学习修改返回值、函数,对IDA堆栈功能模块和标志位功能模块进行深入解析,同时了解了ARM中三级流水线并利用案例熟悉ARM指令转换为机器码的案例。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-09-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FreeBuf 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 交互式反汇编器,简称为IDA。是目前最棒的一个静态反编译软件,为众多0day世界的成员和ShellCode安全分析人士不可缺少的利器!此章节让我们熟悉通过IDA修改参数、函数、返回值,同时详细解读标志位的概念,熟悉堆栈及详细解读ARM三级流水线概念和ARM编码编译为二进制的全过程。
  • 一、环境配置
  • 二、参数分析
    • 1、第一种方法
      • 2、第二种方法
      • 二、修改寄存器-返回值
      • 三、修改寄存器-修改函数
        • 1、方法1-修改Hex
          • 2、方法2-修改General
          • 四、IDA配置堆栈信息
          • 五、IDA标志位详解
          • 六、ARM汇编三级流水线详解
            • 1、什么是三级流水线
              • 2、三级流水线详解
                • 3、案例-ARM指令转换为机器码
                • 七、总结
                相关产品与服务
                Elasticsearch Service
                腾讯云 Elasticsearch Service(ES)是云端全托管海量数据检索分析服务,拥有高性能自研内核,集成X-Pack。ES 支持通过自治索引、存算分离、集群巡检等特性轻松管理集群,也支持免运维、自动弹性、按需使用的 Serverless 模式。使用 ES 您可以高效构建信息检索、日志分析、运维监控等服务,它独特的向量检索还可助您构建基于语义、图像的AI深度应用。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档