前面看过的 NSConcreteGobalBlock 其实在实际应用里是并不是太多的情况,相对来说,接下来要提到的 NSConcreteStackBlock 则是会经常遇到的情况。
从源码看 NSConcreteStackBlock
还是先从代码来看:
#include <stdio.h>
int main(){
int a = 1;
int (^block)(void) = ^{printf("%d\n", a);
return a;
};
int b = block();
printf("%d\n", b);
return 0;
}
翻译成 C++ 代码则是:
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
int a;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _a, int flags=0) : a(_a) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static int __main_block_func_0(struct __main_block_impl_0 *__cself) {int a = __cself->a; // bound by copy
printf("%d\n", a);
return a;
}
static struct __main_block_desc_0 {
size_t reserved;
size_t Block_size;
} __main_block_desc_0_DATA = {0, sizeof(struct __main_block_impl_0)};
int main(){
int a = 1;
int (*block)(void) = (int (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, a);
int b = ((int (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
printf("%d\n", b);
return 0;
}
代码具体和 NSConcreteGobalBlock 相比还是有一些变化,如,由于使用局部变量 a,在 block 中则是对 a 变量进行了拷贝,也就是说,在 block 中修改某一变量并不会影响 block 之外的相同变量。另外一个是关于返回值的定义,对函数的强制类型转化而来,关于这一块的东西,会在逆向分析时在进行对比。对于调用传入的指针 cself,则是在对 main_block_impl_0 结构的转化,注意在定义时,添加了 a 的传入参数,从而获取到参数内容。
从逆向看 NSConcreteStackBlock
x86_64:
__text:0000000100000E60 _main proc near
__text:0000000100000E60
__text:0000000100000E60 var_4C = dword ptr -4Ch
__text:0000000100000E60 var_48 = qword ptr -48h
__text:0000000100000E60 var_3C = dword ptr -3Ch
__text:0000000100000E60 var_38 = qword ptr -38h
__text:0000000100000E60 var_30 = dword ptr -30h
__text:0000000100000E60 var_2C = dword ptr -2Ch
__text:0000000100000E60 var_28 = qword ptr -28h
__text:0000000100000E60 var_20 = qword ptr -20h
__text:0000000100000E60 var_18 = dword ptr -18h
__text:0000000100000E60 var_10 = qword ptr -10h
__text:0000000100000E60 var_8 = dword ptr -8
__text:0000000100000E60 var_4 = dword ptr -4
__text:0000000100000E60
__text:0000000100000E60 push rbp
__text:0000000100000E61 mov rbp, rsp
__text:0000000100000E64 sub rsp, 50h
__text:0000000100000E68 lea rdi, aD ; "%d\n"
__text:0000000100000E6F lea rax, [rbp+var_38]
__text:0000000100000E73 lea rcx, ___block_descriptor_tmp
__text:0000000100000E7A lea rdx, ___main_block_invoke
__text:0000000100000E81 mov rsi, cs:__NSConcreteStackBlock_ptr
__text:0000000100000E88 mov [rbp+var_4], 0
__text:0000000100000E8F mov [rbp+var_8], 1
__text:0000000100000E96 mov [rbp+var_38], rsi
__text:0000000100000E9A mov [rbp+var_30], 40000000h
__text:0000000100000EA1 mov [rbp+var_2C], 0
__text:0000000100000EA8 mov [rbp+var_28], rdx
__text:0000000100000EAC mov [rbp+var_20], rcx
__text:0000000100000EB0 mov r8d, [rbp+var_8]
__text:0000000100000EB4 mov [rbp+var_18], r8d
__text:0000000100000EB8 mov [rbp+var_10], rax
__text:0000000100000EBC mov rax, [rbp+var_10]
__text:0000000100000EC0 mov rcx, rax
__text:0000000100000EC3 mov [rbp+var_48], rdi
__text:0000000100000EC7 mov rdi, rcx
__text:0000000100000ECA call qword ptr [rax+10h]
__text:0000000100000ECD mov [rbp+var_3C], eax
__text:0000000100000ED0 mov esi, [rbp+var_3C]
__text:0000000100000ED3 mov rdi, [rbp+var_48] ; char *
__text:0000000100000ED7 mov al, 0
__text:0000000100000ED9 call _printf
__text:0000000100000EDE mov esi, 0
__text:0000000100000EE3 mov [rbp+var_4C], eax
__text:0000000100000EE6 mov eax, esi
__text:0000000100000EE8 add rsp, 50h
__text:0000000100000EEC pop rbp
__text:0000000100000EED retn
__text:0000000100000EED _main endp
ARM:
__text:00002F0C _main
__text:00002F0C
__text:00002F0C var_34 = -0x34
__text:00002F0C var_30 = -0x30
__text:00002F0C var_2C = -0x2C
__text:00002F0C var_28 = -0x28
__text:00002F0C var_24 = -0x24
__text:00002F0C var_20 = -0x20
__text:00002F0C var_1C = -0x1C
__text:00002F0C var_18 = -0x18
__text:00002F0C var_14 = -0x14
__text:00002F0C var_10 = -0x10
__text:00002F0C var_C = -0xC
__text:00002F0C var_8 = -8
__text:00002F0C
__text:00002F0C PUSH {R4,R7,LR}
__text:00002F0E ADD R7, SP, #4
__text:00002F10 SUB SP, SP, #0x30
__text:00002F12 MOV R0, #(aD - 0x2F1E) ; "%d\n"
__text:00002F1A ADD R0, PC ; "%d\n"
__text:00002F1C ADD R1, SP, #0x34+var_28
__text:00002F1E MOV R2, #(___block_descriptor_tmp - 0x2F2A) ; ___block_descriptor_tmp
__text:00002F26 ADD R2, PC ; ___block_descriptor_tmp
__text:00002F28 MOV R3, #(___main_block_invoke+1 - 0x2F34) ; ___main_block_invoke
__text:00002F30 ADD R3, PC ; ___main_block_invoke
__text:00002F32 MOV R9, #0
__text:00002F3A MOV R12, #0x40000000
__text:00002F42 MOV LR, #(__NSConcreteStackBlock_ptr - 0x2F4E) ; __NSConcreteStackBlock_ptr
__text:00002F4A ADD LR, PC ; __NSConcreteStackBlock_ptr
__text:00002F4C LDR.W LR, [LR] ; __NSConcreteStackBlock
__text:00002F50 MOVS R4, #1
__text:00002F56 STR.W R9, [SP,#0x34+var_8]
__text:00002F5A STR R4, [SP,#0x34+var_C]
__text:00002F5C STR.W LR, [SP,#0x34+var_28]
__text:00002F60 STR.W R12, [SP,#0x34+var_24]
__text:00002F64 STR.W R9, [SP,#0x34+var_20]
__text:00002F68 STR R3, [SP,#0x34+var_1C]
__text:00002F6A STR R2, [SP,#0x34+var_18]
__text:00002F6C LDR R2, [SP,#0x34+var_C]
__text:00002F6E STR R2, [SP,#0x34+var_14]
__text:00002F70 STR R1, [SP,#0x34+var_10]
__text:00002F72 LDR R1, [SP,#0x34+var_10]
__text:00002F74 MOV R2, R1
__text:00002F76 LDR R1, [R1,#0xC]
__text:00002F78 STR R0, [SP,#0x34+var_30]
__text:00002F7A MOV R0, R2
__text:00002F7C BLX R1
__text:00002F7E STR R0, [SP,#0x34+var_2C]
__text:00002F80 LDR R1, [SP,#0x34+var_2C]
__text:00002F82 LDR R0, [SP,#0x34+var_30] ; char *
__text:00002F84 BLX _printf
__text:00002F88 MOVS R1, #0
__text:00002F8E STR R0, [SP,#0x34+var_34]
__text:00002F90 MOV R0, R1
__text:00002F92 ADD SP, SP, #0x30
__text:00002F94 POP {R4,R7,PC}
__text:00002F94 ; End of function _main