2026-03-03


Ghidra API 使用手册 (Cookbook)

基于 GhidraSnippets 项目总结的 Ghidra API 常用模式和最佳实践。


版权信息

本文档由 Claude Sonnet 4.5 协作生成,内容基于 GhidraSnippets 项目整理而成。


目录

  1. 核心 API 概览
  2. 程序与项目操作
  3. 函数操作
  4. 反编译器使用
  5. 指令与汇编
  6. 变量与内存
  7. PCode 操作
  8. 交叉引用
  9. 常用工具函数

核心 API 概览

三大核心 API

Ghidra 提供三个主要的扁平化 API(Flat API),简化了常见操作:

1. FlatProgramAPI - 程序操作核心

 1from ghidra.program.flatapi import FlatProgramAPI
 2
 3state = getState()
 4program = state.getCurrentProgram()
 5fpapi = FlatProgramAPI(program)
 6
 7# 访问程序相关功能
 8print(fpapi.currentProgram)
 9print(fpapi.firstFunction)
10print(fpapi.firstInstruction)

常用方法:

2. FlatDecompilerAPI - 反编译器接口

 1from ghidra.app.decompiler.flatapi import FlatDecompilerAPI
 2from ghidra.program.flatapi import FlatProgramAPI
 3
 4fpapi = FlatProgramAPI(getState().getCurrentProgram())
 5fdapi = FlatDecompilerAPI(fpapi)
 6
 7# 反编译函数
 8main_func = fpapi.getFunction('main')
 9decomp_result = fdapi.decompile(main_func)
10print(decomp_result)

3. FlatDebuggerAPI - 调试器接口

1from ghidra.app.flatapi import FlatDebuggerAPI
2
3# 用于调试相关操作

程序与项目操作

获取当前程序信息

1# 方法 1: 使用全局变量
2program = currentProgram
3print("Program name:", program.getName())
4print("Executable path:", program.getExecutablePath())
5
6# 方法 2: 通过 state
7state = getState()
8program = state.getCurrentProgram()

获取程序段信息

1# 列出所有内存段
2mem = currentProgram.getMemory()
3for block in mem.getBlocks():
4    print("Section: {} @ 0x{} (size: {})".format(
5        block.getName(),
6        block.getStart(),
7        block.getSize()
8    ))

项目操作

 1# 获取项目信息
 2state = getState()
 3project = state.getProject()
 4print("Project name:", project.getName())
 5print("Project location:", project.getProjectLocator())
 6
 7# 列出项目中的所有程序
 8project_data = project.getProjectData()
 9root_folder = project_data.getRootFolder()
10for df in root_folder.getFiles():
11    print("Program:", df.getName())

函数操作

遍历所有函数

 1# 方法 1: 使用 Flat API
 2func = getFirstFunction()
 3while func is not None:
 4    print("Function: {} @ 0x{}".format(func.getName(), func.getEntryPoint()))
 5    func = getFunctionAfter(func)
 6
 7# 方法 2: 使用 FunctionManager
 8fm = currentProgram.getFunctionManager()
 9funcs = fm.getFunctions(True)  # True = 正向遍历
10for func in funcs:
11    print("Function: {} @ 0x{}".format(func.getName(), func.getEntryPoint()))

通过地址获取函数

 1def getAddress(offset):
 2    return currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress(offset)
 3
 4fm = currentProgram.getFunctionManager()
 5addr = getAddress(0x00100690)
 6
 7# 获取入口点处的函数(仅适用于函数入口地址)
 8func = fm.getFunctionAt(addr)
 9
10# 获取包含该地址的函数(推荐)
11func = fm.getFunctionContaining(addr)
12
13# 检查地址是否在函数内
14is_in_func = fm.isInFunction(addr)

通过名称获取函数

1# 注意:可能有多个同名函数(函数重载)
2name = "main"
3funcs = getGlobalFunctions(name)
4print("Found {} function(s) with name '{}'".format(len(funcs), name))
5
6for func in funcs:
7    print("{} is located at 0x{}".format(func.getName(), func.getEntryPoint()))

