F在這裡對其中的一部分API進行了介紹,這篇文章繼續介紹後面的內容。
通過這部分的介紹,可以發現通過Frida操縱內存、查看模塊等信息是如此的簡單。操作內存,最重要的自然就是打補丁了,邪惡的微笑。
@[toc]
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可以參考下面的代碼,注釋寫的很清楚:
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); }}
Enumerates imports of module, returning an array of objects containing the following properties:
//枚舉模塊中所有中的所有導入表(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);
Enumerates exports of module, returning an array of objects containing the following properties:
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); }
註:導出表和導入表後續文章會專門進行介紹。簡單來說,導入表是這個庫依賴的函數表,而導出表是這個庫對外提供的函數表。
Enumerates symbols of module, returning an array of objects containing the following properties。
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);
運行結果如下:
返回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的一些API通常是對內存處理,譬如Memory.copy()複製內存,又如writeByteArray寫入字節到指定內存中。
其主要功能是搜索內存中以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.
本文選取的的是領跑娛樂.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(address, size, pattern): synchronous version of scan() that returns an array of objects containing the following properties:
console.log(JSON.stringify(Memory.scanSync(process_Obj_Module_Arr[i].base,process_Obj_Module_Arr[i].size,pattern)));
如果符合條件的信息比較多,容易導致卡死,慎用。
在目標進程中的堆上申請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字符串
類似與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}));
將字節數組寫入一個指定內存,代碼示例如下:
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 }));
結果如下:
將一個指定地址的數據,代碼示例如下:
var buffer = Memory.readByteArray(r, arr.length); //輸出 console.log(&34;); console.log(hexdump(buffer, { offset: 0, length: arr.length, header: true, ansi: false }));
結果同上。
更多Frida相關內容,歡迎關注我的公眾號:無情劍客