获取地址处的值
idc.get_wide_byte(addr)
:以 1 字节为单位获取地址处的值idc.get_wide_word(addr)
:以 2 字节(字)的单位获取地址处的值idc.get_wide_dword(addr)
:以 4 字节的单位获取地址处的值idc.get_qword(addr)
:以 8 字节的单位获取地址处的值idc.get_bytes(addr, len)
:获取addr
地址处len
长度的数据idc.get_item_size(addr)
:获取addr
地址处的数据大小,例如汇编指令长度。
修改地址处的值
ida_bytes.patch_byte(addr, value)
:修改addr
地址的值为value
,每次修改 1 个字节。ida_bytes.patch_word(addr, value)
:每次修改 2 个字节ida_bytes.patch_dword(addr, value)
:每次修改 4 个字节ida_bytes.patch_qword(addr, value)
:每次修改 8 个字节idc.patch_bytes(addr, data)
:在addr
地址处写入data
(bytes 类型数据)
修改地址处的类型
idc.del_items(addr)
:去除目标地址处数据的属性。idc.create_insn(addr)
:将目标地址处的数据设置为代码。有可能会失败,可以与ida_name.set_name(addr, '')
配合来避免失败。
汇编指令操作
idc.GetDisasm(addr)
或idc.generate_disasm_line(addr,flags)
:获取地址处的汇编语句,这里flags
通常为 0 。idc.print_operand(addr,index)
:获取指定地址addr
的汇编指令的第index
个操作数(字符串形式),如果index
索引超过操作数的个数则返回空字符串。下面简单举几个例子感受一下:
汇编 | inxex = 0 | index = 1 |
---|---|---|
pop rax |
rax |
‘’ |
mov [rsp+10h], rax |
[rsp+10h] |
rax |
call $+5 |
$+5 |
‘’ |
add rax, 68FBh |
rax |
68FBh |
jz short loc_1400100CC |
loc_1400100CC |
‘’ |
popfq |
‘’ | ‘’ |
retn |
‘’ | ‘’ |
idc.get_operand_type(addr, index)
:获取操作数的类型。
o_void (0)
:无效操作数,表示没有操作数。o_reg (1)
:寄存器操作数,表示一个寄存器。o_mem (2)
:内存操作数,表示一个内存地址。o_phrase (3)
:短语操作数,表示根据寄存器和偏移量计算的内存地址。o_displ (4)
:带偏移量的内存操作数,表示根据寄存器、偏移量和可选标志寄存器计算的内存地址。o_imm (5)
:立即数操作数,表示一个立即数值。o_far (6)
:远跳转操作数,表示一个远跳转地址。o_near (7)
:相对跳转操作数,表示一个相对于当前指令地址的跳转地址。
idc.get_operand_value(addr, index)
:获取指定索引操作数中的值。
- 对于寄存器操作数 (
o_reg
),返回寄存器的编号。 - 对于内存操作数 (
o_mem
),返回内存地址的值。 - 对于立即数操作数 (
o_imm
),返回立即数的值。 - 对于相对跳转操作数 (
o_near
),返回跳转的地址。 - 对于其他特定于处理器的操作数类型,返回相应的值,具体含义需要参考相关文档。
idc.print_insn_mnem(addr)
:获取指定地址addr
的汇编指令的操作指令(如 mov、add)。idc.next_head(addr)
:获取当前地址的汇编的下一条汇编的地址。idc.prev_head(addr)
:获取当前地址的汇编的上一条汇编的地址。
由于 IDA Python 没有有效的汇编功能且 idc.generate_disasm_line(addr,flags)
反汇编出的汇编代码与主流的反汇编器 keystone_engine 不通用,因此通常利用 keystone_engine 与 capstone 结合来实现汇编与反汇编功能。
from keystone import *
from capstone import *
asmer = Ks(KS_ARCH_X86, KS_MODE_64)
disasmer = Cs(CS_ARCH_X86, CS_MODE_64)
def disasm(machine_code, addr=0):
l = “”
for i in disasmer.disasm(machine_code, addr):
l += “{:8s} {};\n”.format(i.mnemonic, i.op_str)
return l.strip(‘\n’)
def asm(asm_code, addr=0):
l = b’’
for i in asmer.asm(asm_code, addr)[0]:
l += bytes([i])
return l
段操作
idc.get_segm_name(addr)
:获取地址addr
所在段的名字(参数为当前的地址)。idc.get_segm_start(addr)
:获取地址addr
所在段的开始地址idc.get_segm_end(addr)
:获取地址addr
所在段的结束地址idc.get_first_seg()
:获取第一个段的地址idc.get_next_seg(addr)
:获取地址大于addr
的第一个段的起始地址idautil.Segments()
:返回一个列表记录所有段的地址
遍历所有的段
import idc
import idaapi
import idautils
for seg_addr in idautils.Segments():
segname = idc.get_segm_name(seg_addr)
segstart = idc.get_segm_start(seg_addr)
segend = idc.get_segm_end(seg_addr)
print(“段名:” + segname + " 起始地址:" + hex(segstart) + " 结束地址:" + hex(segend));
函数操作
idautils.Functions(startaddr,endaddr)
:获取指定地址之间的所有函数idc.get_func_name(addr)
:获取指定地址所在函数的函数名get_func_cmt(addr, repeatable)
:获取函数的注释
repeatable
:0 是获取常规注释,1 是获取重复注释。
idc.set_func_cmt(ea, cmt, repeatable)
:设置函数注释idc.choose_func(title)
:弹出选择框要求用户进行选择函数,返回值为用户选择的函数的地址,若直接关闭选择框则返回值为 0xffffffffffffffff 。idc.get_func_off_str(addr)
:寻找函数结尾,如果函数存在则返回结尾地址,否则返回BADADDR
。ida_funcs.set_func_end(addr, newend)
:设置函数结尾为newend
ida_funcs.set_func_start(addr, newstart)
:设置函数开头为newstart
idc.set_name(addr, name)
:设置地址处的名字为name
idc.get_prev_func(addr)
:获取addr
所在函数的前一个函数的地址idc.get_next_func(addr)
:获取addr
所在函数的后一个函数的地址ida_funcs.add_func(addr)
:在addr
地址创建函数
遍历 .text
段内的所有函数
import idc
import idaapi
import idautils
for seg in idautils.Segments():
segname = idc.get_segm_name(seg)
segstart