抖音數據採集教程,Unicorn 模擬 CPU 調用 Native 函數

抖音數據採集教程,Unicorn 模擬 CPU 調用 Native 函數

短視頻、直播數據實時採集接口,請查看文檔: TiToDataandroid


免責聲明:本文檔僅供學習與參考,請勿用於非法用途!不然一切後果自負。架構

接口

內存相關app

  • 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 上手


先本身寫個 超級簡單的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 分析

打開IDA 查看位置,爲了查看方便咱們配置一下, Options--general

簡單的找到函數位置, 並更名


動態調試指針

  1. 咱們動態 IDA 動態調試看看,手機啓動 android 服務。並新啓動一個 IDA 附加進程。打開 Modules 模塊(Debugger--DebuggerWindows--ModulesList)
  2. Modules 中搜索查看 so 的加載
    找到 stringFromJNI 的真實綁定地址就是在 C78CD628

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

  1. F9 調試運行
    對照靜態ida

8646和8648 下面就是 864A 也就是 add 函數了
因此此處對應 add 函數咱們能夠更名, 同理能夠找到 add_six 函數

結論

繼續調試後總結以下:

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

實際操做

先記住兩個函數的偏移位置


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
_ 複製_

調用 libc 函數

依賴調用了其餘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()

Python
_ 複製_

完成模擬操做

-------------- 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

**

相關文章
相關標籤/搜索