2022Frida手冊二進(jìn)制工具包_第1頁
2022Frida手冊二進(jìn)制工具包_第2頁
2022Frida手冊二進(jìn)制工具包_第3頁
2022Frida手冊二進(jìn)制工具包_第4頁
2022Frida手冊二進(jìn)制工具包_第5頁
已閱讀5頁,還剩190頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

Frida手冊使用Frida工具包了解二進(jìn)制內(nèi)容

1

1

。。32.12.2

系統(tǒng)要求。。軟件要求。

332.3編程語言要求。

4Frida

Instrumentation

67。。103.4

Frida

11

144.1

JavaScript與TypeScript。。。。。

144.2FridaAPI4.3

。。16

。。。。17號.2

。。HooksAPI

。。17號。。184.4

。。。。204.4.1

Frida

。。204.4.2

。。23Frida

。。305.1

。。305.1.1

UTF16

。。315.2數(shù)字。

。。。。345.2.1

按值傳遞的數(shù)字參數(shù)。。34內(nèi)容5.2.2

數(shù)值參考。。5.2.3

35365.3

。。。。375.45.5

指向偏移量的指針。

38395.5.1

findExportByName與getExportByName405.6

指向ArrayBuffer的指針。。。。。

。。407Hexdump5.8

。。435.8.1

編寫控制腳本。

445.9

使用Frida的命令行注入我們的腳本。。485.10遠(yuǎn)程儀表。。。。。

。。49

在Frida的REPL中定義全局變量。。。跟隨子進(jìn)程。。。。創(chuàng)建NativeFunction。。。。

525253576.3.1

使用NativeFunction調(diào)用系統(tǒng)API56.7

修改返回值。。。。。使用后訪問值。。。。。。。

616162647276778080

。。60使用ArrayBuffer進(jìn)行操作。。NOP.27.2.1

API

80818283

(DLL/.so)

。。86

.2

DLL

878789

讀取結(jié)構(gòu)體。

。。91內(nèi)容7.5.1

從用戶控制的結(jié)構(gòu)中讀取。。。9293

WINAPI

。。96C

。。99。。。。10..4

。。CModuleJavaScript106S和C

102105CModule7.10.1

。。110從C代碼通知。。

111CModule

。。113

。。。。12.2

id

。。1177.12.3

稱呼。

1181237.12.4

RET

。。125C

127127

NSURLInitWithStringh。。。f。。

128131134137

斯威夫特.字符串。。。

139143

。。。。1469.1

.19.1.2

測試r2frida。。。。/

146147159.5

()

155156158160內(nèi)容9.6

調(diào)用函數(shù)。

。。160Frida

163165Frida167

167168..111.6.2

時間推動。

169170170173177181185187188

。。。。189FridaFridaAPIAndroid示例本手冊的在線版本可在上獲取和更新。以下是本書的結(jié)構(gòu)的簡要說明:Frida1https://frida.re紹 2FridaFridaFridaFridaAPI,F(xiàn)ridaAPI((...)。FridaCModuleLinuxWindows()。這些示例是在不同ǘ臺上完成的,以說明了解Frida工具包適用于任何地方。MacOSObjective?C/SwiftObjectiveCFrida()NPMPythonclang/gcc/gLinux(WindowsWindows10Windows。在大多數(shù)情況下,這就是我們所需要的:Python(Python2.7)Clang()NPMtypescript()(WindowsVisualGCC。(MacOSSwift/Objective?CXCode。Javascript(JS(TypeScript)n與a(Java么 4JavaScript和或Typescript4.了解C語言基礎(chǔ)知識和指針。(*)如果您想學(xué)習(xí)MacOS部分,建議您具備Objective?C知識。Frida(3Frida)。特別是,儀器儀表過程使我們能夠獲取信息的信息:()(二進(jìn)制儀器有多種應(yīng)用:和Frida 6自動化。API根據(jù)目標(biāo)應(yīng)用程序的訪問級別,可以區(qū)分兩種主要類型的儀器:PAGE13PAGE13Frida用于測量其性能、查找錯誤或獲取分析師或開發(fā)人員感興趣的任何信息的代碼。還可以探測某些代碼塊以監(jiān)視它們的訪問方式或調(diào)用位置,這在跟蹤函數(shù)的執(zhí)行鏈時非常有幫助。Frida(IDEFridaFrida是由OleAndreV開發(fā)的二進(jìn)制儀器工具包。NowSecureDynamoRIO3Frida1/oleavr2https:///content/www/us/en/develop/articles/pin?a?dynamic?binary?instrumentation?tool.html3/aMacSTEM(AndroidiOS)。JavaScript迅速?PIN由于Frida非常直接的API及其設(shè)置過程,開發(fā)變得更加容易和更快。Frida的內(nèi)部運(yùn)作方式。MIPS和Frida庫和/或工具包并將其用于商業(yè)目的。該表有助于說明Frida相對于其他產(chǎn)品的主要優(yōu)勢構(gòu)架:弗里達(dá)·迪納摩RIOPIN開源是的是的不跨ǘ臺是的()是(有限)綁定于不同的是否不語言寫得快儀器儀表是否不工具支持寫作儀器儀表是否不沒有C移動支持是否不自由的是的是的不/wiki/ARM_architecture/wiki/MIPS_architectureeaJavaScriptJavaScript來編寫檢測腳本并且具有很高的可移植性。支持的架構(gòu)和系統(tǒng)支持的操作系統(tǒng)列表和架構(gòu):Windows(x86x64)Linux(x86x64armarm64arm64e)?MacOS(x86x64AppleSiliconM1)?x86)iOS(arm64arm64ex64)Fridax86x64ARMFridaMIPStermux(Android終)。/frida/frida/releases。a/FridaInstrumentation圖1.儀表流程Frida的REPL應(yīng)該編寫檢測工具時,有兩個主要部分需要區(qū)分:控制腳本和檢測腳本。**與FridaFridaAPIPythonNodeSwift、()。child_gating()。控制腳本還與儀器進(jìn)行通信(作為保存儀器消息或停用功能淹沒我們的工具。)最后,它還能夠執(zhí)行檢測腳本中的代碼通過RPC(=遠(yuǎn)程過程調(diào)用)。另一方面,有一個儀器腳本需要關(guān)心與正在運(yùn)行的進(jìn)程的任何交互。這個腳本是用JavaScript編寫,書中的大部分示例都是用JavaScript編寫的(aI)TypeScriptRPCFridaREPL(Frida或外部腳本。Frida是FridaJS(??)核。frida?agentFrida(frida?core)我們(安裝鉤子,與我們的儀器通信JavaScript/wiki/Remote_procedure_call?(frida?core)frida?gum。圖2.Frida儀器內(nèi)部結(jié)構(gòu)。A(REPL)()。DPDBUDBUS傳輸JSON2CJavaScriptRPC2有關(guān)Frida架構(gòu)的更詳細(xì)說明,請訪問frida.re/docs/hacking。Frida使用Frida的項目FridaGoogle?Dwarf10a?個分析MacOS和iOS應(yīng)用程序的工具,它使用有趣的API來檢查它們的使用?radare2frida?I?1GitHubFridahttps:///topics/frida1http://www.giovanni?/dwarf/features/``/dpnishant/appmon``https:///nowsecure/r2frida``httpsfuzzer``https:///sensepost/objection``FridaFridaFridaFrida的CLI(在繼續(xù)之前,請確保使用Python的pip安裝frida和frida?tools軟件包:$pipinstallfridafrida?toolsPythonFrida5.2FridaCLIat或tJavaScriptTypeScriptaJSTypeScriptFrida識 15fridapanic?(能swift?frida2(Swift)TypeScript發(fā)展。5.105.10顯示開發(fā)代理之間主要區(qū)別的圖表在TypeScript與JavaScript中:圖4.基于JavaScript和TypeScript的代理之間的步驟差異。t作為一般經(jīng)驗法則,如果您正在編寫一個簡單而快速的JavaScript對于更大、更復(fù)雜的檢測腳本TypeScript是強(qiáng)烈推薦。編輯器自動完成是的不擴(kuò)展支持構(gòu)建時錯誤檢查是是的不運(yùn)行時錯誤檢查是是的1/nowsecure/frida?panic2/maltek/swift?fridaFrida識 16JavaScript(a用(FridaAPIFridaJavascriptAPIJavaAndroidObjCThread模塊提供了操作線程、休眠線程和獲取回溯的功能。ProcessModule(址)APIMacOSFrida

