iOS逆向-04:if 、循环、switch

2021-05-02  本文已影响0人  恍然如梦_b700
int g = 12;

int func(int a,int b){
    printf("boy");
    int c = a + g + b;
    return c;
}

int main(int argc, char * argv[]) {
   
    func(10, 20);
    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
image.png

adrp

adrp(Address Page)
内存地址按页寻址

取常量

adrp x0, 1
这句代码的操作如下:
将1的值左移12位得到0x1000
将0x1048ae12c的低12位清零得到0x1048ae000
将0x1000和0x1048ae000相加得到0x1048af000
add x0, x0, #0xf89
0x1048af000 + 0xf89 = 0x1048aff89
此时x0的值为0x1048aff89,这个地址里面存的也就是"boy"

一个页的大小是4096,而0xFFF为4095,加上1就是0x1000(即4096),所以是1左移12位即可得到一个页的首地址(注:macOS的pageSize是 4k(0x1000),而iPhone的pageSize是16k(0x4000),但是16仍是4的倍数,adrp兼容者mac和iPhone,所以此时定位的仍然是一页数据)

全局变量也是一样

image.png

Hopper反汇编

image.png image.png
image.png

全局变量g = 0xc 也就是12
也可以通过mach-o来查看


image.png image.png

还原代码

int gl = 12;

int funcC(int a, int b) {
//    0000000100006118         sub        sp, sp, #0x20                               ; CODE XREF=_main+32
//    000000010000611c         stp        x29, x30, [sp, #0x10]
//    0000000100006120         add        x29, sp, #0x10
    
//    0000000100006124         stur       w0, [x29, #-0x4]
//    0000000100006128         str        w1, [sp, #0x8]
//    000000010000612c         adrp       x0, #0x100007000                            ; argument #1 for method imp___stubs__printf

//    0000000100006130         add        x0, x0, #0xf89                              ; "boy"
//    0000000100006134         bl         imp___stubs__printf
    
    printf("boy");
//    0000000100006138         ldur       w8, [x29, #-0x4]
    int w8 = a;
//    000000010000613c         adrp       x9, #0x10000d000
//    0000000100006140         add        x9, x9, #0x570                              ; _g
    int x9 = gl;
//    0000000100006144         ldr        w10, x9
//    0000000100006148         add        w8, w8, w10
    int w10 = x9;
    w8 = w8 + w10;
//    000000010000614c         ldr        w10, [sp, #0x8]
    w10 = b;
//    0000000100006150         add        w8, w8, w10
    w8 += w10;
//    0000000100006154         str        w8, [sp, #0x4]
//    0000000100006158         ldr        w8, [sp, #0x4]
    
//    000000010000615c         mov        x0, x8
    int w0 = w8;
//    0000000100006160         ldp        x29, x30, [sp, #0x10]
//    0000000100006164         add        sp, sp, #0x20
    return w0;
}

继续精简还原

从下往上还原

int funcC(int a, int b) {
    printf("boy");
    int w8 = a;
    int x9 = gl;
    int w10 = x9;
    w8 = w8 + w10;
//    w10 = b;
//    w8 += w10;
//    int w0 = w8;
//   return w0;
    return w8+b;//上面几句还原
}

依次类推得到最终结果

int gl = 12;
int funcC(int a, int b) {
    printf("boy");
    return a+gl+b;
}

if 语句

我们看看下面代码的汇编

int g = 12;
void func(int a,int b){
    if (a > b) {
        g = a;
    }else{
        g = b;
    }
}
image.png

通过上面可以看出if else 判断就是 通过cmp + 标号实现的,大于小于都是通过cmp相减。

cmp(Compare)比较指令

   CMP 把一个寄存器的内容和另一个寄存器的内容或立即数进行比较。但不存储结果,只是正确的更改标志。
   一般CMP做完判断后会进行跳转,后面通常会跟上B指令!

循环

for (int i = 0; i < 100; i++) {
        nSum = nSum + 1;
    }
image.png

Switch

1、假设switch语句的分支比较少的时候(例如3,少于4的时候没有意义)没有必要使用此结构,相当于if。
2、各个分支常量的差值较大的时候,编译器会在效率还是内存进行取舍,这个时候编译器还是会编译成类似于if,else的结构。
3、在分支比较多的时候:在编译的时候会生成一个表(跳转表每个地址四个字节)。

1 .当有三个case时,可以看到汇编和if else if 是一样的


image.png image.png
上一篇下一篇

猜你喜欢

热点阅读