t听学长说IDA python很有用,今天就来抽空学习一下。
环境
例子下载:
[](https://buuoj.cn/challenges#[网鼎杯 2020 青龙组]jocker)
工具 | 版本 |
---|---|
python | 3.11.3 |
ida pro | 7.7 |
IDA python介绍
IDA在7.5版本更新后支持python3
,原来的很多函数都有了改变,接下来就来介绍一下改变前后的函数以及它的作用。
获取地址
函数作用 | 函数 |
---|---|
获取光标当前地址 | idc.here() 或 idc.get_screen_ea() |
获取最小地址(可以使用的) | ida_ida.inf_get_min_ea() |
获取最大地址(可以使用的) | ida_ida.inf_get_max_ea() |
获取所选范围的起始地址 | idc.read_selection_start() |
获取所选范围的结束地址 | idc.read_selection_end() |
判断地址是否存在 | idaapi.BADADDR |
这些函数都不需要参数
代码如下,我选中的区域就是部分main函数
1 | print(hex(idc.here())) |
note warning 注意
使用idc.read_selection_start()
和idc.read_selection_end()
是需要使用光标选中两行及以上的,不然就会返回0xffffffff
获取地址的值
获取地址的数值 | |
---|---|
以1字节为单位获取值 | idc.get_wide_byte(addr) |
以2字节(字)的单位获取值 | idc.get_wide_word(addr) |
以4字节的单位获取值 | idc.get_wide_dword(addr) |
以8字节的单位获取值 | idc.get_qword(addr) |
得到运行断点之前的寄存器的值 | ea=get_reg_value(“eax”) |
代码如下
1 | import idc |
修改指令的值
作用 | 函数 |
---|---|
修改addr地址的值为value.每次修改1个字节 | ida_bytes.patch_byte(addr,value) |
每次修改2个字节 | ida_bytes.patch_word(addr,value) |
每次修改4个字节 | ida_bytes.patch_Dword(addr,value) |
每次修改8个字节 | ida_bytes.patch_Qword(addr,value) |
测试代码
1 | ea = idc.get_screen_ea() |
段操作
作用 | 函数 |
---|---|
获取段的名字(参数为当前的地址) | idc.get_segm_name(addr) |
获取段的开始地址 | idc.get_segm_start(addr) |
获取段的结束地址 | idc.get_segm_end(addr) |
获取第一个段 | idc.get_first_seg(addr) |
获取下一个段 | idc.get_next_seg(addr) |
返回一个列表记录所有段的地址 | idautil.Segments() |
代码
1 | for seg in idautils.Segments(): |
函数操作
作用 | 函数 |
---|---|
获取指定地址之间的所有函数 | idautils.Functions(startaddr,endaddr) |
获取指定地址的函数名 | idc.get_func_name(addr) |
获取函数的注释 | get_func_cmt(addr, repeatable) repeatable:0/1 0是获取常规注释 1是获取重复注释 |
设置函数注释 | idc.set_func_cmt(ea, cmt, repeatable) |
弹出框框要求用户进行选择 参数则是信息 | idc.choose_func(title) |
返回: addr 距离函数的偏移形式 | idc.get_func_off_str(addr) |
寻找函数结尾,如果函数存在则返回结尾地址,否则返回BADADDR | idc.find_func_end(addr) |
设置函数结尾 | ida_funcs.set_func_end(ea, newend) newend:新的结束地址 |
设置函数开头 | ida_funcs.set_func_start(addr, newstart) |
设置地址处的名字 | idc.set_name(ea, name, SN_CHECK) Ex函数也使用set_name |
获取首个函数 | idc.get_prev_func(ea) |
获取下一个函数 | idc.get_next_func(ea) |
代码:
1 | for seg in idautils.Segments(): |
练手
网鼎杯 2020 青龙组 Jocker
还是最开始的那道程序
可以看到encrypt
函数去异或0x41,这就是一个很典型的SMC(self modifying code)操作。我们要做的就是让这段for循环运行起来,可以动态调试或者写ida python
脚本运行。这里不再讲动态调试,我们要做的就是找到encrypt
函数的地址,接着去获取该地址处的值,异或0x41来还原即可。
encrypt的地址:0x41500
脚本:
1 | addr = 0x401500 |
之后选中整段函数,重新分析(快捷键C),之后生成函数(快捷键P),即可还原函数