IDA python使用

IDA python使用

IDA Python是IDA自带插件,可以执行Python的辅助操作

如下图所示可以执行python代码,获取当前光标所在地址

IDA Python由三个独立的模块组成:

  • idc:负责提供IDA中的所有函数功能
  • idautils:负责提供大量实用函数
  • idaapi:负责访问核心IDA API

例如以下模块

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
idc.ScreenEA()函数或here()函数:获取当前光标所在地址
idc.SegName(ea):获取当前地址所在的段(segment)名称
idc.GetDisasm(ea):获取当前地址的反汇编语句
idc.GetMnem(ea):获取当前反汇编语句的操作符
idc.GetOpnd:获取操作数
idaapi.MinEA():获取载入程序的最小的有效地址
idaapi.MaxEA():获取载入的程序最大的有效地址
idaapi.get_inf_structure(), info.is32bit()
idaapi.get_func(ea)

idautils.Functions()# 列出所有的函数,返回的是一个迭代器,其中的所有元素都是函数起始地址
idautils.Strings() # 列出所有字符串,每个字符串都有ea, length和strtype属性
idautils.Names() # 所有的name,包括函数名,字符串名

ida_bytes.get_byte(ea) # 获取一个字节
ida_bytes.get_word(ea) # 获取两个字节
ida_bytes.get_dword(ea) # 获取四个字节

# 修改数据类型,相当于手动操作时在对应位置按"D"
# 这里也可以循环操作,比如一大块内存都是通过bytes表示的,需要换成8bit、16bit或32bit表示可以这样
create_byte(ea, 1)
create_16bit_data(ea, 2) # 第二个参数搞不懂有啥用,就按字节数保持不变通过循环实现吧
create_32bit_data(ea, 4)

# ida_nalt
##################################
get_root_filename() # 获取当前二进制文件的名字
get_imagebase() # 获取加载基址

# ida_search
##################################
find_text(ea, 0, 0, string, ida_search.SEARCH_DOWN) # ea是地址,string是要找的字符,其它的不动就行
# 要跳到下一个位置需要如此更新: ea = idc.next_head(ea)

# ida_xref
##################################
get_first_fcref_to(addr) # 找到第一个引用addr的地址,没有则返回-1(也可能是BADADDR=2^32 - 1)
get_next_fcref_to(addr) # 调用上面的函数之后可以一直调用直到返回-1
get_first_cref_to(addr) # 找第一个代码引用
get_next_cref_to(addr)
get_first_dref_to(addr) # 找第一个数据引用
get_next_dref_to(addr)

# idc
##################################
find_func_end(ea) # 给定一个IDA能够识别的函数的开头,返回函数结尾
prev_head(ea) # ea位置上一条指令的地址(只能看相邻的地址,不能看跳转过来的位置)
next_head(ea) # 下一条指令的地址
get_operand_type(ea, n) # ea是指令地址,n代表第几个参数,感觉这个没啥用
get_operand_value(ea, n) # 获取参数的值
get_strlit_content(ea) # 获取ea位置的字符串,估计这个库在写的时候漏了一个l
print_insn_mnem(ea) # 打印操作码,实用的多,要是一个地址没有数据,那么就会返回空字符串(即'',而不是None)
print_operand(ea, n) # 打印操作数,n从0开始(第0个不是操作码,而是第一个操作数),超出下标的是空字符串''


获取所有函数的名字

1
2
3
4
5
from idautils import Names, Strings, Functions
for name in Names():
for string in Strings():
if int(name[0]) = int(string.ea):
print(hex(name[0]),str(name[1]),str(string))
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
0x14001ad70 _Format 函数运算结果: %d

0x14001ad88 aDD_0 %d %d
0x14001ad90 aDD 输入的数字为:%d %d
0x14001ada8 a10_0 数字大于10

0x14001adb8 a10 数字小于等于10

0x14001add0 a1210D 1 + 2 + ... + 10 = %d

0x14001adf0 aD 最终输出结果: %d

0x14001ae50 stack_premsg Stack around the variable '
0x14001ae70 stack_postmsg ' was corrupted.
0x14001ae88 uninit_premsg The variable '
0x14001ae98 uninit_postmsg ' is being used without being initialized.
0x14001aef0 aTheValueOfEspW The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