重命名函数

1# 获取函数对象
2func = getGlobalFunctions("old_name")[0]
3
4# 重命名
5from ghidra.program.model.symbol import SourceType
6func.setName("new_name", SourceType.USER_DEFINED)

获取函数交叉引用

 1fm = currentProgram.getFunctionManager()
 2funcs = fm.getFunctions(True)
 3
 4for func in funcs:
 5    if func.getName() == "system":
 6        print("\nFound 'system' @ 0x{}".format(func.getEntryPoint()))
 7        entry_point = func.getEntryPoint()
 8        references = getReferencesTo(entry_point)
 9
10        for xref in references:
11            print("From: {} To: {} Type: {}".format(
12                xref.getFromAddress(),
13                xref.getToAddress(),
14                xref.getReferenceType()
15            ))

反编译器使用

基本反编译

 1from ghidra.app.decompiler import DecompInterface
 2from ghidra.util.task import ConsoleTaskMonitor
 3
 4program = getCurrentProgram()
 5ifc = DecompInterface()
 6ifc.openProgram(program)
 7
 8# 反编译指定函数
 9function = getGlobalFunctions('main')[0]
10results = ifc.decompileFunction(function, 0, ConsoleTaskMonitor())
11
12# 获取伪 C 代码
13c_code = results.getDecompiledFunction().getC()
14print(c_code)

高级反编译配置

 1from ghidra.app.decompiler import DecompileOptions
 2from ghidra.app.decompiler import DecompInterface
 3from ghidra.util.task import ConsoleTaskMonitor
 4
 5options = DecompileOptions()
 6monitor = ConsoleTaskMonitor()
 7ifc = DecompInterface()
 8ifc.setOptions(options)
 9ifc.openProgram(currentProgram)
10
11# 反编译(带超时)
12func = getGlobalFunctions('main')[0]
13res = ifc.decompileFunction(func, 60, monitor)  # 60秒超时
14
15# 获取高级函数对象
16high_func = res.getHighFunction()

获取变量信息

 1from ghidra.app.decompiler import DecompileOptions
 2from ghidra.app.decompiler import DecompInterface
 3from ghidra.util.task import ConsoleTaskMonitor
 4
 5func = getGlobalFunctions("target_func")[0]
 6options = DecompileOptions()
 7monitor = ConsoleTaskMonitor()
 8ifc = DecompInterface()
 9ifc.setOptions(options)
10ifc.openProgram(func.getProgram())
11
12res = ifc.decompileFunction(func, 60, monitor)
13high_func = res.getHighFunction()
14lsm = high_func.getLocalSymbolMap()
15symbols = lsm.getSymbols()
16
17for symbol in symbols:
18    print("Name:", symbol.name)
19    print("Type:", symbol.dataType)
20    print("Address:", symbol.getPCAddress())
21    print("Size:", symbol.size)
22    print("Storage:", symbol.storage)
23    print("Is Parameter:", symbol.parameter)
24    print("Is ReadOnly:", symbol.readOnly)

分析函数调用参数

 1from ghidra.app.decompiler import DecompileOptions
 2from ghidra.app.decompiler import DecompInterface
 3from ghidra.util.task import ConsoleTaskMonitor
 4
 5# 目标调用地址
 6TARGET_ADDR = toAddr(0x00434f6c)
 7
 8options = DecompileOptions()
 9monitor = ConsoleTaskMonitor()
10ifc = DecompInterface()
11ifc.setOptions(options)
12ifc.openProgram(currentProgram)
13
14# 获取包含该地址的函数
15fm = currentProgram.getFunctionManager()
16func = fm.getFunctionContaining(TARGET_ADDR)
17
18# 反编译
19res = ifc.decompileFunction(func, 60, monitor)
20hf = res.getHighFunction()
21
22# 遍历 PCode 操作
23opiter = hf.getPcodeOps(TARGET_ADDR)
24while opiter.hasNext():
25    op = opiter.next()
26    if op.getMnemonic() == "CALL":
27        # 获取调用参数
28        for i in range(1, op.getNumInputs()):
29            arg = op.getInput(i)
30            print("Argument {}: {}".format(i, arg))

