Statistics
8
Views
0
Downloads
0
Donations
Support
Share
Uploader

高宏飞

Shared on 2026-03-27
Support Statistics
¥.00 · 0times
Text Preview (First 20 pages)
Registered users can read the full content for free

Register as a Gaohf Library member to read the complete e-book online for free and enjoy a better reading experience.

(This page has no text content)
版权信息 书名:有趣的二进制:软件安全与逆向分析 作者:[日] 爱甲健二 译者:周自恒 ISBN:978-7-115-40399-5 本书由北京图灵文化发展有限公司发行数字版。版权所有,侵权必 究。 您购买的图灵电子书仅供您个人使用,未经授权,不得以任何方式复制 和传播本书内容。 我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。 如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐 号等维权措施,并可能追究法律责任。 图灵社区会员 张海川(zhanghaichuan@ptpress.com.cn) 专享 尊重版权
版权声明 译者序 免责声明 关于商标和注册商标 前言 第 1 章 通过逆向工程学习如何读懂二进制代码 1.1 先来实际体验一下软件分析吧 1.1.1 通过 Process Monitor 的日志来确认程序的行为 1.1.2 从注册表访问中能发现些什么 1.1.3 什么是逆向工程 1.2 尝试静态分析 1.2.1 静态分析与动态分析 1.2.2 用二进制编辑器查看文件内容 1.2.3 看不懂汇编语言也可以进行分析 1.2.4 在没有源代码的情况下搞清楚程序的行为 1.2.5 确认程序的源代码 1.3 尝试动态分析  设置 Process Monitor 的过滤规则 1.3.2 调试器是干什么用的 1.3.3 用 OllyDbg 洞察程序的详细逻辑 1.3.4 对反汇编代码进行分析 1.3.5 将分析结果与源代码进行比较 1.4 学习最基础的汇编指令 1.4.1 没必要记住所有的汇编指令 1.4.2 汇编语言是如何实现条件分支的 1.4.3 参数存放在栈中 1.4.4 从汇编代码联想到 C 语言源代码 1.5 通过汇编指令洞察程序行为
1.5.1 给函数设置断点 1.5.2 反汇编并观察重要逻辑 第 2 章 在射击游戏中防止玩家作弊 2.1 解读内存转储 2.1.1 射击游戏的规则 2.1.2 修改 4 个字节就能得高分 2.1.3 获取内存转储 2.1.4 从进程异常终止瞬间的状态查找崩溃的原因 2.1.5 有效运用实时调试 2.1.6 通过转储文件寻找出错原因 2.2 如何防止软件被别人分析 2.2.1 反调试技术 2.2.2 通过代码混淆来防止分析 2.2.3 将可执行文件进行压缩 2.2.4 将压缩过的可执行文件解压缩:解包 2.2.5 通过手动解包 UPX 来理解其工作原理 2.2.6 用硬件断点对 ASPack 进行解包 第 3 章 利用软件的漏洞进行攻击 3.1 利用缓冲区溢出来执行任意代码 3.1.1 引发缓冲区溢出的示例程序 3.1.2 让普通用户用管理员权限运行程序 3.1.3 权限是如何被夺取的 3.1.4 栈是如何使用内存空间的 3.1.5 攻击者如何执行任意代码 3.1.6 用 gdb 查看程序运行时的情况 3.1.7 攻击代码示例 3.1.8 生成可用作 shellcode 的机器语言代码 3.1.9 对 0x00 的改进
3.2 防御攻击的技术 3.2.1 地址随机化:ASLR 3.2.2 除存放可执行代码的内存空间以外,对其余内存空间尽 量禁用执行权限:Exec-Shield 3.2.3 在编译时插入检测栈数据完整性的代码:StackGuard 3.3 绕开安全机制的技术 3.3.1 使用 libc 中的函数来进行攻击:Return-into-libc 3.3.2 利用未随机化的模块内部的汇编代码进行攻击:ROP 第 4 章 自由控制程序运行方式的编程技巧 4.1 通过自制调试器来理解其原理 4.1.1 亲手做一个简单的调试器,在实践中学习 4.1.2 调试器到底是怎样工作的 4.1.3 实现反汇编功能 4.1.4 运行改良版调试器 4.2 在其他进程中运行任意代码 :代码注入 4.2.1 向其他进程注入代码 4.2.2 用 SetWindowsHookEx 劫持系统消息 4.2.3 将 DLL 路径配置到注册表的 AppInit_DLLs 项 4.2.4 通 过 CreateRemoteThread 在其他进程中创建线程 4.2.5 注入函数 4.3 任意替换程序逻辑 :API 钩子 4.3.1 API 钩子的两种类型 4.3.2 用 Detours 实现一个简单的 API 钩子 4.3.3 修改消息框的标题栏 第 5 章 使用工具探索更广阔的世界 5.1 用 Metasploit Framework 验证和调查漏洞 5.1.1 什么是 Metasploit Framework 5.1.2 安全漏洞的信息从何而来
5.1.3 搭建用于测试漏洞的环境 5.1.4 利用漏洞进行攻击 5.1.5 一个 ROP 的实际例子 5.2 用 EMET 观察反 ROP 的机制 5.2.1 什么是 EMET 5.2.2 Anti-ROP 的设计获得了蓝帽奖 5.2.3 如何防止攻击 5.2.4 搞清楚加载器的逻辑 5.2.5 DLL 的程序逻辑 5.2.6 CALL-RETN 检查 5.2.7 如何防止误判 5.2.8 检查栈的合法性 5.3 用 REMnux 分析恶意软件 5.3.1 什么是 REMnux 5.3.2 更新特征数据库 5.3.3 扫描目录 5.4 用 ClamAV 检测恶意软件和漏洞攻击 5.4.1 ClamAV 的特征文件 5.4.2 解压缩 .cvd 文件 5.4.3 被检测到的文件详细信息 5.4.4 检测所使用的打包器以及疑似恶意软件的文件 5.5 用 Zero Wine Tryouts 分析恶意软件 5.5.1 REMnux 与 Zero Wine Tryouts 的区别 5.5.2 运行机制 5.5.3 显示用户界面 5.5.4 确认分析报告 5.6 尽量减少人工分析 :启发式技术 5.6.1 恶意软件应对极限的到来:平均每天 60000 个
5.6.2 启发式技术革命 5.6.3 用两个恶意软件进行测试 附录 A.1 安装 IDA A.2 安装 OllyDbg A.3 安装 WinDbg A.4 安装 Visual Studio 2010 A.5 安装 Metasploit A.6 分析工具 Stirling / BZ Editor Process Monitor Process Explorer Sysinternals 工具 兔耳旋风 参考文献 后记
版权声明 TANOSHII BANNARI NO ARUKIKATA by Kenji Aiko Copyright © 2013 Kenji Aiko All rights reserved. Original Japanese edition published by Gijyutsu-Hyoron Co., Ltd., Tokyo   This Simplified Chinese language edition published by arrangement with Gijyutsu-Hyoron Co., Ltd., Tokyo in care of Tuttle-Mori Agency, Inc., Tokyo   本书中文简体字版由 Gijyutsu-Hyoron Co., Ltd., Tokyo 授权人民邮电出 版社独家出版。未经出版者书面许可,不得以任何方式复制或抄袭本书 内容。 版权所有,侵权必究。
译者序 这是一本讲“底层”知识的书,不过似乎现在大部分计算机用户都跟底层 没多少缘分了。很多人说,写汇编语言的时候总得操心寄存器,写 C 语 言的时候总得操心内存,而如今到了 Web 当道的时代,不但底层的事 情完全用不着操心了,就连应用层的事情也有大把的框架来替你搞定。 想想看,现在连大多数程序员都不怎么关心底层了,更不要说数量更多 的一般用户了。当然,这其实是一件好事,这说明技术进步了,分工细 化了,只需要一小部分人去研究底层,剩下大部分人都可以享受他们的 伟大成果,把精力集中在距离解决实际问题更近的地方,这样才能解放 出更多的生产力。 话说回来,底层到底指的是什么呢?现代数字计算机自问世以来已经过 了将近 60 年,在这 60 年中,计算机的制造技术、性能、外观等都发生 了翻天覆地的变化,然而其基本原理和结构依然还是 1946 年冯 · 诺依 曼大神所描绘的那一套。冯 · 诺依曼结构的精髓在于,处理器按照顺序 执行指令和操作数据,而无论指令还是数据,它们的本质并没有区别, 都是一串二进制数字的序列。换句话说,“二进制”就是现代计算机的最 底层。我们现在用计算机上网、聊天、看视频、玩游戏,根本不会去考 虑二进制层面的问题,不过较早接触计算机的一代人,其实都曾经离底 层很近,像这本书里面所讲的调试器、反汇编器、二进制编辑器、内存 编辑器等,当初可都是必备的法宝,也给我们这一代人带来过很多乐 趣。 在 MS-DOS 时代,很多人都用过一个叫 debug 的命令,这就是一个非 常典型的调试器。准确地说,debug 的功能已经超出了调试器的范畴, 除了调试之外,它还能够进行汇编、反汇编、内存转储,甚至直接修改 磁盘扇区,俨然是那个年代的一把“瑞士军刀”。我上初中的时候,学校 上计算机课用的电脑在 BIOS 里禁用了软驱,而且还设置了 BIOS 密 码,于是我运行 debug,写几条汇编指令,调用系统中断强行抹掉 CMOS 数据,重启之后显示 CMOS 数据异常,于是 BIOS 设置被恢复到 默认状态,软驱也就可以用了,小伙伴们终于可以把游戏带来玩了。当 然,学校老师后来还是找到我谈话,原因仅仅是因为我在信息学奥赛得 过奖,他们觉得除了我以外不可能有别人干得出这种事了……
很多资历比较老的 PC 游戏玩家其实也都和二进制打过交道,比如说, 大家应该还记得一个叫“整人专家 FPE”的软件。如果你曾经用过“整人 专家”,那么这本书第 2 章中讲的那个修改游戏得分的桥段你一定是再 熟悉不过了。除了修改内存中的数据,很多玩家应该也用二进制编辑器 修改过游戏存档,比如当年的《金庸群侠传》《仙剑奇侠传》,改金钱 道具能力值那还是初级技巧,还有一些高级技巧,比如改各种游戏中的 flag,这样错过开启隐藏分支的条件也不怕不怕啦。此外,各种破解游 戏激活策略的补丁也是通过调试和反汇编研究出来的,我也曾经用 SoftICE 玩过一点逆向工程,找到判断是否注册激活的逻辑,然后用一 个无条件跳转替换它,或者是跳过序列号的校验逻辑,不管输入什么序 列号都能激活。 精通二进制的人还懂得如何压榨出每一个比特的能量。说到这一点,不 得不提鼎鼎大名的 64k-intro 大赛。所谓 64k-intro,就是指用一段程序来 产生包含图像和声音的演示动画,而这段程序(可执行文件)的大小被 限制为 64KB(65536 字节)。想想看,用 iPhone 随便拍一张照片就得 差不多 2MB 大小,相当于 64KB 的 32 倍,然而大神们却能在 64KB 的 空间里塞下长达十几分钟的 3D 动画和音乐,着实令人惊叹不已。我第 一次看到 64k-intro 作品是在上初中的时候,当时某一期《大众软件》 杂志对此做了介绍,光盘里还附带了相应的程序文件。当我在自己的电 脑上亲自运行,看到美轮美奂的 3D 动画时,瞬间就被二进制的奇妙感 动了。 二进制的乐趣不胜枚举,其实最大的乐趣莫过于“打开黑箱”所带来的那 种抽丝剥茧的快感。夸张点说,这和物理学家们探求“大统一理论”,不 断逼近宇宙终极规律的过程中所体验到的那种快感颇有异曲同工之妙。 诚然,二进制的可能性是无穷无尽的,这本书所涉及的也只是其中很小 的一方面,但正如作者在前言中所说的那样,希望大家能够借此体会到 底层技术所特有的快乐。烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫 烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫 烫 周自恒 2015 年 8 月于上海
免责声明 本书的内容以提供信息为目的,在使用本书的过程中,读者需要自己做 出判断并承担相应的责任。对于读者因使用本书中的信息所造成的任何 后果,作者、技术评论社、译者、人民邮电出版社恕不负责。 本书中的内容基于 2013 年 7 月 12 日的最新信息编写,在读者实际阅读 时可能已经发生变化。 此外,软件方面由于其版本的更新,可能会与本书中所描述的功能和画 面存在差异。在购买本书之前,请务必确认您所使用的软件版本。 各位读者在阅读本书之前,请同意并遵守上述注意事项。如果没有阅读 上述事项,那么对于由此产生的问题,出版社和作译者可能也无法解 决,敬请各位读者理解。
关于商标和注册商标 本书中所涉及的产品名称,一般皆为相应公司的商标或者注册商标,在 本书正文中已省略 ™、® 等标记。
前言 如今,计算机已经深入千家万户,为我们的生活带来了很多方便。但与 此同时,计算机系统也变得越来越复杂,技术人员需要学习的知识也与 日俱增。和过去相比,计算机技术中难以理解的黑箱也越来越多了。 操作系统到底是干什么的? CPU 和内存到底是干什么的? 软件为什么能够运行? 为什么会存在安全漏洞? 为什么攻击者能够运行任意代码? 要想回答上面这些问题,我们需要用到以汇编为代表的二进制层面的知 识。 尽管现在正是 Web 应用如日中天的时候,但二进制层面的知识依然能 够在关键时刻发挥作用。例如: “用 C/C++ 开发的程序出现了不明原因的 bug,看了源代码还是找不到 原因。” 在这样的情况下,即便不会编写汇编代码,只要能看懂一些汇编语言, 就可以通过调试器立刻锁定发生 bug 的位置,迅速应对。 此外,如果别人编写的库里有 bug,那么即便看不到源代码,我们也能 够对其内部结构进行分析,并找到避开问题的方法,也可以为库的开发 者提供更有帮助的信息。 再举个例子。学习汇编能够更好地理解 CPU 的工作原理,从而能够处 理系统内核、驱动程序这一类近乎于黑箱的底层问题,对于实际的底层 开发工作也非常有帮助。
不过,说实在的,“有没有帮助”“流不流行”这些都不重要,从个人经验 来看,因为感觉“好像有用”“好像有帮助”而开始学习的东西,最后基本 上都没有真正掌握(笑)。当然,也许是因为我天资愚钝,不过我们在 上学的时候,老师天天教导我们要好好学习,可是实际上有几个人真的 好好学习了呢?虽然我没做过统计,但从感觉来看,整个日本也许还不 到 1% 吧。 那么问题来了,要想真正学会一件事,到底需要什么呢? 我是从初中时代开始学习编程的,尽管当时完全没有想过将来要当程序 员,靠技术吃饭,但我依然痴迷于计算机,每天编程到深更半夜,甚至 影响了学习成绩,令父母担忧。 为什么当时的我如此痴迷于计算机而无法自拔呢?那是因为“编程太有 趣了”。自己编写的代码能够按照设想运行起来,或者是没有按照设想 运行起来,再去查找原因,这些事情都为我带来了莫大的乐趣。 我编写这本书,也是为了让大家对技术感到“有趣”,并且“想了解得更 多”。而在编写这本书的过程中,我再一次感到,在不计其数的编程语 言中,汇编语言是最“有趣”的一种。 如果你突然觉得“讲底层问题的书好像挺有意思的”而买了这本书,那么 我相信,这本书一定能够为你带来超出预期的价值。 希望大家能够通过这本书,感受到二进制世界的乐趣。
第 1 章 通过逆向工程学习如何读 懂二进制代码 大家是否听说过“逆向工程”这个词呢? 逆向工程原本是指通过拆解机器装置并观察其运行情况来推导其制造方 法、工作原理和原始设计的行为,但在软件领域,逆向工程主要指的是 阅读反汇编(将机器语言代码转换成汇编语言代码)后的代码,以及使 用调试器分析软件行为等工作。 程序员都应该知道,处理器是通过解释和执行机器语言代码来运行程序 的,但对现在的程序员来说,对机器语言代码进行反汇编并跟踪其行为 并不是一项必备技能。换句话说,“知道是知道,但没亲自尝试过”这种 情况比较普遍。 笔者是一位喜爱汇编语言的工程师,但也并不认为上面的现象有什么问 题。实际上,我自己除了汇编以外,平时也经常使用 C、Python、 JavaScript 等其他语言。不过,有些东西适合用 C、Python、JavaScript 来编写,同样也有一些东西适合用汇编语言来编写。更进一步说,在某 些技术领域中,不懂汇编就无法工作。 经常和处理器层面的东西打交道的工程师被称为 Binarian 。尽管这些人 并不能说多么伟大,但他们的确运用着很多鲜为人知的技术,你想不想 玩玩看呢? 这是一个日本人造出来的词,英文中没有这个词。——译者注 在本章中,我们将通过软件的逆向工程,探索一下二进制世界的奥秘。 1 1
1.1 先来实际体验一下软件分析吧 下面我们就来动手尝试一下逆向工程。 “咦?你还什么都没教呢!” 没关系,也许大家印象里觉得逆向工程是很难的,其实这里面有一半是 误会,因为分析的难度取决于你要分析的对象。有些软件很难进行分 析,但也有一些则很容易。 这里我们准备了一个简单的“恶意”程序,然后从下面三个要点来进行分 析。 文件的创建、修改和删除 注册表项目的创建、修改和删除 网络通信 如果我们能对上述三个方面进行监控,那么就不难跟踪软件的行为。 这里我们需要下面三个工具。 Stirling (二进制编辑器) http://www.vector.co.jp/soft/win95/util/se079072.html Process Monitor(文件和注册表监控) http://technet.microsoft.com/en-us/sysinternals/bb896645 Wireshark(网络监控) http://www.wireshark.org/ 这个软件仅在日本的圈子里有名,软件也只有日文界面,如果不习惯可以使用其他类似工具 2 2
(如 WinHex)来替代。——译者注 我们先启动 Process Monitor 和 Wireshark,修改配置以启用日志输出。 本书中的所有示例文件均可从以下地址下载。 https://github.com/kenjiaiko/binarybook 译者 fork 了这个项目,并对其中的说明文件和源代码注释等进行了翻译,大家可以从这里访 问:https://github.com/shyujikou/binarybook。——译者注 本次的分析对象为 chap01\sample_mal\Release 目录中的 sample_mal.exe 文件,请大家运行这个文件。 运行 sample_mal.exe 后,应该会弹出一个内容为“Hello Malware!”的对 话框。 关闭对话框之后,sample_mal.exe 文件本身也会消失。 1.1.1 通过 Process Monitor 的日志来确认程序的 行为 下面我们来看一下 Process Monitor 的日志。 3 3
▲ Process Monitor 的运行结果(文件访问) 通过跟踪 Process Monitor 的日志,我们可以发现程序在以下位置进行了 CreateFile 操作。 C:\Documents and Settings\XPMUser\「开始」菜单 \ 程序 \ 启动 \0.exe ※Windows XP 的情况。 C:\Users\ 用户名 \AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\0.exe ※Windows Vista 及更高版本的情况。AppData 为隐藏文件夹。 存放在“启动”文件夹中的程序,会随着 Windows 启动自动运行。 请大家注意,我们的示例程序连续执行了 CreateFile、WriteFile 和 CloseFile 这几个操作,这些操作加起来的功能相当于“在指定文件夹创 建并写入一个名为 0.exe 的文件”。 我们来实际确认一下。 ▲ 确认“启动”文件夹中的内容 果然和日志所描述的一样,创建了一个 0.exe 文件。
下面我们用二进制编辑器 Stirling 对比一下 0.exe 和 sample_mal.exe 的内 容。在菜单中点击搜索 / 移动→比较,在弹出的窗口中选择比较对象, 点击 OK 即可。 通过对比我们发现,两个文件的内容完全一致,也就是说,程序将自己 复制了一份。 ▲ 用 Stirling 对文件进行对比(在菜单中点击搜索 / 移动→比较) 图中弹出的对话框中的日文“違いはありません”是“没有差异”的意思。——译者注 由于“启动”文件夹中的程序会在 Windows 启动时自动运行,因此当我 们重启 Windows 时,0.exe 就会被运行。这个程序并不会带来什么实际 的危害,所以大家可以重启系统试试看。 1.1.2 从注册表访问中能发现些什么 下面我们来确认一下注册表的访问情况。 4 4
Process Monitor 会列出程序访问过的注册表项目和文件。注册表是 Windows 系统提供给应用程序的一个用于保存配置信息的数据库,其中 保存的数据包括浏览器设置、文件类型关联、用户密码等。 通过查看 Process Monitor 输出的日志,我们可以知道程序向“启动”文件 夹复制了一个文件。 进一步分析日志,我们还可以发现程序对注册表进行了一些可疑的访 问。 ▲ Process Monitor 的运行结果(注册表访问) 看来程序在 HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\Current Version\Run 中创建了一个名为 sample_mal 的注册表项目。 HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\Current Version\Run 和“启动”文件夹一样,其中注册的程序会在 Windows 重启 时自动运行。 Windows 重启时自动运行的程序可以注册在下列任一注册表的位置。 HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run