欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

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

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

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):

修改后的运行结果:

程序执行正常。

上传的附件 00.png
11.png
text.png
new_text.png

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功