20155306 白皎 0day漏洞——基础知识
20155306 白皎 0day漏洞——(第一篇)基础知识
写在前面:
本次免考实践方向是0day漏洞,以博客的形式记录了我的学习实践过程。第一篇博客主要围绕什么是0day漏洞以及一些以后学习中需要的基础知识和必备工具进行简单介绍和具体的操作。
一、漏洞概述
1. 漏洞与bug
我们通常把一些引起系统软件做“超出设计范围内的事情”的bug称作是漏洞,实际上漏洞和bug也是有一些区别的。
- 功能性的缺陷(bug):影响软件的正常功能,例如执行结果错误、图标显示错误等。
- 安全性逻辑缺陷(漏洞):通常情况下不影响软件的正常功能,但被攻击者成功利用后,有可能引起软件去执行额外的恶意代码。例如很常见的缓冲区漏洞、SQL注入漏洞等。
2. 0day漏洞
- 定义:0day漏洞就是未被公布、未被修复的漏洞称作0day漏洞。
它是危害最大的漏洞,对攻击者来说也是最有价值的漏洞。如果被曝光,那么在广商的官方补丁发布之前,整个网络都处于高危预警状态。
- 公布漏洞的权威机构:
- CVE:CVE对每个公布的漏洞确定了唯一的名称和编号。因此,其编号也是引用漏洞的标准方式。
- CERT:计算甲应急响应组往往会在第一时间跟进当前的严重漏洞,包括描述信息、用户应该才去的临时性防范措施等。
二、二进制文件概述
1.PE文件
PE是win32平台下可执行文件遵守的数据格式。常见的格式有exe文件、dll文件等。
PE文件格式把可执行文件分为若干个数据节(section),不同的资源放在不同的节中,一个典型的PE文件包含的节如下:
* .text:由编译器产生,存放着二进制的机器代码,反汇编和调试的对象。
* .data:初始化的数据块,如宏定义、全局变量、静态变量等
* .idata:可执行文件所使用的动态链接库等外来函数与文件的信息。
* .rsrc:存放程序的资源,如图标、菜单等。
* 除此之外,还可能出现“.rdata",".tls"等。
2.虚拟内存
windows的内存被分为了两个层面。通常在用户模式下,我们用调试器看到的内存都是虚拟内存。
* 物理内存:需要进入内核级别ring0才能看到。
* 虚拟内存:在用户态ring3下,就可以通过调试器来看到内存地址。
如下图所示,是windows虚拟内存和物理内存的示意图。windows让所有进程都相信自己拥有独立都有4GB的内存空间【这些空间包含了程序运行所必需的资源,如代码、栈空间、堆空间等】,都是可以访问的,但实际上运行时能用到的空间根本没有这么多。只有需要进行实际的内存操作的时候,内存管理器才会将“虚拟地址”和“物理地址”相联系起来。
3.PE文件与虚拟内存之间的映射
2.3.1重要概念
首先,要理解几个概念,我们才可以弄清楚PE文件地址和虚拟内存地址之间的映射关系。
-
文件偏移地址(File Offset):数据在PE文件中的地址叫文件便宜地址,是磁盘上存放时相对于文件开头的偏移地址。
-
装载基址(Image Base):PE装入内存时的基地址。
* EXE文件在内存中的基地址是0x00400000
* DLL文件在内存中的基地址是0x10000000
* 基地址是可以通过修改编译选项来更改 -
虚拟内存地址(Virtual Address,VA):PE文件中的指令被装入内存后的地址。
-
相对虚拟地址(Relative Virtual Address,RVA):内存地址相对于映射基址的偏移量。.
虚拟内存地址、映射基址、相对虚拟内存地址之间的关系:
VA=Image Base + RVA
2.3.2文件数据存放和内存存放的不同
PE文件按照两种数据标准存放:
- 磁盘数据标准存放:以0x200字节为基本单位进行组织,若数据不足200字节,则用0x00来填充。
- 内存数据标准存放:以0x1000字节为基本单位进行,同样,不足被补全,超出则分配下一个0x1000为其所用,内存中的节是0x1000的整数倍。
所以当把文件便宜到虚拟内存地址的换算时,还要看所转换的地址位于第几个节内,这种由存储单位引起的节基址差叫做节偏移。
.text节偏移=0x1000-0x400=0xc00
.rdata节偏移=0x7000-0x6200=0xE00
.data节偏移=0x9000-0x7400=0x1C00
节偏移=相对虚拟偏移量RVA-文件偏移量
文件偏移地址=虚拟内存地址(VA)-装载基址(IB)-节偏移=RVA-节偏移
三、必备工具及简单操作
1. OllyDbg
OllyDbg是一个集成了反汇编分析、十六进制编辑、动态调试等多种功能于一身的功能强大的调试器。
主界面共有五个窗口:
- 反汇编窗口:显示被调试程序的反汇编代码,标题栏上的地址、HEX数据、反汇编、注释可以通过在【窗口中右击出现的菜单界面选项->隐藏标题或显示标题来进行切换是否显示。用鼠标左键点击注释标签可以切换注释显示的方式。】
- 寄存器窗口:显示当前所选线程的CPU寄存器内容。同样点击标签寄存器(FPU)可以切换显示寄存器的方式。
- 信息窗口:显示反汇编窗口中选中的第一个命令的参数及一些跳转目标地址、字串等。
- 数据窗口:显示内存或文件的内容。右键菜单可用于切换显示方式。
- 堆栈窗口:显示当前线程的堆栈。
主要的快捷键:
- F8:单步执行(Stepover),跳过函数
- F7:单步执行(Step in),跟入函数
- F2:按一下设置断点,再按一下取消断点
- F4:执行到当前光标所选中的指令,可以在遇到循环的时候按下达到一直执行到循环结束后的指令的效果
- F9:运行程序直到遇到断点
- Ctrl+G:查看任意位置的数据
2. IDA Pro
IDA Pro是一款反汇编的软件,在大多数情况下用于静态反汇编。
它可以对代码单元进行标注。使用IDA对函数进行标注和注解可以做到全文交叉调用,能够自动识别出系统调用。并且,目前的IDA可以用图形的方式显示出一个函数内部的执行流程,在反汇编界面中按空格键进行汇编代码和图形显示两种模式的切换。
3. Ultra Edit
Ultra Edit是IDM Computer Solutions公司出品的著名文本编辑器。 这款功能强大的文本编辑器,可以编辑文字、Hex、ASCII码,可以取代记事本,内建英文单字检查、C++ 、Java、HTML、VB等多种语言的指令突显,可同时编辑多个文件,而且即使开启很大的文件速度也不会慢。
4. Lord PE
Lord PE是一款强大的可执行文件分析辅助脱壳工具,附带16进制编辑器.不包括反汇编模块。字啊本次学习中,我们用它来查找虚拟内存地址和文件偏移地址来进行地址转换。
四、crack实验
本实验的目的是通过应用刚才介绍的工具来破解程序的密码。
首先我们看一下源码:
#include <stdio.h>
#define PASSWORD "1234567"
int verify_password (char *password)
{
int authenticated;
authenticated=strcmp(password,PASSWORD);
return authenticated;
}
main()
{
int valid_flag=0;
char password[1024];
while(1)
{
printf("please input password: ");
scanf("%s",password);
valid_flag = verify_password(password);
if(valid_flag)
{
printf("incorrect password!\n\n");
}
else
{
printf("Congratulation! You have passed the verification!\n");
break;
}
}
}
功能是一个密码的验证。我们必须输入正确的密码“1234567”时,才能得以确定成功,跳出循环,否则会一直提示密码错误请求再次输入。
step1:用IDA,查找跳转指令的内存地址
- 打开IDA,将在vc6.0下已经得到的exe文件再用IDA打开,按下F12输出更加详细的流程图:
-
从流程图可以清晰地看到,if语句的分支语句为"jz short"。
-
按下空格键切换到汇编指令界面,即可找到该语句所在的内存地址,即在.text节0x004010D5,如下图所示:
step2:用ollydbg,在内存中修改程序
- 关闭IDA,用ollydbg打开crack.exe文件
- 按Ctrl+G,输入0x004010D5,找到关键指令
- 选中指令,按下F2设置断点,可以看到该行内存地址变红
- 按F9执行,打开命令调试行,输入一个错误的密码,再按F9运行程序,会发现提示“跳转未实现”,如下图:
- 双击jz,修改jz为jnz,点击assemble写入内存,如图:
-
此时,可以看到原来内存中的机器码从74也变到了75。
step3:用LordPE,查看PE节信息 -
用LordPE打开.exe文件,查看文件节信息
- 根据公式:文件偏移地址=VA-IB-节偏移=0x004010D5-0x00400000-(0x00001000-0x00001000)=0x10D5,也就是说这条指令在PE文件中位于距离文件开头10D5字节的地方。
step4:用Ultra,修改.exe文件的十六进制代码
- 用UEdit打开crack.exe文件,用快捷键ctrl+G,输入0x10D5直接跳到JE指令处,将下图中的74(JE)改为75(JNE),保存后可重新执行文件。
- 打开VC,重新运行文件,可以发现输入正确密码,反而提示密码错误:
回顾整个实验,其实我们就是将整个程序的逻辑反了过来。将机器代码修改从JE修改为JNE,把逻辑变成非0则进行跳转。因此,输入正确密码判断为0,当然会提示密码错误啦!
本博客主要记录了学习0day的一些准备工具,以及一个小实验来感受一下突然接触这么多陌生的工具具体应该怎么使用。最后的一个小实验还是很有趣的,应该是第一次接触通过这样的方式来修改汇编代码,从而达到绕过验证,成功攻击的目的。希望之后可以利用好这些工具,顺利学习下去吧!
参考文献:
[1]王清.《0day安全:软件漏洞分析技术》[M].中国:电子工业出版社,2008.
[2]王清.《0day安全:软件漏洞分析技术(第2版)》[M].中国:电子工业出版社,2011.