mirror of
https://github.com/winterknife/EVENSTAR
synced 2026-06-21 14:13:51 +00:00
added PagingDbgExt project
This commit is contained in:
@@ -7,6 +7,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReadCRDbgExt", "ReadCRDbgEx
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReadMSW", "ReadMSW\ReadMSW.vcxproj", "{F9AB9899-9F93-4252-B634-740F19CCC1DC}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PagingDbgExt", "PagingDbgExt\PagingDbgExt.vcxproj", "{4321EA53-183E-4104-887D-5CBFC14E4211}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Release|x64 = Release|x64
|
||||
@@ -16,6 +18,8 @@ Global
|
||||
{78BD9103-3B0A-46DF-9261-148EA8F34DF0}.Release|x64.Build.0 = Release|x64
|
||||
{F9AB9899-9F93-4252-B634-740F19CCC1DC}.Release|x64.ActiveCfg = Release|x64
|
||||
{F9AB9899-9F93-4252-B634-740F19CCC1DC}.Release|x64.Build.0 = Release|x64
|
||||
{4321EA53-183E-4104-887D-5CBFC14E4211}.Release|x64.ActiveCfg = Release|x64
|
||||
{4321EA53-183E-4104-887D-5CBFC14E4211}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
// ========================================================================
|
||||
// File: BaseDataTypes.h
|
||||
//
|
||||
// Author: winterknife
|
||||
//
|
||||
// Description: Type definitions for common Windows base data types made
|
||||
// for maintaining uniformity across all User Mode and Kernel Mode code
|
||||
//
|
||||
// Modifications:
|
||||
// 2021-07-31 Created
|
||||
// 2022-08-13 Updated
|
||||
// ========================================================================
|
||||
|
||||
// ========================================================================
|
||||
// Pragmas
|
||||
// ========================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
// ========================================================================
|
||||
// Type definitions
|
||||
// ========================================================================
|
||||
|
||||
#pragma region TYPEDEFS
|
||||
|
||||
// 8-bit unsigned integer, range = 0 - 255, unsigned char
|
||||
typedef unsigned __int8 BYTE, *PBYTE;
|
||||
|
||||
// 16-bit unsigned integer, range = 0 - 65535, unsigned short
|
||||
typedef unsigned __int16 WORD, *PWORD;
|
||||
|
||||
// 32-bit unsigned integer, range = 0 - 4294967295, unsigned int or unsigned long
|
||||
typedef unsigned long DWORD, *PDWORD;
|
||||
|
||||
// 64-bit unsigned integer, range = 0 - 18446744073709551615, unsigned long long
|
||||
typedef unsigned __int64 QWORD, *PQWORD;
|
||||
|
||||
// Should be TRUE(1) or FALSE(0), unsigned char or bool
|
||||
typedef unsigned __int8 BOOLEAN, *PBOOLEAN;
|
||||
|
||||
// 8-bit UTF-8/Multibyte/ANSI character, char
|
||||
typedef __int8 CHAR, *PCHAR;
|
||||
|
||||
// 16-bit UTF-16/Wide/UNICODE character, unsigned short
|
||||
typedef wchar_t WCHAR, *PWCHAR;
|
||||
|
||||
// Pointer to any type, size = 4 bytes or 8 bytes depending on code bitness
|
||||
typedef void* PVOID;
|
||||
|
||||
// Pointer to a constant of any type
|
||||
typedef const void* PCVOID;
|
||||
|
||||
// Pointer to constant null-terminated string of ANSI characters
|
||||
typedef _Null_terminated_ const __int8* PCSTR;
|
||||
|
||||
// Pointer to constant null-terminated string of UNICODE characters
|
||||
typedef _Null_terminated_ const wchar_t* PCWSTR;
|
||||
|
||||
// Pointer to constant null-terminated string of ANSI or UNICODE characters depending on character encoding scheme
|
||||
#if defined(UNICODE)
|
||||
typedef const __wchar_t* PCTSTR;
|
||||
#else
|
||||
typedef const __int8* PCTSTR;
|
||||
#endif
|
||||
|
||||
// 32-bit or 64-bit unsigned integer, range = 0 - 4294967295 or 18446744073709551615 depending on compiler bitness
|
||||
// Used for casting pointers
|
||||
#if defined(_WIN64)
|
||||
typedef unsigned __int64 DWORD_PTR, *PDWORD_PTR;
|
||||
#else
|
||||
typedef unsigned long DWORD_PTR, *PDWORD_PTR;
|
||||
#endif
|
||||
|
||||
#pragma endregion
|
||||
@@ -0,0 +1,155 @@
|
||||
// ========================================================================
|
||||
// File: Common.h
|
||||
//
|
||||
// Author: winterknife
|
||||
//
|
||||
// Description: Contains the common stuff for this project
|
||||
//
|
||||
// Modifications:
|
||||
// 2021-08-21 Created
|
||||
// 2025-05-13 Updated
|
||||
// ========================================================================
|
||||
|
||||
// ========================================================================
|
||||
// Pragmas
|
||||
// ========================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
// Specify program entry point
|
||||
#pragma comment(linker, "/ENTRY:DllInit")
|
||||
|
||||
// Merge sections
|
||||
#if defined (_MSC_VER)
|
||||
#if (_MSC_VER >= 1920)
|
||||
#pragma comment(linker, "/MERGE:_RDATA=.rdata")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Emit error message at compile time if trying to build for 32-bit x86 target
|
||||
#if !defined(_WIN64)
|
||||
#error x86 build target is unsupported!
|
||||
#endif
|
||||
|
||||
// ========================================================================
|
||||
// Includes
|
||||
// ========================================================================
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define _NO_CRT_STDIO_INLINE
|
||||
#include <Windows.h>
|
||||
#include <intrin.h>
|
||||
#include <stdio.h>
|
||||
#include "BaseDataTypes.h"
|
||||
|
||||
#pragma intrinsic(__stosb)
|
||||
#pragma intrinsic(__movsb)
|
||||
#pragma intrinsic(strlen)
|
||||
#pragma intrinsic(strcmp)
|
||||
|
||||
// ========================================================================
|
||||
// Macros
|
||||
// ========================================================================
|
||||
|
||||
#pragma region MACROS
|
||||
|
||||
// Module name
|
||||
#define __MODULE__ "PagingDbgExt"
|
||||
|
||||
// Comment out for final build
|
||||
//#define DEBUG_BUILD
|
||||
|
||||
// Print debug message macro
|
||||
#ifdef DEBUG_BUILD
|
||||
#define STRIP(...) __VA_ARGS__
|
||||
#define DEBUG_PREFIX "[DBG]: "
|
||||
#define DEBUG_PRINT(_x_, ...) printf(DEBUG_PREFIX _x_, ##__VA_ARGS__);
|
||||
#else
|
||||
#define DEBUG_PRINT(_x_, ...) void(0)
|
||||
#endif
|
||||
|
||||
// Stringizing operator macro
|
||||
#ifndef _CRT_STRINGIZE
|
||||
#define _CRT_STRINGIZE_(x) #x
|
||||
#define _CRT_STRINGIZE(x) _CRT_STRINGIZE_(x)
|
||||
#endif
|
||||
|
||||
// Get mangled name of a function
|
||||
#define GET_MANGLED_FUNCTION_NAME __pragma(message(__FILE__ _CRT_STRINGIZE((__LINE__): \nfunction:\t) __FUNCSIG__ " is mangled to: " __FUNCDNAME__))
|
||||
|
||||
// To set alternate name of decorated x86 IAT global function pointer
|
||||
#ifdef _X86_
|
||||
// Uses undocumented /ALTERNATENAME linker flag
|
||||
#define ALT_NAME(name, n) __pragma(comment(linker, _CRT_STRINGIZE(/ALTERNATENAME:__imp__##name##@##n####=___imp_##name)))
|
||||
#else
|
||||
#define ALT_NAME(name, n)
|
||||
#endif
|
||||
|
||||
// To declare/initialize global IAT function pointers for run-time dynamic linking, use on global scope
|
||||
#define IMP_FUNC(name, n) EXTERN_C_START PVOID __imp_##name = NULL; EXTERN_C_END ALT_NAME(name, n)
|
||||
|
||||
// To declare/initialize local function pointers for run-time dynamic linking, use on local scope
|
||||
// Warning: will ignore SAL annotations
|
||||
#define IMP_FUNC_PIC(name) typedef decltype(name) __type_##name; __type_##name* ##name = NULL;
|
||||
|
||||
// Check if a function is in a delay loaded module, use on a global scope
|
||||
#define CHECK_DELAY_LOAD(f) extern "C" extern void* __imp_load_ ##f; void test_delay_load ##f(){ (__imp_load_ ##f) ? 1 : 0; }
|
||||
|
||||
// Macro to indicate a specific function to the linker as the first in the link order
|
||||
#define CODE_BEGIN code_seg(push, ".text")
|
||||
|
||||
// Macro to indicate the end of the specific function to the linker
|
||||
#define CODE_END code_seg(pop)
|
||||
|
||||
// Macro to disable all compiler optimizations for a specific function
|
||||
#define OPTIMIZATION_OFF optimize("", off)
|
||||
|
||||
// Macro to re-enable/reset compiler optimizations for a specific function
|
||||
#define OPTIMIZATION_ON optimize("", on)
|
||||
|
||||
// Macro to enable compiler optimizations for generating short sequences of machine code for a specific function
|
||||
#if defined(_M_IX86)
|
||||
#define OPTIMIZATION_SIZE optimize("gsy", on)
|
||||
#else
|
||||
#define OPTIMIZATION_SIZE optimize("gs", on)
|
||||
#endif
|
||||
|
||||
// Macro to enable compiler optimizations for generating fast sequences of machine code for a specific function
|
||||
#if defined(_M_IX86)
|
||||
#define OPTIMIZATION_SPEED optimize("gty", on)
|
||||
#else
|
||||
#define OPTIMIZATION_SPEED optimize("gt", on)
|
||||
#endif
|
||||
|
||||
// Macro to fill a block of memory with zeroes given it's address and length in bytes by generating store string instruction (rep stosb)
|
||||
// Enhanced REP STOSB/MOVSB (ERMSB) are only available since Ivy Bridge Intel microarchitecture (2012/2013)
|
||||
// Processors that provide support for enhanced MOVSB/STOSB operations are enumerated by the CPUID feature flag: CPUID:(EAX=7H, ECX=0H):EBX.ERMSB[bit 9] = 1
|
||||
#define ZERO_MEMORY(Destination, Length) __stosb((PBYTE)Destination, 0, Length)
|
||||
|
||||
// Macro to copy a block of memory given it's source address, destination address and the number of bytes to copy by generating move string instruction (rep movsb)
|
||||
#define COPY_MEMORY(Destination, Source, Count) __movsb((PBYTE)Destination, (const PBYTE)Source, Count)
|
||||
|
||||
#pragma endregion
|
||||
|
||||
// ========================================================================
|
||||
// C inline routines
|
||||
// ========================================================================
|
||||
|
||||
#pragma region INLINES
|
||||
|
||||
/// @brief To compare two blocks of memory and return the number of bytes that match
|
||||
/// @param pcSource1 Pointer to the first block of memory
|
||||
/// @param pcSource2 Pointer to the second block of memory
|
||||
/// @param dwptrLength The number of bytes to compare
|
||||
/// @return Number of bytes in the two blocks that match, if all bytes match up to the specified Length value, the Length value is returned
|
||||
extern "C" __forceinline DWORD_PTR __stdcall compare_memory(_In_ const PVOID pcSource1, _In_ const PVOID pcSource2, _In_ DWORD_PTR dwptrLength) {
|
||||
// Init local variables
|
||||
DWORD_PTR dwptrIndex = 0;
|
||||
|
||||
// Start comparing the two blocks of memory
|
||||
for (dwptrIndex = 0; (dwptrIndex < dwptrLength) && (((PBYTE)pcSource1)[dwptrIndex] == ((PBYTE)pcSource2)[dwptrIndex]); dwptrIndex++);
|
||||
|
||||
return dwptrIndex;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
@@ -0,0 +1,59 @@
|
||||
// ========================================================================
|
||||
// File: DbgExt.h
|
||||
//
|
||||
// Author: winterknife
|
||||
//
|
||||
// Description: Header file for DbgExt.cpp source file
|
||||
//
|
||||
// Modifications:
|
||||
// 2024-10-08 Created
|
||||
// 2024-10-08 Updated
|
||||
// ========================================================================
|
||||
|
||||
// ========================================================================
|
||||
// Pragmas
|
||||
// ========================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
// ========================================================================
|
||||
// Includes
|
||||
// ========================================================================
|
||||
|
||||
#include "Common.h"
|
||||
#define KDEXT_64BIT
|
||||
#include <WDBGEXTS.H>
|
||||
#include <ntverp.h>
|
||||
|
||||
// ========================================================================
|
||||
// C routine declarations
|
||||
// ========================================================================
|
||||
|
||||
#pragma region DECLARATIONS
|
||||
|
||||
/// @brief Load and initialize the extension module
|
||||
/// @param pWindbgExtensionApis Pointer to WINDBG_EXTENSION_APIS64 structure
|
||||
/// @param woMajorVersion Specifies the Microsoft Windows build type
|
||||
/// @param woMinorVersion Specifies the Windows build number of the target system
|
||||
/// @return None
|
||||
extern "C" __declspec(dllexport) VOID __stdcall WinDbgExtensionDllInit(
|
||||
_In_ PWINDBG_EXTENSION_APIS pWindbgExtensionApis,
|
||||
_In_ WORD woMajorVersion,
|
||||
_In_ WORD woMinorVersion
|
||||
);
|
||||
|
||||
/// @brief Returns version information about the extension DLL
|
||||
/// @param None
|
||||
/// @return Pointer to EXT_API_VERSION structure
|
||||
extern "C" __declspec(dllexport) LPEXT_API_VERSION __stdcall ExtensionApiVersion(
|
||||
VOID
|
||||
);
|
||||
|
||||
/// @brief Verifies that the extension module version matches the debugger version, and outputs a warning message if there is a mismatch
|
||||
/// @param None
|
||||
/// @return None
|
||||
extern "C" __declspec(dllexport) VOID __stdcall CheckVersion(
|
||||
VOID
|
||||
);
|
||||
|
||||
#pragma endregion
|
||||
@@ -0,0 +1,184 @@
|
||||
// ========================================================================
|
||||
// File: GetKernelDirectoryTableBase.h
|
||||
//
|
||||
// Author: winterknife
|
||||
//
|
||||
// Description: Header file for GetKernelDirectoryTableBase.cpp source file
|
||||
//
|
||||
// Modifications:
|
||||
// 2025-05-13 Created
|
||||
// 2025-05-18 Updated
|
||||
// ========================================================================
|
||||
|
||||
// ========================================================================
|
||||
// Pragmas
|
||||
// ========================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
// ========================================================================
|
||||
// Includes
|
||||
// ========================================================================
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
// ========================================================================
|
||||
// Macros
|
||||
// ========================================================================
|
||||
|
||||
#pragma region MACROS
|
||||
|
||||
#define PSB_GDT32_NULL 0 * 16
|
||||
#define PSB_GDT32_CODE64 1 * 16
|
||||
#define PSB_GDT32_DATA32 2 * 16
|
||||
#define PSB_GDT32_CODE32 3 * 16
|
||||
#define PSB_GDT32_MAX 3
|
||||
|
||||
#define KUSER_SHARED_DATA_RO_MAPPING_X64_KVA 0xFFFFF78000000000
|
||||
#define ACTIVEPROCESSORCOUNT_OFFSET 0x03C0
|
||||
|
||||
#pragma endregion
|
||||
|
||||
// ========================================================================
|
||||
// Structures/Enumerations/Unions
|
||||
// ========================================================================
|
||||
|
||||
#pragma region STRUCTS_ENUMS_UNIONS
|
||||
|
||||
#pragma pack(push, 2)
|
||||
typedef struct _FAR_JMP_16 {
|
||||
UCHAR OpCode; // opcode = 0xE9
|
||||
USHORT Offset;
|
||||
} FAR_JMP_16, *PFAR_JMP_16;
|
||||
|
||||
typedef struct _FAR_TARGET_32 {
|
||||
ULONG Offset;
|
||||
USHORT Selector;
|
||||
} FAR_TARGET_32, *PFAR_TARGET_32;
|
||||
|
||||
typedef struct _PSEUDO_DESCRIPTOR_32 {
|
||||
USHORT Limit;
|
||||
ULONG Base;
|
||||
} PSEUDO_DESCRIPTOR_32, *PPSEUDO_DESCRIPTOR_32;
|
||||
#pragma pack(pop)
|
||||
|
||||
// 0x10 bytes (sizeof)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4201) // anonymous unions warning
|
||||
typedef union _KGDTENTRY64 {
|
||||
struct {
|
||||
USHORT LimitLow;
|
||||
USHORT BaseLow;
|
||||
union {
|
||||
struct {
|
||||
UCHAR BaseMiddle;
|
||||
UCHAR Flags1;
|
||||
UCHAR Flags2;
|
||||
UCHAR BaseHigh;
|
||||
} Bytes;
|
||||
struct {
|
||||
ULONG BaseMiddle : 8;
|
||||
ULONG Type : 5;
|
||||
ULONG Dpl : 2;
|
||||
ULONG Present : 1;
|
||||
ULONG LimitHigh : 4;
|
||||
ULONG System : 1;
|
||||
ULONG LongMode : 1;
|
||||
ULONG DefaultBig : 1;
|
||||
ULONG Granularity : 1;
|
||||
ULONG BaseHigh : 8;
|
||||
} Bits;
|
||||
};
|
||||
ULONG BaseUpper;
|
||||
ULONG MustBeZero;
|
||||
};
|
||||
ULONG64 Alignment;
|
||||
} KGDTENTRY64, *PKGDTENTRY64;
|
||||
#pragma warning(pop)
|
||||
|
||||
typedef struct _KDESCRIPTOR {
|
||||
USHORT Pad[3];
|
||||
USHORT Limit;
|
||||
PVOID Base;
|
||||
} KDESCRIPTOR, *PKDESCRIPTOR;
|
||||
|
||||
typedef struct _KSPECIAL_REGISTERS {
|
||||
ULONG64 Cr0;
|
||||
ULONG64 Cr2;
|
||||
ULONG64 Cr3;
|
||||
ULONG64 Cr4;
|
||||
ULONG64 KernelDr0;
|
||||
ULONG64 KernelDr1;
|
||||
ULONG64 KernelDr2;
|
||||
ULONG64 KernelDr3;
|
||||
ULONG64 KernelDr6;
|
||||
ULONG64 KernelDr7;
|
||||
KDESCRIPTOR Gdtr;
|
||||
KDESCRIPTOR Idtr;
|
||||
USHORT Tr;
|
||||
USHORT Ldtr;
|
||||
ULONG MxCsr;
|
||||
ULONG64 DebugControl;
|
||||
ULONG64 LastBranchToRip;
|
||||
ULONG64 LastBranchFromRip;
|
||||
ULONG64 LastExceptionToRip;
|
||||
ULONG64 LastExceptionFromRip;
|
||||
ULONG64 Cr8;
|
||||
ULONG64 MsrGsBase;
|
||||
ULONG64 MsrGsSwap;
|
||||
ULONG64 MsrStar;
|
||||
ULONG64 MsrLStar;
|
||||
ULONG64 MsrCStar;
|
||||
ULONG64 MsrSyscallMask;
|
||||
ULONG64 Xcr0;
|
||||
ULONG64 MsrFsBase;
|
||||
ULONG64 SpecialPadding0;
|
||||
} KSPECIAL_REGISTERS, *PKSPECIAL_REGISTERS;
|
||||
|
||||
typedef struct _KPROCESSOR_STATE {
|
||||
KSPECIAL_REGISTERS SpecialRegisters;
|
||||
CONTEXT ContextFrame;
|
||||
} KPROCESSOR_STATE, *PKPROCESSOR_STATE;
|
||||
|
||||
// nt!HalpLowStub
|
||||
typedef struct _PROCESSOR_START_BLOCK* PPROCESSOR_START_BLOCK;
|
||||
typedef struct _PROCESSOR_START_BLOCK {
|
||||
FAR_JMP_16 Jmp; // The block starts with a jmp instruction to the end of the block
|
||||
ULONG CompletionFlag; // Completion flag is set to non-zero when the target processor has started
|
||||
PSEUDO_DESCRIPTOR_32 Gdt32; // Pseudo descriptors for GDT
|
||||
PSEUDO_DESCRIPTOR_32 Idt32; // Pseudo descriptors for IDT
|
||||
KGDTENTRY64 Gdt[PSB_GDT32_MAX + 1]; // The temporary 32-bit GDT itself resides here
|
||||
ULONG64 TiledCr3; // Physical address of the 64-bit top-level identity-mapped page table
|
||||
FAR_TARGET_32 PmTarget; // Far jump target from Rm to Pm code
|
||||
FAR_TARGET_32 LmIdentityTarget; // Far jump target from Pm to Lm code
|
||||
PVOID LmTarget; // Address of LmTarget
|
||||
PPROCESSOR_START_BLOCK SelfMap; // Linear address of this structure
|
||||
ULONG64 MsrPat; // Contents of the PAT msr
|
||||
ULONG64 MsrEFER; // Contents of the EFER msr
|
||||
KPROCESSOR_STATE ProcessorState; // Initial processor state for the processor to be started
|
||||
} PROCESSOR_START_BLOCK;
|
||||
|
||||
#pragma endregion
|
||||
|
||||
// ========================================================================
|
||||
// C routine declarations
|
||||
// ========================================================================
|
||||
|
||||
#pragma region DECLARATIONS
|
||||
|
||||
/// @brief Built-in command to find the kernel's DTB (DirectoryTableBase) which is the physical address of the base of the paging-structure hierarchy for KVAS contained in CR3 from the Low Stub
|
||||
/// @param hCurrentProcess Handle for the current process
|
||||
/// @param hCurrentThread Handle for the current thread
|
||||
/// @param qwCurrentPc Program counter
|
||||
/// @param dwProcessor Current processor
|
||||
/// @param strArgs Command line arguments
|
||||
/// @return None
|
||||
extern "C" __declspec(dllexport) VOID __stdcall get_kernel_dtb(
|
||||
_In_ HANDLE hCurrentProcess,
|
||||
_In_ HANDLE hCurrentThread,
|
||||
_In_ QWORD qwCurrentPc,
|
||||
_In_ DWORD dwProcessor,
|
||||
_In_z_ PCSTR strArgs
|
||||
);
|
||||
|
||||
#pragma endregion
|
||||
@@ -0,0 +1,46 @@
|
||||
// ========================================================================
|
||||
// File: Help.h
|
||||
//
|
||||
// Author: winterknife
|
||||
//
|
||||
// Description: Header file for Help.cpp source file
|
||||
//
|
||||
// Modifications:
|
||||
// 2025-05-14 Created
|
||||
// 2025-05-14 Updated
|
||||
// ========================================================================
|
||||
|
||||
// ========================================================================
|
||||
// Pragmas
|
||||
// ========================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
// ========================================================================
|
||||
// Includes
|
||||
// ========================================================================
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
// ========================================================================
|
||||
// C routine declarations
|
||||
// ========================================================================
|
||||
|
||||
#pragma region DECLARATIONS
|
||||
|
||||
/// @brief Built-in help command for the debugger extension DLL
|
||||
/// @param hCurrentProcess Handle for the current process
|
||||
/// @param hCurrentThread Handle for the current thread
|
||||
/// @param qwCurrentPc Program counter
|
||||
/// @param dwProcessor Current processor
|
||||
/// @param strArgs Command line arguments
|
||||
/// @return None
|
||||
extern "C" __declspec(dllexport) VOID __stdcall help(
|
||||
_In_ HANDLE hCurrentProcess,
|
||||
_In_ HANDLE hCurrentThread,
|
||||
_In_ QWORD qwCurrentPc,
|
||||
_In_ DWORD dwProcessor,
|
||||
_In_z_ PCSTR strArgs
|
||||
);
|
||||
|
||||
#pragma endregion
|
||||
@@ -0,0 +1,89 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{4321ea53-183e-4104-887d-5cbfc14e4211}</ProjectGuid>
|
||||
<RootNamespace>PagingDbgExt</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>.\Bin\x64\</OutDir>
|
||||
<IntDir>.\Temp\x64\</IntDir>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
<RunCodeAnalysis>true</RunCodeAnalysis>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>false</OmitFramePointers>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<SuppressStartupBanner>false</SuppressStartupBanner>
|
||||
<AdditionalOptions>%(AdditionalOptions) /homeparams</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Native</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
<AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalOptions>/EMITPOGOPHASEINFO /NOVCFEATURE /NOCOFFGRPINFO /FILEALIGN:0x200 /PDBALTPATH:$(ProjectName).pdb /Brepro /RELEASE /EMITTOOLVERSIONINFO:NO /NOIMPLIB /NOEXP %(AdditionalOptions)</AdditionalOptions>
|
||||
<ShowProgress>LinkVerbose</ShowProgress>
|
||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Inc\BaseDataTypes.h" />
|
||||
<ClInclude Include="Inc\Common.h" />
|
||||
<ClInclude Include="Inc\DbgExt.h" />
|
||||
<ClInclude Include="Inc\GetKernelDirectoryTableBase.h" />
|
||||
<ClInclude Include="Inc\Help.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Src\DbgExt.cpp" />
|
||||
<ClCompile Include="Src\DllMain.cpp" />
|
||||
<ClCompile Include="Src\GetKernelDirectoryTableBase.cpp" />
|
||||
<ClCompile Include="Src\Help.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Inc\BaseDataTypes.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Inc\Common.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Inc\DbgExt.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Inc\GetKernelDirectoryTableBase.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Inc\Help.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Src\DbgExt.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\GetKernelDirectoryTableBase.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\DllMain.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\Help.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
||||
@@ -0,0 +1,137 @@
|
||||
# EVENSTAR - PagingDbgExt
|
||||
|
||||
## Version
|
||||
- `v10.0.6`
|
||||
|
||||
## Brief
|
||||
- `ISA: x86`
|
||||
- `Mode: Long`
|
||||
- `Bitness: 64-bit`
|
||||
- `CPL: 3`
|
||||
- `OS: Windows`
|
||||
- `Language: C`
|
||||
- _WdbgExts_ "old style" debugger extension `DLL` that contains various experiments around `IA-32e Paging`
|
||||
|
||||
## Usage
|
||||
- Set up kernel-mode debugging of the target
|
||||
```shell
|
||||
0: kd> vertarget
|
||||
Windows 10 Kernel Version 22000 MP (2 procs) Free x64
|
||||
Product: WinNt, suite: TerminalServer SingleUserTS
|
||||
Edition build lab: 22000.1.amd64fre.co_release.210604-1628
|
||||
Kernel base = 0xfffff804`4b40f000 PsLoadedModuleList = 0xfffff804`4c038b90
|
||||
Debug session time: Sun May 18 13:37:25.707 2025 (UTC - 4:00)
|
||||
System Uptime: 0 days 3:28:02.923
|
||||
|
||||
0: kd> .load PagingDbgExt.dll
|
||||
|
||||
0: kd> .chain
|
||||
--snip--
|
||||
Extension DLL chain:
|
||||
PagingDbgExt: API 10.0.6,
|
||||
[path: C:\Users\winterknife\Desktop\Tools\WinDbgExtensions\PagingDbgExt.dll]
|
||||
--snip--
|
||||
|
||||
0: kd> .extmatch /D /e PagingDbgExt *
|
||||
!PagingDbgExt.get_kernel_dtb
|
||||
!PagingDbgExt.help
|
||||
|
||||
0: kd> !PagingDbgExt.help
|
||||
Help for debugger extension DLL PagingDbgExt.dll
|
||||
help - Show help menu
|
||||
get_kernel_dtb - Find the kernel's DTB (DirectoryTableBase) which is the physical address of the base of the paging-structure hierarchy for KVAS contained in CR3 from the Low Stub
|
||||
|
||||
0: kd> !PagingDbgExt.get_kernel_dtb
|
||||
[+] nt!_PROCESSOR_START_BLOCK structure found at PA=0x13000
|
||||
[+] HAL Heap base KVA=0xFFFFF7F000000000
|
||||
[+] nt!_PROCESSOR_START_BLOCK.ProcessorState.SpecialRegisters.Cr3=0x1AE000
|
||||
|
||||
0: kd> ? poi(nt!HalpLowStubPhysicalAddress)
|
||||
Evaluate expression: 77824 = 00000000`00013000
|
||||
|
||||
0: kd> ? poi(nt!HalpOriginalHeapStart)
|
||||
Evaluate expression: -8864812498944 = fffff7f0`00000000
|
||||
|
||||
0: kd> r @cr3
|
||||
cr3=00000000001ae000
|
||||
|
||||
0: kd> !process 4 0
|
||||
Searching for Process with Cid == 4
|
||||
PROCESS ffffce849b2f1040
|
||||
SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000
|
||||
DirBase: 001ae000 ObjectTable: ffffaa0c84203dc0 HandleCount: 1818.
|
||||
Image: System
|
||||
|
||||
0: kd> dt nt!_KPROCESS ffffce849b2f1040 DirectoryTableBase
|
||||
+0x028 DirectoryTableBase : 0x1ae000
|
||||
|
||||
0: kd> dt /p nt!_KPROCESSOR_STATE 0x13090 SpecialRegisters.Cr3
|
||||
+0x000 SpecialRegisters :
|
||||
+0x010 Cr3 : 0x1ae000
|
||||
|
||||
0: kd> !db 0x13000
|
||||
# 13000 e9 4d 06 00 01 00 00 00-01 00 00 00 3f 00 18 30 .M..........?..0
|
||||
# 13010 01 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
|
||||
# 13020 00 00 00 00 00 00 00 00-00 00 00 00 00 9b 20 00 .............. .
|
||||
# 13030 00 00 00 00 00 00 00 00-ff ff 00 00 00 93 cf 00 ................
|
||||
# 13040 00 00 00 00 00 00 00 00-ff ff 00 00 00 9b cf 00 ................
|
||||
# 13050 00 00 00 00 00 00 00 00-00 20 af 7a 00 00 00 00 ......... .z....
|
||||
# 13060 79 36 01 00 30 00 d7 36-01 00 10 00 00 00 00 00 y6..0..6........
|
||||
# 13070 70 18 82 4b 04 f8 ff ff-00 c0 00 00 f0 f7 ff ff p..K............
|
||||
|
||||
0: kd> db poi(nt!HalpLowStub)
|
||||
fffff7f0`0000c000 e9 4d 06 00 01 00 00 00-01 00 00 00 3f 00 18 30 .M..........?..0
|
||||
fffff7f0`0000c010 01 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
|
||||
fffff7f0`0000c020 00 00 00 00 00 00 00 00-00 00 00 00 00 9b 20 00 .............. .
|
||||
fffff7f0`0000c030 00 00 00 00 00 00 00 00-ff ff 00 00 00 93 cf 00 ................
|
||||
fffff7f0`0000c040 00 00 00 00 00 00 00 00-ff ff 00 00 00 9b cf 00 ................
|
||||
fffff7f0`0000c050 00 00 00 00 00 00 00 00-00 20 af 7a 00 00 00 00 ......... .z....
|
||||
fffff7f0`0000c060 79 36 01 00 30 00 d7 36-01 00 10 00 00 00 00 00 y6..0..6........
|
||||
fffff7f0`0000c070 70 18 82 4b 04 f8 ff ff-00 c0 00 00 f0 f7 ff ff p..K............
|
||||
|
||||
0: kd> dps poi(nt!HalpLowStub) L10
|
||||
fffff7f0`0000c000 00000001`00064de9
|
||||
fffff7f0`0000c008 3018003f`00000001
|
||||
fffff7f0`0000c010 00000000`00000001
|
||||
fffff7f0`0000c018 00000000`00000000
|
||||
fffff7f0`0000c020 00000000`00000000
|
||||
fffff7f0`0000c028 00209b00`00000000
|
||||
fffff7f0`0000c030 00000000`00000000
|
||||
fffff7f0`0000c038 00cf9300`0000ffff
|
||||
fffff7f0`0000c040 00000000`00000000
|
||||
fffff7f0`0000c048 00cf9b00`0000ffff
|
||||
fffff7f0`0000c050 00000000`00000000
|
||||
fffff7f0`0000c058 00000000`7aaf2000
|
||||
fffff7f0`0000c060 36d70030`00013679
|
||||
fffff7f0`0000c068 00000000`00100001
|
||||
fffff7f0`0000c070 fffff804`4b821870 nt!HalpLMStub
|
||||
fffff7f0`0000c078 fffff7f0`0000c000
|
||||
|
||||
0: kd> !pte poi(nt!HalpLowStub)
|
||||
VA fffff7f00000c000
|
||||
PXE at FFFFBA5D2E974F78 PPE at FFFFBA5D2E9EFE00 PDE at FFFFBA5D3DFC0000 PTE at FFFFBA7BF8000060
|
||||
contains 0000000002182063 contains 8000000002185063 contains 8000000002186063 contains 8000000000013963
|
||||
pfn 2182 ---DA--KWEV pfn 2185 ---DA--KW-V pfn 2186 ---DA--KW-V pfn 13 -G-DA--KW-V
|
||||
|
||||
0: kd> !vtop 0x1ae000 0xfffff7f00000c000
|
||||
Amd64VtoP: Virt fffff7f00000c000, pagedir 00000000001ae000
|
||||
Amd64VtoP: PML4E 00000000001aef78
|
||||
Amd64VtoP: PDPE 0000000002182e00
|
||||
Amd64VtoP: PDE 0000000002185000
|
||||
Amd64VtoP: PTE 0000000002186060
|
||||
Amd64VtoP: Mapped phys 0000000000013000
|
||||
Virtual address fffff7f00000c000 translates to physical address 13000.
|
||||
|
||||
0: kd> .unload PagingDbgExt.dll
|
||||
Unloading PagingDbgExt extension DLL
|
||||
```
|
||||
|
||||
## Tested OS Versions
|
||||
- `Windows 11 21H2 Build 22000 Revision 675 64-bit`
|
||||
|
||||
## References
|
||||
1. [Getting Physical with USB Type-C: Windows 10 RAM Forensics and UEFI Attacks - Alex Ionescu](http://publications.alex-ionescu.com/Recon/ReconBru%202017%20-%20Getting%20Physical%20with%20USB%20Type-C,%20Windows%2010%20RAM%20Forensics%20and%20UEFI%20Attacks.pdf)
|
||||
2. [VmmWinInit_DTB_FindValidate_X64_LowStub](https://github.com/ufrisk/MemProcFS/blob/master/vmm/vmmwininit.c#L801)
|
||||
3. [find_low_stub](https://github.com/chompie1337/SMBGhost_RCE_PoC/blob/master/exploit.py#L396)
|
||||
4. [DriverInitPageTableBase](https://github.com/Cr4sh/KernelForge/blob/master/kforge_driver/kforge_driver.cpp#L60)
|
||||
5. [WinIoQueryPML4Value](https://github.com/hfiref0x/WinObjEx64/blob/master/Source/WinObjEx64/drivers/winio.c#L188)
|
||||
@@ -0,0 +1,61 @@
|
||||
// ========================================================================
|
||||
// File: DbgExt.cpp
|
||||
//
|
||||
// Author: winterknife
|
||||
//
|
||||
// Description: Source file that contains the basic template for a
|
||||
// WdbgExts extension DLL
|
||||
//
|
||||
// Modifications:
|
||||
// 2024-10-08 Created
|
||||
// 2024-10-08 Updated
|
||||
// ========================================================================
|
||||
|
||||
// ========================================================================
|
||||
// Includes
|
||||
// ========================================================================
|
||||
|
||||
#include "../Inc/DbgExt.h"
|
||||
|
||||
// ========================================================================
|
||||
// Globals
|
||||
// ========================================================================
|
||||
|
||||
#pragma region GLOBALS
|
||||
|
||||
EXT_API_VERSION ApiVersion = { (VER_PRODUCTVERSION_W >> 8), (VER_PRODUCTVERSION_W & 0xff), EXT_API_VERSION_NUMBER64, 0 };
|
||||
WINDBG_EXTENSION_APIS ExtensionApis;
|
||||
DWORD SavedMajorVersion;
|
||||
DWORD SavedMinorVersion;
|
||||
|
||||
#pragma endregion
|
||||
|
||||
// ========================================================================
|
||||
// Routines
|
||||
// ========================================================================
|
||||
|
||||
#pragma region ROUTINES
|
||||
|
||||
VOID __stdcall WinDbgExtensionDllInit(
|
||||
_In_ PWINDBG_EXTENSION_APIS pWindbgExtensionApis,
|
||||
_In_ WORD woMajorVersion,
|
||||
_In_ WORD woMinorVersion
|
||||
) {
|
||||
ExtensionApis = *pWindbgExtensionApis;
|
||||
SavedMajorVersion = woMajorVersion;
|
||||
SavedMinorVersion = woMinorVersion;
|
||||
}
|
||||
|
||||
LPEXT_API_VERSION __stdcall ExtensionApiVersion(
|
||||
VOID
|
||||
) {
|
||||
return &ApiVersion;
|
||||
}
|
||||
|
||||
VOID __stdcall CheckVersion(
|
||||
VOID
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
@@ -0,0 +1,57 @@
|
||||
// ========================================================================
|
||||
// File: DllMain.cpp
|
||||
//
|
||||
// Author: winterknife
|
||||
//
|
||||
// Description: Source file that contains the DLL entry point
|
||||
//
|
||||
// Modifications:
|
||||
// 2024-10-08 Created
|
||||
// 2024-10-08 Updated
|
||||
// ========================================================================
|
||||
|
||||
// ========================================================================
|
||||
// Includes
|
||||
// ========================================================================
|
||||
|
||||
#include "../Inc/Common.h"
|
||||
|
||||
// ========================================================================
|
||||
// Routines
|
||||
// ========================================================================
|
||||
|
||||
#pragma region ROUTINES
|
||||
|
||||
#pragma CODE_BEGIN
|
||||
/// @brief DLL entry point
|
||||
/// @param hModule A handle to the DLL module
|
||||
/// @param dwReason The reason code that indicates why the DLL entry-point function is being called
|
||||
/// @param dwReserved Reserved
|
||||
/// @return TRUE if DLL initialization succeeds or FALSE if it fails
|
||||
extern "C" __declspec(noinline) BOOLEAN __stdcall DllInit(
|
||||
_In_ HMODULE hModule,
|
||||
_In_ DWORD dwReason,
|
||||
_In_opt_ DWORD dwReserved
|
||||
) {
|
||||
UNREFERENCED_PARAMETER(hModule);
|
||||
UNREFERENCED_PARAMETER(dwReserved);
|
||||
|
||||
switch (dwReason) {
|
||||
case DLL_THREAD_ATTACH:
|
||||
break;
|
||||
|
||||
case DLL_THREAD_DETACH:
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_ATTACH:
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#pragma CODE_END
|
||||
|
||||
#pragma endregion
|
||||
@@ -0,0 +1,135 @@
|
||||
// ========================================================================
|
||||
// File: GetKernelDirectoryTableBase.cpp
|
||||
//
|
||||
// Author: winterknife
|
||||
//
|
||||
// Description: Source file that contains the necessary routines to find the
|
||||
// kernel's DirectoryTableBase using an arbitrary physical memory read primitive
|
||||
// to locate the Low Stub with heuristic scanning
|
||||
//
|
||||
// Modifications:
|
||||
// 2025-05-13 Created
|
||||
// 2025-05-18 Updated
|
||||
// ========================================================================
|
||||
|
||||
// ========================================================================
|
||||
// Includes
|
||||
// ========================================================================
|
||||
|
||||
#include "../Inc/GetKernelDirectoryTableBase.h"
|
||||
#include "../Inc/DbgExt.h"
|
||||
|
||||
// ========================================================================
|
||||
// Routines
|
||||
// ========================================================================
|
||||
|
||||
#pragma region ROUTINES
|
||||
|
||||
_Use_decl_annotations_
|
||||
VOID __stdcall get_kernel_dtb(
|
||||
HANDLE hCurrentProcess,
|
||||
HANDLE hCurrentThread,
|
||||
QWORD qwCurrentPc,
|
||||
DWORD dwProcessor,
|
||||
PCSTR strArgs
|
||||
) {
|
||||
UNREFERENCED_PARAMETER(hCurrentProcess);
|
||||
UNREFERENCED_PARAMETER(hCurrentThread);
|
||||
UNREFERENCED_PARAMETER(qwCurrentPc);
|
||||
UNREFERENCED_PARAMETER(dwProcessor);
|
||||
UNREFERENCED_PARAMETER(strArgs);
|
||||
|
||||
// Init local variables
|
||||
PVOID pBuffer = NULL;
|
||||
DWORD dwActiveProcessorCount = 0;
|
||||
QWORD qwPhysicalAddress = 0;
|
||||
DWORD dwBytesRead = 0;
|
||||
PPROCESSOR_START_BLOCK pProcessorStartBlock = NULL;
|
||||
QWORD qwKernelDirectoryTableBase = 0;
|
||||
|
||||
// Determine if the target uses 64-bit pointers
|
||||
if (!IsPtr64()) {
|
||||
dprintf("[-] IA-32 target is not supported by this extension!\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Allocate 0x1000 (PAGE_SIZE_4KB) bytes worth of heap memory to read the Low Stub
|
||||
pBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 0x1000);
|
||||
if (pBuffer == NULL) {
|
||||
dprintf("[-] Error allocating heap memory!\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// This technique of finding the Low Stub doesn't work if the number of Application Processors (APs) == 1
|
||||
// This happens because the nt!_PROCESSOR_START_BLOCK structure is filled incorrectly in this case
|
||||
// Get nt!_KUSER_SHARED_DATA.ActiveProcessorCount
|
||||
if (!ReadMemory((KUSER_SHARED_DATA_RO_MAPPING_X64_KVA + ACTIVEPROCESSORCOUNT_OFFSET), &dwActiveProcessorCount, 0x04, NULL)) {
|
||||
dprintf("[-] Error reading virtual memory!\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Check nt!_KUSER_SHARED_DATA.ActiveProcessorCount
|
||||
if (dwActiveProcessorCount < 2) {
|
||||
dprintf("[-] This technique does not work for UniProcessor (UP) systems!\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Locate the Low Stub with heuristic scanning
|
||||
// The Low Stub is always present on x86 APIC systems in one of the physical pages in the range starting at 0x1000 (4 KB) and less than 0x100000 (1 MB)
|
||||
// It is a piece of 16-bit code that aids in CPU mode transitions (Real Mode to Protected Mode to Long Mode) on boot or waking up from S2 and S3 sleeps
|
||||
// nt!HalpLowStub contains the KVA of nt!_PROCESSOR_START_BLOCK structure
|
||||
// nt!HalpLowStubPhysicalAddress contains the PA of nt!_PROCESSOR_START_BLOCK structure
|
||||
for (qwPhysicalAddress = 0x1000; qwPhysicalAddress < 0x100000; qwPhysicalAddress += 0x1000) {
|
||||
ReadPhysical(qwPhysicalAddress, pBuffer, 0x1000, &dwBytesRead);
|
||||
if (dwBytesRead != 0x1000) {
|
||||
dprintf("[-] Error reading physical memory!\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Low Stub is the nt!_PROCESSOR_START_BLOCK structure
|
||||
pProcessorStartBlock = (PPROCESSOR_START_BLOCK)pBuffer;
|
||||
|
||||
// nt!_PROCESSOR_START_BLOCK structure starts with the following bytes decoded as the JMP rel16 instruction:
|
||||
// E9 4D 06 jmp 0x650
|
||||
// This piece of 16-bit x86 code jumps to the end of the nt!_PROCESSOR_START_BLOCK structure
|
||||
// The size of this structure is 0x650/0n1616 bytes starting from Windows 10 1703 Creators Update (RS2) Build 15063
|
||||
if (pProcessorStartBlock->Jmp.OpCode != 0xE9)
|
||||
continue;
|
||||
|
||||
if (pProcessorStartBlock->Jmp.Offset != 0x06)
|
||||
continue;
|
||||
|
||||
// nt!_PROCESSOR_START_BLOCK.CompletionFlag should be set when the Application Processor (AP) has been initialized
|
||||
if (pProcessorStartBlock->CompletionFlag != 1)
|
||||
continue;
|
||||
|
||||
// nt!_PROCESSOR_START_BLOCK.LmTarget should point to nt!HalpLMStub
|
||||
if (pProcessorStartBlock->LmTarget == 0)
|
||||
continue;
|
||||
|
||||
// nt!_PROCESSOR_START_BLOCK.ProcessorState.SpecialRegisters.Cr3 should not be zero
|
||||
if (pProcessorStartBlock->ProcessorState.SpecialRegisters.Cr3 == 0)
|
||||
continue;
|
||||
|
||||
// Found!
|
||||
dprintf("[+] nt!_PROCESSOR_START_BLOCK structure found at PA=0x%I64X\n", qwPhysicalAddress);
|
||||
|
||||
// Get the base address of the HAL Heap which is pointed to by nt!HalpOriginalHeapStart
|
||||
dprintf("[+] HAL Heap base KVA=0x%I64X\n", ((QWORD)(pProcessorStartBlock->SelfMap) & 0xFFFFFFFFF0000000));
|
||||
|
||||
// Get the physical address of the first table that is used in virtual address translation for KVAS contained in CR3
|
||||
qwKernelDirectoryTableBase = pProcessorStartBlock->ProcessorState.SpecialRegisters.Cr3;
|
||||
dprintf("[+] nt!_PROCESSOR_START_BLOCK.ProcessorState.SpecialRegisters.Cr3=0x%I64X\n", qwKernelDirectoryTableBase);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
cleanup:
|
||||
if (pBuffer)
|
||||
HeapFree(GetProcessHeap(), 0, pBuffer);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
@@ -0,0 +1,48 @@
|
||||
// ========================================================================
|
||||
// File: Help.cpp
|
||||
//
|
||||
// Author: winterknife
|
||||
//
|
||||
// Description: Source file that contains the implementation of the built-in
|
||||
// help command for the debugger extension DLL
|
||||
//
|
||||
// Modifications:
|
||||
// 2025-05-14 Created
|
||||
// 2025-05-18 Updated
|
||||
// ========================================================================
|
||||
|
||||
// ========================================================================
|
||||
// Includes
|
||||
// ========================================================================
|
||||
|
||||
#include "../Inc/Help.h"
|
||||
#include "../Inc/DbgExt.h"
|
||||
|
||||
// ========================================================================
|
||||
// Routines
|
||||
// ========================================================================
|
||||
|
||||
#pragma region ROUTINES
|
||||
|
||||
_Use_decl_annotations_
|
||||
VOID __stdcall help(
|
||||
HANDLE hCurrentProcess,
|
||||
HANDLE hCurrentThread,
|
||||
QWORD qwCurrentPc,
|
||||
DWORD dwProcessor,
|
||||
PCSTR strArgs
|
||||
) {
|
||||
UNREFERENCED_PARAMETER(hCurrentProcess);
|
||||
UNREFERENCED_PARAMETER(hCurrentThread);
|
||||
UNREFERENCED_PARAMETER(qwCurrentPc);
|
||||
UNREFERENCED_PARAMETER(dwProcessor);
|
||||
UNREFERENCED_PARAMETER(strArgs);
|
||||
|
||||
dprintf(
|
||||
"Help for debugger extension DLL PagingDbgExt.dll\n"
|
||||
" help - Show help menu\n"
|
||||
" get_kernel_dtb - Find the kernel's DTB (DirectoryTableBase) which is the physical address of the base of the paging-structure hierarchy for KVAS contained in CR3 from the Low Stub\n"
|
||||
);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
Reference in New Issue
Block a user