吉德拉很棒,我喜歡盡可能多的腳本。但是,吉德拉(Ghidra)的Python腳本是基於Jython的,如今它並不處於一個很好的狀態。如果他們甚至可以在Jython環境中運行,那麼安裝新包裝是一種麻煩,而且隨著Python 2慢慢被關閉,它只會變得更糟。
因此,吉德拉橋(Ghidra Bridge)努力避開了這個問題 - 而不是被困在Jython,而是為Python物體建立了RPC代理,因此我們可以呼籲Ghidra/Jython-Land進入我們需要的數據,然後將其帶回到更新的Python中,以便您需要您的所有包裝來完成您的工作。
目的是要盡可能透明,因此,一旦設置,您就不需要知道對像是本地還是遠程ghidra-橋樑應無縫處理/設置/呼叫。
如果您喜歡這樣,您可能還會對其他反向工程工具的等效物感興趣:
如果您真的很喜歡,請隨時給我買咖啡:https://ko-fi.com/justfoxing
pip install ghidra_bridge
python -m ghidra_bridge.install_server ~/ghidra_scripts
對於更好的交互式外殼,例如Ipython,或者如果您需要在交互式環境中進行Python 3庫,則可以在交互式GUI會話的背景下啟動橋樑。
否則:
您可以將Ghidra Bridge作為後分析腳本運行,以進行無頭分析,然後對客戶進行進一步的分析。為此,請使用Ghidra_bridge_server.py(不是_background.py),因此在關閉橋樑之前,它不會退出。
$ghidraRoot/support/analyzeHeadless <path to directory to store project> <name for project> -import <path to file to import> -scriptPath <install directory for the server scripts> -postscript ghidra_bridge_server.py
有關如何運行Analyzehead命令(如果需要),請參見Ghidra支持/目錄中的AnalyzeheadelessReadme.html。
您可以在不加載任何程序的情況下在環境中啟動橋樑,例如,如果您想訪問某些API,例如DatatyPemanager,該API不需要分析程序
$ghidraRoot/support/pythonRun <install directory for the server scripts>/ghidra_bridge_server.py
來自客戶python環境:
import ghidra_bridge
with ghidra_bridge . GhidraBridge ( namespace = globals ()):
print ( getState (). getCurrentAddress (). getOffset ())
ghidra . program . model . data . DataUtilities . isUndefinedData ( currentProgram , currentAddress )或者
import ghidra_bridge
b = ghidra_bridge . GhidraBridge ( namespace = globals ()) # creates the bridge and loads the flat API into the global namespace
print ( getState (). getCurrentAddress (). getOffset ())
# ghidra module implicitly loaded at the same time as the flat API
ghidra . program . model . data . DataUtilities . isUndefinedData ( currentProgram , currentAddress )警告:如果您在非背心地面模式下運行,請避免單擊腳本彈出板上的“取消”按鈕,因為這將使服務器套接字處於不良狀態,並且您必須完全關閉Ghidra才能修復它。
要乾淨地關閉服務器,如果您在上面的安裝說明中完成了步驟3,請單擊“工具” - > Ghidra橋 - >關閉。否則,請從橋樑文件夾中運行ghidra_bridge_server_shutdown.py腳本。
另外,您可以從任何連接的客戶端調用Remote_shutdown。
import ghidra_bridge
b = ghidra_bridge . GhidraBridge ( namespace = globals ())
b . remote_shutdown ()請注意,運行時,Ghidra Bridge服務器有效地將代碼執行作為服務。如果攻擊者能夠與吉德拉港(Port Ghidra Bridge)進行交談,則他們可以通過與Ghidra合作的特權來瑣碎地獲得執行。
還要注意,用於發送和接收Ghidra橋消息的協議未經加密且未驗證 - 中間人攻擊將允許完全控制命令和響應,再次在服務器上提供瑣碎的代碼執行(以及對客戶端的更多工作)。
默認情況下,Ghidra Bridge服務器僅在Localhost上傾聽以稍微降低攻擊表面。僅當您有信心自己在安全的網絡上,僅在外部網絡地址上聽。此外,攻擊者仍然有可能向Localhost發送消息(例如,通過瀏覽器中的惡意JavaScript或利用其他過程並攻擊Ghidra Bridge來提高特權)。您可以通過僅在需要時或在非網絡連接的系統上運行它,從而從具有降低的權限(非Admin用戶或在容器內部)運行Ghidra Bridge來降低這種風險。
Ghidra Bridge的設計為透明,以便在沒有太多更改的情況下輕鬆移植非橋接的腳本。但是,如果您樂於進行更改,並且會遇到由於運行大量遠程查詢而引起的放緩(例如, for function in currentProgram.getFunctionManager().getFunctions(): doSomething()只有一個消息往返。
以下示例演示了二進制中所有功能的所有名稱的列表:
import ghidra_bridge
b = ghidra_bridge . GhidraBridge ( namespace = globals ())
name_list = b . remote_eval ( "[ f.getName() for f in currentProgram.getFunctionManager().getFunctions(True)]" )如果您的評估要花一些時間,則可能需要使用TimeOut_override參數來增加橋樑將等待多長時間,然後才能確定問題出現。
如果您需要為遠程評估提供參數,則可以向遠程_eval函數提供任意關鍵字參數,該參數將作為本地變量傳遞到評估上下文中。以下參數通過函數傳遞:
import ghidra_bridge
b = ghidra_bridge . GhidraBridge ( namespace = globals ())
func = currentProgram . getFunctionManager (). getFunctions ( True ). next ()
mnemonics = b . remote_eval ( "[ i.getMnemonicString() for i in currentProgram.getListing().getInstructions(f.getBody(), True)]" , f = func )簡而言之,還請注意,評估上下文具有啟動服務器啟動服務器的___ -main __中的相同的全球群體 - 在Ghidra橋式服務器的情況下,這些全球包括平面API和值(例如Curturn Program)。
如果您的腳本中有一個特別緩慢的調用,則可能會擊中橋樑用來確保連接未斷開的響應超時。如果發生這種情況,您會看到類似Exception: Didn't receive response <UUID> before timeout 。
有兩個選擇可以增加超時。創建橋樑時,您可以使用withs_timeout參數以秒為單位設置超時值(例如, b = ghidra_bridge.GhidraBridge(namespace=globals(), response_timeout=20) ),該命令適用於所有橋樑上的所有命令。另外,如果您只想更改一個命令的超時,則可以使用上述遠程_eval使用timeout_override參數(例如, b.remote_eval("[ f.getName() for f in currentProgram.getFunctionManager().getFunctions(True)]", timeout_override=20) 。如果將值-1用於這些參數中的任何一個,則將禁用響應超時,並且橋將永遠等待您的響應回來 - 請注意,如果橋樑遇到問題,這可能會導致您的腳本掛起。
如果您想從Ghidra側(例如Ghidra,Java,對接名稱空間)導入模塊,則有兩個選擇。
remote_module = b.remote_import("java.math.BigInteger") )。這具有一個優勢,您可以完全控制遠程模塊(並且可以獲取具有與本地模塊相同名稱的遠程模塊),並且何時發布了遠程模塊,但是它確實需要更多的工作。b = ghidra_bridge.GhidraBridge(namespace=globals(), hook_import=True) )。這將為導入機械增加一個鉤子,以便如果沒有其他東西可以填充導入,則橋樑將嘗試處理它。這使您只需使用標準import ghidra.framework.model.ToolListener語法連接到橋樑後。這具有一個優勢,它可能更容易使用(您仍然必須確保在連接橋樑後發生導入),但是它不允許您以與本地模塊相同的名稱導入遠程模塊(本地導入優先),並且它將遠程模塊放在SYS.S.S.Modules中的遠程模塊作為適當的導入,因此它們和橋樑可能會持續負載,直到該進程均可終止。此外,具有Hook_import = True的多個橋樑將嘗試按照它們連接的順序解決導入,這可能不是您想要的行為。通常,Ghidra腳本在剛開始時會獲得Ghidra狀態和當前*變量(Current Program,CurrentAddress等)的實例,並且在腳本運行時不會更新。但是,如果您運行Ghidra Python解釋器,則可以通過每個命令更新其狀態,以便CurrentAddress始終與GUI匹配。
為了反映這一點,Ghidrabridge將自動嘗試確定您是在交互式環境(例如Python解釋器,Ipython)還是從腳本中運行客戶端。如果是一個互動環境,它將向Ghidra註冊一個活動聽眾,並執行一些可疑的幕後Shenanigans,以確保該州更新了GUI更改,以便像Ghidra Python解釋器一樣行事。如果您給它一個橋接的對象,它還將用伸出橋的吉德拉在橋上使用Ghidra的help() 。
您不必關心這一點,但是如果出於某種原因,自動檢測沒有給您所需的結果,則可以在創建客戶端Ghidrabridge時指定布爾互動Interactive_mode參數以根據需要強制其啟動或關閉。
實際的橋樑RPC代碼在JFX-Bridge中實現。在那裡檢查一下,並將與此處的橋相關的非Ghidra提出特定問題。