CModuleCJavaScriptAPIAPI對于代碼檢測,有4個模塊:InterceptorAPI即使StalkerFrida稍后將在章節(jié)中詳細(xì)介紹...AndroidJAVAAPIJAVA更詳細(xì)的逐個API文檔可以在frida.re3中找到網(wǎng)站及其使用的一些示例。arr6.9InterceptorAPIStalkerAPIStalker3https://frida.re/docs/javascript?apiPAGE19PAGE19FridaStalker譯 術(shù)。()CPU5Stalker5Stalker()MarcosattiOle。APIAPI/wiki/Dynamic_recompilation#:~:text=In%20computer%%/max/2400/1*8rD7LvTEldL7wRPDjWhKQ.png/wiki/Checksum#:~:text=A%20checksum%20is%20a%據(jù)%2到%2證%2據(jù)%2Dynarec_Guide技術(shù),但最常見的一種是基于蹦床的鉤子。function_Bfunction_BJMP圖6.蹦床內(nèi)部結(jié)構(gòu)這是對API圖6.蹦床內(nèi)部結(jié)構(gòu)這是對API。InterceptorNativePointers(Frida在TypeScript址,并讓我們附加一些有趣的回調(diào):?內(nèi)容,這就是函數(shù)/x86?api?hooking?demystified/#ah?basicFrida識 20參數(shù)以及其他內(nèi)存部分在被操作之前。?這同樣適用于內(nèi)存區(qū)域。rI是一個Python包CLI工具pip$pip安裝frida?tools(frida?trace和)FridaFrida命令行界面bashWindowsMacOSTerminal/iTerm。Frida的CLI是一個非常重要的工具,因為它在某種程度上替代了對控制腳本的需求(通)FridaCLICLIPAGE21PAGE21Frida姓名:$弗里達(dá)1234$弗里達(dá)記事本.exeaPID。faa要從命令行中恢復(fù)執(zhí)行,只需鍵入%resume,進(jìn)程就會繼續(xù)執(zhí)行。()。S和t8弗里達(dá)的運(yùn)行時間弗里達(dá)的運(yùn)行時間Fridaduktape(式JavaScript擎)、JavaScriptV8QuickJS (代duktape)對本S了而8細(xì)志外8比S高但SM(即們信比QuickJS貴。FridaV8(5.3frida?trace)。https://v8.dev/quickjs/簡單解釋完Frida的運(yùn)行時,我們繼續(xù)討論Frida的CLI參數(shù)。入%resumeaUSBUSB(主要是智能手機(jī))。frida?H1stdio=pipe。e?o將輸出記錄到文件中。?c允許加載Frida代碼共享存儲庫中托管的檢測腳本。如果有人已經(jīng)編寫了一個腳本1https://codeshare.frida.re/Frida識 23該任務(wù)需要什么??梢宰詣訌脑摯鎯熘蝎@取它。FridaCLIFridaInterceptorAPIA。檢測實時進(jìn)程或生成新進(jìn)程。b.跟蹤子進(jìn)程(注:這是按系統(tǒng)實現(xiàn)sW)*或*定W用于移動設(shè)備的USB。$frida?trace?fbinary.exe?f($efe與所提供的匹配的任何PID或進(jìn)程名稱。還可以選擇JavaScript運(yùn)行時JavaScript的V8或QuickJS:$frida?trace?runtime=quickjs|v81234PAGE24PAGE24FridaFridaCLI?I和?X僅影響模塊導(dǎo)出,而不影響模塊導(dǎo)入,因為模塊導(dǎo)入使用?T參數(shù)??梢允褂?通配符進(jìn)行部分匹配,例如創(chuàng)建文件*。CreateFileAKERNELBASE.DLL!CreateFileAKERNEL32.DLL!CreateFileW、KERNELBASE.DLL!CreateFileWKERNEL32.DLL!DeleteFileWADVAPI32.DLL:RegOpenKeyExW.$ei“CreateFileW”IaaKERNELBASECre?ateFileW.$ei“CreateFile*”IKERNEL32KERNELBASECreateFileWCreateFileA。$ei“CreateFileW”I“KERNEL32.DLL”?$frida?trace?i“CreateFileW”?X“KERNEL32.DLL”:aE的CreateFileW。這些參數(shù)可以重復(fù)使用以包含或排除多個功能或模塊。還有一種可能性是$frida?trace<PID>?a“customLib.DLL!0x1234要記住和/或考慮的其他修飾符:aI稱呼。S*S以及更深入的錯誤報告。a下表總結(jié)了不同的命令行frida?trace的開關(guān):影響排除功能包含模塊排除模塊?s在S8API儀器代碼。為了詳細(xì)了解該工具的工作原理,我們將使用一個實用的例子。在這種情況下,目標(biāo)進(jìn)程是notepad.exe,Windows簽名純文本編輯器。該二進(jìn)制文件使用KERNEL32的CreateFileW終端:$e本.xenotepad.exePID在Windows中,您可以使用tasklist命令獲取PID。e1儀表功能...2“\34“\5處6開始跟蹤2個函數(shù)。按Ctrl+C停止。KERNELBASE.DLLKERNEL32.DLL的CreateFileW()現(xiàn)在有件事引起了我們的注意,為什么有兩個存根生成?CreateFileWKERNELBASE.DLLKERNEL32CreateFile我們想要使用哪個模塊來檢測frida?trace儀器從這個APIMSDN11:1處理CreateFileW(LPCWSTR

