目录
1.1 关于漏洞
1.1.1 bug与漏洞
漏洞:引起软件做出“超出设计范围的事情”的bug。(vulnerability)
功能性逻辑缺陷(bug):影响软件的正常功能,如执行结果错误、图标显示错误等。
安全性逻辑缺陷(漏洞):通常不影响软件的正常功能,但被攻击者利用后,存在引发软件执行外来恶意代码的可能。
常见漏洞:
缓冲区溢出漏洞
网站中的跨站脚本漏洞(XSS)
SQL注入漏洞
1.1.2 几个经典的安全问题
[1] 我从不运行任何来历不明的软件,为什么还会中病毒?
如果病毒利用重量级的系统漏洞进行传播,那将在劫难逃。因为系统漏洞可以引起计算机被远程控制,更何况传播病毒。横扫世界的冲击波蠕虫、slammer 蠕虫等就是这种类型的病毒。
如果服务器软件存在安全漏洞,或者系统中可以被 RPC 远程调用的函数中存在缓冲区 溢出漏洞,攻击者也可以发起“主动”进攻。在这种情况下,您的计算机会轻易沦为所谓 的“肉鸡”。
[2] 我只是点击了一个 URL 链接,并没有执行任何其他操作,为什么会中木马?
如果所使用的浏览器在解析 HTML 文件时存在缓冲区溢出漏洞,那么攻击者就可以精心构造一个承载着恶意代码的 HTML 文件,并把其链接发给你。当点击这种链接时,漏洞被触发,从而导致 HTML 中所承载的恶意代码(shellcode)被执行。这段代码通常是在没有任何提示的情况下去指定的地方下载木马客户端并运行。
此外,第三方软件所加载的 ActiveX 控件中的漏洞也是被“网马”所经常利用的对象。所 以千万不要忽视 URL 链接。
[3] Word 文档、Power Point 文档、Excel 表格文档并非可执行文件,它们会导致恶意代码 的执行吗?
和 html 文件一样,这类文档本身虽然是数据文件,但是如果 Office 软件在解析这些数据 文件的特定数据结构时存在缓冲区溢出漏洞的话,攻击者就可以通过一个精心构造的 Word 文 档来触发并利用漏洞。当您在用 Office 软件打开这个 Word 文档的时候,一段恶意代码可能已 经悄无声息地被执行过了。
[4] 上网时,我总是使用高强度的密码注册账户,我的账户安全吗?
高强度的密码只能抵抗密码暴力猜解的攻击,具体安全与否还取决于很多其他因素:
密码存在哪里,例如,存本地计算机还是远程服务器。
密码怎样存,例如,明文存放还是加密存放,什么强度的加密算法等。
密码怎样传递,例如,密钥交换的过程是否安全,网络通讯是否使用 SSL 等。
这些过程中如果有任何一处失误,都有可能引起密码泄漏。例如,一个网站存在 SQL 注入漏洞,而你的账号密码又以明文形式存在 Web 服务器的数据库中,那么无论密码多长, 包含多少特殊字符,最终仍将为脚本注入攻击者获取。
此外,如果密码存在本地,即使使用高强度的 Hash 算法进行加密,如果没有考虑到 CRACK 攻击,验证机制也很可能被轻易突破。
1.1.3 漏洞挖掘、分析及利用
利用漏洞进行攻击大致分三步:
漏洞挖掘
漏洞分析
漏洞利用
1. 漏洞挖掘
从技术角度讲,漏洞挖掘实际上是一种高级的测试(QA)。学术界一直热衷于使用静态分析的方法寻找源代码中的漏洞;而在工程界,不管是安全专家还是攻击者,普遍采用的漏洞挖掘方法是 Fuzz,这实际是一种“灰”盒测试。
2. 漏洞分析
当 fuzz 捕捉到软件中一个严重的异常时,当您想透过厂商公布的简单描述了解漏洞细节的 时候,您就需要具备一定的漏洞分析能力。一般情况下,我们需要调试二进制级别的程序。 在分析漏洞时,如果能够搜索到 POC(proof of concept)代码,就能重现漏洞被触发的现 场。这时可以使用调试器观察漏洞的细节,或者利用一些工具(如 Paimei)更方便地找到漏洞 的触发点。
当无法获得 POC 时,就只有厂商提供的对漏洞的简单描述了。一个比较通用的办法是使 用补丁比较器,首先比较 patch 前后可执行文件都有哪些地方被修改,之后可以利用反汇编工 具(如 IDA Pro)重点逆向分析这些地方。
漏洞分析需要扎实的逆向基础和调试技术。
3. 漏洞利用
随着时间的推移,经过无数安全专家和黑客们针锋相对的研究,这项技术已经在多种流行 的操作系统和编译环境下得到了实践,并日趋完善。这包括:
内存漏洞(堆栈溢出)
Web 应用 漏洞(脚本注入)
...
1.1.4 漏洞的公布与0 day响应
漏洞公布的流程取决于漏洞是被谁发现的。 如果是安全专家、Pen Tester(渗透测试人员)、Ethic Hacker(道德黑客) 在测试中发现了漏洞,一般会立刻通知厂商的 产品安全中心。软件厂商在经过漏洞确认、补丁测试之后,会正式发布漏洞公告和官方补丁。
0 day:未被公布、 未被修复的漏洞。
0 day 漏洞是危害最大的漏洞,而对攻击者来说也是最有价值的漏洞。
有时 0 day 漏洞会被曝光,那意味着全世界的黑客都知道这个漏洞,也懂得怎么 去利用它,在厂商的官方补丁发布前,整个 Internet 的网络将处于高危预警状态。
0 day 曝光属于严重的安全事件,一般情况下,软件厂商都会进入应急响应处理流程,以 最快的速度修复漏洞,保护用户的合法权利。
公布漏洞的权威机构:
(1)CVE (Common Vulnerabilities and Exposures) CVE -CVE 截至目前,这里收录 了两万多个漏洞。CVE 会对每个公布的漏洞进行编号、审查。CVE 编号通常也是引用漏洞的 标准方式。
(2)CERT(Computer Emergency Response Team) The CERT Division | Software Engineering Institute 计算机应急响应组往往 会在第一时间跟进当前的严重漏洞,包括描述信息、POC 的发布链接、厂商的安全响应进度、 用户应该采取的临时性防范措施等。
此外,微软安全中心所公布的漏洞也是所有安全工作者和黑客们最感兴趣的地方。微软 每个月第二周的星期二发布补丁,这一天通常被称为“Black Tuesday”,因为会有许多攻击者通宵达旦地去研究这些补丁 patch 了哪些漏洞,并写出 exploit。因为在补丁刚刚发布的一段时 间内,并非所有用户都能及时修复,故这种新公布的漏洞也有一定利用价值。有时把攻击这种 刚刚被 patch 过的漏洞称为 1 day 攻击。(patch 发布后 n 天,叫做 n day,未 发 patch 统称 0 day)
1.2 二进制文件概述
1.2.1 PE文件格式
PE (Portable Executable) 是 Win32平台下可执行文件遵守的数据格式。
-
".exe"文件
-
".dll"文件
PE 文件格式把可执行文件分成若干个数据节(section),不同的资源被放在不同的节中。典型格式如下:
.text 由编译器产生,存放着二进制的机器代码,也是我们反汇编和调试的对象。
.data 初始化的数据块,如宏定义、全局变量、静态变量等。
.idata 可执行文件所使用的动态链接库等外来函数与文件的信息。
.rsrc 存放程序的资源,如图标、菜单等。
除此以外,还可能出现的节包括“.reloc”、“.edata”、“.tls”、“.rdata”等。
如果是正常编译出的标准 PE 文件,其节信息往往是大致相同的。但这些 section名只为方便记忆与使用,使用Visual C++中的编译指示符#pragma dat a_seg()可以把代码中的任意部分编译到 PE 的任意节中,节名也可以自定义。如果可执行文件经过了“加壳”处理,PE中节信息的可读性则严重降低。 在 Crack 和反病毒分析中需要经常处理这类PE文件。
1.2.2 虚拟内存
Windows内存分两个层面:
物理内存
比较复杂
需要进入Win内核级别的ring0才能看到
虚拟内存
用户模式下所见的内存为虚拟内存
如上图所见,Windows 让所有的进程都“相信”自己拥有独立的 4GB内存空间。然而计算机中那根实际的内存条可能只有512MB,为所有进程都分配4GB的内存便是不切实际的,而这一切都是通过虚拟内存管理器的映射做到的。
如果进程不使用这些“虚拟地址”,它们对进程来说就只是一笔“无形的数字财富”;当需要进行实际的内存操作时,内存管理器才会把“虚拟地址”和“物理地址”联系起来。
进程所拥有的 4GB 虚拟内存中包含了程序运行时所必需的资源,比如代码、栈空间、堆空间、资源区、动态链接库等。(同操作系统原理中的”虚拟内存“概念有所区别)
1.2.3 PE 文件与虚拟内存之间的映射
几个重要概念
文件偏移地址(File Offset) 数据在 PE 文件中的地址叫文件偏移地址,个人认为叫做文件地址更加准确。这是文件在 磁盘上存放时相对于文件开头的偏移。
装载基址(Image Base) PE 装入内存时的基地址。默认情况下,EXE 文件在内存中的基地址是 0x00400000,DLL 文件是 0x10000000。这些位置可以通过修改编译选项更改。
虚拟内存地址(Virtual Address,VA) PE 文件中的指令被装入内存后的地址。
相对虚拟地址(Relative Virtual Address,RVA) 相对虚拟地址是内存地址相对于映射基址的偏移量。
虚拟内存地址、映射基址、相对虚拟内存地址三者之间有如下关系:
$$
VA = Image\;Base+ RVA
$$
-
在默认情况下,一般 PE 文件的 0 字节将对映到虚拟内存的 0x00400000 位置,这个地址就是所谓的装载基址(Image Base)。
-
内存装载时,数据结构与PE基本是保持一致,但仍有差别在里面:
-
PE 文件中的数据按照磁盘数据标准存放,以 0x200 字节为基本单位进行组织。当一 个数据节(section)不足 0x200 字节时,不足的地方将被 0x00 填充;当一个数据节超过 0x200 字节时,下一个 0x200 块将分配给这个节使用。因此 PE 数据节的大小永远是 0x200 的整数倍。
-
当代码装入内存后,将按照内存数据标准存放,并以 0x1000 字节为基本单位进行组 织。类似的,不足将被补全,若超出将分配下一个 0x1000 为其所用。因此,内存中的节总是 0x1000 的整数倍。
-
通过下表可以更直观地认识到这种差别:
-
可以使用Windows自带的程序员计算器进行验证
-
-
由于内存中数据节相对于装载基址的偏移量和文件中数据节的偏移量有上述差异,所以进 行文件偏移到虚拟内存地址之间的换算时,还要看所转换的地址位于第几个节内。 我们把这种由存储单位差异引起的节基址差称做节偏移,在上例中:
-
那么文件偏移地址与虚拟内存地址之间的换算关系可以用下面的公式来计算:
-
文件偏移地址 = 虚拟内存地址(VA)−装载基址(Image Base)−节偏移 = RVA -节偏移
-
以上表为例,如果在调试时遇到虚拟内存中 0x00404141 处的一条指令,那么要换算出 这条指令在文件中的偏移量,则有:
-
文件偏移量 = 0x00404141- 0x00400000 - (0x1000 - 0x400) = 0x3541
-
-
可以使用诸如LordPE等工具来做这些换算工作
-
1.3 常用的工具
[1] OllyDbg
[2] IDA Pro
[3] 二进制编辑器
-
UltraEdit
-
Hex Workshop
-
WinHex
-
010 editor
其中 UltraEdit 功能非常的丰富、强大
[4] VMware
[5] 高效快捷的编程环境,如Python、Go等
每一个不曾起舞的日子,都是对生命的辜负。