主頁 > 資料庫 > 抖音資料采集Frida教程,rpc、Process、Module、Memory使用方法及示例

抖音資料采集Frida教程,rpc、Process、Module、Memory使用方法及示例

2021-01-18 06:39:42 資料庫

抖音資料采集Frida教程,rpc、Process、Module、Memory使用方法及示例

前言

大家好,窩又來寫文章了,咱們現在在這篇文章中,我們來對其官方的一些非常常用的API進行學習,所謂工欲善其事,必先利其器,想要好好學習FRIDA我們就必須對FRIDA API深入的學習以對其有更深的了解和使用,通常大部分核心原理也在官方API中寫著,我們學會來使用一些案例來結合API的使用,
注意,運行以下任何代碼時都需要提前啟動手機中的frida-server檔案,


1.1 FRIDA輸出列印

1.1.1 console輸出

不論是什么語言都好,第一個要學習總是如何輸出和列印,那我們就來學習在FRIDA列印值,在官方API有兩種列印的方式,分別是consolesend,我們先來學習非常的簡單的console,這里我創建一個js檔案,代碼示例如下,

function hello_printf() {
    Java.perform(function () {
        console.log("");
        console.log("hello-log");
        console.warn("hello-warn");
        console.error("hello-error");
    });
}
setImmediate(hello_printf,0);

當檔案創建好之后,我們需要運行在手機中安裝的frida-server檔案,在上一章我們學過了如何安裝在android手機安裝frida-server,現在來使用它,我們在ubuntu中開啟一個終端,運行以下代碼,啟動我們安裝好的frida-server檔案,

roysue@ubuntu:~$ adb shell
sailfish:/ $ su
sailfish:/ $ ./data/local/tmp/frida-server

然后執行以下代碼,對目標應用app的行程com.roysue.roysueapplication使用-l命令注入Chap03.js中的代碼1-1以及執行腳本之后的效果圖1-1
frida -U com.roysue.roysueapplication -l Chap03.js
代碼1-1 代碼示例


image.png
圖1-1 終端執行
可以到終點已經成功注入了腳本并且列印了hello,但是顏色不同,這是log的級別的原因,在FRIDAconsole中有三個級別分別是log、warn、error

級別 含義
log 正常
warn 警告
error 錯誤

1.1.2 console之hexdump

error級別最為嚴重其次warn,但是一般在使用中我們只會使用log來輸出想看的值;然后我們繼續學習console的好兄弟,hexdump,其含義:列印記憶體中的地址,target引數可以是ArrayBuffer或者NativePointer,而options引數則是自定義輸出格式可以填這幾個引數offset、lengt、header、ansi
hexdump代碼示例以及執行效果如下,

var libc = Module.findBaseAddress('libc.so');
console.log(hexdump(libc, {
  offset: 0,
  length: 64,
  header: true,
  ansi: true
}));
           0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
