Logo 逆向知识库

IDA Python

常用的代码

参考#

  • 示例代码在 /opt/ida-pro/python/examples
  • IDAPython 官方文档 其实并没有什么用,不如直接看源码

 

补全#

在 .py 文件顶部加上

import sys
sys.path.append("/opt/ida-pro/python")

这里的 /opt/ida-pro/ 换成 ida 安装目录,代码补全就会自动识别了(vim+ycm可以识别)

根据 /opt/ida-pro/python/idautils.py ,以下面的代码作为头部,可以获得与 IDA 内 Python 解释器相同的环境,复制代码只需要赋值除了头以外的即可执行

# IDA default imports
# ====================================
import sys
sys.path.append("/opt/ida-pro/python")
import ida_bytes
import ida_dbg
import ida_entry
import ida_funcs
import ida_ida
import ida_idaapi
import ida_idd
import ida_idp
import ida_kernwin
import ida_loader
import ida_nalt
import ida_name
import ida_netnode
import ida_segment
import ida_strlist
import ida_typeinf
import ida_ua
import ida_xref

import idc
import types
import os
import sys
# ====================================

 

 

一些概念#

EA#

EA 是 Effective Address(有效地址)的缩写

 

UA#

ida_ua 是 IDA Pro 的反汇编引擎接口模块,UA 代表 Universal Assembler(通用汇编器)。它提供了底层的指令分析功能。

def analyze_instruction(ea):
    # 创建指令对象
    insn = ida_ua.insn_t()
    
    # 解码指令
    length = ida_ua.decode_insn(insn, ea)
    if length <= 0:
        return "Not a valid instruction"
    
    # 获取指令信息
    print(f"指令长度: {length}")
    print(f"指令类型: {insn.itype}")
    print(f"操作数数量: {insn.Op1.type != ida_ua.o_void}")
    
    # 分析操作数
    for i in range(8):  # UA_MAXOP = 8
        op = insn.ops[i]
        if op.type == ida_ua.o_void:
            break
        print(f"操作数 {i}:")
        print(f"  类型: {op.type}")  # o_reg(寄存器), o_imm(立即数)等
        print(f"  值: {op.value}")

 

ida_name#

名称对应地址?

 

信息类#

模块/类函数描述
ida_nameget_name_ea(_from, name)获取函数名对应的地址,如果失败,就返回 ida_idaapi.BADADDR
ida_funcsget_func(ea)获取一个 ida_funcs.func_t 对象,常用 start_ea 和 end_ea 属性
 del_func(ea) 
idautilsHeads(start_ea, end_ea)返回一个 Generator,包含指令/数据的头 地址
idcprint_insn_mnem(ea)汇编的 mnemonic,如 call, lea
 print_operand(ea, n)汇编的第 n 个操作数
 0000021800000218000002180000021800000218000002180000021800000218000002180000021800000218000002180000021800000218000002180000021800000218获取完整的汇编指令
ida_uainsn_t()初始化一个 ida_ua.insn_t 对象,用于之后的指令解析
 decode_insn(out: 'insn_t', ea) -> int解析位于 ea 的指令,返回长度(一般只用于长度,因为其他参数都过于底层)
ida_ua.insn_tOp1, Op2…, Op8ida_ua.op_t,即 opcode 常用属性 ida_ua::type ,详见附录I
 ops: list同上,只是以列表的形式
ida_idpget_reg_name(reg: int, width: 'size_t', reghi: int)根据寄存器号获取寄存器的名字
 ph_get_regnames()当前处理器可用寄存器
ida_bytesida_bytes.create_strlit(ea,len,ida_nalt.STRTYPE_C)相当于用户在地址上按 “A”
idaapiprev_head(ea, minea)获取上一条汇编(或Head)

 

Patch 类#

ida_bytes.patch_byte(ea, x:int)
ida_bytes.patch_bytes(ea, buf:bytes)

 

ida_funcs.func_t#

  • start_ea
  • end_ea

 

附录I ida_ua.insn_t 的 Op 类型#

以下描述均可在 ida-pro/python/ida_ua.py 中找到

常量描述
ida_ua.o_void0空类型,意思是当前位置没有 opcode,且之后也没有了
ida_ua.o_reg1寄存器,寄存器存在 op_t::reg,可以用 ida_idp.get_reg_name 获取名字
ida_ua.o_mem2直接内存引用(数据),可用 op_t::addr 获取地址。[] 中的只能是数据,例如 [0x1234]
ida_ua.o_phrase3内存引用[基寄存器+定位寄存器]。注意框中不能有常数(除了缩放),有的话就是 o_displ
ida_ua.o_displ4内存引用[基寄存器+定位寄存器+偏移],可用 op_t:addr 获取偏移。
ida_ua.imm5立即数,可用 op_t::value 获取值。
ida_ua.o_far6远地址,可用 op_t::addr 获取
ida_ua.o_near7近地址,可用 op_t::addr 获取

这里的 phrase 定义还是未知的,目前只能猜。比如 [rax] 是 0,[rax+rcx] 是 4,[rcx] 是 1