0x14001b000 aACastToASmalle A cast to a smaller data type has caused a loss of data. If this was intentional, you should mask the source of the cast with the appropriate bitmask. For example:
char c = (i & 0xFF);
Changing the code in this way will not affect the quality of the resulting optimized code.

0x14001b158 aStackMemoryWas Stack memory was corrupted

0x14001b180 aALocalVariable A local variable was used before it was initialized

0x14001b1c0 aStackMemoryAro Stack memory around _alloca was corrupted

0x14001b1f8 aUnknownRuntime Unknown Runtime Check Error

0x14001b300 aUnknownFilenam Unknown Filename
0x14001b318 aUnknownModuleN Unknown Module Name
0x14001b330 aRunTimeCheckFa_0 Run-Time Check Failure #%d - %s
0x14001b358 aStackCorrupted Stack corrupted near unknown variable
0x14001b388 a2x %.2X
0x14001b390 msg Stack area around _alloca memory reserved by this function is corrupted

0x14001b3f0 aData
Data: <
0x14001b400 aAllocationNumb
Allocation number within this function:
0x14001b438 aSize
Size:
0x14001b448 aAddress0x
Address: 0x
0x14001b460 aStackAreaAroun Stack area around _alloca memory reserved by this function is corrupted
0x14001b4b8 aSSPSZdSDSSSSS %s%s%p%s%zd%s%d%s%s%s%s%s
0x14001b4d8 aAVariableIsBei A variable is being used without being initialized.
0x14001b548 aStackPointerCo Stack pointer corruption
0x14001b568 aCastToSmallerT Cast to smaller type causing loss of data
0x14001b5a0 aStackMemoryCor Stack memory corruption
0x14001b5c0 aLocalVariableU Local variable used before initialization
0x14001b5f8 aStackAroundAll Stack around _alloca corrupted
0x14001b708 ProcName RegOpenKeyExW
0x14001b718 aRegqueryvaluee RegQueryValueExW
0x14001b730 aRegclosekey RegCloseKey
0x14001b830 aPdbopenvalidat PDBOpenValidate5

填充程序

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
from idc import GetDisasm, print_insn_mnem, get_operand_value
from ida_bytes import next_head
from ida_bytes import patch_byte
start = 0x798
end = 0xf67
ea = start
while ea < end:
old_ea = ea
instr1 = GetDisasm(ea)
op1 = print_insn_mnem(ea)
ea = next_head(ea, end)
instr2 = GetDisasm(ea)
op2 = print_insn_mnem(ea)
if (op1 == 'jb' and op2 == 'jnb') or (op1 == 'jnb' and op2 == 'jb'):
value1 = get_operand_value(old_ea, 0)
value2 = get_operand_value(ea, 0)
if value1 = value2:
print(hex(old_ea), instr1)
print(hex(ea), instr2)
print(hex(value1), hex(value2))
print('-' * 30)
old_ea = next_head(ea, end)
ea = value1

for i in range(old_ea, ea):
patch_byte(i, 0x90) # 填充对应位置的数据

ida脚本处理批量程序

1
2
3
4
5
6
7
8
9
10
11
12
13
import os
import subprocess
IDA_PATH = "xxxxx\\IDAPro7.5\\ida64.exe"
PLUGIN_PATH = "xxxx.py"

# 获取所有需要分析的二进制文件路径
ELF_PATH = 'xxxx'
elfs = os.listdir(ELF_PATH)
print('number of elfs:', len(elfs))
for elf in elfs:
elf_path = ELF_PATH + elf
cmd = IDA_PATH + " -c -A -S" + PLUGIN_PATH + " " + elf_path
subprocess.call(cmd)

ida脚本传入参数

1
2
3
4
5
6
7
8
9
10
11
12
13
# 执行的时候按照下面的格式
# 传入的参数应该是命令行能识别的数据,如果按照上面那个批量脚本传一些python数据结构似乎是不行的
# ida -c -A -S"script_path argv[1] argv[2] argv[3]" filepath

# 在脚本文件中
import idc
def main(A, B, C):
pass

if _ name _ = " _ main _ ":
idc.Wait()
main(idc.ARGV[1], idc.ARGV[2], idc.ARGV[3])
idc.Exit(0)

获取所有函数

1
2
3
4
5
6
from idaapi import *

#获取当前程序的函数列表
functions = [get_func_name(x) for x in Functions()]
for function in functions:
print(function)
打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2021-2024 John Doe
  • 访问人数: | 浏览次数:

让我给大家分享喜悦吧!

微信