短視頻、直播數據實時採集接口,請查看文檔: 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
**