本章是第1章“基础知识”,隶属于第一篇“漏洞利用原理(初级)”。本章目的是让读者有对和漏洞有关的基本概念有一个简单的了解。
本章首先介绍了漏洞研究中的一些基本概念和原理,其次讲解了Windows平台下可执行文件的结构和内存方面的一些基础知识,最后列举了漏洞分析中常用的工具。
目前来说,我基本上是按照书上的结构写,且尽可能忠实于原文。以后写得熟练了,会更有一些个人的风格。
笔记主要由两部分组成:
- 一部分是书中的重点,这些知识有必要反复咀嚼;
- 另一部分是实践时碰到的问题的技术细节,将其记录下来有助于以后参考。
1. 漏洞概述
1.1 Bug与漏洞
软件行业现状:
- 随着现代软件工业的发展,软件规模越来越大,软件内部的逻辑也日益复杂;
- 测试环节(QA:Quality Assurance,质量保证)变得日渐重要;
- 即使在测试上投入了巨大精力,依旧没有人敢声称能够避免软件中的所有逻辑缺陷——bug。
在形形色色的bug中,有些会引起严重的后果。
我们将这类能引起软件做一些“超出设计范围的事情”的bug,称为“漏洞”(vulnerability):
- 功能性逻辑缺陷(bug):影响软件的正常功能。例如:执行结果错误、图标显示错误等。
- 安全性逻辑缺陷(漏洞):通常情况下不影响软件功能,但被攻击者利用后,有可能引起软件执行额外的恶意代码。例如:缓冲区溢出漏洞、跨站脚本漏洞(XSS),SQL注入漏洞。
因此,我在下面附了百度百科和Wikipedia的相关词条链接,以后类似。(百度百科的好处就是中文便于阅读,Wikipedia的优势在于相对严谨。)
- 百度百科:bug、漏洞
- Wikipedia:Software bug、vulnerability
对于某些重要的概念,随文插入相关链接,读起来方便;而在文末给出,则更有总结效果;不插链接,只做高亮,则可使行文流畅,避免繁琐。我在想到底采用哪种方式更好。
1.2 几个令人困惑的安全问题
也许你具备一些基本的计算机知识,但是你仍然对下面一些问题有所困惑:
- 我从不允许任何来历不明的软件,为什么还会中病毒strong>
病毒可以利用重量级的系统漏洞传播。例如:冲击波蠕虫、Slammer蠕虫。
攻击者也可以利用漏洞发起主动攻击。
- 我只是点击了一个URL安全链接,并没有执行任何其他操作,为什么会中木马strong>
如果浏览器在解析HTML文件时存在缓冲区溢出漏洞,攻击者可以精心构造一个承载着恶意代码(Shellcode)的HTML文件,将连接发给用户。用户点击链接时,漏洞被触发,HTML文件中的恶意代码被触发。
- Word文档、Power Point文档、Excel表格文档并非可执行文件,它们会导致恶意代码的执行吗strong>
和HTML文件一样,这类文档虽然是数据文件,但是如果Offiice软件在解析这些数据文件的特定数据结构时存在缓冲区漏洞的话,攻击者就可以通过巧妙的构造文档内容,触发并利用漏洞,进而执行恶意代码。
- 上 时,我总是使用高强度的密码注册账户,我的账户安全吗strong>
高强度密码只能抵抗暴力猜解,具体安全与否还取决于很多其他因素:
- 密码存放位置:本地计算机还是远程服务器;
- 密码存放方式:明文还是加密,加密算法强度如何;
- 密码传递方式:密钥交换的过程安全与否, 络通讯是否使用SSL。
这些过程中有任何一处失误,都有可能导致密码泄露。
你也许读过很多 络安全的书籍和文章,会看到许多诸如端口扫描、 络监听、密码猜解、DOS等专业名词。虽然这些话题在 络安全技术中也许永远都不会过时,但是读完本书后,你会发现漏洞利用技术才是实施有效攻击的最核心技术,才是突破安全、实施深度入侵的关键所在。
1.3 漏洞挖掘、漏洞分析、漏洞利用
利用漏洞进行攻击大致可以分为小标题中的三个步骤。这三个部分既有所相同,也有所不同。
1.3.1 漏洞挖掘
- 安全性漏洞往往不会对软件本身功能造成很大影响,因此很难被功能性测试发现;
- 安全性漏洞往往有极高的利用价值;
- 有无数技术精湛、精力旺盛的人夜以继日地寻找软件中的安全漏洞;
- 挖掘漏洞的人中,既有攻击者,也有安全专家;
- 学术界热衷于使用静态分析方法,工程界则普遍采用Fuzz技术。
在第三章中,本书会进一步介绍漏洞挖掘和产品安全性测试的有关内容。
1.3.2 漏洞分析
当你想从厂商公布的简单的漏洞 告中了解漏洞细节时,你就需要具备一定的漏洞分析能力。
一般情况下,我们需要调试二进制级别的程序。
- 如果有POC(Proof of concept)代码,就能重现漏洞的触发过程。我们可以利用调试器和工具了解细节。
- 如果没有POC,就只能分析厂商提供的漏洞描述。通用的办法是利用补丁比较器找到被文件修改的地方,之后可以用反汇编工具对这些地方进行重点逆向分析。
漏洞分析需要扎实的逆向基础和调试技术,此外还需要精通各种场景下的漏洞利用方法。这些能力更多地是依靠经验,很难总结出通用的条款。 本书第5章会用若干实际案例帮助你体会漏洞分析的过程。
1.3.3 漏洞利用
漏洞利用技术源远流长,如今已经十分成熟,且应用颇广。
本书将从攻防两个角度着重介绍Windows平台下内存漏洞利用技术的方方面面。
由于手机安全及Web应用中的脚本注入攻击所使用的技术和Windows平台下缓冲区溢出技术相差较大,且自成体系,因此本书只作原理性介绍。
1.3.4 漏洞的公布与0day响应
漏洞公布流程取决于漏洞是被谁发现的:
- 安全专家:立刻通知厂商的产品安全中心,厂商在经过漏洞确认和补丁测试后,正式发布漏洞公告和官方补丁。
- 攻击者:不会立刻通知厂商,可能会利用漏洞做任何事情。
这种未被公布、未被修复的漏洞往往被称为0day:
- 0day漏洞危害最大;
- 对攻击者来说也最有价值;
- 0day一般只是被极少数攻击者掌握;
- 有时0day会被曝光,那么在官方补丁发布前,整个 络将处于高危预警状态;
- 软件厂商在0day曝光后会进入应急响应处理流程,以最快的速度修复漏洞,保护用户合法权利。
公布漏洞的权威机构有;
- CVE(Common Vulnerabilities & Exposures)
- CERT(Computer emergency response team)
- 对于Windows,微软安全中心每个月第二周的星期二发布补丁:Black Tuesday
2. 二进制文件概述
2.1 PE文件格式
PE:Portable Executable,可移植的可执行文件。常见的PE文件格式有:.exe,.dll。
PE文件格式规定了可执行文件中各种信息是如何组织的。程序执行时,操作系统安装PE文件格式的约定去相应地方定位各种类型的资源,并装入内存的不同区域。
PE文件格式把可执行文件分成若干个数据节(section),不同资源存放在不同的字节中:
- .text:由编译器产生,存放二进制机器代码,是我们反汇编和调试的对象;
- .data:初始化的数据块,如宏定义、全局变量、静态变量等;
- .idata:可执行文件中使用的动态链接库等外来函数与文件的信息;
- .rsrc:存放程序的资源,如图标、菜单等;
- 还可能出现的字节有:“.reloc”、“.edata”、“.tls”、“.radata”等。
2.2 虚拟内存
Windows内存可分为两个层面:虚拟内存和物理内存。
- 物理内存比较复杂,需要进入Windows内核级别ring0才能看到。
- 在用户模式下,我们用调试器看到的内存地址都是虚拟内存。
引入“虚拟内存”的目的有二:
- 对底层的存储器进行抽象,使开发者能够关心更高层级的事务;
- 让每个进程都以为自己被分配了足够的内存空间——至少大于实际的物理内存。
这一部分的相关内容,在Tanenbaum的《Modern Operating Systems》一书中有更加详细和精辟的介绍。由于我已经有了《操作系统》的先修基础,因而此处不再赘述。 其实“虚拟内存”是操作系统的一个非常重要的概念,可以用相当大的篇幅对其进行描述,我们以后还会不断地碰到这个概念。
2.3 PE文件与虚拟内存之间的映射
调试漏洞时,可能会遇到如下两种情况:
- 静态反汇编工具看到的PE文件中某条指令的位置,是相对于磁盘文件而言的,即所谓的文件偏移;我们可能需要知道这条指令在内存中所处的位置,即虚拟内存地址(VMA)。
- 反之,在调试时看到的某条指令的地址是虚拟内存地址,我们也要经常回到PE文件中找到这条指令对应的机器码。
为此,我们需要弄清楚PE文件地址和虚拟内存地址之间的映射关系。 首先,我们介绍几个重要概念:
- 文件偏移地址(File Offset):数据在PE文件中的地址。这是文件在磁盘上存放时相对于文件开头的偏移。
- 装载基址(Image Base):PE文件装入内存时的基地址。本书中也叫映射基址。比如.exe文件在内存中的基址就是0x00400000。这个值可以通过修改编译选项更改。
- 虚拟内存地址(VA:Virtual Address):PE文件中的指令被装入内存后的地址。
- 相对虚拟地址(RVA:Relative Virtual Address):内存地址相对于映射基址的偏移量。
虚拟内存地址、映射基址、相对虚拟地址三者之间的关系:
- 虚拟内存地址 = 映射基址 + 相对虚拟地址
- Virtual Address = Image Base + Relative Virtual Address

