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(),用来查询哪个地方调用了这个地址。
二、函数调用的统计
每当检索到函数调入的时候,就下一个断点。需要继承DBG_Hooks,实现其中的函数。
脚本运行完后,自动对每个函数调用设置了断点,并且断点属性是不用停下来,继续执行。然后执行调试的时候,响应的处理动作就会被执行。
三、函数栈大小
栈对于程序的运行有着重要的作用,对我们分析程序来讲更为重要。通过下面中的几个函数,我们可以得到程序在函数调用时的栈内信息,这对于我们分析函数和其参数意义重大。下面脚本是在统计每个函数调用时栈内参数的大小。
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(),用来查询哪个地方调用了这个地址。
- from idaapi import *
- f1 = file('danger_call.txt','w')
- danger_funcs = ["strcpy","sprintf","strncpy"]
- for func in danger_funcs:
- addr = LocByName(func)
- if addr != BADADDR:
- cross_refs = CodeRefsTo(addr, 0)
- f1.write("################\n")
- for ref in cross_refs:
- f1.write(str(hex(ref)) + '\n')
- f1.close()
二、函数调用的统计
每当检索到函数调入的时候,就下一个断点。需要继承DBG_Hooks,实现其中的函数。
- from idaapi import *
- class FuncCov(DBG_Hooks):
- # breakpoint handler
- def dbg_bpt(self,tid,ea):
- print hex(ea)
- return
- #def dbg_library_load(self, pid, tid, ea, name, base, size):
- print name
- return
- debugger = FuncCov()
- debugger.hook() #set hook
- current_addr = ScreenEA()
- for f in Functions(SegStart(current_addr), SegEnd(current_addr)):
- #print f
- AddBpt(f) #set breakpoint
- SetBptAttr(f, BPTATTR_FLAGS,0x0)
- num_breakpoints = GetBptQty() #return number of breakpoint
- print "Set %d breakpoints." %num_breakpoints
脚本运行完后,自动对每个函数调用设置了断点,并且断点属性是不用停下来,继续执行。然后执行调试的时候,响应的处理动作就会被执行。
三、函数栈大小
栈对于程序的运行有着重要的作用,对我们分析程序来讲更为重要。通过下面中的几个函数,我们可以得到程序在函数调用时的栈内信息,这对于我们分析函数和其参数意义重大。下面脚本是在统计每个函数调用时栈内参数的大小。
- from idaapi import *
- var_size_threshold = 16
- current_addr = ScreenEA()
- for f in Functions(SegStart(current_addr), SegEnd(current_addr)):
- stack_frame = GetFrame(f) #get frame of stack
- frame_size = GetStrucSize(stack_frame) #compute size of stackframe
- frame_counter = 0
- prev_count = -1
- distance = 0
- while frame_counter < frame_size:
- stack_var = GetMemberName(stack_frame, frame_counter) #get one from stack
- if stack_var != "":
- if prev_count != -1:
- distance = frame_counter - prev_distance
- prev_distance = frame_counter #record last location
- if distance >= var_size_threshold:
- print "[*] Function: %s - > Stack Variable: %s (%d bytes)" % ( GetFunctionName(f), prev_member, distance )
- else:
- prev_count = frame_counter
- prev_distance = frame_counter
- prev_member = stack_var
- try:
- frame_counter = frame_counter + GetMemberSize(stack_frame, frame_counter) #compute offset
- except:
- frame_counter += 1
- else:
- frame_counter += 1