优化:复用反编译器实例

为了提高性能,避免每次都重新创建反编译器实例:

 1from ghidra.app.decompiler import DecompInterface, DecompileOptions
 2from ghidra.util.task import ConsoleTaskMonitor
 3
 4class DecompilerCache:
 5    """反编译器缓存管理器"""
 6
 7    def __init__(self, program):
 8        self.program = program
 9        self.ifc = None
10        self.monitor = ConsoleTaskMonitor()
11        self._init_decompiler()
12
13    def _init_decompiler(self):
14        """初始化反编译器(仅执行一次)"""
15        if self.ifc is None:
16            options = DecompileOptions()
17            self.ifc = DecompInterface()
18            self.ifc.setOptions(options)
19            self.ifc.openProgram(self.program)
20            print("Decompiler initialized")
21
22    def decompile(self, func, timeout=60):
23        """反编译函数"""
24        return self.ifc.decompileFunction(func, timeout, self.monitor)
25
26    def get_c_code(self, func):
27        """获取伪 C 代码"""
28        res = self.decompile(func)
29        if res.decompileCompleted():
30            return res.getDecompiledFunction().getC()
31        return None
32
33    def get_high_function(self, func):
34        """获取高级函数对象"""
35        res = self.decompile(func)
36        if res.decompileCompleted():
37            return res.getHighFunction()
38        return None
39
40    def dispose(self):
41        """清理资源"""
42        if self.ifc:
43            self.ifc.dispose()
44            self.ifc = None
45
46# 使用示例:批量反编译多个函数
47cache = DecompilerCache(currentProgram)
48
49try:
50    fm = currentProgram.getFunctionManager()
51    funcs = fm.getFunctions(True)
52
53    for func in funcs:
54        # 复用同一个反编译器实例
55        c_code = cache.get_c_code(func)
56        if c_code:
57            print("Function: {}".format(func.getName()))
58            print(c_code[:200])  # 打印前 200 字符
59            print("-" * 80)
60finally:
61    cache.dispose()

优化:缓存反编译结果

如果需要多次访问相同函数的反编译结果,可以缓存:

 1from ghidra.app.decompiler import DecompInterface, DecompileOptions
 2from ghidra.util.task import ConsoleTaskMonitor
 3
 4class DecompilerWithCache:
 5    """带结果缓存的反编译器"""
 6
 7    def __init__(self, program):
 8        self.program = program
 9        self.ifc = DecompInterface()
10        self.monitor = ConsoleTaskMonitor()
11        self.cache = {}  # 缓存:func_addr -> DecompileResults
12
13        # 初始化反编译器
14        options = DecompileOptions()
15        self.ifc.setOptions(options)
16        self.ifc.openProgram(program)
17
18    def decompile(self, func, use_cache=True):
19        """
20        反编译函数(支持缓存)
21
22        参数:
23            func: Function 对象
24            use_cache: 是否使用缓存(默认 True)
25
26        返回:
27            DecompileResults 对象
28        """
29        func_addr = func.getEntryPoint()
30
31        # 检查缓存
32        if use_cache and func_addr in self.cache:
33            print("Cache hit for function: {}".format(func.getName()))
34            return self.cache[func_addr]
35
36        # 反编译
37        print("Decompiling function: {}".format(func.getName()))
38        res = self.ifc.decompileFunction(func, 60, self.monitor)
39
40        # 存入缓存
41        if use_cache and res.decompileCompleted():
42            self.cache[func_addr] = res
43
44        return res
45
46    def get_c_code(self, func, use_cache=True):
47        """获取伪 C 代码(支持缓存)"""
48        res = self.decompile(func, use_cache)
49        if res.decompileCompleted():
50            return res.getDecompiledFunction().getC()
51        return None
52
53    def clear_cache(self):
54        """清空缓存"""
55        self.cache.clear()
56        print("Cache cleared")
57
58    def dispose(self):
59        """清理资源"""
60        self.clear_cache()
61        if self.ifc:
62            self.ifc.dispose()
63
64# 使用示例
65decompiler = DecompilerWithCache(currentProgram)
66
67try:
68    func = getGlobalFunctions("main")[0]
69
70    # 第一次调用:执行反编译
71    code1 = decompiler.get_c_code(func)
72
73    # 第二次调用:使用缓存(快速)
74    code2 = decompiler.get_c_code(func)
75
76    # 强制重新反编译
77    code3 = decompiler.get_c_code(func, use_cache=False)
78
79finally:
80    decompiler.dispose()

