ida python使用
idapython脚本
ida 中内置python2和idc两种形式的脚本
一般我们使用ida python
# 关于数据
# 获取数据
对于程序内的地址可以直接引用, 然后获取其数据需要以对应的数据类型获取数据,如: Byte()
, Dword()
,
获取数据的脚本大致如下:
addr = 0xaaaa
arr = []
for i in range(xxx):
arr.append(Byte(addr + i))
arr.append(Dword(addr + 4 * i))
print(arr)
2
3
4
5
6
# 设置数据
设置数据类型,使用MakeQword(addr)
, MakeDword(addr)
, 将对应地址设置为所需要的类型,
# 修改数据
ida python 中提供对应的函数为:PatchByte(addr, byte)
会将地址addr中的数据替换为byte, 注意参数12分别为地址和数据,
一般常用在自解密的文件,我们使用ida python脚本可以自己解密出来正确的数据,
自解密的话我们也要对应的原本的数值,注意在程序内的取地址内数值用
Byte(addr)
,下面简单演示一个异或的情况的自解密。
addr = 0xaaaa
for i in range(xxxx):
PatchByte(addr +i, Byte(addr + i)^ 0x123)
2
3
# 字符串相关
使用GetStr(addr)
获取一个从指定位置开始的c语言风格字符串(以'\x00'结尾的), 也可以使用MakeStr(start_addr, end_addr)
设置指定长度的字符串,
warning
在ida 7.0中MakeStr会报错, 问题在于目录 ida/python 中python的api转接到idc的位置出现参数错误,修改如下:
# /ida/python/idc_bc695.py
# 原
def MakeStr(ea, endea): return create_strlit(ea, 0 if (endea) == ida_idaapi.BADADDR else endea-ea)
# 修改后
def MakeStr(ea, endea): return create_strlit(ea, endea)
2
3
4
5
# 设置注释
MakeComm(addr, dec)
# dump 程序
ida并没有直接提供dump的功能, 我们可以通过脚本实现,
import idaapi
data = idaapi.dbg_read_memory(start_address, data_length)
fp = open('path/to/dump', 'wb')
fp.write(data)
fp.close()
2
3
4
5
6
# 宏观结构和相关操作
# 函数
Functions(start, end)
可以获取指定范围内的函数的起始地址, 如果没有参数默认为从text段开头到结束, 即 所有的function,
# 段
查找段: get_seg_byname(str)
返回对应的段对象,
# 符号
符号,命名称为Name, 使用Names()
可以获得相对应的所有位置的命名,
MakeName(addr, dec)
可以定名符号,
在设置命名时, ida中有一定的规则, 我们一般需要洗掉一些不能非法字符:
STRIP_CHARS = ['(', ')', '[', ']', '{', '}', ' ', '"']
REPLACE_CHARS = ['.', '*', '-', ',', ';', ':', '/', '\xb7']
def clean_function_name(in_str):
# Kill generic 'bad' characters
s = ""
for c in in_str.decode():
if c in string.printable:
s += c
for c in STRIP_CHARS:
s = s.replace(c, '')
for c in REPLACE_CHARS:
s = s.replace(c, '_')
return s
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 动态调试相关
然后在动调主要使用到的函数:
AddBpt(long Address)
: 在指定的地址设置断点
GetRegValue(string Register)
:获取一个寄存器的名称
SetRegValue(long Value, string Register)
设置寄存器的值
RunTo(long Address)
: 运行到指定的地址,然后停下。
GetDebuggerEvnt(WFNE_SUSP, -1)
:应该是获取调试某一过程中信息,一般就在RunTo()
后和操作寄存器前使用,解决脚本和调试异步而导致的寄存器读取报错的问题
一般使用的:
- 用于程序运行, 获取相关位置,设定相关寄存器。
RunTo(xxxx)
GetDebuggerEvent(WFNE_SUSP, -1)
SetRegValue(xxx, 'xxx')
xxx = GetRegValue("xxx")
2
3
4
- 获取栈内数据:
RunTo(xxx)
GetDebuggerEvent(WFNE_SUSP, -1)
stack = GetRegValue("esp")
2
3
这样,运行到某个位置,获取esp/rsp的值,为栈顶,通过偏移可以获取相对应的栈内地址,然后使用Byte()
/ Dword()
来获取相关数据,如果需要的话我们还可以通过PatchByte(long Addr, byte)
来进行数据的修改,
- 程序多次运行
idapyhton似乎是不可以多次重复调动调试,但是我们可以通过修改eip/rip来让其重复运行一段位置,一般进行爆破。
这个时候要注意的是修改eip/rip回跳的位置,要慎重选择。
# 插件制作
一些ida插件的技巧。
# golang_rev
目前仿造lazy_ida写的一个插件,用于在golang逆向中快速恢复符号,设置字符串,
warning
占坑,慢慢写