天天看點

抖音資料采集教程,Unicorn 模拟 CPU 調用 Native 函數

抖音資料采集教程,Unicorn 模拟 CPU 調用 Native 函數

短視訊、直播資料實時采集接口,請檢視文檔: TiToData

免責聲明:本文檔僅供學習與參考,請勿用于非法用途!否則一切後果自負。

接口

記憶體相關

  • uc_mem_map
  • uc_mem_read
  • uc_mem_write

寄存器相關

  • uc_reg_read
  • uc_reg_write

指令執行類

  • UC_HOOK_INTR
  • UC_HOOK_INSN
  • UC_HOOK_CODE
  • UC_HOOK_BLOCK

記憶體通路類

  • UC_HOOK_MEM_READ
  • UC_HOOK_MEM_WRITE
  • UC_HOOK_MEM_FETCH
  • .....

異常處理類

  • UC_HOOK_MEM_READ_UNMAPPED
  • UC_HOOK_MEM_WRITE_UNMAPPED
  • UC_HOOK_MEM_FETCH_UNMAPPED

Unicorn 上手

抖音資料采集教程,Unicorn 模拟 CPU 調用 Native 函數

先自己寫個 超級簡單的app,并編譯(沒有開混淆保護)

#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

_ 複制_

抖音資料采集教程,Unicorn 模拟 CPU 調用 Native 函數

抹去符号,讓他直接在 so 中調用 add_definitions(-fvisibility=hidden)

抖音資料采集教程,Unicorn 模拟 CPU 調用 Native 函數

32位下,參數小于4個的時候會直接通過寄存器來傳遞!!多餘的隻能進入堆棧當中(從右到左依次入棧)

IDA 分析

打開IDA 檢視位置,為了檢視友善我們配置一下, Options--general

抖音資料采集教程,Unicorn 模拟 CPU 調用 Native 函數

簡單的找到函數位置, 并改名

抖音資料采集教程,Unicorn 模拟 CPU 調用 Native 函數
抖音資料采集教程,Unicorn 模拟 CPU 調用 Native 函數

動态調試

  1. 我們動态 IDA 動态調試看看,手機啟動 android 服務。并新啟動一個 IDA 附加程序。打開 Modules 子產品(Debugger--DebuggerWindows--ModulesList)
  2. Modules 中搜尋
    抖音資料采集教程,Unicorn 模拟 CPU 調用 Native 函數
    檢視 so 的加載
    抖音資料采集教程,Unicorn 模拟 CPU 調用 Native 函數
    找到 stringFromJNI 的真實綁定位址就是在 C78CD628 中

接下來就要看他參數的調用傳遞情況和堆棧情況

  1. F9 調試運作

    對照靜态ida

    抖音資料采集教程,Unicorn 模拟 CPU 調用 Native 函數

8646和8648 下面就是 864A 也就是 add 函數了

抖音資料采集教程,Unicorn 模拟 CPU 調用 Native 函數

是以此處對應 add 函數我們可以改名, 同理可以找到 add_six 函數

結論

繼續調試後總結如下:

  1. ARM32位下,參數小于4個的時候會直接通過寄存器來傳遞(R0-R3)!從右至左依次入!多餘的隻能進入堆棧當中(從右到左依次入棧)
  2. ARM64位下,參數小于8個會通過 (X0-X7)寄存器傳遞從右至左依次入棧;多餘的要使用棧來傳遞剩餘參數
  3. 32位下,THUMB 指令集是滿棧模式,sp 始終指向有值的内容

實際操作

先記住兩個函數的偏移位置
抖音資料采集教程,Unicorn 模拟 CPU 調用 Native 函數

add 函數偏移位置 8500

抖音資料采集教程,Unicorn 模拟 CPU 調用 Native 函數

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

調用 libc 函數

"""
【依賴調用了其他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      

繼續閱讀