Frida API進階

2020-09-05 無情劍客Burning

F在這裡對其中的一部分API進行了介紹,這篇文章繼續介紹後面的內容。

通過這部分的介紹,可以發現通過Frida操縱內存、查看模塊等信息是如此的簡單。操作內存,最重要的自然就是打補丁了,邪惡的微笑。

@[toc]

Module對象

Module.load(path): loads the specified module from the filesystem path and returns a Module object. Throws an exception if the specified module cannot be loaded. 常用的API可以參考下面的代碼,注釋寫的很清楚:

Process.EnumererateModules()

Enumerates modules loaded right now, returning an array of Module objects.

//枚舉當前加載的模塊 var process_Obj_Module_Arr = Process.enumerateModules();for(var i = 0; i < process_Obj_Module_Arr.length; i++) { //包含&34;字符串的 if(process_Obj_Module_Arr[i].path.indexOf(&34;)!=-1) { console.log(&34;,process_Obj_Module_Arr[i].name); console.log(&34;,process_Obj_Module_Arr[i].base); console.log(&34;,process_Obj_Module_Arr[i].size); console.log(&34;,process_Obj_Module_Arr[i].path); }}

enumerateImports(導入表)

Enumerates imports of module, returning an array of objects containing the following properties:

  • type: string specifying either function or variable
  • name: import name as a string
  • module: module name as a string
  • address: absolute address as a NativePointer
  • slot: memory location where the import is stored, as a NativePointer

//枚舉模塊中所有中的所有導入表(Import)函數 function frida_Module_import() { Java.perform(function () { const hooks = Module.load(&39;); var Imports = hooks.enumerateImports(); for(var i = 0; i < Imports.length; i++) { //函數類型 console.log(&34;,Imports[i].type); //函數名稱 console.log(&34;,Imports[i].name); //屬於的模塊 console.log(&34;,Imports[i].module); //函數地址 console.log(&34;,Imports[i].address); } });}setImmediate(frida_Module_import,0);

enumerateExports(導出表)

Enumerates exports of module, returning an array of objects containing the following properties:

  • type: string specifying either function or variable
  • name: export name as a string
  • address: absolute address as a NativePointer