(左边蓝色块为 PE文件,右边黄色块为 内存)
这里有一个容易混淆的地方:
- 文件偏移是相对于文件开始处0字节的偏移,相对虚拟地址则是相对于装载基址(对.exe文件来说,是0x00400000)的偏移。
- 操作系统在进行装载时“基本”保持PE文件中的各种数据结构,因此文件偏移和相对虚拟地址有很大的一致性。
文件数据的存放单位和内存数据的存放单位是不同的:
- PE文件中的数据,按照磁盘数据标准存放,以0x200字节为基本单位进行组织。
- 代码装入内存后,按照内存数据标准存放,以0x1000字节为基本单位进行组织。
节(section) | 相对虚拟地址(RVA) | 文件偏移地址 |
---|---|---|
.text | 0x00001000 | 0x0400 |
.rdata | 0x00007000 | 0x6200 |
.data | 0x00009000 | 0x7400 |
.rsrc | 0x0002D000 | 0x7800 |
由于内存中数据节相对于装载基址的偏移量和文件中数据节的偏移量有上述差异,因此,在进行文件偏移到虚拟内存地址之间的换算时,需要考虑转换的地址位于第几个节内。
我们把这种由存储单位差异引起的节基址差称为节偏移。 节偏移的计算公式为:
- 节偏移 = RVA – 文件偏移
则表格中各节的偏移分别为:
- .text:0x1000 – 0x0400 = 0x0C00
- .rdata:0x7000 – 0x6200 = 0x0E00
- .data:0x9000 – 0x7400 = 0x1C00
- .rsrc:0x2D000 – 0x7800 = 0x25800
由上式可得文件偏移计算公式:
- 文件偏移 = RVA – 节偏移
- = (虚拟内存地址 – 装载基址) – 节偏移
比如,在调试中,遇到虚拟内存中0x00404141处的一条指令,那么该指令在文件中的偏移为:
- 文件偏移 = 0x00404141 – 0x00400000 – 0x0C00 = 0x3541
当然,有一些PE工具为我们提供了这类地址转换,比如 Lord PE。在下一小节我们马上就会提到一些常用的工具。
注:一开始我在这个地方困扰了很久,因为书中直接给出了文件偏移的计算公式。其实很简单,就是将节偏移计算公式进行移项,然后再根据RVA = 虚拟内存地址 – 装载基址,就能得到文件偏移的计算公式了。其实引入“节偏移”这个概念,就是为了方便文件偏移和虚拟内存地址之间的互算。 给出的例子应该是默认为.exe文件,且指令处在.text节中,所以就用了.text的节偏移值。
3. 必备工具
“有一点需要提醒你:本书对这些工具的介绍只能让你简单上手,不要指望能立刻把它们挥洒自如——那需要你在实践中不断地学习和体会。”
在这一部分,书中介绍了几个常用的工具: (我在部分用过的工具上附了下载链接,亲测可用。当然,没有什么软件是百度和谷歌找不到的~)
- OllyDbg、SoftICE、WinDbg
- IDA Pro
- VMware
- Python编程环境
对于我用过的几个工具的简介:
- IDA Pro:当今最强大的反汇编软件。具有强大的标注功能,我第一次用的时候,简直惊呆了。第二次用的时候,又一脸懵逼了,因为功能真是太复杂了。
- VMware:爱折腾的人的必备神器。大学两年多以来,在里面跑过不下二十个操作系统,如果是在本机上装双系统,不知道能把电能搞瘫多少次。
3.1 Crack小实验
下面是一段c代码,用于密码验证:
本次破解的关键,就是修改跳转条件:
- 原来的代码要求输入正确的密码才能验证成功,修改后,只要输入的密码和正确的不一样,就能验证成功。
(原本在这里写了一系列的软件操作步骤,但是想想,这背离了我写学习笔记的初衷:笔记不是照搬原文,而是整理思路和发现问题。因此,现在这里只保留了我在实践中遇到的一些细节问题,读者朋友们可以跳过这一段。等到你自己动手操作过一遍,再来看这里,说不定可以对你有所帮助。)
下面是一些细节性的问题:
- IDA Pro选中一个函数,多按两次空格,可以查看汇编代码
- 再强调一次,IDA这工具真是有点复杂,不过以后用得熟了,应该会好一些;
- main函数一般位于GetCommandLineA处,且有明显特征:调用之前有三次连续的压栈操作(系统给main函数传入argc、argv等参数);
- OllyDbg中,F7和F8的区别在于:F7:遇到函数调用指令跟入(Step in);F8:遇到函数调用指令不跟入(Step over);
- 原书似乎对JE和JZ有点混淆,我反汇编得到的是JZ,关于JZ和JE之类的跳转命令,可以参考这篇博文;
- 其实可以试一试把TEST换成XOR甚至是其他命令,看看能得到什么结果;
- 汇编语言不用特意去学,了解基本的语法和含义即可;
- 工具只要掌握一些基本的命令和功能,其他都在实践和操作中熟悉,在百度和谷歌中深入;
- 计算十六进制地址什么的,Casio计算器输入起来比电脑更快。
第1章“基础知识”就写到这里,希望能对你有所帮助。
第一次写得有点多,在以后的文章里,我会精简一点,尽量突出原书的重点和我碰到的问题,这样才能算是好的学习笔记。 文中有些地方其实可以加粗或者高亮,以突出强调,但是很难把握分寸,太多的加粗或者高亮有时反而会产生负面效果。所以,以后慢慢摸索吧,现在就先这样。
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!