优化:检查函数是否已分析

在反编译前检查函数状态,避免不必要的操作:

 1def is_function_analyzed(func):
 2    """检查函数是否已被分析"""
 3    # 检查函数体是否为空
 4    if func.getBody().isEmpty():
 5        return False
 6
 7    # 检查是否有指令
 8    listing = currentProgram.getListing()
 9    instructions = listing.getInstructions(func.getBody(), True)
10    if not instructions.hasNext():
11        return False
12
13    return True
14
15def decompile_if_needed(ifc, func):
16    """仅在需要时反编译"""
17    if not is_function_analyzed(func):
18        print("Function {} not analyzed, skipping".format(func.getName()))
19        return None
20
21    res = ifc.decompileFunction(func, 60, ConsoleTaskMonitor())
22    if not res.decompileCompleted():
23        print("Decompilation failed for {}".format(func.getName()))
24        return None
25
26    return res
27
28# 使用示例
29ifc = DecompInterface()
30ifc.openProgram(currentProgram)
31
32try:
33    fm = currentProgram.getFunctionManager()
34    for func in fm.getFunctions(True):
35        res = decompile_if_needed(ifc, func)
36        if res:
37            print("Successfully decompiled: {}".format(func.getName()))
38finally:
39    ifc.dispose()

指令与汇编

遍历函数中的所有指令

 1from binascii import hexlify
 2
 3listing = currentProgram.getListing()
 4main_func = getGlobalFunctions("main")[0]
 5addrSet = main_func.getBody()
 6
 7# 获取地址集合中的所有指令
 8instructions = listing.getInstructions(addrSet, True)  # True = 正向
 9
10for instr in instructions:
11    addr = instr.getAddress()
12    mnemonic = instr.getMnemonicString()
13    opcode = hexlify(instr.getBytes()).decode('utf-8')
14
15    print("0x{}: {} ({})".format(addr, mnemonic, opcode))

查找特定指令模式

 1# 查找所有寄存器调用和跳转
 2listing = currentProgram.getListing()
 3func = getGlobalFunctions("target")[0]
 4addrSet = func.getBody()
 5instructions = listing.getInstructions(addrSet, True)
 6
 7for instr in instructions:
 8    mnemonic = instr.getMnemonicString()
 9
10    # 查找 CALL/JMP 到寄存器
11    if mnemonic in ["CALL", "JMP"]:
12        num_operands = instr.getNumOperands()
13        if num_operands > 0:
14            op_type = instr.getOperandType(0)
15            # 检查是否为寄存器操作数
16            if op_type & instr.OP_TYPE_REGISTER:
17                print("Found: {} @ 0x{}".format(instr, instr.getAddress()))

统计指令助记符

 1from collections import Counter
 2
 3listing = currentProgram.getListing()
 4instructions = listing.getInstructions(True)
 5
 6mnemonics = []
 7for instr in instructions:
 8    mnemonics.append(instr.getMnemonicString())
 9
10# 统计出现次数
11counter = Counter(mnemonics)
12for mnemonic, count in counter.most_common(10):
13    print("{}: {}".format(mnemonic, count))

变量与内存

