IDAPython是IDA的一款插件。将python和ida结合起来,利用python语言就可以更加自动化的分析程序。

IDA5版本里没有带这个插件,需要自己装,并且目前不支持python2.6+。所以还是用IDA6吧,内置自带IDAPython。

这个插件内部的脚本放在ida主目录的python目录里,里面有4个py,idaapi.py,idautils.py,idc.py,init.py,下面将会遇到的函数也都出自这里。


使用这个插件的方式有三种:
1.打开IDA后,在界面最下面(状态栏上面)的那行,可以输入命令脚本,但仅限一行。
2.菜单栏File-python command里可以输入命令脚本。
3.菜单来File-Script file里可以导入命令脚本文件。

很明显,想要达到“分析”的效果,必须使用第三种方法(快捷键Alt+F7)。熟练使用下面讲的一些函数后,根据我们特定的需求写出python脚本来,就可以达到快速的分析。在脚本处理是地址一般默认也是用十进制表示,出于习惯可以自行转换为十六进制。

首先,它可以使用所有的IDC函数。其次,它有一些特有的函数,并且python语言的特定都可以使用。手工分析总会在Pure Code,Externs,Pure Data各个段中庞大的数据弄的脑袋短路IDAPython帮我们把我们经常要做的比较繁琐的事情模块化为函数,主要是下面4种:
1.段的地址操作
2.函数的处理
3.交叉引用的检索
4.调试器Hook(需要选一个调试器)

透过下面的三个例子,我们来初步认识一下idapython的这四种函数的使用。

一、特定敏感系统函数调用的提取
下面的代码选了"strcpy","sprintf","strncpy"三个库函数作为监控对象,检索程序对它的调用。这里用到了CodeRefsTo(),用来查询哪个地方调用了这个地址。

[python] 

1. from idaapi import *  
2. f1 = file('danger_call.txt','w')  
3. danger_funcs = ["strcpy","sprintf","strncpy"]  
4. for func in danger_funcs:  
5.         addr = LocByName(func)  
6. if addr != BADADDR:  
7. 0)  
8. "################\n")  
9. for ref in cross_refs:  
10. '\n')  
11.   
12.   
13. f1.close()



二、函数调用的统计


每当检索到函数调入的时候,就下一个断点。需要继承DBG_Hooks,实现其中的函数。


[python] 

1. from idaapi import *  
2. class FuncCov(DBG_Hooks):  
3. # breakpoint handler  
4. def dbg_bpt(self,tid,ea):  
5. print hex(ea)  
6. return  
7. #def dbg_library_load(self, pid, tid, ea, name, base, size):  
8. print name  
9. return  
10.                   
11. debugger = FuncCov()  
12. debugger.hook()        #set hook  
13.   
14.   
15. current_addr = ScreenEA()  
16. for f in Functions(SegStart(current_addr), SegEnd(current_addr)):  
17. #print f  
18. #set breakpoint  
19. 0x0)  
20.   
21.   
22. num_breakpoints = GetBptQty()        #return number of breakpoint  
23. print "Set %d breakpoints." %num_breakpoints



脚本运行完后,自动对每个函数调用设置了断点,并且断点属性是不用停下来,继续执行。然后执行调试的时候,响应的处理动作就会被执行。




三、函数栈大小


栈对于程序的运行有着重要的作用,对我们分析程序来讲更为重要。通过下面中的几个函数,我们可以得到程序在函数调用时的栈内信息,这对于我们分析函数和其参数意义重大。下面脚本是在统计每个函数调用时栈内参数的大小。


[python] 

1. from idaapi import *  
2. var_size_threshold = 16  
3. current_addr = ScreenEA()  
4.   
5.   
6. for f in Functions(SegStart(current_addr), SegEnd(current_addr)):  
7. #get frame of stack  
8. #compute size of stackframe  
9.   
10.   
11. 0  
12. 1  
13. 0  
14.   
15.   
16. while frame_counter < frame_size:  
17. #get one from stack  
18. if stack_var != "":  
19. if prev_count != -1:  
20.                                 distance = frame_counter - prev_distance  
21. #record last location  
22.                                   
23. if distance >= var_size_threshold:  
24. print  "[*] Function: %s - > Stack Variable: %s (%d bytes)" % ( GetFunctionName(f), prev_member, distance )    
25. else:  
26.                                 prev_count = frame_counter  
27.                                 prev_distance = frame_counter  
28.                                 prev_member = stack_var  
29. try:  
30. #compute offset  
31. except:  
32. 1  
33. else:  
34. 1