dod-cyber-crime-center/Dragodis
GitHub: dod-cyber-crime-center/Dragodis
Dragodis 是一个 Python 框架,提供统一的反汇编器 API,让逆向分析脚本可以在 IDA Pro、Ghidra 和 Vivisect 之间通用运行。
Stars: 57 | Forks: 17
# Dragodis
Dragodis 是一个 Python 框架,允许创建
通用的反汇编脚本。Dragodis 目前支持以下
反汇编器:
- [Ghidra](https://ghidra-sre.org)
- [IDA Pro](https://hex-rays.com)
- [Vivisect](https://vivisect.readthedocs.io)
`Dragodis` 这个名字是由 `Dragoman`(专业的
口译译员)和 `Disassembler`(反汇编器)组合而成的。
创建 Dragodis 是为了满足在
Ghidra 中运行 IDA 脚本的需求。许多用于自动化分析的脚本在大多数反汇编器中都能很好地工作。
消除在自动化分析中使用需要付费许可证的反汇编器的需求是我们的理想目标。
通用反汇编器 API 还有其他好处。许多逆向
工程师都有自己偏好的反汇编器。Dragodis 允许在不同反汇编器用户之间简单地
共享脚本。Dragodis 还致力于提供比其他反汇编器所提供的更清晰、更易于使用的 API。
## 安装
使用 pip 安装 dragodis:
```
pip install dragodis
```
然后按照[此处](./docs/install.md)的说明安装后端反汇编器。
## 使用方法
要使用 Dragodis,只需将输入二进制文件的路径传入 `IDA` 或 `Ghidra` 类。
这将创建一个反汇编器实例,并对给定的输入文件进行分析。
```
import dragodis
with dragodis.Ghidra(r"C:\strings.exe") as ghidra:
print(ghidra.get_dword(0x401000))
```
```
import dragodis
with dragodis.IDA(r"C:\strings.exe") as ida:
print(ida.get_dword(0x401000))
```
也可以在不使用上下文管理器的情况下,通过使用 `start()` 和 `stop()` 函数来运行反汇编器。
```
import dragodis
ghidra = dragodis.Ghidra(r"C:\strings.exe")
ghidra.start()
ghidra.get_dword(0x401000)
ghidra.stop()
```
或者,你可以通过在 `disassembler` 参数中提供反汇编器名称,或设置 `DRAGODIS_DISASSEMBLER`
环境变量,使用 `open_program()` 更动态地选择反汇编器。
```
import dragodis
with dragodis.open_program(r"C:\strings.exe", disassembler="ida") as ida:
print(ida.get_dword(0x401000))
```
强烈建议使用 `DRAGODIS_DISASSEMBLER` 环境变量,以确保你的脚本
无需任何修改即可交叉兼容。同时,这也赋予用户选择
他们想要使用的反汇编器的权力。
```
A "NotInstalledError" will be thrown if the disassembler chosen is not properly installed.
```
```
import os
os.environ["DRAGODIS_DISASSEMBLER"] = "ida"
import dragodis
with dragodis.open_program(r"C:\strings.exe") as dis:
print(f"Disassembler used: {dis.name}")
print(dis.get_dword(0x401000))
```
如果你本地处于反汇编器的解释器中(IDA 的输出窗口或 Ghidra 的 pyhidraw 解释器),
那么你可以通过直接访问该对象来初始化反汇编器对象:
```
# 如果在 IDA 中
import dragodis
dis = dragodis.IDA()
# 如果在 Ghidra 中
import dragodis
dis = dragodis.Ghidra()
```
我们还可以在反汇编器本地使用 `open_program()` 函数直接调用脚本。
发生这种情况时,提供的输入文件路径必须与反汇编器检测到的输入文件路径相匹配。
### 指定处理器类型
可以在初始化 `Disassembler` 对象时或通过 `open_program()` 指定处理器类型。
这在加载 shellcode 时非常有用。
在支持任何后端反汇编器的情况下使用 `open_program()` 时,请使用 `dragodis.PROCESSOR_*` 标志,该标志将转换
为相应反汇编器的合理默认值。
```
import dragodis
with dragodis.open_program(r"C:\input.exe", processor=dragodis.PROCESSOR_ARM) as dis:
...
```
如果使用特定的反汇编器,则可以传入该反汇编器支持的任何选项。
(请查阅相应反汇编器的文档以了解如何格式化参数。)
```
# IDA
import dragodis
ida = dragodis.IDA(r"C:\input", processor="arm:ARMv7-M")
# Ghidra
import dragodis
ghidra = dragodis.Ghidra(r"C:\input", processor="ARM:LE:32:v7")
# Vivisect
import dragodis
vivisect = dragodis.Vivisect(r"C:\input", processor="arm")
```
或者,我们可以使用带有后端前缀的参数为反汇编器自动选择处理器。
```
import dragodis
# 为特定 disassembler 覆盖 processor spec。
# (例如,如果使用 Ghidra backend,请选择“ARM:LE:32:v7”。)
with dragodis.open_program(r"C:\input", processor=dragodis.PROCESSOR_ARM, ghidra_processor="ARM:LE:32:v7") as dis:
...
# 为每个 disassembler 覆盖 processor spec。
processor = dict(
ida_processor="arm:ARMv7-M",
ghidra_processor="ARM:LE:32:v7",
vivisect_processor="arm",
)
with dragodis.open_program(r"C:\input", **processor) as dis:
...
```
### 指定文件类型
可以在初始化 `Disassembler` 对象时或通过 `open_program()` 指定文件类型。
在支持任何后端反汇编器的情况下使用 `open_program()` 时,请使用 `dragodis.FILETYPE_*` 标志,该标志将转换
为相应反汇编器的合理默认值。
```
import dragodis
with dragodis.open_program(r"C:\input.exe", filetype=dragodis.FILETYPE_PE) as dis:
...
```
如果使用特定的反汇编器,则可以传入该反汇编器支持的任何选项。
(请查阅相应反汇编器的文档以了解如何格式化参数。)
```
# IDA
import dragodis
ida = dragodis.IDA(r"C:\input", filetype="Portable")
# Ghidra
import dragodis
ghidra = dragodis.Ghidra(r"C:\input", filetype="ghidra.app.util.opinion.PeLoader")
# Vivisect
import dragodis
vivisect = dragodis.Vivisect(r"C:\input", filetype="pe")
```
或者,我们可以使用带有后端前缀的参数为反汇编器自动选择正确的文件类型。
```
import dragodis
filetype = dict(
ida_filetype="Portable",
ghidra_filetype="ghidra.app.util.opinion.PeLoader",
vivisect_filetype="pe",
)
with dragodis.open_program(r"C:\input", **filetype) as dis:
...
```
## 跳过自动分析
在底层反汇编器启动期间,可以选择跳过分析。
这可以在初始化 `Disassembler` 对象时或通过 `open_program()` 进行设置。
如果禁用了分析,用户需要自行执行自定义分析或显式调用 `analyze()`。
```
import dragodis
with dragodis.open_program(r"C:\input", analyze=False) as dis:
# do things before analysis
dis.analyze()
```
## 配置
所有选项都可以通过 [settings.toml](src/dragodis/config/settings.toml) 文件进行配置。
可以修改此文件以配置 Dragodis 和底层反汇编器。
Dragodis 会在 `~/.config/dragodis/settings.toml` 或 `%LOCALAPPDATA%\dc3\dragodis\settings.toml`
中查找用户定义的配置文件以覆盖默认设置。
运行以下命令以查看当前配置:
```
python -m dragodis.config list
```
运行以下命令在文本编辑器中编辑配置。
(这会将默认配置复制到用户目录中)
```
python -m dragodis.config edit
```
要在不编辑的情况下创建新的用户配置文件:
```
python -m dragodis.config create
```
我们使用 [Dynaconf](https://dynaconf.com),它提供了便利功能,例如使用以 `DRAGODIS_` 为前缀的
环境变量来设置配置。
例如,设置到 IDA 远程服务器的连接重试次数:
```
export DRAGODIS_IDA__RETRY_COUNT=50 # '__' to access nested field.
```
注意:大多数这些配置也可以在 `open_program()` 调用期间提供。
此处提供的选项将覆盖设置文件中的配置。
## 反汇编器 API 对照表
作为参考,下表提供了 Dragodis 和每个受支持的
反汇编器之间大致等效的通用 API 调用的映射。
*注意:这些是等效反汇编器 API 函数之间的粗略转换,旨在帮助您从
使用 IDA 或 Ghidra 过渡到使用 Dragodis。
它们并不总是直接对应的。
为简洁起见,此处省略了一些细节和结果上的差异。请参阅源代码以获取更多信息。*
## 基础操作
| Dragodis* | IDA | Ghidra | Vivisect** |
|--------------------------------------|--------------------------------------------------------|----------------------------------------------------------------------------------|---------------------------------------------------------|
| dis.processor_name | ida_ida.inf_get_procname() | currentProgram.getLanguage().getProcessor() | vw.arch.getArchName() |
| dis.compiler_name | ida_typeinf.get_compiler_name(ida_ida.inf_get_cc_id()) | currentProgram.getCompiler() | *不适用* |
| dis.bit_size | ida_ida.inf_get_app_bitness() | currentProgram.getDefaultPointerSize() * 8 | vw.workspace.getPointerSize() * 8 |
| dis.is_big_endian | ida_ida.inf_is_be() | currentProgram.getLanguage().isBigEndian() | vw.bigend |
| dis.min_address | ida_ida.inf_get_min_ea() | currentProgram.getMinAddress() | min(addr for addr, *_ in vw.getSegments()) |
| dis.max_address | ida_ida.inf_get_max_ea() | currentProgram.getMaxAddress() | max(addr + size for addr, size, *_ in vw.getSegments()) |
| dis.base_address | ida_nalt.get_imagebase() | currentProgram.getImageBase() | vw.getFileMeta(filename, "imagebase") |
| dis.get_virtual_address(file_offset) | ida_loader.get_fileregion_ea(file_offset) | currentProgram.getMemory().locateAddressesForFileOffset(file_offset) | *复杂操作:请参见源代码* |
| dis.get_file_offset(address) | ida_loader.get_fileregion_offset(address) | currentProgram.getMemory().getAddressSourceInfo(toAddr(address)).getFileOffset() | *复杂操作:请参见源代码* |
| dis.entry_point | ida_ida.inf_get_start_ip() | *(名称为 "entry" 或 "_start" 的导出)* | vw.getEntryPoints()\[0\] |
### 数据
| Dragodis* | IDA | Ghidra | Vivisect** |
|-----------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------|
| dis.get_byte(address) | ida_bytes.get_wide_byte(address) | getByte(toAddr(address)) | vw.readMemory(addr, 1) |
| dis.get_bytes(address, size) | ida_bytes.get_bytes(address, size) | getBytes(toAddr(address), size) | vw.readMemory(addr, size) |
| dis.find_bytes(b"\xde\xad\xbe\xef", start) | idc.find_binary(start, idc.SEARCH_DOWN, "DE AD BE EF") | currentProgram.getMemory().findBytes(start, b"\xde\xad\xbe\xef", None, True, monitor) | vw.searchMemory(b"\xde\xad\xbe\xef") |
| dis.find_bytes(b"\xde\xad\xbe\xef", start, reverse=True) | idc.find_binary(start, idc.SEARCH_UP, "DE AD BE EF") | currentProgram.getMemory().findBytes(start, b"\xde\xad\xbe\xef", None, False, monitor) | *不支持* |
| dis.get_word(address) | ida_bytes.get_wide_word(address) | getShort(toAddr(address)) | *不适用* |
| dis.get_dword(address) | ida_bytes.get_wide_dword(address) | getInt(toAddr(address)) | *不适用* |
| dis.get_qword(address) | ida_bytes.get_qword(address) | getLong(toAddr(address)) | *不适用* |
| dis.get_string_bytes(address) | idc.get_strlit_contents(address) | *复杂操作:请参见源代码* | vw.readMemString(address) |
| dis.lines(start_address, end_address)
dis.line_addresses(start_address, end_address) | idautils.Heads(start_address, end_address) | currentProgram.getListing().getCodeUnits(address_set, True) | *不适用* | | line = dis.get_line(address) | *不适用* | code_unit = currentProgram.getListing().getCodeUnitContaining(toAddr(address)) | vw.getLocation(address) | | line.address
dis.get_line_address(address) | idc.get_item_head(address) | code_unit.getAddress() | vw.getLocation(address)\[0] | | line.name
dis.get_name(address) | ida_name.get_name(address) | code_unit.getLabel() | vw.getName(address) | | line.name = "new_name" | ida_name.set_name(address, "new_name") | symbol = code_unit.getPrimarySymbol(); symbol.setName("new_name", symbol.getSource()) | vw.makeName(address, "new_name") | | line.size | ida_bytes.get_item_size(address) | code_unit.getLength() | vw.getLocation(address)\[1] | | line.type | ida_bytes.get_flags(address) | code_unit.getClass()
code_unit.getDataType().getName() | vw.getLocation(address)\[2] | | line.type = LineType.dword | idc.create_dword(address) | createDWord(address) | vw.makeNumber(address, 4) | | line.data | ida_bytes.get_bytes(address, ida_bytes.get_item_size(address)) | code_unit.getBytes() | vw.readMemory(*vw.getLocation(address)\[:2]) | | line.data = b"new data" | ida_bytes.patch_bytes(address, b"new data") | setBytes(code_unit.getAddress(), b"new data") | vw.writeMemory(address, b"new_data") | | line.get_comment()
dis.get_comment(address) | ida_bytes.get_cmt(address, 0) | code_unit.getComment(0) | vw.getComment(address) | | line.set_comment("new comment") | ida_bytes.set_cmt(address, "new comment", 0) | code_unit.setComment(0, "new comment") | vw.setComment(address, "new comment") | | line.next
dis.next_line_address(address) | idc.next_head(address) | currentProgram.getListing().getCodeUnitAfter(code_unit.getAddress()) | *不适用* | | line.prev
dis.prev_line_address(address) | idc.prev_head(address) | currentProgram.getListing().getCodeUnitBefore(code_unit.getAddress()) | *不适用* | | line.undefine() | ida_bytes.del_items(address) | clearListing(code_unit.getAddress()) | vw.delLocation(address) | | line.value | ida_bytes.get_wide_byte(address)
ida_bytes.get_wide_word(address)
*等等* | code_unit.getValue() | vw.readMemValue(address, size) | | line.value = new_value | ida_bytes.patch_byte(address, new_value)
ida_bytes.patch_word(address, new_value)
ida_bytes.patch_dword(address, new_value)
*等等* | setByte(code_unit.getAddress(), new_value)
setShort(code_unit.getAddress(), new_valuebr>setInt(code_unit.getAddress(), new_value)
*等等* | vw.writeMemValue(address, new_value, size) | | data_type = dis.get_data_type("dword") | data_type = ida_typeinf.tinfo_t(); data_type.get_named_type(ida_typeinf.get_idati(), "dword") | data_type = DataTypeParser(None, DataTypeParser.AllowedDataTypes.valueOf("ALL")).parse("dword") | *不适用* | | data_type.name | *不适用* | data_type.getName() | *不适用* | | data_type.size | ida_bytes.get_data_elsize(address, ida_bytes.get_flags(address) & ida_bytes.DT_TYPE) | data_type.getLength() | *不适用* | | dis.undefine(start, end) | ida_bytes.del_items(start, ida_bytes.DELIT_SIMPLE, end - start) | clearListing(toAddr(start), toAddr(end)) | *不适用* | | dis.set_bytes(address, b"new data") | ida_bytes.patch_bytes(address, b"new_data") | currentProgram.getMemory().setBytes(address, b"new data") | vw.writeMemory(address, b"new data") | ### 交叉引用 | Dragodis* | IDA | Ghidra | Vivisect** | |----------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------| | dis.references_from(address)
dis.get_line(address).references_from
dis.get_function(address).references_from() | idautils.XrefsFrom(address) | getReferencesFrom(toAddr(address)) | vw.getXrefsFrom(address) | | dis.references_to(address)
dis.get_line(address).references_to
dis.get_function(address).references_to() | idautils.XrefsTo(address) | getReferencesTo(toAddr(address)) | vw.getXrefsTo(address) | | ref.from_address | ref.frm | ref.getFromAddress() | ref\[0] | | ref.to_address | ref.to | ref.getToAddress() | ref\[1] | | ref.type | ref.type | ref.getReferenceType() | ref\[2] | | ref.is_code | ref.iscode | not ref.getReferenceType().isData() | ref\[2].rtype == REF_CODE | | ref.is_data | not ref.iscode | ref.getReferenceType().isData() | ref\[2].rtype == REF_DATA | | dis.create_reference(from_address, to_address, dragodis.ReferenceType.*) | ida_xref.add_cref(from_address, to_address, idc.fl_*)
ida_xref.add_dref(from_address, to_address, idc.dr_*) | currentProgram.getReferenceManager().addMemoryReference(toAddr(from_address), toAddr(to_address), RefType.*, SourceType.USER_DEFINED, 0) | vw.addXref(from_address, to_address, rtype, rflags) | ### 导入/导出 | Dragodis* | IDA | Ghidra | Vivisect** | |-------------------------|----------------------------------------------------------------------------------------------|-----------------------------------------------------------------|---------------------------------| | dis.imports() | \[ida_nalt.enum_import_names(i, callback) for i in range(ida_nalt.get_import_module_qty())\] | currentProgram.getSymbolTable().getExternalSymbols() | vw.getImports() | | dis.exports() | \[ida_entry.get_entry_ordinal(i) for i in range(ida_entry.get_entry_qty())\] | currentProgram.getSymbolTable().getExternalEntryPointIterator() | vw.getExports() | | import_.address | *在回调中返回* | symbol.getAddress() | import_\[0] | | import_.name | *在回调中返回* | symbol.getName() | import_\[3].partition(".")\[-1] | | import_.namespace | ida_nalt.get_import_module_name(i) | symbol.getParentSymbol().getName() | import_\[3].partition(".")\[0] | | import_.references_to() | idautils.XrefsTo(address) | symbol.getReferences() | vw.getXrefsTo(import_\[0]) | | export.address | ida_entry.get_entry(ordinal) | symbol.getAddress() | export\[0] | | export.name | ida_entry.get_entry_name(ordinal) | symbol.getName() | export\[2] | | export.references_to() | idautils.XrefsTo(ida_entry.get_entry(ordinal)) | symbol.getReferences() | vw.getXrefsTo(export\[0]) | ### 函数 | Dragodis* | IDA | Ghidra | Vivisect** | |-------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------| | dis.functions() | idautils.Functions() | currentProgram.getListing().getFunctions(True) | vw.getFunctions() | | func = dis.get_function(address) | func = ida_funcs.get_func(address) | func = getFunctionContaining(toAddr(address)) | func_addr = vw.getFunction(address) | | func.start | func.start_ea | func.getEntryPoint() | func_addr | | func.end | func.end_ea | func.getBody().getMaxAddress() | func_addr + vw.getFunctionMeta(func_addr, "Size") | | func.name
dis.get_name(address) | ida_funcs.get_func_name(address) | func.getName() | vw.getName(func_addr) | | func.name = "new_name" | ida_name.set_name(address, "new_name") | func.setName("new_name", SourceType.USER_DEFINED) | vw.makeName(func_addr, "new_name") | | func.get_comment() | ida_funcs.get_func_cmt(func, 0) | func.getComment() | vw.getComment(func_addr) | | func.set_comment("new comment") | ida_funcs.set_func_cmt(func, "new comment", 0) | func.setComment("new comment") | vw.setComment(func_addr, "new comment") | | dis.get_flowchart(address)
func.flowchart | ida_gdl.FlowChart(func) | BasicBlockModel(currentProgram).getCodeBlocksContaining(func.getBody(), monitor) | vw.getFunctionGraph(func_addr) | | func.stack_frame | ida_frame.get_frame(func) | func.getStackFrame() | vw.getFunctionLocals(func_addr) | | dis.get_function_signature(address)
func.signature | tif = ida_typeinf.tinfo_t()
ida_nalt.get_tinfo(tif, address)
func_type_data = ida_typeinf.func_type_data_t()
tif.get_func_details(func_type_data) | func.getSignature() | vw.getFunctionApi(func_addr) | | func = dis.create_function(start, end) | func = ida_funcs.add_func(start, end) | func = currentProgram.getFunctionManager().createFunction(None, toAddr(start), AddressSet(toAddr(start), toAddr(end)), SourceType.USER_DEFINED) | vw.makeFunction(start, meta={"Size": size}) | | func = dis.create_function(start) | func = ida_funcs.add_func(start) | func = CreateFunctionCmd(toAddr(start), True).applyTo(currentProgram).getFunction() | vw.makeFunction(start) | | func.undefine() | ida_funcs.del_func(start) | DeleteFunctionCmd(func.getEntryPoint(), True).applyTo(currentProgram) | vw.delFunction(func_addr) | ### 指令 | Dragodis* | IDA | Ghidra | Vivisect** | |--------------------------------------------|-----------------------------------------------------------|------------------------------------------------------------------------------------------------------|--------------------------------| | insn = dis.get_instruction(address) | insn = ida_ua.insn_t(); ida_ua.decode_insn(insn, address) | insn = currentProgram.getListing().getCodeUnitAt(toAddr(address)) | insn = vw.parseOpcode(address) | | insn.is_call | ida_idp.is_call_insn(insn) | insn.getFlowType().isCall() | insn.iflags & envi.IF_CALL | | insn.is_jump | *复杂操作:请参见源代码* | insn.getFlowType().isJump() | insn.iflags & envi.IF_BRANCH | | insn.is_return | ida_idp.is_ret_insn(insn) | insn.getFlowType().isTerminal() | insn.iflags & envi.IF_RET | | insn.mnemonic
dis.get_mnemonic(address) | ida_ua.ua_mnem(address) | insn.getMnemonicString() | insn.mnem | | insn.text | idc.GetDisasm(address) | str(insn) | str(insn) | | insn.operands | insn.ops | *不适用:请参见操作数部分* | insn.getOperands() | | insn.stack_depth | idc.get_spd(address) | CallDepthChangeInfo(currentProgram.getListing().getFunctionContaining(insn.getAddress())).getDepth() | *复杂操作:请参见源代码* | | insn.stack_delta | idc.get_sp_delta(address) | *复杂操作:请参见源代码* | *复杂操作:请参见源代码* | ### 操作数 *`insn` 的获取方式如上所述* | Dragodis* | IDA | Ghidra | Vivisect** | |-------------------------------------------------------------------------------|---------------------------------------------------------------------|-------------------------------|---------------------------------------| | operand = dis.get_operand(address, index)
operand = insn.operands\[index\] | operand = insn.ops\[index\] | *不适用* | operand = insn.getOperands()\[index\] | | operand.type
dis.get_operand_type(address, index) | idc.get_operand_type(address, index) | insn.getOperandType(index) | operand.\_\_class\_\_ | | operand.width | ida_ua.get_dtype_size(operand.dtype) | *复杂操作:请参见源代码* | operand.tsize | | operand.value
dis.get_operand_value(address, index) | *(取决于类型)*
operand.addr
operand.reg
operand.value | insn.getOpObjects(index) | operand.getOperValue() | | *(phrase 操作数)*
operand.value.base | operand.reg
ida_intel.x86_base_reg(insn, operand) | insn.getOpObjects(index)\[0\] | operand.reg | | *(phrase 操作数)*
operand.value.index | ida_intel.x86_index_reg(insn, operand) | insn.getOpObjects(index)\[1\] | operand.index | | *(phrase 操作数)*
operand.value.scale | 1 << ida_intel.sib_scale(operand) | insn.getOpObjects(index)\[2\] | operand.scale | | *(phrase 操作数)*
operand.value.offset | operand.addr
idc.get_operand_value(address, index) | insn.getOpObjects(index)\[3\] | operand.disp | | *(寄存器操作数)*
operand.value | operand.reg
idc.get_operand_value(address, index) | insn.getOpObjects(index)\[0\] | operand.reg.reg | | *(立即数操作数)*
operand.value | operand.value
idc.get_operand_value(address, index) | insn.getOpObjects(index)\[0\] | operand.getOperValue() | | *(内存引用操作数)*
operand.value | operand.addr
idc.get_operand_value(address, index) | insn.getOpObjects(index)\[0\] | operand.getOperValue() | ### 寄存器 | Dragodis* | IDA | Ghidra | Vivisect** | |------------------------------------|--------------------------------------------------------------------------|----------------------------------------------|------------------------------------------------------------| | register = dis.get_register("eax") | register = ida_idp.reg_info_t(); ida_idp.parse_reg_name(register, "eax") | register = currentProgram.getRegister("eax") | register = vw.arch.archGetRegCtx().getRegisterIndex("eax") | | register.name | ida_idp.get_reg_name(register.reg, register.size) | register.getName() | vw.arch.archGetRegCtx().getRegisterName(register) | | register.bit_width | register.size * 8 | register.getBitLength() | vw.arch.archGetCtx().getRegisterWidth(register) | ### 段 | Dragodis* | IDA | Ghidra | Vivisect** | |-----------------------------------------------------------------------|---------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------| | dis.segments() | \[ida_segment.getnseg(n) for n in range(ida_segment.get_segm_qty())\] | currentProgram.getMemory().getBlocks() | vw.getSegments() | | segment = dis.get_segment(name)
segment = dis.get_segment(address) | segment = ida_segment.get_segm_by_name(name)
segment = ida_segment.getseg(address) | memory_block = currentProgram.getMemory().getBlock(name)
memory_block = currentProgram.getMemory().getBlock(toAddr(address)) | addr, size, name, _ = vw.getSegment(address) | | segment.name | ida_segment.get_segm_name(segment) | memory_block.getName() | name | | segment.start | segment.start_ea | memory_block.getStart() | addr | | segment.end | segment.end_ea | memory_block.getEnd() | addr + size | | segment.initialized | ida_bytes.is_loaded(segment.start_ea) | memory_block.isInitialized() | bool(vw.getMemoryMap(addr)) | | segment.bit_size | segment.abits() | memory_block.getStart().getSize() | *不适用* | | segment.permissions | segment.perm | memory_block.isRead()
memory_block.isWrite()
memory_block.isExecute()
memory_block.isVolatile() | _, _, flags, _ = vw.getMemoryMap(addr) | | dis.create_segment(".new_seg", 0x1234, 256) | ida_segment.add_segm(0, 0x1234, 0x1334, ".new_seg", "XTRN") | currentProgram.getMemory().createUninitializedBlock(".new_seg", toAddr(0x1234), 256, False) | vw.addSegment(0x1234, 256, ".new_seg", filename) | ### 字符串 | Dragodis* | IDA | Ghidra | Vivisect** | |---------------------------|-------------------------------------------------------------------|---------------------------------------|---------------------------------------------------------------------------| | dis.strings(min_length=5) | finder = idautils.Strings(); finder.setup(minlen=5); list(finder) | findStrings(None, 5, 1, False, True) | vw.getLocations(vivisect.LOC_STRINGS) + vw.getLocations(vivisect.LOC_UNI) | \* dragodis 列中的 `dis` 表示从 `dragodis.open_program()` 获取的已打开的反汇编器对象 \** Vivisect 列中的 `vw` 表示由 `vivisect.VivWorkspace()` 创建的工作区
dis.line_addresses(start_address, end_address) | idautils.Heads(start_address, end_address) | currentProgram.getListing().getCodeUnits(address_set, True) | *不适用* | | line = dis.get_line(address) | *不适用* | code_unit = currentProgram.getListing().getCodeUnitContaining(toAddr(address)) | vw.getLocation(address) | | line.address
dis.get_line_address(address) | idc.get_item_head(address) | code_unit.getAddress() | vw.getLocation(address)\[0] | | line.name
dis.get_name(address) | ida_name.get_name(address) | code_unit.getLabel() | vw.getName(address) | | line.name = "new_name" | ida_name.set_name(address, "new_name") | symbol = code_unit.getPrimarySymbol(); symbol.setName("new_name", symbol.getSource()) | vw.makeName(address, "new_name") | | line.size | ida_bytes.get_item_size(address) | code_unit.getLength() | vw.getLocation(address)\[1] | | line.type | ida_bytes.get_flags(address) | code_unit.getClass()
code_unit.getDataType().getName() | vw.getLocation(address)\[2] | | line.type = LineType.dword | idc.create_dword(address) | createDWord(address) | vw.makeNumber(address, 4) | | line.data | ida_bytes.get_bytes(address, ida_bytes.get_item_size(address)) | code_unit.getBytes() | vw.readMemory(*vw.getLocation(address)\[:2]) | | line.data = b"new data" | ida_bytes.patch_bytes(address, b"new data") | setBytes(code_unit.getAddress(), b"new data") | vw.writeMemory(address, b"new_data") | | line.get_comment()
dis.get_comment(address) | ida_bytes.get_cmt(address, 0) | code_unit.getComment(0) | vw.getComment(address) | | line.set_comment("new comment") | ida_bytes.set_cmt(address, "new comment", 0) | code_unit.setComment(0, "new comment") | vw.setComment(address, "new comment") | | line.next
dis.next_line_address(address) | idc.next_head(address) | currentProgram.getListing().getCodeUnitAfter(code_unit.getAddress()) | *不适用* | | line.prev
dis.prev_line_address(address) | idc.prev_head(address) | currentProgram.getListing().getCodeUnitBefore(code_unit.getAddress()) | *不适用* | | line.undefine() | ida_bytes.del_items(address) | clearListing(code_unit.getAddress()) | vw.delLocation(address) | | line.value | ida_bytes.get_wide_byte(address)
ida_bytes.get_wide_word(address)
*等等* | code_unit.getValue() | vw.readMemValue(address, size) | | line.value = new_value | ida_bytes.patch_byte(address, new_value)
ida_bytes.patch_word(address, new_value)
ida_bytes.patch_dword(address, new_value)
*等等* | setByte(code_unit.getAddress(), new_value)
setShort(code_unit.getAddress(), new_valuebr>setInt(code_unit.getAddress(), new_value)
*等等* | vw.writeMemValue(address, new_value, size) | | data_type = dis.get_data_type("dword") | data_type = ida_typeinf.tinfo_t(); data_type.get_named_type(ida_typeinf.get_idati(), "dword") | data_type = DataTypeParser(None, DataTypeParser.AllowedDataTypes.valueOf("ALL")).parse("dword") | *不适用* | | data_type.name | *不适用* | data_type.getName() | *不适用* | | data_type.size | ida_bytes.get_data_elsize(address, ida_bytes.get_flags(address) & ida_bytes.DT_TYPE) | data_type.getLength() | *不适用* | | dis.undefine(start, end) | ida_bytes.del_items(start, ida_bytes.DELIT_SIMPLE, end - start) | clearListing(toAddr(start), toAddr(end)) | *不适用* | | dis.set_bytes(address, b"new data") | ida_bytes.patch_bytes(address, b"new_data") | currentProgram.getMemory().setBytes(address, b"new data") | vw.writeMemory(address, b"new data") | ### 交叉引用 | Dragodis* | IDA | Ghidra | Vivisect** | |----------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------| | dis.references_from(address)
dis.get_line(address).references_from
dis.get_function(address).references_from() | idautils.XrefsFrom(address) | getReferencesFrom(toAddr(address)) | vw.getXrefsFrom(address) | | dis.references_to(address)
dis.get_line(address).references_to
dis.get_function(address).references_to() | idautils.XrefsTo(address) | getReferencesTo(toAddr(address)) | vw.getXrefsTo(address) | | ref.from_address | ref.frm | ref.getFromAddress() | ref\[0] | | ref.to_address | ref.to | ref.getToAddress() | ref\[1] | | ref.type | ref.type | ref.getReferenceType() | ref\[2] | | ref.is_code | ref.iscode | not ref.getReferenceType().isData() | ref\[2].rtype == REF_CODE | | ref.is_data | not ref.iscode | ref.getReferenceType().isData() | ref\[2].rtype == REF_DATA | | dis.create_reference(from_address, to_address, dragodis.ReferenceType.*) | ida_xref.add_cref(from_address, to_address, idc.fl_*)
ida_xref.add_dref(from_address, to_address, idc.dr_*) | currentProgram.getReferenceManager().addMemoryReference(toAddr(from_address), toAddr(to_address), RefType.*, SourceType.USER_DEFINED, 0) | vw.addXref(from_address, to_address, rtype, rflags) | ### 导入/导出 | Dragodis* | IDA | Ghidra | Vivisect** | |-------------------------|----------------------------------------------------------------------------------------------|-----------------------------------------------------------------|---------------------------------| | dis.imports() | \[ida_nalt.enum_import_names(i, callback) for i in range(ida_nalt.get_import_module_qty())\] | currentProgram.getSymbolTable().getExternalSymbols() | vw.getImports() | | dis.exports() | \[ida_entry.get_entry_ordinal(i) for i in range(ida_entry.get_entry_qty())\] | currentProgram.getSymbolTable().getExternalEntryPointIterator() | vw.getExports() | | import_.address | *在回调中返回* | symbol.getAddress() | import_\[0] | | import_.name | *在回调中返回* | symbol.getName() | import_\[3].partition(".")\[-1] | | import_.namespace | ida_nalt.get_import_module_name(i) | symbol.getParentSymbol().getName() | import_\[3].partition(".")\[0] | | import_.references_to() | idautils.XrefsTo(address) | symbol.getReferences() | vw.getXrefsTo(import_\[0]) | | export.address | ida_entry.get_entry(ordinal) | symbol.getAddress() | export\[0] | | export.name | ida_entry.get_entry_name(ordinal) | symbol.getName() | export\[2] | | export.references_to() | idautils.XrefsTo(ida_entry.get_entry(ordinal)) | symbol.getReferences() | vw.getXrefsTo(export\[0]) | ### 函数 | Dragodis* | IDA | Ghidra | Vivisect** | |-------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------| | dis.functions() | idautils.Functions() | currentProgram.getListing().getFunctions(True) | vw.getFunctions() | | func = dis.get_function(address) | func = ida_funcs.get_func(address) | func = getFunctionContaining(toAddr(address)) | func_addr = vw.getFunction(address) | | func.start | func.start_ea | func.getEntryPoint() | func_addr | | func.end | func.end_ea | func.getBody().getMaxAddress() | func_addr + vw.getFunctionMeta(func_addr, "Size") | | func.name
dis.get_name(address) | ida_funcs.get_func_name(address) | func.getName() | vw.getName(func_addr) | | func.name = "new_name" | ida_name.set_name(address, "new_name") | func.setName("new_name", SourceType.USER_DEFINED) | vw.makeName(func_addr, "new_name") | | func.get_comment() | ida_funcs.get_func_cmt(func, 0) | func.getComment() | vw.getComment(func_addr) | | func.set_comment("new comment") | ida_funcs.set_func_cmt(func, "new comment", 0) | func.setComment("new comment") | vw.setComment(func_addr, "new comment") | | dis.get_flowchart(address)
func.flowchart | ida_gdl.FlowChart(func) | BasicBlockModel(currentProgram).getCodeBlocksContaining(func.getBody(), monitor) | vw.getFunctionGraph(func_addr) | | func.stack_frame | ida_frame.get_frame(func) | func.getStackFrame() | vw.getFunctionLocals(func_addr) | | dis.get_function_signature(address)
func.signature | tif = ida_typeinf.tinfo_t()
ida_nalt.get_tinfo(tif, address)
func_type_data = ida_typeinf.func_type_data_t()
tif.get_func_details(func_type_data) | func.getSignature() | vw.getFunctionApi(func_addr) | | func = dis.create_function(start, end) | func = ida_funcs.add_func(start, end) | func = currentProgram.getFunctionManager().createFunction(None, toAddr(start), AddressSet(toAddr(start), toAddr(end)), SourceType.USER_DEFINED) | vw.makeFunction(start, meta={"Size": size}) | | func = dis.create_function(start) | func = ida_funcs.add_func(start) | func = CreateFunctionCmd(toAddr(start), True).applyTo(currentProgram).getFunction() | vw.makeFunction(start) | | func.undefine() | ida_funcs.del_func(start) | DeleteFunctionCmd(func.getEntryPoint(), True).applyTo(currentProgram) | vw.delFunction(func_addr) | ### 指令 | Dragodis* | IDA | Ghidra | Vivisect** | |--------------------------------------------|-----------------------------------------------------------|------------------------------------------------------------------------------------------------------|--------------------------------| | insn = dis.get_instruction(address) | insn = ida_ua.insn_t(); ida_ua.decode_insn(insn, address) | insn = currentProgram.getListing().getCodeUnitAt(toAddr(address)) | insn = vw.parseOpcode(address) | | insn.is_call | ida_idp.is_call_insn(insn) | insn.getFlowType().isCall() | insn.iflags & envi.IF_CALL | | insn.is_jump | *复杂操作:请参见源代码* | insn.getFlowType().isJump() | insn.iflags & envi.IF_BRANCH | | insn.is_return | ida_idp.is_ret_insn(insn) | insn.getFlowType().isTerminal() | insn.iflags & envi.IF_RET | | insn.mnemonic
dis.get_mnemonic(address) | ida_ua.ua_mnem(address) | insn.getMnemonicString() | insn.mnem | | insn.text | idc.GetDisasm(address) | str(insn) | str(insn) | | insn.operands | insn.ops | *不适用:请参见操作数部分* | insn.getOperands() | | insn.stack_depth | idc.get_spd(address) | CallDepthChangeInfo(currentProgram.getListing().getFunctionContaining(insn.getAddress())).getDepth() | *复杂操作:请参见源代码* | | insn.stack_delta | idc.get_sp_delta(address) | *复杂操作:请参见源代码* | *复杂操作:请参见源代码* | ### 操作数 *`insn` 的获取方式如上所述* | Dragodis* | IDA | Ghidra | Vivisect** | |-------------------------------------------------------------------------------|---------------------------------------------------------------------|-------------------------------|---------------------------------------| | operand = dis.get_operand(address, index)
operand = insn.operands\[index\] | operand = insn.ops\[index\] | *不适用* | operand = insn.getOperands()\[index\] | | operand.type
dis.get_operand_type(address, index) | idc.get_operand_type(address, index) | insn.getOperandType(index) | operand.\_\_class\_\_ | | operand.width | ida_ua.get_dtype_size(operand.dtype) | *复杂操作:请参见源代码* | operand.tsize | | operand.value
dis.get_operand_value(address, index) | *(取决于类型)*
operand.addr
operand.reg
operand.value | insn.getOpObjects(index) | operand.getOperValue() | | *(phrase 操作数)*
operand.value.base | operand.reg
ida_intel.x86_base_reg(insn, operand) | insn.getOpObjects(index)\[0\] | operand.reg | | *(phrase 操作数)*
operand.value.index | ida_intel.x86_index_reg(insn, operand) | insn.getOpObjects(index)\[1\] | operand.index | | *(phrase 操作数)*
operand.value.scale | 1 << ida_intel.sib_scale(operand) | insn.getOpObjects(index)\[2\] | operand.scale | | *(phrase 操作数)*
operand.value.offset | operand.addr
idc.get_operand_value(address, index) | insn.getOpObjects(index)\[3\] | operand.disp | | *(寄存器操作数)*
operand.value | operand.reg
idc.get_operand_value(address, index) | insn.getOpObjects(index)\[0\] | operand.reg.reg | | *(立即数操作数)*
operand.value | operand.value
idc.get_operand_value(address, index) | insn.getOpObjects(index)\[0\] | operand.getOperValue() | | *(内存引用操作数)*
operand.value | operand.addr
idc.get_operand_value(address, index) | insn.getOpObjects(index)\[0\] | operand.getOperValue() | ### 寄存器 | Dragodis* | IDA | Ghidra | Vivisect** | |------------------------------------|--------------------------------------------------------------------------|----------------------------------------------|------------------------------------------------------------| | register = dis.get_register("eax") | register = ida_idp.reg_info_t(); ida_idp.parse_reg_name(register, "eax") | register = currentProgram.getRegister("eax") | register = vw.arch.archGetRegCtx().getRegisterIndex("eax") | | register.name | ida_idp.get_reg_name(register.reg, register.size) | register.getName() | vw.arch.archGetRegCtx().getRegisterName(register) | | register.bit_width | register.size * 8 | register.getBitLength() | vw.arch.archGetCtx().getRegisterWidth(register) | ### 段 | Dragodis* | IDA | Ghidra | Vivisect** | |-----------------------------------------------------------------------|---------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------| | dis.segments() | \[ida_segment.getnseg(n) for n in range(ida_segment.get_segm_qty())\] | currentProgram.getMemory().getBlocks() | vw.getSegments() | | segment = dis.get_segment(name)
segment = dis.get_segment(address) | segment = ida_segment.get_segm_by_name(name)
segment = ida_segment.getseg(address) | memory_block = currentProgram.getMemory().getBlock(name)
memory_block = currentProgram.getMemory().getBlock(toAddr(address)) | addr, size, name, _ = vw.getSegment(address) | | segment.name | ida_segment.get_segm_name(segment) | memory_block.getName() | name | | segment.start | segment.start_ea | memory_block.getStart() | addr | | segment.end | segment.end_ea | memory_block.getEnd() | addr + size | | segment.initialized | ida_bytes.is_loaded(segment.start_ea) | memory_block.isInitialized() | bool(vw.getMemoryMap(addr)) | | segment.bit_size | segment.abits() | memory_block.getStart().getSize() | *不适用* | | segment.permissions | segment.perm | memory_block.isRead()
memory_block.isWrite()
memory_block.isExecute()
memory_block.isVolatile() | _, _, flags, _ = vw.getMemoryMap(addr) | | dis.create_segment(".new_seg", 0x1234, 256) | ida_segment.add_segm(0, 0x1234, 0x1334, ".new_seg", "XTRN") | currentProgram.getMemory().createUninitializedBlock(".new_seg", toAddr(0x1234), 256, False) | vw.addSegment(0x1234, 256, ".new_seg", filename) | ### 字符串 | Dragodis* | IDA | Ghidra | Vivisect** | |---------------------------|-------------------------------------------------------------------|---------------------------------------|---------------------------------------------------------------------------| | dis.strings(min_length=5) | finder = idautils.Strings(); finder.setup(minlen=5); list(finder) | findStrings(None, 5, 1, False, True) | vw.getLocations(vivisect.LOC_STRINGS) + vw.getLocations(vivisect.LOC_UNI) | \* dragodis 列中的 `dis` 表示从 `dragodis.open_program()` 获取的已打开的反汇编器对象 \** Vivisect 列中的 `vw` 表示由 `vivisect.VivWorkspace()` 创建的工作区
标签:API封装, DAST, Ghidra, IDA Pro, Python, Vivisect, 二进制分析, 二进制文件, 云安全监控, 云安全运维, 云资产清单, 反汇编框架, 开源, 恶意软件分析, 插件开发, 无后门, 网络安全, 自动化分析, 跨平台脚本, 跨站脚本, 逆向工具, 逆向工程, 通用反汇编, 隐私保护, 静态分析