吉德拉很棒,我喜欢尽可能多的脚本。但是,吉德拉(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提出特定问题。