返回介绍

15.7 IDAPython 脚本示例

发布于 2024-10-11 21:05:45 字数 3693 浏览 0 评论 0 收藏 0

为将 IDC 与 IDAPython 进行比较,在下面几节中,我们将提供与前面讨论 IDC 时相同的示例。我们尽可能充分利用特定于 Python 的功能,以在一定程度上说明以 Python 编写脚本所带来的效率。

15.7.1 枚举函数

IDAPython 的一个主要优点在于,它使用 Python 的强大数据类型来简化对数据库对象集合的访问。在代码清单 15-8 中,我们以 Python 重新实现了代码清单 15-1 列出的函数枚举脚本。回想一下,这段脚本的目的在于遍历数据库中的每一个函数,并打印出与每个函数有关的基本信息,包括函数的起始和结束地址、函数参数的大小、函数的局部变量空间的大小。所有输出全部在消息窗口中显示。

代码清单 15-8 使用 Python 枚举函数

funcs = Functions()➊  
for f in funcs: ➋  
   name = Name(f)  
   end = GetFunctionAttr(f, FUNCATTR_END)  
   locals = GetFunctionAttr(f, FUNCATTR_FRSIZE)  
   frame = GetFrame(f)     # retrieve a handle to the function’s stack frame  
   if frame is None: continue  
   ret = GetMemberOffset(frame, " r")  # " r" is the name of the return address  
   if ret == -1: continue  
   firstArg = ret + 4  
   args = GetStrucSize(frame) – firstArg  
   Message("Function: %s, starts at %x, ends at %x\n" % (name, f, end))  
   Message("   Local variable area is %d bytes\n" % locals)  
   Message("   Arguments occupy %d bytes (%d args)\n" % (args, args / 4))  

在这段特殊的脚本中,使用 Python 除了用到有助于执行➋处 for 循环的 Functions (➊)列表生成器外,并没有为我们提高多大效率。

15.7.2 枚举指令

代码清单 15-9 说明如何利用 idautils 模块中的列表生成器以 Python 编写代码清单 15-2 列出的指令计数脚本。

代码清单 15-9 使用 Python 枚举指令

from idaapi import *  
func = get_func(here())➊   # here() is synonymous with ScreenEA()  
if not func is None:  
   fname = Name(func.startEA)  
   count = 0  
   for i in FuncItems(func.startEA) ➋ : count = count + 1  
   Warning("%s contains %d instructions\n" % (fname,count))  
else:  
   Warning("No function found at location %x" % here())

与 IDC 版本的不同包括使用 SDK 函数(➊,通过 idaapi 访问)来检索对函数对象(具体为 func_t )的引用,并使用 FuncItems 生成器(➋,取自 idautils )以便于遍历函数内的所有指令。由于我们无法在生成器上使用 Python 的 len 函数,因此我们仍然需要检索生成器列表,以逐个计算每一条指令。

15.7.3 枚举交叉引用

idautils 模块包含几个生成器函数,使用它们可以生成比我们在 IDC 中看到的列表更直观的交叉引用列表。代码清单 15-10 重写了我们之前在代码清单 15-3 中看到的函数调用枚举脚本。

代码清单 15-10 使用 Python 枚举函数调用

from idaapi import *  
func = get_func(here())  
if not func is None:  
   fname = Name(func.startEA)  
   items = FuncItems(func.startEA)  
   for i in items:  
      for xref in XrefsFrom(i, 0): ➊  
         if xref.type == fl_CN or xref.type == fl_CF:  
            Message("%s calls %s from 0x%x\n" % (fname, Name(xref.to), i))  
else:  
   Warning("No function found at location %x" % here())

这段脚本的新内容是使用 XrefsFrom 生成器(➊ ,取自 idautils )从当前指令中检索所有交叉引用。 XrefsFrom 将返回对 xrefblk_t 对象(其中包含有关当前交叉引用的详细信息)的引用。

15.7.4 枚举导出的函数

代码清单 15-11 是代码清单 15-5 中.idt 生成器脚本的 Python 版本。

代码清单 15-11 生成 IDT 文件的 Python 脚本

file = AskFile(1, "*.idt", "Select IDT save file")  
with open(file, 'w') as fd:  
   fd.write("ALIGNMENT 4\n")  
   fd.write("0 Name=%s\n" % GetInputFile())  
   for i in range(GetEntryPointQty()):  
      ord = GetEntryOrdinal(i)  
      if ord == 0: continue  
      addr = GetEntryPoint(ord)  
if ord == addr: continue   #entry point has no ordinal  
fd.write("%d Name=%s" % (ord, Name(addr)))  
purged = GetFunctionAttr(addr, FUNCATTR_ARGSIZE)  
if purged > 0:  
   fd.write(" Pascal=%d" % purged)  
fd.write("\n")

这两段脚本看起来非常类似,因为 IDAPython 没有用于生成入口点列表的生成器函数,所以我们必须使用在代码清单 15-5 中使用的同一组函数。不过,有一个值得我们注意的区别:IDAPython 没有采用 IDC 的文件处理函数,而是使用了 Python 内置的文件处理函数。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文