2. Ghidra脚本开发入门:Python脚本基础、Ghidra脚本API概览、第一个Hello World脚本

说实话,很多朋友刚开始接触Ghidra脚本开发时,第一反应是「这玩意儿是不是很难?」。我当年也是这么想的。但真正上手后才发现——嗯,Ghidra的Python脚本接口设计得相当友好。你只要有基础的Python知识,再懂一点点逆向的概念,就能写出有用的脚本。

这一章,我们就从零开始。我会带你过一遍Python脚本的基础,然后看看Ghidra给我们提供了哪些API,最后亲手写一个Hello World脚本。别急,咱们一步步来。

2.1 Python脚本基础:你只需要知道这些

Ghidra支持Jython 2.7,说白了就是Python 2.7的语法。虽然Python 2已经退休了,但在Ghidra里它依然是主力。我个人建议你记住几个核心点就够了:

  • 变量不用声明类型——直接赋值就行。比如 addr = 0x401000
  • 缩进决定代码块——用4个空格,别用Tab。我踩过这个坑,脚本跑起来报缩进错误,排查了半天。
  • 函数用def定义——比如 def my_function():
  • 列表和字典很常用——列表用 [],字典用 {}
小提示: 如果你之前只用过Python 3,注意print在Python 2里是语句不是函数——写 print "Hello" 而不是 print("Hello")。不过Ghidra的脚本环境里,两种写法都能跑,但建议统一用不带括号的。

你可能会问:「就这些?」对,就这些。Ghidra脚本里真正复杂的不是Python语法,而是API的调用逻辑。咱们接着往下看。

2.2 Ghidra脚本API概览:核心对象一览

Ghidra的API,说白了就是一堆Java类,但通过Jython暴露给了我们。我习惯把它们分成三大类:

类别 核心类/接口 作用
程序模型 currentProgram, Address, Memory, FunctionManager 访问二进制文件的地址、内存、函数等
分析工具 FlatProgramAPI, Decompiler, DataTypeManager 提供反编译、类型分析等高级功能
交互界面 askString, println, toAddr 与用户交互、输出信息

其中,FlatProgramAPI 是你最常用的。它把很多底层操作封装成了简单的方法。比如你想获取当前地址的指令,直接调用 getInstructionAt(addr) 就行。我在做自动化分析时,90%的脚本都只用了这个API。

重点: 所有脚本都默认有一个 state 对象,通过它你可以拿到 currentProgramcurrentAddress 等。这是Ghidra脚本的入口。

为了让你更直观地理解这些API之间的关系,我画了一张图:

Ghidra脚本API核心结构 脚本入口 (state) 程序模型 currentProgram, Memory 分析工具 FlatProgramAPI, Decompiler 交互界面 askString, println getInstructionAt() getFunctionAt() decompile() getDataType() toAddr() askChoice() println() popup() 从state出发,通过三大核心API访问底层方法 FlatProgramAPI 是最常用的封装层

2.3 第一个Hello World脚本:动手写起来

理论说再多,不如跑一个脚本实在。咱们来写一个最简单的Hello World。打开Ghidra,加载任意一个二进制文件(比如notepad.exe),然后按以下步骤操作:

  1. 点击菜单 Window → Script Manager
  2. 在弹出的窗口中,点击 Create New Script 按钮
  3. 选择 Python 作为语言,输入文件名 HelloWorld.py
  4. 在编辑器中输入下面的代码
# HelloWorld.py
# 我的第一个Ghidra脚本

def run():
    # 获取当前程序名称
    program_name = currentProgram.getName()
    
    # 输出到控制台
    println("Hello, Ghidra!")
    println("当前分析的程序是: " + program_name)
    
    # 弹出一个对话框
    popup("欢迎来到Ghidra脚本世界!")
    
    # 获取当前地址
    current_addr = currentAddress
    println("当前光标所在地址: " + str(current_addr))
注意: 脚本必须包含一个 run() 函数,Ghidra会调用它作为入口。如果你忘了定义这个函数,脚本会报错。我曾经犯过这个低级错误,找了半天才发现。

写完后,点击工具栏上的绿色三角形按钮运行。你会看到控制台输出三行信息,同时弹出一个对话框。就这么简单——你已经成功运行了第一个Ghidra脚本。

你可能会问:「println和popup是从哪来的?」它们其实是Ghidra脚本环境内置的函数,不需要import。类似的还有 askStringaskChoicetoAddr 等。这些函数在 FlatProgramAPI 里都有定义,但Ghidra为了方便,直接把它们暴露在了全局命名空间中。

调试小技巧: 如果你不确定某个函数是否存在,可以在脚本里直接输入 dir() 并运行,它会列出当前作用域下所有可用的名字。这个方法我用了无数次,比翻文档快多了。

2.4 脚本的保存与组织

Ghidra的脚本默认保存在用户目录下的 ghidra_scripts 文件夹里。我个人习惯按功能分类存放:

  • analysis/ —— 分析类脚本
  • patch/ —— 补丁类脚本
  • utils/ —— 工具类脚本
  • tutorial/ —— 教程类脚本

这样组织的好处是,当你的脚本数量超过几十个时,找起来不会头大。另外,Ghidra的Script Manager支持按文件夹过滤,你可以在右上角的搜索框里输入文件夹名快速定位。

好了,这一章的内容就到这里。你学会了Python脚本的基础、Ghidra API的三大核心分类,还亲手写了一个Hello World脚本。下一章我们会深入FlatProgramAPI,看看如何用它来遍历函数、分析指令——那才是真正开始干活的时候。


专注资料整理