var Exports = hooks.enumerateExports();for(var i = 0; i < Exports.length; i++) { //函數類型 console.log(&34;,Exports[i].type); //函數名稱 console.log(&34;,Exports[i].name); //函數地址 console.log(&34;,Exports[i].address); }

註:導出表和導入表後續文章會專門進行介紹。簡單來說,導入表是這個庫依賴的函數表,而導出表是這個庫對外提供的函數表。

enumerateSymbols(符號表)

Enumerates symbols of module, returning an array of objects containing the following properties。

  • isGlobal: boolean specifying whether symbol is globally visible
  • type: string specifying one of:unknownsectionundefined (Mach-O)absolute (Mach-O)prebound-undefined (Mach-O)indirect (Mach-O)object (ELF)function (ELF)file (ELF)common (ELF)tls (ELF)
  • section: if present, is an object containing:id: string containing section index, segment name (if applicable) and section name – same format as r2’s section IDsprotection: protection like in Process.enumerateRanges()
  • name: symbol name as a string
  • address: absolute address as a NativePointer
  • size: if present, a number specifying the symbol’s size in bytes

function frida_Module_symbol() { Java.perform(function () { const hooks = Module.load(&39;); var Symbol = hooks.enumerateSymbols(); for(var i = 0; i < Symbol.length; i++) { console.log(&34;,Symbol[i].isGlobal); console.log(&34;,Symbol[i].type); console.log(&34;,JSON.stringify(Symbol[i].section)); console.log(&34;,Symbol[i].name); console.log(&34;,Symbol[i].address); } });}setImmediate(frida_Module_symbol,0);

運行結果如下:

獲取export的絕對地址

返回so文件中Export函數庫中函數名稱為exportName函數的絕對地址。

Module.findExportByName(moduleName|null, exportName), Module.getExportByName(moduleName|null, exportName): returns the absolute address of the export named exportName in moduleName. If the module isn’t known you may pass null instead of its name, but this can be a costly search and should be avoided. In the event that no such module or export could be found, the find-prefixed function returns null whilst the get-prefixed function throws an exception.

function frida_Module_address() { Java.perform(function () { console.log(&34;,Module.getExportByName(&39;, &39;)); console.log(&34;,Module.findExportByName(&39;, &39;)); });}setImmediate(frida_Module_address,0);

運行結果:

Memory對象

Memory的一些API通常是對內存處理,譬如Memory.copy()複製內存,又如writeByteArray寫入字節到指定內存中。

Memory.scan

其主要功能是搜索內存中以address地址開始,搜索長度為size,需要搜是條件是pattern,callbacks搜索之後的回調函數;此函數相當於搜索內存的功能。

Memory.scan(address, size, pattern, callbacks): scan memory for occurences of pattern in the memory range given by address and size.

  • pattern must be of the form 「13 37 ?? ff」 to match 0x13 followed by 0x37 followed by any byte followed by 0xff. For more advanced matching it is also possible to specify an r2-style mask. The mask is bitwise AND-ed against both the needle and the haystack. To specify the mask append a : character after the needle, followed by the mask using the same syntax. For example: 「13 37 13 37 : 1f ff ff f1」. For convenience it is also possible to specify nibble-level wildcards, like 「?3 37 13 ?7」, which gets translated into masks behind the scenes.
  • callbacks is an object with:onMatch: function (address, size): called with address containing the address of the occurence as a NativePointer and size specifying the size as a number.This function may return the string stop to cancel the memory scanning early.onError: function (reason): called with reason when there was a memory access error while scanningonComplete: function (): called when the memory range has been fully scanned

本文選取的的是領跑娛樂.apk,為一個賭博類的APP,後續會專門分析這個app。

對apk的解包在這裡進行了介紹,通過Radare2查看libgame.so這個庫的函數信息,如下:

匹配規則對應的是opcode,下面的代碼將pattern設置為&34;,正好匹配第一行和第二行的opcode。

var process_Obj_Module_Arr = Process.enumerateModules();for(var i = 0; i < process_Obj_Module_Arr.length; i++) { //包含&34;字符串的 if(process_Obj_Module_Arr[i].path.indexOf(&34;)!=-1) { console.log(&34;,process_Obj_Module_Arr[i].name); console.log(&34;,process_Obj_Module_Arr[i].base); console.log(&34;,process_Obj_Module_Arr[i].size); console.log(&34;,process_Obj_Module_Arr[i].path); // Print its properties: console.log(JSON.stringify(process_Obj_Module_Arr[i])); // Dump it from its base address: console.log(hexdump(process_Obj_Module_Arr[i].base)); // The pattern that you are interested in: var pattern = &39;; Memory.scan(process_Obj_Module_Arr[i].base, process_Obj_Module_Arr[i].size, pattern, { onMatch: function (address, size) { console.log(&39;, address, &39;, size); // Optionally stop scanning early: return &39;; }, onComplete: function () { console.log(&39;); } }); } }

最終的運行結果:

很容易可以計算出偏移:0xc429f3bc - 0xc4041000 = 0x25e3bc

同步搜索內存數據Memory.scanSync

Memory.scanSync(address, size, pattern): synchronous version of scan() that returns an array of objects containing the following properties:

  • address: absolute address as a NativePointer.
  • size: size in bytes

console.log(JSON.stringify(Memory.scanSync(process_Obj_Module_Arr[i].base,process_Obj_Module_Arr[i].size,pattern)));

如果符合條件的信息比較多,容易導致卡死,慎用。

內存分配Memory.alloc

在目標進程中的堆上申請size大小的內存,並且會按照Process.pageSize對齊,返回一個NativePointer,並且申請的內存如果在JavaScript裡面沒有對這個內存的使用的時候會自動釋放的。也就是說,如果你不想要這個內存被釋放,你需要自己保存一份對這個內存塊的引用。

Memory.alloc(size): allocate size bytes of memory on the heap, or, if size is a multiple of Process.pageSize, one or more raw memory pages managed by the OS. The returned value is a NativePointer and the underlying memory will be released when all JavaScript handles to it are gone. This means you need to keep a reference to it while the pointer is being used by code outside the JavaScript runtime.

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

以上代碼在目標進程中申請了10位元組的空間

也可以使用: Memory.allocUtf8String(str) 分配utf字符串 Memory.allocUtf16String 分配utf16字符串 Memory.allocAnsiString 分配ansi字符串

內存複製Memory.copy

類似與c語言中的memcpy

const r = Memory.alloc(10);//複製以module.base地址開始的10個字節 那肯定會是7F 45 4C 46...因為一個ELF文件的Magic屬性如此。Memory.copy(r,process_Obj_Module_Arr[i].base,10);console.log(hexdump(r, { offset: 0, length: 10, header: true, ansi: false}));

寫入內存Memory.writeByteArray

將字節數組寫入一個指定內存,代碼示例如下:

var arr = [ 0x62, 0x20, 0x75,0x20, 0x72,0x20,0x6E,0x20,0x69,0x20,0x6E,0x20,0x67]; //申請一個新的內存空間 返回指針 大小是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 }));

結果如下:

讀取內存Memory.readByteArray

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

var buffer = Memory.readByteArray(r, arr.length); //輸出 console.log(&34;); console.log(hexdump(buffer, { offset: 0, length: arr.length, header: true, ansi: false }));

結果同上。

公眾號

更多Frida相關內容,歡迎關注我的公眾號:無情劍客


相關焦點

  • Frida進階-API
    同時簡單介紹下HOOK 系統函數的利器frida-trace。內存,內存還是內存。>function frida_Java$new(Java.array(&39;, [ 0x48, 0x65, 0x69 ])); });} setImmediate(frida_Java,0);部分運行結果如下:
  • Frida API的"樂器"
    運行上面的程序(在Win10系統下),使用腳本 frida-lObjC.api: an object mapping function names to NativeFunction instances for direct access to a big portion of
  • Frida之API使用進階
    運行 frida-U-l hello.js com.lingpao.lpcf622b–debug--runtime
  • Frida API之網絡
    在Frida API進階-文件 對文件描述符、輸入輸出流進行了介紹。本篇文章集於此介紹Frida中網絡相關的API。SocketSocket.listen([options]): open a TCP or UNIX listening socket.
  • Frida常用API
    instance.getName()); // bluetoothDeviceInfo(instance); }, onComplete: function() { console.log(&34;);} }); }); });通過下面的命令運行程序frida
  • Frida腳本教程
    Hello worldHello world經典的入門程序,frida版本的來一個。frida -U -l hello.js com.android.bluetoothfrida -U -l hello.js com.android.bluetooth
  • 當Frida來「敲」門
    0x2 fridafrida是平臺原生app的Greasemonkey,說的專業一點,就是一種動態插樁工具,可以插入一些代碼到原生app的內存空間去,(動態地監視和修改其行為),這些原生平臺可以是Win、Mac、Linux、Android
  • 詳解Hook框架frida,讓你在逆向工作中效率成倍提升!
    (2) frida CLI是安裝的frida的其中一個工具,也是最常用的一個工具。2.frida serverfrida-server需要我們單獨下載,在 frida項目的github上可以直接下載對應系統已經編譯好的frida server
  • Frida全平臺使用
    pip install frida-tools網上狠毒文章說使用 pip install frida 和 pip install frida-tools 進行安裝,但是現在一條命名就夠了。如果不嫌麻煩,也可以通過源碼進行安裝。
  • 安卓安全從零到一: FRIDA hook Native基礎
    的api, 不要直接使用java的            // https://github.com/frida/frida-java-bridge/blob/062999b618451e5ac414d08d4f52bec05bd6adf6/lib/env.js            console.log('args[2]:', Java.vm.getEnv().getStringUtfChars
  • frida學習筆記3 之hook so中的方法
    hook so 常用工具SubstrateCydia-需rootfrida--需rootVA系列-非root(VA、VXP、SandVXposed)frida方式hook材料準備heibaobao.apk
  • Frida進階內存漫遊
    關於Activity的聲明周期在Frida API進階-文件有介紹。
  • Frida使用之資料庫
    下面的代碼查詢buglydb資料庫信息:function frida_Java() { Java.perform(function () { var db, smt, row, id, tm; db = SqliteDatabase.open
  • Frida之文件操作
    import frida,sysdef on_message(message, data): if message[&39;] == &39;: print(&34;.format(message[&39;])) else: print(message)passsession = frida.get_usb_device
  • Textobot-TB插件進程級API詳解&基礎篇完結
    如果是通過frida-gatget模塊注入又需要修改目標App,所以不管用哪種方式要持久化的執行JavaScript,在官方提供的接口裡面都沒有現成的。針對這個缺陷,Textobot用TB插件的模式彌補了Frida沒有持久化的問題。同時,為了方便編寫實用的TB插件,Textobot還導出了一些輔助性的C API。
  • 安卓逆向——Frida hook java層
    各位愛好安卓逆向的大佬們早上好,今天呢小弟不才在這裡拙劣的給大家講解一下咱們frida hook
  • C#進階之學習設計微服務:api認證
    2,配置網關服務Ocelot使用ocelot認證時,需要配置Ocelot.json,對相應的路由添加節點{"DownstreamPathTemplate": "/api/{url}","DownstreamScheme": "http
  • 常用api大全
    Android中文版api手冊地址:http://www.matools.com/api/androidAnt最新版api手冊地址:http://www.matools.com/api/antASM字節碼操作api手冊地址:http://www.matools.com/api/asmAxis2最新版
  • Rocket-API 版本更新,API 敏捷開發框架
    修改欄位,以便有更好的兼容性    api_info(group) 為 api_info(group_name)        api_info(comment) 為 api_info(name)        api_info_history(group) 為 api_info_history(group_name)        api_info_history(
  • 小程序的api是什麼
    其實api並不專屬於小程序,任何程式語言或程序形態都有相對應的api。而我們今天談的小程序api,是微信小程序團隊為了方便開發人員製作開發小程序,而將一些常用的,或者底層的方法進行封裝,並提供給開發人員使用的程序接口。微信小程序是屬於相對封閉的一個環境,獲取或通知外部的程序,或者使用小程序內部的功能,都必須要經過小程序的api調用來實現。