读取内存

 1def getString(addr):
 2    """从内存中读取以 null 结尾的字符串"""
 3    mem = currentProgram.getMemory()
 4    result = ""
 5    while True:
 6        byte = mem.getByte(addr.add(len(result)))
 7        if byte == 0:
 8            return result
 9        result += chr(byte)
10
11# 使用示例
12addr = toAddr(0x00401000)
13string_value = getString(addr)
14print("String at 0x{}: {}".format(addr, string_value))

获取栈变量

 1def get_stack_var_from_varnode(func, varnode):
 2    """
 3    从 Varnode 获取栈变量
 4
 5    参数:
 6        func: Function 对象
 7        varnode: Varnode 或 VarnodeAST 对象
 8
 9    返回:
10        栈变量列表
11    """
12    if varnode.isUnique():
13        # 如果是 unique 空间,需要找到定义
14        high_var = varnode.getHigh()
15        if high_var:
16            varnode = high_var.getRepresentative()
17
18    if varnode.isAddress():
19        addr = varnode.getAddress()
20        offset = addr.getOffset()
21
22        # 获取栈变量
23        stack_vars = func.getAllVariables()
24        results = []
25        for var in stack_vars:
26            if var.isStackVariable():
27                if var.getStackOffset() == offset:
28                    results.append(var)
29        return results
30
31    return []

PCode 操作

PCode 基础

PCode 是 Ghidra 的中间表示(IR),用于表示指令的语义。

 1from ghidra.app.decompiler import DecompInterface
 2from ghidra.util.task import ConsoleTaskMonitor
 3
 4ifc = DecompInterface()
 5ifc.openProgram(currentProgram)
 6
 7func = getGlobalFunctions('target')[0]
 8res = ifc.decompileFunction(func, 60, ConsoleTaskMonitor())
 9high_func = res.getHighFunction()
10
11# 遍历所有 PCode 操作
12opiter = high_func.getPcodeOps()
13while opiter.hasNext():
14    op = opiter.next()
15    mnemonic = op.getMnemonic()
16
17    print("PCode Op: {}".format(mnemonic))
18
19    # 获取输入
20    for i in range(op.getNumInputs()):
21        input_var = op.getInput(i)
22        print("  Input {}: {}".format(i, input_var))
23
24    # 获取输出
25    output = op.getOutput()
26    if output:
27        print("  Output: {}".format(output))

PCode 操作类型

常见的 PCode 操作:

函数模拟(Emulation)

 1from ghidra.app.emulator import EmulatorHelper
 2from ghidra.program.model.symbol import SymbolUtilities
 3
 4def getAddress(offset):
 5    return currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress(offset)
 6
 7def getSymbolAddress(symbolName):
 8    symbol = SymbolUtilities.getLabelOrFunctionSymbol(currentProgram, symbolName, None)
 9    if symbol:
10        return symbol.getAddress()
11    raise Exception("Failed to locate symbol: {}".format(symbolName))
12
13# 创建模拟器
14emuHelper = EmulatorHelper(currentProgram)
15
16# 设置起始地址
17mainFunctionEntry = getSymbolAddress("main")
18mainFunctionEntryLong = int("0x{}".format(mainFunctionEntry), 16)
19emuHelper.writeRegister(emuHelper.getPCRegister(), mainFunctionEntryLong)
20
21# 设置寄存器初始值
22emuHelper.writeRegister("RAX", 0x20)
23emuHelper.writeRegister("RSP", 0x000000002FFF0000)
24emuHelper.writeRegister("RBP", 0x000000002FFF0000)
25
26# 写入内存
27emuHelper.writeMemoryValue(getAddress(0x000000000008C000), 4, 0x99AABBCC)
28emuHelper.writeMemory(getAddress(0x00000000000CF000), b'\x99\xAA\xBB\xCC')
29
30# 单步执行
31while True:
32    executionAddress = emuHelper.getExecutionAddress()
33
34    # 打印当前指令
35    instr = getInstructionAt(executionAddress)
36    print("Address: 0x{} ({})".format(executionAddress, instr))
37
38    # 读取寄存器
39    rax = emuHelper.readRegister("RAX")
40    print("  RAX = {:#018x}".format(rax))
41
42    # 执行一步
43    success = emuHelper.step(monitor)
44    if not success:
45        lastError = emuHelper.getLastError()
46        print("Emulation Error: '{}'".format(lastError))
47        break
48
49    # 检查终止条件
50    if executionAddress == getAddress(0x0):
51        break
52
53# 清理
54emuHelper.dispose()

