Lingze's blog Lingze's blog
timeline
about
friends
categories
tags

lingze

bin不是垃圾桶的意思!
timeline
about
friends
categories
tags
  • tools
lingze
2020-07-12

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)
1
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)
1
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)
1
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()
1
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
1
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")
1
2
3
4
  • 获取栈内数据:
RunTo(xxx)
GetDebuggerEvent(WFNE_SUSP, -1)
stack = GetRegValue("esp")
1
2
3

这样,运行到某个位置,获取esp/rsp的值,为栈顶,通过偏移可以获取相对应的栈内地址,然后使用Byte()/ Dword()来获取相关数据,如果需要的话我们还可以通过PatchByte(long Addr, byte)来进行数据的修改,

  • 程序多次运行

idapyhton似乎是不可以多次重复调动调试,但是我们可以通过修改eip/rip来让其重复运行一段位置,一般进行爆破。

这个时候要注意的是修改eip/rip回跳的位置,要慎重选择。

# 插件制作

一些ida插件的技巧。

# golang_rev

目前仿造lazy_ida写的一个插件,用于在golang逆向中快速恢复符号,设置字符串,

warning

占坑,慢慢写

#reverse#ida#ida_python
上次更新: 2/24/2021, 2:44:29 PM
Theme by Vdoing | Copyright © 2019-2021 lingze | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式