IDApython 笔记

Last updated on October 7, 2023 pm

IDApython学习笔记

基本指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ea = here() #当前光标处地址

asm = idc.GetDisasm(ea) # 获取当前地址的整句汇编指令 如 mov rax 1
op = idc.print_insn_mnem(ea) # 获取当前地址汇编操作,如 mov
operand = idc.print_operand(ea,0) # 获取当前地址汇编操作的操作数,0是第一个操作数,1是第二个操作数,如果超过返回空

_prev_ins = idc.prev_head(ea) # 上一条指令地址
_next_ins = idc.next_head(ea) # 下一条指令地址

_prev_addr = idc.prev_addr(ea) # 上一条指令地址 这里地址是连续的 比如ea = 0x4002 则返回0x4001
_next_addr = idc.next_addr(ea) # 下一条指令地址 这里地址是连续的 比如ea = 0x4001 则返回0x4002

seg_name = idc.get_segm_name(ea) #当前地址所处段
for seg in Segments(): # 获得每个段起始地址 返回值为每个段起始地址
print(seg)

for func in Functions():# 获得每一个函数名字
print(idc.get_func_name(func))

函数

基本指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
name = idc.get_func_name(ea) #当前地址所属函数名字
func = ida_funcs.get_func(ea) #当前地址所属函数 返回一个func_t对象
func = idaapi.get_func(ea) #功能同上

# 利用func_t对象,有如下几个操作
func_start = func.start_ea #该函数起始地址
func_end = func.end_ea #该函数结束地址 注意结束地址是此函数最后一条指令的下一条指令地址

func_start = idc.get_func_attr(ea, FUNCATTR_START) # 此地址所属函数起始地址 FUNCATTR_START是宏 等于0
func_end = idc.get_func_attr(ea,FUNCATTR_END)# 此地址所属函数结束地址 同func_end FUNCATTR_END是宏 等于8

# 获取上一个函数起始地址
idc.get_prev_fchunk(ea)
idc.get_prev_func(ea)

# 获取下一个函数起始地址
idc.get_next_fchunk(ea)
idc.get_next_func(ea)

交叉引用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
xrefs = XrefsFrom(ea,0)
# 返回一个xref列表对象,以此ea为起点,可以有如下操作
for xref in xrefs:
xref.frm # 起点
xref.to # 终点,即此函数可以跳去哪
#第二个参数是选取交叉引用范围,0,默认是全部 ,1 是远跳转 2 是数据引用

xrefx = XrefsTo(ea,0)
# 返回一个xref列表对象,以此ea为终点,可以有如下操作
for xref in xrefs:
xref.frm # 何处来,即谁调用了它
xref.to # 何处去,即它可以去哪里
#第二个参数是选取交叉引用范围,0,默认是全部 ,1 是远跳转 2 是数据引用
# 一般用此函数找引用

xref = CodeRefsFrom(ea,0)
# 与 XrefsFrom含义一样,不过返回的是list对象,也只有远跳转,第二参数控制流向,即上面的 frm 和 to 对应
xref = CodeRefsTo(ea,0)
# 与 XrefsTo含义一样,不过返回的是list对象,第二参数控制流向,即上面的 frm 和 to 对应

ref = ida_xref.get_first_dref_to(addr)
# 得到引用此变量的首条语句地址 如果没有返回-1 这个是仅变量的交叉引用 无法查看函数的交叉引用,但是XrefXXXX都可以查看
nex_ref = ida_xref.ger_next_derf_to(addr,ref)
# 得到引用此变量的在ref的下条语句地址 如果没有返回-1 这个是仅变量的交叉引用 无法查看函数的交叉引用,但是XrefXXXX都可以查看

func_addr =idc.get_name_ea_simple(func_name) # 通过函数名字获得该函数地址 如果没有该函数返回-1

一些个交叉引用使用方式

patch掉所有call危险函数的地方

1
2
3
4
5
6
7
8
danger_func = ['gets','free']
for func in danger_func:
func_addr = idc.get_name_ea_simple(func)
xrefs = CodeRefsTo(func_addr,0)
for xref in xrefs:
if idc.GetDisasm(xref).startswith('call'):
len = next_head(xref) - xref
idaapi.patch_bytes(xref,b'\x90'*len)

处理ea到end之间所有的数据

1
2
3
4
5
for addr in range(ea,end,4):
xrefs = XrefsTo(ea)
for xref in xrefs:
if 'mov' in GetDisasm(xref.frm):
# your method

Block

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ea = here()
func = idaapi.get_func(ea)
CFG = idaapi.FlowChart(func) # 此函数的CFG

for blocks in CFG:
print(blocks.start_ea) # 每一个block的起始地址
print(block.end_ea) # 每一个block的结束地址 但注意 结束地址是下一个block的起始地址
print()

for succ in blocks.succs(): # 每一个block的后继
print(succ.start_ea)
print(succ.end_ea)

for pred in blocks.preds() # 每一个block的前驱
print(pred.start_ea)
print(pred.end_ea)

获取数据

1
2
3
4
5
6
idc.get_wide_byte(ea) // 获取单字节
idc.get_wide_word(ea) // 获取一个字
idc.get_wide_dword(ea) // 获取双字
idc.get_qword(ea) // 获取四字
idc.GetFloat(ea)
idc.GetDouble(ea)

补丁

1
2
3
4
patch_byte(ea, value)
patch_word(ea, value)
patch_dword(ea, value)
patch_qword(ea, value)

IDApython 笔记
http://example.com/2023/06/24/IDApython/
Author
yring
Posted on
June 24, 2023
Licensed under