00000000  7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00  .ELF............
00000010  03 00 28 00 01 00 00 00 00 00 00 00 34 00 00 00  ..(.........4...
00000020  34 a8 04 00 00 00 00 05 34 00 20 00 08 00 28 00  4.......4. ...(.
00000030  1e 00 1d 00 06 00 00 00 34 00 00 00 34 00 00 00  ........4...4...

1.1.3 send

send是在python層定義的on_message回呼函式,jscode內所有的資訊都被監控script.on('message', on_message),當輸出資訊的時候on_message函式會拿到其資料再通過format轉換, 其最重要的功能也是最核心的是能夠直接將資料以json格式輸出,當然資料是二進制的時候也依然是可以使用send,十分方便,我們來看代碼1-2示例以及執行效果,

# -*- coding: utf-8 -*-
import frida
import sys
def on_message(message, data):
    if message['type'] == 'send':
        print("[*] {0}".format(message['payload']))
    else:
        print(message)
jscode = """
    Java.perform(function () 
    {
        var jni_env = Java.vm.getEnv();
        console.log(jni_env);
        send(jni_env);
    });
 """
process = frida.get_usb_device().attach('com.roysue.roysueapplication')
script = process.create_script(jscode)
script.on('message', on_message)
script.load()
sys.stdin.read()
運行腳本效果如下:
roysue@ubuntu:~/Desktop/Chap09$ python Chap03.py 
[object Object]
[*] {'handle': '0xdf4f8000', 'vm': {}}

可以看出這里兩種方式輸出的不同的效果,console直接輸出了[object Object],無法輸出其正常的內容,因為jni_env實際上是一個物件,但是使用send的時候會自動將物件轉json格式輸出,通過對比,我們就知道send的好處啦~

1.2 FRIDA變數型別

學完輸出之后我們來學習如何宣告變數型別,

API 含義
new Int64(v) 定義一個有符號Int64型別的變數值為v,引數v可以是字串或者以0x開頭的的十六進制值
new UInt64(v) 定義一個無符號Int64型別的變數值為v,引數v可以是字串或者以0x開頭的的十六進制值
new NativePointer(s) 定義一個指標,指標地址為s
ptr(“0”) 同上

代碼示例以及效果

Java.perform(function () {
    console.log("");
    console.log("new Int64(1):"+new Int64(1));
    console.log("new UInt64(1):"+new UInt64(1));
    console.log("new NativePointer(0xEC644071):"+new NativePointer(0xEC644071));
    console.log("new ptr('0xEC644071'):"+new ptr(0xEC644071));
});
    輸出效果如下:
    new Int64(1):1
    new UInt64(1):1
    new NativePointer(0xEC644071):0xec644071
    new ptr('0xEC644071'):0xec644071

frida也為Int64(v)提供了一些相關的API:

API 含義
add(rhs)、sub(rhs)、and(rhs)、or(rhs)、xor(rhs) 加、減、邏輯運算
shr(N)、shl(n) 向右/向左移位n位生成新的Int64
Compare(Rhs) 回傳整數比較結果
toNumber() 轉換為數字
toString([radix=10]) 轉換為可選基數的字串(默認為10)

我也寫了一些使用案例,代碼如下,

function hello_type() {
    Java.perform(function () {
        console.log("");
        //8888 + 1 = 8889
        console.log("8888 + 1:"+new Int64("8888").add(1));
        //8888 - 1 = 8887
        console.log("8888 - 1:"+new Int64("8888").sub(1));
        //8888 << 1 = 4444
        console.log("8888 << 1:"+new Int64("8888").shr(1));
        //8888 == 22 = 1 1是false
        console.log("8888 == 22:"+new Int64("8888").compare(22));
        //轉string
        console.log("8888 toString:"+new Int64("8888").toString());
    });
}

代碼執行效果如圖1-2,
image.png
圖1-2 Int64 API

1.3 RPC遠程呼叫

可以替換或插入的空物件,以向應用程式公開RPC樣式的API,該鍵指定方法名稱,該值是匯出的函式,此函式可以回傳一個純值以立即回傳給呼叫方,或者承諾異步回傳,也就是說可以通過rpc的匯出的功能使用在python層,使python層與js互動,官方示例代碼有Node.js版本與python版本,我們在這里使用python版本,代碼如下,

1.3.1 遠程呼叫代碼示例

import frida
def on_message(message, data):
    if message['type'] == 'send':
        print(message['payload'])
    elif message['type'] == 'error':
        print(message['stack'])
session = frida.get_usb_device().attach('com.roysue.roysueapplication')
source = """
    rpc.exports = {
    add: function (a, b) {
        return a + b;
    },
    sub: function (a, b) {
        return new Promise(function (resolve) {
        setTimeout(function () {
            resolve(a - b);
        }, 100);
        });
    }
    };
"""
script = session.create_script(source)
script.on('message', on_message)
script.load()
print(script.exports.add(2, 3))
print(script.exports.sub(5, 3))
session.detach()

1.3.2 遠程呼叫代碼示例詳解

官方原始碼示例是附加在目標行程為iTunes,再通過將rpc./agent.js檔案讀取到source,進行使用,我這里修改了附加的目標的行程以及直接將rpc的代碼定義在source中,我們來看看這段是咋運行的,仍然先對目標行程附加,然后在寫js中代碼,也是source變數,通過rpc.exports關鍵字定義需要匯出的兩個函式,上面定義了add函式和sub函式,兩個的函式寫作方式不一樣,大家以后寫按照add方法寫就好了,sub稍微有點復雜,宣告完函式之后創建了一個腳本并且注入行程,加載了腳本之后可以到print(script.exports.add(2, 3))以及print(script.exports.sub(5, 3)),python層直接呼叫,add的回傳的結果為5sub則是2,下見下圖1-3
image.png
圖1-3 執行python腳本

1.4 Process物件

我們現在來介紹以及使用一些Process物件中比較常用的api~

1.4.1 Process.id

Process.id:回傳附加目標行程的PID

1.4.2 Process.isDebuggerAttached()

Process.isDebuggerAttached():檢測當前是否對目標程式已經附加

1.4.3 Process.enumerateModules()

列舉當前加載的模塊,回傳模塊物件的陣列,
Process.enumerateModules()會列舉當前所有已加載的so模塊,并且回傳了陣列Module物件,Module物件下一節我們來詳細說,在這里我們暫時只使用Module物件的name屬性,

function frida_Process() {
    Java.perform(function () {
        var process_Obj_Module_Arr = Process.enumerateModules();
        for(var i = 0; i < process_Obj_Module_Arr.length; i++) {
            console.log("",process_Obj_Module_Arr[i].name);
        }
    });
}
setImmediate(frida_Process,0);

我來們開看看這段js代碼寫了啥:在js中能夠直接使用Process物件的所有api,呼叫了Process.enumerateModules()方法之后會回傳一個陣列,陣列中存盤N個叫Module的物件,既然已經知道回傳了的是一個陣列,很簡單我們就來for回圈它便是,這里我使用下標的方式呼叫了Module物件的name屬性,nameso模塊的名稱,見下圖1-4
image.png
圖1-4 終端輸出了所有已加載的so

1.4.4 Process.enumerateThreads()

Process.enumerateThreads():列舉當前所有的執行緒,回傳包含以下屬性的物件陣列:

屬性 含義
id 執行緒id
state 當前運行狀態有running, stopped, waiting, uninterruptible or halted
context 帶有鍵pc和sp的物件,它們是分別為ia32/x64/arm指定EIP/RIP/PC和ESP/RSP/SP的NativePointer物件,也可以使用其他處理器特定的密鑰,例如eax、rax、r0、x0等,

使用代碼示例如下:

function frida_Process() {
    Java.perform(function () {
       var enumerateThreads =  Process.enumerateThreads();
       for(var i = 0; i < enumerateThreads.length; i++) {
        console.log("");
        console.log("id:",enumerateThreads[i].id);
        console.log("state:",enumerateThreads[i].state);
        console.log("context:",JSON.stringify(enumerateThreads[i].context));
        }
    });
}
setImmediate(frida_Process,0);

獲取當前是所有執行緒之后回傳了一個陣列,然后回圈輸出它的值,如下圖1-5
image.png
圖1-4 終端執行

1.4.5 Process.getCurrentThreadId()

Process.getCurrentThreadId():獲取此執行緒的作業系統特定 ID 作為數字

1.5 Module物件

3.4章節中Process.EnumererateModules()方法回傳了就是一個Module物件,咱們這里來詳細說說Module物件,先來瞧瞧它都有哪些屬性,

1.5.1 Module物件的屬性

屬性 含義
name 模塊名稱
base 模塊地址,其變數型別為NativePointer
size 大小
path 完整檔案系統路徑

除了屬性我們再來看看它有什么方法,

1.5.2 Module物件的API

API 含義
Module.load() 加載指定so檔案,回傳一個Module物件
enumerateImports() 列舉所有Import庫函式,回傳Module陣列物件
enumerateExports() 列舉所有Export庫函式,回傳Module陣列物件
enumerateSymbols() 列舉所有Symbol庫函式,回傳Module陣列物件
Module.findExportByName(exportName)、Module.getExportByName(exportName) 尋找指定so中export庫中的函式地址
Module.findBaseAddress(name)、Module.getBaseAddress(name) 回傳so的基地址

1.5.3 Module.load()

frida-12-5版本中更新了該API,主要用于加載指定so檔案,回傳一個Module物件,
使用代碼示例如下:

function frida_Module() {
    Java.perform(function () {
         //引數為so的名稱 回傳一個Module物件
         const hooks = Module.load('libhello.so');
         //輸出
         console.log("模塊名稱:",hooks.name);
         console.log("模塊地址:",hooks.base);
         console.log("大小:",hooks.size);
         console.log("檔案系統路徑",hooks.path);
    });
}
setImmediate(frida_Module,0);
輸出如下:
模塊名稱: libhello.so
模塊地址: 0xdf2d3000
大小: 24576
檔案系統路徑 /data/app/com.roysue.roysueapplication-7adQZoYIyp5t3G5Ef5wevQ==/lib/arm/libhello.so

1.5.4 Process.EnumererateModules()

咱們這一小章節就來使用Module物件,把上章的Process.EnumererateModules()物件輸出給它補全了,代碼如下,

function frida_Module() {
    Java.perform(function () {
        var process_Obj_Module_Arr = Process.enumerateModules();
        for(var i = 0; i < process_Obj_Module_Arr.length; i++) {
            if(process_Obj_Module_Arr[i].path.indexOf("hello")!=-1)
            {
                console.log("模塊名稱:",process_Obj_Module_Arr[i].name);
                console.log("模塊地址:",process_Obj_Module_Arr[i].base);
                console.log("大小:",process_Obj_Module_Arr[i].size);
                console.log("檔案系統路徑",process_Obj_Module_Arr[i].path);
            }
         }
    });
}
setImmediate(frida_Module,0);
輸出如下:
模塊名稱: libhello.so
模塊地址: 0xdf2d3000
大小: 24576
檔案系統路徑 /data/app/com.roysue.roysueapplication-7adQZoYIyp5t3G5Ef5wevQ==/lib/arm/libhello.so

這邊如果去除判斷的話會列印所有加載的so的資訊,這里我們就知道了哪些方法回傳了Module物件了,然后我們再繼續深入學習Module物件自帶的API

1.5.5 enumerateImports()

該API會列舉模塊中所有中的所有Import函式,示例代碼如下,

function frida_Module() {
    Java.perform(function () {
        const hooks = Module.load('libhello.so');
        var Imports = hooks.enumerateImports();
        for(var i = 0; i < Imports.length; i++) {
            //函式型別
            console.log("type:",Imports[i].type);
            //函式名稱
            console.log("name:",Imports[i].name);
            //屬于的模塊
            console.log("module:",Imports[i].module);
            //函式地址
            console.log("address:",Imports[i].address);
         }
    });
}
setImmediate(frida_Module,0);
輸出如下:
[Google Pixel::com.roysue.roysueapplication]-> type: function
name: __cxa_atexit
module: /system/lib/libc.so
address: 0xf58f4521
type: function
name: __cxa_finalize
module: /system/lib/libc.so
address: 0xf58f462d                                                                                                                                           
type: function
name: __stack_chk_fail
module: /system/lib/libc.so
address: 0xf58e2681
...

1.5.6 enumerateExports()

該API會列舉模塊中所有中的所有Export函式,示例代碼如下,

function frida_Module() {
    Java.perform(function () {
        const hooks = Module.load('libhello.so');
        var Exports = hooks.enumerateExports();
        for(var i = 0; i < Exports.length; i++) {
            //函式型別
            console.log("type:",Exports[i].type);
            //函式名稱
            console.log("name:",Exports[i].name);
            //函式地址
            console.log("address:",Exports[i].address);
         }
    });
}
setImmediate(frida_Module,0);
輸出如下:
[Google Pixel::com.roysue.roysueapplication]-> type: function
name: Java_com_roysue_roysueapplication_hellojni_getSum
address: 0xdf2d411b
type: function
name: unw_save_vfp_as_X
address: 0xdf2d4c43
type: function
address: 0xdf2d4209
type: function
...

1.5.7 enumerateSymbols()

代碼示例如下,

function frida_Module() {
    Java.perform(function () {
        const hooks = Module.load('libc.so');
        var Symbol = hooks.enumerateSymbols();
        for(var i = 0; i < Symbol.length; i++) {
            console.log("isGlobal:",Symbol[i].isGlobal);
            console.log("type:",Symbol[i].type);
            console.log("section:",JSON.stringify(Symbol[i].section));
            console.log("name:",Symbol[i].name);
            console.log("address:",Symbol[i].address);
         }
    });
}
setImmediate(frida_Module,0);
輸出如下:
isGlobal: true
type: function
section: {"id":"13.text","protection":"r-x"}
name: _Unwind_GetRegionStart
address: 0xf591c798
isGlobal: true
type: function
section: {"id":"13.text","protection":"r-x"}
name: _Unwind_GetTextRelBase
address: 0xf591c7cc
...

1.5.8 Module.findExportByName(exportName), Module.getExportByName(exportName)

回傳so檔案中Export函式庫中函式名稱為exportName函式的絕對地址,
代碼示例如下,

function frida_Module() {
    Java.perform(function () {
        Module.getExportByName('libhello.so', 'c_getStr')
        console.log("Java_com_roysue_roysueapplication_hellojni_getStr address:",Module.findExportByName('libhello.so', 'Java_com_roysue_roysueapplication_hellojni_getStr'));
        console.log("Java_com_roysue_roysueapplication_hellojni_getStr address:",Module.getExportByName('libhello.so', 'Java_com_roysue_roysueapplication_hellojni_getStr'));
    });
}
setImmediate(frida_Module,0);
輸出如下:
Java_com_roysue_roysueapplication_hellojni_getStr address: 0xdf2d413d
Java_com_roysue_roysueapplication_hellojni_getStr address: 0xdf2d413d

1.5.9 Module.findBaseAddress(name)、Module.getBaseAddress(name)

回傳name模塊的基地址,
代碼示例如下,

function frida_Module() {
    Java.perform(function () {
        var name = "libhello.so";
        console.log("so address:",Module.findBaseAddress(name));
        console.log("so address:",Module.getBaseAddress(name));
    });
}
setImmediate(frida_Module,0);
輸出如下:
so address: 0xdf2d3000
so address: 0xdf2d3000

1.6 Memory物件

Memory的一些API通常是對記憶體處理,譬如Memory.copy()復制記憶體,又如writeByteArray寫入位元組到指定記憶體中,那我們這章中就是學習使用Memory API向記憶體中寫入資料、讀取資料,

1.6.1 Memory.scan搜索記憶體資料

其主要功能是搜索記憶體中以address地址開始,搜索長度為size,需要搜是條件是pattern,callbacks搜索之后的回呼函式;此函式相當于搜索記憶體的功能,
我們來直接看例子,然后結合例子講解,如下圖1-5

圖1-5 IDA中so檔案某處資料
如果我想搜索在記憶體中112A地址的起始資料要怎么做,代碼示例如下,

function frida_Memory() {
    Java.perform(function () {
        //先獲取so的module物件
        var module = Process.findModuleByName("libhello.so"); 
        //??是通配符
        var pattern = "03 49 ?? 50 20 44";
        //基址
        console.log("base:"+module.base)
        //從so的基址開始搜索,搜索大小為so檔案的大小,搜指定條件03 49 ?? 50 20 44的資料
        var res = Memory.scan(module.base, module.size, pattern, {
            onMatch: function(address, size){
                //搜索成功
                console.log('搜索到 ' +pattern +" 地址是:"+ address.toString());  
            }, 
            one rror: function(reason){
                //搜索失敗
                console.log('搜索失敗');
            },
            onComplete: function()
            {
                //搜索完畢
                console.log("搜索完畢")
            }
          });
    });
}
setImmediate(frida_Memory,0);

先來看看回呼函式的含義,onMatch:function(address,size):使用包含作為NativePointer的實體地址的address和指定大小為數字的size呼叫,此函式可能會回傳字串STOP以提前取消記憶體掃描,onError:Function(Reason):當掃描時出現記憶體訪問錯誤時使用原因呼叫,onComplete:function():當記憶體范圍已完全掃描時呼叫,
我們來來說上面這段代碼做了什么事情:搜索libhello.so檔案在記憶體中的資料,搜索以pattern條件的在記憶體中能匹配的資料,搜索到之后根據回呼函式回傳資料,
我們來看看執行之后的效果圖1-6
image.png
圖1-6 終端執行
我們要如何驗證搜索到底是不是圖1-5112A地址,其實很簡單,so的基址是0xdf2d3000,而搜到的地址是0xdf2d412a,我們只要df2d412a-df2d3000=112A,就是說我們已經搜索到了!

1.6.2 搜索記憶體資料Memory.scanSync

功能與Memory.scan一樣,只不過它是回傳多個匹配到條件的資料,
代碼示例如下,

function frida_Memory() {
    Java.perform(function () {
        var module = Process.findModuleByName("libhello.so"); 
        var pattern = "03 49 ?? 50 20 44";
        var scanSync = Memory.scanSync(module.base, module.size, pattern);
        console.log("scanSync:"+JSON.stringify(scanSync));
    });
}
setImmediate(frida_Memory,0);
輸出如下,可以看到地址搜索出來是一樣的
scanSync:[{"address":"0xdf2d412a","size":6}]

1.6.3 記憶體分配Memory.alloc

在目標行程中的堆上申請size大小的記憶體,并且會按照Process.pageSize對齊,回傳一個NativePointer,并且申請的記憶體如果在JavaScript里面沒有對這個記憶體的使用的時候會自動釋放的,也就是說,如果你不想要這個記憶體被釋放,你需要自己保存一份對這個記憶體塊的參考,
使用案例如下

function frida_Memory() {
    Java.perform(function () {
        const r = Memory.alloc(10);
        console.log(hexdump(r, {
            offset: 0,
            length: 10,
            header: true,
            ansi: false
        }));
    });
}
setImmediate(frida_Memory,0);

以上代碼在目標行程中申請了10位元組的空間<br>可以看到在`0xdfe4cd40`處申請了`10`個位元組記憶體空間
也可以使用:
Memory.allocUtf8String(str) 分配utf字串
Memory.allocUtf16String 分配utf16字串
Memory.allocAnsiString 分配ansi字串

1.6.4 記憶體復制Memory.copy

如同c api memcp一樣呼叫,使用案例如下,

function frida_Memory() {
    Java.perform(function () {
        //獲取so模塊的Module物件
        var module = Process.findModuleByName("libhello.so"); 
        //條件
        var pattern = "03 49 ?? 50 20 44";
        //搜字串 只是為了將so的記憶體資料復制出來 方便演示~
        var scanSync = Memory.scanSync(module.base, module.size, pattern);
        //申請一個記憶體空間大小為10個位元組
        const r = Memory.alloc(10);
        //復制以module.base地址開始的10個位元組 那肯定會是7F 45 4C 46...因為一個ELF檔案的Magic屬性如此,
        Memory.copy(r,module.base,10);
        console.log(hexdump(r, {
            offset: 0,
            length: 10,
            header: true,
            ansi: false
        }));
    });
}
setImmediate(frida_Memory,0);
輸出如下,
           0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
e8142070  7f 45 4c 46 01 01 01 00 00 00                    .ELF......

module.base中復制10個位元組的記憶體到新年申請的r

1.6.6 寫入記憶體Memory.writeByteArray

將位元組陣列寫入一個指定記憶體,代碼示例如下:

function frida_Memory() {     
    Java.perform(function () {
        //定義需要寫入的位元組陣列 這個位元組陣列是字串"roysue"的十六進制
        var arr = [ 0x72, 0x6F, 0x79, 0x73, 0x75, 0x65];
        //申請一個新的記憶體空間 回傳指標 大小是arr.length
        const r = Memory.alloc(arr.length);
        //將arr陣列寫入R地址中
        Memory.writeByteArray(r,arr);
        //輸出
        console.log(hexdump(r, {
            offset: 0,
            length: arr.length,
            header: true,
            ansi: false
        }));  
    });
}
setImmediate(frida_Memory,0);
輸出如下,
           0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
00000000  72 6f 79 73 75 65                                roysue

1.6.7 讀取記憶體Memory.readByteArray

將一個指定地址的資料,代碼示例如下:

function frida_Memory() {     
    Java.perform(function () {
        //定義需要寫入的位元組陣列 這個位元組陣列是字串"roysue"的十六進制
        var arr = [ 0x72, 0x6F, 0x79, 0x73, 0x75, 0x65];
        //申請一個新的記憶體空間 回傳指標 大小是arr.length
        const r = Memory.alloc(arr.length);
        //將arr陣列寫入R地址中
        Memory.writeByteArray(r,arr);
        //讀取r指標,長度是arr.length 也就是會列印上面一樣的值
        var buffer = Memory.readByteArray(r, arr.length);
        //輸出
        console.log("Memory.readByteArray:");
        console.log(hexdump(buffer, {
            offset: 0,
            length: arr.length,
            header: true,
            ansi: false
        }));
      });  
    });
}
setImmediate(frida_Memory,0);
輸出如下,
[Google Pixel::com.roysue.roysueapplication]-> Memory.readByteArray:
           0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
00000000  72 6f 79 73 75 65                                roysue

結語

在這篇中我們學會了在FRIDACLI中如何輸出想要輸出格式,也學會如何宣告變數,一步步的學習,在逐步的學習的程序,總是會遇到不同的問題,歌曲<奇跡再現>我相信你一定聽過吧~,新的風暴已經出現,怎么能夠停止不前..遇到問題不要怕,總會解決的,

短視頻、直播資料實時采集介面,請查看檔案: TiToData


免責宣告:本檔案僅供學習與參考,請勿用于非法用途!否則一切后果自負,

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

標籤:大數據

上一篇:求教 將兩個無關聯的表內內容查詢到一個表內

下一篇:知識分享:程式員應該會的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