0Day安全软件漏洞分析第2版阅读随笔1

本文最后更新于:2024年9月27日 下午

0Day安全软件漏洞分析第2版阅读随笔1

《0Day安全软件漏洞分析第2版》,浅浅阅读了几章

第一章-基础知识

一些常识

公布漏洞的权威机构

(1) CVE (Common Vulnerabilities and Exposures) 截至目前,这里收录了两万多个漏洞。CVE 会对每个公布的漏洞进行编号、审查。CVE 编号通常也是引用漏洞的标准方式。

(2)CERT(Computer Emergency Response Team) 计算机应急响应组往往会在第一时间跟进当前的严重漏洞,包括描述信息、POC 的发布链接、厂商的安全响应进度、 用户应该采取的临时性防范措施等。

何为0Day

​ 微软每个月第二周的星期二发布补丁,这一天通常被称为Black Tuesday,因为会有许多攻击者通宵达旦地去研究这些补丁 patch 了哪些漏洞,并写出 exploit。因为在补丁刚刚发布的一段时 间内,并非所有用户都能及时修复,故这种新公布的漏洞也有一定利用价值。有时把攻击这种 刚刚被 patch 过的漏洞称为 1 day 攻击(patch 发布后1天,叫做1day,5天叫做 5day,未发 patch 统称 0 day)

必备工具

OllyDbg

Ollydbg 是一个集成了反汇编分析、十六进制编辑、动态调试等多种功能于一身的功能强大的调试器。

但是仅支持动态调试32位的系统。

IDAPro

IDA 好像是一张二进制的地图,通过它的标注功能可以迅速掌握大量汇编代码的架构,不至于在繁杂的二进制迷宫中迷失方向。目前版本的 IDA 甚至可以用图形方式显示出一个函数内部的执行流程。

x64dbg

通过这款调试工具用户可以分析64位的应用,这是OllyDbg所不能做到的,它只能分析32位应用,所以想要分析64位应用,x64dbg是一款专门用于分析64位应用的调试软件。

二进制编辑器

比较著名的十六进制编辑器包括 UltraEdit、Hex Workshop 和 WinHex 和 010 editor

二进制文件概述

PE文件格式

PE,是Portable Executable的缩写,是Win32平台下可执行文件所遵守的数据格式。像.exe.dll都是典型的PE文件。在文件执行时,操作系统会按照PE文件格式的约定去相应的地方调用资源,然后装入内存的不同区域。

PE文件格式将可执行文件分为了几个数据节,一个典型的分节:

  • .text: 由编译器产生,存放二进制的机器码,也是我们反汇编和调试的对象。
  • .data: 初始化的数据块,如宏定义、全局变量、静态变量等
  • .idata: 动态链接库等外来函数的信息
  • .rsrc: 程序资源,如图标、菜单等、

但我们需要注意的是,节可以被任意命名,并且代码的任意部分可以编译到PE的任意节中,如果可执行文件经过了“加壳”处理,PE 的节信息就会变得非常“古怪”。 在 Crack 和反病毒分析中需要经常处理这类古怪的 PE 文件。

虚拟内存

在内核状态下,我们才能看到并调试物理内存。所以用户态下,我们用调试器看到的都是虚拟内存。Windows让所有的程序都认为自己拥有独立的4GB的内存,这当然是不可能的哈哈的😁

如下图展示:

这里书中有个比喻非常精妙:

  • 内存管理机制就像银行
  • 进程=用户
  • 内存管理器=银行
  • 物理内存=现金
  • 虚拟内存=存款
  • 当进程(用户)需要使用物理内存(现金)的时候,它就会向银行(内存管理器)申请将虚拟内存(存款)映射为物理内存。

PE文件与虚拟内存间的映射

​ 在静态调试中,我们看到的某个指令的位置,它是当前函数调用相对于磁盘文件得到的,也就是文件偏移。我们还需要知道这条指令在内存中的位置,即虚拟内存地址。

  • 文件偏移地址:数据在PE文件中相对于文件开头的地址,这里的意思就是文件没有运行的时候
  • 装载基址:PE装入内存时的基地址。默认情况下,EXE 文件在虚拟内存中的基地址是 0x00400000,DLL 文件是 0x10000000。这些位置可以通过修改编译选项更改。
  • 虚拟内存地址:PE文件中机制被装入内存后的地址。
  • 相对虚拟地址:内存地址相对于映射基址的偏移量。
  • 相对虚拟地址=虚拟内存地址-装载基址

操作系统在装载时基本上不会破坏程序的各种数据结构,所以文件地址和相对虚拟地址有很大的一致性,但是存在存放基本单位的差别。

  • 文件数据按0x200字节为基本单位进行组织,PE数据节的大小始终是0x200的整数倍
  • 内存数据按0x1000字节为基本单位进行组织,内存数据节的大小始终是0x1000的整数倍
  • 这种由文件单位引起的节基址差称作节偏移,所以文件偏移地址=虚拟内存地址-装载基址-节地址差

crack_me1

实验代码来源于原书

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#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;
}
}
}

使用命令gcc -o crack_me.exe test.c编译为64位的exe文件,当然如果你不是x86-64架构,那么命令有所变化,需要编为32位的程序😋。

接下来,使用IDA查看文件结构,这个时候假装我们不知道代码是自己写的😁

可以看到如下的文件结构:

这里普及一下:红色的线表示if语句为真,绿色的线表示if语句结果为假

然后可以发现,我们需要得到Congratulation!,那么用鼠标选中这条线,按空格切换到汇编代码:

使用了一个jz指令,这里我们需要知道这条指令由状态标志寄存器的ZF位决定,为1则跳转

ZF表示结果运算是否为0,如果为0则置1,反之置0。

所以这里我只需要让ZF=1即可

将程序拖进x64dbg里,然后程序会自动运行,这里读者不知道为什么会自动中断😂,这里直接继续运行

到需要我们输入密码即可,这里我们需要寻找之前分析出来的判断位置,然后下断点,修改标志位即可破解成功!

我们可以通过调用堆栈窗口,查看crack_me.exe的调用,然后查找出来位置,然后在即将跳转的那个指令处打下断点,可以发现这里x64gbd汇编出来是je指令,笔者这里还不清楚为什么会这样😭。当然这里效果和jz是一样,破解方法不变。

然后在terminal里输入密码,就会在断点处停下,在视图右侧会显示当前CPU的一些寄存器的状态,修改ZF=1再单步调试到输出即可。

破解成功!原密码为1234567

第一章学习完毕!

之前有些基础,所以觉得不难,但是还是觉得这本书太适合入门了,写的很清晰明了的😍


0Day安全软件漏洞分析第2版阅读随笔1
https://3xsh0re.github.io/2023/10/26/0Day安全软件漏洞分析第2版阅读随笔1/
作者
3xsh0re
发布于
2023年10月26日
许可协议