汇编基础(七)Ida分析Ipa中的MachO文件,得到汇编,还原高级代码、简单版

准备

  • 首先我们准备一个工程
  • 添加一些简单的函数调用,最基本的运算
  • Bulid得到一个app包
  • 将app包里面的MachO文件放入到ida中分析汇编(ida去网上找资源)
  • 初步的将汇编还原成高级代码

操作

1.创建工程名字就叫:还原高级代码

2.添加函数、运算

汇编基础(七)Ida分析Ipa中的MachO文件,得到汇编,还原高级代码、简单版_第1张图片

3.Bulid得到得到app包

汇编基础(七)Ida分析Ipa中的MachO文件,得到汇编,还原高级代码、简单版_第2张图片

4.将App包中的MachO文件放入到ida进行解析,生成汇编代码

汇编基础(七)Ida分析Ipa中的MachO文件,得到汇编,还原高级代码、简单版_第3张图片

汇编、源代码

汇编

__text:0000000100006228 _func ; CODE XREF: _main+28↓p
__text:0000000100006228
__text:0000000100006228 var_C = -0xC
__text:0000000100006228 var_8 = -8
__text:0000000100006228 var_4 = -4
__text:0000000100006228 var_s0 = 0
__text:0000000100006228
__text:0000000100006228 SUB SP, SP, #0x20
__text:000000010000622C STP X29, X30, [SP,#0x10+var_s0]
__text:0000000100006230 ADD X29, SP, #0x10
__text:0000000100006234 STUR W0, [X29,#var_4]
__text:0000000100006238 STR W1, [SP,#0x10+var_8]
__text:000000010000623C ADRP X0, #aHaha@PAGE ; "haha"
__text:0000000100006240 ADD X0, X0, #aHaha@PAGEOFF ; "haha"
__text:0000000100006244 BL _printf
__text:0000000100006248 ADRP X30, #_number@PAGE
__text:000000010000624C ADD X30, X30, #_number@PAGEOFF
__text:0000000100006250 LDUR W1, [X29,#var_4]
__text:0000000100006254 LDR W8, [SP,#0x10+var_8]
__text:0000000100006258 ADD W8, W1, W8
__text:000000010000625C LDR W1, [X30]
__text:0000000100006260 ADD W8, W8, W1
__text:0000000100006264 STR W0, [SP,#0x10+var_C]
__text:0000000100006268 MOV X0, X8
__text:000000010000626C LDP X29, X30, [SP,#0x10+var_s0]
__text:0000000100006270 ADD SP, SP, #0x20
__text:0000000100006274 RET
__text:0000000100006274 ; End of function _func

源代码

int number = 30;
int func(int a, int b){
printf("haha");
return a + b + number;
}
int main(int argc, char * argv[]) {
printf("%d",func(1, 2));
return 0;
}

汇编分析

  1. 定义的4个变量 将一些偏移量存起来,方便观看
    __text:0000000100006228 var_C = -0xC
    __text:0000000100006228 var_8 = -8
    __text:0000000100006228 var_4 = -4
    __text:0000000100006228 var_s0 = 0
  2. 下面三句拉伸栈空间
    __text:0000000100006278 SUB SP, SP, #0x30
    __text:000000010000627C STP X29, X30, [SP,#0x20+var_s0]
    __text:0000000100006280 ADD X29, SP, #0x20
  3. 将w0 w1 放入栈
    __text:0000000100006234 STUR W0, [X29,#var_4]
    __text:0000000100006238 STR W1, [SP,#0x10+var_8]
  4. 获取一个常量或者全局变量
    __text:000000010000623C ADRP X0, #aHaha@PAGE ; "haha"
    __text:0000000100006240 ADD X0, X0, #aHaha@PAGEOFF ; "haha"
  5. 打印这个常量或者全局变量
    __text:0000000100006244 BL _printf
  6. 获取一个常量或者全局变量
    __text:0000000100006248 ADRP X30, #_number@PAGE
    __text:000000010000624C ADD X30, X30, #_number@PAGEOFF
  7. 一个变量
    __text:0000000100006250 LDUR W1, [X29,#var_4]
  8. 一个变量
    __text:0000000100006254 LDR W8, [SP,#0x10+var_8]
  9. 运算 +
    __text:0000000100006258 ADD W8, W1, W8
  10. 一个变量
    __text:000000010000625C LDR W1, [X30]
  11. 运算 +
    __text:0000000100006260 ADD W8, W8, W1
  12. 将w0存入到栈
    __text:0000000100006264 STR W0, [SP,#0x10+var_C]
  13. x0 = x8
    __text:0000000100006268 MOV X0, X8
  14. 读取回家的路 栈底fp以及lr
    __text:000000010000626C LDP X29, X30, [SP,#0x10+var_s0]
  15. 将栈空间收回 用之前需要拉伸、 用完需要恢复
    __text:0000000100006270 ADD SP, SP, #0x20
  16. 返回main函数
    __text:0000000100006274 RET

进一步简化

  1. 因为一开始就知道func函数,并且在main的汇编当中我们看到 w8 = #1 w9 = #2 w0 = w8 w1 = w9 所以判定有两个参数


    汇编基础(七)Ida分析Ipa中的MachO文件,得到汇编,还原高级代码、简单版_第4张图片

    func(int a, int b){
    }

  2. STUR W0, [X29,#var_4] STR W1, [SP,#0x10+var_8] 存入栈两个参数 就是两个变量 main 中w8 = #1 w9 = #2 w0 = w8 w1 = w9
    int var_4 = a;
    int var_8 = b;
  3. ADRP X0, #aHaha@PAGE ; "haha" ADD X0, X0, #aHaha@PAGEOFF ; "haha" BL _printf
    printf("haha");
  4. ADRP X30, #_number@PAGE ADD X30, X30, #_number@PAGEOFF 拿到的是&number 因为下面的 LDR W1, [X30],ADD W8, W8, W1 w8 == var_8 var_8 == b b 是int 所以 _number 是int类型
    _number 是全局变量
    int number; &number
  5. LDUR W1, [X29,#var_4]
    int w1 = var_4
  6. LDR W8, [SP,#0x10+var_8]
    int w8 = var_8
  7. ADD W8, W1, W8
    w8 = w1 + w8
  8. LDR W1, [X30]
    w1 = number
  9. ADD W8, W8, W1
    w8 = W8 + W1
  10. W0, [SP,#0x10+var_C]
    int var_c = a;
  11. MOV X0, X8 保存返回值
    return x8;

初步还原的代码

int number; 
func(int a, int b){
  int var_4 = a;
  int var_8 = b;
  printf("haha");
  int w1 = var_4;
  int w8 = var_8;
  w8 = w1 + w8;
  w1 =  number;
  w8 = W8 + W1;
  int var_c = a;
  return x8;
} 

最简化

最终

int number; 
func(int a, int b){
  printf("haha");
  return a + b + number;
} 

原码

>int number  = 30;
int func(int a, int b){
    printf("haha");
    return a + b + number;
}
int main(int argc, char * argv[]) {
    printf("%d",func(1, 2));
    return 0;
}

结论

问题

  • 怎么确定func是否有返回值?
    因为int var_c = a; W0, [SP,#0x10+var_C] 这句话,w0都是返回值,如果没有retrun 为什么多此一举呐?

  • 为什么有返回值在main函数中调用玩func没有调用w0这个返回值呐?
    因为大家在写代码的时候,函数有返回值,但是我们调用的时候没用,就会出现这个问题。

  • Number的值拿不到吗?
    因为系统知道静态变量的值,不需要我们做操作,就好比,为什么拉伸栈空间的时候函数一开始的栈起始位置是多少?因为系统知道,并且我们知道这个是一个值就OK,当成一个常量,只不过不知道它的值

你可能感兴趣的:(汇编基础(七)Ida分析Ipa中的MachO文件,得到汇编,还原高级代码、简单版)