lp文件名,dwDesiredAccess,dw共享模式,LPSECURITY_ATTRIBUTESlpSecurityAttributes,6雙字dwCreationDisposition,7雙字dwFlagsAndAttributes,8處理h模板文件9);CreateFileW(UTF?16)/en?us/windows/win32/api/fileapi/nf?fileapi?createfilewCreateFileW(WUnicodeC(UTF?16僅適用于Windows)handleronEnter生成的存根:({log(CreateFileW(+args[0].readUtf16String()+ ));3 },需要注意的是onEnter中有3個參數(shù)console.logonEnter(返回)。來自參數(shù)數(shù)組的參數(shù)并將其讀取為UTF?16編碼的字符串。最后我們得到以下輸出:1/*TID0x325c*/2第5877章3第5877章4第5877章5第5878章6第5879章由于KERNELBASE的存根,我們有CreateFileW的重復(fù)項。由于KERNELBASE的存根,我們有CreateFileW的重復(fù)項。(frida?trace在您的環(huán)境中,但這不會影響最終輸出。notepad.exetest.dat。FridaAPIFridarepl(FridaAPI。(constlet...)FridaREPL(FridaREPLeval(如果您使用腳本,則無需擔(dān)心。:)Frida為了分配字符串,我們有以下API:述Memory.allocAnsiString分配ANSI字符串(僅限Windows)Memory.allocUtf8String分配UTF8字符串Memory.allocUtf16String分配UTF16字符串(僅限Windows)():constmyTestString=Memory.allocAnsiString(“HELLOWORLD”);可以使用字符串讀取API讀取myTestString:述讀取C風(fēng)格字符串讀取ANSI字符串g.readUtf16String 用Frida型 31API。可以使用Memory.readAnsiString()API讀取myTestString:myTestString.readAnsiString();如果它是一個C字符串并且該字符串的長度為1024個字節(jié),則有可能將字符串的大小作為參數(shù)傳遞:myTestString.readCString(1024);Frida與弗里達(dá)分享!:)。5.1.1WinAPIaC/m快速POC。在這種情況下,他想將SearchPathW掛鉤到獲取lpFileName參數(shù);該API是KERNEL32.DLL的一部分或內(nèi)核庫.DLL12345678);

DWORD搜索路徑W(LPCWSTRlpPath,LPCWSTRlp文件名,LPCWSTRlp擴(kuò)展,DWORDnBufferLength,LPWSTRlpBuffer,LPWSTR*lpFilePartSearchPathWlpFileNameLPCWSTRWindows我做了一個示例程序來測試它,你可以在下面編譯它使用VisualStudio的Windows:用Frida型 32#include<iostream>#include<Windows.h>34intmain()5{TCHARlpBuffer[MAX_PATH];LPWSTR*lpFilePart{};9=SearchPath(NULL,Lc:\\windows\\,NULLMAX\_PATHlpBufferlpFilePart)std::cout12 值:” <<13結(jié)束;14}c:/windowsFrida的REPL(4.3JavaScriptTypeScriptJavaScriptTypeScriptJavaScriptTypeScript(第5.10節(jié)TypeScript構(gòu)建代理)。首先,我們創(chuàng)建一個名為instrumentation.js的文件。從那里,我們需要:(0)用Frida型 33constsearchPathPtr=Module.getExportByName(“KERNELBASE.\DLL”,“SearchPathW”);34攔截器.attach(searchPathPtr,{56789});

onEnter(參數(shù)){console.log(“輸出:”+args[0].readUtf16String(\}alsfeFrida應(yīng)用檢測代碼后。?lflag設(shè)置檢測腳本。然后我們的控制臺打?。篭TypeScript1constsearchPathPtr:NativePointer=Module.getExportByNam\2e(“KERNELBASE.DLL”,“SearchPathW”);34類SearchPathW{onEnter(args:NativePointer[]){console.log(輸出:7 }8}9

+args[0].readUtf16String());10Interceptor.attach(searchPathPtr,newSearchPathW);()看起來也更ǖ凈、更清晰。主要區(qū)別在于,而不是onEnter用Frida型 34第一個也是最重要的一個是我們需要知道參數(shù)只是一個數(shù)字類型或它的地址,因為如果不是內(nèi)存中的地址,那么我們就不能使用Frida的API來獲取數(shù)值它們通過值或引用傳遞。如果參數(shù)是簡單整數(shù),如下所示存根:1個整數(shù)2添加(inta,intb)3{4 ab;5}如果我們寫:1攔截器.attach(addPtr,{234567

onEnter(數(shù)){console.log(a:console.log(b: }

+args[0].toInt32());+args[1].toInt32());toInt32()獲取真實輸入。用Frida型 35API:{}.readInt(){}.readUInt(){}.readInt(){}.readUInt()8?16?32?64從給定地址讀取浮點數(shù)。{}.readShort(){}.readFloat{}.readDouble地址{}.readLong() {}.readULong({}.readUShort(地址讀取無符號短數(shù)。從給定地址讀取無符號整數(shù)。

說明從給定地其中{}等于NativePointer或ptr()。對于這個例子,我們將使用與之前相同的函數(shù),它將打印兩個值到屏幕上:用Frida型 361//給定a=1337,b=73312無效3print_numbers(int*a,int*b)4{5 printf(,*a,*b);6}]和我們無法理解的隨機(jī)地址,但我們可以使用hexdumpAPI查看其內(nèi)容:17ffecdce5c08a31c000039050000c091d0b349560\20009. 四..()C制的是. 它的APIreadInt()1攔截器.attach(addPtr,{234567

onEnter(參數(shù)){console.log(a: +args[0].readInt());console.log(b: +args[1].readInt());}}這將打印出a=1337和b=7331值。API。寫入NUMERICAAPI的TODO表C20。PAGE37PAGE37使用Frida處理數(shù)據(jù)類型1Interceptor.attach(addPtr,{onEnter:23456});

function(args){args[0].writeInt(10);args[1].writeInt(20);}6.7輸出將在我們的目標(biāo)程序上進(jìn)行修改,結(jié)果會打印a=10和b=20。在下一節(jié)中,我們將了解如何處理指針??梢允褂胷eadPointer()API7.4readPointerAPIsocklen_t1ssize_trecvfrom(intsockfd,void*buf,size_tlen,intf\2滯后,34德倫);

結(jié)構(gòu)sockaddr*src_addr,socklen_t*ad\手冊頁指出:1/man/2/recvfrom26readPointer檢索它:1//...234567//...

onEnter:function(args){console.log(args[5].readPointer(););}如果您有興趣了解Frida如何與JS指針交互,請閱讀以下引用:關(guān)于本機(jī)指針關(guān)于本機(jī)指針aaNativePointerJS64也可以使用指向偏移量的指針,這些將在下一小節(jié)中介紹。FridamyBaseAddr=Module.findBaseAddress(myLib.so);findBaseAddress返回模塊的基地址,現(xiàn)在可用于應(yīng)用偏移量:myOffsetPtr=myBaseAddr.add(ptr(0x76E))r(5.4.1myLib.so地址,但是如果我們不知道模塊名稱或者模塊名稱是命名與預(yù)期不同?Process.enumerateModulesSync(API,API有關(guān)此API的示例,請查看第4.9節(jié)aModule.findExportByNameAPI。句法:Module.findExportByName([MODULE_NAME],[EXPORT_NAME])APInull用Frida型 405.5.1findExportByName與getExportByName(Mod?ule.getExportByName和Module.findExportByName?么。.getExportByName.findExportByNamenull.findExportByNameArrayBuffer[Local::]?>Memory.allocUtf8String(foo)20x7f81143f6be0.read/.write(.readU32()/.writeU32())APIArrayBuffer1[Local::]?>test=newArrayBuffer(10)2000000000000000000000000.\3 ????在這種情況下,數(shù)據(jù)類型可以訪問.unwrap()方法,該方法返回指向ArrayBuffer第一個元素的指針:PAGE41PAGE41使用Frida處理數(shù)據(jù)類型1[本地::]?>test.unwrap()2“0x7fc17c210930”指針大小在執(zhí)行更復(fù)雜的操作并確保檢測腳本足夠可移植時,必須考慮指針的大小。APIProcess.pointerSize()6.36.4HexdumpNativePointerArrayBufferArrayBuffer句法:hexdump(地址,[,選項])其中選項可以是:1{e|e|456}為了獲得更好的表示,請使用console.log進(jìn)行漂亮的打印?!癶elloFridaProcess.enumerateModules()$c$fa.out34[Local::a.out]?>Process.enumerateModulesSync()5[6{7“基數(shù)”:“0x1072f1000”,8name: a.out,9“路徑”:“/Users/fernandou/Desktop/a.out”,10“尺寸”:1638411},12...13]不同的偏移量或需要更長的長度。hexdumpAPI逐字節(jié)顯示數(shù)據(jù)并且只顯示ASCIIAPI(用Frida型 43a的(Fridafrida?createCLI$frida?創(chuàng)建代理這與以下內(nèi)容相同:$git克隆git:///oleavr/frida?agent?example.git請注意,的:1fridafrida?create/package.json/tsconfig.json/agent/index.ts創(chuàng)建./agent/logger.ts6創(chuàng)建./.gitignore78運(yùn)行`npminstall`進(jìn)行引導(dǎo),然后:9?保持一個終端運(yùn)行:npmrunh0?Larl\1s2?*.ts–REPL將生效?保存時重新加載1314提示:使用VisualStudioCode等編輯器來完成代碼\15etion、內(nèi)聯(lián)文檔、即時類型檢查反饋、重構(gòu)工具、e\1617TC。1819弗里達(dá))ls?l20總計1621drwxr?xr?x4費(fèi)爾南杜Primarygroup1282月14日15:46a\22gent/用Frida型 44231fernandou44921415:46p\24ackage.json251fernandou組1672月14日15:46t\26sconfig.jsonnpmnpm運(yùn)行構(gòu)建_agent.jsnpmrunFridaREPLfrida?l_agent.jsnotepad.exe代理人。REPL5.8.1編寫控制腳本1導(dǎo)入操作系統(tǒng)2導(dǎo)入系統(tǒng)34進(jìn)?弗里達(dá)56_SCRIPT_FILENAME=agent.js7defon_message(messagedate): 息。 print(message)1011defmain(process_name):withopen(_SCRIPT_FILENAME,r)script_file:script_file.read()15frida.get_local_device()用Frida型 451819202122232425262728293031

pid=device.spawn(pid)=device.attach(pid)=session.create_script(on_message).load()設(shè)備.resume(pid)print(按CTRL?Z停止執(zhí)行。)sys.stdin.read()會話.detach()name== main:33 (sys.argv[1])用Frida型 46Frida用Frida型 47確切地說。讓我們解釋一下這個腳本中最重要的部分:defon_message(messagedata): 息。 print(message)3on_message回調(diào)將接收來自代理的消息,我們將打印它們并暫時避免處理它們。1device=frida.get_local_device()2pid=device.spawn(process_name)3print(pid:%d%pid)()spawn(PID|ProcessName)APId1個會話=device.attach(pid)23script=session.create_script(code)4script.on(message,on_message)5script.load()67設(shè)備.resume(pid)Attach(pid)(()PAGE48PAGE48使用Frida處理數(shù)據(jù)類型()?,F(xiàn)在,您可以擴(kuò)展此腳本以將消息記錄到文件中,而不是將它們打印到控制臺。請務(wù)必在發(fā)送消息之前對消息進(jìn)行批處理以減少開銷。Fridaa的L()FridaREPLletconst要注入檢測腳本,我們使用?l參數(shù):frida?lmyscript.js<PID|進(jìn)程名稱>a的要%resum$als>或者從頭開始生成一個進(jìn)程:$alsf>為了結(jié)束本節(jié),在下一節(jié)中,我們來看看遠(yuǎn)程檢測。()(備??)。afrida?server(server?14.2.14?windows?x86_64.exe.xz)。要使用Frida遠(yuǎn)程檢測應(yīng)用程序,我們需要:frida?server2在第1點中。Frida((frida?tools和frida軟件包)。frida?serverFrida版本。github1$wget/frida/frida/releases/download/1\24.2.14/frida?server?14.2.14?linux?x86_64.xz`然后解壓并賦予其執(zhí)行權(quán)限:$unxzfrida?server?14.2.14?linux?x86_64.xz2/frida/frida/releasesfrida?server?14.2.14?linux?x86_642chmod+xserver?14.2.14?linux?x86_64然后開始聽:./frida?server?14.2.14?linux?x86_64?l(了。frida和frida?trace中的?H標(biāo)志允許我們連接到特定的地址/端?組合:frida?HIP:端?或者frida?trace?H?Process.pointerSize弗里達(dá)?H01?f/bin/ls?fIP?是:FridaCodeShare存儲庫FridaFridaAndroidJNIAPIObjCFrida$aesfFridaCodeSharehttps://codeshare.frida.re/FridaREPL通過Frida的REPL(frida?lfrida?compile(在REPL中CreateFileWPtrCreateFileWconstCreateFileWPtr=Module.getExportByName(kernelbase.dll,CreateFileW)但我們無法從REPL訪問它。因此,我們使用以下語法:(global).variableName=realVariable?對于JavaScript。(全局).variableName=realVariable?對于TypeScript。(全局).CreateFileWPtr=CreateFileWPtr或者(全局為NativePointer).CreateFileWPtr=CreateFileWPtr一旦我們運(yùn)行我們的小腳本,我們就可以訪問我們的變量:1frida?lglobalstest.jsnotepad.exe2CreateFileWPtr30x7f7a59bfe500法 53FridaI(Frida的L和CreateProcessInternalWLinuxFrida(1#?8?2print_function3

import56從frida_tools.application導(dǎo)入frida7導(dǎo)入Reactor8910類Application(object):def

init

(self):self._stop_requested=threading.Event()self._reactor=Reactor(run_until_return=lambdar\1314個演員:self._stop_requested.wait())15self._device=frida.get_local_device()self._sessions=set()1819

self._device.on(添加子項,lambdachild:self\1/frida/frida?python/master/examples/child_gating.py法 54._reactor.schedule(lambda:self._on_child_add(child)))self._device.on(child?removed,lambdachild:se\lf._reactor.schedule(lambdaself._on_child_removed(\23)))(“as\elf._reactor.schedule(lambda:self._on_output(pid,fd,da\26塔)))2728def運(yùn)行(自我):29self._reactor.schedule(lambda:self._start())30self._reactor.run()3132def_start(自身):33v=[h,c,ts]34環(huán)境={35BADGER:獾?獾?獾,36“SNAKE”:“蘑菇蘑菇”,37}38print(生成(argv={}).format(argv))39pid=self._device.spawn(argv,env=env,stdio=pi\40人41)self._instrument(pid)4243def_stop_if_idle(自身):44如果len(self._sessions)==0:45self._stop_requested.set()4647def_instrument(自身,PID):print([*]Attach(pid={}).format(pid))self._device.attach(pid)session.on(detached,self._react\or.schedule(lambdaself._on_detached(pid\52n)))_child_gating()”)session.enable_child_gating()(“[*]create_script()”)=session.create_script( \Interceptor.attach(Module.getExportByName(null, open),{:({({Memory.readUtf8String(args[0])法 556263 64});

});65”””)66

script.on(消息,lambda消息,數(shù)據(jù):self._\e(lambda:(pid)))68 ()”).load()print((pid={}).format(pid))self._device.resume(pid)self._sessions.add(73def_on_child_add(print([+]child_added:{}.format(child))self._instrument(child.pid)77def_on_child_removed():print([?]child_removed:{}.format(child))80f():(,}(pidfdrepr()))84f():print(離:pid={},Reason={} .format(\8889900.5)91

self._sessions.remove(會話)self._reactor.schedule(self._stop_if_idle,延遲=\f():print(pid={},Payload={}.format(pi\載”]))959697應(yīng)用程序=應(yīng)用程序()()/bin/sh?ccat/etc/hosts()。_startPAGE56PAGE56一旦進(jìn)程被生成并掛起,它的PID就會被發(fā)送到_instrument。_instrumentPID3.(2)。4.檢測腳本繼續(xù)執(zhí)行,直到?jīng)]有更多進(jìn)程被檢測(即父進(jìn)程和子進(jìn)程都不活動)。NativeFunctionNativeFunctionsJavaScript本機(jī)函數(shù)語法:新的NativeFunction(地址,returnType,argTypes[,abi])創(chuàng)建NativeFunction對象需要什么:?(可選)ABI或調(diào)用約定(stdcall、fastcall...)讓我們做一個簡單的例子,假設(shè)有以下添加函數(shù):法 581個整數(shù)(intaintb3{4 ab;5}而我們想要用自己的方式隨意調(diào)用,我們?nèi)绾蝿?chuàng)建native函數(shù)呢?我們現(xiàn)在不考慮ABI。這樣我們就得到了a=int,b=int,return=int。所以,我們現(xiàn)在可以構(gòu)建自己的NativeFunction:新的NativeFunction(ptr(my_address),int,[int,int])我們可以用我們自己的術(shù)語來稱呼它:1constmyAdd=newNativeFunction(ptr(0x0065fd40),int,\2[int,int]);34myAdd(10,10);例如,如果您確定ABI是_fastcall,則可以添加調(diào)用約定參數(shù):新的NativeFunction(ptr(my_address),int,[int,int],fastcall)APIAPINativeFunction在第一個示例中,我們將通過mkdirAPI創(chuàng)建一個NativeFunction:法 59#include<sys/types.h>#include<sys/stat.h>#include<unistd.h>#include<stdio.h>56無效7主要()8{91011121314151618192021}

mkdir(/home/fernandou/frida/test_folder,0700);結(jié)構(gòu)體統(tǒng)計st={0};if(stat(/home/fernandou/frida/test_folder,&st)==\{put\n);}別的{put\n);}然后我們可以在Frida的REPL中運(yùn)行該程序:1$clangmkdir.c?ocMkdir2$弗里達(dá)?fcMkdir一旦我們進(jìn)入程序,我們首先需要一個指向mkdir的指針1[Local::a.out]?>mkdir=Module.getExportByName(null,mk\2目錄)3“0x7fff204ca3b4”NativeFunctionconstUTF8PAGE60PAGE601[Local::a.out]?>folderName=Memory.allocUtf8String(fri\2dahandbook)30x108b6dbe0在Frida的REPLNativeFunctionsfridahandbookNativeFunction:1[Local::a.out]?>frida_mkdir=newNativeFunction(mkdir,\2int,[pointer])3函數(shù)4[Local::a.out]?>frida_mkdir(folderName)506[本地::a.out]?>\7\89感謝您使用弗里達(dá)!1011弗里達(dá)ls?l12d???r?????2費(fèi)爾南杜Primarygroup13b14:22fridahandbook6426鐵\我們使用指針作為參數(shù)并返回int值來創(chuàng)建本機(jī)函數(shù),在此示例中不需要指定ABI。8mkdir(mkdirat(errno)。這意味著我們的NativeFunction工作完美,并且我們已經(jīng)創(chuàng)建了文件夾!2/linux/man?pages/man2/mkdir.2.html.replace(KERNEL32.DLL!MoveFileW0假設(shè)程序在繼續(xù)之前檢查文件是否被移動,但我們只希望它相信它確實被移動了:1constretvalOne:NativePointer=ptr(0x1);2類MoveFileW{onLeave(retval:NativeReturnValue)3 {retval.replace(retvalOne);45 }6}NativeReturnValue可以訪問retval方法,我們可以使用它來修改對象。再次建議盡可能多地使用const以防止出現(xiàn)問題。執(zhí)行。Frida可以做到這一點,但是我們需要考慮一些額外的信息。用.readUtf16String()之類的API基本結(jié)構(gòu)法 621類myInstrumentedFunction{234567891011}

r=onEnter(args:NativePointer[]){this.firstParam=args[0];}onLeave(retval:NativeReturnValue){console.log(this.firstParam.readCString())}我們要做的第一件事是創(chuàng)建我們想要的變量onLeaveNativePointer范圍,以便在兩個階段都可以訪問。然后我們就可以在onLeave階段訪問它。萬一onLeavehexdump(現(xiàn)在我們將通過一個真實的例子來說明如何使用它。CryptDecryptMSDNAPIBOOLHCRYPTKEYhKey,HCRYPTHASHhHash,45678);

布爾值雙字字節(jié)雙字

最終的,dwFlags,*pb數(shù)據(jù),*pdw數(shù)據(jù)長度MSDN注釋:法 631pb數(shù)據(jù)23指向包含要解密的數(shù)據(jù)的緩沖區(qū)的指針\4特德。執(zhí)行解密后,明文\5xt6\8 pdwDataLen所以我們有一個hKey但這不是最重要的論據(jù)APIonLeave和1類CryptDecrypt{2345678910111213}

onEnter(args:NativePointer[]){this.buffer=args[4];this.buffer_size=args[5];}onLeave(retval:InitationReturnValue){this.buffer.readCString(this.buffer_size);}args[4如果我們嘗試在onEnter期間檢查this.buffer=args[4],我們將如果我們要檢查的不是字符串或數(shù)字法 64hexdumpAPI1類CryptDecrypt{23456789101112131415161819}

onEnter(args:NativePointer[]){this.buffer=args[4];this.buffer_size=args[5];}onLeave(retval:InitationReturnValue){讓緩沖區(qū)大??;if(this.buffer_size){hexdump(this.buffer,{長度:this.buffer_size.readPointer().toInt32()});}}如果我們有興趣在函數(shù)時修改輸入值慎用。如果我們想要做的是調(diào)用帶有自定義參數(shù)的函數(shù)為了我們自己的利益(例如調(diào)用CreateFileW返回我們一個HANDLE)我們來這里的目的是什么。假設(shè)我們有一個程序檢查文件是否存在,如果該文件確實存在那么程序?qū)⒉粫^續(xù)執(zhí)行。我們不想刪除此文件,因為它是我們中其他程序的依賴項法 65這是我們的示例程序:#include<sys/types.h>#include<sys/stat.h>#include<unistd.h>#include<stdio.h>56無效7主要()8{st0if(stat(/bin/ls,&st)==?1)11 {putsbu\sybox14//執(zhí)行真實代碼15}16別的{18put(文件夾存在\n);19//不執(zhí)行任何操作就退出20}21}這個程序與我們之前見過的程序類似,它調(diào)用stat檢查文件是否存在,如果不存在則繼續(xù)執(zhí)行。Fridastat(radare2法 66通過檢查反匯編我們可以注意到:法 671 0x100003ed6

e843000000

sym.imp.memse\│2t()3│n_ls]

;void*memset(void*s,intc,size_tn)0x100003edb488d3d7c0000。rdi=[str.bi\│ ;section.3.

TEXT.

cstring\6 ;0x100003f5e;“/bin/ls”7│8var_98h]

0x100003ee2

488bb568ffff。rsi=qword[\9│10INODE64()11│12噗噗噗噗噗噗噗

0x100003ee90x100003eee

e83c00000083f8ff

sym.imp.stat_\var=eax?0\13│0x100003f08

┌─<0x100003ef114

0f8511000000if(var)轉(zhuǎn)到\stat_INODE64FridaREPL1[Local::a.out]?>Module.enumerateImports(a.out)2[3 {4 “0x7fff2051725c”,5 /usr/lib/libSystem.B.dylib,6“名稱”:“dyld_stub_binder”,6“名稱”:“dyld_stub_binder”,7“槽”:“0x103229000”,8“類型”:“功能”9},10{11“地址”:“0x7fff205456f8”,1213模塊:/usr/lib/libSystem.B.dylib“名稱”:“memset”,14“槽”:“0x10322d000”,15“類型”:“功能”16},{18“地址”:“0x7fff20410274”,1920模塊:/usr/lib/libSystem.B.dylib“名稱”:“投入”,21“槽”:“0x10322d008”,22“類型”:“功能”23},,法 6824 {2526

“地址”:“0x7fff204ca39c”,模塊:/usr/lib/libSystem.B.dylib,27“名稱”:“統(tǒng)計$INODE64”,28“槽”:“0x10322d010”,29“類型”:“功能”30}31]在此列表中,我們可以注意到一個損壞的名稱:1 {2 “0x7fff204ca39c”,3 /usr/lib/libSystem.B.dylib,45“槽”“0x10322d010”,67}這意味著如果我們想調(diào)用Module.getExportByName我們需要stat$INODE64函數(shù)名稱而不是stat。一旦我們有了這些數(shù)據(jù),我們就可以編寫我們的檢測腳本:1constredirectString=Memory.allocUtf8String(/bin/fooba\2r”);3conststatPtr=Module.getExportByName(null,stat$INODE6\44);56攔截器.attach(statPtr,{789101112131415161819

onEnter(參數(shù)){常量firstArg=args[0];讓statArg=firstArg.readUtf8String();console.log(stat查: +firstArg.readUtf8String());if(statArg.indexOf(bin/ls)!=?1){args[0]=重定向字符串;}console.log(徑: +args[0].readUtf8String());}法 69我們可以啟動這個腳本:$aftls輸出結(jié)果如下:1aftls2 3 理暗示工具包

_|4心

Frida14.2.12?世界一流的動態(tài)工具\(yùn)5 |(_6 >

_|命令:7 /_/help89個物體1011

。。。。。。。。。。。。

目的??>顯示有關(guān)\退出/退出?>退出12

https://www.frida.re/docs/home/`a.out`程! \1415文件不存在。16安裝我們自己的busybox二進(jìn)制文件17stat正在檢查:/bin/ls18最終統(tǒng)計路徑?:/bin/foobar19[Local::a.out]?>進(jìn)程終止是我們所期望的,stat參數(shù)被重定向到/bin/foobar反而。有時我們想要銷毀一個函數(shù)在發(fā)生一組特定條件之后,要么因為我們沒有在運(yùn)行時撤消掛鉤。法 70#include<sys/types.h>#include<sys/stat.h>#include<unistd.h>#include<stdio.h>56無效7check_file(字符*路徑)8{9結(jié)構(gòu)體統(tǒng)計st={0};10if(stat(路徑,&st)==?1)11{12printf[%s\n,路徑);13}14別的15{16printf[%s\n,路徑);}18}19無效20主要()21{22check_file(“/bin/ls”);23check_file(“/bin/cd”);24}ls(如果我們使用Frida和TypeScript的自動完成功能,可以檢查這一點)。我們的腳本將是:法 711constredirectString=Memory.allocUtf8String(/bin/fooba\2r”);3conststatPtr=Module.getExportByName(null,stat$INODE6\44);56讓statListener=Interceptor.attach(statPtr,{7891012131415

onEnter(參數(shù)){this.removeHook=false;讓statArg=args[0].readUtf8String();console.log(stat正在檢查:+args[0].readUtf8St\if(statArg.indexOf(bin/ls)!=?1){args[0]=重定向字符串;this.removeHook=true;}16 console.log(最終統(tǒng)計路徑?:17ring());

+args[0].readUtf8St\1819202122232425});

},onLeave(retval){(this.removeHook{console.log(正在刪除統(tǒng)計工具...);statListener.detach();}}onEnteronLeavethis.removeHookfalsestatListener最后,這是我們得到的輸出:法 721$frida?fa.out?lscript.js23文件[/bin/ls]不存在。5stat/bin/lsstat/bin/foobar除stat檢測...8[Local::a.out]?>進(jìn)程終止stat/bin/lsFridastructtypedef_UNICODE_STRING{USHORTUSHORTPWSTR}UNICODE_STRING,*PUNICODE_STRING;++std::stringSwift.Stringg(<2)((Process.pointerSize為了測試這些知識并了解如何獲取字符串,讓我們看一下這個簡單的程序:法 731#include<iostream>23無效print_std_string(std::stringarg_1){45}6

std::cout<<arg_1<<std::endl;8主(無效){91011121314}

std::stringmy_string=“弗里達(dá)很棒””你應(yīng)該在frida.re上查看一下”;print_std_string(my_string);返回0;print_std_string(std::string一旦我們在Frida的REPL中啟動這個程序并運(yùn)行在我們的二進(jìn)制文件中,我們注意到Module.enumerateExportsSync()的名稱被破壞了,但是由于我們?yōu)闇y試函數(shù)選擇的名稱我們可以發(fā)現(xiàn)一個名為_Z16print_std_stringNSt3_?的損壞函數(shù)_112basic_stringIcNS_11char_traitsIcEENS_9分配器IcEEEE。這是我們要使用Interceptor.attach的函數(shù)。Interceptor.attach(Module.getExportByName(null,_Z16prin\t_std_stringNSt3112basic_stringIcNS_11char_traitsIcEENS\IcEEEE),{4onEnter(參數(shù)){5constLSB=args[0].readU8()&1;6console.log(位: +位);7conststdString=args[0].8添加(進(jìn)程.pointerSize*2)。9讀取指針()。10readUtf8String();11console.log(std::字符串:+標(biāo)準(zhǔn)字符串);12}13});然后,我們可以運(yùn)行這個小腳本并獲得以下輸出:法 741std::stringf\3rida.re4[Local::a.out]?>進(jìn)程終止clang++12.0.0GCC。std::vector。std::vector<clang1//clang++vectortest.cc2#include<向量>3#include<iostream>45無效print_vector_size(std::vector<int>v)6{78}910intmain()11{12131415}

std::cout<<向量大?。?lt;<v.size()<<std::endl;>v=,,,,,,,,,(v)給定數(shù)據(jù)類型,可以迭代指針直到向量的最新元素。該向量在內(nèi)存中的表示方式如下:法 75每40x0a通過Process.pointerSize(在本例中是64位應(yīng)用程序指針大小=8)。因為向量的每個成員都是一個int4個字節(jié)的向量可以獲取它的值。換句話說:rr為了測試這一點,以下代碼將迭代該成員的每個成員std::vector并將它們存儲在列表中:1constvectorPrintPtr=ptr(0x00400af0);23攔截器.attach(vectorPrintPtr,{4567891011121314151617})

({constFinalAddr=args[0].add(8).readPointer();讓startAddr=args[0].readPointer();讓向量大小=0;讓元素=[];while(startAddr<FinalAddr){矢量大小+=1;elements.push(startAddr.readInt());startAddr=startAddr.add(0x4);}控制臺.log(元素);console.log(向量大小:+矢量大小);}法 761[本地::a.out]?>21,2,3,4,5,6,7,8,9,10MSVCstd::vectorMSVC++為向量結(jié)構(gòu)生成不同的內(nèi)存布局。Process.pointerSize(6416)。簡而言之:在Process.pointerSize這給我們留下了以下代碼:1constvectorPrintPtr=ptr(0x00400af0);23攔截器.attach(vectorPrintPtr,{456789101112131415161819

onEnter:函數(shù)(參數(shù)){constFinalAddr=args[0].(.pointerSize*2)this.startAddrargs[0].()this.向量大小=0;this.elements=[];while(this.startAddr<FinalAddr){this.向量大小+=1;this.elements.push(this.startAddr.readInt());this.startAddr=this.startAddr.add(0x4);}console.log(this.elements);console.log(向量大?。?this.向量大小);法 7720 }21})當(dāng)檢測我們的MSVC應(yīng)用程序時,檢測腳本會打印以下輸出:1[本地::vectortest.exe]?>21,2,3,4,5,6,7,8,9,10,113矢量大小:11ArrayBufferFridaf(“target1intmain(intargc,char*argv[]){if(argc<3){234>\n,argv[0]);56

fprintf(stderr,用法:%s<目標(biāo)><端?\退出(1);7 0;8}該Cfprintfintfprintf(FILE*stream,constchar*format,...);*format法 781constfprintfPtr=Module.getExportByName(null,fprintf\2);34攔截器.attach(fPrintfPtr,{56789e10

onEnter(參數(shù)){常量firstArg=args[1];this.bufferSize=firstArg.readCString().length+1;this.arrayBuf=firstArg.readByteArray(this.bufferSiz\this.str=String.fromCharCode.apply(null,newUint8A\11數(shù)組(this.arrayBuf));121314 15});16

this.str=this.str.replace(target, foobarargs[1]=str2ab(this.str).unwrap();17函數(shù)str2ab(str){18192021222324}

bufnewArrayBuffer(str.length);bufViewnewUint8Array(buf);for(vari=0,strLen=str.length;i<strLen;{bufView[i]=str.charCodeAt(i);}返回緩沖區(qū);str2ab是一個輔助函數(shù),它將字符串轉(zhuǎn)換回Uint8Array。1this.buffer_size=args[1].readCString().length+1;2console.log(buffer_size:+this.buffer_size);3this.arrayBuf=args[1].readByteArray(this.buff

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論