首页
社区
课程
招聘
[原创](arm入门)反汇编分析一个arm函数调用的生死因果
发表于: 2013-7-18 11:05 36384

[原创](arm入门)反汇编分析一个arm函数调用的生死因果

2013-7-18 11:05
36384

arm的资料没有x86丰富,但搞安卓底层又绕不开这个。我作为一个初学者走了不少弯路,那么现在我用一个实际的例子来分析一个最简单的arm函数调用过程,希望能帮到大家,如果有理解不正确之处请高手指出。

注:这里的指令实际上是thumb(thumb2?),每个指令2字节

C源码:------------------------------------------------------------------
#include <stdio.h>
#include <dlfcn.h>

void (*func)();
  
void sub() {
  void *p = dlopen("libxxx.so", RTLD_NOW);
  if (!p) {
    return;
  }
  else {
    // myfn是libxxx.so的一个函数,作用是打印"call myfn...!"
    func = (void (*)())dlsym(p,"myfn");
    func();
  }
}

int main()
{
  printf("RTLD_NOW=%d\n", RTLD_NOW);
  sub();
  return 0;
}

运行结果---------------------------------------------------------------


反汇编分析-------------------------------------------------------------
sub:
1.    84a0:  4808        ldr  r0, [pc, #32]  ; (84c4 <printf@plt+0x6c>)
2.    84a2:  2100        movs  r1, #0
3.    84a4:  b510        push  {r4, lr}
4.    84a6:  4c08        ldr  r4, [pc, #32]  ; (84c8 <printf@plt+0x70>)
5.    84a8:  4478        add  r0, pc
6.    84aa:  447c        add  r4, pc
7.    84ac:  f7ff efc8   blx  8440 <dlopen@plt>
8.    84b0:  b138        cbz  r0, 84c2 <printf@plt+0x6a>
9.    84b2:  4906        ldr  r1, [pc, #24]  ; (84cc <printf@plt+0x74>)
10.   84b4:  4479        add  r1, pc
11.   84b6:  f7ff efca   blx  844c <dlsym@plt>
12.   84ba:  4905        ldr  r1, [pc, #20]  ; (84d0 <printf@plt+0x78>)
13.   84bc:  5863        ldr  r3, [r4, r1]
14.   84be:  6018        str  r0, [r3, #0]
15.   84c0:  4780        blx  r0
16.   84c2:  bd10        pop  {r4, pc}



//   为5.做准备
1.   r0 = [0x84a0+4+32] = [0x84c4] = 0x48 

//   dlopen的参数2
2.   r1 = 0  

//   lr是sub的返回地址
3.   r4,lr 入栈 

//   为6.做准备
//   必须对齐到(0,4,8,c),所以0x84ca变成0x84c8
4.   r4 = [0x84a6+4+32] = [0x84ca] = [0x84c8] = 0xc26

//   dlopen的参数1 -> 0x84f4处存放字符串libxxx.so
5.   r0 = 0x48+0x84a8+4 = 0x84f4 

//   为13.做准备
6.   r4 = 0xc26+0x84aa+4= 0x90D4

//   参数r0&r1,返回值r0
7.   call dlopen

//   如果r0为0,则跳转到0x84c2
8.   条件跳转

//   为10.做准备
//   ce对齐到cc
9.   r1 = [0x84b2+4+24] = [0x84CE] = [0x84cc] = 0x46

//   dlsym的参数2 -> 0x84FE处存放字符串myfn
10.  r1 = 0x46+0x84b4+4 = 0x84FE

//   参数r0&r1,返回值r0,这个返回值就是myfn的地址
11.  call dlsym

//   为13.做准备
//   d2对齐到d0
12.  r1 = [0x84ba+4+20] = [0x84D2] = [0x84d0] = 0xfffffffc

//   r3是用来干嘛的呢,见14.
13.  r3 = [0x90D4+0xfffffffc] = [0x90d0] = 0x90f0

//   将myfn的地址保存
14.  [0x90f0] = r0

15.  call myfn

16.  出栈,将lr放入pc,该sub返回

修改--------------------------------------------------------------------
从以上分析得知,12-14行的作用是将myfn的地址缓存以便加快以后重复的调用(该程序只调用了一次)
如果这个分析是正确的,那么将12-14行去掉应该不会影响程序的正常执行

下面是试验(将12-14行替换成nop,机器码0xc046):


修改后的运行结果:


程序执行正常。


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 6
支持
分享
最新回复 (23)
雪    币: 23
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
c涨姿势了
2013-7-18 11:11
0
雪    币: 428
活跃值: (33)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
对新手很有帮助的说,THX。。。
2013-7-18 11:19
0
雪    币: 1839
活跃值: (295)
能力值: ( LV9,RANK:370 )
在线值:
发帖
回帖
粉丝
4
顶一个,,,
2013-7-18 11:30
0
雪    币: 114
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
做个系列吧,系统的普及一下,造福人类!
2013-7-18 11:40
0
雪    币: 440
活跃值: (1163)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
6
先做个Mark吧!
2013-7-18 12:02
0
雪    币: 218
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
7
顶一下,表示来学习的,
2013-7-18 12:23
0
雪    币: 86
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
看到下面的解释:
/   为6.做准备
//   必须对齐到(0,4,8,c),所以0x84ca变成0x84c8
4.   r4 = [0x84a6+4+32] = [0x84ca] = [0x84c8] = 0xc26

这里有三个问题:
1 为什么 [0x84a6+4+32]会有+4呢?我发现主要有操作pc的就要+4,是因为要pc自动往后么?
2 所以0x84ca变成0x84c8,为什么不是0x84cc,我理解的是栈都是从高地址到低地址的原因,所以地址要往下,对么?
3 [0x84c8] 怎么变成0xc26,跟帖主说的thumb指令集有啥关系么?
2013-7-21 00:08
0
雪    币: 257
活跃值: (44)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
[QUOTE=threewind;1201102]看到下面的解释:
/   为6.做准备
//   必须对齐到(0,4,8,c),所以0x84ca变成0x84c8
4.   r4 = [0x84a6+4+32] = [0x84ca] = [0x84c8] = 0xc26

这里有三个问题:
1 为什么 [0x84a6+4+32]会有+4呢?我发现主...[/QUOTE]

1 和arm的流水线有关,你只要记住arm指令pc+8,thumb指令pc+4
2 定义如此 #define ALIGN(x, y) ((y) * ((x)/(y)))
3 [0x84c8]减去基地址0x8000,就是0x4c8处的值,上面不是贴了图么
2013-7-21 13:43
0
雪    币: 154
活跃值: (91)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
10
[QUOTE=gemo;1201241]1 和arm的流水线有关,你只要记住arm指令pc+8,thumb指令pc+4
2 定义如此 #define ALIGN(x, y) ((y) * ((x)/(y)))
3 [0x84c8]减去基地址0x8000,就是0x4c8处的值,上面不是贴了图么[/QUOTE]

什么情况下+4呢,没有-4么,遵循四舍五入还是总是+4呢?
比如一个导出函数地址不是4的倍数,那它的真实地址一定+4或者+到满足4的倍数?
还有如果是thumb2指令集的话+多少?

按照macro来使:
ALIGN(addr,4) -> 4 * addr / 4?
2013-7-21 14:57
0
雪    币: 257
活跃值: (44)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
11
我建议C基础不牢的先去认真学一下C,LS真的连ALIGN宏都看不懂么
2013-7-21 15:13
0
雪    币: 154
活跃值: (91)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
12
看来我2了。。。百度学习一下把。。。
2013-7-21 15:46
0
雪    币: 29
活跃值: (499)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
13
楼主,目前我有一个疑惑就是:你在第1、4、9条指令处读取的是一个字节的数据,但在第12条指令的时候读取的是4字节的数据。这是根据什么来判断的呢?难道是根据“该地址前or后的数据是否为0x00”?
2013-11-20 23:55
0
雪    币: 257
活跃值: (44)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
14
都是读的4字节,了解数据在内存中的存储方式先
2013-11-21 10:09
0
雪    币: 29
活跃值: (499)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
15
哦,是我没注意,谢谢解答!
2013-11-21 11:42
0
雪    币: 130
活跃值: (34)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
多谢楼主!涨姿势了!
2013-11-22 09:46
0
雪    币: 5
活跃值: (33)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
通俗易懂,mark
2014-3-6 09:29
0
雪    币: 1
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
学习了 mark!
2014-6-30 18:35
0
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
妈了  回去看
2014-7-5 01:06
0
雪    币: 413
活跃值: (351)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
[QUOTE=threewind;1201102]看到下面的解释:
/   为6.做准备
//   必须对齐到(0,4,8,c),所以0x84ca变成0x84c8
4.   r4 = [0x84a6+4+32] = [0x84ca] = [0x84c8] = 0xc26

这里有三个问题:
1 为什么 [0x84a6+4+32]会有+4呢?我发现主...[/QUOTE]

第一个问题:因为是arm体系规定的,当读pc寄存器值时,如果是arm指令,则值为当前的PC值+8,当是thumb指令时,则读出的值是当前的PC值+4.

第二个问题:由于arm是32位的,在数据总线访问存储器时都是一次读取32位数据的,当访问地址不是对齐的时候,arm中叫做非对齐数据访问。此时arm会自动转换成对齐访问。在你的问题中,0x84ca地址中的数据是属于0x84c8,0x84c9,0x84ca,0x84cb四字中的数据,所以把0x84ca转换成0x84c8,一次性读取4字节,然后丢弃没用的数据。

第三个问题,[0x84c8]是存储器寻址方式,也就是说寻找存储器地址0x84c8处的数据。
2014-9-6 22:35
0
雪    币: 39
活跃值: (30)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
学习,谢谢分享
2015-4-26 11:08
0
雪    币: 220
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
学习了,谢谢各位分享
2018-4-25 14:16
0
雪    币: 58
活跃值: (153)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
学习了,谢谢分享
2018-4-25 16:52
0
雪    币: 3139
活跃值: (588)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
虽然时间久远,但是还是学习了 mark!
2020-9-22 14:27
0
游客
登录 | 注册 方可回帖
返回
//