在 ARM 汇编里函数调用是使用 bl 指令跳转到函数地址,攻击者逆向分析很容易找到调用过程,分析参数和返回值。
可以将一些敏感的函数,比如将加密函数写成 inline 内联,无论代码里调用了多少次函数,编译器会将整个函数代码拷贝到需要调用的地方,而不会使用 bl 指令跳转,不能明显的看出函数参数传递和返回值,大大增加了分析的难度。
以下是一个简单的异或加密函数:
char* xor_encrypt (char *inbuf, int len){
char *outbuf = malloc(len);
for (int i=0; i <= len; i++) {
outbuf[i] = inbuf[i] ^ 0x33;
}
return outbuf;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
char *str1 = xor_encrypt("123", 3);
char *str2 = xor_encrypt("456", 3);
char *str3 = xor_encrypt("789", 3);
}
反汇编的效果如下:
xor_encrypt 函数的反汇编代码如下:
inlineTest`xor_encrypt:
0x7b3f0 <+0>: push {r7, lr}
0x7b3f2 <+2>: mov r7, sp
0x7b3f4 <+4>: sub sp, #0x10
0x7b3f6 <+6>: str r0, [sp, #0xc]
0x7b3f8 <+8>: str r1, [sp, #0x8]
-> 0x7b3fa <+10>: ldr r0, [sp, #0x8]
0x7b3fc <+12>: blx 0x7efd8 ; symbol stub for: malloc
0x7b400 <+16>: movs r1, #0x0
0x7b402 <+18>: str r0, [sp, #0x4]
0x7b404 <+20>: str r1, [sp]
0x7b406 <+22>: ldr r0, [sp]
0x7b408 <+24>: ldr r1, [sp, #0x8]
0x7b40a <+26>: cmp r0, r1
0x7b40c <+28>: bgt 0x7b42c ; <+60> at ViewController.m:324
0x7b40e <+30>: ldr r0, [sp]
0x7b410 <+32>: ldr r1, [sp, #0xc]
0x7b412 <+34>: add r0, r1
0x7b414 <+36>: ldrsb.w r0, [r0]
0x7b418 <+40>: eor r0, r0, #0x33
0x7b41c <+44>: ldr r1, [sp]
0x7b41e <+46>: ldr r2, [sp, #0x4]
0x7b420 <+48>: add r1, r2
0x7b422 <+50>: strb r0, [r1]
0x7b424 <+52>: ldr r0, [sp]
0x7b426 <+54>: adds r0, #0x1
0x7b428 <+56>: str r0, [sp]
0x7b42a <+58>: b 0x7b406 ; <+22> at ViewController.m:319
0x7b42c <+60>: ldr r0, [sp, #0x4]
0x7b42e <+62>: add sp, #0x10
0x7b430 <+64>: pop {r7, pc}
将函数的声明修改成 static inline
static inline char* xor_encrypt(char *inbuf, int len) __attribute__ ((always_inline));
编译后的反汇编的效果如下:
inlineTest`-[ViewController viewDidLoad]:
0xbd3a0 <+0>: push {r7, lr}
0xbd3a2 <+2>: mov r7, sp
0xbd3a4 <+4>: sub sp, #0x4c
0xbd3a6 <+6>: add r2, sp, #0xc
0xbd3a8 <+8>: movw r3, #0x3d40
0xbd3ac <+12>: movt r3, #0x0
0xbd3b0 <+16>: add r3, pc
0xbd3b2 <+18>: ldr r3, [r3]
0xbd3b4 <+20>: movw r9, #0x4510
0xbd3b8 <+24>: movt r9, #0x0
0xbd3bc <+28>: add r9, pc
0xbd3be <+30>: movw r12, #0x459e
0xbd3c2 <+34>: movt r12, #0x0
0xbd3c6 <+38>: add r12, pc
0xbd3c8 <+40>: str r0, [sp, #0x18]
0xbd3ca <+42>: str r1, [sp, #0x14]
0xbd3cc <+44>: ldr r0, [sp, #0x18]
0xbd3ce <+46>: str r0, [sp, #0xc]
0xbd3d0 <+48>: ldr.w r0, [r12]
0xbd3d4 <+52>: str r0, [sp, #0x10]
0xbd3d6 <+54>: ldr.w r1, [r9]
0xbd3da <+58>: mov r0, r2
0xbd3dc <+60>: blx r3
0xbd3de <+62>: movs r0, #0x3
0xbd3e0 <+64>: movw r1, #0x3747
0xbd3e4 <+68>: movt r1, #0x0
0xbd3e8 <+72>: add r1, pc
-> 0xbd3ea <+74>: str r1, [sp, #0x28]
0xbd3ec <+76>: str r0, [sp, #0x24]
0xbd3ee <+78>: ldr r0, [sp, #0x24]
0xbd3f0 <+80>: blx 0xc0fd8 ; symbol stub for: malloc
0xbd3f4 <+84>: movs r1, #0x0
0xbd3f6 <+86>: str r0, [sp, #0x20]
0xbd3f8 <+88>: str r1, [sp, #0x1c]
0xbd3fa <+90>: ldr r0, [sp, #0x1c]
0xbd3fc <+92>: ldr r1, [sp, #0x24]
0xbd3fe <+94>: cmp r0, r1
0xbd400 <+96>: bgt 0xbd420 ; <+128> [inlined] xor_encrypt + 50 at ViewController.m:334
0xbd402 <+98>: ldr r0, [sp, #0x1c]
0xbd404 <+100>: ldr r1, [sp, #0x28]
0xbd406 <+102>: add r0, r1
0xbd408 <+104>: ldrsb.w r0, [r0]
0xbd40c <+108>: eor r0, r0, #0x33
0xbd410 <+112>: ldr r1, [sp, #0x1c]
0xbd412 <+114>: ldr r2, [sp, #0x20]
0xbd414 <+116>: add r1, r2
0xbd416 <+118>: strb r0, [r1]
0xbd418 <+120>: ldr r0, [sp, #0x1c]
0xbd41a <+122>: adds r0, #0x1
0xbd41c <+124>: str r0, [sp, #0x1c]
0xbd41e <+126>: b 0xbd3fa ; <+90> [inlined] xor_encrypt + 12 at ViewController.m:334
0xbd420 <+128>: movs r0, #0x3
0xbd422 <+130>: movw r1, #0x3709
0xbd426 <+134>: movt r1, #0x0
0xbd42a <+138>: add r1, pc
0xbd42c <+140>: ldr r2, [sp, #0x20]
0xbd42e <+142>: str r2, [sp, #0x8]
0xbd430 <+144>: str r1, [sp, #0x38]
0xbd432 <+146>: str r0, [sp, #0x34]
0xbd434 <+148>: ldr r0, [sp, #0x34]
0xbd436 <+150>: blx 0xc0fd8 ; symbol stub for: malloc
0xbd43a <+154>: movs r1, #0x0
0xbd43c <+156>: str r0, [sp, #0x30]
0xbd43e <+158>: str r1, [sp, #0x2c]
0xbd440 <+160>: ldr r0, [sp, #0x2c]
0xbd442 <+162>: ldr r1, [sp, #0x34]
0xbd444 <+164>: cmp r0, r1
0xbd446 <+166>: bgt 0xbd466 ; <+198> [inlined] xor_encrypt + 50 at ViewController.m:335
0xbd448 <+168>: ldr r0, [sp, #0x2c]
0xbd44a <+170>: ldr r1, [sp, #0x38]
0xbd44c <+172>: add r0, r1
0xbd44e <+174>: ldrsb.w r0, [r0]
0xbd452 <+178>: eor r0, r0, #0x33
0xbd456 <+182>: ldr r1, [sp, #0x2c]
0xbd458 <+184>: ldr r2, [sp, #0x30]
0xbd45a <+186>: add r1, r2
0xbd45c <+188>: strb r0, [r1]
0xbd45e <+190>: ldr r0, [sp, #0x2c]
0xbd460 <+192>: adds r0, #0x1
0xbd462 <+194>: str r0, [sp, #0x2c]
0xbd464 <+196>: b 0xbd440 ; <+160> [inlined] xor_encrypt + 12 at ViewController.m:335
0xbd466 <+198>: movs r0, #0x3
0xbd468 <+200>: movw r1, #0x36c7
0xbd46c <+204>: movt r1, #0x0
0xbd470 <+208>: add r1, pc
0xbd472 <+210>: ldr r2, [sp, #0x30]
0xbd474 <+212>: str r2, [sp, #0x4]
0xbd476 <+214>: str r1, [sp, #0x48]
0xbd478 <+216>: str r0, [sp, #0x44]
0xbd47a <+218>: ldr r0, [sp, #0x44]
0xbd47c <+220>: blx 0xc0fd8 ; symbol stub for: malloc
0xbd480 <+224>: movs r1, #0x0
0xbd482 <+226>: str r0, [sp, #0x40]
0xbd484 <+228>: str r1, [sp, #0x3c]
0xbd486 <+230>: ldr r0, [sp, #0x3c]
0xbd488 <+232>: ldr r1, [sp, #0x44]
0xbd48a <+234>: cmp r0, r1
0xbd48c <+236>: bgt 0xbd4ac ; <+268> [inlined] xor_encrypt + 50 at ViewController.m:336
0xbd48e <+238>: ldr r0, [sp, #0x3c]
0xbd490 <+240>: ldr r1, [sp, #0x48]
0xbd492 <+242>: add r0, r1
0xbd494 <+244>: ldrsb.w r0, [r0]
0xbd498 <+248>: eor r0, r0, #0x33
0xbd49c <+252>: ldr r1, [sp, #0x3c]
0xbd49e <+254>: ldr r2, [sp, #0x40]
0xbd4a0 <+256>: add r1, r2
0xbd4a2 <+258>: strb r0, [r1]
0xbd4a4 <+260>: ldr r0, [sp, #0x3c]
0xbd4a6 <+262>: adds r0, #0x1
0xbd4a8 <+264>: str r0, [sp, #0x3c]
0xbd4aa <+266>: b 0xbd486 ; <+230> [inlined] xor_encrypt + 12 at ViewController.m:336
0xbd4ac <+268>: ldr r0, [sp, #0x40]
0xbd4ae <+270>: str r0, [sp]
0xbd4b0 <+272>: add sp, #0x4c
0xbd4b2 <+274>: pop {r7, pc}
可以看出 xor_encrypt 在 viewDidLoad 里调用了三次,所以 xor_encrypt 的代码拷贝了三份,增强了分析的难度。
原文地址:https://www.exchen.net/ios-hacker-%E4%BD%BF%E7%94%A8-inline-%E5%86%85%E8%81%94%E5%87%BD%E6%95%B0%E5%AF%B9%E6%8A%97%E9%80%86%E5%90%91%E5%88%86%E6%9E%90.html