- 献词
- 致谢
- 前言
- 第一部分 IDA 简介
- 第 1 章 反汇编简介
- 第 2 章 逆向与反汇编工具
- 第 3 章 IDA Pro 背景知识
- 第二部分 IDA 基本用法
- 第 4 章 IDA 入门
- 第 5 章 IDA 数据显示窗口
- 第 6 章 反汇编导航
- 第 7 章 反汇编操作
- 第 8 章 数据类型与数据结构
- 第 9 章 交叉引用与绘图功能
- 第 10 章 IDA 的多种面孔
- 第三部分 IDA 高级应用
- 第 11 章 定制 IDA
- 第 12 章 使用 FLIRT 签名来识别库
- 第 13 章 扩展 IDA 的知识
- 第 14 章 修补二进制文件及其他 IDA 限制
- 第四部分 扩展 IDA 的功能
- 第 15 章 编写 IDA 脚本
- 第 16 章 IDA 软件开发工具包
- 第 17 章 IDA 插件体系结构
- 第 18 章 二进制文件与 IDA 加载器模块
- 第 19 章 IDA 处理器模块
- 第五部分 实际应用
- 第 20 章 编译器变体
- 第 21 章 模糊代码分析
- 第 22 章 漏洞分析
- 第 23 章 实用 IDA 插件
- 第六部分 IDA 调试器
- 第 24 章 IDA 调试器
- 第 25 章 反汇编器/ 调试器集成
- 第 26 章 其他调试功能
- 附录 A 使用 IDA 免费版本 5.0
- 附录 B IDC/SDK 交叉引用
15.7 IDAPython 脚本示例
为将 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论