二进制漏洞基础知识(开了一个新的坑,坑多慢慢填,祝愿自己能有决心将补坑任务完成!)
(自己读书总结的内容,转载需要说明来源哦!)

漏洞概述

漏洞定义:

  功能性逻辑缺陷(bug):影响软件的正常功能,例如,执行结果错误、图标显示错误等。
  安全性逻辑缺陷(漏洞):通常情况下不影响软件的正常功能,但被攻击者成功利用后,有可能引起软件去执行额外的恶意代码。常见的漏洞包括软件中的缓冲区溢出漏洞、网站中的跨站脚本漏洞(XSS)、SQL 注入漏洞等。

安全误区:

1、不运行来历不明的软件就不会中毒。
  不对,如果病毒利用系统级漏洞进行传播,或者计算机内程序存在一些远程命令执行的漏洞,那么可能会被攻击者“主动进攻”
2、点击一个链接,不会中毒。
  如果浏览器存在解析漏洞,那么在解析服务器传来的数据的时候。其中包含的shellcode可能被触发,后续下载木马。
3、Word,PPT,Excel不是可执行文件,所以点击没有问题。
  Office全家桶里包含许多功能组件,有一些已经被曝光的漏洞可以让你的电脑执行恶意代码或者远程下载恶意代码执行。
4、密码很复杂,那么我的账户是安全的。
  密码复杂只能防止爆破。密码存储安全问题,密码传输安全问题,登录凭证保护,钓鱼攻击等等都有可能被攻击者利用。

漏洞挖掘、漏洞分析

  挖掘:从技术角度讲,漏洞挖掘实际上是一种高级的测试( QA)。学术界一直热衷于使用静态分析的方法寻找源代码中的漏洞;而在工程界,不管是安全专家还是攻击者,普遍采用的漏洞挖掘方法是 Fuzz,这实际是一种“灰”盒测试。
  分析:在分析漏洞时,如果能够搜索到 POC( proof of concept)代码,就能重现漏洞被触发的现场。这时可以使用调试器观察漏洞的细节,或者利用一些工具(如 Paimei)更方便地找到漏洞的触发点。当无法获得 POC 时,就只有厂商提供的对漏洞的简单描述了。一个比较通用的办法是使用补丁比较器,首先比较 patch 前后可执行文件都有哪些地方被修改,之后可以利用反汇编工具(如 IDA Pro)重点逆向分析这些地方。

漏洞公布

1、CVE (Common Vulnerabilities and Exposures) http://cve.mitre.org/ 不用过多介绍了。
2、CERT(Computer Emergency Response Team)http://www.cert.org/ 计算机应急响应组往往会在第一时间跟进当前的严重漏洞,包括描述信息、 POC 的发布链接、厂商的安全响应进度、用户应该采取的临时性防范措施等。
3、CNVD(国家信息安全漏洞共享平台)https://www.cnvd.org.cn/ 不用过多介绍了。
4、微软的安全中心所公布的漏洞也是所有安全工作者和黑客们最感兴趣的地方。微软
每个月第二周的星期二发布补丁。有许多攻击者通宵达旦地去研究这些补丁patch了哪些漏洞,并写出exploit。因为在补丁刚刚发布的一段时间内,并非所有用户都能及时修复,故这种新公布的漏洞也有一定利用价值。
5、各大安全厂商的威胁情报,漏洞库等等。

二进制文件概述

PE格式

  PE( Portable Exec utable)是 Win32 平台下可执行文件遵守的数据格式。常见的可执行文件(如“ .exe”文件和“ .dll”文件)都是典型的 PE 文件。
PE典型节区:
  .text 由编译器产生,存放着二进制的机器代码,也是我们反汇编和调试的对象。
  .data 初始化的数据块,如宏定义、全局变量、静态变量等。
  .idata 可执行文件所使用的动态链接库等外来函数与文件的信息。
  .rsrc 存放程序的资源,如图标、菜单等。
除此以外,还可能出现的节包括“ .reloc”、“ .edata”、“ .tls”、“ .rdata”等。

虚拟内存

  Windows 的内存可以被分为两个层面:物理内存和虚拟内存。其中,物理内存比较复杂,
需要进入 Windows 内核级别 ring0 才能看到。通常,在用户模式下,我们用调试器看到的内存
地址都是虚拟内存。

虚拟内存.png

