Frida官方手冊 - JavaScript API(篇一)
freakish發表於2017-10-22
JavaScript API
目錄
- Global
- console
- rpc
- Frida
- Process
- Module
- ModuleMap
- Memory
- MemoryAccessMonitor
- Thread
- Int64
- UInt64
- NativePointer
- NativeFunction
- NativeCallback
- SystemFunction
- Socket
- SocketListener
- SocketConnection
- IOStream
- InputStream
- OutputStream
- UnixInputStream
- UnixOutputStream
- Win32InputStream
- Win32OutputStream
- File
- SqliteDatabase
- SqliteStatement
- Interceptor
- Stalker
- ApiResolver
- DebugSymbol
- Instruction
- ObjC
- Java
- WeakRef
- X86Writer
- X86Relocator
- X86_enum_types
- ArmWriter
- ArmRelocation
- ThumbWriter
- ThumbRelocator
- ARM_enum_types
- Arm64Writer
- Arm64Relocator
- AArch64_enum_types
- MipsWriter
- MipsRelocator
- Mips_enum_types
Global
- hexdump(target[, options]): 把一個 ArrayBuffer 或者 NativePointer 的target變數,附加一些 options 屬性,按照指定格式進行輸出,比如:
- int64(v): new Int64(v) 的縮寫格式
- uint64(v): new UInt64(v) 的縮寫格式
- ptr(s): new NativePointer(s) 的縮寫格式
- NULL ptr(“0”) 的縮寫格式
- recv([type, ]callback): 註冊一個回撥,當下次有訊息到來的時候會收到回撥訊息,可選引數 type 相當於一個過濾器,表示只接收這種型別的訊息。需要注意的一點是, 這個訊息回撥是一次性的, 收到一個訊息之後,如果需要繼續接收訊息,那就需要重新呼叫一個 recv
- send(message[, data]): 從目標程式中往主控端發 message(必須是可以序列換成Json的),如果你還有二進位制資料需要附帶傳送(比如使用 Memory.readByteArray 複製的記憶體資料),就把這個附加資料填入 data 引數,但是有個要求,就是 data 引數必須是一個 ArrayBuffer 或者是一個整形陣列(數值是 0-255)
- setTimeout(fn, delay): 在延遲 delay 毫秒之後,呼叫 fn,這個呼叫會返回一個ID,這個ID可以傳遞給 clearTimeout 用來進行呼叫取消。
- clearTimeout(id): 取消透過 setTimeout 發起的延遲呼叫
- setInterval(fn, delay): 每隔 delay 毫秒呼叫一次 fn,返回一個ID,這個ID可以傳給 clearInterval 進行呼叫取消。
- clearInterval(id): 取消透過 setInterval 發起的呼叫
console
- console.log(line), console.warn(line), console.error(line): 向標準輸入輸出介面寫入 line 字串。 比如:使用 Frida-Python 的時候就輸出到 stdout 或者 stderr,使用 frida-qml 的時候則輸出到 qDebug,如果輸出的是一個ArrayBuffer,會以預設引數自動呼叫 hexdump 進行格式化輸出。
rpc
- rpc.exports: 可以在你的程式中匯出一些 RPC-Style API函式,Key指定匯出的名稱,Value指定匯出的函式,函式可以直接返回一個值,也可以是非同步方式以 Promise 的方式返回,舉個例子:
- 對於Python主控端可以使用下面這樣的指令碼使用匯出的函式:
- 在上面這個例子裡面,我們使用 script.on(‘message’, on_message) 來監控任何來自目標程式的訊息,訊息監控可以來自 script 和 session 兩個方面,比如,如果你想要監控目標程式的退出,可以使用下面這個語句 session.on(‘detached’, my_function)
Frida
- Frida.version: 包含當前Frida的版本資訊
Process
- Process.arch: CPU架構資訊,取值範圍:ia32、x64、arm、arm64
- Process.platform: 平臺資訊,取值範圍:windows、darwin、linux、qnx
- Process.pageSize: 虛擬記憶體頁面大小,主要用來輔助增加指令碼可移植性
- Process.pointerSize: 指標佔用的記憶體大小,主要用來輔助增加指令碼可移植性
- Process.codeSigningPolicy: 取值範圍是 optional 或者 required,後者表示Frida會盡力避免修改記憶體中的程式碼,並且不會執行未簽名的程式碼。預設值是 optional,除非是在 Gadget 模式下透過配置檔案來使用 required,透過這個屬性可以確定 Interceptor API 是否有限制,確定程式碼修改或者執行未簽名程式碼是否安全。(譯者注:這個目前沒有實驗清楚,可以參考原文)
- Process.isDebuggerAttached(): 確定當前是否有偵錯程式附加
- Process.getCurrentThreadId(): 獲取當前執行緒ID
- Process.enumerateThreads(callbacks): 列舉所有執行緒,每次列舉到一個執行緒就執行回撥類callbacks:
- onMatch: function(thread): 當列舉到一個執行緒的時候,就呼叫這個函式,其中thread引數包含 :
- id,執行緒ID
- state,執行緒狀態,取之範圍是 running, stopped, waiting, uninterruptible, halted
- context, 包含 pc, sp,分別代表 EIP/RIP/PC 和 ESP/RSP/SP,分別對應於 ia32/x64/arm平臺,其他的暫存器也都有,比如 eax, rax, r0, x0 等。
- 函式可以直接返回 stop 來停止列舉。
- onComplete: function(): 當所有的執行緒列舉都完成的時候呼叫。
- onMatch: function(thread): 當列舉到一個執行緒的時候,就呼叫這個函式,其中thread引數包含 :
- Process.enumerateThreadSync(): enumerateThreads()的同步版本,返回執行緒物件陣列
- Process.findModuleByAddress(address), Process.getModuleByAddress(address), Process.findModuleByName(name), Process.getModuleByName(name): 根據地址或者名稱來查詢模組,如果找不到這樣的模組,find開頭的函式返回 null,get開頭的函式會丟擲異常。
- Process.enumerateModules(callbacks): 列舉已經載入的模組,列舉到模組之後呼叫回撥物件:
- onMatch: function(module): 列舉到一個模組的時候呼叫,module物件包含如下欄位:
- name, 模組名
- base, 基地址
- size,模組大小
- path,模組路徑
- 函式可以返回 stop 來停止列舉 。
- onComplete: function(): 當所有的模組列舉完成的時候呼叫。
- onMatch: function(module): 列舉到一個模組的時候呼叫,module物件包含如下欄位:
- Process.enumerateModulesSync(): enumerateModules() 函式的同步版本,返回模組物件陣列
- Process.findRangeByAddress(address), Process.getRangeByAddress(address): 返回一個記憶體塊物件, 如果在這個address找不到記憶體塊物件,那麼 findRangeByAddress() 返回 null 而 getRangeByAddress 則丟擲異常。
- Process.numerateRanges(protection | specifier, callbacks): 列舉指定 protection 型別的記憶體塊,以指定形式的字串給出:rwx,而 rw- 表示最少是可讀可寫,也可以用分類符,裡面包含 protection 這個Key,取值就是前面提到的rwx,還有一個 coalesce 這個Key,表示是否要把位置相鄰並且屬性相同的記憶體塊合併給出結果,列舉過程中回撥 callbacks 物件:
- onMatch: function(range): 每次列舉到一個記憶體塊都回撥回來,其中Range物件包含如下屬性:
- base:基地址
- size:記憶體塊大小
- protection:保護屬性
- file:(如果有的話)記憶體對映檔案:
4.1 path,檔案路徑
4.2 offset,檔案內偏移 - 如果要停止列舉過程,直接返回 stop 即可
- onComplete: function(): 所有記憶體塊列舉完成之後會回撥
- onMatch: function(range): 每次列舉到一個記憶體塊都回撥回來,其中Range物件包含如下屬性:
- Process.enumerateRangesSync(protection | specifier): enumerateRanges()函式的同步版本,返回記憶體塊陣列
- Process.enumerateMallocRanges(callbacks): 用於列舉在系統堆上申請的記憶體塊
- Process.enumerateMallocRangesSync(protection): Process.enumerateMallocRanges() 的同步版本
- Process.setExceptionHandler(callback): 在程式內安裝一個異常處理函式(Native Exception),回撥函式會在目標程式本身的異常處理函式之前呼叫 ,回撥函式只有一個引數 details,包含以下幾個屬性:
- type,取值為下列之一:
- abort
- access-violation
- guard-page
- illegal-instruction
- stack-overflow
- arithmetic
- breakpoint
- single-step
- system
- address,異常發生的地址,NativePointer
- memory,如果這個物件不為空,則會包含下面這些屬性:
- operation: 引發一場的操作型別,取值範圍是 read, write 或者 execute
- address: 操作發生異常的地址,NativePointer
- context,包含 pc 和 sp 的NativePointer,分別代表指令指標和堆疊指標
- nativeContext,基於作業系統定義的異常上下文資訊的NativePointer,在 context 裡面的資訊不夠用的時候,可以考慮用這個指標,但是一般不建議使用(譯者注:估計是考慮到可移植性或者穩定性)
- 捕獲到異常之後,怎麼使用就看你自己了,比如可以把異常資訊寫到日誌裡面,然後傳送個資訊給主控端,然後同步等待主控端的響應之後處理,或者直接修改異常資訊裡面包含的暫存器的值,嘗試恢復掉異常,繼續執行。如果你處理了異常資訊,那麼這個異常回撥裡面你要返回 true,Frida會把異常交給程式異常處理函式處理,如果到最後都沒人去處理這個異常,就直接結束目標程式。
- type,取值為下列之一:
Module
- Module.emuerateImports(name, callbacks): 列舉模組 name 的匯入表,列舉到一個匯入項的時候回撥callbacks, callbacks包含下面2個回撥:
- onMatch: function(imp): 列舉到一個匯入項到時候會被呼叫,imp包含如下的欄位:
- type,匯入項的型別, 取值範圍是 function或者variable
- name,匯入項的名稱
- module,模組名稱
- address,匯入項的絕對地址
- 以上所有的屬性欄位,只有 name 欄位是一定會有,剩餘的其他欄位不能保證都有,底層會盡量保證每個欄位都能給出資料,但是不能保證一定能拿到資料,onMatch函式可以返回字串 stop 表示要停止列舉。
- onComplete: function(): 當所有的匯入表項都列舉完成的時候會回撥
- onMatch: function(imp): 列舉到一個匯入項到時候會被呼叫,imp包含如下的欄位:
- Module.eumerateImportsSync(name): enumerateImports()的同步版本
- Module.emuerateExports(name, callbacks): 列舉指定模組 name 的匯出表項,結果用 callbacks 進行回撥:
- onMatch: function(exp): 其中 exp 代表列舉到的一個匯出項,包含如下幾個欄位:
- type,匯出項型別,取值範圍是 function或者variable
- name,匯出項名稱
- address,匯出項的絕對地址,NativePointer
- 函式返回 stop 的時候表示停止列舉過程
- onComplete: function(): 列舉完成回撥
- onMatch: function(exp): 其中 exp 代表列舉到的一個匯出項,包含如下幾個欄位:
- Module.enumerateExportsSync(): Module.enumerateExports()的同步版本
- Module.enumerateSymbols(name, callbacks): 列舉指定模組中包含的符號,列舉結果透過回撥進行通知:
- onMatch: function(sym): 其中 sym 包含下面幾個欄位:
- isGlobal,布林值,表示符號是否全域性可見
- type,符號的型別,取值是下面其中一種:
- unknown
- undefined
- absolute
- section
- prebound-undefined
- indirect
- section,如果這個欄位不為空的話,那這個欄位包含下面幾個屬性:
- id,小節序號,段名,節名
- protection,保護屬性型別, rwx這樣的屬性
- name,符號名稱
- address,符號的絕對地址,NativePointer
- 這個函式返回 stop 的時候,表示要結束列舉過程
- Module.enumerateSymbolsSync(name): Module.enumerateSymbols() 的同步版本
- onMatch: function(sym): 其中 sym 包含下面幾個欄位:
- Module.enumerateRanges(name, protection, callbacks): 功能基本等同於 Process.enumerateRanges(),只不過多了一個模組名限定了列舉的範圍
- Module.enumerateRangesSync(name, protection): Module.enumerateRanges() 的同步版本
- Module.findBaseAddress(name): 獲取指定模組的基地址
- Module.findExportByName(module | null, exp): 返回模組module 內的匯出項的絕對地址,如果模組名不確定,第一個引數傳入 null,這種情況下會增大查詢開銷,儘量不要使用。
ModuleMap
- new ModuleMap([filter]): 可以理解為記憶體模組快照,主要目的是可以作為一個模組速查表,比如你可以用這個快照來快速定位一個具體的地址是屬於哪個模組。建立ModuleMap的時候,就是對目標程式當前載入的模組的資訊作一個快照,後續想要更新這個快照資訊的時候,可以使用 update 進行更新。 這個 filter 引數是可選的,主要是用來過濾你關心的模組,可以用來縮小快照的範圍(注意:filter是過濾函式,不是字串引數),為了讓模組進入這個快照裡,過濾函式的返回值要設定為true,反之設為false,如果後續記憶體中的模組載入資訊更新了, 還會繼續呼叫這個filter函式。
- has(address): 檢查 address 這個地址是不是包含在ModuleMap裡面,返回bool值
- find(address), get(address): 返回 address 地址所指向的模組物件詳細資訊,如果不存在 find 返回null,get 直接會丟擲異常,具體的返回的物件的詳細資訊,可以參考 Process.enumerateModules()
- findName(address), getName(address), findPath(address), getPath(address): 功能跟 find(), get() 類似,但是隻返回 name 或者 path 欄位,可以省點開銷
- update(): 更新ModuleMap資訊,如果有模組載入或者解除安裝,最好呼叫一次,免得使用舊資料。
Memory
- Memory.scan(address, size, pattern, callbacks): 在 address 開始的地址,size 大小的記憶體範圍內以 pattern 這個模式進行匹配查詢,查詢到一個記憶體塊就回撥callbacks,各個引數詳細如下:
- pattern 比如使用13 37 ?? ff來匹配0x13開頭,然後跟著0x37,然後是任意位元組內容,接著是0xff這樣的記憶體塊
- callbacks 是掃描函式回撥物件:
- onMatch: function(address, size): 掃描到一個記憶體塊,起始地址是address,大小size的記憶體塊,返回 stop 表示停止掃描
- onError: function(reason): 掃描記憶體的時候出現記憶體訪問異常的時候回撥
- onComplete: function(): 記憶體掃描完畢的時候呼叫
- Memory.scanSync(address, size, pattern): 記憶體掃描 scan() 的同步版本
- Memory.alloc(size): 在目標程式中的堆上申請size大小的記憶體,並且會按照Process.pageSize對齊,返回一個NativePointer,並且申請的記憶體如果在JavaScript裡面沒有對這個記憶體的使用的時候會自動釋放的。也就是說,如果你不想要這個記憶體被釋放,你需要自己儲存一份對這個記憶體塊的引用。
- Memory.copy(dust, src, n): 就像是memcpy
- Memory.dup(address, size): 等價於 Memory.alloc()和Memory.copy()的組合。
- Memory.protect(address, size, protection): 更新address開始,size大小的記憶體塊的保護屬性,protection 的取值參考 Process.enumerateRanges(),比如:Memory.protect(ptr(“0x123”, 4096, ‘rw-‘));
- Memory.patchCode(address, size, apply): apply是一個回撥函式,這個函式是用來在 address 開始的地址和 size 大小的地方開始Patch的時候呼叫,回撥引數是一個NativePointer的可寫指標,需要在apply回撥函式里面要完成patch程式碼的寫入,注意,這個可寫的指標地址不一定和上面的address是同一個地址,因為在有的系統上是不允許直接寫入程式碼段的,需要先寫入到一個臨時的地方,然後在影射到響應程式碼段上,(比如 iOS上, 會引發程式丟失 CS_VALID 狀態),比如:
- 下面是接著是一些資料型別讀寫:
- Memory.readPointer(address)
- Memory.writePointer(address, ptr)
- Memory.readS8, Memory.readU8
- …
MemoryAccessMonitor
MemoryAccessMonitor.enable(ranges, callbacks): 監控一個或多個記憶體塊的訪問,在觸發到記憶體訪問的時候發出通知。ranges 要麼是一個單獨的記憶體塊,要麼是一個記憶體塊陣列,每個記憶體塊包含如下屬性:
- base: 觸發記憶體訪問的NativePointer地址
- size: 被觸發訪問的記憶體塊的大小
- callbacks: 回撥物件結構:
- onAccess: function(details): 發生訪問的時候同步呼叫這個函式,details物件包含如下屬性:
- operation: 觸發記憶體訪問的操作型別,取值範圍是 read, write 或者 execute
- from: 觸發記憶體訪問的指令地址,NativePointer
- address: 被訪問的記憶體地址
- rangeIndex: 被訪問的記憶體塊的索引,就是呼叫MemoryAccessMonitor.enable()的時候指定的記憶體塊序號
- pageIndex: 在被監控記憶體塊範圍內的頁面序號
- pagesCompleted: 到目前為止已經發生過記憶體訪問的頁面的個數(已經發生過記憶體訪問的頁面將不再進行監控)
- pagesTotal: 初始指定的需要監控的記憶體頁面總數
MemoryAccessMonitor.disable(): 停止監控頁面訪問操作
Thread
- Thread.backtrace([context, backtracer]): 抓取當前執行緒的呼叫堆疊,並以 NativePointer 指標陣列的形式返回。
- 如果你是在 Interceptor.onEnter或者Interceptor.onLeave 中呼叫這個函式的話,那就必須要把 this.context 作為引數傳入,這樣就能拿到更佳精準的堆疊呼叫資訊,如果省略這個引數不傳,那就意味著從當前堆疊的位置開始抓取,這樣的抓取效果可能不會很好,因為有不少V8引擎的棧幀的干擾。
- 第二個可選引數 backtracer,表示使用哪種型別的堆疊抓取演算法,目前的取值範圍是 Backtracer.FUZZY 和 Backtracer.ACCURATE,目前後者是預設模式。精確抓取模式下,如果如果程式是偵錯程式友好(比如是標準編譯器編譯的結果,沒有什麼反除錯技巧)或者有符號表的支援,抓取效果是最好的,而模糊抓取模式下,抓取器會在堆疊上嘗試抓取,並且會猜測裡面包含的返回地址,也就是說中間可能包含一些錯誤的資訊,但是這種模式基本能在任何二進位制程式裡面工作:
- Thread.sleep(delay): 執行緒暫停 delay 秒執行
下篇繼續
- 一篇文章寫太長發現瀏覽器容易崩潰,所以下篇繼續
相關文章
- Frida官方手冊 - JavaScript API(篇二)2017-10-24JavaScriptAPI
- Frida官方手冊 - JavaScript API(篇三)2017-11-03JavaScriptAPI
- Frida官方手冊 - 安裝Frida2017-10-19
- Frida官方手冊 - 在iOS上使用Frida2017-10-20iOS
- Frida官方手冊 - 函式Hook2017-10-19函式Hook
- Frida官方手冊 - 快速入門2017-10-18
- Frida官方手冊 - 基礎用法2017-10-19
- Frida官方手冊 - 在Android上使用Frida2017-10-21Android
- Frida官方手冊 - Android上示例一則2017-10-21Android
- iptables官方手冊整理薦2012-02-29
- WGCLOUD官方手冊 - 快速進行服務介面API的監測2022-12-27GCCloudAPI
- TypeScript 官方手冊翻譯計劃【一】:基礎2021-11-21TypeScript
- sql server 2012官方手冊之一2017-06-27SQLServer
- [原創] Frida操作手冊-Android環境準備2018-12-10Android
- 【譯】JavaScript 完整手冊2018-11-29JavaScript
- DOJO API 中文參考手冊2018-04-20API
- JavaScript物件參考手冊2018-08-11JavaScript物件
- TypeScript 官方手冊翻譯計劃【十三】:模組2021-12-16TypeScript
- TypeScript 官方手冊翻譯計劃【十二】:類2021-12-11TypeScript
- JavaScript正規表示式 手冊2019-10-10JavaScript
- JavaScript語言參考手冊2009-03-07JavaScript
- 2015阿里百川官方手冊2015-05-15阿里
- Java GUI入門手冊-AWT篇2021-05-12JavaGUI
- TypeScript 官方手冊翻譯計劃【五】:物件型別2021-11-28TypeScript物件型別
- ORACLE AMM 、ASMM 、自動記憶體管理(官方手冊)2018-06-27OracleASM記憶體
- 翻譯:SET Variable(已提交到MariaDB官方手冊)2018-03-22
- 翻譯:window function(已提交到MariaDB官方手冊)2018-04-24Function
- 翻譯:TRUNCATE TABLE(已提交到MariaDB官方手冊)2018-04-19
- 翻譯:INSERT(已提交到MariaDB官方手冊)2018-04-19
- 深入剖析Retrofit系列(一)來自官方的Retrofit開發手冊(中英互譯)2018-08-17
- 小程式 音訊API採坑完全手冊2018-05-11音訊API
- TypeScript 官方手冊翻譯計劃【二】:普通型別2021-11-27TypeScript型別
- 翻譯:delete語句(已提交到MariaDB官方手冊)2018-04-20delete
- 翻譯:update語句(已提交到MariaDB官方手冊)2018-04-19
- oracle create table官方手冊如何快速檢視學習方法2013-05-17Oracle
- Frida-跨平臺注入工具基礎篇2020-08-19
- oracle exadata資料庫一體機之產品家族之官方手冊彙集2017-10-31Oracle資料庫
- 易優獲取當前文件上一篇、下一篇內容-Eyoucms標籤手冊2024-08-15