交叉引用

获取引用到某地址的所有位置

 1target_addr = toAddr(0x00401000)
 2references = getReferencesTo(target_addr)
 3
 4for xref in references:
 5    from_addr = xref.getFromAddress()
 6    to_addr = xref.getToAddress()
 7    ref_type = xref.getReferenceType()
 8
 9    print("From: 0x{} To: 0x{} Type: {}".format(
10        from_addr, to_addr, ref_type
11    ))

获取从某地址引用的所有位置

1source_addr = toAddr(0x00401000)
2references = getReferencesFrom(source_addr)
3
4for xref in references:
5    print("Reference to: 0x{}".format(xref.getToAddress()))

查找函数调用者

 1def get_callers(target_func):
 2    """获取调用目标函数的所有函数"""
 3    entry_point = target_func.getEntryPoint()
 4    xrefs = getReferencesTo(entry_point)
 5
 6    fm = currentProgram.getFunctionManager()
 7    callers = []
 8
 9    for xref in xrefs:
10        from_addr = xref.getFromAddress()
11        caller = fm.getFunctionContaining(from_addr)
12        if caller and caller not in callers:
13            callers.append(caller)
14
15    return callers
16
17# 使用示例
18target = getGlobalFunctions("system")[0]
19callers = get_callers(target)
20
21for caller in callers:
22    print("Caller: {} @ 0x{}".format(caller.getName(), caller.getEntryPoint()))

常用工具函数

地址转换

1# 从偏移量创建地址
2def getAddress(offset):
3    return currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress(offset)
4
5# 使用 toAddr(Ghidra 内置)
6addr = toAddr(0x00401000)
7
8# 从字符串解析地址
9addr = currentProgram.getAddressFactory().getAddress("00401000")

符号查找

 1from ghidra.program.model.symbol import SymbolUtilities
 2
 3def getSymbolAddress(symbolName):
 4    symbol = SymbolUtilities.getLabelOrFunctionSymbol(
 5        currentProgram, symbolName, None
 6    )
 7    if symbol:
 8        return symbol.getAddress()
 9    return None
10
11# 使用示例
12main_addr = getSymbolAddress("main")

批量函数重命名

 1from ghidra.app.decompiler import DecompileOptions
 2from ghidra.app.decompiler import DecompInterface
 3from ghidra.util.task import ConsoleTaskMonitor
 4from ghidra.program.model.symbol import SourceType
 5
 6def getString(addr):
 7    mem = currentProgram.getMemory()
 8    result = ""
 9    while True:
