短视频、直播数据实时采集接口,请查看文档: TiToDataandroid
免责声明:本文档仅供学习与参考,请勿用于非法用途!不然一切后果自负。架构
内存相关app
寄存器相关函数
指令执行类布局
内存访问类学习
异常处理类测试
先本身写个 超级简单的app,并编译(没有开混淆保护)this
#include <jni.h> #include <string> int add(int a, int b){ int sum=a+b; return sum; } int add_six(int a,int b,int c, int d, int e,int f){ int sum=0; sum=add(a,b); sum=add(sum,c); sum=add(sum,d); sum=add(sum,e); sum=add(sum,f); return sum; } extern "C" JNIEXPORT jstring JNICALL Java_com_zok_uni_MainActivity_stringFromJNI( JNIEnv* env, jobject /* this */) { std::string hello = "Hello from C++"; int sum=add(3,4); sum=add_six(1,2,3,4,5,6); return env->NewStringUTF(hello.c_str()); }
C
_ 复制_
抹去符号,让他直接在 so 中调用 add_definitions(-fvisibility=hidden)
32位下,参数小于4个的时候会直接经过寄存器来传递!!多余的只能进入堆栈当中(从右到左依次入栈)3d
打开IDA 查看位置,为了查看方便咱们配置一下, Options--general
简单的找到函数位置, 并更名
动态调试指针
stringFromJNI
的真实绑定地址就是在 C78CD628
中接下来就要看他参数的调用传递状况和堆栈状况
8646和8648 下面就是 864A 也就是 add 函数了
因此此处对应 add 函数咱们能够更名, 同理能够找到 add_six 函数
继续调试后总结以下:
先记住两个函数的偏移位置
add 函数偏移位置 8500
add_six 函数偏移位置 851C
接下来就能够经过函数传递和堆栈布局来对这两个函数的模拟调用
""" 实现对 so 中函数调用 示例apk中两个函数 int add(int a, int b){ int sum=a+b; return sum; } int add_six(int a,int b,int c, int d, int e,int f){ int sum=0; sum=add(a,b); sum=add(sum,c); sum=add(sum,d); sum=add(sum,e); sum=add(sum,f); return sum; } extern "C" JNIEXPORT jstring JNICALL Java_com_zok_uni_MainActivity_stringFromJNI( JNIEnv* env, jobject /* this */) { std::string hello = "Hello from C++"; int sum=add(3,4); sum=add_six(1,2,3,4,5,6); return env->NewStringUTF(hello.c_str()); } """ import unicorn import capstone import binascii import struct # 取出 so 内容 with open("so/03.so",'rb') as f: CODE=f.read() def capstone_print(code, offset): """capstone 测试输出""" print("\033[1;32m-------- capstone 输出--------\033[0m") CP = capstone.Cs(capstone.CS_ARCH_ARM, capstone.CS_MODE_THUMB) # 指定 THUMB 指令集 for i in CP.disasm(code[offset:], 0, 20): print('\033[1;32m地址: 0x%x | 操做码: %s | 内容: %s\033[0m'%(offset + i.address, i.mnemonic, i.op_str)) def uni_add(): """ add(a+b) 将汇编片断,映射到 unicorn 虚拟内存中,将 pc 指向第一条指令处并执行 """ print('-------- unicorn 执行前--------') # 1. 建立实例 mu = unicorn.Uc(unicorn.UC_ARCH_ARM, unicorn.UC_MODE_THUMB) # 要指定架构和模式, 这里用 arm 架构, 指定 THUMB 指令集 # 2. 将代码片断映射到模拟器的虚拟地址 ADDRESS = 0x1000 # 映射开始地址 SIZE = 1024*1024*10 # 分配映射大小(多分一点) # 3. 开始映射 mu.mem_map(ADDRESS, SIZE) # 初始化映射 参数1:地址 参数2:空间大小 默认初始化后默认值:0 mu.mem_write(ADDRESS, CODE) # 写入指令 参数1: 写入位置 参数2:写入内容 # 写入寄存器 # 4. 寄存器初始化 指令集涉及到 R0,R1,R2,R3 4个寄存器 mu.reg_write(unicorn.arm_const.UC_ARM_REG_R0, 0x1) # 在 r0 寄存器上写入 0x1 mu.reg_write(unicorn.arm_const.UC_ARM_REG_R1, 0x2) # 在 r1 寄存器上写入 0x2 # 5. 初始化堆栈,由于要对内存进行操做 设置 SP SP = ADDRESS+SIZE-1 mu.reg_write(unicorn.arm_const.UC_ARM_REG_SP,SP) # 6. pc 指针指向地址开始执行 Hook (暂时屏蔽) # mu.hook_add(unicorn.UC_HOOK_CODE, hook_code) # 跟踪 cpu 执行状态 hook 这里默认跟踪全部,具体也能够配置 # mu.hook_add(unicorn.UC_HOOK_MEM_WRITE, hook_mem) # 跟踪 cpu 执行内存操做, 须要自写回调函数 # mu.hook_add(unicorn.UC_HOOK_INTR,hook_syscall) # hook 系统调用函数 # mu.hook_add(unicorn.UC_HOOK_BLOCK,hook_block) # hook 基本块 # 由于有内存操做,hook的时候并无映射内存,就会报错。因此要~主动映射内存 # mu.hook_add(unicorn.UC_HOOK_MEM_WRITE_UNMAPPED,hook_mem_write_unmapped) print_result(mu) # capstone 输出 try: add_satrt = ADDRESS+0x8500+1 # 偏移位置 ida 查看 THUMB 指令集因此要 ADDRESS +1, add_end = ADDRESS+0x851A # 由于 IDA 中 0x851A 最后一条是 LR,咱们这里不须要因此不 +1 便可 mu.emu_start(add_satrt, add_end) # 参数1:起始位置,参数2:结束位置 print('-------- unicorn 执行后--------') print_result(mu) # capstone 输出 except unicorn.UcError as e: print('\033[1;31mError: %s \033[0m' % e) def uni_add_six(): """6个参数超过 amr32 4个寄存器,须要将多的2个参数放到堆栈当中""" print('-------- unicorn 执行前--------') # 1. 建立实例 mu = unicorn.Uc(unicorn.UC_ARCH_ARM, unicorn.UC_MODE_THUMB) # 要指定架构和模式, 这里用 arm 架构, 指定 THUMB 指令集 # 2. 将代码片断映射到模拟器的虚拟地址 ADDRESS = 0x1000 # 映射开始地址 SIZE = 1024*1024*10 # 分配映射大小(多分一点) # 3. 开始映射 mu.mem_map(ADDRESS, SIZE) # 初始化映射 参数1:地址 参数2:空间大小 默认初始化后默认值:0 mu.mem_write(ADDRESS, CODE) # 写入指令 参数1: 写入位置 参数2:写入内容 # 写入寄存器 # 4. 寄存器初始化 指令集涉及到 R0,R1,R2,R3 4个寄存器 mu.reg_write(unicorn.arm_const.UC_ARM_REG_R0, 0x1) # 在 r0 寄存器上写入 0x1 mu.reg_write(unicorn.arm_const.UC_ARM_REG_R1, 0x2) # 在 r1 寄存器上写入 0x2 mu.reg_write(unicorn.arm_const.UC_ARM_REG_R2, 0x3) # 在 r1 寄存器上写入 0x3 mu.reg_write(unicorn.arm_const.UC_ARM_REG_R3, 0x4) # 在 r1 寄存器上写入 0x4 # 可是 IDA 中咱们并无作堆栈平衡处理,要指向一个地址,他才能执行完 mu.reg_write(unicorn.arm_const.UC_ARM_REG_LR,ADDRESS+0x456) # 随便指向 0x456 一个存在的地址 # 5. 初始化堆栈,由于要对内存进行操做 设置 SP SP = ADDRESS+SIZE-16 # 多减点,预留 sp 剩下两个参数的位置 mu.reg_write(unicorn.arm_const.UC_ARM_REG_SP,SP) # 6. 多的两个参数,5和 6 要手动放入堆栈当中(从右至左) mu.mem_write(SP, struct.pack('I', 5)) mu.mem_write(SP+4, struct.pack('I', 6)) print_result(mu) # capstone 输出 try: add_satrt = ADDRESS+0x851C+1 # 偏移位置 ida 查看 THUMB 指令集因此要 ADDRESS +1, add_end = ADDRESS+0x858E + 8 # 由于咱们手动平衡了内存因此多给点空间 mu.emu_start(add_satrt, add_end) # 参数1:起始位置,参数2:结束位置 print('-------- unicorn 执行后--------') print_result(mu) # capstone 输出 except unicorn.UcError as e: print('\033[1;31mError: %s \033[0m' % e) def print_result(mu): """调试寄存器值 UC_ARM_REG_R0 = 66 UC_ARM_REG_R1 = 67 UC_ARM_REG_R2 = 68 UC_ARM_REG_R3 = 69 UC_ARM_REG_R4 = 70 """ for i in range(66,78): print("寄存器[R%d], hex 值:%x"%(i-66,mu.reg_read(i))) print("SP 值:%x" % (mu.reg_read(unicorn.arm_const.UC_ARM_REG_SP))) print("PC 值:%x" % (mu.reg_read(unicorn.arm_const.UC_ARM_REG_PC))) if __name__ == "__main__": # add 2 参数的相加 print('--------------add --------------') capstone_print(CODE, 0x8500) uni_add() # 模拟 add 函数 print('\n-------------- add_six --------------') # add_six 6个参数的相加 capstone_print(CODE, 0x851C) uni_add_six()
Python
_ 复制_
依赖调用了其余so函数的状况下就不能像以前例子这样调用了
c 中函数如图, 咱们就须要在调用了外部函数的位置打 排齐
调用位置在 859A
""" 【依赖调用了其余so函数的状况下就不能像以前例子这样调用了】 实现对 so 中函数调用 int add_six(char* flag,int b,int c, int d, int e,int f){ int sum=0; if(strstr(flag, "add")){ sum=add(sum,c); sum=add(sum,d); }else{ sum=add(sum,e); sum=add(sum,f); } } extern "C" JNIEXPORT jstring JNICALL Java_com_zok_uni_MainActivity_stringFromJNI( JNIEnv* env, jobject /* this */) { std::string hello = "Hello from C++"; int sum=add(3,4); sum=add_six("flag",2,3,4,5,6); return env->NewStringUTF(hello.c_str()); } """ import unicorn import capstone import binascii import struct # 取出 so 内容 with open("so/callstrstr.so",'rb') as f: CODE=f.read() def capstone_print(code, offset): """capstone 测试输出""" print("\033[1;32m-------- capstone 输出--------\033[0m") CP = capstone.Cs(capstone.CS_ARCH_ARM, capstone.CS_MODE_THUMB) # 指定 THUMB 指令集 for i in CP.disasm(code[offset:], 0, 20): print('\033[1;32m地址: 0x%x | 操做码: %s | 内容: %s\033[0m'%(offset + i.address, i.mnemonic, i.op_str)) def uni_add_six(): """6个参数超过 amr32 4个寄存器,须要将多的2个参数放到堆栈当中""" print('-------- unicorn 执行前--------') # 1. 建立实例 mu = unicorn.Uc(unicorn.UC_ARCH_ARM, unicorn.UC_MODE_THUMB) # 要指定架构和模式, 这里用 arm 架构, 指定 THUMB 指令集 # 2. 将代码片断映射到模拟器的虚拟地址 ADDRESS = 0x1000 # 映射开始地址 SIZE = 1024*1024*10 # 分配映射大小(多分一点) # 3. 开始映射 mu.mem_map(ADDRESS, SIZE) # 初始化映射 参数1:地址 参数2:空间大小 默认初始化后默认值:0 mu.mem_write(ADDRESS, CODE) # 写入指令 参数1: 写入位置 参数2:写入内容 """处理外部 so 调用""" # 此处要给,调用了外部 so 的地址写入 nop, 而后经过添加回调函数来实现效果 mu.mem_write(ADDRESS+0x859A, b'\x00\xbf\x00\xbf') # \x00\xbf\x00\xbf 为 两个 nop, 由于0x859A处有4个字节,因此用两个nop 填充 # 写入寄存器 # 4. 寄存器初始化 指令集涉及到 R0,R1,R2,R3 4个寄存器 # 第一个参数是 string ,须要给指针、 mu.mem_map(ADDRESS+SIZE+0x1000, 1024) # 开辟 mu.mem_write(ADDRESS+SIZE+0x1000, b'flag2') # 写入 bytes=mu.mem_read(ADDRESS+SIZE+0x1000,5) # 调试输出 print(binascii.b2a_hex(bytes)) mu.reg_write(unicorn.arm_const.UC_ARM_REG_R0, ADDRESS+SIZE+0x1000) # 在 r0 寄存器上写入刚刚建立的指针 mu.reg_write(unicorn.arm_const.UC_ARM_REG_R1, 0x2) # 在 r1 寄存器上写入 0x2 mu.reg_write(unicorn.arm_const.UC_ARM_REG_R2, 0x3) # 在 r1 寄存器上写入 0x3 mu.reg_write(unicorn.arm_const.UC_ARM_REG_R3, 0x4) # 在 r1 寄存器上写入 0x4 # 可是 IDA 中咱们并无作堆栈平衡处理,要指向一个地址,他才能执行完 mu.reg_write(unicorn.arm_const.UC_ARM_REG_LR,ADDRESS+0x456) # 随便指向 0x456 一个存在的地址 # 5. 初始化堆栈,由于要对内存进行操做 设置 SP SP = ADDRESS+SIZE-16 # 多减点,预留 sp 剩下两个参数的位置 mu.reg_write(unicorn.arm_const.UC_ARM_REG_SP,SP) # 6. 多的两个参数,5和 6 要手动放入堆栈当中(从右至左) mu.mem_write(SP, struct.pack('I', 5)) mu.mem_write(SP+4, struct.pack('I', 6)) # hook 代码 mu.hook_add(unicorn.UC_HOOK_CODE, hook_code) mu.hook_add(unicorn.UC_HOOK_INTR,hook_syscall) # hook 系统调用函数 mu.hook_add(unicorn.UC_HOOK_BLOCK,hook_block) # hook 基本块 print_result(mu) # capstone 输出 try: add_satrt = ADDRESS+0x854C+1 # 偏移位置 ida 查看 THUMB 指令集因此要 ADDRESS +1, add_end = ADDRESS+0x85D8 # 由于咱们手动平衡了内存因此多给点空间 mu.emu_start(add_satrt, add_end) # 参数1:起始位置,参数2:结束位置 print('-------- unicorn 执行后--------') print_result(mu) # capstone 输出 except unicorn.UcError as e: print('\033[1;31mError: %s \033[0m' % e) def hook_code(mu, address, size, user_data): """定义回调函数, 在进入汇编指令以前就会先运行这里 mu: 模拟器 address: 执行地址 size: 汇编指令大小 user_data: 经过 hook_add 添加的参数 """ code=mu.mem_read(address,size) # 读取 if address==0x1000+0x859A: # 外部 so 调用地址 """hook 两个参数并返回正确值(自行计算)""" r0value=readstring(mu,mu.reg_read(unicorn.arm_const.UC_ARM_REG_R0)) r1value = readstring(mu, mu.reg_read(unicorn.arm_const.UC_ARM_REG_R1)) index=r0value.find(r1value) # 用 find 的方法模拟实现并写入 R0 寄存器中便可 if index==-1: # 没有找到的话,就返回 0 mu.reg_write(unicorn.arm_const.UC_ARM_REG_R0,0) else: # 找到的话,就返回位置 mu.reg_write(unicorn.arm_const.UC_ARM_REG_R0, index) print("\033[1;36m执行外部 so 函数 strstr 参数1: %s, 参数2: %s\033[0m"%(r0value, r1value)) CP = capstone.Cs(capstone.CS_ARCH_ARM, capstone.CS_MODE_THUMB) # 指定 THUMB 指令集 for i in CP.disasm(code, 0, len(code)): print('\033[1;30m【Hook cpu】 地址: 0x%x | 操做码: %s | 内容: %s\033[0m'%(address + i.address, i.mnemonic, i.op_str)) return def hook_syscall(mu,intno,user_data): print("\033[1;36mhook 系统调用 系统调用号: 0x%d"%intno) if intno==2: # 例子 2 是退出 print("系统调用退出!!") print_result(mu) print("\033[0m") return def hook_block(mu, address, size, user_data): # code = mu.mem_read(address,size) print("\033[1;36mhook 基本块") print_result(mu) print("\033[0m") return def print_result(mu): """调试寄存器值 """ for i in range(66,78): print("寄存器[R%d], hex 值:%x"%(i-66,mu.reg_read(i))) print("SP 值:%x" % (mu.reg_read(unicorn.arm_const.UC_ARM_REG_SP))) print("PC 值:%x" % (mu.reg_read(unicorn.arm_const.UC_ARM_REG_PC))) def readstring(mu,address): """读出结果""" result='' tmp=mu.mem_read(address,1) while(tmp[0]!=0): result=result+chr(tmp[0]) address=address+1 tmp = mu.mem_read(address, 1) return result if __name__ == "__main__": print('\n-------------- add_six 延展外部 so 调用示例--------------') capstone_print(CODE, 0x851C) uni_add_six()
-------------- add_six 延展外部 so 调用示例-------------- -------- capstone 输出-------- 地址: 0x851c | 操做码: movs | 内容: r0, r0 地址: 0x851e | 操做码: b | 内容: #0x124 地址: 0x8520 | 操做码: movs | 内容: r0, #2 地址: 0x8522 | 操做码: b | 内容: #0x128 -------- unicorn 执行前-------- b'666c616732' 寄存器[R0], hex 值:a02000 寄存器[R1], hex 值:2 寄存器[R2], hex 值:3 寄存器[R3], hex 值:4 寄存器[R4], hex 值:0 寄存器[R5], hex 值:0 寄存器[R6], hex 值:0 寄存器[R7], hex 值:0 寄存器[R8], hex 值:0 寄存器[R9], hex 值:0 寄存器[R10], hex 值:0 寄存器[R11], hex 值:0 SP 值:a00ff0 PC 值:0 hook 基本块 寄存器[R0], hex 值:a02000 寄存器[R1], hex 值:2 寄存器[R2], hex 值:3 寄存器[R3], hex 值:4 寄存器[R4], hex 值:0 寄存器[R5], hex 值:0 寄存器[R6], hex 值:0 寄存器[R7], hex 值:0 寄存器[R8], hex 值:0 寄存器[R9], hex 值:0 寄存器[R10], hex 值:0 寄存器[R11], hex 值:0 SP 值:a00ff0 PC 值:954c 【Hook cpu】 地址: 0x954c | 操做码: push | 内容: {r4, r5, r6, r7, lr} 【Hook cpu】 地址: 0x954e | 操做码: add | 内容: r7, sp, #0xc 【Hook cpu】 地址: 0x9550 | 操做码: str | 内容: r8, [sp, #-0x4]! 【Hook cpu】 地址: 0x9554 | 操做码: sub | 内容: sp, #0x40 【Hook cpu】 地址: 0x9556 | 操做码: ldr.w | 内容: ip, [r7, #0xc] 【Hook cpu】 地址: 0x955a | 操做码: ldr.w | 内容: lr, [r7, #8] 【Hook cpu】 地址: 0x955e | 操做码: mov | 内容: r4, r3 【Hook cpu】 地址: 0x9560 | 操做码: mov | 内容: r5, r2 【Hook cpu】 地址: 0x9562 | 操做码: mov | 内容: r6, r1 【Hook cpu】 地址: 0x9564 | 操做码: mov | 内容: r8, r0 【Hook cpu】 地址: 0x9566 | 操做码: str | 内容: r0, [sp, #0x2c] 【Hook cpu】 地址: 0x9568 | 操做码: str | 内容: r1, [sp, #0x28] 【Hook cpu】 地址: 0x956a | 操做码: str | 内容: r2, [sp, #0x24] 【Hook cpu】 地址: 0x956c | 操做码: str | 内容: r3, [sp, #0x20] 【Hook cpu】 地址: 0x956e | 操做码: movs | 内容: r0, #0 【Hook cpu】 地址: 0x9570 | 操做码: str | 内容: r0, [sp, #0x1c] 【Hook cpu】 地址: 0x9572 | 操做码: ldr | 内容: r0, [sp, #0x2c] 【Hook cpu】 地址: 0x9574 | 操做码: str | 内容: r0, [sp, #0x34] 【Hook cpu】 地址: 0x9576 | 操做码: ldr | 内容: r0, [pc, #0x64] 【Hook cpu】 地址: 0x9578 | 操做码: add | 内容: r0, pc 【Hook cpu】 地址: 0x957a | 操做码: str | 内容: r0, [sp, #0x30] 【Hook cpu】 地址: 0x957c | 操做码: ldr | 内容: r0, [sp, #0x34] 【Hook cpu】 地址: 0x957e | 操做码: ldr | 内容: r1, [sp, #0x30] 【Hook cpu】 地址: 0x9580 | 操做码: str | 内容: r0, [sp, #0x3c] 【Hook cpu】 地址: 0x9582 | 操做码: str | 内容: r1, [sp, #0x38] 【Hook cpu】 地址: 0x9584 | 操做码: ldr | 内容: r0, [sp, #0x3c] 【Hook cpu】 地址: 0x9586 | 操做码: ldr | 内容: r1, [sp, #0x38] 【Hook cpu】 地址: 0x9588 | 操做码: str.w | 内容: ip, [sp, #0x18] 【Hook cpu】 地址: 0x958c | 操做码: str.w | 内容: lr, [sp, #0x14] 【Hook cpu】 地址: 0x9590 | 操做码: str | 内容: r4, [sp, #0x10] 【Hook cpu】 地址: 0x9592 | 操做码: str | 内容: r5, [sp, #0xc] 【Hook cpu】 地址: 0x9594 | 操做码: str | 内容: r6, [sp, #8] 【Hook cpu】 地址: 0x9596 | 操做码: str.w | 内容: r8, [sp, #4] 执行外部 so 函数 strstr 参数1: flag2, 参数2: add 【Hook cpu】 地址: 0x959a | 操做码: nop | 内容: 【Hook cpu】 地址: 0x959c | 操做码: nop | 内容: 【Hook cpu】 地址: 0x959e | 操做码: cmp | 内容: r0, #0 【Hook cpu】 地址: 0x95a0 | 操做码: beq | 内容: #0x1a hook 基本块 寄存器[R0], hex 值:0 寄存器[R1], hex 值:16a2c 寄存器[R2], hex 值:3 寄存器[R3], hex 值:4 寄存器[R4], hex 值:4 寄存器[R5], hex 值:3 寄存器[R6], hex 值:2 寄存器[R7], hex 值:a00fe8 寄存器[R8], hex 值:a02000 寄存器[R9], hex 值:0 寄存器[R10], hex 值:0 寄存器[R11], hex 值:0 SP 值:a00f98 PC 值:95ba 【Hook cpu】 地址: 0x95ba | 操做码: ldr | 内容: r0, [sp, #0x1c] 【Hook cpu】 地址: 0x95bc | 操做码: ldr | 内容: r1, [r7, #8] 【Hook cpu】 地址: 0x95be | 操做码: bl | 内容: #0xffffff72 hook 基本块 寄存器[R0], hex 值:0 寄存器[R1], hex 值:5 寄存器[R2], hex 值:3 寄存器[R3], hex 值:4 寄存器[R4], hex 值:4 寄存器[R5], hex 值:3 寄存器[R6], hex 值:2 寄存器[R7], hex 值:a00fe8 寄存器[R8], hex 值:a02000 寄存器[R9], hex 值:0 寄存器[R10], hex 值:0 寄存器[R11], hex 值:0 SP 值:a00f98 PC 值:9530 【Hook cpu】 地址: 0x9530 | 操做码: sub | 内容: sp, #0x14 【Hook cpu】 地址: 0x9532 | 操做码: mov | 内容: r2, r1 【Hook cpu】 地址: 0x9534 | 操做码: mov | 内容: r3, r0 【Hook cpu】 地址: 0x9536 | 操做码: str | 内容: r0, [sp, #0x10] 【Hook cpu】 地址: 0x9538 | 操做码: str | 内容: r1, [sp, #0xc] 【Hook cpu】 地址: 0x953a | 操做码: ldr | 内容: r0, [sp, #0x10] 【Hook cpu】 地址: 0x953c | 操做码: ldr | 内容: r1, [sp, #0xc] 【Hook cpu】 地址: 0x953e | 操做码: add | 内容: r0, r1 【Hook cpu】 地址: 0x9540 | 操做码: str | 内容: r0, [sp, #8] 【Hook cpu】 地址: 0x9542 | 操做码: ldr | 内容: r0, [sp, #8] 【Hook cpu】 地址: 0x9544 | 操做码: str | 内容: r2, [sp, #4] 【Hook cpu】 地址: 0x9546 | 操做码: str | 内容: r3, [sp] 【Hook cpu】 地址: 0x9548 | 操做码: add | 内容: sp, #0x14 【Hook cpu】 地址: 0x954a | 操做码: bx | 内容: lr hook 基本块 寄存器[R0], hex 值:5 寄存器[R1], hex 值:5 寄存器[R2], hex 值:5 寄存器[R3], hex 值:0 寄存器[R4], hex 值:4 寄存器[R5], hex 值:3 寄存器[R6], hex 值:2 寄存器[R7], hex 值:a00fe8 寄存器[R8], hex 值:a02000 寄存器[R9], hex 值:0 寄存器[R10], hex 值:0 寄存器[R11], hex 值:0 SP 值:a00f98 PC 值:95c2 【Hook cpu】 地址: 0x95c2 | 操做码: str | 内容: r0, [sp, #0x1c] 【Hook cpu】 地址: 0x95c4 | 操做码: ldr | 内容: r0, [sp, #0x1c] 【Hook cpu】 地址: 0x95c6 | 操做码: ldr | 内容: r1, [r7, #0xc] 【Hook cpu】 地址: 0x95c8 | 操做码: bl | 内容: #0xffffff68 hook 基本块 寄存器[R0], hex 值:5 寄存器[R1], hex 值:6 寄存器[R2], hex 值:5 寄存器[R3], hex 值:0 寄存器[R4], hex 值:4 寄存器[R5], hex 值:3 寄存器[R6], hex 值:2 寄存器[R7], hex 值:a00fe8 寄存器[R8], hex 值:a02000 寄存器[R9], hex 值:0 寄存器[R10], hex 值:0 寄存器[R11], hex 值:0 SP 值:a00f98 PC 值:9530 【Hook cpu】 地址: 0x9530 | 操做码: sub | 内容: sp, #0x14 【Hook cpu】 地址: 0x9532 | 操做码: mov | 内容: r2, r1 【Hook cpu】 地址: 0x9534 | 操做码: mov | 内容: r3, r0 【Hook cpu】 地址: 0x9536 | 操做码: str | 内容: r0, [sp, #0x10] 【Hook cpu】 地址: 0x9538 | 操做码: str | 内容: r1, [sp, #0xc] 【Hook cpu】 地址: 0x953a | 操做码: ldr | 内容: r0, [sp, #0x10] 【Hook cpu】 地址: 0x953c | 操做码: ldr | 内容: r1, [sp, #0xc] 【Hook cpu】 地址: 0x953e | 操做码: add | 内容: r0, r1 【Hook cpu】 地址: 0x9540 | 操做码: str | 内容: r0, [sp, #8] 【Hook cpu】 地址: 0x9542 | 操做码: ldr | 内容: r0, [sp, #8] 【Hook cpu】 地址: 0x9544 | 操做码: str | 内容: r2, [sp, #4] 【Hook cpu】 地址: 0x9546 | 操做码: str | 内容: r3, [sp] 【Hook cpu】 地址: 0x9548 | 操做码: add | 内容: sp, #0x14 【Hook cpu】 地址: 0x954a | 操做码: bx | 内容: lr hook 基本块 寄存器[R0], hex 值:b 寄存器[R1], hex 值:6 寄存器[R2], hex 值:6 寄存器[R3], hex 值:5 寄存器[R4], hex 值:4 寄存器[R5], hex 值:3 寄存器[R6], hex 值:2 寄存器[R7], hex 值:a00fe8 寄存器[R8], hex 值:a02000 寄存器[R9], hex 值:0 寄存器[R10], hex 值:0 寄存器[R11], hex 值:0 SP 值:a00f98 PC 值:95cc 【Hook cpu】 地址: 0x95cc | 操做码: str | 内容: r0, [sp, #0x1c] 【Hook cpu】 地址: 0x95ce | 操做码: b | 内容: #2 hook 基本块 寄存器[R0], hex 值:b 寄存器[R1], hex 值:6 寄存器[R2], hex 值:6 寄存器[R3], hex 值:5 寄存器[R4], hex 值:4 寄存器[R5], hex 值:3 寄存器[R6], hex 值:2 寄存器[R7], hex 值:a00fe8 寄存器[R8], hex 值:a02000 寄存器[R9], hex 值:0 寄存器[R10], hex 值:0 寄存器[R11], hex 值:0 SP 值:a00f98 PC 值:95d0 【Hook cpu】 地址: 0x95d0 | 操做码: ldr | 内容: r0, [sp, #0x1c] 【Hook cpu】 地址: 0x95d2 | 操做码: add | 内容: sp, #0x40 【Hook cpu】 地址: 0x95d4 | 操做码: ldr | 内容: r8, [sp], #4 -------- unicorn 执行后-------- 寄存器[R0], hex 值:b 寄存器[R1], hex 值:6 寄存器[R2], hex 值:6 寄存器[R3], hex 值:5 寄存器[R4], hex 值:4 寄存器[R5], hex 值:3 寄存器[R6], hex 值:2 寄存器[R7], hex 值:a00fe8 寄存器[R8], hex 值:0 寄存器[R9], hex 值:0 寄存器[R10], hex 值:0 寄存器[R11], hex 值:0 SP 值:a00fdc PC 值:95d4
**