书里面有个非常有趣的理解思路
进程相当于储户。
· 内存管理器相当于银行。
· 物理内存相当于钞票。
· 虚拟内存相当于存款。
· 进程可能拥有大片的内存,但使用的往往很少;储户拥有大笔的存款,但实际生活中的开销并没有多少。
· 进程不使用虚拟内存时,这些内存只是一些地址,是虚拟存在的,是一笔无形的数字财富。
  进程使用内存时,内存管理器会为这个虚拟地址映射实际的物理内存地址,虚拟内存地址和最终被映射到的物理内存地址之间没有什么必然联系;储户需要用钱时,银行才会兑换一定的现金给储户,但物理钞票的号码与储户心目中的数字存款之间可能并没有任何联系。
  操作系统的实际物理内存空间可以远远小于进程的虚拟内存空间之和,仍能正常调度;银行中的现金准备可以远远小于所有储户的储蓄额总和,仍能正常运转,因为很少会出现所有储户同时要取出全部存款的现象;社会上实际流通的钞票也可以远远小于社会的财富总额。

PE文件和虚拟内存的映射

1、静态反汇编工具看到的 PE 文件中某条指令的位置是相对于磁盘文件而言的,即所谓的文件偏移,我们可能还需要知道这条指令在内存中所处的位置,即虚拟内存地址(VA)
2、反之,在调试时看到的某条指令的地址是虚拟内存地址,我们也经常需要回到PE文件中找到这条指令对应的机器码。

基础概念
1、文件偏移地址(File Offset):数据在 PE 文件中的地址叫文件偏移地址,个人认为叫做文件地址更加准确。这是文件在磁盘上存放时相对于文件开头的偏移。
2、装载基址(Image Base):PE 装入内存时的基地址。默认情况下, EXE文件在内存中的基地址是 0x00400000,DLL文件是0x10000000。这些位置可以通过修改编译选项更改。
3、虚拟内存地址(Virtual Address,VA):PE文件中的指令被装入内存后的地址。
4、相对虚拟地址(Relative Virtual Address,RVA):相对虚拟地址是内存地址相对于映射基址的偏移量。


虚拟内存地址、映射基址、相对虚拟内存地址三者之间有如下关系。

VA = Image Base + RVA

  文件偏移是相对于文件开始处 0 字节的偏移,RVA(相对虚拟地址)则是相对于装载基址 0x00400000 处的偏移。由于操作系统在进行装载时“基本”上保持 PE 中的各种数据结构,所以文件偏移地址和 RVA 有很大的一致性。但是还是存在一些区别,这些差异是由于文件数据的存放单位与内存数据存放单位不同而造成的。
(1)PE 文件中的数据按照磁盘数据标准存放,以 0x200 字节为基本单位进行组织。当一个数据节(section)不足 0x200 字节时,不足的地方将被 0x00 填充;当一个数据节超过 0x200字节时,下一个 0x200 块将分配给这个节使用。因此 PE 数据节的大小永远是 0x200 的整数倍。
(2)当代码装入内存后,将按照内存数据标准存放,并以 0x1000 字节为基本单位进行组织。类似的,不足将被补全,若超出将分配下一个 0x1000 为其所用。因此,内存中的节总是0x1000 的整数倍。

文件偏移与RVA

  节偏移:由存储单位差异引起的节基址差称做节偏移
如上图:
.text 节偏移=0x1000-0x400=0xc00
.rdata 节偏移=0x7000-0x6200=0xE00
.data 节偏移=0x9000-0x7400=0x1C00
.rsrc 节偏移=0x2D000-0x7800=0x25800
文件偏移地址与虚拟内存地址之间的换算关系可以用下面的公式来计算。
文件偏移地址 = 虚拟内存地址(VA) −装载基址(Image Base) − 节偏移
       = RVA -节偏移
  许多PE工具提供了这类地址的转换,书中举例程序为LordPE。我测试了一下DIE也具备该功能,推荐使用DIE。

工具介绍

1、OllyDbg:动态32位调试器
2、SoftICE:没用过,以后测一测。
3、WinDbg:微软官方内核级调试器
4、X64Dbg:64位调试器
5、IDA Pro:静态反编译工具
6、二进制编辑器(010Editor、WinHex等)
7、虚拟机(VMware,VirtutalBox)
8、python环境(Anaconda + VSCode)
  使用方法就不写了。

分析小实验

//这段代码我从书里复制过来的,没有编译过,有问题自己改改。我直接用的给的测试用例进行实验。
#include <stdio.h>
#define PASSWORD "1234567"
int verify_password (char *password)
{
    int authenticated;
    authenticated = strcmp(password,PASSWORD);
    return authenticated;
}
int 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;
        }
    }
    return 0;
}

要求:
  使用IDA,OllyDbg(或x64Dbg)和Winhex都爆破成功。
  爆破:将软件进行破解。

X64Dbg
  x64Dbg将0040106E处的jne改为jmp即可。


IDA
  IDA将0040106E处的75 0F改为EB 0F即可。