10        byte = mem.getByte(addr.add(len(result)))
11        if byte == 0:
12            return result
13        result += chr(byte)
14
15# 设置反编译器
16options = DecompileOptions()
17monitor = ConsoleTaskMonitor()
18ifc = DecompInterface()
19ifc.setOptions(options)
20ifc.openProgram(currentProgram)
21
22# 找到 register_function
23fm = currentProgram.getFunctionManager()
24register_function = None
25for func in fm.getFunctions(True):
26    if func.getName() == "register_function":
27        register_function = func
28        break
29
30# 获取所有调用者
31entry_point = register_function.getEntryPoint()
32xrefs = getReferencesTo(entry_point)
33callers = []
34for xref in xrefs:
35    from_addr = xref.getFromAddress()
36    caller = fm.getFunctionContaining(from_addr)
37    if caller and caller not in callers:
38        callers.append(caller)
39
40# 处理每个调用者
41for caller in callers:
42    if not caller:
43        continue
44
45    res = ifc.decompileFunction(caller, 60, monitor)
46    hf = res.getHighFunction()
47    opiter = hf.getPcodeOps()
48
49    while opiter.hasNext():
50        op = opiter.next()
51        if op.getMnemonic() == "CALL":
52            call_target = op.getInput(0)
53            if call_target.getAddress() == entry_point:
54                # 提取字符串参数和函数地址参数
55                func_name_varnode = op.getInput(2)
56                func_addr_varnode = op.getInput(3)
57
58                # 获取字符串
59                func_name_def = func_name_varnode.getDef()
60                func_name_addr = toAddr(func_name_def.getInput(0).getOffset())
61                func_name = getString(func_name_addr)
62
63                # 获取函数地址
64                func_addr = toAddr(func_addr_varnode.getDef().getInput(1).getOffset())
65                func_obj = fm.getFunctionAt(func_addr)
66
67                # 重命名
68                if func_obj:
69                    func_obj.setName(func_name, SourceType.USER_DEFINED)
70                    print("Renamed function @ 0x{} to '{}'".format(func_addr, func_name))

最佳实践

1. 错误处理

 1try:
 2    func = getGlobalFunctions("target")[0]
 3except IndexError:
 4    print("Function 'target' not found")
 5    exit()
 6
 7# 检查 None
 8addr = toAddr(0x00401000)
 9func = fm.getFunctionAt(addr)
10if func is None:
11    print("No function at address")

2. 资源清理

 1# 反编译器使用后清理
 2ifc = DecompInterface()
 3ifc.openProgram(currentProgram)
 4try:
 5    # ... 使用反编译器
 6    pass
 7finally:
 8    ifc.dispose()
 9
10# 模拟器使用后清理
11emuHelper = EmulatorHelper(currentProgram)
12try:
13    # ... 使用模拟器
14    pass
15finally:
16    emuHelper.dispose()

3. 性能优化

1# 使用 FunctionManager 而不是重复调用 getGlobalFunctions
2fm = currentProgram.getFunctionManager()
3funcs = fm.getFunctions(True)
4
5# 缓存常用对象
6listing = currentProgram.getListing()
7memory = currentProgram.getMemory()
8addr_factory = currentProgram.getAddressFactory()

4. 事务管理(修改程序时)

 1from ghidra.program.model.symbol import SourceType
 2
 3# 开始事务
 4txId = currentProgram.startTransaction("Rename Functions")
 5try:
 6    func = getGlobalFunctions("old_name")[0]
 7    func.setName("new_name", SourceType.USER_DEFINED)
 8
 9    # 提交事务
10    currentProgram.endTransaction(txId, True)
11except Exception as e:
12    # 回滚事务
13    currentProgram.endTransaction(txId, False)
14    print("Error: {}".format(e))

常见问题

Q: 如何区分 getFunctionAt 和 getFunctionContaining?

A:

推荐使用 getFunctionContaining

Q: 如何处理多个同名函数?

A: Ghidra 允许函数重载,所以 getGlobalFunctions(name) 返回列表:

1funcs = getGlobalFunctions("main")
2if len(funcs) > 1:
3    print("Multiple functions found, selecting first")
4func = funcs[0]

Q: PCode 的 unique 空间是什么?

A: Unique 空间是临时存储空间,用于中间计算结果。要获取实际变量,需要追踪定义:

1if varnode.isUnique():
2    high_var = varnode.getHigh()
3    if high_var:
4        varnode = high_var.getRepresentative()

Q: 如何安全地修改程序?

A: 始终使用事务(Transaction):

1txId = currentProgram.startTransaction("Description")
2try:
3    # 修改操作
4    currentProgram.endTransaction(txId, True)
5except:
6    currentProgram.endTransaction(txId, False)

参考资源


版本信息

本文档基于 Ghidra 10.2+ API 编写。不同版本的 API 可能有所差异。