ida-domain-api
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDomain API for IDA Pro
IDA Pro的Domain API
Use this skill to efficiently use the Domain API for IDA Pro, which is easier and more concise than the legacy IDA Python SDK.
Always prefer the IDA Domain API over the legacy low-level IDA Python SDK. The Domain API provides a clean, Pythonic interface that is easier to use and understand.
使用本技能可高效运用IDA Pro的Domain API,它比旧版IDA Python SDK更易用、更简洁。
优先使用IDA Domain API而非旧版底层IDA Python SDK。Domain API提供了简洁、符合Python风格的接口,更易于使用和理解。
Documentation Resources
文档资源
| Resource | URL |
|---|---|
| LLM-optimized overview | https://ida-domain.docs.hex-rays.com/llms.txt |
| Getting Started | https://ida-domain.docs.hex-rays.com/getting_started/index.md |
| Examples | https://ida-domain.docs.hex-rays.com/examples/index.md |
| API Reference | https://ida-domain.docs.hex-rays.com/ref/{module}/index.md |
Available API modules: , , , , , , , , , , , , , , ,
bytescommentsdatabaseentriesflowchartfunctionsheadshooksinstructionsnamesoperandssegmentssignature_filesstringstypesxrefsTo fetch specific API documentation, use URLs like:
- - Function analysis API
https://ida-domain.docs.hex-rays.com/ref/functions/index.md - - Cross-reference API
https://ida-domain.docs.hex-rays.com/ref/xrefs/index.md - - String analysis API
https://ida-domain.docs.hex-rays.com/ref/strings/index.md
可用API模块:, , , , , , , , , , , , , , ,
bytescommentsdatabaseentriesflowchartfunctionsheadshooksinstructionsnamesoperandssegmentssignature_filesstringstypesxrefs获取特定API文档,可使用如下格式的URL:
- - 函数分析API
https://ida-domain.docs.hex-rays.com/ref/functions/index.md - - 交叉引用API
https://ida-domain.docs.hex-rays.com/ref/xrefs/index.md - - 字符串分析API
https://ida-domain.docs.hex-rays.com/ref/strings/index.md
Opening a Database
打开数据库
python
from ida_domain import Database
from ida_domain.database import IdaCommandOptionspython
from ida_domain import Database
from ida_domain.database import IdaCommandOptionsOpen an existing .i64/.idb
打开现有.i64/.idb文件
ida_options = IdaCommandOptions(auto_analysis=False, new_database=False)
with Database.open("path/to/sample.i64", ida_options, save_on_close=False) as db:
pass
ida_options = IdaCommandOptions(auto_analysis=False, new_database=False)
with Database.open("path/to/sample.i64", ida_options, save_on_close=False) as db:
pass
Analyze a raw input file and create a new database
分析原始输入文件并创建新数据库
ida_options = IdaCommandOptions(
auto_analysis=True,
new_database=True,
output_database="path/to/cache/sample.i64",
load_resources=True,
)
with Database.open("path/to/input.exe", ida_options, save_on_close=True) as db:
pass
undefinedida_options = IdaCommandOptions(
auto_analysis=True,
new_database=True,
output_database="path/to/cache/sample.i64",
load_resources=True,
)
with Database.open("path/to/input.exe", ida_options, save_on_close=True) as db:
pass
undefinedCommonly Used IdaCommandOptions
常用IdaCommandOptions选项
IdaCommandOptionsload_resources=True-Rplugin_options-Opython
ida_options = IdaCommandOptions(
auto_analysis=True,
new_database=True,
output_database=str(cache_path),
load_resources=True,
plugin_options="lumina:host=0.0.0.0 -Osecondary_lumina:host=0.0.0.0",
)This sets both primary and secondary Lumina server addresses to , effectively disabling Lumina lookups. The field is a raw string; emits verbatim, so embedding inside the value for additional plugin options works correctly — the above produces .
0.0.0.0plugin_optionsbuild_args()-O{value}-O-Olumina:host=0.0.0.0 -Osecondary_lumina:host=0.0.0.0Other useful fields: (), (), (), (). See the docstring for the full list.
processor-plog_file-Lscript_file-Sdb_compression-PIdaCommandOptionsIdaCommandOptionsload_resources=True-Rplugin_options-Opython
ida_options = IdaCommandOptions(
auto_analysis=True,
new_database=True,
output_database=str(cache_path),
load_resources=True,
plugin_options="lumina:host=0.0.0.0 -Osecondary_lumina:host=0.0.0.0",
)这会将主、次Lumina服务器地址均设置为,从而有效禁用Lumina查询。字段是原始字符串;会原样输出,因此在值中嵌入以传递额外插件选项是可行的——上述代码会生成。
0.0.0.0plugin_optionsbuild_args()-O{value}-O-Olumina:host=0.0.0.0 -Osecondary_lumina:host=0.0.0.0其他实用字段:(对应)、(对应)、(对应)、(对应)。完整列表请查看的文档字符串。
processor-plog_file-Lscript_file-Sdb_compression-PIdaCommandOptionsTransparent Database Cache for Headless Tools
无头工具的透明数据库缓存
For repeatable CLI tools, do not re-analyze raw binaries every run. Prefer this pattern:
- if the input is already an or
.i64, use it directly.idb - otherwise hash the raw input and use the SHA-256 as the cache key
- create on demand
<cache>/<sha256>.i64 - serialize access with a lock file and an extra check, because another IDA process may have the database unpacked
.nam - create the cached database with
save_on_close=True - reopen cached databases read-only with
save_on_close=False - after requesting auto-analysis, call before querying
ida_auto.auto_wait()
python
import contextlib
import fcntl
import hashlib
import os
import time
from pathlib import Path
import ida_auto
from ida_domain import Database
from ida_domain.database import IdaCommandOptions
DATABASE_POLL_INTERVAL = 0.25
DATABASE_ACCESS_TIMEOUT = 5.0
DATABASE_ANALYSIS_TIMEOUT = 120.0
def get_cache_dir() -> Path:
root = Path(os.environ.get("XDG_CACHE_HOME", Path.home() / ".cache"))
return root / "your-tool"
def compute_sha256(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as f:
for chunk in iter(lambda: f.read(65536), b""):
digest.update(chunk)
return digest.hexdigest()
def wait_for_repack(db_path: Path, timeout: float) -> None:
nam_path = db_path.with_suffix(".nam")
deadline = time.monotonic() + timeout
while nam_path.exists():
if time.monotonic() >= deadline:
raise RuntimeError(f"database appears busy: {db_path}")
time.sleep(DATABASE_POLL_INTERVAL)
@contextlib.contextmanager
def database_access_guard(db_path: Path, timeout: float):
wait_for_repack(db_path, timeout)
lock_path = Path(str(db_path) + ".lock")
lock_fd = lock_path.open("w")
deadline = time.monotonic() + timeout
try:
while True:
try:
fcntl.flock(lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
break
except OSError:
if time.monotonic() >= deadline:
raise RuntimeError(f"timed out waiting for lock: {db_path}")
time.sleep(DATABASE_POLL_INTERVAL)
wait_for_repack(db_path, max(0.0, deadline - time.monotonic()))
yield
finally:
fcntl.flock(lock_fd, fcntl.LOCK_UN)
lock_fd.close()
def resolve_database(file_path: Path) -> Path:
if file_path.suffix.lower() in {".i64", ".idb"}:
return file_path
cache_dir = get_cache_dir()
cache_dir.mkdir(parents=True, exist_ok=True)
cache_path = cache_dir / f"{compute_sha256(file_path)}.i64"
if cache_path.exists():
return cache_path
with database_access_guard(cache_path, DATABASE_ANALYSIS_TIMEOUT):
if cache_path.exists():
return cache_path
ida_options = IdaCommandOptions(
auto_analysis=True,
new_database=True,
output_database=str(cache_path),
load_resources=True,
)
with Database.open(str(file_path), ida_options, save_on_close=True):
ida_auto.auto_wait()
if not cache_path.exists():
raise RuntimeError(f"analysis did not create {cache_path}")
return cache_path
@contextlib.contextmanager
def open_database_session(db_path: Path, auto_analysis: bool = False):
with database_access_guard(db_path, DATABASE_ACCESS_TIMEOUT):
ida_options = IdaCommandOptions(auto_analysis=auto_analysis, new_database=False)
with Database.open(str(db_path), ida_options, save_on_close=False) as db:
if auto_analysis:
ida_auto.auto_wait()
yield dbNotes:
- keep cached database creation quiet in normal mode; only log cache paths in verbose/debug mode
- if you need a different cache policy, keep the same three-phase guard: wait for , acquire
.nam, re-checkflock.nam - if you must fall back to for options not exposed by
idapro.open_database(...), import your local project modules beforeida-domain, becauseimport idaprocan mutateidaprosys.path - disable Lumina via in
plugin_options="lumina:host=0.0.0.0 -Osecondary_lumina:host=0.0.0.0"(see "Commonly Used IdaCommandOptions" above); no need to fall back toIdaCommandOptionsfor thisidapro.open_database()
对于可重复运行的CLI工具,不要每次运行都重新分析原始二进制文件。建议采用以下模式:
- 如果输入文件已经是或
.i64,直接使用它.idb - 否则对原始输入文件进行哈希,使用SHA-256作为缓存键
- 按需创建
<cache>/<sha256>.i64 - 使用锁文件和额外的检查实现序列化访问,因为其他IDA进程可能正在解压数据库
.nam - 创建缓存数据库时设置
save_on_close=True - 以只读模式重新打开缓存数据库,设置
save_on_close=False - 请求自动分析后,在查询前调用
ida_auto.auto_wait()
python
import contextlib
import fcntl
import hashlib
import os
import time
from pathlib import Path
import ida_auto
from ida_domain import Database
from ida_domain.database import IdaCommandOptions
DATABASE_POLL_INTERVAL = 0.25
DATABASE_ACCESS_TIMEOUT = 5.0
DATABASE_ANALYSIS_TIMEOUT = 120.0
def get_cache_dir() -> Path:
root = Path(os.environ.get("XDG_CACHE_HOME", Path.home() / ".cache"))
return root / "your-tool"
def compute_sha256(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as f:
for chunk in iter(lambda: f.read(65536), b""):
digest.update(chunk)
return digest.hexdigest()
def wait_for_repack(db_path: Path, timeout: float) -> None:
nam_path = db_path.with_suffix(".nam")
deadline = time.monotonic() + timeout
while nam_path.exists():
if time.monotonic() >= deadline:
raise RuntimeError(f"database appears busy: {db_path}")
time.sleep(DATABASE_POLL_INTERVAL)
@contextlib.contextmanager
def database_access_guard(db_path: Path, timeout: float):
wait_for_repack(db_path, timeout)
lock_path = Path(str(db_path) + ".lock")
lock_fd = lock_path.open("w")
deadline = time.monotonic() + timeout
try:
while True:
try:
fcntl.flock(lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
break
except OSError:
if time.monotonic() >= deadline:
raise RuntimeError(f"timed out waiting for lock: {db_path}")
time.sleep(DATABASE_POLL_INTERVAL)
wait_for_repack(db_path, max(0.0, deadline - time.monotonic()))
yield
finally:
fcntl.flock(lock_fd, fcntl.LOCK_UN)
lock_fd.close()
def resolve_database(file_path: Path) -> Path:
if file_path.suffix.lower() in {".i64", ".idb"}:
return file_path
cache_dir = get_cache_dir()
cache_dir.mkdir(parents=True, exist_ok=True)
cache_path = cache_dir / f"{compute_sha256(file_path)}.i64"
if cache_path.exists():
return cache_path
with database_access_guard(cache_path, DATABASE_ANALYSIS_TIMEOUT):
if cache_path.exists():
return cache_path
ida_options = IdaCommandOptions(
auto_analysis=True,
new_database=True,
output_database=str(cache_path),
load_resources=True,
)
with Database.open(str(file_path), ida_options, save_on_close=True):
ida_auto.auto_wait()
if not cache_path.exists():
raise RuntimeError(f"analysis did not create {cache_path}")
return cache_path
@contextlib.contextmanager
def open_database_session(db_path: Path, auto_analysis: bool = False):
with database_access_guard(db_path, DATABASE_ACCESS_TIMEOUT):
ida_options = IdaCommandOptions(auto_analysis=auto_analysis, new_database=False)
with Database.open(str(db_path), ida_options, save_on_close=False) as db:
if auto_analysis:
ida_auto.auto_wait()
yield db注意:
- 在正常模式下保持缓存数据库创建过程静默;仅在verbose/debug模式下记录缓存路径
- 如果需要不同的缓存策略,保留相同的三步防护:等待文件、获取
.nam锁、重新检查flock文件.nam - 如果必须回退到以使用
idapro.open_database(...)未公开的选项,请在ida-domain之前导入本地项目模块,因为import idapro可能会修改idaprosys.path - 通过在中设置
IdaCommandOptions禁用Lumina(参见上文“常用IdaCommandOptions选项”);无需为此回退到plugin_options="lumina:host=0.0.0.0 -Osecondary_lumina:host=0.0.0.0"idapro.open_database()
Key Database Properties
核心数据库属性
python
with Database.open(path, ida_options) as db:
db.minimum_ea # Start address
db.maximum_ea # End address
db.metadata # Database metadata
db.architecture # Target architecture
db.functions # All functions (iterable)
db.strings # All strings (iterable)
db.segments # Memory segments
db.names # Symbols and labels
db.entries # Entry points
db.types # Type definitions
db.comments # All comments
db.xrefs # Cross-reference utilities
db.bytes # Byte manipulation
db.instructions # Instruction accesspython
with Database.open(path, ida_options) as db:
db.minimum_ea # 起始地址
db.maximum_ea # 结束地址
db.metadata # 数据库元数据
db.architecture # 目标架构
db.functions # 所有函数(可迭代)
db.strings # 所有字符串(可迭代)
db.segments # 内存段
db.names # 符号与标签
db.entries # 入口点
db.types # 类型定义
db.comments # 所有注释
db.xrefs # 交叉引用工具
db.bytes # 字节操作
db.instructions # 指令访问Functions
函数
Iterating Functions
遍历函数
python
undefinedpython
undefinedIterate all functions
遍历所有函数
for func in db.functions:
print(db.functions.get_name(func))
for func in db.functions:
print(db.functions.get_name(func))
Get function count
获取函数数量
count = len(db.functions)
If your report needs thunk functions or library functions, iterate `db.functions` directly and classify them by flags. Do not assume a higher-level wrapper already included them.count = len(db.functions)
如果你的报告需要包含跳转函数或库函数,请直接遍历`db.functions`并通过标志进行分类。不要假设更高层级的封装已经包含了这些函数。Finding Functions
查找函数
python
func = db.functions.get_at(0x401000) # By address
func = db.functions.get_function_by_name("main") # By name
func = db.functions.get_next(ea) # Next function after eapython
func = db.functions.get_at(0x401000) # 通过地址查找
func = db.functions.get_function_by_name("main") # 通过名称查找
func = db.functions.get_next(ea) # 获取ea之后的下一个函数Functions in range
获取地址范围内的函数
for func in db.functions.get_between(start_ea, end_ea):
print(func.start_ea)
undefinedfor func in db.functions.get_between(start_ea, end_ea):
print(func.start_ea)
undefinedFunction Properties
函数属性
python
name = db.functions.get_name(func)
signature = db.functions.get_signature(func)
flags = db.functions.get_flags(func) # Returns FunctionFlagspython
name = db.functions.get_name(func)
signature = db.functions.get_signature(func)
flags = db.functions.get_flags(func) # 返回FunctionFlagsCheck function attributes
检查函数属性
db.functions.is_far(func)
db.functions.does_return(func)
undefineddb.functions.is_far(func)
db.functions.does_return(func)
undefinedFunction Code
函数代码
python
undefinedpython
undefinedGet disassembly lines
获取反汇编代码行
lines = db.functions.get_disassembly(func, remove_tags=True)
lines = db.functions.get_disassembly(func, remove_tags=True)
Get decompiled pseudocode
获取反编译伪代码
pseudocode = db.functions.get_pseudocode(func, remove_tags=True)
pseudocode = db.functions.get_pseudocode(func, remove_tags=True)
Get microcode
获取微代码
microcode = db.functions.get_microcode(func, remove_tags=True)
undefinedmicrocode = db.functions.get_microcode(func, remove_tags=True)
undefinedFunction Analysis
函数分析
python
undefinedpython
undefinedGet instructions in function
获取函数内的指令
for insn in db.functions.get_instructions(func):
print(insn.ea)
for insn in db.functions.get_instructions(func):
print(insn.ea)
Get flowchart for basic blocks
获取基本块流程图
flowchart = db.functions.get_flowchart(func)
for block in flowchart:
print(f"Block: {block.start_ea:#x} - {block.end_ea:#x}")
flowchart = db.functions.get_flowchart(func)
for block in flowchart:
print(f"Block: {block.start_ea:#x} - {block.end_ea:#x}")
Get callers/callees
获取调用者/被调用者
callers = db.functions.get_callers(func)
callees = db.functions.get_callees(func)
callers = db.functions.get_callers(func)
callees = db.functions.get_callees(func)
Get function chunks
获取函数块
for chunk in db.functions.get_chunks(func):
print(f"Chunk: {chunk.start_ea:#x}, main={chunk.is_main}")
for chunk in db.functions.get_chunks(func):
print(f"Chunk: {chunk.start_ea:#x}, main={chunk.is_main}")
Get data items within function
获取函数内的数据项
for data_ea in db.functions.get_data_items(func):
print(f"Data at {data_ea:#x}")
undefinedfor data_ea in db.functions.get_data_items(func):
print(f"Data at {data_ea:#x}")
undefinedThunk-Aware Analysis
跳转函数感知分析
If your tool renders callers/callees, API usage, or function summaries, resolve thunks once and reuse the result everywhere. A good default is:
- check
FunctionFlags.THUNK - follow only single-target thunk chains
- stop on cycles, zero-target chains, or multi-target chains
- cap the depth so malformed databases cannot loop forever
python
from ida_domain.functions import FunctionFlags
MAX_THUNK_DEPTH = 5
def resolve_thunk(db, func):
current = func
seen = set()
for _ in range(MAX_THUNK_DEPTH):
if not (db.functions.get_flags(current) & FunctionFlags.THUNK):
return current
if current.start_ea in seen:
return current
seen.add(current.start_ea)
callees = list(db.functions.get_callees(current))
if len(callees) != 1:
return current
current = callees[0]
return currentUse the resolved target consistently for:
- caller lists
- callee lists
- API/import classification
- attaching per-function metadata like matches or tags
如果你的工具需要展示调用者/被调用者、API使用情况或函数摘要,请一次性解析跳转函数并在所有场景复用结果。推荐默认逻辑:
- 检查标志
FunctionFlags.THUNK - 仅跟踪单目标跳转链
- 在出现循环、零目标链或多目标链时停止
- 设置深度上限,避免畸形数据库导致无限循环
python
from ida_domain.functions import FunctionFlags
MAX_THUNK_DEPTH = 5
def resolve_thunk(db, func):
current = func
seen = set()
for _ in range(MAX_THUNK_DEPTH):
if not (db.functions.get_flags(current) & FunctionFlags.THUNK):
return current
if current.start_ea in seen:
return current
seen.add(current.start_ea)
callees = list(db.functions.get_callees(current))
if len(callees) != 1:
return current
current = callees[0]
return current在以下场景中统一使用解析后的目标:
- 调用者列表
- 被调用者列表
- API/导入分类
- 附加函数元数据(如匹配结果或标签)
Local Variables
局部变量
python
undefinedpython
undefinedGet all local variables
获取所有局部变量
lvars = db.functions.get_local_variables(func)
for lvar in lvars:
print(f"{lvar.name}: {lvar.type_str}, arg={lvar.is_argument}")
lvars = db.functions.get_local_variables(func)
for lvar in lvars:
print(f"{lvar.name}: {lvar.type_str}, arg={lvar.is_argument}")
Find variable by name
通过名称查找变量
lvar = db.functions.get_local_variable_by_name(func, "result")
lvar = db.functions.get_local_variable_by_name(func, "result")
Get variable references in pseudocode
获取伪代码中的变量引用
refs = db.functions.get_local_variable_references(func, lvar)
for ref in refs:
print(f"Line {ref.line_number}: {ref.access_type} in {ref.context}")
undefinedrefs = db.functions.get_local_variable_references(func, lvar)
for ref in refs:
print(f"Line {ref.line_number}: {ref.access_type} in {ref.context}")
undefinedModifying Functions
修改函数
python
db.functions.set_name(func, "new_name")
db.functions.set_comment(func, "This function does X", repeatable=False)
db.functions.create(ea) # Create function at address
db.functions.remove(ea) # Remove function at addresspython
db.functions.set_name(func, "new_name")
db.functions.set_comment(func, "This function does X", repeatable=False)
db.functions.create(ea) # 在指定地址创建函数
db.functions.remove(ea) # 删除指定地址的函数Instructions
指令
Iterating Instructions
遍历指令
python
undefinedpython
undefinedAll instructions in database
遍历数据库中所有指令
for insn in db.instructions:
print(db.instructions.get_disassembly(insn))
for insn in db.instructions:
print(db.instructions.get_disassembly(insn))
Instructions in range
遍历地址范围内的指令
for insn in db.instructions.get_between(start_ea, end_ea):
print(insn.ea)
undefinedfor insn in db.instructions.get_between(start_ea, end_ea):
print(insn.ea)
undefinedGetting Instructions
获取指令
python
insn = db.instructions.get_at(ea) # Decode at address
insn = db.instructions.get_previous(ea) # Previous instructionpython
insn = db.instructions.get_at(ea) # 解码指定地址的指令
insn = db.instructions.get_previous(ea) # 获取前一条指令Instruction Properties
指令属性
python
disasm = db.instructions.get_disassembly(insn)
mnemonic = db.instructions.get_mnemonic(insn) # "mov", "push", etc.
db.instructions.is_valid(insn)python
disasm = db.instructions.get_disassembly(insn)
mnemonic = db.instructions.get_mnemonic(insn) # "mov", "push"等指令助记符
db.instructions.is_valid(insn)Control Flow Analysis
控制流分析
python
db.instructions.is_call_instruction(insn) # Is this a call?
db.instructions.is_indirect_jump_or_call(insn) # Indirect jump/call?
db.instructions.breaks_sequential_flow(insn) # Stops flow (ret, jmp)?python
db.instructions.is_call_instruction(insn) # 是否为调用指令?
db.instructions.is_indirect_jump_or_call(insn) # 是否为间接跳转/调用?
db.instructions.breaks_sequential_flow(insn) # 是否中断顺序执行流(如ret、jmp)?Working with Operands
操作数处理
python
count = db.instructions.get_operands_count(insn)
operands = db.instructions.get_operands(insn) # List of Operand objects
for op in operands:
info = op.get_info()
print(f"Operand {op.number}: {op.type.name}")
if isinstance(op, RegisterOperand):
print(f" Register: {op.get_register_name()}")
elif isinstance(op, ImmediateOperand):
print(f" Value: 0x{op.get_value():x}")
elif isinstance(op, MemoryOperand):
if op.is_direct_memory():
print(f" Memory: 0x{op.get_address():x}")python
count = db.instructions.get_operands_count(insn)
operands = db.instructions.get_operands(insn) # Operand对象列表
for op in operands:
info = op.get_info()
print(f"Operand {op.number}: {op.type.name}")
if isinstance(op, RegisterOperand):
print(f" Register: {op.get_register_name()}")
elif isinstance(op, ImmediateOperand):
print(f" Value: 0x{op.get_value():x}")
elif isinstance(op, MemoryOperand):
if op.is_direct_memory():
print(f" Memory: 0x{op.get_address():x}")Segments
内存段
Iterating Segments
遍历内存段
python
for segment in db.segments:
name = db.segments.get_name(segment)
size = db.segments.get_size(segment)
print(f"{name}: {segment.start_ea:#x} - {segment.end_ea:#x}")
count = len(db.segments)python
for segment in db.segments:
name = db.segments.get_name(segment)
size = db.segments.get_size(segment)
print(f"{name}: {segment.start_ea:#x} - {segment.end_ea:#x}")
count = len(db.segments)Finding Segments
查找内存段
python
seg = db.segments.get_at(0x401000) # Segment containing address
seg = db.segments.get_by_name(".text") # By namepython
seg = db.segments.get_at(0x401000) # 获取包含指定地址的内存段
seg = db.segments.get_by_name(".text") # 通过名称查找内存段Segment Properties
内存段属性
python
name = db.segments.get_name(segment)
size = db.segments.get_size(segment)
bitness = db.segments.get_bitness(segment) # 16, 32, or 64
seg_class = db.segments.get_class(segment) # "CODE", "DATA", etc.python
name = db.segments.get_name(segment)
size = db.segments.get_size(segment)
bitness = db.segments.get_bitness(segment) # 16、32或64位
seg_class = db.segments.get_class(segment) # "CODE"、"DATA"等Creating Segments
创建内存段
python
from ida_domain.segments import PredefinedClass, AddSegmentFlagspython
from ida_domain.segments import PredefinedClass, AddSegmentFlagsAdd segment with explicit range
添加指定范围的内存段
seg = db.segments.add(
seg_para=0,
start_ea=0x1000,
end_ea=0x2000,
seg_name="MySegment",
seg_class=PredefinedClass.CODE
)
seg = db.segments.add(
seg_para=0,
start_ea=0x1000,
end_ea=0x2000,
seg_name="MySegment",
seg_class=PredefinedClass.CODE
)
Append segment after last one
在最后一个内存段后追加新段
seg = db.segments.append(seg_para=0, seg_size=0x1000, seg_name="NewSeg")
undefinedseg = db.segments.append(seg_para=0, seg_size=0x1000, seg_name="NewSeg")
undefinedModifying Segments
修改内存段
python
from ida_domain.segments import SegmentPermissions, AddressingMode
db.segments.set_name(segment, "new_name")
db.segments.set_permissions(segment, SegmentPermissions.READ | SegmentPermissions.EXEC)
db.segments.add_permissions(segment, SegmentPermissions.WRITE)
db.segments.remove_permissions(segment, SegmentPermissions.WRITE)
db.segments.set_addressing_mode(segment, AddressingMode.BIT64)
db.segments.set_comment(segment, "Code section", repeatable=False)python
from ida_domain.segments import SegmentPermissions, AddressingMode
db.segments.set_name(segment, "new_name")
db.segments.set_permissions(segment, SegmentPermissions.READ | SegmentPermissions.EXEC)
db.segments.add_permissions(segment, SegmentPermissions.WRITE)
db.segments.remove_permissions(segment, SegmentPermissions.WRITE)
db.segments.set_addressing_mode(segment, AddressingMode.BIT64)
db.segments.set_comment(segment, "Code section", repeatable=False)Strings
字符串
Iterating Strings
遍历字符串
python
for string in db.strings:
print(f"{string.address:#x}: {string}")python
for string in db.strings:
print(f"{string.address:#x}: {string}")By index
通过索引获取
first_string = db.strings[0]
count = len(db.strings)
undefinedfirst_string = db.strings[0]
count = len(db.strings)
undefinedFinding Strings
查找字符串
python
string = db.strings.get_at(0x402000) # String at addresspython
string = db.strings.get_at(0x402000) # 获取指定地址的字符串Strings in range
获取地址范围内的字符串
for s in db.strings.get_between(start_ea, end_ea):
print(s.contents)
undefinedfor s in db.strings.get_between(start_ea, end_ea):
print(s.contents)
undefinedString Properties
字符串属性
python
print(string.address) # Address
print(string.length) # Length in characters
print(string.type) # StringType enum
print(string.encoding) # Internal encoding
print(string.contents) # UTF-8 bytes
print(str(string)) # Decoded stringpython
print(string.address) # 地址
print(string.length) # 字符长度
print(string.type) # StringType枚举
print(string.encoding) # 内部编码
print(string.contents) # UTF-8字节
print(str(string)) # 解码后的字符串Rebuilding String List
重建字符串列表
python
from ida_domain.strings import StringListConfig, StringType
config = StringListConfig(
string_types=[StringType.C, StringType.C_16],
min_len=3,
only_ascii_7bit=False
)
db.strings.rebuild(config)
db.strings.clear() # Clear string listpython
from ida_domain.strings import StringListConfig, StringType
config = StringListConfig(
string_types=[StringType.C, StringType.C_16],
min_len=3,
only_ascii_7bit=False
)
db.strings.rebuild(config)
db.strings.clear() # 清空字符串列表Xrefs
交叉引用
Getting References TO an Address
获取指向指定地址的引用
python
undefinedpython
undefinedAll xrefs to an address
获取指向指定地址的所有交叉引用
for xref in db.xrefs.to_ea(target_ea):
print(f"{xref.from_ea:#x} -> {xref.to_ea:#x} ({xref.type.name})")
for xref in db.xrefs.to_ea(target_ea):
print(f"{xref.from_ea:#x} -> {xref.to_ea:#x} ({xref.type.name})")
Just code references
仅获取代码引用
for ea in db.xrefs.code_refs_to_ea(target_ea, flow=False):
print(f"Code ref from {ea:#x}")
for ea in db.xrefs.code_refs_to_ea(target_ea, flow=False):
print(f"Code ref from {ea:#x}")
Just data references
仅获取数据引用
for ea in db.xrefs.data_refs_to_ea(target_ea):
print(f"Data ref from {ea:#x}")
for ea in db.xrefs.data_refs_to_ea(target_ea):
print(f"Data ref from {ea:#x}")
Call references only
仅获取调用引用
for ea in db.xrefs.calls_to_ea(func_ea):
print(f"Called from {ea:#x}")
for ea in db.xrefs.calls_to_ea(func_ea):
print(f"Called from {ea:#x}")
Detailed caller information
获取详细的调用者信息
for caller in db.xrefs.get_callers(func_ea):
print(f"Called from {caller.name} at {caller.ea:#x}")
undefinedfor caller in db.xrefs.get_callers(func_ea):
print(f"Called from {caller.name} at {caller.ea:#x}")
undefinedGetting References FROM an Address
获取来自指定地址的引用
python
undefinedpython
undefinedAll xrefs from an address
获取来自指定地址的所有交叉引用
for xref in db.xrefs.from_ea(source_ea):
print(f"{xref.from_ea:#x} -> {xref.to_ea:#x}")
for xref in db.xrefs.from_ea(source_ea):
print(f"{xref.from_ea:#x} -> {xref.to_ea:#x}")
Code/data refs from
获取来自该地址的代码/数据引用
for ea in db.xrefs.code_refs_from_ea(source_ea):
print(f"Code ref to {ea:#x}")
for ea in db.xrefs.calls_from_ea(source_ea):
print(f"Calls {ea:#x}")
undefinedfor ea in db.xrefs.code_refs_from_ea(source_ea):
print(f"Code ref to {ea:#x}")
for ea in db.xrefs.calls_from_ea(source_ea):
print(f"Calls {ea:#x}")
undefinedData Access Analysis
数据访问分析
python
undefinedpython
undefinedWho reads this data?
谁读取了该数据?
for ea in db.xrefs.reads_of_ea(data_ea):
print(f"Read by {ea:#x}")
for ea in db.xrefs.reads_of_ea(data_ea):
print(f"Read by {ea:#x}")
Who writes to this data?
谁写入了该数据?
for ea in db.xrefs.writes_to_ea(data_ea):
print(f"Written by {ea:#x}")
undefinedfor ea in db.xrefs.writes_to_ea(data_ea):
print(f"Written by {ea:#x}")
undefinedXrefInfo Properties
XrefInfo属性
python
xref.is_call # Is this a call reference?
xref.is_jump # Is this a jump reference?
xref.is_read # Is this a data read?
xref.is_write # Is this a data write?
xref.is_flow # Is this ordinary flow?
xref.user # Is this user-defined?python
xref.is_call # 是否为调用引用?
xref.is_jump # 是否为跳转引用?
xref.is_read # 是否为数据读取引用?
xref.is_write # 是否为数据写入引用?
xref.is_flow # 是否为普通执行流引用?
xref.user # 是否为用户定义的引用?Names
符号名称
Iterating Names
遍历符号名称
python
for ea, name in db.names:
print(f"{ea:#x}: {name}")
count = len(db.names)python
for ea, name in db.names:
print(f"{ea:#x}: {name}")
count = len(db.names)Getting Names
获取符号名称
python
name = db.names.get_at(0x401000)
ea, name = db.names[0] # By indexpython
name = db.names.get_at(0x401000)
ea, name = db.names[0] # 通过索引获取Setting Names
设置符号名称
python
from ida_domain.names import SetNameFlags
db.names.set_name(ea, "my_function")
db.names.set_name(ea, "my_func", flags=SetNameFlags.CHECK) # Validate chars
db.names.force_name(ea, "func") # Creates func_2 if func exists
db.names.delete(ea) # Remove namepython
from ida_domain.names import SetNameFlags
db.names.set_name(ea, "my_function")
db.names.set_name(ea, "my_func", flags=SetNameFlags.CHECK) # 验证字符合法性
db.names.force_name(ea, "func") # 若func已存在则创建func_2
db.names.delete(ea) # 删除符号名称Name Properties
符号名称属性
python
db.names.is_valid_name("my_name") # Check if valid
db.names.is_public_name(ea) # Is public?
db.names.is_weak_name(ea) # Is weak?
db.names.make_name_public(ea)
db.names.make_name_non_public(ea)
db.names.make_name_weak(ea)
db.names.make_name_non_weak(ea)python
db.names.is_valid_name("my_name") # 检查名称是否合法
db.names.is_public_name(ea) # 是否为公共名称?
db.names.is_weak_name(ea) # 是否为弱名称?
db.names.make_name_public(ea)
db.names.make_name_non_public(ea)
db.names.make_name_weak(ea)
db.names.make_name_non_weak(ea)Demangling
名称解混淆
python
from ida_domain.names import DemangleFlags
demangled = db.names.get_demangled_name(ea)
demangled = db.names.get_demangled_name(ea, DemangleFlags.NORETTYPE)
demangled = db.names.demangle_name("?main@@YAXXZ")python
from ida_domain.names import DemangleFlags
demangled = db.names.get_demangled_name(ea)
demangled = db.names.get_demangled_name(ea, DemangleFlags.NORETTYPE)
demangled = db.names.demangle_name("?main@@YAXXZ")Types
类型
Getting Types
获取类型
python
undefinedpython
undefinedBy name
通过名称获取
tinfo = db.types.get_by_name("MyStruct")
tinfo = db.types.get_by_name("MyStruct")
At address
通过地址获取
tinfo = db.types.get_at(ea)
tinfo = db.types.get_at(ea)
Iterate all types
遍历所有类型
for tinfo in db.types:
print(tinfo)
undefinedfor tinfo in db.types:
print(tinfo)
undefinedParsing Types
解析类型
python
undefinedpython
undefinedParse declarations from string
从字符串解析类型声明
errors = db.types.parse_declarations(None, "struct Point { int x; int y; };")
errors = db.types.parse_declarations(None, "struct Point { int x; int y; };")
Parse single declaration
解析单个类型声明
tinfo = db.types.parse_one_declaration(None, "int (callback)(void)", "callback_t")
tinfo = db.types.parse_one_declaration(None, "int (callback)(void)", "callback_t")
Parse header file
解析头文件
errors = db.types.parse_header_file(library, Path("header.h"))
undefinederrors = db.types.parse_header_file(library, Path("header.h"))
undefinedApplying Types
应用类型
python
from ida_domain.types import TypeApplyFlags
db.types.apply_at(tinfo, ea, flags=TypeApplyFlags.DEFINITE)python
from ida_domain.types import TypeApplyFlags
db.types.apply_at(tinfo, ea, flags=TypeApplyFlags.DEFINITE)Type Details
类型详情
python
details = db.types.get_details(tinfo)
print(details.name)
print(details.size)
print(details.attributes)python
details = db.types.get_details(tinfo)
print(details.name)
print(details.size)
print(details.attributes)For structs/unions
针对结构体/联合体
if details.udt:
print(details.udt.num_members)
print(details.udt.attributes)
if details.udt:
print(details.udt.num_members)
print(details.udt.attributes)
For functions
针对函数
if details.func:
print(details.func.attributes)
undefinedif details.func:
print(details.func.attributes)
undefinedType Libraries
类型库
python
undefinedpython
undefinedLoad/create libraries
加载/创建类型库
lib = db.types.load_library(Path("types.til"))
lib = db.types.create_library(Path("new.til"), "My Types")
lib = db.types.load_library(Path("types.til"))
lib = db.types.create_library(Path("new.til"), "My Types")
Import/export types
导入/导出类型
db.types.import_type(source_lib, "MyStruct")
db.types.export_type(dest_lib, "MyStruct")
db.types.import_type(source_lib, "MyStruct")
db.types.export_type(dest_lib, "MyStruct")
Save library
保存类型库
db.types.save_library(lib, Path("output.til"))
db.types.unload_library(lib)
---db.types.save_library(lib, Path("output.til"))
db.types.unload_library(lib)
---Bytes
字节操作
Reading Values
读取值
python
byte = db.bytes.get_byte_at(ea)
word = db.bytes.get_word_at(ea)
dword = db.bytes.get_dword_at(ea)
qword = db.bytes.get_qword_at(ea)
float_val = db.bytes.get_float_at(ea)
double_val = db.bytes.get_double_at(ea)python
byte = db.bytes.get_byte_at(ea)
word = db.bytes.get_word_at(ea)
dword = db.bytes.get_dword_at(ea)
qword = db.bytes.get_qword_at(ea)
float_val = db.bytes.get_float_at(ea)
double_val = db.bytes.get_double_at(ea)Read multiple bytes
读取多个字节
data = db.bytes.get_bytes_at(ea, size=16)
original = db.bytes.get_original_bytes_at(ea, size=16)
data = db.bytes.get_bytes_at(ea, size=16)
original = db.bytes.get_original_bytes_at(ea, size=16)
Read strings
读取字符串
string = db.bytes.get_string_at(ea)
cstring = db.bytes.get_cstring_at(ea, max_length=256)
undefinedstring = db.bytes.get_string_at(ea)
cstring = db.bytes.get_cstring_at(ea, max_length=256)
undefinedWriting Values
写入值
python
db.bytes.set_byte_at(ea, 0x90)
db.bytes.set_word_at(ea, 0x1234)
db.bytes.set_dword_at(ea, 0x12345678)
db.bytes.set_qword_at(ea, 0x123456789ABCDEF0)
db.bytes.set_bytes_at(ea, b"\x90\x90\x90")python
db.bytes.set_byte_at(ea, 0x90)
db.bytes.set_word_at(ea, 0x1234)
db.bytes.set_dword_at(ea, 0x12345678)
db.bytes.set_qword_at(ea, 0x123456789ABCDEF0)
db.bytes.set_bytes_at(ea, b"\x90\x90\x90")Patching (with History)
补丁操作(带历史记录)
python
db.bytes.patch_byte_at(ea, 0x90) # Saves original
db.bytes.patch_bytes_at(ea, data)
db.bytes.revert_byte_at(ea) # Restore originalpython
db.bytes.patch_byte_at(ea, 0x90) # 保存原始值
db.bytes.patch_bytes_at(ea, data)
db.bytes.revert_byte_at(ea) # 恢复原始值Get original values
获取原始值
orig = db.bytes.get_original_byte_at(ea)
undefinedorig = db.bytes.get_original_byte_at(ea)
undefinedSearching
搜索
python
from ida_domain.bytes import SearchFlagspython
from ida_domain.bytes import SearchFlagsFind bytes
查找字节序列
ea = db.bytes.find_bytes_between(b"\x55\x89\xe5", start_ea, end_ea)
ea = db.bytes.find_bytes_between(b"\x55\x89\xe5", start_ea, end_ea)
Find all occurrences
查找所有匹配项
addresses = db.bytes.find_binary_sequence(b"\x90\x90")
addresses = db.bytes.find_binary_sequence(b"\x90\x90")
Find text
查找文本
ea = db.bytes.find_text_between("error", flags=SearchFlags.DOWN)
ea = db.bytes.find_text_between("error", flags=SearchFlags.DOWN)
Find immediate value
查找立即数
ea = db.bytes.find_immediate_between(0x1234)
undefinedea = db.bytes.find_immediate_between(0x1234)
undefinedCreating Data Items
创建数据项
python
from ida_domain.strings import StringType
db.bytes.create_byte_at(ea, count=4)
db.bytes.create_word_at(ea)
db.bytes.create_dword_at(ea, count=10) # Array of 10 dwords
db.bytes.create_qword_at(ea)
db.bytes.create_float_at(ea)
db.bytes.create_double_at(ea)
db.bytes.create_string_at(ea, string_type=StringType.C)
db.bytes.create_struct_at(ea, count=1, tid=struct_tid)python
from ida_domain.strings import StringType
db.bytes.create_byte_at(ea, count=4)
db.bytes.create_word_at(ea)
db.bytes.create_dword_at(ea, count=10) # 创建10个双字的数组
db.bytes.create_qword_at(ea)
db.bytes.create_float_at(ea)
db.bytes.create_double_at(ea)
db.bytes.create_string_at(ea, string_type=StringType.C)
db.bytes.create_struct_at(ea, count=1, tid=struct_tid)Querying Properties
查询属性
python
size = db.bytes.get_data_size_at(ea)
db.bytes.is_value_initialized_at(ea)
db.bytes.is_code_at(ea)
db.bytes.is_data_at(ea)
db.bytes.is_head_at(ea)
db.bytes.is_tail_at(ea)
db.bytes.is_unknown_at(ea)python
size = db.bytes.get_data_size_at(ea)
db.bytes.is_value_initialized_at(ea)
db.bytes.is_code_at(ea)
db.bytes.is_data_at(ea)
db.bytes.is_head_at(ea)
db.bytes.is_tail_at(ea)
db.bytes.is_unknown_at(ea)Get disassembly at address
获取指定地址的反汇编代码
disasm = db.bytes.get_disassembly_at(ea)
undefineddisasm = db.bytes.get_disassembly_at(ea)
undefinedNavigation
导航
python
next_head = db.bytes.get_next_head(ea)
prev_head = db.bytes.get_previous_head(ea)
next_addr = db.bytes.get_next_address(ea)
prev_addr = db.bytes.get_previous_address(ea)python
next_head = db.bytes.get_next_head(ea)
prev_head = db.bytes.get_previous_head(ea)
next_addr = db.bytes.get_next_address(ea)
prev_addr = db.bytes.get_previous_address(ea)Comments
注释
Regular Comments
常规注释
python
from ida_domain.comments import CommentKindpython
from ida_domain.comments import CommentKindGet comment
获取注释
info = db.comments.get_at(ea, CommentKind.REGULAR)
if info:
print(info.comment)
info = db.comments.get_at(ea, CommentKind.REGULAR)
if info:
print(info.comment)
Set comment
设置注释
db.comments.set_at(ea, "This is important", CommentKind.REGULAR)
db.comments.set_at(ea, "Shows everywhere", CommentKind.REPEATABLE)
db.comments.set_at(ea, "This is important", CommentKind.REGULAR)
db.comments.set_at(ea, "Shows everywhere", CommentKind.REPEATABLE)
Delete comment
删除注释
db.comments.delete_at(ea, CommentKind.ALL)
undefineddb.comments.delete_at(ea, CommentKind.ALL)
undefinedIterating Comments
遍历注释
python
for comment_info in db.comments:
print(f"{comment_info.ea:#x}: {comment_info.comment}")python
for comment_info in db.comments:
print(f"{comment_info.ea:#x}: {comment_info.comment}")All comment types
遍历所有类型的注释
for info in db.comments.get_all(CommentKind.ALL):
print(f"{info.ea:#x} (repeatable={info.repeatable}): {info.comment}")
undefinedfor info in db.comments.get_all(CommentKind.ALL):
print(f"{info.ea:#x} (repeatable={info.repeatable}): {info.comment}")
undefinedExtra Comments (Anterior/Posterior)
额外注释(前置/后置)
python
from ida_domain.comments import ExtraCommentKindpython
from ida_domain.comments import ExtraCommentKindSet extra comment
设置额外注释
db.comments.set_extra_at(ea, index=0, comment="Before line", kind=ExtraCommentKind.ANTERIOR)
db.comments.set_extra_at(ea, index=0, comment="After line", kind=ExtraCommentKind.POSTERIOR)
db.comments.set_extra_at(ea, index=0, comment="Before line", kind=ExtraCommentKind.ANTERIOR)
db.comments.set_extra_at(ea, index=0, comment="After line", kind=ExtraCommentKind.POSTERIOR)
Get extra comments
获取额外注释
comment = db.comments.get_extra_at(ea, index=0, kind=ExtraCommentKind.ANTERIOR)
for comment in db.comments.get_all_extra_at(ea, ExtraCommentKind.ANTERIOR):
print(comment)
comment = db.comments.get_extra_at(ea, index=0, kind=ExtraCommentKind.ANTERIOR)
for comment in db.comments.get_all_extra_at(ea, ExtraCommentKind.ANTERIOR):
print(comment)
Delete
删除额外注释
db.comments.delete_extra_at(ea, index=0, kind=ExtraCommentKind.ANTERIOR)
---db.comments.delete_extra_at(ea, index=0, kind=ExtraCommentKind.ANTERIOR)
---Entries
入口点
Iterating Entry Points
遍历入口点
python
for entry in db.entries:
print(f"{entry.ordinal}: {entry.name} at {entry.address:#x}")
count = len(db.entries)
first = db.entries[0]python
for entry in db.entries:
print(f"{entry.ordinal}: {entry.name} at {entry.address:#x}")
count = len(db.entries)
first = db.entries[0]Finding Entries
查找入口点
python
entry = db.entries.get_at(ea) # By address
entry = db.entries.get_by_ordinal(1) # By ordinal
entry = db.entries.get_by_name("main") # By name
entry = db.entries.get_at_index(0) # By indexpython
entry = db.entries.get_at(ea) # 通过地址查找
entry = db.entries.get_by_ordinal(1) # 通过序号查找
entry = db.entries.get_by_name("main") # 通过名称查找
entry = db.entries.get_at_index(0) # 通过索引查找Entry Properties
入口点属性
python
print(entry.ordinal)
print(entry.address)
print(entry.name)
print(entry.forwarder_name)
entry.has_forwarder()python
print(entry.ordinal)
print(entry.address)
print(entry.name)
print(entry.forwarder_name)
entry.has_forwarder()Modifying Entries
修改入口点
python
db.entries.add(address=ea, name="new_entry", ordinal=10)
db.entries.rename(ordinal=10, new_name="renamed_entry")
db.entries.set_forwarder(ordinal=10, forwarder_name="other.dll!func")
db.entries.exists(ordinal=10)python
db.entries.add(address=ea, name="new_entry", ordinal=10)
db.entries.rename(ordinal=10, new_name="renamed_entry")
db.entries.set_forwarder(ordinal=10, forwarder_name="other.dll!func")
db.entries.exists(ordinal=10)Utility Iterators
实用迭代器
python
for ordinal in db.entries.get_ordinals():
print(ordinal)
for addr in db.entries.get_addresses():
print(f"{addr:#x}")
for name in db.entries.get_names():
print(name)
for fwd in db.entries.get_forwarders():
print(f"{fwd.ordinal}: {fwd.name}")python
for ordinal in db.entries.get_ordinals():
print(ordinal)
for addr in db.entries.get_addresses():
print(f"{addr:#x}")
for name in db.entries.get_names():
print(name)
for fwd in db.entries.get_forwarders():
print(f"{fwd.ordinal}: {fwd.name}")Heads
头部项
Iterating Heads
遍历头部项
python
for ea in db.heads:
print(f"Head at {ea:#x}")python
for ea in db.heads:
print(f"Head at {ea:#x}")In range
遍历地址范围内的头部项
for ea in db.heads.get_between(start_ea, end_ea):
print(ea)
undefinedfor ea in db.heads.get_between(start_ea, end_ea):
print(ea)
undefinedNavigation
导航
python
next_ea = db.heads.get_next(ea)
prev_ea = db.heads.get_previous(ea)python
next_ea = db.heads.get_next(ea)
prev_ea = db.heads.get_previous(ea)Head Properties
头部项属性
python
db.heads.is_head(ea) # Is start of item?
db.heads.is_tail(ea) # Is part of multi-byte item?
db.heads.is_code(ea) # Is instruction?
db.heads.is_data(ea) # Is data?
db.heads.is_unknown(ea) # Is unclassified?
size = db.heads.size(ea)
start, end = db.heads.bounds(ea)python
db.heads.is_head(ea) # 是否为项的起始地址?
db.heads.is_tail(ea) # 是否为多字节项的一部分?
db.heads.is_code(ea) # 是否为指令?
db.heads.is_data(ea) # 是否为数据?
db.heads.is_unknown(ea) # 是否未分类?
size = db.heads.size(ea)
start, end = db.heads.bounds(ea)Flowchart
流程图
Creating Flowcharts
创建流程图
python
from ida_domain.flowchart import FlowChart, FlowChartFlagspython
from ida_domain.flowchart import FlowChart, FlowChartFlagsFrom function
基于函数创建
flowchart = FlowChart(db, func=my_func)
flowchart = FlowChart(db, func=my_func)
From address range
基于地址范围创建
flowchart = FlowChart(db, bounds=(start_ea, end_ea))
flowchart = FlowChart(db, bounds=(start_ea, end_ea))
With predecessor info
包含前驱信息
flowchart = FlowChart(db, func=my_func, flags=FlowChartFlags.PREDS)
undefinedflowchart = FlowChart(db, func=my_func, flags=FlowChartFlags.PREDS)
undefinedIterating Basic Blocks
遍历基本块
python
for block in flowchart:
print(f"Block {block.id}: {block.start_ea:#x} - {block.end_ea:#x}")python
for block in flowchart:
print(f"Block {block.id}: {block.start_ea:#x} - {block.end_ea:#x}")By index
通过索引获取
block = flowchart[0]
count = len(flowchart)
undefinedblock = flowchart[0]
count = len(flowchart)
undefinedBlock Navigation
基本块导航
python
for succ in block.get_successors():
print(f"Successor: {succ.id}")
for pred in block.get_predecessors():
print(f"Predecessor: {pred.id}")
succ_count = block.count_successors()
pred_count = block.count_predecessors()python
for succ in block.get_successors():
print(f"Successor: {succ.id}")
for pred in block.get_predecessors():
print(f"Predecessor: {pred.id}")
succ_count = block.count_successors()
pred_count = block.count_predecessors()Block Instructions
基本块指令
python
for insn in block.get_instructions():
print(f"{insn.ea:#x}")python
for insn in block.get_instructions():
print(f"{insn.ea:#x}")Enums Reference
枚举参考
XrefType
XrefType
python
from ida_domain.xrefs import XrefType
XrefType.OFFSET # Offset reference
XrefType.WRITE # Write access
XrefType.READ # Read access
XrefType.CALL_FAR # Far call
XrefType.CALL_NEAR # Near call
XrefType.JUMP_FAR # Far jump
XrefType.JUMP_NEAR # Near jump
XrefType.ORDINARY_FLOW # Sequential flow
xref_type.is_code_ref() # Check if code ref
xref_type.is_data_ref() # Check if data refpython
from ida_domain.xrefs import XrefType
XrefType.OFFSET # 偏移引用
XrefType.WRITE # 写入访问
XrefType.READ # 读取访问
XrefType.CALL_FAR # 远调用
XrefType.CALL_NEAR # 近调用
XrefType.JUMP_FAR # 远跳转
XrefType.JUMP_NEAR # 近跳转
XrefType.ORDINARY_FLOW # 顺序执行流
xref_type.is_code_ref() # 检查是否为代码引用
xref_type.is_data_ref() # 检查是否为数据引用FunctionFlags
FunctionFlags
python
from ida_domain.functions import FunctionFlags
FunctionFlags.NORET # Doesn't return
FunctionFlags.LIB # Library function
FunctionFlags.THUNK # Thunk function
FunctionFlags.HIDDEN # Hidden chunk
FunctionFlags.LUMINA # From Lumina
FunctionFlags.FAR # Far function
FunctionFlags.FRAME # Uses frame pointerpython
from ida_domain.functions import FunctionFlags
FunctionFlags.NORET # 不返回
FunctionFlags.LIB # 库函数
FunctionFlags.THUNK # 跳转函数
FunctionFlags.HIDDEN # 隐藏块
FunctionFlags.LUMINA # 来自Lumina
FunctionFlags.FAR # 远函数
FunctionFlags.FRAME # 使用帧指针LocalVariableAccessType
LocalVariableAccessType
python
from ida_domain.functions import LocalVariableAccessType
LocalVariableAccessType.READ # Variable is read
LocalVariableAccessType.WRITE # Variable is written
LocalVariableAccessType.ADDRESS # Address taken (&var)python
from ida_domain.functions import LocalVariableAccessType
LocalVariableAccessType.READ # 变量被读取
LocalVariableAccessType.WRITE # 变量被写入
LocalVariableAccessType.ADDRESS # 取变量地址(&var)LocalVariableContext
LocalVariableContext
python
from ida_domain.functions import LocalVariableContext
LocalVariableContext.ASSIGNMENT # var = expr
LocalVariableContext.CONDITION # if (var)
LocalVariableContext.CALL_ARG # func(var)
LocalVariableContext.RETURN # return var
LocalVariableContext.ARITHMETIC # var + 1
LocalVariableContext.COMPARISON # var == x
LocalVariableContext.ARRAY_INDEX # arr[var]
LocalVariableContext.POINTER_DEREF # *var
LocalVariableContext.CAST # (type)varpython
from ida_domain.functions import LocalVariableContext
LocalVariableContext.ASSIGNMENT # var = expr
LocalVariableContext.CONDITION # if (var)
LocalVariableContext.CALL_ARG # func(var)
LocalVariableContext.RETURN # return var
LocalVariableContext.ARITHMETIC # var + 1
LocalVariableContext.COMPARISON # var == x
LocalVariableContext.ARRAY_INDEX # arr[var]
LocalVariableContext.POINTER_DEREF # *var
LocalVariableContext.CAST # (type)varOperandType
OperandType
python
from ida_domain.operands import OperandType
OperandType.REGISTER # Register
OperandType.MEMORY # Direct memory
OperandType.PHRASE # Register addressing
OperandType.DISPLACEMENT # Reg + displacement
OperandType.IMMEDIATE # Immediate value
OperandType.FAR_ADDRESS # Far address
OperandType.NEAR_ADDRESS # Near addresspython
from ida_domain.operands import OperandType
OperandType.REGISTER # 寄存器
OperandType.MEMORY # 直接内存
OperandType.PHRASE # 寄存器寻址
OperandType.DISPLACEMENT # 寄存器+偏移
OperandType.IMMEDIATE # 立即数
OperandType.FAR_ADDRESS # 远地址
OperandType.NEAR_ADDRESS # 近地址StringType
StringType
python
from ida_domain.strings import StringType
StringType.C # C-style null-terminated
StringType.C_16 # C-style 16-bit
StringType.C_32 # C-style 32-bit
StringType.PASCAL # Pascal-style
StringType.LEN2 # 2-byte length prefix
StringType.LEN4 # 4-byte length prefixpython
from ida_domain.strings import StringType
StringType.C # C风格空终止字符串
StringType.C_16 # C风格16位字符串
StringType.C_32 # C风格32位字符串
StringType.PASCAL # Pascal风格字符串
StringType.LEN2 # 2字节长度前缀
StringType.LEN4 # 4字节长度前缀SegmentPermissions
SegmentPermissions
python
from ida_domain.segments import SegmentPermissions
SegmentPermissions.READ
SegmentPermissions.WRITE
SegmentPermissions.EXEC
SegmentPermissions.ALLpython
from ida_domain.segments import SegmentPermissions
SegmentPermissions.READ
SegmentPermissions.WRITE
SegmentPermissions.EXEC
SegmentPermissions.ALLAddressingMode
AddressingMode
python
from ida_domain.segments import AddressingMode
AddressingMode.BIT16 # 16-bit segment
AddressingMode.BIT32 # 32-bit segment
AddressingMode.BIT64 # 64-bit segmentpython
from ida_domain.segments import AddressingMode
AddressingMode.BIT16 # 16位段
AddressingMode.BIT32 # 32位段
AddressingMode.BIT64 # 64位段PredefinedClass
PredefinedClass
python
from ida_domain.segments import PredefinedClass
PredefinedClass.CODE
PredefinedClass.DATA
PredefinedClass.CONST
PredefinedClass.STACK
PredefinedClass.BSS
PredefinedClass.XTRNpython
from ida_domain.segments import PredefinedClass
PredefinedClass.CODE
PredefinedClass.DATA
PredefinedClass.CONST
PredefinedClass.STACK
PredefinedClass.BSS
PredefinedClass.XTRNCommentKind
CommentKind
python
from ida_domain.comments import CommentKind
CommentKind.REGULAR # Normal comment
CommentKind.REPEATABLE # Shows at all refs
CommentKind.ALL # Both typespython
from ida_domain.comments import CommentKind
CommentKind.REGULAR # 普通注释
CommentKind.REPEATABLE # 在所有引用处显示
CommentKind.ALL # 两种类型ExtraCommentKind
ExtraCommentKind
python
from ida_domain.comments import ExtraCommentKind
ExtraCommentKind.ANTERIOR # Before the line
ExtraCommentKind.POSTERIOR # After the linepython
from ida_domain.comments import ExtraCommentKind
ExtraCommentKind.ANTERIOR # 行前注释
ExtraCommentKind.POSTERIOR # 行后注释TypeAttr
TypeAttr
python
from ida_domain.types import TypeAttr
TypeAttr.INT, TypeAttr.UINT
TypeAttr.FLOAT, TypeAttr.DOUBLE
TypeAttr.PTR, TypeAttr.ARRAY
TypeAttr.FUNC, TypeAttr.STRUCT
TypeAttr.UNION, TypeAttr.ENUM
TypeAttr.CONST, TypeAttr.VOLATILEpython
from ida_domain.types import TypeAttr
TypeAttr.INT, TypeAttr.UINT
TypeAttr.FLOAT, TypeAttr.DOUBLE
TypeAttr.PTR, TypeAttr.ARRAY
TypeAttr.FUNC, TypeAttr.STRUCT
TypeAttr.UNION, TypeAttr.ENUM
TypeAttr.CONST, TypeAttr.VOLATILEFlowChartFlags
FlowChartFlags
python
from ida_domain.flowchart import FlowChartFlags
FlowChartFlags.NONE # Default
FlowChartFlags.NOEXT # Don't compute external blocks
FlowChartFlags.PREDS # Compute predecessorspython
from ida_domain.flowchart import FlowChartFlags
FlowChartFlags.NONE # 默认
FlowChartFlags.NOEXT # 不计算外部块
FlowChartFlags.PREDS # 计算前驱块Common Patterns
常见模式
Find All Calls to a Function
查找对指定函数的所有调用
python
func = db.functions.get_function_by_name("malloc")
if func:
for caller in db.xrefs.get_callers(func.start_ea):
print(f"Called from {caller.name} at {caller.ea:#x}")python
func = db.functions.get_function_by_name("malloc")
if func:
for caller in db.xrefs.get_callers(func.start_ea):
print(f"Called from {caller.name} at {caller.ea:#x}")Rename Functions Based on Strings
根据字符串重命名函数
python
for func in db.functions:
for insn in db.functions.get_instructions(func):
for xref in db.xrefs.from_ea(insn.ea):
string = db.strings.get_at(xref.to_ea)
if string and "error" in str(string).lower():
db.functions.set_name(func, f"func_with_error_{func.start_ea:x}")
breakpython
for func in db.functions:
for insn in db.functions.get_instructions(func):
for xref in db.xrefs.from_ea(insn.ea):
string = db.strings.get_at(xref.to_ea)
if string and "error" in str(string).lower():
db.functions.set_name(func, f"func_with_error_{func.start_ea:x}")
breakAnalyze Function Complexity
分析函数复杂度
python
func = db.functions.get_at(ea)
flowchart = db.functions.get_flowchart(func)
print(f"Basic blocks: {len(flowchart)}")
total_edges = sum(block.count_successors() for block in flowchart)
print(f"Cyclomatic complexity: {total_edges - len(flowchart) + 2}")python
func = db.functions.get_at(ea)
flowchart = db.functions.get_flowchart(func)
print(f"Basic blocks: {len(flowchart)}")
total_edges = sum(block.count_successors() for block in flowchart)
print(f"Cyclomatic complexity: {total_edges - len(flowchart) + 2}")Export Function Pseudocode
导出函数伪代码
python
for func in db.functions:
name = db.functions.get_name(func)
try:
pseudocode = db.functions.get_pseudocode(func)
print(f"// {name}")
for line in pseudocode:
print(line)
except RuntimeError:
print(f"// Could not decompile {name}")python
for func in db.functions:
name = db.functions.get_name(func)
try:
pseudocode = db.functions.get_pseudocode(func)
print(f"// {name}")
for line in pseudocode:
print(line)
except RuntimeError:
print(f"// Could not decompile {name}")Find Cross-References to Strings
查找字符串的交叉引用
python
for string in db.strings:
refs = list(db.xrefs.to_ea(string.address))
if refs:
print(f'"{string}" referenced from:')
for xref in refs:
print(f" {xref.from_ea:#x}")python
for string in db.strings:
refs = list(db.xrefs.to_ea(string.address))
if refs:
print(f'"{string}" referenced from:')
for xref in refs:
print(f" {xref.from_ea:#x}")Legacy API (Avoid)
旧版API(避免使用)
The legacy , , APIs still work but are harder to use. Prefer the Domain API for new analysis scripts. Only use legacy APIs when Domain API doesn't expose needed functionality.
idcidautilsida_funcs旧版、、API仍然可用,但使用难度更高。优先使用Domain API开发新的分析脚本。仅当Domain API未提供所需功能时,才使用旧版API。
idcidautilsida_funcs