主頁 > 資料庫 > 抖音資料采集教程,Unicorn 模擬 CPU 呼叫 Native 函式

抖音資料采集教程,Unicorn 模擬 CPU 呼叫 Native 函式

2021-01-29 07:49:02 資料庫

抖音資料采集教程,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 上手


先自己寫個 超級簡單的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
_ 復制_

抹去符號,讓他直接在 so 中呼叫 add_definitions(-fvisibility=hidden)

32位下,引數小于4個的時候會直接通過暫存器來傳遞!!多余的只能進入堆疊當中(從右到左依次入堆疊)

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=https://www.cnblogs.com/titodata/archive/2021/01/28/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

**

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/253943.html

標籤:其他

上一篇:Mysql事務中的ACID是怎么實作的

下一篇:MySql下載及簡介

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • GPU虛擬機創建時間深度優化

    **?桔妹導讀:**GPU虛擬機實體創建速度慢是公有云面臨的普遍問題,由于通常情況下創建虛擬機屬于低頻操作而未引起業界的重視,實際生產中還是存在對GPU實體創建時間有苛刻要求的業務場景。本文將介紹滴滴云在解決該問題時的思路、方法、并展示最終的優化成果。 從公有云服務商那里購買過虛擬主機的資深用戶,一 ......

    uj5u.com 2020-09-10 06:09:13 more
  • 可編程網卡芯片在滴滴云網路的應用實踐

    **?桔妹導讀:**隨著云規模不斷擴大以及業務層面對延遲、帶寬的要求越來越高,采用DPDK 加速網路報文處理的方式在橫向縱向擴展都出現了局限性。可編程芯片成為業界熱點。本文主要講述了可編程網卡芯片在滴滴云網路中的應用實踐,遇到的問題、帶來的收益以及開源社區貢獻。 #1. 資料中心面臨的問題 隨著滴滴 ......

    uj5u.com 2020-09-10 06:10:21 more
  • 滴滴資料通道服務演進之路

    **?桔妹導讀:**滴滴資料通道引擎承載著全公司的資料同步,為下游實時和離線場景提供了必不可少的源資料。隨著任務量的不斷增加,資料通道的整體架構也隨之發生改變。本文介紹了滴滴資料通道的發展歷程,遇到的問題以及今后的規劃。 #1. 背景 資料,對于任何一家互聯網公司來說都是非常重要的資產,公司的大資料 ......

    uj5u.com 2020-09-10 06:11:05 more
  • 滴滴AI Labs斬獲國際機器翻譯大賽中譯英方向世界第三

    **桔妹導讀:**深耕人工智能領域,致力于探索AI讓出行更美好的滴滴AI Labs再次斬獲國際大獎,這次獲獎的專案是什么呢?一起來看看詳細報道吧! 近日,由國際計算語言學協會ACL(The Association for Computational Linguistics)舉辦的世界最具影響力的機器 ......

    uj5u.com 2020-09-10 06:11:29 more
  • MPP (Massively Parallel Processing)大規模并行處理

    1、什么是mpp? MPP (Massively Parallel Processing),即大規模并行處理,在資料庫非共享集群中,每個節點都有獨立的磁盤存盤系統和記憶體系統,業務資料根據資料庫模型和應用特點劃分到各個節點上,每臺資料節點通過專用網路或者商業通用網路互相連接,彼此協同計算,作為整體提供 ......

    uj5u.com 2020-09-10 06:11:41 more
  • 滴滴資料倉庫指標體系建設實踐

    **桔妹導讀:**指標體系是什么?如何使用OSM模型和AARRR模型搭建指標體系?如何統一流程、規范化、工具化管理指標體系?本文會對建設的方法論結合滴滴資料指標體系建設實踐進行解答分析。 #1. 什么是指標體系 ##1.1 指標體系定義 指標體系是將零散單點的具有相互聯系的指標,系統化的組織起來,通 ......

    uj5u.com 2020-09-10 06:12:52 more
  • 單表千萬行資料庫 LIKE 搜索優化手記

    我們經常在資料庫中使用 LIKE 運算子來完成對資料的模糊搜索,LIKE 運算子用于在 WHERE 子句中搜索列中的指定模式。 如果需要查找客戶表中所有姓氏是“張”的資料,可以使用下面的 SQL 陳述句: SELECT * FROM Customer WHERE Name LIKE '張%' 如果需要 ......

    uj5u.com 2020-09-10 06:13:25 more
  • 滴滴Ceph分布式存盤系統優化之鎖優化

    **桔妹導讀:**Ceph是國際知名的開源分布式存盤系統,在工業界和學術界都有著重要的影響。Ceph的架構和演算法設計發表在國際系統領域頂級會議OSDI、SOSP、SC等上。Ceph社區得到Red Hat、SUSE、Intel等大公司的大力支持。Ceph是國際云計算領域應用最廣泛的開源分布式存盤系統, ......

    uj5u.com 2020-09-10 06:14:51 more
  • es~通過ElasticsearchTemplate進行聚合~嵌套聚合

    之前寫過《es~通過ElasticsearchTemplate進行聚合操作》的文章,這一次主要寫一個嵌套的聚合,例如先對sex集合,再對desc聚合,最后再對age求和,共三層嵌套。 Aggregations的部分特性類似于SQL語言中的group by,avg,sum等函式,Aggregation ......

    uj5u.com 2020-09-10 06:14:59 more
  • 爬蟲日志監控 -- Elastc Stack(ELK)部署

    傻瓜式部署,只需替換IP與用戶 導讀: 現ELK四大組件分別為:Elasticsearch(核心)、logstash(處理)、filebeat(采集)、kibana(可視化) 下載均在https://www.elastic.co/cn/downloads/下tar包,各組件版本最好一致,配合fdm會 ......

    uj5u.com 2020-09-10 06:15:05 more
最新发布
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:33:24 more
  • MySQL中binlog備份腳本分享

    關于MySQL的二進制日志(binlog),我們都知道二進制日志(binlog)非常重要,尤其當你需要point to point災難恢復的時侯,所以我們要對其進行備份。關于二進制日志(binlog)的備份,可以基于flush logs方式先切換binlog,然后拷貝&壓縮到到遠程服務器或本地服務器 ......

    uj5u.com 2023-04-20 08:28:06 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:27:27 more
  • 快取與資料庫雙寫一致性幾種策略分析

    本文將對幾種快取與資料庫保證資料一致性的使用方式進行分析。為保證高并發性能,以下分析場景不考慮執行的原子性及加鎖等強一致性要求的場景,僅追求最終一致性。 ......

    uj5u.com 2023-04-20 08:26:48 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:26:35 more
  • 云時代,MySQL到ClickHouse資料同步產品對比推薦

    ClickHouse 在執行分析查詢時的速度優勢很好的彌補了MySQL的不足,但是對于很多開發者和DBA來說,如何將MySQL穩定、高效、簡單的同步到 ClickHouse 卻很困難。本文對比了 NineData、MaterializeMySQL(ClickHouse自帶)、Bifrost 三款產品... ......

    uj5u.com 2023-04-20 08:26:29 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:25:13 more
  • Redis 報”OutOfDirectMemoryError“(堆外記憶體溢位)

    Redis 報錯“OutOfDirectMemoryError(堆外記憶體溢位) ”問題如下: 一、報錯資訊: 使用 Redis 的業務介面 ,產生 OutOfDirectMemoryError(堆外記憶體溢位),如圖: 格式化后的報錯資訊: { "timestamp": "2023-04-17 22: ......

    uj5u.com 2023-04-20 08:24:54 more
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:24:03 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:23:11 more