diff --git a/Source/Shared/ntos/ntbuilds.h b/Source/Shared/ntos/ntbuilds.h index 4af6980..4a7ddd2 100644 --- a/Source/Shared/ntos/ntbuilds.h +++ b/Source/Shared/ntos/ntbuilds.h @@ -4,9 +4,9 @@ * * TITLE: NTBUILDS.H * -* VERSION: 1.29 +* VERSION: 1.30 * -* DATE: 21 May 2026 +* DATE: 31 Jul 2026 * * Windows NT builds definition file. * @@ -22,6 +22,41 @@ // Defines for Major Windows NT release builds // +// +// Archeology part START +// + +// Windows NT 3.51 +#define NT_WIN_NT351 1057 + +// Windows NT 4.0 +#define NT_WIN_NT4 1381 + +// Windows 2000 +#define NT_WIN_2K 2195 + +// Windows XP +#define NT_WIN_XP 2600 + +// Windows XP 64 uses same build as server +#define NT_WIN_XP_64 3790 + +// Windows 2003 (RTM/SP1) +#define NT_WINSRV_2003 3790 + +// +// Archeology part END +// + +// Windows Vista RTM +#define NT_WIN_VISTA_RTM 6000 + +// Windows Vista SP1 +#define NT_WIN_VISTA_SP1 6001 + +// Windows Vista SP2 +#define NT_WIN_VISTA_SP2 6002 + // Windows 7 RTM #define NT_WIN7_RTM 7600 diff --git a/Source/Shared/ntos/ntos.h b/Source/Shared/ntos/ntos.h index ec050c5..f2ad8b4 100644 --- a/Source/Shared/ntos/ntos.h +++ b/Source/Shared/ntos/ntos.h @@ -5,9 +5,9 @@ * * TITLE: NTOS.H * -* VERSION: 1.247 +* VERSION: 1.252 * -* DATE: 12 Jul 2026 +* DATE: 12 Aug 2026 * * Common header file for the ntos API functions and definitions. * @@ -512,6 +512,11 @@ char _RTL_CONSTANT_STRING_type_check(const void *s); #define MAX_USTRING ( sizeof(WCHAR) * (MAXUSHORT/sizeof(WCHAR)) ) #endif +#ifndef __PCSID_DEFINED__ +#define __PCSID_DEFINED__ +typedef const SID* PCSID; +#endif /* __PCSID_DEFINED__ */ + typedef struct _EX_RUNDOWN_REF { union { @@ -754,8 +759,46 @@ typedef struct _VM_COUNTERS { SIZE_T QuotaNonPagedPoolUsage; SIZE_T PagefileUsage; SIZE_T PeakPagefileUsage; - SIZE_T PrivatePageCount; -} VM_COUNTERS; +} VM_COUNTERS, *PVM_COUNTERS; + +typedef struct _VM_COUNTERS_EX { + SIZE_T PeakVirtualSize; + SIZE_T VirtualSize; + ULONG PageFaultCount; + SIZE_T PeakWorkingSetSize; + SIZE_T WorkingSetSize; + SIZE_T QuotaPeakPagedPoolUsage; + SIZE_T QuotaPagedPoolUsage; + SIZE_T QuotaPeakNonPagedPoolUsage; + SIZE_T QuotaNonPagedPoolUsage; + SIZE_T PagefileUsage; + SIZE_T PeakPagefileUsage; + SIZE_T PrivateUsage; +} VM_COUNTERS_EX, * PVM_COUNTERS_EX; + +typedef struct _VM_COUNTERS_EX2 { + union + { + VM_COUNTERS_EX CountersEx; + struct + { + SIZE_T PeakVirtualSize; + SIZE_T VirtualSize; + ULONG PageFaultCount; + SIZE_T PeakWorkingSetSize; + SIZE_T WorkingSetSize; + SIZE_T QuotaPeakPagedPoolUsage; + SIZE_T QuotaPagedPoolUsage; + SIZE_T QuotaPeakNonPagedPoolUsage; + SIZE_T QuotaNonPagedPoolUsage; + SIZE_T PagefileUsage; + SIZE_T PeakPagefileUsage; + SIZE_T PrivateUsage; + }; + }; + SIZE_T PrivateWorkingSetSize; + SIZE_T SharedCommitUsage; +} VM_COUNTERS_EX2, * PVM_COUNTERS_EX2; typedef struct _SYSTEM_THREAD_INFORMATION { LARGE_INTEGER KernelTime; @@ -799,8 +842,24 @@ typedef struct _SYSTEM_PROCESS_INFORMATION { ULONG HandleCount; ULONG SessionId; ULONG_PTR UniqueProcessKey; - VM_COUNTERS VmCounters; - IO_COUNTERS IoCounters; + SIZE_T PeakVirtualSize; + SIZE_T VirtualSize; + ULONG PageFaultCount; + SIZE_T PeakWorkingSetSize; + SIZE_T WorkingSetSize; + SIZE_T QuotaPeakPagedPoolUsage; + SIZE_T QuotaPagedPoolUsage; + SIZE_T QuotaPeakNonPagedPoolUsage; + SIZE_T QuotaNonPagedPoolUsage; + SIZE_T PagefileUsage; + SIZE_T PeakPagefileUsage; + SIZE_T PrivatePageCount; + LARGE_INTEGER ReadOperationCount; + LARGE_INTEGER WriteOperationCount; + LARGE_INTEGER OtherOperationCount; + LARGE_INTEGER ReadTransferCount; + LARGE_INTEGER WriteTransferCount; + LARGE_INTEGER OtherTransferCount; SYSTEM_THREAD_INFORMATION Threads[1]; //not a part of this structure } SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION; @@ -922,6 +981,91 @@ typedef struct _SYSTEM_BASIC_INFORMATION { CCHAR NumberOfProcessors; } SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION; +typedef struct _SYSTEM_PERFORMANCE_INFORMATION { + LARGE_INTEGER IdleProcessTime; + LARGE_INTEGER IoReadTransferCount; + LARGE_INTEGER IoWriteTransferCount; + LARGE_INTEGER IoOtherTransferCount; + ULONG IoReadOperationCount; + ULONG IoWriteOperationCount; + ULONG IoOtherOperationCount; + ULONG AvailablePages; + ULONG CommittedPages; + ULONG CommitLimit; + ULONG PeakCommitment; + ULONG PageFaultCount; + ULONG CopyOnWriteCount; + ULONG TransitionCount; + ULONG CacheTransitionCount; + ULONG DemandZeroCount; + ULONG PageReadCount; + ULONG PageReadIoCount; + ULONG CacheReadCount; + ULONG CacheIoCount; + ULONG DirtyPagesWriteCount; + ULONG DirtyWriteIoCount; + ULONG MappedPagesWriteCount; + ULONG MappedWriteIoCount; + ULONG PagedPoolPages; + ULONG NonPagedPoolPages; + ULONG PagedPoolAllocs; + ULONG PagedPoolFrees; + ULONG NonPagedPoolAllocs; + ULONG NonPagedPoolFrees; + ULONG FreeSystemPtes; + ULONG ResidentSystemCodePage; + ULONG TotalSystemDriverPages; + ULONG TotalSystemCodePages; + ULONG NonPagedPoolLookasideHits; + ULONG PagedPoolLookasideHits; + ULONG AvailablePagedPoolPages; + ULONG ResidentSystemCachePage; + ULONG ResidentPagedPoolPage; + ULONG ResidentSystemDriverPage; + ULONG CcFastReadNoWait; + ULONG CcFastReadWait; + ULONG CcFastReadResourceMiss; + ULONG CcFastReadNotPossible; + ULONG CcFastMdlReadNoWait; + ULONG CcFastMdlReadWait; + ULONG CcFastMdlReadResourceMiss; + ULONG CcFastMdlReadNotPossible; + ULONG CcMapDataNoWait; + ULONG CcMapDataWait; + ULONG CcMapDataNoWaitMiss; + ULONG CcMapDataWaitMiss; + ULONG CcPinMappedDataCount; + ULONG CcPinReadNoWait; + ULONG CcPinReadWait; + ULONG CcPinReadNoWaitMiss; + ULONG CcPinReadWaitMiss; + ULONG CcCopyReadNoWait; + ULONG CcCopyReadWait; + ULONG CcCopyReadNoWaitMiss; + ULONG CcCopyReadWaitMiss; + ULONG CcMdlReadNoWait; + ULONG CcMdlReadWait; + ULONG CcMdlReadNoWaitMiss; + ULONG CcMdlReadWaitMiss; + ULONG CcReadAheadIos; + ULONG CcLazyWriteIos; + ULONG CcLazyWritePages; + ULONG CcDataFlushes; + ULONG CcDataPages; + ULONG ContextSwitches; + ULONG FirstLevelTbFills; + ULONG SecondLevelTbFills; + ULONG SystemCalls; + ULONGLONG CcTotalDirtyPages; + ULONGLONG CcDirtyPageThreshold; + LONGLONG ResidentAvailablePages; + ULONGLONG SharedCommittedPages; + ULONGLONG MdlPagesAllocated; + ULONGLONG PfnDatabaseCommittedPages; + ULONGLONG SystemPageTableCommittedPages; + ULONGLONG ContiguousPagesAllocated; +} SYSTEM_PERFORMANCE_INFORMATION, * PSYSTEM_PERFORMANCE_INFORMATION; + typedef struct _SYSTEM_ISOLATED_USER_MODE_INFORMATION { BOOLEAN SecureKernelRunning : 1; BOOLEAN HvciEnabled : 1; @@ -938,7 +1082,8 @@ typedef struct _SYSTEM_ISOLATED_USER_MODE_INFORMATION { BOOLEAN HardwareEnforcedHvpt : 1; BOOLEAN HardwareHvptAvailable : 1; BOOLEAN SpareFlags2 : 1; - BOOLEAN Spare0[6]; + BOOLEAN EncryptionKeyTpmBound : 1; + BOOLEAN Spare0[5]; ULONGLONG Spare1; } SYSTEM_ISOLATED_USER_MODE_INFORMATION, *PSYSTEM_ISOLATED_USER_MODE_INFORMATION; @@ -1015,6 +1160,25 @@ typedef struct _SYSTEM_FIRMWARE_PARTITION_INFORMATION { UNICODE_STRING FirmwarePartition; // \Device\HarddiskX } SYSTEM_FIRMWARE_PARTITION_INFORMATION, * PSYSTEM_FIRMWARE_PARTITION_INFORMATION; +typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION { + LARGE_INTEGER IdleTime; + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER DpcTime; + LARGE_INTEGER InterruptTime; + ULONG InterruptCount; + ULONG Spare0; +} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, * PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION; + +_Struct_size_bytes_(NextEntryOffset) +typedef struct _SYSTEM_PAGEFILE_INFORMATION { + ULONG NextEntryOffset; + ULONG TotalSize; + ULONG TotalInUse; + ULONG PeakUsage; + UNICODE_STRING PageFileName; +} SYSTEM_PAGEFILE_INFORMATION, * PSYSTEM_PAGEFILE_INFORMATION; + typedef struct _RTL_PROCESS_BACKTRACE_INFORMATION { PCHAR SymbolicBackTrace; ULONG TraceCount; @@ -5784,6 +5948,7 @@ typedef enum _MEMORY_INFORMATION_CLASS { MemoryPhysicalContiguityInformation, MemoryBadInformation, MemoryBadInformationAllProcesses, + MemoryImageExtensionInformation, MaxMemoryInfoClass } MEMORY_INFORMATION_CLASS, *PMEMORY_INFORMATION_CLASS; @@ -5962,6 +6127,19 @@ typedef struct _MEMORY_WORKING_SET_EX_INFORMATION { } u1; } MEMORY_WORKING_SET_EX_INFORMATION, * PMEMORY_WORKING_SET_EX_INFORMATION; +typedef enum _MEMORY_IMAGE_EXTENSION_TYPE { + MemoryImageExtensionCfgScp, + MemoryImageExtensionCfgEmulatedScp, + MemoryImageExtensionTypeMax, +} MEMORY_IMAGE_EXTENSION_TYPE; + +typedef struct _MEMORY_IMAGE_EXTENSION_INFORMATION { + MEMORY_IMAGE_EXTENSION_TYPE ExtensionType; + ULONG Flags; + PVOID ExtensionImageBaseRva; + SIZE_T ExtensionSize; +} MEMORY_IMAGE_EXTENSION_INFORMATION, * PMEMORY_IMAGE_EXTENSION_INFORMATION; + #define MM_ZERO_ACCESS 0 // this value is not used. #define MM_READONLY 1 #define MM_EXECUTE 2 @@ -10641,6 +10819,8 @@ RtlWow64SetThreadContext( * ************************************************************************************/ +#define RtlProcessHeap() (NtCurrentPeb()->ProcessHeap) + typedef NTSTATUS(NTAPI * PRTL_HEAP_COMMIT_ROUTINE)( _In_ PVOID Base, _Inout_ PVOID *CommitAddress, @@ -10765,6 +10945,33 @@ RtlEnumProcessHeaps( _In_ PRTL_ENUM_HEAPS_ROUTINE EnumRoutine, _In_ PVOID Parameter); +NTSYSAPI +BOOLEAN +NTAPI +RtlValidateHeap( + _In_opt_ HANDLE HeapHandle, + _In_ ULONG Flags, + _In_opt_ PVOID BaseAddress); + +NTSYSAPI +SIZE_T +NTAPI +RtlCompactHeap( + _In_ HANDLE HeapHandle, + _In_ ULONG Flags); + +NTSYSAPI +BOOLEAN +NTAPI +RtlLockHeap( + _In_ HANDLE HeapHandle); + +NTSYSAPI +BOOLEAN +NTAPI +RtlUnlockHeap( + _In_ HANDLE HeapHandle); + /************************************************************************************ * * RTL Compression API. @@ -11074,6 +11281,132 @@ RtlCaptureStackBackTrace( _Out_writes_to_(FramesToCapture, return) PVOID* BackTrace, _Out_opt_ PULONG BackTraceHash); +typedef struct _RTL_PROCESS_MODULES* PRTL_PROCESS_MODULES; +typedef struct _RTL_PROCESS_MODULE_INFORMATION_EX* PRTL_PROCESS_MODULE_INFORMATION_EX; +typedef struct _RTL_PROCESS_BACKTRACES* PRTL_PROCESS_BACKTRACES; +typedef struct _RTL_PROCESS_LOCKS* PRTL_PROCESS_LOCKS; + +typedef struct _RTL_PROCESS_VERIFIER_OPTIONS { + ULONG SizeStruct; + ULONG Option; + UCHAR OptionData[1]; +} RTL_PROCESS_VERIFIER_OPTIONS, * PRTL_PROCESS_VERIFIER_OPTIONS; + +typedef struct _RTL_DEBUG_INFORMATION { + HANDLE SectionHandleClient; + PVOID ViewBaseClient; + PVOID ViewBaseTarget; + ULONG_PTR ViewBaseDelta; + HANDLE EventPairClient; + HANDLE EventPairTarget; + HANDLE TargetProcessId; + HANDLE TargetThreadHandle; + ULONG Flags; + SIZE_T OffsetFree; + SIZE_T CommitSize; + SIZE_T ViewSize; + union + { + PRTL_PROCESS_MODULES Modules; + PRTL_PROCESS_MODULE_INFORMATION_EX ModulesEx; + }; + PRTL_PROCESS_BACKTRACES BackTraces; + PVOID Heaps; + PRTL_PROCESS_LOCKS Locks; + PVOID SpecificHeap; + HANDLE TargetProcessHandle; + PRTL_PROCESS_VERIFIER_OPTIONS VerifierOptions; + PVOID ProcessHeap; + HANDLE CriticalSectionHandle; + HANDLE CriticalSectionOwnerThread; + PVOID Reserved[4]; +} RTL_DEBUG_INFORMATION, * PRTL_DEBUG_INFORMATION; + +NTSYSAPI +PRTL_DEBUG_INFORMATION +NTAPI +RtlCreateQueryDebugBuffer( + _In_opt_ ULONG MaximumCommit, + _In_ BOOLEAN UseEventPair); + +NTSYSAPI +NTSTATUS +NTAPI +RtlDestroyQueryDebugBuffer( + _In_ PRTL_DEBUG_INFORMATION Buffer); + +#define RTL_QUERY_PROCESS_MODULES 0x00000001 +#define RTL_QUERY_PROCESS_BACKTRACES 0x00000002 +#define RTL_QUERY_PROCESS_HEAP_SUMMARY 0x00000004 +#define RTL_QUERY_PROCESS_HEAP_TAGS 0x00000008 +#define RTL_QUERY_PROCESS_HEAP_ENTRIES 0x00000010 +#define RTL_QUERY_PROCESS_LOCKS 0x00000020 +#define RTL_QUERY_PROCESS_MODULES32 0x00000040 +#define RTL_QUERY_PROCESS_VERIFIER_OPTIONS 0x00000080 +#define RTL_QUERY_PROCESS_MODULESEX 0x00000100 +#define RTL_QUERY_PROCESS_HEAP_SEGMENTS 0x00000200 +#define RTL_QUERY_PROCESS_CS_OWNER 0x00000400 +#define RTL_QUERY_PROCESS_USE_CURRENT_PROCESS 0x40000000 +#define RTL_QUERY_PROCESS_NONINVASIVE 0x80000000 +#define RTL_QUERY_PROCESS_NONINVASIVE_CS_OWNER 0x80000800 + +NTSYSAPI +NTSTATUS +NTAPI +RtlQueryProcessDebugInformation( + _In_ HANDLE UniqueProcessId, + _In_ ULONG Flags, + _Inout_ PRTL_DEBUG_INFORMATION Buffer); + +// Windows 7/8/10 +typedef struct _RTL_HEAP_INFORMATION_V1 { + PVOID BaseAddress; + ULONG Flags; + USHORT EntryOverhead; + USHORT CreatorBackTraceIndex; + SIZE_T BytesAllocated; + SIZE_T BytesCommitted; + ULONG NumberOfTags; + ULONG NumberOfEntries; + ULONG NumberOfPseudoTags; + ULONG PseudoTagGranularity; + ULONG Reserved[5]; + PVOID Tags; + PVOID Entries; +} RTL_HEAP_INFORMATION_V1, * PRTL_HEAP_INFORMATION_V1; + +// Windows 11 > 22000 +typedef struct _RTL_HEAP_INFORMATION_V2 { + PVOID BaseAddress; + ULONG Flags; + USHORT EntryOverhead; + USHORT CreatorBackTraceIndex; + SIZE_T BytesAllocated; + SIZE_T BytesCommitted; + ULONG NumberOfTags; + ULONG NumberOfEntries; + ULONG NumberOfPseudoTags; + ULONG PseudoTagGranularity; + ULONG Reserved[5]; + PVOID Tags; + PVOID Entries; + ULONG64 HeapTag; +} RTL_HEAP_INFORMATION_V2, * PRTL_HEAP_INFORMATION_V2; + +#define RTL_HEAP_SIGNATURE 0xFFEEFFEEUL +#define RTL_HEAP_SEGMENT_SIGNATURE 0xDDEEDDEEUL + +typedef struct _RTL_PROCESS_HEAPS_V1 { + ULONG NumberOfHeaps; + _Field_size_(NumberOfHeaps) RTL_HEAP_INFORMATION_V1 Heaps[1]; +} RTL_PROCESS_HEAPS_V1, * PRTL_PROCESS_HEAPS_V1; + +typedef struct _RTL_PROCESS_HEAPS_V2 { + ULONG NumberOfHeaps; + _Field_size_(NumberOfHeaps) RTL_HEAP_INFORMATION_V2 Heaps[1]; +} RTL_PROCESS_HEAPS_V2, * PRTL_PROCESS_HEAPS_V2; + + /************************************************************************************ * * RTL AVL Tree API. @@ -11485,6 +11818,123 @@ RtlSetIoCompletionCallback( _In_ APC_CALLBACK_FUNCTION CompletionProc, _In_ ULONG Flags); +/************************************************************************************ +* +* RTL WNF (Windows Notification Facility support. +* +************************************************************************************/ + +#define WNF_STATE_KEY 0x41C64E6DA3BC0074 + +typedef ULONG WNF_CHANGE_STAMP, * PWNF_CHANGE_STAMP; + +typedef enum _WNF_STATE_NAME_INFORMATION { + WnfInfoStateNameExist, + WnfInfoSubscribersPresent, + WnfInfoIsQuiescent +} WNF_STATE_NAME_INFORMATION; + +typedef struct _WNF_STATE_NAME { + union + { + ULONGLONG Value; + ULONG Data[2]; + struct + { + ULONG64 Version : 4; + ULONG64 NameLifetime : 2; + ULONG64 DataScope : 4; + ULONG64 PermanentData : 1; + ULONG64 Unique : 53; + }; + }; +} WNF_STATE_NAME, * PWNF_STATE_NAME; +typedef const WNF_STATE_NAME* PCWNF_STATE_NAME; + +typedef enum _WNF_STATE_NAME_LIFETIME { + WnfWellKnownStateName, + WnfPermanentStateName, + WnfPersistentStateName, + WnfTemporaryStateName +} WNF_STATE_NAME_LIFETIME; + +typedef enum _WNF_DATA_SCOPE { + WnfDataScopeSystem, + WnfDataScopeSession, + WnfDataScopeUser, + WnfDataScopeProcess, + WnfDataScopeMachine, + WnfDataScopePhysicalMachine, +} WNF_DATA_SCOPE; + +typedef struct _WNF_TYPE_ID { + GUID TypeId; +} WNF_TYPE_ID, * PWNF_TYPE_ID; +typedef const WNF_TYPE_ID* PCWNF_TYPE_ID; + +_Must_inspect_result_ +NTSYSAPI +BOOLEAN +NTAPI +RtlEqualWnfChangeStamps( + _In_ WNF_CHANGE_STAMP ChangeStamp1, + _In_ WNF_CHANGE_STAMP ChangeStamp2); + +_Always_(_Post_satisfies_(return == STATUS_NO_MEMORY || return == STATUS_RETRY || return == STATUS_SUCCESS)) +typedef _Function_class_(WNF_USER_CALLBACK) +NTSTATUS NTAPI WNF_USER_CALLBACK( + _In_ WNF_STATE_NAME StateName, + _In_ WNF_CHANGE_STAMP ChangeStamp, + _In_opt_ PWNF_TYPE_ID TypeId, + _In_opt_ PVOID CallbackContext, + _In_reads_bytes_opt_(Length) const VOID* Buffer, + _In_ ULONG Length); + +typedef WNF_USER_CALLBACK* PWNF_USER_CALLBACK; + +NTSYSAPI +NTSTATUS +NTAPI +RtlQueryWnfStateData( + _Out_ PWNF_CHANGE_STAMP ChangeStamp, + _In_ WNF_STATE_NAME StateName, + _In_ PWNF_USER_CALLBACK Callback, + _In_opt_ PVOID CallbackContext, + _In_opt_ PWNF_TYPE_ID TypeId); + +NTSYSAPI +NTSTATUS +NTAPI +RtlPublishWnfStateData( + _In_ WNF_STATE_NAME StateName, + _In_opt_ PCWNF_TYPE_ID TypeId, + _In_reads_bytes_opt_(Length) const VOID * Buffer, + _In_opt_ ULONG Length, + _In_opt_ const VOID * ExplicitScope); + +typedef struct WNF_USER_SUBSCRIPTION* PWNF_USER_SUBSCRIPTION; + +#define WNF_CREATE_SERIALIZATION_GROUP_FLAG 0x00000001L + +NTSYSAPI +NTSTATUS +NTAPI +RtlSubscribeWnfStateChangeNotification( + _Out_ PWNF_USER_SUBSCRIPTION * SubscriptionHandle, + _In_ WNF_STATE_NAME StateName, + _In_ WNF_CHANGE_STAMP ChangeStamp, + _In_ PWNF_USER_CALLBACK Callback, + _In_opt_ PVOID CallbackContext, + _In_opt_ PCWNF_TYPE_ID TypeId, + _In_opt_ ULONG SerializationGroup, + _In_ ULONG Flags); + +NTSYSAPI +NTSTATUS +NTAPI +RtlUnsubscribeWnfStateChangeNotification( + _In_ PWNF_USER_SUBSCRIPTION SubscriptionHandle); + /************************************************************************************ * * RTL data exports. @@ -11509,13 +11959,39 @@ NTSYSAPI UNICODE_STRING RtlNtPathSeperatorString; * ************************************************************************************/ +#ifndef EVENT_DESCRIPTOR_DEF +#define EVENT_DESCRIPTOR_DEF +typedef struct _EVENT_DESCRIPTOR { + USHORT Id; + UCHAR Version; + UCHAR Channel; + UCHAR Level; + UCHAR Opcode; + USHORT Task; + ULONGLONG Keyword; +} EVENT_DESCRIPTOR, * PEVENT_DESCRIPTOR; +typedef const EVENT_DESCRIPTOR* PCEVENT_DESCRIPTOR; + +typedef enum _EVENT_INFO_CLASS { + EventProviderBinaryTrackInfo, + EventProviderSetReserved1, + EventProviderSetTraits, + EventProviderUseDescriptorType, + MaxEventInfo +} EVENT_INFO_CLASS; +#endif + +typedef struct _EVENT_FILTER_DESCRIPTOR* PEVENT_FILTER_DESCRIPTOR; +typedef struct _EVENT_DATA_DESCRIPTOR EVENT_DATA_DESCRIPTOR, * PEVENT_DATA_DESCRIPTOR; +typedef enum _EVENT_INFO_CLASS EVENT_INFO_CLASS; + typedef VOID(NTAPI *PETWENABLECALLBACK)( _In_ LPCGUID SourceId, _In_ ULONG IsEnabled, _In_ UCHAR Level, _In_ ULONGLONG MatchAnyKeyword, _In_ ULONGLONG MatchAllKeyword, - _In_opt_ /*EVENT_FILTER_DESCRIPTOR*/ PVOID FilterData, + _In_opt_ PEVENT_FILTER_DESCRIPTOR FilterData, _Inout_opt_ PVOID CallbackContext ); @@ -11528,15 +12004,29 @@ EtwEventRegister( _In_opt_ PVOID CallbackContext, _Out_ PREGHANDLE RegHandle); +NTSYSAPI +ULONG +NTAPI +EtwEventUnregister( + _In_ REGHANDLE RegHandle); + NTSYSAPI ULONG NTAPI EtwEventWriteNoRegistration( _In_ LPCGUID ProviderId, - _In_ /*PCEVENT_DESCRIPTOR*/ PVOID EventDescriptor, + _In_ PCEVENT_DESCRIPTOR EventDescriptor, _In_ ULONG UserDataCount, - _In_reads_opt_(UserDataCount) /*PEVENT_DATA_DESCRIPTOR*/PVOID UserData); + _In_reads_opt_(UserDataCount) PEVENT_DATA_DESCRIPTOR UserData); +NTSYSAPI +ULONG +NTAPI +EtwEventSetInformation( + _In_ REGHANDLE RegHandle, + _In_ EVENT_INFO_CLASS InformationClass, + _In_reads_bytes_(InformationLength) PVOID EventInformation, + _In_ ULONG InformationLength); /* ** Runtime Library API END @@ -12022,6 +12512,85 @@ NtReleaseSemaphore( _In_ LONG ReleaseCount, _Out_opt_ PLONG PreviousCount); +/************************************************************************************ +* +* WNF API. +* +************************************************************************************/ + +NTSYSAPI +NTSTATUS +NTAPI +NtCreateWnfStateName( + _Out_ PWNF_STATE_NAME StateName, + _In_ WNF_STATE_NAME_LIFETIME NameLifetime, + _In_ WNF_DATA_SCOPE DataScope, + _In_ BOOLEAN PersistData, + _In_opt_ PCWNF_TYPE_ID TypeId, + _In_ ULONG MaximumStateSize, + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor); + +NTSYSAPI +NTSTATUS +NTAPI +NtDeleteWnfStateName( + _In_ PCWNF_STATE_NAME StateName); + +NTSYSAPI +NTSTATUS +NTAPI +NtUpdateWnfStateData( + _In_ PCWNF_STATE_NAME StateName, + _In_reads_bytes_opt_(Length) const VOID* Buffer, + _In_opt_ ULONG Length, + _In_opt_ PCWNF_TYPE_ID TypeId, + _In_opt_ PCSID ExplicitScope, + _In_ WNF_CHANGE_STAMP MatchingChangeStamp, + _In_ LOGICAL CheckStamp); + +NTSYSAPI +NTSTATUS +NTAPI +NtDeleteWnfStateData( + _In_ PCWNF_STATE_NAME StateName, + _In_opt_ PCSID ExplicitScope); + +NTSYSAPI +NTSTATUS +NTAPI +NtQueryWnfStateData( + _In_ PCWNF_STATE_NAME StateName, + _In_opt_ PCWNF_TYPE_ID TypeId, + _In_opt_ PCSID ExplicitScope, + _Out_ PWNF_CHANGE_STAMP ChangeStamp, + _Out_writes_bytes_opt_(*BufferLength) PVOID Buffer, + _Inout_ PULONG BufferLength); + +NTSYSAPI +NTSTATUS +NTAPI +NtQueryWnfStateNameInformation( + _In_ PCWNF_STATE_NAME StateName, + _In_ WNF_STATE_NAME_INFORMATION NameInfoClass, + _In_opt_ PCSID ExplicitScope, + _Out_writes_bytes_(BufferLength) PVOID Buffer, + _In_ ULONG BufferLength); + +NTSYSAPI +NTSTATUS +NTAPI +NtSubscribeWnfStateChange( + _In_ PCWNF_STATE_NAME StateName, + _In_opt_ WNF_CHANGE_STAMP ChangeStamp, + _In_ ULONG EventMask, + _Out_opt_ PULONG64 SubscriptionId); + +NTSYSAPI +NTSTATUS +NTAPI +NtUnsubscribeWnfStateChange( + _In_ PCWNF_STATE_NAME StateName); + /************************************************************************************ * * Object and Handle API. diff --git a/Source/Shared/ntos/ntsup.c b/Source/Shared/ntos/ntsup.c index a625d26..585da3c 100644 --- a/Source/Shared/ntos/ntsup.c +++ b/Source/Shared/ntos/ntsup.c @@ -4,9 +4,9 @@ * * TITLE: NTSUP.C * -* VERSION: 2.28 +* VERSION: 2.34 * -* DATE: 11 Jul 2026 +* DATE: 18 Aug 2026 * * Native API support functions. * @@ -23,20 +23,13 @@ #pragma warning(push) #pragma warning(disable: 26812) // Prefer 'enum class' over 'enum' -#pragma warning(disable: 6320) // exception may mask +#pragma warning(disable: 6320) // exception may mask /* -* -* SHA256 algo (used by Ronova so keep it here). -* +* Ronova port start. +* SHA256 algo. */ -typedef struct _NTSUP_SHA256_CTX { - ULONG State[8]; - ULONG64 BitCount; - UCHAR Buffer[64]; -} NTSUP_SHA256_CTX, * PNTSUP_SHA256_CTX; - #define NTSUP_ROTR32(v,b) _rotr(v,b) #define NTSUP_CH(x,y,z) (((x) & (y)) ^ ((~x) & (z))) #define NTSUP_MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) @@ -194,49 +187,1347 @@ VOID ntsupSha256Final( padLen = 64 - ((bitCount >> 3) & 0x3f); if (padLen < 9) padLen += 64; - ntsupSha256Update(Ctx, pad, padLen - 8); - ntsupSha256Update(Ctx, len, 8); + ntsupSha256Update(Ctx, pad, padLen - 8); + ntsupSha256Update(Ctx, len, 8); + + for (i = 0; i < 8; i++) { + Digest[i * 4 + 0] = (UCHAR)(Ctx->State[i] >> 24); + Digest[i * 4 + 1] = (UCHAR)(Ctx->State[i] >> 16); + Digest[i * 4 + 2] = (UCHAR)(Ctx->State[i] >> 8); + Digest[i * 4 + 3] = (UCHAR)(Ctx->State[i]); + } + + RtlSecureZeroMemory(Ctx, sizeof(NTSUP_SHA256_CTX)); + RtlSecureZeroMemory(pad, sizeof(pad)); + RtlSecureZeroMemory(len, sizeof(len)); +} + +/* +* ntsupIsAddressValid +* +* Purpose: +* +* Validates that a given virtual memory address range is accessible +* in the current process address space. +* +* The routine checks: +* +* - Address is not NULL. +* - Memory region can be queried using NtQueryVirtualMemory. +* - Memory state is committed (MEM_COMMIT). +* - Memory protection does not include PAGE_NOACCESS. +* - Memory protection does not include PAGE_GUARD. +* - Requested size fits completely inside the queried memory region. +* +*/ +BOOLEAN NTAPI ntsupIsAddressValid( + _In_ PVOID Address, + _In_ SIZE_T Size +) +{ + MEMORY_BASIC_INFORMATION mbi; + NTSTATUS status; + + if (Address == NULL) + return FALSE; + + status = NtQueryVirtualMemory( + NtCurrentProcess(), + Address, + MemoryBasicInformation, + &mbi, + sizeof(mbi), + NULL); + + if (!NT_SUCCESS(status)) + return FALSE; + + if (mbi.State != MEM_COMMIT) + return FALSE; + + if (mbi.Protect & PAGE_NOACCESS) + return FALSE; + + if (mbi.Protect & PAGE_GUARD) + return FALSE; + + if (Size != 0) { + + if ((ULONG_PTR)Address < (ULONG_PTR)mbi.BaseAddress) + return FALSE; + + if (((ULONG_PTR)Address + Size) > + ((ULONG_PTR)mbi.BaseAddress + mbi.RegionSize)) + { + return FALSE; + } + } + + return TRUE; +} + +/* +* Ronova port end. +*/ + +/* +* ntsupStrChrW +* +* Purpose: +* +* Returns a pointer to the first occurrence of Character in String +* (including the terminator if Character is 0), or NULL if not found. +* +*/ +LPWSTR ntsupStrChrW( + _In_z_ LPCWSTR String, + _In_ WCHAR Character +) +{ + while (*String != UNICODE_NULL) { + if (*String == Character) + return (LPWSTR)String; + String++; + } + + if (Character == UNICODE_NULL) + return (LPWSTR)String; + + return NULL; +} + +/* +* ntsupStrChrA +* +* Purpose: +* +* Returns a pointer to the first occurrence of Character in String +* (including the terminator if Character is 0), or NULL if not found. +* +*/ +LPSTR ntsupStrChrA( + _In_z_ LPCSTR String, + _In_ CHAR Character +) +{ + while (*String != ANSI_NULL) { + if (*String == Character) + return (LPSTR)String; + String++; + } + + if (Character == ANSI_NULL) + return (LPSTR)String; + + return NULL; +} + +/* +* ntsupStrLenA +* +* Purpose: +* +* Returns the length, in characters, of a null-terminated ANSI string, or 0 if the pointer is NULL. +* +*/ +SIZE_T ntsupStrLenA( + _In_opt_ LPCSTR String +) +{ + LPCSTR String0 = String; + + if (String == NULL) + return 0; + + while (*String != ANSI_NULL) + String++; + + return (SIZE_T)(String - String0); +} + +/* +* ntsupStrLenW +* +* Purpose: +* +* Returns the length, in characters, of a null-terminated UTF-16 string, or 0 if the pointer is NULL. +* +*/ +SIZE_T ntsupStrLenW( + _In_opt_ LPCWSTR String +) +{ + LPCWSTR String0 = String; + + if (String == NULL) + return 0; + + while (*String != UNICODE_NULL) + String++; + + return (SIZE_T)(String - String0); +} + +/* +* ntsupStrCmpA +* +* Purpose: +* +* Performs a case-sensitive comparison of two null-terminated ANSI strings. +* +*/ +INT ntsupStrCmpA( + _In_opt_ LPCSTR String1, + _In_opt_ LPCSTR String2 +) +{ + CHAR c1, c2; + + if (String1 == String2) + return 0; + + if (String1 == NULL) + return -1; + + if (String2 == NULL) + return 1; + + do { + c1 = *String1; + c2 = *String2; + String1++; + String2++; + } while ((c1 != ANSI_NULL) && (c1 == c2)); + + return (INT)(c1 - c2); +} + +/* +* ntsupStrCmpW +* +* Purpose: +* +* Performs a case-sensitive comparison of two null-terminated UTF-16 strings. +* +*/ +INT ntsupStrCmpW( + _In_opt_ LPCWSTR String1, + _In_opt_ LPCWSTR String2 +) +{ + WCHAR c1, c2; + + if (String1 == String2) + return 0; + + if (String1 == NULL) + return -1; + + if (String2 == NULL) + return 1; + + do { + c1 = *String1; + c2 = *String2; + String1++; + String2++; + } while ((c1 != UNICODE_NULL) && (c1 == c2)); + + return (INT)(c1 - c2); +} + +/* +* ntsupStrCmpIA +* +* Purpose: +* +* Performs a case-insensitive comparison of two null-terminated ANSI strings. +* +*/ +INT ntsupStrCmpIA( + _In_opt_ LPCSTR String1, + _In_opt_ LPCSTR String2 +) +{ + CHAR c1, c2; + + if (String1 == String2) + return 0; + + if (String1 == NULL) + return -1; + + if (String2 == NULL) + return 1; + + do { + c1 = ntsupLowerCharA(*String1); + c2 = ntsupLowerCharA(*String2); + String1++; + String2++; + } while ((c1 != ANSI_NULL) && (c1 == c2)); + + return (INT)(c1 - c2); +} + +/* +* ntsupStrCmpIW +* +* Purpose: +* +* Performs a case-insensitive comparison of two null-terminated UTF-16 strings. +* +*/ +INT ntsupStrCmpIW( + _In_opt_ LPCWSTR String1, + _In_opt_ LPCWSTR String2 +) +{ + WCHAR c1, c2; + + if (String1 == String2) + return 0; + + if (String1 == NULL) + return -1; + + if (String2 == NULL) + return 1; + + do { + c1 = ntsupLowerCharW(*String1); + c2 = ntsupLowerCharW(*String2); + String1++; + String2++; + } while ((c1 != UNICODE_NULL) && (c1 == c2)); + + return (INT)(c1 - c2); +} + +/* +* ntsupStrCopyA +* +* Purpose: +* +* Copies a null-terminated ANSI string from Source to Destination +* (unbounded, caller-guaranteed capacity). +* +*/ +LPSTR ntsupStrCopyA( + _Out_writes_z_(_String_length_(Source) + 1) LPSTR Destination, + _In_z_ LPCSTR Source +) +{ + LPSTR p; + + if ((Destination == NULL) || (Source == NULL)) + return Destination; + + p = Destination; + + while (*Source != ANSI_NULL) { + *p = *Source; + p++; + Source++; + } + + *p = ANSI_NULL; + + return Destination; +} + +/* +* ntsupStrCopyW +* +* Purpose: +* +* Copies a null-terminated wide-character (UTF-16) string from Source to Destination +* (unbounded, caller-guaranteed capacity) +* +*/ +LPWSTR ntsupStrCopyW( + _Out_writes_z_(_String_length_(Source) + 1) LPWSTR Destination, + _In_z_ LPCWSTR Source +) +{ + LPWSTR p; + + if ((Destination == NULL) || (Source == NULL)) + return Destination; + + p = Destination; + + while (*Source != UNICODE_NULL) { + *p = *Source; + p++; + Source++; + } + + *p = UNICODE_NULL; + + return Destination; +} + +/* +* ntsupStrNCopyA +* +* Purpose: +* +* Copies up to SourceCount characters from an ANSI source string +* into a fixed-size destination buffer, always null-terminating. +* +*/ +LPSTR ntsupStrNCopyA( + _Out_writes_z_(DestinationCount) LPSTR Destination, + _In_ SIZE_T DestinationCount, + _In_reads_(SourceCount) LPCSTR Source, + _In_ SIZE_T SourceCount +) +{ + LPSTR p; + + if ((Destination == NULL) || (Source == NULL) || (DestinationCount == 0)) + return Destination; + + DestinationCount--; + p = Destination; + + while ((*Source != ANSI_NULL) && + (DestinationCount > 0) && + (SourceCount > 0)) + { + *p = *Source; + p++; + Source++; + DestinationCount--; + SourceCount--; + } + + *p = ANSI_NULL; + + return Destination; +} + +/* +* ntsupStrNCopyW +* +* Purpose: +* +* Copies up to SourceCount characters from a UTF-16 source string +* into a fixed-size destination buffer, always null-terminating. +* +*/ +LPWSTR ntsupStrNCopyW( + _Out_writes_z_(DestinationCount) LPWSTR Destination, + _In_ SIZE_T DestinationCount, + _In_reads_(SourceCount) LPCWSTR Source, + _In_ SIZE_T SourceCount +) +{ + LPWSTR p; + + if ((Destination == NULL) || (Source == NULL) || (DestinationCount == 0)) + return Destination; + + DestinationCount--; + p = Destination; + + while ((*Source != UNICODE_NULL) && + (DestinationCount > 0) && + (SourceCount > 0)) + { + *p = *Source; + p++; + Source++; + DestinationCount--; + SourceCount--; + } + + *p = UNICODE_NULL; + + return Destination; +} + +INT ntsupStrNCmpA( + _In_opt_ LPCSTR String1, + _In_opt_ LPCSTR String2, + _In_ SIZE_T Count +) +{ + CHAR c1, c2; + + if (String1 == String2) + return 0; + + if (String1 == NULL) + return -1; + + if (String2 == NULL) + return 1; + + if (Count == 0) + return 0; + + do { + c1 = *String1; + c2 = *String2; + String1++; + String2++; + Count--; + } while ((c1 != ANSI_NULL) && + (c1 == c2) && + (Count > 0)); + + return (INT)(c1 - c2); +} + +INT ntsupStrNCmpW( + _In_opt_ LPCWSTR String1, + _In_opt_ LPCWSTR String2, + _In_ SIZE_T Count +) +{ + WCHAR c1, c2; + + if (String1 == String2) + return 0; + + if (String1 == NULL) + return -1; + + if (String2 == NULL) + return 1; + + if (Count == 0) + return 0; + + do { + c1 = *String1; + c2 = *String2; + String1++; + String2++; + Count--; + } while ((c1 != UNICODE_NULL) && + (c1 == c2) && + (Count > 0)); + + return (INT)(c1 - c2); +} + +/* +* ntsupStrStrIA +* +* Purpose: +* +* Case insensitive string search. +* +*/ +LPCSTR ntsupStrStrIA( + _In_ LPCSTR String, + _In_ LPCSTR SubString +) +{ + CHAR c0, c1, c2; + LPCSTR tmpString; + LPCSTR tmpSubString; + + if (String == SubString) + return String; + + if (String == NULL) + return NULL; + + if (SubString == NULL) + return NULL; + + // + // Empty substring matches at beginning. + // + if (*SubString == 0) + return String; + + c0 = ntsupLowerCharA(*SubString); + + while (c0 != 0) { + + while (*String != 0) { + + c2 = ntsupLowerCharA(*String); + + if (c2 == c0) + break; + + String++; + } + + if (*String == 0) + return NULL; + + tmpString = String; + tmpSubString = SubString; + + do { + + c1 = ntsupLowerCharA(*tmpString); + c2 = ntsupLowerCharA(*tmpSubString); + + tmpString++; + tmpSubString++; + + } while ((c1 == c2) && (c2 != 0)); + + + if (c2 == 0) + return String; + + String++; + } + + return NULL; +} + +/* +* ntsupStrStrIW +* +* Purpose: +* +* Case insensitive string search. +* +*/ +LPCWSTR ntsupStrStrIW( + _In_ LPCWSTR String, + _In_ LPCWSTR SubString +) +{ + WCHAR c0, c1, c2; + LPCWSTR tmpString; + LPCWSTR tmpSubString; + + if (String == SubString) + return String; + + if (String == NULL) + return NULL; + + if (SubString == NULL) + return NULL; + + // + // Empty substring matches at beginning. + // + if (*SubString == 0) + return String; + + c0 = ntsupLowerCharW(*SubString); + + while (c0 != 0) { + + while (*String != 0) { + + c2 = ntsupLowerCharW(*String); + + if (c2 == c0) + break; + + String++; + } + + if (*String == 0) + return NULL; + + tmpString = String; + tmpSubString = SubString; + + do { + + c1 = ntsupLowerCharW(*tmpString); + c2 = ntsupLowerCharW(*tmpSubString); + + tmpString++; + tmpSubString++; + + } while ((c1 == c2) && (c2 != 0)); + + + if (c2 == 0) + return String; + + String++; + } + + return NULL; +} + +/* +* ntsupStrStrA +* +* Purpose: +* +* Case sensitive string search. +* +*/ +LPCSTR ntsupStrStrA( + _In_ LPCSTR String, + _In_ LPCSTR SubString +) +{ + CHAR c0, c1, c2; + LPCSTR tmpString; + LPCSTR tmpSubString; + + if (String == SubString) + return String; + + if (String == NULL) + return NULL; + + if (SubString == NULL) + return NULL; + + // + // Empty substring matches at beginning. + // + if (*SubString == 0) + return String; + + c0 = *SubString; + + while (c0 != 0) { + + while (*String != 0) { + + c2 = *String; + + if (c2 == c0) + break; + + String++; + } + + if (*String == 0) + return NULL; + + tmpString = String; + tmpSubString = SubString; + + do { + + c1 = *tmpString; + c2 = *tmpSubString; + + tmpString++; + tmpSubString++; + + } while ((c1 == c2) && (c2 != 0)); + + + if (c2 == 0) + return String; + + String++; + } + + return NULL; +} + +/* +* ntsupStrStrW +* +* Purpose: +* +* Case sensitive string search. +* +*/ +LPCWSTR ntsupStrStrW( + _In_ LPCWSTR String, + _In_ LPCWSTR SubString +) +{ + WCHAR c0, c1, c2; + LPCWSTR tmpString; + LPCWSTR tmpSubString; + + if (String == SubString) + return String; + + if (String == NULL) + return NULL; + + if (SubString == NULL) + return NULL; + + // + // Empty substring matches at beginning. + // + if (*SubString == 0) + return String; + + c0 = *SubString; + + while (c0 != 0) { + + while (*String != 0) { + + c2 = *String; + + if (c2 == c0) + break; + + String++; + } + + if (*String == 0) + return NULL; + + tmpString = String; + tmpSubString = SubString; + + do { + + c1 = *tmpString; + c2 = *tmpSubString; + + tmpString++; + tmpSubString++; + + } while ((c1 == c2) && (c2 != 0)); + + + if (c2 == 0) + return String; + + String++; + } + + return NULL; +} + +/* +* ntsupStrCatA +* +* Purpose: +* +* Append source string to destination string. +* +*/ +LPSTR ntsupStrCatA( + _Inout_ LPSTR Destination, + _In_ LPCSTR Source +) +{ + if ((Destination == NULL) || (Source == NULL)) + return Destination; + + while (*Destination != 0) + Destination++; + + while (*Source != 0) { + + *Destination = *Source; + + Destination++; + Source++; + } + + *Destination = 0; + + return Destination; +} + + +/* +* ntsupStrCatW +* +* Purpose: +* +* Append source string to destination string. +* +*/ +LPWSTR ntsupStrCatW( + _Inout_ LPWSTR Destination, + _In_ LPCWSTR Source +) +{ + if ((Destination == NULL) || (Source == NULL)) + return Destination; + + while (*Destination != 0) + Destination++; + + while (*Source != 0) { + + *Destination = *Source; + + Destination++; + Source++; + } + + *Destination = 0; + + return Destination; +} + +/* +* ntsupStrCatExA +* +* Purpose: +* +* Append source string to destination string. +* +* Destination buffer is always NULL terminated if size permits. +* +*/ +LPSTR ntsupStrCatExA( + _Inout_updates_z_(DestinationCount) LPSTR Destination, + _In_ SIZE_T DestinationCount, + _In_ LPCSTR Source +) +{ + LPSTR p; + + if ((Destination == NULL) || + (Source == NULL) || + (DestinationCount == 0)) + { + return Destination; + } + + p = Destination; + while ((*p != 0) && (DestinationCount > 1)) { + p++; + DestinationCount--; + } + + while ((*Source != 0) && (DestinationCount > 1)) { + + *p = *Source; + + p++; + Source++; + + DestinationCount--; + } + + *p = 0; + return Destination; +} + +/* +* ntsupStrCatExW +* +* Purpose: +* +* Append source string to destination string. +* +* Destination buffer is always NULL terminated if size permits. +* +*/ +LPWSTR ntsupStrCatExW( + _Inout_updates_z_(DestinationCount) LPWSTR Destination, + _In_ SIZE_T DestinationCount, + _In_ LPCWSTR Source +) +{ + LPWSTR p; + + if ((Destination == NULL) || + (Source == NULL) || + (DestinationCount == 0)) + { + return Destination; + } + + p = Destination; + while ((*p != 0) && (DestinationCount > 1)) { + p++; + DestinationCount--; + } + + while ((*Source != 0) && (DestinationCount > 1)) { + + *p = *Source; + + p++; + Source++; + + DestinationCount--; + } + + *p = 0; + return Destination; +} + +/* +* ntsupStrToUInt64A +* +* Purpose: +* +* Converts a decimal ANSI string to its ULONGLONG value. +* +*/ +BOOL ntsupStrToUInt64A( + _In_ LPCSTR String, + _Out_ PULONGLONG Value +) +{ + ULONGLONG result = 0; + ULONGLONG digit; + + *Value = 0; + + if (!String || !*String) + return FALSE; + + while (*String) { + + if (!ntsupIsDigitA(*String)) + return FALSE; + + digit = (ULONGLONG)(*String - '0'); + + if (result > (ULLONG_MAX - digit) / 10) + return FALSE; + + result = result * 10 + digit; + String++; + } + + *Value = result; + + return TRUE; +} + +/* +* ntsupStrToUInt64W +* +* Purpose: +* +* Converts a UTF-16 string to its ULONGLONG value. +* +*/ +BOOL ntsupStrToUInt64W( + _In_ LPCWSTR String, + _Out_ PULONGLONG Value +) +{ + ULONGLONG result = 0; + ULONGLONG digit; + + *Value = 0; + + if (!String || !*String) + return FALSE; + + while (*String) { + + if (!ntsupIsDigitW(*String)) + return FALSE; + + digit = (ULONGLONG)(*String - L'0'); + + if (result > (ULLONG_MAX - digit) / 10) + return FALSE; + + result = result * 10 + digit; + String++; + } + + *Value = result; + + return TRUE; +} + +/* +* ntsupUInt64ToStrW +* +* Purpose: +* +* Converts a ULONGLONG value to its UTF-16 string representation. +* +*/ +SIZE_T ntsupUInt64ToStrW( + _In_ ULONGLONG Value, + _Out_writes_z_(BufferCount) LPWSTR Buffer, + _In_ SIZE_T BufferCount +) +{ + WCHAR temp[21]; + SIZE_T length; + SIZE_T i; + + if (!Buffer || BufferCount == 0) + return 0; + + Buffer[0] = 0; + + if (Value == 0) { + if (BufferCount < 2) + return 0; + + Buffer[0] = L'0'; + Buffer[1] = 0; + return 1; + } + + length = 0; + + while (Value != 0 && length < RTL_NUMBER_OF(temp)) { + temp[length++] = (WCHAR)(L'0' + (Value % 10)); + Value /= 10; + } + + if (Value != 0) //msvc shut up + return 0; + + if ((length + 1) > BufferCount) + return 0; + + for (i = 0; i < length; i++) + Buffer[i] = temp[length - i - 1]; + + Buffer[length] = 0; + + return length; +} + +/* +* ntsupUInt64ToStrA +* +* Purpose: +* +* Converts a ULONGLONG value to its ANSI string representation. +* +*/ +SIZE_T ntsupUInt64ToStrA( + _In_ ULONGLONG Value, + _Out_writes_z_(BufferCount) LPSTR Buffer, + _In_ SIZE_T BufferCount +) +{ + CHAR temp[21]; + SIZE_T length; + SIZE_T i; + + if (!Buffer || BufferCount == 0) + return 0; + + Buffer[0] = 0; + + if (Value == 0) { + if (BufferCount < 2) + return 0; + + Buffer[0] = '0'; + Buffer[1] = 0; + + return 1; + } + + length = 0; + + while (Value != 0 && length < RTL_NUMBER_OF(temp)) { + temp[length++] = (CHAR)('0' + (Value % 10)); + Value /= 10; + } + + if (Value != 0) //msvc shut up + return 0; + + if ((length + 1) > BufferCount) + return 0; + + for (i = 0; i < length; i++) + Buffer[i] = temp[length - i - 1]; + + Buffer[length] = 0; + + return length; +} + +/* +* ntsupHexToUInt64A +* +* Purpose: +* +* Converts a ANSI hexademical string to the ULONGLONG value. +* +*/ +ULONGLONG ntsupHexToUInt64A( + _In_opt_ LPCSTR String +) +{ + INT digit; + ULONGLONG value = 0; + + if (!String) + return 0; + + while (*String) { + + digit = ntsupHexDigitToInt((UCHAR)*String); + if (digit < 0) + break; + + value = (value << 4) | (ULONG)digit; + String++; + } + + return value; +} + +/* +* ntsupHexToUInt64W +* +* Purpose: +* +* Converts a UTF-16 hexademical string to the ULONGLONG value. +* +*/ +ULONGLONG ntsupHexToUInt64W( + _In_opt_ LPCWSTR String +) +{ + INT digit; + ULONGLONG value = 0; + + if (!String) + return 0; + + while (*String) { + + digit = ntsupHexDigitToInt((WCHAR)*String); + if (digit < 0) + break; + + value = (value << 4) | (ULONG)digit; + String++; + } + + return value; +} + +/* +* ntsupHeapAlloc +* +* Purpose: +* +* Wrapper for RtlAllocateHeap with process heap. +* +*/ +PVOID NTAPI ntsupHeapAlloc( + _In_ SIZE_T Size +) +{ + return RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, Size); +} + +/* +* ntsupHeapReAlloc +* +* Purpose: +* +* Wrapper for RtlReAllocateHeap with process heap. +* +*/ +PVOID NTAPI ntsupHeapReAlloc( + _In_ PVOID BaseAddress, + _In_ SIZE_T Size +) +{ + if (BaseAddress == NULL) + return ntsupHeapAlloc(Size); + + return RtlReAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, BaseAddress, Size); +} + +/* +* ntsupHeapFree +* +* Purpose: +* +* Wrapper for RtlFreeHeap with process heap. +* +*/ +BOOL NTAPI ntsupHeapFree( + _In_ PVOID BaseAddress +) +{ + return RtlFreeHeap(RtlProcessHeap(), 0, BaseAddress); +} + +/* +* ntsupHeapSize +* +* Purpose: +* +* Wrapper for RtlSizeHeap with process heap. +* +*/ +SIZE_T NTAPI ntsupHeapSize( + _In_ PVOID BaseAddress +) +{ + return RtlSizeHeap(RtlProcessHeap(), 0, BaseAddress); +} - for (i = 0; i < 8; i++) { - Digest[i * 4 + 0] = (UCHAR)(Ctx->State[i] >> 24); - Digest[i * 4 + 1] = (UCHAR)(Ctx->State[i] >> 16); - Digest[i * 4 + 2] = (UCHAR)(Ctx->State[i] >> 8); - Digest[i * 4 + 3] = (UCHAR)(Ctx->State[i]); - } +/* +* ntsupHeapValidate +* +* Purpose: +* +* Wrapper for RtlValidateHeap with process heap. +* +*/ +BOOL NTAPI ntsupHeapValidate( + _In_ PVOID BaseAddress +) +{ + return RtlValidateHeap(RtlProcessHeap(), 0, BaseAddress); +} - RtlSecureZeroMemory(Ctx, sizeof(NTSUP_SHA256_CTX)); - RtlSecureZeroMemory(pad, sizeof(pad)); - RtlSecureZeroMemory(len, sizeof(len)); +/* +* ntsupHeapCompact +* +* Purpose: +* +* Wrapper for RtlCompactHeap with process heap. +* +*/ +SIZE_T NTAPI ntsupHeapCompact( + VOID +) +{ + return RtlCompactHeap(RtlProcessHeap(), 0); } /* -* ntsupHeapAlloc +* ntsupHeapLock * * Purpose: * -* Wrapper for RtlAllocateHeap with process heap. +* Wrapper for RtlLockHeap with process heap. * */ -PVOID ntsupHeapAlloc( - _In_ SIZE_T Size +BOOL NTAPI ntsupHeapLock( + VOID ) { - return RtlAllocateHeap(ntsupProcessHeap(), HEAP_ZERO_MEMORY, Size); + return RtlLockHeap(RtlProcessHeap()); } /* -* ntsupHeapFree +* ntsupHeapUnlock * * Purpose: * -* Wrapper for RtlFreeHeap with process heap. +* Wrapper for RtlUnlockHeap with process heap. * */ -BOOL ntsupHeapFree( - _In_ PVOID BaseAddress +BOOL NTAPI ntsupHeapUnlock( + VOID ) { - return RtlFreeHeap(ntsupProcessHeap(), 0, BaseAddress); + return RtlUnlockHeap(RtlProcessHeap()); } /* @@ -247,7 +1538,7 @@ BOOL ntsupHeapFree( * Wrapper for ntsupVirtualAllocEx with standard parameters. * */ -PVOID ntsupVirtualAllocEx( +PVOID NTAPI ntsupVirtualAllocEx( _In_ SIZE_T Size, _In_ ULONG AllocationType, _In_ ULONG Protect) @@ -281,7 +1572,7 @@ PVOID ntsupVirtualAllocEx( * Wrapper for supVirtualAllocEx. * */ -PVOID ntsupVirtualAlloc( +PVOID NTAPI ntsupVirtualAlloc( _In_ SIZE_T Size) { return ntsupVirtualAllocEx(Size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); @@ -295,7 +1586,7 @@ PVOID ntsupVirtualAlloc( * Wrapper for NtLockVirtualMemory. * */ -BOOL ntsupVirtualLock( +BOOL NTAPI ntsupVirtualLock( _In_ LPVOID lpAddress, _In_ SIZE_T dwSize ) @@ -314,7 +1605,7 @@ BOOL ntsupVirtualLock( * Wrapper for NtUnlockVirtualMemory. * */ -BOOL ntsupVirtualUnlock( +BOOL NTAPI ntsupVirtualUnlock( _In_ LPVOID lpAddress, _In_ SIZE_T dwSize ) @@ -333,7 +1624,7 @@ BOOL ntsupVirtualUnlock( * Wrapper for NtFreeVirtualMemory. * */ -BOOL ntsupVirtualFree( +BOOL NTAPI ntsupVirtualFree( _In_ PVOID Memory) { NTSTATUS ntStatus = STATUS_UNSUCCESSFUL; @@ -363,7 +1654,7 @@ BOOL ntsupVirtualFree( * Create new file (or open existing) and write buffer to it. * */ -SIZE_T ntsupWriteBufferToFile( +SIZE_T NTAPI ntsupWriteBufferToFile( _In_ PCWSTR FileName, _In_ PVOID Buffer, _In_ SIZE_T Size, @@ -470,7 +1761,7 @@ SIZE_T ntsupWriteBufferToFile( NtClose(hFile); } RtlFreeUnicodeString(&ntFileName); - if (Result) *Result = ntStatus; + if (Result)*Result = ntStatus; } return bytesWritten; } @@ -483,7 +1774,7 @@ SIZE_T ntsupWriteBufferToFile( * Find Module entry for given name. * */ -PVOID ntsupFindModuleEntryByName( +PVOID NTAPI ntsupFindModuleEntryByName( _In_ PRTL_PROCESS_MODULES ModulesList, _In_ LPCSTR ModuleName ) @@ -497,7 +1788,7 @@ PVOID ntsupFindModuleEntryByName( moduleEntry = &ModulesList->Modules[i]; fnameOffset = moduleEntry->OffsetToFileName; entryName = (LPSTR)&moduleEntry->FullPathName[fnameOffset]; - if (_strcmpi_a(entryName, ModuleName) == 0) + if (ntsupStrCmpIA(entryName, ModuleName) == 0) return moduleEntry; } @@ -512,7 +1803,7 @@ PVOID ntsupFindModuleEntryByName( * Find Module entry for given name. * */ -PVOID ntsupFindModuleEntryByName_U( +PVOID NTAPI ntsupFindModuleEntryByName_U( _In_ PRTL_PROCESS_MODULES ModulesList, _In_ LPCWSTR ModuleName ) @@ -534,7 +1825,7 @@ PVOID ntsupFindModuleEntryByName_U( moduleEntry = &ModulesList->Modules[i]; fnameOffset = moduleEntry->OffsetToFileName; entryName = (LPSTR)&moduleEntry->FullPathName[fnameOffset]; - if (_strcmpi_a(entryName, moduleName.Buffer) == 0) { + if (ntsupStrCmpIA(entryName, moduleName.Buffer) == 0) { result = moduleEntry; break; } @@ -556,7 +1847,7 @@ PVOID ntsupFindModuleEntryByName_U( * Returns module entry if found, NULL otherwise. * */ -BOOL ntsupFindModuleEntryByAddress( +BOOL NTAPI ntsupFindModuleEntryByAddress( _In_ PRTL_PROCESS_MODULES ModulesList, _In_ PVOID Address, _Out_ PULONG ModuleIndex @@ -586,7 +1877,7 @@ BOOL ntsupFindModuleEntryByAddress( * Get Module Entry for given Address. * */ -PVOID ntsupGetModuleEntryByAddress( +PVOID NTAPI ntsupGetModuleEntryByAddress( _In_ PRTL_PROCESS_MODULES ModulesList, _In_ PVOID Address ) @@ -597,7 +1888,7 @@ PVOID ntsupGetModuleEntryByAddress( if (IN_REGION(Address, ModulesList->Modules[i].ImageBase, ModulesList->Modules[i].ImageSize)) - { + { return &ModulesList->Modules[i]; } } @@ -612,7 +1903,7 @@ PVOID ntsupGetModuleEntryByAddress( * Find Module Name for given Address. * */ -PVOID ntsupFindModuleNameByAddress( +PVOID NTAPI ntsupFindModuleNameByAddress( _In_ PRTL_PROCESS_MODULES ModulesList, _In_ PVOID Address, _Inout_ LPWSTR Buffer, @@ -643,12 +1934,12 @@ PVOID ntsupFindModuleNameByAddress( (LPSTR)&moduleEntry->FullPathName[moduleEntry->OffsetToFileName], &usConvertedName); - if (NT_SUCCESS(ntStatus)) { + if (NT_SUCCESS(ntStatus) && (usConvertedName.Buffer != NULL)) { copyLength = usConvertedName.Length / sizeof(WCHAR); copyLength = MIN(copyLength, (SIZE_T)ccBuffer - 1); - _strncpy( + ntsupStrNCopy( Buffer, ccBuffer, usConvertedName.Buffer, @@ -677,7 +1968,7 @@ PVOID ntsupFindModuleNameByAddress( * If function succeeded - use RtlFreeUnicodeString to release allocated string. * */ -NTSTATUS ntsupConvertToUnicode( +NTSTATUS NTAPI ntsupConvertToUnicode( _In_ LPCSTR AnsiString, _Inout_ PUNICODE_STRING UnicodeString) { @@ -698,7 +1989,7 @@ NTSTATUS ntsupConvertToUnicode( * If function succeeded - use RtlFreeAnsiString to release allocated string. * */ -NTSTATUS ntsupConvertToAnsi( +NTSTATUS NTAPI ntsupConvertToAnsi( _In_ LPCWSTR UnicodeString, _Inout_ PANSI_STRING AnsiString) { @@ -716,7 +2007,7 @@ NTSTATUS ntsupConvertToAnsi( * Adjust privilege for the token. * */ -NTSTATUS ntsupSetPrivilege( +NTSTATUS NTAPI ntsupSetPrivilege( _In_ HANDLE TokenHandle, _In_ DWORD Privilege, _In_ BOOLEAN Enable, @@ -767,7 +2058,7 @@ NTSTATUS ntsupSetPrivilege( * Return FALSE on any error. * */ -BOOLEAN ntsupEnablePrivilege( +BOOLEAN NTAPI ntsupEnablePrivilege( _In_ DWORD Privilege, _In_ BOOLEAN Enable ) @@ -807,7 +2098,7 @@ BOOLEAN ntsupEnablePrivilege( * Return current process token value with TOKEN_QUERY access right. * */ -HANDLE ntsupGetCurrentProcessToken( +HANDLE NTAPI ntsupGetCurrentProcessToken( VOID) { HANDLE tokenHandle = NULL; @@ -830,7 +2121,7 @@ HANDLE ntsupGetCurrentProcessToken( * Return MmSystemRangeStart value. * */ -ULONG_PTR ntsupQuerySystemRangeStart( +ULONG_PTR NTAPI ntsupQuerySystemRangeStart( VOID ) { @@ -858,7 +2149,7 @@ ULONG_PTR ntsupQuerySystemRangeStart( * Return user mode applications accessible address range. * */ -BOOLEAN ntsupQueryUserModeAccessibleRange( +BOOLEAN NTAPI ntsupQueryUserModeAccessibleRange( _Out_ PULONG_PTR MinimumUserModeAddress, _Out_ PULONG_PTR MaximumUserModeAddress ) @@ -900,7 +2191,7 @@ BOOLEAN ntsupQueryUserModeAccessibleRange( * Perform check if the kernel debugger active. * */ -BOOLEAN ntsupIsKdEnabled( +BOOLEAN NTAPI ntsupIsKdEnabled( _Out_opt_ PBOOLEAN DebuggerAllowed, _Out_opt_ PBOOLEAN DebuggerNotPresent ) @@ -967,7 +2258,7 @@ BOOLEAN ntsupIsKdEnabled( * Return TRUE if process is wow64. * */ -BOOL ntsupIsProcess32bit( +BOOL NTAPI ntsupIsProcess32bit( _In_ HANDLE hProcess ) { @@ -998,7 +2289,7 @@ BOOL ntsupIsProcess32bit( * Read list of loaded kernel modules. * */ -PVOID ntsupGetLoadedModulesListEx( +PVOID NTAPI ntsupGetLoadedModulesListEx( _In_ BOOL ExtendedOutput, _Out_opt_ PULONG ReturnLength, _In_ PNTSUPMEMALLOC AllocMem, @@ -1082,7 +2373,7 @@ PVOID ntsupGetLoadedModulesListEx( * Returned buffer must be freed with ntsupHeapFree after usage. * */ -PVOID ntsupGetLoadedModulesList( +PVOID NTAPI ntsupGetLoadedModulesList( _Out_opt_ PULONG ReturnLength ) { @@ -1103,7 +2394,7 @@ PVOID ntsupGetLoadedModulesList( * Returned buffer must be freed with ntsupHeapFree after usage. * */ -PVOID ntsupGetLoadedModulesList2( +PVOID NTAPI ntsupGetLoadedModulesList2( _Out_opt_ PULONG ReturnLength ) { @@ -1124,7 +2415,7 @@ PVOID ntsupGetLoadedModulesList2( * Returned buffer must be freed with FreeMem function after usage. * */ -PVOID ntsupGetSystemInfoEx( +PVOID NTAPI ntsupGetSystemInfoEx( _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, _Out_opt_ PULONG ReturnLength, _In_ PNTSUPMEMALLOC AllocMem, @@ -1181,7 +2472,7 @@ PVOID ntsupGetSystemInfoEx( * Returned buffer must be freed with ntsupHeapFree after usage. * */ -PVOID ntsupGetSystemInfo( +PVOID NTAPI ntsupGetSystemInfo( _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, _Out_opt_ PULONG ReturnLength ) @@ -1203,7 +2494,7 @@ PVOID ntsupGetSystemInfo( * Return FALSE on any error. * */ -BOOL ntsupResolveSymbolicLink( +BOOL NTAPI ntsupResolveSymbolicLink( _In_opt_ HANDLE RootDirectoryHandle, _In_ PUNICODE_STRING LinkName, _Inout_ LPWSTR Buffer, @@ -1263,7 +2554,7 @@ BOOL ntsupResolveSymbolicLink( * Lookups thread win32 start address. * */ -BOOL ntsupQueryThreadWin32StartAddress( +BOOL NTAPI ntsupQueryThreadWin32StartAddress( _In_ HANDLE ThreadHandle, _Out_opt_ PULONG_PTR Win32StartAddress ) @@ -1294,7 +2585,7 @@ BOOL ntsupQueryThreadWin32StartAddress( * */ _Success_(return) -NTSTATUS ntsupOpenDirectoryEx( +NTSTATUS NTAPI ntsupOpenDirectoryEx( _Out_ PHANDLE DirectoryHandle, _In_opt_ HANDLE RootDirectoryHandle, _In_ PUNICODE_STRING DirectoryName, @@ -1325,7 +2616,7 @@ NTSTATUS ntsupOpenDirectoryEx( * Open directory handle with DIRECTORY_QUERY access, with root directory support. * */ -NTSTATUS ntsupOpenDirectory( +NTSTATUS NTAPI ntsupOpenDirectory( _Out_ PHANDLE DirectoryHandle, _In_opt_ HANDLE RootDirectoryHandle, _In_ LPCWSTR DirectoryName, @@ -1348,7 +2639,7 @@ NTSTATUS ntsupOpenDirectory( * If nothing found return FALSE. * */ -BOOL ntsupQueryProcessName( +BOOL NTAPI ntsupQueryProcessName( _In_ ULONG_PTR dwProcessId, _In_ PVOID ProcessList, _Inout_ LPWSTR Buffer, @@ -1370,7 +2661,7 @@ BOOL ntsupQueryProcessName( if ((ULONG_PTR)List.Process->UniqueProcessId == dwProcessId) { - _strncpy( + ntsupStrNCopy( Buffer, ccBuffer, List.Process->ImageName.Buffer, @@ -1398,10 +2689,10 @@ BOOL ntsupQueryProcessName( * If nothing found return FALSE. * */ -BOOL ntsupQueryProcessEntryById( +BOOL NTAPI ntsupQueryProcessEntryById( _In_ HANDLE UniqueProcessId, _In_ PVOID ProcessList, - _Out_ PSYSTEM_PROCESS_INFORMATION* Entry + _Out_ PSYSTEM_PROCESS_INFORMATION * Entry ) { ULONG NextEntryDelta = 0, iteration = 0; @@ -1443,7 +2734,7 @@ BOOL ntsupQueryProcessEntryById( * Use FreeMem to release allocated buffer. * */ -NTSTATUS ntsupQueryProcessImageFileNameByProcessId( +NTSTATUS NTAPI ntsupQueryProcessImageFileNameByProcessId( _In_ HANDLE UniqueProcessId, _Out_ PUNICODE_STRING ProcessImageFileName, _In_ PNTSUPMEMALLOC AllocMem, @@ -1491,11 +2782,11 @@ NTSTATUS ntsupQueryProcessImageFileNameByProcessId( * Use FreeMem to release allocated buffer. * */ -NTSTATUS ntsupQuerySystemObjectInformationVariableSize( +NTSTATUS NTAPI ntsupQuerySystemObjectInformationVariableSize( _In_ PFN_NTQUERYROUTINE QueryRoutine, _In_opt_ HANDLE ObjectHandle, _In_ DWORD InformationClass, - _Out_ PVOID* Buffer, + _Out_ PVOID * Buffer, _Out_opt_ PULONG ReturnLength, _In_ PNTSUPMEMALLOC AllocMem, _In_ PNTSUPMEMFREE FreeMem @@ -1506,7 +2797,7 @@ NTSTATUS ntsupQuerySystemObjectInformationVariableSize( ULONG returnLengthLocal = 0; *Buffer = NULL; - if (ReturnLength) *ReturnLength = 0; + if (ReturnLength)*ReturnLength = 0; ntStatus = QueryRoutine(ObjectHandle, InformationClass, @@ -1539,7 +2830,7 @@ NTSTATUS ntsupQuerySystemObjectInformationVariableSize( if (NT_SUCCESS(ntStatus)) { *Buffer = queryBuffer; - if (ReturnLength) *ReturnLength = returnLengthLocal; + if (ReturnLength)*ReturnLength = returnLengthLocal; } else { FreeMem(queryBuffer); @@ -1548,6 +2839,93 @@ NTSTATUS ntsupQuerySystemObjectInformationVariableSize( return ntStatus; } +/* +* ntsupQuerySystemObjectInformationVariableSizeEx +* +* Purpose: +* +* Generic object information query routine with automatic buffer growth. +* +* Use FreeMem to release allocated buffer. +* +*/ +NTSTATUS NTAPI ntsupQuerySystemObjectInformationVariableSizeEx( + _In_ PFN_NTQUERYROUTINE QueryRoutine, + _In_opt_ HANDLE ObjectHandle, + _In_ DWORD InformationClass, + _Out_ PVOID * Buffer, + _Out_opt_ PULONG ReturnLength, + _In_ ULONG InitialBufferSize, + _In_ PNTSUPMEMALLOC AllocMem, + _In_ PNTSUPMEMFREE FreeMem +) +{ + NTSTATUS ntStatus; + PVOID queryBuffer; + ULONG bufferSize; + ULONG returnLengthLocal = 0; + + if (Buffer == NULL) + return STATUS_INVALID_PARAMETER; + + *Buffer = NULL; + + if (ReturnLength) + *ReturnLength = 0; + + bufferSize = (InitialBufferSize != 0) ? + InitialBufferSize : PAGE_SIZE; + + queryBuffer = AllocMem(bufferSize); + if (queryBuffer == NULL) + return STATUS_INSUFFICIENT_RESOURCES; + + while ((ntStatus = QueryRoutine( + ObjectHandle, + InformationClass, + queryBuffer, + bufferSize, + &returnLengthLocal)) == STATUS_INFO_LENGTH_MISMATCH || + ntStatus == STATUS_BUFFER_TOO_SMALL || + ntStatus == STATUS_BUFFER_OVERFLOW) + { + FreeMem(queryBuffer); + + // + // Prefer the returned size if available, + // otherwise grow exponentially. + // + if (returnLengthLocal > bufferSize) + bufferSize = returnLengthLocal; + else + bufferSize <<= 1; + + if (bufferSize == 0 || + bufferSize > MAX_NTSUP_BUFFER_SIZE) + { + return STATUS_INVALID_BUFFER_SIZE; + } + + queryBuffer = AllocMem(bufferSize); + if (queryBuffer == NULL) + return STATUS_INSUFFICIENT_RESOURCES; + } + + if (NT_SUCCESS(ntStatus)) { + + *Buffer = queryBuffer; + + if (ReturnLength) + *ReturnLength = returnLengthLocal; + + return ntStatus; + } + + FreeMem(queryBuffer); + + return ntStatus; +} + /* * ntsupQueryVsmProtectionInformation * @@ -1556,7 +2934,7 @@ NTSTATUS ntsupQuerySystemObjectInformationVariableSize( * Query VSM protection information. * */ -BOOLEAN ntsupQueryVsmProtectionInformation( +BOOLEAN NTAPI ntsupQueryVsmProtectionInformation( _Out_ PBOOLEAN pbDmaProtectionsAvailable, _Out_ PBOOLEAN pbDmaProtectionsInUse, _Out_ PBOOLEAN pbHardwareMbecAvailable, @@ -1567,10 +2945,10 @@ BOOLEAN ntsupQueryVsmProtectionInformation( ULONG returnLength; SYSTEM_VSM_PROTECTION_INFORMATION svpi; - if (pbDmaProtectionsAvailable) *pbDmaProtectionsAvailable = FALSE; - if (pbDmaProtectionsInUse) *pbDmaProtectionsInUse = FALSE; - if (pbHardwareMbecAvailable) *pbHardwareMbecAvailable = FALSE; - if (pbApicVirtualizationAvailable) *pbApicVirtualizationAvailable = FALSE; + if (pbDmaProtectionsAvailable)*pbDmaProtectionsAvailable = FALSE; + if (pbDmaProtectionsInUse)*pbDmaProtectionsInUse = FALSE; + if (pbHardwareMbecAvailable)*pbHardwareMbecAvailable = FALSE; + if (pbApicVirtualizationAvailable)*pbApicVirtualizationAvailable = FALSE; RtlSecureZeroMemory(&svpi, sizeof(SYSTEM_VSM_PROTECTION_INFORMATION)); @@ -1581,10 +2959,10 @@ BOOLEAN ntsupQueryVsmProtectionInformation( &returnLength); if (NT_SUCCESS(ntStatus)) { - if (pbDmaProtectionsAvailable) *pbDmaProtectionsAvailable = svpi.DmaProtectionsAvailable; - if (pbDmaProtectionsInUse) *pbDmaProtectionsInUse = svpi.DmaProtectionsInUse; - if (pbHardwareMbecAvailable) *pbHardwareMbecAvailable = svpi.HardwareMbecAvailable; - if (pbApicVirtualizationAvailable) *pbApicVirtualizationAvailable = svpi.ApicVirtualizationAvailable; + if (pbDmaProtectionsAvailable)*pbDmaProtectionsAvailable = svpi.DmaProtectionsAvailable; + if (pbDmaProtectionsInUse)*pbDmaProtectionsInUse = svpi.DmaProtectionsInUse; + if (pbHardwareMbecAvailable)*pbHardwareMbecAvailable = svpi.HardwareMbecAvailable; + if (pbApicVirtualizationAvailable)*pbApicVirtualizationAvailable = svpi.ApicVirtualizationAvailable; return TRUE; } else { @@ -1595,28 +2973,36 @@ BOOLEAN ntsupQueryVsmProtectionInformation( } /* -* ntsupQueryHVCIState +* ntsupQueryVBSState * * Purpose: * -* Query HVCI/IUM state. +* Query VBS/HVCI state. * */ -BOOLEAN ntsupQueryHVCIState( +BOOLEAN NTAPI ntsupQueryVBSState( + _Out_ PBOOLEAN pbVBSRunning, _Out_ PBOOLEAN pbHVCIEnabled, - _Out_ PBOOLEAN pbHVCIStrictMode, - _Out_ PBOOLEAN pbHVCIIUMEnabled + _Out_ PBOOLEAN pbHVCIStrictMode ) { - BOOLEAN hvciEnabled; ULONG returnLength; NTSTATUS ntStatus; SYSTEM_CODEINTEGRITY_INFORMATION ci; + SYSTEM_ISOLATED_USER_MODE_INFORMATION iumi; - if (pbHVCIEnabled) *pbHVCIEnabled = FALSE; - if (pbHVCIStrictMode) *pbHVCIStrictMode = FALSE; - if (pbHVCIIUMEnabled) *pbHVCIIUMEnabled = FALSE; + if (pbVBSRunning) + *pbVBSRunning = FALSE; + if (pbHVCIEnabled) + *pbHVCIEnabled = FALSE; + + if (pbHVCIStrictMode) + *pbHVCIStrictMode = FALSE; + + // + // Query Code Integrity configuration. + // ci.Length = sizeof(ci); ntStatus = NtQuerySystemInformation( @@ -1625,50 +3011,76 @@ BOOLEAN ntsupQueryHVCIState( sizeof(ci), &returnLength); - if (NT_SUCCESS(ntStatus)) { + if (!NT_SUCCESS(ntStatus)) { + RtlSetLastWin32Error(RtlNtStatusToDosError(ntStatus)); + return FALSE; + } - hvciEnabled = ((ci.CodeIntegrityOptions & CODEINTEGRITY_OPTION_ENABLED) && + if (pbHVCIEnabled) { + *pbHVCIEnabled = ((ci.CodeIntegrityOptions & CODEINTEGRITY_OPTION_ENABLED) && (ci.CodeIntegrityOptions & CODEINTEGRITY_OPTION_HVCI_KMCI_ENABLED)); + } - if (pbHVCIEnabled) - *pbHVCIEnabled = hvciEnabled; + if (pbHVCIStrictMode) { + *pbHVCIStrictMode = ((ci.CodeIntegrityOptions & CODEINTEGRITY_OPTION_HVCI_KMCI_STRICTMODE_ENABLED) != 0); + } - if (pbHVCIStrictMode) - *pbHVCIStrictMode = (hvciEnabled == TRUE) && - (ci.CodeIntegrityOptions & CODEINTEGRITY_OPTION_HVCI_KMCI_STRICTMODE_ENABLED); + // + // Query VBS / Isolated User Mode state. + // + RtlSecureZeroMemory(&iumi, sizeof(iumi)); - if (pbHVCIIUMEnabled) - *pbHVCIIUMEnabled = (ci.CodeIntegrityOptions & CODEINTEGRITY_OPTION_HVCI_IUM_ENABLED) > 0; + ntStatus = NtQuerySystemInformation( + SystemIsolatedUserModeInformation, + &iumi, + sizeof(iumi), + &returnLength); - return TRUE; - } - else { + if (!NT_SUCCESS(ntStatus)) { RtlSetLastWin32Error(RtlNtStatusToDosError(ntStatus)); + return FALSE; } - return FALSE; + if (pbVBSRunning) + *pbVBSRunning = iumi.SecureKernelRunning; + + // + // Prefer the isolated user mode information for HVCI state. + // It reflects the actual VBS-backed HVCI status. + // + if (pbHVCIEnabled)*pbHVCIEnabled = iumi.HvciEnabled; + + if (pbHVCIStrictMode)*pbHVCIStrictMode = iumi.HvciStrictMode; + + return TRUE; } /* -* ntsupLookupImageSectionByName +* ntsupLookupImageSectionByNameEx * * Purpose: * -* Lookup section pointer and size for section name. +* Lookup PE image section by name. +* +* If ImageSize is non-zero, the image is range-checked by +* RtlImageNtHeaderEx. Otherwise, range checking is disabled. * */ -PVOID ntsupLookupImageSectionByName( - _In_ CHAR* SectionName, +PVOID NTAPI ntsupLookupImageSectionByNameEx( + _In_ CHAR * SectionName, _In_ ULONG SectionNameLength, _In_ PVOID DllBase, - _Out_ PULONG SectionSize + _In_ SIZE_T ImageSize, + _Out_opt_ PULONG SectionSize ) { - BOOLEAN bFound = FALSE; + NTSTATUS ntStatus; ULONG i; + SIZE_T cbSectionTable; + ULONG ntHeaderFlags; PVOID Section; - IMAGE_NT_HEADERS* NtHeaders = RtlImageNtHeader(DllBase); - IMAGE_SECTION_HEADER* SectionTableEntry; + PIMAGE_NT_HEADERS NtHeaders; + PIMAGE_SECTION_HEADER SectionTableEntry; // // Assume failure. @@ -1676,44 +3088,89 @@ PVOID ntsupLookupImageSectionByName( if (SectionSize) *SectionSize = 0; - if (NtHeaders == NULL) + if (DllBase == NULL || + SectionName == NULL || + SectionNameLength == 0) + { + return NULL; + } + + if (SectionNameLength > IMAGE_SIZEOF_SHORT_NAME) + SectionNameLength = IMAGE_SIZEOF_SHORT_NAME; + + // + // Determine whether image range checking is possible. + // + ntHeaderFlags = (ImageSize == 0) ? RTL_IMAGE_NT_HEADER_EX_FLAG_NO_RANGE_CHECK : 0; + + ntStatus = RtlImageNtHeaderEx(ntHeaderFlags, DllBase, ImageSize, &NtHeaders); + if (!NT_SUCCESS(ntStatus)) + return NULL; + + if (NtHeaders->FileHeader.NumberOfSections == 0) + return NULL; + + cbSectionTable = (SIZE_T)NtHeaders->FileHeader.NumberOfSections * + sizeof(IMAGE_SECTION_HEADER); + + // + // Overflow check. + // + if ((cbSectionTable / sizeof(IMAGE_SECTION_HEADER)) != + NtHeaders->FileHeader.NumberOfSections) + { return NULL; + } - SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeaders + - sizeof(ULONG) + - sizeof(IMAGE_FILE_HEADER) + - NtHeaders->FileHeader.SizeOfOptionalHeader); + SectionTableEntry = IMAGE_FIRST_SECTION(NtHeaders); + if (!ntsupIsAddressValid(SectionTableEntry, cbSectionTable)) + return NULL; // // Locate section. // - i = NtHeaders->FileHeader.NumberOfSections; - while (i > 0) { + for (i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++, SectionTableEntry++) { - if (_strncmp_a( + if (ntsupStrNCmpA( (CHAR*)SectionTableEntry->Name, SectionName, SectionNameLength) == 0) { - bFound = TRUE; - break; - } + Section = RtlOffsetToPointer( + DllBase, + SectionTableEntry->VirtualAddress); - i -= 1; - SectionTableEntry += 1; - } + if (SectionSize) + *SectionSize = SectionTableEntry->Misc.VirtualSize; - // - // Section not found, abort scan. - // - if (!bFound) - return NULL; + return Section; + } + } - Section = (PVOID)((ULONG_PTR)DllBase + SectionTableEntry->VirtualAddress); - if (SectionSize) - *SectionSize = SectionTableEntry->Misc.VirtualSize; + return NULL; +} - return Section; +/* +* ntsupLookupImageSectionByName +* +* Purpose: +* +* Lookup PE image section by name. +* +*/ +PVOID NTAPI ntsupLookupImageSectionByName( + _In_ CHAR * SectionName, + _In_ ULONG SectionNameLength, + _In_ PVOID DllBase, + _Out_ PULONG SectionSize +) +{ + return ntsupLookupImageSectionByNameEx( + SectionName, + SectionNameLength, + DllBase, + 0, // Unknown image size. + SectionSize); } /* @@ -1724,7 +3181,7 @@ PVOID ntsupLookupImageSectionByName( * Lookup pattern in buffer. * */ -PVOID ntsupFindPattern( +PVOID NTAPI ntsupFindPattern( _In_ CONST PBYTE Buffer, _In_ SIZE_T BufferSize, _In_ CONST PBYTE Pattern, @@ -1767,8 +3224,8 @@ PVOID ntsupFindPattern( * Lookup pattern in buffer with specified mask. * */ -DWORD ntsupFindPatternEx( - _In_ PATTERN_SEARCH_PARAMS* SearchParams +DWORD NTAPI ntsupFindPatternEx( + _In_ PATTERN_SEARCH_PARAMS * SearchParams ) { PBYTE p; @@ -1838,7 +3295,7 @@ DWORD ntsupFindPatternEx( * NtOpenProcess wrapper. * */ -NTSTATUS ntsupOpenProcess( +NTSTATUS NTAPI ntsupOpenProcess( _In_ HANDLE UniqueProcessId, _In_ ACCESS_MASK DesiredAccess, _Out_ PHANDLE ProcessHandle @@ -1863,22 +3320,23 @@ NTSTATUS ntsupOpenProcess( } /* -* ntsupOpenThread +* ntsupOpenThreadEx * * Purpose: * * NtOpenThread wrapper. * */ -NTSTATUS ntsupOpenThread( +NTSTATUS NTAPI ntsupOpenThreadEx( _In_ PCLIENT_ID ClientId, _In_ ACCESS_MASK DesiredAccess, + _In_ ULONG ObjectAttributes, _Out_ PHANDLE ThreadHandle ) { NTSTATUS ntStatus; HANDLE threadHandle = NULL; - OBJECT_ATTRIBUTES objectAttributes = RTL_INIT_OBJECT_ATTRIBUTES((PUNICODE_STRING)NULL, 0); + OBJECT_ATTRIBUTES objectAttributes = RTL_INIT_OBJECT_ATTRIBUTES((PUNICODE_STRING)NULL, ObjectAttributes); ntStatus = NtOpenThread( &threadHandle, @@ -1891,6 +3349,26 @@ NTSTATUS ntsupOpenThread( return ntStatus; } +/* +* ntsupOpenThread +* +* Purpose: +* +* NtOpenThread wrapper. +* +*/ +NTSTATUS NTAPI ntsupOpenThread( + _In_ PCLIENT_ID ClientId, + _In_ ACCESS_MASK DesiredAccess, + _Out_ PHANDLE ThreadHandle +) +{ + return ntsupOpenThreadEx(ClientId, + DesiredAccess, + 0, + ThreadHandle); +} + /* * ntsupCICustomKernelSignersAllowed * @@ -1899,7 +3377,7 @@ NTSTATUS ntsupOpenThread( * Return license state if present (EnterpriseG). * */ -NTSTATUS ntsupCICustomKernelSignersAllowed( +NTSTATUS NTAPI ntsupCICustomKernelSignersAllowed( _Out_ PBOOLEAN bAllowed) { NTSTATUS ntStatus; @@ -1929,7 +3407,7 @@ NTSTATUS ntsupCICustomKernelSignersAllowed( * Tests if the given token has the given privilege enabled/enabled by default. * */ -NTSTATUS ntsupPrivilegeEnabled( +NTSTATUS NTAPI ntsupPrivilegeEnabled( _In_ HANDLE ClientToken, _In_ ULONG Privilege, _Out_ LPBOOL pfResult @@ -1952,6 +3430,52 @@ NTSTATUS ntsupPrivilegeEnabled( return status; } +/* +* ntsupSetEnvironmentVariable +* +* Purpose: +* +* Set environment variable. +* +*/ +BOOLEAN NTAPI ntsupSetEnvironmentVariable( + _In_ LPCWSTR Name, + _In_opt_ LPCWSTR Value +) +{ + UNICODE_STRING usName; + UNICODE_STRING usValue; + NTSTATUS status; + + if (Name == NULL) + return FALSE; + + RtlInitUnicodeString( + &usName, + Name); + + if (Value != NULL) { + + RtlInitUnicodeString( + &usValue, + Value); + + status = RtlSetEnvironmentVariable( + NULL, + &usName, + &usValue); + } + else { + + status = RtlSetEnvironmentVariable( + NULL, + &usName, + NULL); + } + + return NT_SUCCESS(status); +} + /* * ntsupQueryEnvironmentVariableOffset * @@ -1960,7 +3484,7 @@ NTSTATUS ntsupPrivilegeEnabled( * Return offset to the given environment variable. * */ -LPWSTR ntsupQueryEnvironmentVariableOffset( +LPWSTR NTAPI ntsupQueryEnvironmentVariableOffset( _In_ PUNICODE_STRING Value ) { @@ -1968,6 +3492,9 @@ LPWSTR ntsupQueryEnvironmentVariableOffset( PWCHAR ptrEnvironment; ULONG scanCount = 0; + if (Value == NULL || Value->Buffer == NULL) + return NULL; + ptrEnvironment = (PWCHAR)RtlGetCurrentPeb()->ProcessParameters->Environment; do { @@ -1978,7 +3505,7 @@ LPWSTR ntsupQueryEnvironmentVariableOffset( if (RtlPrefixUnicodeString(Value, &str1, TRUE)) break; - ptrEnvironment += _strlen(ptrEnvironment) + 1; + ptrEnvironment += ntsupStrLen(ptrEnvironment) + 1; } while (1); @@ -1993,7 +3520,7 @@ LPWSTR ntsupQueryEnvironmentVariableOffset( * Reimplemented ExpandEnvironmentStrings. * */ -DWORD ntsupExpandEnvironmentStrings( +DWORD NTAPI ntsupExpandEnvironmentStrings( _In_ LPCWSTR lpSrc, _Out_writes_to_opt_(nSize, return) LPWSTR lpDst, _In_ DWORD nSize @@ -2003,7 +3530,7 @@ DWORD ntsupExpandEnvironmentStrings( SIZE_T srcLength = 0, returnLength = 0, dstLength = (SIZE_T)nSize; if (lpSrc) { - srcLength = _strlen(lpSrc); + srcLength = ntsupStrLen(lpSrc); } ntStatus = RtlExpandEnvironmentStrings( @@ -2035,7 +3562,7 @@ DWORD ntsupExpandEnvironmentStrings( * Function return operation status code. * */ -NTSTATUS ntsupIsUserHasInteractiveSid( +NTSTATUS NTAPI ntsupIsUserHasInteractiveSid( _In_ HANDLE hToken, _Out_ PBOOL pbInteractiveSid) { @@ -2125,7 +3652,7 @@ NTSTATUS ntsupIsUserHasInteractiveSid( * Function return operation status code. * */ -NTSTATUS ntsupIsLocalSystem( +NTSTATUS NTAPI ntsupIsLocalSystem( _Out_ PBOOL pbResult) { BOOL bResult = FALSE; @@ -2212,7 +3739,7 @@ NTSTATUS ntsupIsLocalSystem( * Returns process elevation type. * */ -BOOL ntsupGetProcessElevationType( +BOOL NTAPI ntsupGetProcessElevationType( _In_opt_ HANDLE ProcessHandle, _Out_ TOKEN_ELEVATION_TYPE * lpType ) @@ -2253,7 +3780,7 @@ BOOL ntsupGetProcessElevationType( * Returns process elevation state. * */ -NTSTATUS ntsupIsProcessElevated( +NTSTATUS NTAPI ntsupIsProcessElevated( _In_ ULONG ProcessId, _Out_ PBOOL Elevated) { @@ -2262,7 +3789,7 @@ NTSTATUS ntsupIsProcessElevated( HANDLE processHandle = NULL, tokenHandle = NULL; TOKEN_ELEVATION tokenInfo; - if (Elevated) *Elevated = FALSE; + if (Elevated)*Elevated = FALSE; ntStatus = ntsupOpenProcess( UlongToHandle(ProcessId), @@ -2305,7 +3832,7 @@ NTSTATUS ntsupIsProcessElevated( * Flush file cache and memory standby list. * */ -VOID ntsupPurgeSystemCache( +VOID NTAPI ntsupPurgeSystemCache( VOID ) { @@ -2409,7 +3936,7 @@ VOID ntsupPurgeSystemCache( * Return system root directory silo session aware. * */ -PWSTR ntsupGetSystemRoot( +PWSTR NTAPI ntsupGetSystemRoot( VOID ) { @@ -2429,7 +3956,7 @@ PWSTR ntsupGetSystemRoot( * Reference process debug object. * */ -NTSTATUS ntsupGetProcessDebugObject( +NTSTATUS NTAPI ntsupGetProcessDebugObject( _In_ HANDLE ProcessHandle, _Out_ PHANDLE DebugObjectHandle ) @@ -2450,7 +3977,7 @@ NTSTATUS ntsupGetProcessDebugObject( * Load resource by given id (win32 FindResource, SizeofResource, LockResource). * */ -PBYTE ntsupQueryResourceData( +PBYTE NTAPI ntsupQueryResourceData( _In_ ULONG_PTR ResourceId, _In_ PVOID DllHandle, _In_ PULONG DataSize @@ -2493,7 +4020,7 @@ PBYTE ntsupQueryResourceData( * Enable/Disable Wow64 redirection. * */ -NTSTATUS ntsupEnableWow64Redirection( +NTSTATUS NTAPI ntsupEnableWow64Redirection( _In_ BOOLEAN bEnable ) { @@ -2531,7 +4058,7 @@ NTSTATUS NTAPI ntsupDetectObjectCallback( } if (Entry->Name.Buffer) { - if (_strcmpi_w(Entry->Name.Buffer, Param->Buffer) == 0) { + if (ntsupStrCmpIW(Entry->Name.Buffer, Param->Buffer) == 0) { return STATUS_SUCCESS; } } @@ -2632,7 +4159,7 @@ NTSTATUS NTAPI ntsupEnumSystemObjects( * Return TRUE if the given object exists, FALSE otherwise. * */ -BOOLEAN ntsupIsObjectExists( +BOOLEAN NTAPI ntsupIsObjectExists( _In_ LPCWSTR RootDirectory, _In_ LPCWSTR ObjectName ) @@ -2640,7 +4167,7 @@ BOOLEAN ntsupIsObjectExists( OBJSCANPARAM Param; Param.Buffer = ObjectName; - Param.BufferSize = (ULONG)_strlen(ObjectName); + Param.BufferSize = (ULONG)ntsupStrLen(ObjectName); return NT_SUCCESS(ntsupEnumSystemObjects(RootDirectory, NULL, ntsupDetectObjectCallback, &Param)); } @@ -2653,7 +4180,7 @@ BOOLEAN ntsupIsObjectExists( * Tests if the current user is admin with full access token. * */ -BOOLEAN ntsupUserIsFullAdmin( +BOOLEAN NTAPI ntsupUserIsFullAdmin( VOID ) { @@ -2723,7 +4250,7 @@ BOOLEAN ntsupUserIsFullAdmin( * Allocated memory must be freed by called with supHeapFree. * */ -NTSTATUS ntsupDuplicateUnicodeString( +NTSTATUS NTAPI ntsupDuplicateUnicodeString( _In_ PCUNICODE_STRING SourceString, _Out_ PUNICODE_STRING DestinationString ) @@ -2782,7 +4309,7 @@ NTSTATUS ntsupDuplicateUnicodeString( * Allocated memory must be freed by called with supHeapFree. * */ -NTSTATUS ntsupDuplicateAnsiString( +NTSTATUS NTAPI ntsupDuplicateAnsiString( _In_ PCANSI_STRING SourceString, _Out_ PANSI_STRING DestinationString ) @@ -2841,7 +4368,7 @@ NTSTATUS ntsupDuplicateAnsiString( * Allocated string must be freed by caller with RtlFreeUnicodeString. * */ -NTSTATUS ntsupQueryProcessCommandLine( +NTSTATUS NTAPI ntsupQueryProcessCommandLine( _In_ HANDLE ProcessHandle, _Out_ PUNICODE_STRING CommandLine, _In_ PNTSUPMEMALLOC AllocMem, @@ -2914,7 +4441,7 @@ NTSTATUS ntsupQueryProcessCommandLine( * executable section. * */ -NTSTATUS ntsupHashImageSections( +NTSTATUS NTAPI ntsupHashImageSections( _In_ PVOID ImageBase, _In_ SIZE_T ImageSize, // Size of image mapping _Out_writes_bytes_(HashBufferSize) PBYTE HashBuffer, @@ -2949,7 +4476,7 @@ NTSTATUS ntsupHashImageSections( if (!NT_SUCCESS(RtlImageNtHeaderEx(0, ImageBase, ImageSize, - (PIMAGE_NT_HEADERS*)&ntHeaders)) || ntHeaders == NULL) + (PIMAGE_NT_HEADERS*)&ntHeaders)) || ntHeaders == NULL) { return STATUS_INVALID_IMAGE_FORMAT; } @@ -2961,7 +4488,7 @@ NTSTATUS ntsupHashImageSections( // Validate image size matches reported size. // if (ntHeaders->OptionalHeader.SizeOfImage > ImageSize && - ImageType == ImageTypeLoaded) + ImageType == ImageTypeLoaded) { return STATUS_INVALID_IMAGE_FORMAT; } @@ -3052,7 +4579,7 @@ NTSTATUS ntsupHashImageSections( } if (sectionStart < baseAddress || - sectionStart >= baseAddress + ImageSize) + sectionStart >= baseAddress + ImageSize) { continue; } @@ -3076,4 +4603,53 @@ NTSTATUS ntsupHashImageSections( return STATUS_SUCCESS; } +/* +* ntsupQueryProcessDebugInformation +* +* Purpose: +* +* Allocate process debug information buffer. +* +*/ +PRTL_DEBUG_INFORMATION NTAPI ntsupQueryProcessDebugInformation( + _In_ HANDLE ProcessId, + _In_ ULONG Flags +) +{ + PRTL_DEBUG_INFORMATION debugBuffer; + NTSTATUS ntStatus; + + debugBuffer = RtlCreateQueryDebugBuffer(0, FALSE); + if (debugBuffer == NULL) + return NULL; + + ntStatus = RtlQueryProcessDebugInformation( + ProcessId, + Flags, + debugBuffer); + + if (!NT_SUCCESS(ntStatus)) { + RtlDestroyQueryDebugBuffer(debugBuffer); + return NULL; + } + + return debugBuffer; +} + +/* +* ntsupFreeProcessDebugInformation +* +* Purpose: +* +* Free process debug information buffer. +* +*/ +VOID NTAPI ntsupFreeProcessDebugInformation( + _In_opt_ PRTL_DEBUG_INFORMATION DebugInformation +) +{ + if (DebugInformation != NULL) + RtlDestroyQueryDebugBuffer(DebugInformation); +} + #pragma warning(pop) diff --git a/Source/Shared/ntos/ntsup.h b/Source/Shared/ntos/ntsup.h index 916560a..bad27b8 100644 --- a/Source/Shared/ntos/ntsup.h +++ b/Source/Shared/ntos/ntsup.h @@ -4,14 +4,13 @@ * * TITLE: NTSUP.H * -* VERSION: 2.27 +* VERSION: 2.34 * -* DATE: 27 Jun 2026 +* DATE: 18 Aug 2026 * * Common header file for the NT API support functions and definitions. * * Depends on: ntos.h -* minirtl * * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF * ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED @@ -49,347 +48,617 @@ #include #undef _NTDEF_ -#include "minirtl/minirtl.h" - #ifdef ENABLE_C_EXTERN #if defined(__cplusplus) extern "C" { #endif #endif -typedef NTSTATUS(NTAPI* PFN_NTQUERYROUTINE)( - _In_opt_ HANDLE ObjectHandle, - _In_ DWORD InformationClass, - _Out_writes_bytes_(ObjectInformationLength) PVOID ObjectInformation, - _In_ ULONG ObjectInformationLength, - _Out_opt_ PULONG ReturnLength); - -typedef PVOID(CALLBACK* PNTSUPMEMALLOC)( - _In_ SIZE_T NumberOfBytes); + typedef NTSTATUS(NTAPI* PFN_NTQUERYROUTINE)( + _In_opt_ HANDLE ObjectHandle, + _In_ DWORD InformationClass, + _Out_writes_bytes_(ObjectInformationLength) PVOID ObjectInformation, + _In_ ULONG ObjectInformationLength, + _Out_opt_ PULONG ReturnLength); -typedef BOOL(CALLBACK* PNTSUPMEMFREE)( - _In_ PVOID Memory); + typedef PVOID(CALLBACK* PNTSUPMEMALLOC)( + _In_ SIZE_T NumberOfBytes); -#define ntsupProcessHeap() NtCurrentPeb()->ProcessHeap + typedef BOOL(CALLBACK* PNTSUPMEMFREE)( + _In_ PVOID Memory); #define NTSUPHASH_SHA256_SIZE 32 -#define MAX_NTSUP_BUFFER_SIZE (512 * 1024 * 1024) //512MB +#define MAX_NTSUP_BUFFER_SIZE (512* 1024* 1024) //512MB #define MAX_NTSUP_ENV_SCAN 4096 -#define MAX_NTSUP_PROCESS_ENUM_ITER (1024 * 1024) +#define MAX_NTSUP_PROCESS_ENUM_ITER (1024* 1024) #define MAX_NTSUP_WRITE_CHUNK 0x7FFFFFFF -typedef struct _OBJSCANPARAM { - PCWSTR Buffer; - ULONG BufferSize; -} OBJSCANPARAM, * POBJSCANPARAM; - -typedef NTSTATUS(NTAPI* PENUMOBJECTSCALLBACK)( - _In_ POBJECT_DIRECTORY_INFORMATION Entry, - _In_opt_ PVOID CallbackParam); - -typedef BOOL(CALLBACK* pfnPatternSearchCallback)( - _In_ PBYTE Buffer, - _In_ ULONG PatternSize, - _In_opt_ PVOID CallbackContext - ); - -typedef struct _PATTERN_SEARCH_PARAMS { - PBYTE Buffer; - DWORD BufferSize; - PBYTE Pattern; - DWORD PatternSize; - PBYTE Mask; - pfnPatternSearchCallback Callback; - PVOID CallbackContext; -} PATTERN_SEARCH_PARAMS, * PPATTERN_SEARCH_PARAMS; - -typedef enum _NTSUP_IMAGE_TYPE { - ImageTypeRaw, // Raw file mapping (CreateFileMapping) - ImageTypeLoaded // Loaded module (PEB/LdrEntry) -} NTSUP_IMAGE_TYPE; - -PVOID ntsupHeapAlloc( - _In_ SIZE_T Size); - -BOOL ntsupHeapFree( - _In_ PVOID BaseAddress); - -PVOID ntsupVirtualAllocEx( - _In_ SIZE_T Size, - _In_ ULONG AllocationType, - _In_ ULONG Protect); - -PVOID ntsupVirtualAlloc( - _In_ SIZE_T Size); - -BOOL ntsupVirtualFree( - _In_ PVOID Memory); - -BOOL ntsupVirtualLock( - _In_ LPVOID lpAddress, - _In_ SIZE_T dwSize); - -BOOL ntsupVirtualUnlock( - _In_ LPVOID lpAddress, - _In_ SIZE_T dwSize); - -SIZE_T ntsupWriteBufferToFile( - _In_ PCWSTR FileName, - _In_ PVOID Buffer, - _In_ SIZE_T Size, - _In_ BOOL Flush, - _In_ BOOL Append, - _Out_opt_ NTSTATUS* Result); - -PVOID ntsupGetModuleEntryByAddress( - _In_ PRTL_PROCESS_MODULES ModulesList, - _In_ PVOID Address); - -PVOID ntsupFindModuleEntryByName( - _In_ PRTL_PROCESS_MODULES ModulesList, - _In_ LPCSTR ModuleName); - -PVOID ntsupFindModuleEntryByName_U( - _In_ PRTL_PROCESS_MODULES ModulesList, - _In_ LPCWSTR ModuleName); - -BOOL ntsupFindModuleEntryByAddress( - _In_ PRTL_PROCESS_MODULES ModulesList, - _In_ PVOID Address, - _Out_ PULONG ModuleIndex); - -PVOID ntsupFindModuleNameByAddress( - _In_ PRTL_PROCESS_MODULES ModulesList, - _In_ PVOID Address, - _Inout_ LPWSTR Buffer, - _In_ DWORD ccBuffer); - -NTSTATUS ntsupConvertToUnicode( - _In_ LPCSTR AnsiString, - _Inout_ PUNICODE_STRING UnicodeString); - -NTSTATUS ntsupConvertToAnsi( - _In_ LPCWSTR UnicodeString, - _Inout_ PANSI_STRING AnsiString); - -NTSTATUS ntsupSetPrivilege( - _In_ HANDLE TokenHandle, - _In_ DWORD Privilege, - _In_ BOOLEAN Enable, - _Out_opt_ PTOKEN_PRIVILEGES PreviousState, - _Out_opt_ PULONG ReturnLength); - -BOOLEAN ntsupEnablePrivilege( - _In_ DWORD Privilege, - _In_ BOOLEAN Enable); - -HANDLE ntsupGetCurrentProcessToken( - VOID); - -ULONG_PTR ntsupQuerySystemRangeStart( - VOID); - -BOOLEAN ntsupQueryUserModeAccessibleRange( - _Out_ PULONG_PTR MinimumUserModeAddress, - _Out_ PULONG_PTR MaximumUserModeAddress); - -BOOL ntsupIsProcess32bit( - _In_ HANDLE hProcess); - -PVOID ntsupGetLoadedModulesListEx( - _In_ BOOL ExtendedOutput, - _Out_opt_ PULONG ReturnLength, - _In_ PNTSUPMEMALLOC AllocMem, - _In_ PNTSUPMEMFREE FreeMem); - -PVOID ntsupGetLoadedModulesList( - _Out_opt_ PULONG ReturnLength); - -PVOID ntsupGetLoadedModulesList2( - _Out_opt_ PULONG ReturnLength); - -PVOID ntsupGetSystemInfoEx( - _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, - _Out_opt_ PULONG ReturnLength, - _In_ PNTSUPMEMALLOC AllocMem, - _In_ PNTSUPMEMFREE FreeMem); - -PVOID ntsupGetSystemInfo( - _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, - _Out_opt_ PULONG ReturnLength); - -NTSTATUS NTAPI ntsupEnumSystemObjects( - _In_opt_ LPCWSTR RootDirectory, - _In_opt_ HANDLE RootDirectoryHandle, - _In_ PENUMOBJECTSCALLBACK CallbackProc, - _In_opt_ PVOID CallbackParam); - -BOOL ntsupResolveSymbolicLink( - _In_opt_ HANDLE RootDirectoryHandle, - _In_ PUNICODE_STRING LinkName, - _Inout_ LPWSTR Buffer, - _In_ DWORD cbBuffer); - -BOOL ntsupQueryThreadWin32StartAddress( - _In_ HANDLE ThreadHandle, - _Out_opt_ PULONG_PTR Win32StartAddress); - -NTSTATUS ntsupQueryProcessCommandLine( - _In_ HANDLE ProcessHandle, - _Out_ PUNICODE_STRING CommandLine, - _In_ PNTSUPMEMALLOC AllocMem, - _In_ PNTSUPMEMFREE FreeMem); - -_Success_(return) -NTSTATUS ntsupOpenDirectoryEx( - _Out_ PHANDLE DirectoryHandle, - _In_opt_ HANDLE RootDirectoryHandle, - _In_ PUNICODE_STRING DirectoryName, - _In_ ACCESS_MASK DesiredAccess); - -NTSTATUS ntsupOpenDirectory( - _Out_ PHANDLE DirectoryHandle, - _In_opt_ HANDLE RootDirectoryHandle, - _In_ LPCWSTR DirectoryName, - _In_ ACCESS_MASK DesiredAccess); - -BOOL ntsupQueryProcessName( - _In_ ULONG_PTR dwProcessId, - _In_ PVOID ProcessList, - _Inout_ LPWSTR Buffer, - _In_ DWORD ccBuffer); - -BOOL ntsupQueryProcessEntryById( - _In_ HANDLE UniqueProcessId, - _In_ PVOID ProcessList, - _Out_ PSYSTEM_PROCESS_INFORMATION* Entry); - -NTSTATUS ntsupQueryProcessImageFileNameByProcessId( - _In_ HANDLE UniqueProcessId, - _Out_ PUNICODE_STRING ProcessImageFileName, - _In_ PNTSUPMEMALLOC AllocMem, - _In_ PNTSUPMEMFREE FreeMem); - -NTSTATUS ntsupQuerySystemObjectInformationVariableSize( - _In_ PFN_NTQUERYROUTINE QueryRoutine, - _In_opt_ HANDLE ObjectHandle, - _In_ DWORD InformationClass, - _Out_ PVOID* Buffer, - _Out_opt_ PULONG ReturnLength, - _In_ PNTSUPMEMALLOC AllocMem, - _In_ PNTSUPMEMFREE FreeMem); - -BOOLEAN ntsupQueryVsmProtectionInformation( - _Out_ PBOOLEAN pbDmaProtectionsAvailable, - _Out_ PBOOLEAN pbDmaProtectionsInUse, - _Out_ PBOOLEAN pbHardwareMbecAvailable, - _Out_ PBOOLEAN pbApicVirtualizationAvailable); - -BOOLEAN ntsupQueryHVCIState( - _Out_ PBOOLEAN pbHVCIEnabled, - _Out_ PBOOLEAN pbHVCIStrictMode, - _Out_ PBOOLEAN pbHVCIIUMEnabled); - -PVOID ntsupLookupImageSectionByName( - _In_ CHAR* SectionName, - _In_ ULONG SectionNameLength, - _In_ PVOID DllBase, - _Out_ PULONG SectionSize); - -PVOID ntsupFindPattern( - _In_ CONST PBYTE Buffer, - _In_ SIZE_T BufferSize, - _In_ CONST PBYTE Pattern, - _In_ SIZE_T PatternSize); - -DWORD ntsupFindPatternEx( - _In_ PATTERN_SEARCH_PARAMS * SearchParams); - -NTSTATUS ntsupOpenProcess( - _In_ HANDLE UniqueProcessId, - _In_ ACCESS_MASK DesiredAccess, - _Out_ PHANDLE ProcessHandle); - -NTSTATUS ntsupOpenThread( - _In_ PCLIENT_ID ClientId, - _In_ ACCESS_MASK DesiredAccess, - _Out_ PHANDLE ThreadHandle); - -NTSTATUS ntsupCICustomKernelSignersAllowed( - _Out_ PBOOLEAN bAllowed); - -NTSTATUS ntsupPrivilegeEnabled( - _In_ HANDLE ClientToken, - _In_ ULONG Privilege, - _Out_ LPBOOL pfResult); - -LPWSTR ntsupQueryEnvironmentVariableOffset( - _In_ PUNICODE_STRING Value); - -DWORD ntsupExpandEnvironmentStrings( - _In_ LPCWSTR lpSrc, - _Out_writes_to_opt_(nSize, return) LPWSTR lpDst, - _In_ DWORD nSize); - -NTSTATUS ntsupIsLocalSystem( - _Out_ PBOOL pbResult); - -NTSTATUS ntsupIsUserHasInteractiveSid( - _In_ HANDLE hToken, - _Out_ PBOOL pbInteractiveSid); - -BOOL ntsupGetProcessElevationType( - _In_opt_ HANDLE ProcessHandle, - _Out_ TOKEN_ELEVATION_TYPE * lpType); - -NTSTATUS ntsupIsProcessElevated( - _In_ ULONG ProcessId, - _Out_ PBOOL Elevated); - -VOID ntsupPurgeSystemCache( - VOID); - -PWSTR ntsupGetSystemRoot( - VOID); - -NTSTATUS ntsupGetProcessDebugObject( - _In_ HANDLE ProcessHandle, - _Out_ PHANDLE DebugObjectHandle); - -PBYTE ntsupQueryResourceData( - _In_ ULONG_PTR ResourceId, - _In_ PVOID DllHandle, - _In_ PULONG DataSize); - -NTSTATUS ntsupEnableWow64Redirection( - _In_ BOOLEAN bEnable); - -BOOLEAN ntsupIsKdEnabled( - _Out_opt_ PBOOLEAN DebuggerAllowed, - _Out_opt_ PBOOLEAN DebuggerNotPresent); - -BOOLEAN ntsupIsObjectExists( - _In_ LPCWSTR RootDirectory, - _In_ LPCWSTR ObjectName); - -BOOLEAN ntsupUserIsFullAdmin( - VOID); - -NTSTATUS ntsupDuplicateUnicodeString( - _In_ PCUNICODE_STRING SourceString, - _Out_ PUNICODE_STRING DestinationString); - -NTSTATUS ntsupDuplicateAnsiString( - _In_ PCANSI_STRING SourceString, - _Out_ PANSI_STRING DestinationString); - -NTSTATUS ntsupHashImageSections( - _In_ PVOID ImageBase, - _In_ SIZE_T ImageSize, - _Out_writes_bytes_(HashBufferSize) PBYTE HashBuffer, - _In_ SIZE_T HashBufferSize, - _In_ NTSUP_IMAGE_TYPE ImageType); + typedef struct _OBJSCANPARAM { + PCWSTR Buffer; + ULONG BufferSize; + } OBJSCANPARAM, * POBJSCANPARAM; + + typedef NTSTATUS(NTAPI* PENUMOBJECTSCALLBACK)( + _In_ POBJECT_DIRECTORY_INFORMATION Entry, + _In_opt_ PVOID CallbackParam); + + typedef BOOL(CALLBACK* pfnPatternSearchCallback)( + _In_ PBYTE Buffer, + _In_ ULONG PatternSize, + _In_opt_ PVOID CallbackContext + ); + + typedef struct _PATTERN_SEARCH_PARAMS { + PBYTE Buffer; + DWORD BufferSize; + PBYTE Pattern; + DWORD PatternSize; + PBYTE Mask; + pfnPatternSearchCallback Callback; + PVOID CallbackContext; + } PATTERN_SEARCH_PARAMS, * PPATTERN_SEARCH_PARAMS; + + typedef enum _NTSUP_IMAGE_TYPE { + ImageTypeRaw, // Raw file mapping (CreateFileMapping) + ImageTypeLoaded // Loaded module (PEB/LdrEntry) + } NTSUP_IMAGE_TYPE; + + typedef struct _NTSUP_SHA256_CTX { + ULONG State[8]; + ULONG64 BitCount; + UCHAR Buffer[64]; + } NTSUP_SHA256_CTX, * PNTSUP_SHA256_CTX; + + VOID ntsupSha256Init( + _Out_ PNTSUP_SHA256_CTX Ctx); + + VOID ntsupSha256Update( + _Inout_ PNTSUP_SHA256_CTX Ctx, + _In_reads_bytes_(Length) const UCHAR* Data, + _In_ SIZE_T Length); + + VOID ntsupSha256Final( + _Inout_ PNTSUP_SHA256_CTX Ctx, + _Out_writes_bytes_all_(32) UCHAR Digest[32]); + + // + // Ronova requires get rid of minirtl. + // + FORCEINLINE INT ntsupHexDigitToInt( + _In_ UINT ch + ) + { + if ((ch >= '0') && (ch <= '9')) + return (INT)(ch - '0'); + + ch = (UINT)((ch >= 'A' && ch <= 'Z') ? (ch + ('a' - 'A')) : ch); + + if ((ch >= 'a') && (ch <= 'f')) + return (INT)(ch - 'a' + 10); + + return -1; + } + + FORCEINLINE BOOLEAN ntsupIsDigitA( + _In_ CHAR Ch + ) + { + return (BOOLEAN)(Ch >= '0' && Ch <= '9'); + } + + FORCEINLINE BOOLEAN ntsupIsDigitW( + _In_ WCHAR Ch + ) + { + return (BOOLEAN)(Ch >= L'0' && Ch <= L'9'); + } + + // + // Minirtl section START + // + FORCEINLINE CHAR ntsupLowerCharA( + _In_ CHAR c + ) + { + if ((c >= 'A') && (c <= 'Z')) + return c + 0x20; + else + return c; + } + + FORCEINLINE WCHAR ntsupLowerCharW( + _In_ WCHAR c + ) + { + if ((c >= L'A') && (c <= L'Z')) + return c + 0x20; + else + return c; + } + + LPWSTR ntsupStrChrW( + _In_z_ LPCWSTR String, + _In_ WCHAR Character); + LPSTR ntsupStrChrA( + _In_z_ LPCSTR String, + _In_ CHAR Character); + + SIZE_T ntsupStrLenA( + _In_opt_ LPCSTR String); + SIZE_T ntsupStrLenW( + _In_opt_ LPCWSTR String); + + INT ntsupStrCmpA( + _In_opt_ LPCSTR String1, + _In_opt_ LPCSTR String2); + INT ntsupStrCmpW( + _In_opt_ LPCWSTR String1, + _In_opt_ LPCWSTR String2); + + INT ntsupStrCmpIA( + _In_opt_ LPCSTR String1, + _In_opt_ LPCSTR String2); + INT ntsupStrCmpIW( + _In_opt_ LPCWSTR String1, + _In_opt_ LPCWSTR String2); + + LPSTR ntsupStrCopyA( + _Out_writes_z_(_String_length_(Source) + 1) LPSTR Destination, + _In_z_ LPCSTR Source); + LPWSTR ntsupStrCopyW( + _Out_writes_z_(_String_length_(Source) + 1) LPWSTR Destination, + _In_z_ LPCWSTR Source); + + LPSTR ntsupStrNCopyA( + _Out_writes_z_(DestinationCount) LPSTR Destination, + _In_ SIZE_T DestinationCount, + _In_reads_(SourceCount) LPCSTR Source, + _In_ SIZE_T SourceCount); + LPWSTR ntsupStrNCopyW( + _Out_writes_z_(DestinationCount) LPWSTR Destination, + _In_ SIZE_T DestinationCount, + _In_reads_(SourceCount) LPCWSTR Source, + _In_ SIZE_T SourceCount); + + INT ntsupStrNCmpA( + _In_opt_ LPCSTR String1, + _In_opt_ LPCSTR String2, + _In_ SIZE_T Count); + INT ntsupStrNCmpW( + _In_opt_ LPCWSTR String1, + _In_opt_ LPCWSTR String2, + _In_ SIZE_T Count); + + LPCSTR ntsupStrStrIA( + _In_ LPCSTR String, + _In_ LPCSTR SubString); + LPCWSTR ntsupStrStrIW( + _In_ LPCWSTR String, + _In_ LPCWSTR SubString); + + LPCSTR ntsupStrStrA( + _In_ LPCSTR String, + _In_ LPCSTR SubString); + LPCWSTR ntsupStrStrW( + _In_ LPCWSTR String, + _In_ LPCWSTR SubString); + + LPSTR ntsupStrCatA( + _Inout_ LPSTR Destination, + _In_ LPCSTR Source); + LPWSTR ntsupStrCatW( + _Inout_ LPWSTR Destination, + _In_ LPCWSTR Source); + + LPSTR ntsupStrCatExA( + _Inout_updates_z_(DestinationCount) LPSTR Destination, + _In_ SIZE_T DestinationCount, + _In_ LPCSTR Source); + LPWSTR ntsupStrCatExW( + _Inout_updates_z_(DestinationCount) LPWSTR Destination, + _In_ SIZE_T DestinationCount, + _In_ LPCWSTR Source); + + BOOL ntsupStrToUInt64A( + _In_ LPCSTR String, + _Out_ PULONGLONG Value); + BOOL ntsupStrToUInt64W( + _In_ LPCWSTR String, + _Out_ PULONGLONG Value); + + SIZE_T ntsupUInt64ToStrW( + _In_ ULONGLONG Value, + _Out_writes_z_(BufferCount) LPWSTR Buffer, + _In_ SIZE_T BufferCount); + SIZE_T ntsupUInt64ToStrA( + _In_ ULONGLONG Value, + _Out_writes_z_(BufferCount) LPSTR Buffer, + _In_ SIZE_T BufferCount); + + ULONGLONG ntsupHexToUInt64A( + _In_opt_ LPCSTR String); + ULONGLONG ntsupHexToUInt64W( + _In_opt_ LPCWSTR String); + +#ifdef _UNICODE +#define ntsupLowerChar ntsupLowerCharW +#define ntsupStrChr ntsupStrChrW +#define ntsupStrLen ntsupStrLenW +#define ntsupStrCmp ntsupStrCmpW +#define ntsupStrCmpI ntsupStrCmpIW +#define ntsupStrCopy ntsupStrCopyW +#define ntsupStrNCopy ntsupStrNCopyW +#define ntsupStrNCmp ntsupStrNCmpW +#define ntsupStrStrI ntsupStrStrIW +#define ntsupStrStr ntsupStrStrW +#define ntsupStrCat ntsupStrCatW +#define ntsupStrCatEx ntsupStrCatExW +#define ntsupStrToUInt64 ntsupStrToUInt64W +#define ntsupUInt64ToStr ntsupUInt64ToStrW +#define ntsupHexToUInt64 ntsupHexToUInt64W +#define ntsupIsDigit ntsupIsDigitW +#else +#define ntsupLowerChar ntsupLowerCharA +#define ntsupStrChr ntsupStrChrA +#define ntsupStrLen ntsupStrLenA +#define ntsupStrCmp ntsupStrCmpA +#define ntsupStrCmpI ntsupStrCmpIA +#define ntsupStrCopy ntsupStrCopyA +#define ntsupStrNCopy ntsupStrNCopyA +#define ntsupStrNCmp ntsupStrNCmpA +#define ntsupStrStrI ntsupStrStrIA +#define ntsupStrStr ntsupStrStrA +#define ntsupStrCat ntsupStrCatA +#define ntsupStrCatEx ntsupStrCatExA +#define ntsupStrToUInt64 ntsupStrToUInt64A +#define ntsupUInt64ToStr ntsupUInt64ToStrA +#define ntsupHexToUInt64 ntsupHexToUInt64A +#define ntsupIsDigit ntsupIsDigitA +#endif + + // + // Minirtl section END + // + + PVOID NTAPI ntsupHeapAlloc( + _In_ SIZE_T Size); + + PVOID NTAPI ntsupHeapReAlloc( + _In_ PVOID BaseAddress, + _In_ SIZE_T Size); + + BOOL NTAPI ntsupHeapFree( + _In_ PVOID BaseAddress); + + SIZE_T NTAPI ntsupHeapSize( + _In_ PVOID BaseAddress); + + BOOL NTAPI ntsupHeapValidate( + _In_ PVOID BaseAddress); + + SIZE_T NTAPI ntsupHeapCompact( + VOID); + + BOOL NTAPI ntsupHeapLock( + VOID); + + BOOL NTAPI ntsupHeapUnlock( + VOID); + + BOOLEAN NTAPI ntsupIsAddressValid( + _In_ PVOID Address, + _In_ SIZE_T Size); + + PVOID NTAPI ntsupVirtualAllocEx( + _In_ SIZE_T Size, + _In_ ULONG AllocationType, + _In_ ULONG Protect); + + PVOID NTAPI ntsupVirtualAlloc( + _In_ SIZE_T Size); + + BOOL NTAPI ntsupVirtualFree( + _In_ PVOID Memory); + + BOOL NTAPI ntsupVirtualLock( + _In_ LPVOID lpAddress, + _In_ SIZE_T dwSize); + + BOOL NTAPI ntsupVirtualUnlock( + _In_ LPVOID lpAddress, + _In_ SIZE_T dwSize); + + SIZE_T NTAPI ntsupWriteBufferToFile( + _In_ PCWSTR FileName, + _In_ PVOID Buffer, + _In_ SIZE_T Size, + _In_ BOOL Flush, + _In_ BOOL Append, + _Out_opt_ NTSTATUS* Result); + + PVOID NTAPI ntsupGetModuleEntryByAddress( + _In_ PRTL_PROCESS_MODULES ModulesList, + _In_ PVOID Address); + + PVOID NTAPI ntsupFindModuleEntryByName( + _In_ PRTL_PROCESS_MODULES ModulesList, + _In_ LPCSTR ModuleName); + + PVOID NTAPI ntsupFindModuleEntryByName_U( + _In_ PRTL_PROCESS_MODULES ModulesList, + _In_ LPCWSTR ModuleName); + + BOOL NTAPI ntsupFindModuleEntryByAddress( + _In_ PRTL_PROCESS_MODULES ModulesList, + _In_ PVOID Address, + _Out_ PULONG ModuleIndex); + + PVOID NTAPI ntsupFindModuleNameByAddress( + _In_ PRTL_PROCESS_MODULES ModulesList, + _In_ PVOID Address, + _Inout_ LPWSTR Buffer, + _In_ DWORD ccBuffer); + + NTSTATUS NTAPI ntsupConvertToUnicode( + _In_ LPCSTR AnsiString, + _Inout_ PUNICODE_STRING UnicodeString); + + NTSTATUS NTAPI ntsupConvertToAnsi( + _In_ LPCWSTR UnicodeString, + _Inout_ PANSI_STRING AnsiString); + + NTSTATUS NTAPI ntsupSetPrivilege( + _In_ HANDLE TokenHandle, + _In_ DWORD Privilege, + _In_ BOOLEAN Enable, + _Out_opt_ PTOKEN_PRIVILEGES PreviousState, + _Out_opt_ PULONG ReturnLength); + + BOOLEAN NTAPI ntsupEnablePrivilege( + _In_ DWORD Privilege, + _In_ BOOLEAN Enable); + + HANDLE NTAPI ntsupGetCurrentProcessToken( + VOID); + + ULONG_PTR NTAPI ntsupQuerySystemRangeStart( + VOID); + + BOOLEAN NTAPI ntsupQueryUserModeAccessibleRange( + _Out_ PULONG_PTR MinimumUserModeAddress, + _Out_ PULONG_PTR MaximumUserModeAddress); + + BOOL NTAPI ntsupIsProcess32bit( + _In_ HANDLE hProcess); + + PVOID NTAPI ntsupGetLoadedModulesListEx( + _In_ BOOL ExtendedOutput, + _Out_opt_ PULONG ReturnLength, + _In_ PNTSUPMEMALLOC AllocMem, + _In_ PNTSUPMEMFREE FreeMem); + + PVOID NTAPI ntsupGetLoadedModulesList( + _Out_opt_ PULONG ReturnLength); + + PVOID NTAPI ntsupGetLoadedModulesList2( + _Out_opt_ PULONG ReturnLength); + + PVOID NTAPI ntsupGetSystemInfoEx( + _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, + _Out_opt_ PULONG ReturnLength, + _In_ PNTSUPMEMALLOC AllocMem, + _In_ PNTSUPMEMFREE FreeMem); + + PVOID NTAPI ntsupGetSystemInfo( + _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, + _Out_opt_ PULONG ReturnLength); + + NTSTATUS NTAPI ntsupEnumSystemObjects( + _In_opt_ LPCWSTR RootDirectory, + _In_opt_ HANDLE RootDirectoryHandle, + _In_ PENUMOBJECTSCALLBACK CallbackProc, + _In_opt_ PVOID CallbackParam); + + BOOL NTAPI ntsupResolveSymbolicLink( + _In_opt_ HANDLE RootDirectoryHandle, + _In_ PUNICODE_STRING LinkName, + _Inout_ LPWSTR Buffer, + _In_ DWORD cbBuffer); + + BOOL NTAPI ntsupQueryThreadWin32StartAddress( + _In_ HANDLE ThreadHandle, + _Out_opt_ PULONG_PTR Win32StartAddress); + + NTSTATUS NTAPI ntsupQueryProcessCommandLine( + _In_ HANDLE ProcessHandle, + _Out_ PUNICODE_STRING CommandLine, + _In_ PNTSUPMEMALLOC AllocMem, + _In_ PNTSUPMEMFREE FreeMem); + + _Success_(return) + NTSTATUS NTAPI ntsupOpenDirectoryEx( + _Out_ PHANDLE DirectoryHandle, + _In_opt_ HANDLE RootDirectoryHandle, + _In_ PUNICODE_STRING DirectoryName, + _In_ ACCESS_MASK DesiredAccess); + + NTSTATUS NTAPI ntsupOpenDirectory( + _Out_ PHANDLE DirectoryHandle, + _In_opt_ HANDLE RootDirectoryHandle, + _In_ LPCWSTR DirectoryName, + _In_ ACCESS_MASK DesiredAccess); + + BOOL NTAPI ntsupQueryProcessName( + _In_ ULONG_PTR dwProcessId, + _In_ PVOID ProcessList, + _Inout_ LPWSTR Buffer, + _In_ DWORD ccBuffer); + + BOOL NTAPI ntsupQueryProcessEntryById( + _In_ HANDLE UniqueProcessId, + _In_ PVOID ProcessList, + _Out_ PSYSTEM_PROCESS_INFORMATION* Entry); + + NTSTATUS NTAPI ntsupQueryProcessImageFileNameByProcessId( + _In_ HANDLE UniqueProcessId, + _Out_ PUNICODE_STRING ProcessImageFileName, + _In_ PNTSUPMEMALLOC AllocMem, + _In_ PNTSUPMEMFREE FreeMem); + + NTSTATUS NTAPI ntsupQuerySystemObjectInformationVariableSize( + _In_ PFN_NTQUERYROUTINE QueryRoutine, + _In_opt_ HANDLE ObjectHandle, + _In_ DWORD InformationClass, + _Out_ PVOID* Buffer, + _Out_opt_ PULONG ReturnLength, + _In_ PNTSUPMEMALLOC AllocMem, + _In_ PNTSUPMEMFREE FreeMem); + + NTSTATUS NTAPI ntsupQuerySystemObjectInformationVariableSizeEx( + _In_ PFN_NTQUERYROUTINE QueryRoutine, + _In_opt_ HANDLE ObjectHandle, + _In_ DWORD InformationClass, + _Out_ PVOID* Buffer, + _Out_opt_ PULONG ReturnLength, + _In_ ULONG InitialBufferSize, + _In_ PNTSUPMEMALLOC AllocMem, + _In_ PNTSUPMEMFREE FreeMem); + + BOOLEAN NTAPI ntsupQueryVsmProtectionInformation( + _Out_ PBOOLEAN pbDmaProtectionsAvailable, + _Out_ PBOOLEAN pbDmaProtectionsInUse, + _Out_ PBOOLEAN pbHardwareMbecAvailable, + _Out_ PBOOLEAN pbApicVirtualizationAvailable); + + BOOLEAN NTAPI ntsupQueryVBSState( + _Out_ PBOOLEAN pbVBSRunning, + _Out_ PBOOLEAN pbHVCIEnabled, + _Out_ PBOOLEAN pbHVCIStrictMode); + + PVOID NTAPI ntsupLookupImageSectionByNameEx( + _In_ CHAR* SectionName, + _In_ ULONG SectionNameLength, + _In_ PVOID DllBase, + _In_ SIZE_T ImageSize, + _Out_opt_ PULONG SectionSize); + + PVOID NTAPI ntsupLookupImageSectionByName( + _In_ CHAR* SectionName, + _In_ ULONG SectionNameLength, + _In_ PVOID DllBase, + _Out_ PULONG SectionSize); + + PVOID NTAPI ntsupFindPattern( + _In_ CONST PBYTE Buffer, + _In_ SIZE_T BufferSize, + _In_ CONST PBYTE Pattern, + _In_ SIZE_T PatternSize); + + DWORD NTAPI ntsupFindPatternEx( + _In_ PATTERN_SEARCH_PARAMS* SearchParams); + + NTSTATUS NTAPI ntsupOpenProcess( + _In_ HANDLE UniqueProcessId, + _In_ ACCESS_MASK DesiredAccess, + _Out_ PHANDLE ProcessHandle); + + NTSTATUS NTAPI ntsupOpenThreadEx( + _In_ PCLIENT_ID ClientId, + _In_ ACCESS_MASK DesiredAccess, + _In_ ULONG ObjectAttributes, + _Out_ PHANDLE ThreadHandle); + + NTSTATUS NTAPI ntsupOpenThread( + _In_ PCLIENT_ID ClientId, + _In_ ACCESS_MASK DesiredAccess, + _Out_ PHANDLE ThreadHandle); + + NTSTATUS NTAPI ntsupCICustomKernelSignersAllowed( + _Out_ PBOOLEAN bAllowed); + + NTSTATUS NTAPI ntsupPrivilegeEnabled( + _In_ HANDLE ClientToken, + _In_ ULONG Privilege, + _Out_ LPBOOL pfResult); + + LPWSTR NTAPI ntsupQueryEnvironmentVariableOffset( + _In_ PUNICODE_STRING Value); + + BOOLEAN NTAPI ntsupSetEnvironmentVariable( + _In_ LPCWSTR Name, + _In_opt_ LPCWSTR Value); + + DWORD NTAPI ntsupExpandEnvironmentStrings( + _In_ LPCWSTR lpSrc, + _Out_writes_to_opt_(nSize, return) LPWSTR lpDst, + _In_ DWORD nSize); + + NTSTATUS NTAPI ntsupIsLocalSystem( + _Out_ PBOOL pbResult); + + NTSTATUS NTAPI ntsupIsUserHasInteractiveSid( + _In_ HANDLE hToken, + _Out_ PBOOL pbInteractiveSid); + + BOOL NTAPI ntsupGetProcessElevationType( + _In_opt_ HANDLE ProcessHandle, + _Out_ TOKEN_ELEVATION_TYPE* lpType); + + NTSTATUS NTAPI ntsupIsProcessElevated( + _In_ ULONG ProcessId, + _Out_ PBOOL Elevated); + + VOID NTAPI ntsupPurgeSystemCache( + VOID); + + PWSTR NTAPI ntsupGetSystemRoot( + VOID); + + NTSTATUS NTAPI ntsupGetProcessDebugObject( + _In_ HANDLE ProcessHandle, + _Out_ PHANDLE DebugObjectHandle); + + PBYTE NTAPI ntsupQueryResourceData( + _In_ ULONG_PTR ResourceId, + _In_ PVOID DllHandle, + _In_ PULONG DataSize); + + NTSTATUS NTAPI ntsupEnableWow64Redirection( + _In_ BOOLEAN bEnable); + + BOOLEAN NTAPI ntsupIsKdEnabled( + _Out_opt_ PBOOLEAN DebuggerAllowed, + _Out_opt_ PBOOLEAN DebuggerNotPresent); + + BOOLEAN NTAPI ntsupIsObjectExists( + _In_ LPCWSTR RootDirectory, + _In_ LPCWSTR ObjectName); + + BOOLEAN NTAPI ntsupUserIsFullAdmin( + VOID); + + NTSTATUS NTAPI ntsupDuplicateUnicodeString( + _In_ PCUNICODE_STRING SourceString, + _Out_ PUNICODE_STRING DestinationString); + + NTSTATUS NTAPI ntsupDuplicateAnsiString( + _In_ PCANSI_STRING SourceString, + _Out_ PANSI_STRING DestinationString); + + NTSTATUS NTAPI ntsupHashImageSections( + _In_ PVOID ImageBase, + _In_ SIZE_T ImageSize, + _Out_writes_bytes_(HashBufferSize) PBYTE HashBuffer, + _In_ SIZE_T HashBufferSize, + _In_ NTSUP_IMAGE_TYPE ImageType); + + PRTL_DEBUG_INFORMATION NTAPI ntsupQueryProcessDebugInformation( + _In_ HANDLE ProcessId, + _In_ ULONG Flags); + + VOID NTAPI ntsupFreeProcessDebugInformation( + _In_opt_ PRTL_DEBUG_INFORMATION DebugInformation); #define ntsupQuerySecurityInformation(\ ObjectHandle, SecurityInformationClass, Buffer, ReturnLength, AllocMem, FreeMem) \ @@ -409,6 +678,12 @@ ntsupQuerySystemObjectInformationVariableSize((PFN_NTQUERYROUTINE)NtQueryObject, ObjectHandle, ObjectInformationClass, (PVOID*)Buffer, ReturnLength, \ (PNTSUPMEMALLOC)AllocMem, (PNTSUPMEMFREE)FreeMem) +#define ntsupQueryObjectInformationEx(\ + ObjectHandle, ObjectInformationClass, Buffer, ReturnLength, InitialBufferSize, AllocMem, FreeMem) \ +ntsupQuerySystemObjectInformationVariableSizeEx((PFN_NTQUERYROUTINE)NtQueryObject, \ + ObjectHandle, ObjectInformationClass, (PVOID*)Buffer, ReturnLength, InitialBufferSize, \ + (PNTSUPMEMALLOC)AllocMem, (PNTSUPMEMFREE)FreeMem) + #define ntsupQueryThreadInformation(\ ThreadHandle, ThreadInformationClass, Buffer, ReturnLength, AllocMem, FreeMem) \ ntsupQuerySystemObjectInformationVariableSize((PFN_NTQUERYROUTINE)NtQueryInformationThread, \ diff --git a/Source/WinObjEx64/Resource.rc b/Source/WinObjEx64/Resource.rc index 4f66c8e..a5d735d 100644 Binary files a/Source/WinObjEx64/Resource.rc and b/Source/WinObjEx64/Resource.rc differ diff --git a/Source/WinObjEx64/WinObjEx64.vcxproj b/Source/WinObjEx64/WinObjEx64.vcxproj index a716667..b453c38 100644 --- a/Source/WinObjEx64/WinObjEx64.vcxproj +++ b/Source/WinObjEx64/WinObjEx64.vcxproj @@ -149,6 +149,7 @@ false rsrc\obex.manifest true + true false @@ -178,6 +179,7 @@ false rsrc\obex.manifest true + true false @@ -230,6 +232,7 @@ false rsrc\obex.manifest true + true false @@ -279,6 +282,7 @@ false rsrc\obex.manifest true + true false @@ -331,6 +335,7 @@ false rsrc\obex.manifest true + true false @@ -418,7 +423,6 @@ - @@ -473,7 +477,6 @@ - diff --git a/Source/WinObjEx64/WinObjEx64.vcxproj.filters b/Source/WinObjEx64/WinObjEx64.vcxproj.filters index b42f146..202c545 100644 --- a/Source/WinObjEx64/WinObjEx64.vcxproj.filters +++ b/Source/WinObjEx64/WinObjEx64.vcxproj.filters @@ -264,9 +264,6 @@ Minirtl - - Source Files\tests - Source Files\tests @@ -418,9 +415,6 @@ Minirtl - - Source Files\tests - Source Files\tests diff --git a/Source/WinObjEx64/aboutDlg.c b/Source/WinObjEx64/aboutDlg.c index ac5d7c2..5c8eb98 100644 --- a/Source/WinObjEx64/aboutDlg.c +++ b/Source/WinObjEx64/aboutDlg.c @@ -193,7 +193,7 @@ VOID AboutDialogInit( } g_kdctx.IsSecureBoot = bSecureBoot; - if (supQueryHVCIState(&bHVCIEnabled, &bHVCIStrict, &bHVCIIUMEnabled)) { + if (supQueryVBSState(&bHVCIIUMEnabled, &bHVCIEnabled, &bHVCIStrict)) { if (bHVCIEnabled) { _strcat(szBuffer, TEXT(", HVCI")); if (bHVCIStrict) diff --git a/Source/WinObjEx64/extras/extrasCallbacks.c b/Source/WinObjEx64/extras/extrasCallbacks.c index d6275c0..9c76173 100644 --- a/Source/WinObjEx64/extras/extrasCallbacks.c +++ b/Source/WinObjEx64/extras/extrasCallbacks.c @@ -4,9 +4,9 @@ * * TITLE: EXTRASCALLBACKS.C * -* VERSION: 2.11 +* VERSION: 2.12 * -* DATE: 11 Jul 2026 +* DATE: 26 Jul 2026 * * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF * ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED @@ -1067,10 +1067,11 @@ OBEX_FINDCALLBACK_ROUTINE(FindCiCallbacks) // // Locate PAGE image section as required variable is always in PAGE. // - SectionBase = supLookupImageSectionByName( + SectionBase = supLookupImageSectionByNameEx( PAGE_SECTION, PAGE_SECTION_LENGTH, g_kdctx.NtOsImageMap, + g_kdctx.NtOsImageSize, &SectionSize); if ((SectionBase == 0) || (SectionSize == 0)) @@ -3222,10 +3223,11 @@ OBEX_FINDCALLBACK_ROUTINE(FindEmpCallbackListHead) // // Locate PAGE image section as required variable is always in PAGE. // - SectionBase = supLookupImageSectionByName( + SectionBase = supLookupImageSectionByNameEx( PAGE_SECTION, PAGE_SECTION_LENGTH, g_kdctx.NtOsImageMap, + g_kdctx.NtOsImageSize, &SectionSize); if ((SectionBase == 0) || (SectionSize == 0)) diff --git a/Source/WinObjEx64/extras/extrasSSDT.c b/Source/WinObjEx64/extras/extrasSSDT.c index 002cb90..806f0de 100644 --- a/Source/WinObjEx64/extras/extrasSSDT.c +++ b/Source/WinObjEx64/extras/extrasSSDT.c @@ -4,9 +4,9 @@ * * TITLE: EXTRASSSDT.C * -* VERSION: 2.11 +* VERSION: 2.12 * -* DATE: 12 Jul 2026 +* DATE: 26 Jul 2026 * * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF * ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED @@ -206,6 +206,7 @@ BOOL SdtListCreateTable( { if (!kdFindKiServiceTable( (ULONG_PTR)g_kdctx.NtOsImageMap, + g_kdctx.NtOsImageSize, (ULONG_PTR)g_kdctx.NtOsBase, &g_kdctx.Data->KeServiceDescriptorTable)) { @@ -579,7 +580,7 @@ BOOL SdtListCreateTableShadow( lpFunctionName = tableEntry->Name; tableEntry->KernelStubAddress = g_SDTCtx.W32pServiceTableUserBase[i]; - functionPtr = (PBYTE)g_SDTCtx.KernelModule + tableEntry->KernelStubAddress; + functionPtr = (PBYTE)g_SDTCtx.MappedKernelModule + tableEntry->KernelStubAddress; tableEntry->KernelStubAddress += g_SDTCtx.KernelBaseAddress; sdtFn.ServiceName = tableEntry->Name; diff --git a/Source/WinObjEx64/kldbg.c b/Source/WinObjEx64/kldbg.c index 3cf5a90..9204c1f 100644 --- a/Source/WinObjEx64/kldbg.c +++ b/Source/WinObjEx64/kldbg.c @@ -4,9 +4,9 @@ * * TITLE: KLDBG.C, based on KDSubmarine by Evilcry * -* VERSION: 2.10 +* VERSION: 2.12 * -* DATE: 27 Feb 2026 +* DATE: 25 Jul 2026 * * MINIMUM SUPPORTED OS WINDOWS 7 * @@ -1295,7 +1295,8 @@ PVOID ObFindPrivateNamespaceLookupTable2( ESERVERSILO_GLOBALS PspHostSiloGlobals; - HMODULE hNtOs = (HMODULE)Context->NtOsImageMap; + HMODULE hLoadedNtOs = (HMODULE)Context->NtOsImageMap; + ULONG hLoadedNtOsSize = Context->NtOsImageSize; do { @@ -1319,9 +1320,10 @@ PVOID ObFindPrivateNamespaceLookupTable2( // // Locate .text image section. // - SectionBase = supLookupImageSectionByName(TEXT_SECTION, + SectionBase = supLookupImageSectionByNameEx(TEXT_SECTION, TEXT_SECTION_LENGTH, - (PVOID)hNtOs, + (PVOID)hLoadedNtOs, + hLoadedNtOsSize, &SectionSize); if (SectionBase == NULL || SectionSize == 0) @@ -1333,7 +1335,7 @@ PVOID ObFindPrivateNamespaceLookupTable2( // if (g_NtBuildNumber >= NT_WIN10_REDSTONE4) { - ptrCode = (PBYTE)GetProcAddress(hNtOs, "PsGetServerSiloServiceSessionId"); + ptrCode = (PBYTE)GetProcAddress(hLoadedNtOs, "PsGetServerSiloServiceSessionId"); } else { @@ -1369,7 +1371,7 @@ PVOID ObFindPrivateNamespaceLookupTable2( // Find address to PspHostSiloGlobals in code. // varAddress = ObFindAddress((ULONG_PTR)Context->NtOsBase, - (ULONG_PTR)hNtOs, + (ULONG_PTR)hLoadedNtOs, IL_PspHostSiloGlobals, ptrCode, DA_ScanBytesPNSVariant1, @@ -1427,7 +1429,8 @@ PVOID ObFindPrivateNamespaceLookupTable( PVOID SectionBase; ULONG SectionSize = 0; - HMODULE hNtOs = (HMODULE)Context->NtOsImageMap; + HMODULE hLoadedNtOs = (HMODULE)Context->NtOsImageMap; + ULONG hLoadedNtOsSize = Context->NtOsImageSize; if (g_NtBuildNumber > NT_WIN10_THRESHOLD2) return ObFindPrivateNamespaceLookupTable2(Context); @@ -1437,9 +1440,10 @@ PVOID ObFindPrivateNamespaceLookupTable( // // Locate PAGE image section. // - SectionBase = supLookupImageSectionByName(PAGE_SECTION, + SectionBase = supLookupImageSectionByNameEx(PAGE_SECTION, PAGE_SECTION_LENGTH, - (PVOID)hNtOs, + (PVOID)hLoadedNtOs, + hLoadedNtOsSize, &SectionSize); if ((SectionBase == 0) || (SectionSize == 0)) @@ -1467,7 +1471,7 @@ PVOID ObFindPrivateNamespaceLookupTable( break; Address = ObFindAddress((ULONG_PTR)Context->NtOsBase, - (ULONG_PTR)hNtOs, + (ULONG_PTR)hLoadedNtOs, IL_PspHostSiloGlobals, ptrCode, DA_ScanBytesPNSVariant2, @@ -1521,6 +1525,7 @@ PVOID ObGetCallbackBlockRoutine( */ BOOL kdpFindKiServiceTableByPattern( _In_ ULONG_PTR MappedImageBase, + _In_ ULONG MappedImageSize, _In_ ULONG_PTR KernelImageBase, _Out_ ULONG_PTR * Address ) @@ -1534,9 +1539,10 @@ BOOL kdpFindKiServiceTableByPattern( // // Locate .text image section. // - sectionBase = (ULONG_PTR)supLookupImageSectionByName(TEXT_SECTION, + sectionBase = (ULONG_PTR)supLookupImageSectionByNameEx(TEXT_SECTION, TEXT_SECTION_LENGTH, (PVOID)MappedImageBase, + MappedImageSize, §ionSize); if (sectionBase == 0) @@ -1589,6 +1595,7 @@ BOOL kdpFindKiServiceTableByPattern( */ BOOL kdFindKiServiceTable( _In_ ULONG_PTR MappedImageBase, + _In_ ULONG MappedImageSize, _In_ ULONG_PTR KernelImageBase, _Inout_ KSERVICE_TABLE_DESCRIPTOR * ServiceTable ) @@ -1622,7 +1629,9 @@ BOOL kdFindKiServiceTable( // if (varAddress == 0) { - if (!kdpFindKiServiceTableByPattern(MappedImageBase, + if (!kdpFindKiServiceTableByPattern( + MappedImageBase, + MappedImageSize, KernelImageBase, &varAddress)) { @@ -2945,6 +2954,7 @@ BOOL kdLoadNtKernelImage( { PUCHAR pModuleName; PRTL_PROCESS_MODULES pModulesList = NULL; + PLDR_DATA_TABLE_ENTRY pModuleEntry = NULL; WCHAR szFileName[(4 + MAX_PATH) * 2]; @@ -2976,16 +2986,16 @@ BOOL kdLoadNtKernelImage( DONT_RESOLVE_DLL_REFERENCES); if (Context->NtOsImageMap) { - - supLoadSymbolsForNtImage( - (PSYMCONTEXT)g_kdctx.NtOsSymContext, - szFileName, - Context->NtOsImageMap, - 0, - NULL); - + if (NT_SUCCESS(LdrFindEntryForAddress(Context->NtOsImageMap, &pModuleEntry))) { + Context->NtOsImageSize = pModuleEntry->SizeOfImage; + supLoadSymbolsForNtImage( + (PSYMCONTEXT)g_kdctx.NtOsSymContext, + szFileName, + Context->NtOsImageMap, + 0, + NULL); + } } - } return (Context->NtOsImageMap != NULL); @@ -3086,14 +3096,14 @@ BOOLEAN kdpQueryMmUnloadedDrivers( _In_ PKLDBGCONTEXT Context ) { - HMODULE hNtOs; + HMODULE hLoadedNtOs; ULONG_PTR NtOsBase, lookupAddress = 0; PBYTE ptrCode, sigPattern; PVOID SectionBase; ULONG SectionSize = 0; - ULONG sigSize; + ULONG sigSize, hLoadedNtOsSize; ULONG Index = 0, instLength = 0, tempOffset; LONG relativeValue = 0; @@ -3105,7 +3115,8 @@ BOOLEAN kdpQueryMmUnloadedDrivers( return TRUE; NtOsBase = (ULONG_PTR)g_kdctx.NtOsBase; - hNtOs = (HMODULE)g_kdctx.NtOsImageMap; + hLoadedNtOs = (HMODULE)g_kdctx.NtOsImageMap; + hLoadedNtOsSize = g_kdctx.NtOsImageSize; do { @@ -3129,9 +3140,10 @@ BOOLEAN kdpQueryMmUnloadedDrivers( // // Locate PAGE image section. // - SectionBase = supLookupImageSectionByName(PAGE_SECTION, + SectionBase = supLookupImageSectionByNameEx(PAGE_SECTION, PAGE_SECTION_LENGTH, - (PVOID)hNtOs, + (PVOID)hLoadedNtOs, + hLoadedNtOsSize, &SectionSize); if ((SectionBase == 0) || (SectionSize == 0)) diff --git a/Source/WinObjEx64/kldbg.h b/Source/WinObjEx64/kldbg.h index d080dba..95109df 100644 --- a/Source/WinObjEx64/kldbg.h +++ b/Source/WinObjEx64/kldbg.h @@ -1,12 +1,12 @@ /******************************************************************************* * -* (C) COPYRIGHT AUTHORS, 2015 - 2025 +* (C) COPYRIGHT AUTHORS, 2015 - 2026 * * TITLE: KLDBG.H * -* VERSION: 2.09 +* VERSION: 2.12 * -* DATE: 19 Aug 2025 +* DATE: 24 Jul 2026 * * Common header file for the Kernel Debugger Driver support. * @@ -263,8 +263,9 @@ typedef struct _KLDBGCONTEXT { PVOID NtOsBase; ULONG NtOsSize; - //ntoskrnl mapped image + //ntoskrnl mapped image and size PVOID NtOsImageMap; + ULONG NtOsImageSize; //system range start ULONG_PTR SystemRangeStart; @@ -577,6 +578,7 @@ PVOID kdQueryIopInvalidDeviceRequest( BOOL kdFindKiServiceTable( _In_ ULONG_PTR MappedImageBase, + _In_ ULONG MappedImageSize, _In_ ULONG_PTR KernelImageBase, _Inout_ KSERVICE_TABLE_DESCRIPTOR* ServiceTable); diff --git a/Source/WinObjEx64/main.c b/Source/WinObjEx64/main.c index 405a8c9..6ce7b8f 100644 --- a/Source/WinObjEx64/main.c +++ b/Source/WinObjEx64/main.c @@ -1071,11 +1071,8 @@ LRESULT CALLBACK MainWindowProc( } break; - case WM_CLOSE: - DestroyWindow(hwnd); - return TRUE; - case WM_DESTROY: + supWriteObexConfiguration(hwnd); PostQuitMessage(0); return 0; @@ -1511,6 +1508,7 @@ DWORD guiCreateMainWindowAndComponents( HIMAGELIST treeViewImages; INITCOMMONCONTROLSEX iccx; WNDCLASSEX wndClass; + POBEX_CONFIG pObexConfig; HINSTANCE hInstance = Globals->hInstance; WCHAR szWindowTitle[100]; @@ -1569,6 +1567,8 @@ DWORD guiCreateMainWindowAndComponents( _strcat(szWindowTitle, TEXT(" (Wine)")); } + pObexConfig = supGetParametersBlock(); + // // Create main window. // @@ -1577,10 +1577,10 @@ DWORD guiCreateMainWindowAndComponents( MAKEINTATOM(classAtom), szWindowTitle, WS_VISIBLE | WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, - CW_USEDEFAULT, - SCALE_DPI_VALUE(800, Globals->CurrentDPI), - SCALE_DPI_VALUE(600, Globals->CurrentDPI), + pObexConfig->X, + pObexConfig->Y, + SCALE_DPI_VALUE(pObexConfig->Width, Globals->CurrentDPI), + SCALE_DPI_VALUE(pObexConfig->Height, Globals->CurrentDPI), NULL, NULL, hInstance, diff --git a/Source/WinObjEx64/sup/sup.c b/Source/WinObjEx64/sup/sup.c index 5461d68..99fd50f 100644 --- a/Source/WinObjEx64/sup/sup.c +++ b/Source/WinObjEx64/sup/sup.c @@ -4,9 +4,9 @@ * * TITLE: SUP.C * -* VERSION: 2.11 +* VERSION: 2.12 * -* DATE: 11 Jul 2026 +* DATE: 28 Jul 2026 * * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF * ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED @@ -1128,37 +1128,17 @@ PVOID supGetTokenInfo( ) { PVOID Buffer = NULL; - ULONG returnLength = 0; - - if (ReturnLength) - *ReturnLength = 0; - NtQueryInformationToken(TokenHandle, + if (NT_SUCCESS(supQueryTokenInformation( + TokenHandle, TokenInformationClass, - NULL, - 0, - &returnLength); - - Buffer = supHeapAlloc((SIZE_T)returnLength); - if (Buffer) { - - if (NT_SUCCESS(NtQueryInformationToken(TokenHandle, - TokenInformationClass, - Buffer, - returnLength, - &returnLength))) - { - if (ReturnLength) - *ReturnLength = returnLength; - return Buffer; - } - else { - supHeapFree(Buffer); - return NULL; - } + &Buffer, + ReturnLength))) + { + return Buffer; } - return Buffer; + return NULL; } /* @@ -1223,24 +1203,6 @@ PVOID supGetSystemInfo( (PNTSUPMEMFREE)supHeapFree); } -/* -* supxFreeObjectTypes -* -* Purpose: -* -* Free object types memory callback. -* -*/ -BOOL CALLBACK supxFreeObjectTypes( - _In_opt_ PVOID Context -) -{ - if (Context) - supHeapFree(Context); - - return TRUE; -} - /* * supGetObjectTypesInfo * @@ -1255,38 +1217,16 @@ PVOID supGetObjectTypesInfo( VOID ) { - PVOID buffer = NULL; - ULONG bufferSize = 1024 * 16; - NTSTATUS ntStatus; - ULONG returnedLength = 0; - - buffer = supHeapAlloc((SIZE_T)bufferSize); - if (buffer == NULL) - return NULL; + PVOID buffer = NULL; + ULONG returnedLength = 0; - while ((ntStatus = NtQueryObject( - NULL, - ObjectTypesInformation, - buffer, - bufferSize, - &returnedLength)) == STATUS_INFO_LENGTH_MISMATCH) + if (NT_SUCCESS(supQueryObjectTypesInformation(&buffer, + &returnedLength, + 1024 * 16))) { - supHeapFree(buffer); - bufferSize *= 2; - - if (bufferSize > (16 * 1024 * 1024)) - return NULL; - - buffer = supHeapAlloc((SIZE_T)bufferSize); - } - - if (NT_SUCCESS(ntStatus)) { return buffer; } - if (buffer) - supHeapFree(buffer); - return NULL; } @@ -9879,6 +9819,228 @@ VOID supCloseKnownPropertiesDialog( SendMessage(hwndDlg, WM_CLOSE, 0, 0); } +/* +* supxReadDwordValue +* +* Purpose: +* +* Tiny helper to read from Registry DWORD value. +* +*/ +BOOL supxReadDwordValue( + _In_ HKEY hKey, + _In_ LPCWSTR lpValueName, + _Out_ PDWORD Value +) +{ + DWORD cbData = sizeof(DWORD); + DWORD dwType = REG_DWORD; + + if (ERROR_SUCCESS == RegQueryValueEx(hKey, + lpValueName, + NULL, + &dwType, + (LPBYTE)Value, + &cbData)) + { + return (dwType == REG_DWORD && cbData == sizeof(DWORD)); + } + + return FALSE; +} + +/* +* supxWriteDwordValue +* +* Purpose: +* +* Tiny helper to write into Registry DWORD value. +* +*/ +BOOL supxWriteDwordValue( + _In_ HKEY hKey, + _In_ LPCWSTR lpValueName, + _In_ DWORD Value +) +{ + return (ERROR_SUCCESS == RegSetValueEx(hKey, + lpValueName, + 0, + REG_DWORD, + (LPBYTE)&Value, + sizeof(DWORD))); +} + +/* +* supWriteObexConfiguration +* +* Purpose: +* +* Writes program configuration data to the registry. +* +*/ +_Success_(return) +BOOL supWriteObexConfiguration( + _In_ HWND hwnd +) +{ + HKEY hKey; + DWORD value; + WINDOWPLACEMENT wp; + RECT rc; + POBEX_CONFIG config = supGetParametersBlock(); + + if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, + supObexConfiguration, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_WRITE, + NULL, + &hKey, + NULL)) + { + return FALSE; + } + + // + // Window position and size + // + RtlSecureZeroMemory(&wp, sizeof(wp)); + wp.length = sizeof(wp); + GetWindowPlacement(hwnd, &wp); + rc = wp.rcNormalPosition; + + value = (DWORD)rc.left; + supxWriteDwordValue(hKey, supObexWindowX, value); + + value = (DWORD)rc.top; + supxWriteDwordValue(hKey, supObexWindowY, value); + + value = (DWORD)(rc.right - rc.left); + supxWriteDwordValue(hKey, supObexWindowW, value); + + value = (DWORD)(rc.bottom - rc.top); + supxWriteDwordValue(hKey, supObexWindowH, value); + + // + // Normalization symbol + // + supxWriteDwordValue(hKey, + supObexNormalizationSymbol, + (DWORD)config->szNormalizationSymbol); + + // + // Symbol path + // + if (config->SymbolsPathValid) { + + RegSetValueEx(hKey, + supObexSymPath, + 0, + REG_SZ, + (LPBYTE)config->szSymbolsPath, + ((DWORD)_strlen(config->szSymbolsPath) + 1) * sizeof(WCHAR)); + } + + // + // DbgHelp.dll path + // + if (config->SymbolsDbgHelpDllValid) { + + RegSetValueEx(hKey, + supObexSymDbgHelpDll, + 0, + REG_SZ, + (LPBYTE)config->szSymbolsDbgHelpDll, + ((DWORD)_strlen(config->szSymbolsDbgHelpDll) + 1) * sizeof(WCHAR)); + } + + RegCloseKey(hKey); + + return TRUE; +} + +/* +* supxValidateWindowPlacement +* +* Purpose: +* +* Sanitizes a WinObjEx64 main window size and position in place. +* +* The target monitor is the one nearest to the window's +* saved rect (primary monitor if position is not yet set). +* +*/ +VOID supxValidateWindowPlacement( + _Inout_ POBEX_CONFIG Configuration +) +{ + BOOL xDefault, yDefault; + LONG cxWorkArea, cyWorkArea; + LONGLONG right, bottom; + HMONITOR hMonitor; + POINT pt; + MONITORINFO mi; + RECT rcWindow; + + // + // CW_USEDEFAULT must be consistent for X and Y together. + // + xDefault = (Configuration->X == CW_USEDEFAULT); + yDefault = (Configuration->Y == CW_USEDEFAULT); + + if (xDefault != yDefault) { + Configuration->X = CW_USEDEFAULT; + Configuration->Y = CW_USEDEFAULT; + xDefault = yDefault = TRUE; + } + + if (xDefault && yDefault) { + pt.x = 0; + pt.y = 0; + hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY); + } + else { + rcWindow.left = Configuration->X; + rcWindow.top = Configuration->Y; + rcWindow.right = Configuration->X + Configuration->Width; + rcWindow.bottom = Configuration->Y + Configuration->Height; + + hMonitor = MonitorFromRect(&rcWindow, MONITOR_DEFAULTTONEAREST); + } + + mi.cbSize = sizeof(mi); + if (!GetMonitorInfo(hMonitor, &mi)) { + return; + } + + cxWorkArea = mi.rcWork.right - mi.rcWork.left; + cyWorkArea = mi.rcWork.bottom - mi.rcWork.top; + + if (Configuration->Width <= 0 || Configuration->Width > cxWorkArea) { + Configuration->Width = OBEX_DEFAULT_WIDTH; + } + if (Configuration->Height <= 0 || Configuration->Height > cyWorkArea) { + Configuration->Height = OBEX_DEFAULT_HEIGHT; + } + + if (!xDefault && !yDefault) { + + right = (LONGLONG)Configuration->X + Configuration->Width; + bottom = (LONGLONG)Configuration->Y + Configuration->Height; + + if (right < mi.rcWork.left || + bottom < mi.rcWork.top || + Configuration->X > mi.rcWork.right || + Configuration->Y > mi.rcWork.bottom) + { + Configuration->X = CW_USEDEFAULT; + Configuration->Y = CW_USEDEFAULT; + } + } +} + /* * supReadObexConfiguration * @@ -9905,24 +10067,32 @@ BOOL supReadObexConfiguration( '@', ']', '[', '^', '_', '`', '{', '}', '~' }; + // + // Default values. + // Configuration->SymbolsPathValid = FALSE; Configuration->SymbolsDbgHelpDllValid = FALSE; + Configuration->szNormalizationSymbol = OBJ_NAME_NORMALIZATION_SYMBOL; + Configuration->X = CW_USEDEFAULT; + Configuration->Y = CW_USEDEFAULT; + Configuration->Width = OBEX_DEFAULT_WIDTH; + Configuration->Height = OBEX_DEFAULT_HEIGHT; + if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, supObexConfiguration, 0, KEY_READ, &hKey)) { - cbData = sizeof(DWORD); - dwType = REG_DWORD; - if (ERROR_SUCCESS == RegQueryValueEx(hKey, supObexNormalizationSymbol, - NULL, &dwType, (LPBYTE)&data, &cbData)) - { - if (dwType == REG_DWORD && cbData == sizeof(DWORD)) { - symbol = (WCHAR)data; - for (i = 0; i < RTL_NUMBER_OF(szValidSymbols); i++) { - if (szValidSymbols[i] == symbol) { - Configuration->szNormalizationSymbol = symbol; - break; - } + supxReadDwordValue(hKey, supObexWindowX, (PDWORD)&Configuration->X); + supxReadDwordValue(hKey, supObexWindowY, (PDWORD)&Configuration->Y); + supxReadDwordValue(hKey, supObexWindowW, (PDWORD)&Configuration->Width); + supxReadDwordValue(hKey, supObexWindowH, (PDWORD)&Configuration->Height); + + if (supxReadDwordValue(hKey, supObexNormalizationSymbol, &data)) { + symbol = (WCHAR)data; + for (i = 0; i < RTL_NUMBER_OF(szValidSymbols); i++) { + if (szValidSymbols[i] == symbol) { + Configuration->szNormalizationSymbol = symbol; + break; } } } @@ -9952,9 +10122,11 @@ BOOL supReadObexConfiguration( } RegCloseKey(hKey); + supxValidateWindowPlacement(Configuration); return TRUE; } + supxValidateWindowPlacement(Configuration); return FALSE; } diff --git a/Source/WinObjEx64/sup/sup.h b/Source/WinObjEx64/sup/sup.h index 05ce70d..7781835 100644 --- a/Source/WinObjEx64/sup/sup.h +++ b/Source/WinObjEx64/sup/sup.h @@ -4,9 +4,9 @@ * * TITLE: SUP.H * -* VERSION: 2.11 +* VERSION: 2.12 * -* DATE: 12 Jul 2026 +* DATE: 28 Jul 2026 * * Common header file for the program support routines. * @@ -51,11 +51,19 @@ #define supObexSymPath L"SymPath" #define supObexSymDbgHelpDll L"SymDbgHelpDll" #define supObexNormalizationSymbol L"NormalizationSymbol" +#define supObexWindowX L"WindowX" +#define supObexWindowY L"WindowY" +#define supObexWindowH L"WindowH" +#define supObexWindowW L"WindowW" // All relatives to supObexConfiguration typedef struct _OBEX_CONFIG { BOOLEAN SymbolsPathValid; BOOLEAN SymbolsDbgHelpDllValid; + INT X; + INT Y; + INT Width; + INT Height; WCHAR szNormalizationSymbol; //supObexNormalizationSymbol WCHAR szSymbolsPath[MAX_PATH + 1]; //supObexSymbolsPath WCHAR szSymbolsDbgHelpDll[MAX_PATH + 1]; //supObexSymbolsDbgHelpDll @@ -425,8 +433,8 @@ BOOL supHeapFree( #define supQueryProcessEntryById ntsupQueryProcessEntryById #define supWriteBufferToFile ntsupWriteBufferToFile #define supQueryVsmProtectionInformation ntsupQueryVsmProtectionInformation -#define supQueryHVCIState ntsupQueryHVCIState -#define supLookupImageSectionByName ntsupLookupImageSectionByName +#define supQueryVBSState ntsupQueryVBSState +#define supLookupImageSectionByNameEx ntsupLookupImageSectionByNameEx #define supFindPattern ntsupFindPattern #define supFindPatternEx ntsupFindPatternEx #define supOpenProcess ntsupOpenProcess @@ -457,6 +465,12 @@ BOOL supHeapFree( #define supQueryThreadInformation(ThreadHandle, ThreadInformationClass, Buffer, ReturnLength) \ ntsupQueryThreadInformation(ThreadHandle, ThreadInformationClass, Buffer, ReturnLength, supHeapAlloc, supHeapFree) +#define supQueryTokenInformation(TokenHandle, TokenInformationClass, Buffer, ReturnLength) \ + ntsupQueryTokenInformation(TokenHandle, TokenInformationClass, Buffer, ReturnLength, supHeapAlloc, supHeapFree) + +#define supQueryObjectTypesInformation(Buffer, ReturnLength, InitialBufferSize) \ + ntsupQueryObjectInformationEx(NULL, ObjectTypesInformation, Buffer, ReturnLength, InitialBufferSize, supHeapAlloc, supHeapFree) + FORCEINLINE BOOLEAN supUnicodeStringValid( _In_ PUNICODE_STRING SourceString ) @@ -1269,6 +1283,10 @@ BOOL supImageFixSections( VOID supCloseKnownPropertiesDialog( _In_opt_ HWND hwndDlg); +_Success_(return) +BOOL supWriteObexConfiguration( + _In_ HWND hwnd); + _Success_(return) BOOL supReadObexConfiguration( _Out_ POBEX_CONFIG Configuration); diff --git a/Source/WinObjEx64/sup/w32k.c b/Source/WinObjEx64/sup/w32k.c index 8eca5a2..99cecba 100644 --- a/Source/WinObjEx64/sup/w32k.c +++ b/Source/WinObjEx64/sup/w32k.c @@ -4,9 +4,9 @@ * * TITLE: W32K.C * -* VERSION: 2.11 +* VERSION: 2.12 * -* DATE: 22 Jun 2026 +* DATE: 25 Jul 2026 * * Win32k syscall table actual handlers resolving routines. * @@ -110,7 +110,8 @@ PBYTE ApiSetFindWin32kApiSetTableRef( * */ ULONG_PTR SdtpQueryWin32kApiSetTable( - _In_ HMODULE hModule, + _In_ HMODULE Win32kModule, + _In_ ULONG Win32kModuleSize, _In_ PVOID ImageBase, _In_ ULONG_PTR ImageSize, _In_opt_ SYMCONTEXT* SymContext @@ -118,7 +119,7 @@ ULONG_PTR SdtpQueryWin32kApiSetTable( { LONG relativeValue = 0; ULONG SectionSize = 0, Index; - PBYTE ptrCode = (PBYTE)hModule; + PBYTE ptrCode = (PBYTE)Win32kModule; PVOID SectionBase; ULONG_PTR tableAddress = 0, instructionLength = 0; hde64s hs; @@ -131,7 +132,7 @@ ULONG_PTR SdtpQueryWin32kApiSetTable( ImageSize, &tableAddress)) { - tableAddress = tableAddress - (ULONG_PTR)ImageBase + (ULONG_PTR)hModule; + tableAddress = tableAddress - (ULONG_PTR)ImageBase + (ULONG_PTR)Win32kModule; } } @@ -141,9 +142,10 @@ ULONG_PTR SdtpQueryWin32kApiSetTable( // // Locate .text image section as required variable is always in .text. // - SectionBase = supLookupImageSectionByName(TEXT_SECTION, + SectionBase = supLookupImageSectionByNameEx(TEXT_SECTION, TEXT_SECTION_LENGTH, - (PVOID)hModule, + (PVOID)Win32kModule, + Win32kModuleSize, &SectionSize); if (SectionBase == 0 || SectionSize == 0) @@ -192,8 +194,8 @@ ULONG_PTR SdtpQueryWin32kApiSetTable( // Sanity check. // tableAddress = (ULONG_PTR)ptrCode + Index + instructionLength + relativeValue; - if (tableAddress < (ULONG_PTR)hModule || - tableAddress >= ((ULONG_PTR)hModule + ImageSize)) + if (tableAddress < (ULONG_PTR)Win32kModule || + tableAddress >= ((ULONG_PTR)Win32kModule + ImageSize)) { return 0; } @@ -725,22 +727,22 @@ NTSTATUS SdtResolveModuleFromImportThunk( pFuncThunk = (PIMAGE_THUNK_DATA)((ULONG_PTR)FunctionPtr + hs.len + rel); pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData( - Context->KernelModule, + Context->MappedKernelModule, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &importSize); for (pIID = pImportDescriptor; pIID->Name != 0; pIID++) { - pOrigFirstThunk = (PIMAGE_THUNK_DATA)RtlOffsetToPointer(Context->KernelModule, pIID->OriginalFirstThunk); - pFirstThunk = (PIMAGE_THUNK_DATA)RtlOffsetToPointer(Context->KernelModule, pIID->FirstThunk); + pOrigFirstThunk = (PIMAGE_THUNK_DATA)RtlOffsetToPointer(Context->MappedKernelModule, pIID->OriginalFirstThunk); + pFirstThunk = (PIMAGE_THUNK_DATA)RtlOffsetToPointer(Context->MappedKernelModule, pIID->FirstThunk); for (; pOrigFirstThunk->u1.AddressOfData; ++pOrigFirstThunk, ++pFirstThunk) { - pImageImportByName = (PIMAGE_IMPORT_BY_NAME)RtlOffsetToPointer(Context->KernelModule, + pImageImportByName = (PIMAGE_IMPORT_BY_NAME)RtlOffsetToPointer(Context->MappedKernelModule, pOrigFirstThunk->u1.AddressOfData); if (pFirstThunk == pFuncThunk) { - pszDllName = (LPCSTR)RtlOffsetToPointer(Context->KernelModule, pIID->Name); + pszDllName = (LPCSTR)RtlOffsetToPointer(Context->MappedKernelModule, pIID->Name); return SdtMapModuleFromImportThunkWithResolve( pszDllName, @@ -1118,6 +1120,7 @@ ULONG SdtWin32kInitializeOnce( ULONG ulResult = 0, schemaVersion; ULONG_PTR varAddress; PULONG pKernelLimit; + PLDR_DATA_TABLE_ENTRY pMappedModule; PRTL_PROCESS_MODULE_INFORMATION pModule; HANDLE heapHandle; HMODULE hModule; @@ -1189,7 +1192,12 @@ ULONG SdtWin32kInitializeOnce( ulResult = ErrShadowWin32kLoadFail; break; } - Context->KernelModule = hModule; + Context->MappedKernelModule = hModule; + if (!NT_SUCCESS(LdrFindEntryForAddress(hModule, &pMappedModule))) { + ulResult = ErrShadowWin32kLoadFail; + break; + } + Context->MappedKernelModuleSize = pMappedModule->SizeOfImage; // // Check whatever win32u is compatible with win32k data, compare number of services. @@ -1209,7 +1217,7 @@ ULONG SdtWin32kInitializeOnce( // Query win32k!W32pServiceTable, calculate it kernel address. // RtlSecureZeroMemory(&resolveInfo, sizeof(RESOLVE_INFO)); - if (!NT_SUCCESS(NtRawGetProcAddress(Context->KernelModule, "W32pServiceTable", &resolveInfo))) { + if (!NT_SUCCESS(NtRawGetProcAddress(Context->MappedKernelModule, "W32pServiceTable", &resolveInfo))) { ulResult = ErrShadowW32pServiceTableNotFound; break; } @@ -1217,7 +1225,7 @@ ULONG SdtWin32kInitializeOnce( Context->W32pServiceTableUserBase = (PULONG)resolveInfo.Function; Context->W32pServiceTableKernelBase = - Context->KernelBaseAddress + (ULONG_PTR)resolveInfo.Function - (ULONG_PTR)Context->KernelModule; + Context->KernelBaseAddress + (ULONG_PTR)resolveInfo.Function - (ULONG_PTR)Context->MappedKernelModule; // // Find Win32kApiSetTable where needed. @@ -1260,7 +1268,6 @@ ULONG SdtWin32kInitializeOnce( logAdd(EntryTypeInformation, TEXT("Session aware ApiSet parsing expected")); - Context->W32GetSessionStatePtr = (ULONG_PTR)GetProcAddress(hModule, "W32GetSessionState"); if (Context->W32GetSessionStatePtr == 0) { ulResult = ErrShadowWin32kGetStateNotFound; @@ -1310,7 +1317,7 @@ ULONG SdtWin32kInitializeOnce( // // Remember table offset. // - Context->Win32kApiSetTableOffset = SdtpQueryW32GetWin32kApiSetTableOffset(Context->KernelModule); + Context->Win32kApiSetTableOffset = SdtpQueryW32GetWin32kApiSetTableOffset(Context->MappedKernelModule); if (Context->Win32kApiSetTableOffset == 0) { ulResult = ErrShadowWin32kOffsetNotFound; break; @@ -1324,7 +1331,9 @@ ULONG SdtWin32kInitializeOnce( // This is old win32k layout. // Locate Win32kApiSetTable variable. Failure will result in unresolved apiset adapters. // - Context->Win32kApiSetTable = SdtpQueryWin32kApiSetTable(Context->KernelModule, + Context->Win32kApiSetTable = SdtpQueryWin32kApiSetTable( + Context->MappedKernelModule, + Context->MappedKernelModuleSize, (PVOID)Context->KernelBaseAddress, Context->KernelImageSize, symContext); @@ -1363,13 +1372,13 @@ ULONG SdtWin32kInitializeOnce( if (ulResult != ErrShadowApiSetNotFound) { - if (Context->KernelModule) - FreeLibrary(Context->KernelModule); + if (Context->MappedKernelModule) + FreeLibrary(Context->MappedKernelModule); if (Context->ExportsEnumHeap) supDestroyHeap(Context->ExportsEnumHeap); - Context->KernelModule = NULL; + Context->MappedKernelModule = NULL; Context->ExportsEnumHeap = NULL; } @@ -1389,8 +1398,8 @@ ULONG SdtWin32kInitializeOnce( VOID SdtWin32kUninitialize( _In_ PSDT_CONTEXT Context) { - if (Context->KernelModule) - FreeLibrary(Context->KernelModule); + if (Context->MappedKernelModule) + FreeLibrary(Context->MappedKernelModule); if (Context->ExportsEnumHeap) supDestroyHeap(Context->ExportsEnumHeap); diff --git a/Source/WinObjEx64/sup/w32k.h b/Source/WinObjEx64/sup/w32k.h index b511278..c25d389 100644 --- a/Source/WinObjEx64/sup/w32k.h +++ b/Source/WinObjEx64/sup/w32k.h @@ -4,9 +4,9 @@ * * TITLE: W32K.H * -* VERSION: 2.11 +* VERSION: 2.12 * -* DATE: 22 Jun 2026 +* DATE: 24 Jul 2026 * * Common header file for the win32k support routines. * @@ -147,7 +147,8 @@ typedef struct _SDT_CONTEXT { HANDLE ExportsEnumHeap; //heap handle for enum HMODULE UserModule; //win32u.dll hmodule - HMODULE KernelModule; //win32k.sys hmodule + HMODULE MappedKernelModule; //win32k.sys hmodule + ULONG MappedKernelModuleSize; //win32k.sys hmodule size PRAW_SYSCALL_ENTRY UserTable; //win32u syscalls exports dump ULONG UserLimit; //win32u syscalls count diff --git a/Source/WinObjEx64/tests/ntsup_tests.c b/Source/WinObjEx64/tests/ntsup_tests.c deleted file mode 100644 index 4f05978..0000000 --- a/Source/WinObjEx64/tests/ntsup_tests.c +++ /dev/null @@ -1,897 +0,0 @@ -/******************************************************************************* -* -* (C) COPYRIGHT AUTHORS, 2015 - 2026 UGN/HE -* -* TITLE: NTSUP_TESTS.C -* -* VERSION: 2.10 -* -* DATE: 10 Jan 2026 -* -* NTSup test code used while debug. -* -* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF -* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED -* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A -* PARTICULAR PURPOSE. -* -*******************************************************************************/ -#define OEMRESOURCE - -#include "global.h" -#include "ntos\ntsup.h" -#pragma warning(push) -#pragma warning(disable:28251) //Inconsistent annotation for any intrin, "feature" of the latest MSVC -#pragma warning(disable: 6387) //_Param_(1) could be '0' -#pragma warning(disable: 28159) //GetTickCount -#include - -static ULONG g_FailCount = 0; -static BOOL g_Verbose = TRUE; - -#define TEST_ASSERT(expr) do { if (!(expr)) { ++g_FailCount; if (g_Verbose) DbgPrint("ASSERT FAILED: %s (%s:%d)\n", #expr, __FUNCTION__, __LINE__); } } while (0) - -PVOID CALLBACK TestAlloc(_In_ SIZE_T NumberOfBytes) -{ - return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, NumberOfBytes); -} - -BOOL CALLBACK TestFree(_In_ PVOID Memory) -{ - if (Memory) HeapFree(GetProcessHeap(), 0, Memory); - return TRUE; -} - -PVOID CALLBACK FailAlloc(_In_ SIZE_T NumberOfBytes) -{ - (void)NumberOfBytes; - return NULL; -} - -BOOL ReadFileContent( - _In_ LPCWSTR FileName, - _Out_ PBYTE* Buffer, - _Out_ DWORD* Size -) -{ - HANDLE hFile; - DWORD fileSize, bytesRead; - PBYTE data; - - *Buffer = NULL; - *Size = 0; - - hFile = CreateFile(FileName, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - - if (hFile == INVALID_HANDLE_VALUE) - return FALSE; - - fileSize = GetFileSize(hFile, NULL); - if (fileSize == INVALID_FILE_SIZE) { - CloseHandle(hFile); - return FALSE; - } - - data = (PBYTE)ntsupHeapAlloc(fileSize ? fileSize : 1); - if (data == NULL) { - CloseHandle(hFile); - return FALSE; - } - - bytesRead = 0; - if (fileSize) { - if (!ReadFile(hFile, data, fileSize, &bytesRead, NULL) || bytesRead != fileSize) { - ntsupHeapFree(data); - CloseHandle(hFile); - return FALSE; - } - } - - CloseHandle(hFile); - - *Buffer = data; - *Size = fileSize; - return TRUE; -} - -VOID WriteBufferToFile_WriteNewFile(VOID) -{ - WCHAR tempPath[MAX_PATH]; - WCHAR filePath[MAX_PATH]; - NTSTATUS resultStatus; - SIZE_T written; - BYTE const data1[] = { 1,2,3,4,5 }; - PBYTE fileData; - DWORD fileSize; - ULONG i; - - RtlSecureZeroMemory(tempPath, sizeof(tempPath)); - RtlSecureZeroMemory(filePath, sizeof(filePath)); - - GetTempPath(MAX_PATH, tempPath); - wsprintfW(filePath, L"%sntsup_test_%lu.bin", tempPath, GetTickCount()); - - written = ntsupWriteBufferToFile( - filePath, - (PVOID)data1, - sizeof(data1), - TRUE, - FALSE, - &resultStatus); - - TEST_ASSERT(written == sizeof(data1)); - TEST_ASSERT(NT_SUCCESS(resultStatus)); - - fileData = NULL; - fileSize = 0; - TEST_ASSERT(ReadFileContent(filePath, &fileData, &fileSize)); - if (fileData) { - TEST_ASSERT(fileSize == sizeof(data1)); - for (i = 0; i < fileSize; i++) - TEST_ASSERT(fileData[i] == data1[i]); - ntsupHeapFree(fileData); - } - - DeleteFile(filePath); -} - -VOID WriteBufferToFile_AppendFile(VOID) -{ - WCHAR tempPath[MAX_PATH]; - WCHAR filePath[MAX_PATH]; - NTSTATUS resultStatus; - SIZE_T written; - BYTE const data1[] = { 0x10,0x11,0x12 }; - BYTE const data2[] = { 0xAA,0xBB }; - PBYTE fileData; - DWORD fileSize; - ULONG i; - - RtlSecureZeroMemory(tempPath, sizeof(tempPath)); - RtlSecureZeroMemory(filePath, sizeof(filePath)); - - GetTempPath(MAX_PATH, tempPath); - wsprintfW(filePath, L"%sntsup_test_append_%lu.bin", tempPath, GetTickCount()); - - written = ntsupWriteBufferToFile( - filePath, - (PVOID)data1, - sizeof(data1), - TRUE, - FALSE, - &resultStatus); - - TEST_ASSERT(written == sizeof(data1)); - TEST_ASSERT(NT_SUCCESS(resultStatus)); - - written = ntsupWriteBufferToFile( - filePath, - (PVOID)data2, - sizeof(data2), - TRUE, - TRUE, - &resultStatus); - - TEST_ASSERT(written == sizeof(data2)); - TEST_ASSERT(NT_SUCCESS(resultStatus)); - - fileData = NULL; - fileSize = 0; - TEST_ASSERT(ReadFileContent(filePath, &fileData, &fileSize)); - if (fileData) { - TEST_ASSERT(fileSize == sizeof(data1) + sizeof(data2)); - for (i = 0; i < sizeof(data1); i++) - TEST_ASSERT(fileData[i] == data1[i]); - for (i = 0; i < sizeof(data2); i++) - TEST_ASSERT(fileData[sizeof(data1) + i] == data2[i]); - ntsupHeapFree(fileData); - } - - DeleteFile(filePath); -} - -VOID WriteBufferToFile_InvalidPath(VOID) -{ - NTSTATUS resultStatus; - SIZE_T written; - BYTE dummy[4] = { 0 }; - - written = ntsupWriteBufferToFile( - L"", - dummy, - sizeof(dummy), - FALSE, - FALSE, - &resultStatus); - - TEST_ASSERT(written == 0); - TEST_ASSERT(!NT_SUCCESS(resultStatus)); -} - -VOID WriteBufferToFile_ZeroSizeWrite(VOID) -{ - WCHAR tempPath[MAX_PATH]; - WCHAR filePath[MAX_PATH]; - NTSTATUS resultStatus; - SIZE_T written; - PBYTE fileData; - DWORD fileSize; - - RtlSecureZeroMemory(tempPath, sizeof(tempPath)); - RtlSecureZeroMemory(filePath, sizeof(filePath)); - - GetTempPath(MAX_PATH, tempPath); - wsprintfW(filePath, L"%sntsup_test_zero_%lu.bin", tempPath, GetTickCount()); - - written = ntsupWriteBufferToFile( - filePath, - (PVOID)"", - 0, - TRUE, - FALSE, - &resultStatus); - - TEST_ASSERT(written == 0); - TEST_ASSERT(NT_SUCCESS(resultStatus) || written == 0); // Accept success with zero write - - fileData = NULL; - fileSize = 0; - if (ReadFileContent(filePath, &fileData, &fileSize)) { - TEST_ASSERT(fileSize == 0); - if (fileData) ntsupHeapFree(fileData); - } - - DeleteFile(filePath); -} - -VOID FindModuleNameByAddress_ValidModuleName(VOID) -{ - PRTL_PROCESS_MODULES modules; - ULONG returnLength; - PRTL_PROCESS_MODULE_INFORMATION modInfo; - WCHAR nameBuffer[260]; - PVOID foundEntry; - PVOID testAddress; - ANSI_STRING ansiExpected; - UNICODE_STRING usExpected; - SIZE_T expectedLen; - - modules = (PRTL_PROCESS_MODULES)ntsupGetLoadedModulesList(&returnLength); - TEST_ASSERT(modules != NULL); - if (modules == NULL) - return; - - if (modules->NumberOfModules == 0) { - ntsupHeapFree(modules); - TEST_ASSERT(FALSE); - return; - } - - modInfo = &modules->Modules[0]; - testAddress = (PBYTE)modInfo->ImageBase + (modInfo->ImageSize / 2); - - RtlSecureZeroMemory(nameBuffer, sizeof(nameBuffer)); - - foundEntry = ntsupFindModuleNameByAddress( - modules, - testAddress, - nameBuffer, - _countof(nameBuffer)); - - TEST_ASSERT(foundEntry != NULL); - TEST_ASSERT(nameBuffer[0] != 0); - - if (foundEntry) { - RtlInitString(&ansiExpected, - (PCSZ)&modInfo->FullPathName[modInfo->OffsetToFileName]); - usExpected.Buffer = NULL; - usExpected.Length = usExpected.MaximumLength = 0; - if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&usExpected, &ansiExpected, TRUE))) { - expectedLen = usExpected.Length / sizeof(WCHAR); - TEST_ASSERT(_strlen(nameBuffer) <= expectedLen); - TEST_ASSERT(_strcmp(nameBuffer, usExpected.Buffer) == 0); - RtlFreeUnicodeString(&usExpected); - } - } - - ntsupHeapFree(modules); -} - -VOID FindModuleNameByAddress_TruncatedBuffer(VOID) -{ - PRTL_PROCESS_MODULES modules; - ULONG returnLength; - PRTL_PROCESS_MODULE_INFORMATION modInfo; - WCHAR tinyBuffer[4]; - PVOID testAddress; - PVOID foundEntry; - SIZE_T lenCaptured; - - modules = (PRTL_PROCESS_MODULES)ntsupGetLoadedModulesList(&returnLength); - TEST_ASSERT(modules != NULL); - if (modules == NULL) - return; - - if (modules->NumberOfModules == 0) { - ntsupHeapFree(modules); - TEST_ASSERT(FALSE); - return; - } - - modInfo = &modules->Modules[0]; - testAddress = modInfo->ImageBase; - - RtlSecureZeroMemory(tinyBuffer, sizeof(tinyBuffer)); - - foundEntry = ntsupFindModuleNameByAddress( - modules, - testAddress, - tinyBuffer, - _countof(tinyBuffer)); - - TEST_ASSERT(foundEntry != NULL); - lenCaptured = _strlen(tinyBuffer); - TEST_ASSERT(lenCaptured <= (_countof(tinyBuffer) - 1)); - TEST_ASSERT(tinyBuffer[_countof(tinyBuffer) - 1] == 0); - - ntsupHeapFree(modules); -} - -VOID FindModuleNameByAddress_InvalidAddress(VOID) -{ - PRTL_PROCESS_MODULES modules; - ULONG returnLength; - WCHAR buffer[32]; - PVOID foundEntry; - - modules = (PRTL_PROCESS_MODULES)ntsupGetLoadedModulesList(&returnLength); - TEST_ASSERT(modules != NULL); - if (modules == NULL) - return; - - RtlSecureZeroMemory(buffer, sizeof(buffer)); - - foundEntry = ntsupFindModuleNameByAddress( - modules, - ULongToPtr(0x1), // very low address, should not belong to system module range - buffer, - _countof(buffer)); - - TEST_ASSERT(foundEntry == NULL); - TEST_ASSERT(buffer[0] == 0); - - ntsupHeapFree(modules); -} - -VOID FindModuleNameByAddress_InvalidBufferArgs(VOID) -{ - PRTL_PROCESS_MODULES modules; - ULONG returnLength; - PRTL_PROCESS_MODULE_INFORMATION modInfo; - PVOID testAddress; - PVOID foundEntry; - WCHAR nameBuffer[8]; - - modules = (PRTL_PROCESS_MODULES)ntsupGetLoadedModulesList(&returnLength); - TEST_ASSERT(modules != NULL); - if (modules == NULL) - return; - - if (modules->NumberOfModules == 0) { - ntsupHeapFree(modules); - TEST_ASSERT(FALSE); - return; - } - - modInfo = &modules->Modules[0]; - testAddress = modInfo->ImageBase; - - foundEntry = ntsupFindModuleNameByAddress( - modules, - testAddress, - NULL, - 0); - TEST_ASSERT(foundEntry == NULL); - - RtlSecureZeroMemory(nameBuffer, sizeof(nameBuffer)); - foundEntry = ntsupFindModuleNameByAddress( - modules, - testAddress, - nameBuffer, - 0); - TEST_ASSERT(foundEntry == NULL); - TEST_ASSERT(nameBuffer[0] == 0); - - ntsupHeapFree(modules); -} - -VOID GetLoadedModulesListEx_BasicList(VOID) -{ - PRTL_PROCESS_MODULES modules; - ULONG returnLength = 0; - ULONG count, i; - BOOLEAN haveNonZero = FALSE; - - modules = (PRTL_PROCESS_MODULES)ntsupGetLoadedModulesListEx( - FALSE, - &returnLength, - (PNTSUPMEMALLOC)ntsupHeapAlloc, - (PNTSUPMEMFREE)ntsupHeapFree); - - TEST_ASSERT(modules != NULL); - if (modules == NULL) - return; - - count = modules->NumberOfModules; - TEST_ASSERT(count > 0); - TEST_ASSERT(returnLength > 0); - - if (count > 0) { - TEST_ASSERT(modules->Modules[0].ImageBase != NULL); - TEST_ASSERT(modules->Modules[0].ImageSize > 0); - } - - for (i = 0; i < count && i < 32; i++) { - if (modules->Modules[i].FullPathName[0] != 0) { - haveNonZero = TRUE; - break; - } - } - TEST_ASSERT(haveNonZero); - - ntsupHeapFree(modules); -} - -VOID GetLoadedModulesListEx_ExtendedList(VOID) -{ - PRTL_PROCESS_MODULES modules; - ULONG returnLength = 0; - - modules = (PRTL_PROCESS_MODULES)ntsupGetLoadedModulesListEx( - TRUE, - &returnLength, - (PNTSUPMEMALLOC)ntsupHeapAlloc, - (PNTSUPMEMFREE)ntsupHeapFree); - - if (modules == NULL) { - if (g_Verbose) DbgPrint("Extended module list not available (SystemModuleInformationEx unsupported?) - skipping related assertions.\n"); - return; - } - - TEST_ASSERT(returnLength > 0); - TEST_ASSERT(modules->NumberOfModules > 0); - TEST_ASSERT(modules->Modules[0].ImageBase != NULL); - - ntsupHeapFree(modules); -} - -VOID GetLoadedModulesListEx_NullReturnLength(VOID) -{ - PRTL_PROCESS_MODULES modules; - - modules = (PRTL_PROCESS_MODULES)ntsupGetLoadedModulesListEx( - FALSE, - NULL, - (PNTSUPMEMALLOC)ntsupHeapAlloc, - (PNTSUPMEMFREE)ntsupHeapFree); - - TEST_ASSERT(modules != NULL); - if (modules) - ntsupHeapFree(modules); -} - -VOID GetLoadedModulesListEx_AllocFailure(VOID) -{ - PVOID modules; - ULONG returnLength = 0; - - modules = ntsupGetLoadedModulesListEx( - FALSE, - &returnLength, - (PNTSUPMEMALLOC)FailAlloc, - (PNTSUPMEMFREE)TestFree); - - TEST_ASSERT(modules == NULL); - TEST_ASSERT(returnLength == 0); -} - -VOID GetSystemInfoEx_SystemProcessInformation(VOID) -{ - PVOID buffer; - ULONG retLen = 0; - ULONG safeCheck = 0; - ULONG bytesWalked = 0; - - buffer = ntsupGetSystemInfoEx( - SystemProcessInformation, - &retLen, - (PNTSUPMEMALLOC)TestAlloc, - (PNTSUPMEMFREE)TestFree); - - if (buffer == NULL) { - if (g_Verbose) DbgPrint("SystemProcessInformation unsupported or allocation failed, skipping.\n"); - return; - } - - TEST_ASSERT(retLen > 0); - - if (retLen > sizeof(SYSTEM_PROCESS_INFORMATION)) { - - PSYSTEM_PROCESS_INFORMATION spi = (PSYSTEM_PROCESS_INFORMATION)buffer; - - while (TRUE) { - TEST_ASSERT(spi->NextEntryDelta % sizeof(ULONG) == 0); - bytesWalked += spi->NextEntryDelta; - safeCheck++; - - if (spi->NextEntryDelta == 0) - break; - - if (safeCheck > 0x100000) { - TEST_ASSERT(FALSE); - break; - } - - spi = (PSYSTEM_PROCESS_INFORMATION)((PUCHAR)spi + spi->NextEntryDelta); - } - } - - TestFree(buffer); -} - -VOID GetSystemInfoEx_NullReturnLength(VOID) -{ - PVOID buffer; - - buffer = ntsupGetSystemInfoEx( - SystemBasicInformation, - NULL, - (PNTSUPMEMALLOC)TestAlloc, - (PNTSUPMEMFREE)TestFree); - - TEST_ASSERT(buffer == NULL); - if (buffer) - TestFree(buffer); -} - -VOID GetSystemInfoEx_AllocFailure(VOID) -{ - PVOID buffer; - ULONG retLen = 0; - - buffer = ntsupGetSystemInfoEx( - SystemBasicInformation, - &retLen, - (PNTSUPMEMALLOC)FailAlloc, - (PNTSUPMEMFREE)TestFree); - - TEST_ASSERT(buffer == NULL); - TEST_ASSERT(retLen == 0); -} - -VOID GetSystemInfoEx_InvalidClass(VOID) -{ - PVOID buffer; - ULONG retLen = 0; - - buffer = ntsupGetSystemInfoEx( - (SYSTEM_INFORMATION_CLASS)0xFFFFFFFF, //-V1016 - &retLen, - (PNTSUPMEMALLOC)TestAlloc, - (PNTSUPMEMFREE)TestFree); - - TEST_ASSERT(buffer == NULL); - TEST_ASSERT(retLen == 0); -} - -VOID HashImageSections_LoadedImage(VOID) -{ - HMODULE hMod; - PIMAGE_NT_HEADERS nth; - BYTE hash[NTSUPHASH_SHA256_SIZE]; - NTSTATUS status; - SIZE_T imageSize; - - hMod = GetModuleHandle(NULL); - TEST_ASSERT(hMod != NULL); - if (hMod == NULL) return; - - nth = RtlImageNtHeader(hMod); - TEST_ASSERT(nth != NULL); - if (nth == NULL) return; - - imageSize = nth->OptionalHeader.SizeOfImage; - RtlSecureZeroMemory(hash, sizeof(hash)); - - status = ntsupHashImageSections( - (PVOID)hMod, - imageSize, - hash, - sizeof(hash), - ImageTypeLoaded); - - TEST_ASSERT(NT_SUCCESS(status)); - if (NT_SUCCESS(status)) { - SIZE_T i, zeroCount = 0; - for (i = 0; i < sizeof(hash); i++) - if (hash[i] == 0) zeroCount++; - TEST_ASSERT(zeroCount != sizeof(hash)); - } -} - -VOID HashImageSections_RawFileMapping(VOID) -{ - WCHAR path[MAX_PATH]; - HANDLE hFile, hMapping; - LARGE_INTEGER fsz; - PVOID mapBase; - BYTE hash[NTSUPHASH_SHA256_SIZE]; - NTSTATUS status; - - RtlSecureZeroMemory(path, sizeof(path)); - if (!GetModuleFileName(NULL, path, MAX_PATH)) - return; - - hFile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - TEST_ASSERT(hFile != INVALID_HANDLE_VALUE); - if (hFile == INVALID_HANDLE_VALUE) return; - - fsz.LowPart = GetFileSize(hFile, (LPDWORD)&fsz.HighPart); - TEST_ASSERT(fsz.QuadPart > 0); - - hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); - TEST_ASSERT(hMapping != NULL); - if (hMapping == NULL) { - CloseHandle(hFile); - return; - } - - mapBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0); - TEST_ASSERT(mapBase != NULL); - if (mapBase == NULL) { - CloseHandle(hMapping); - CloseHandle(hFile); - return; - } - - RtlSecureZeroMemory(hash, sizeof(hash)); - status = ntsupHashImageSections( - mapBase, - (SIZE_T)fsz.QuadPart, - hash, - sizeof(hash), - ImageTypeRaw); - - TEST_ASSERT(NT_SUCCESS(status)); - - UnmapViewOfFile(mapBase); - CloseHandle(hMapping); - CloseHandle(hFile); -} - -VOID BuildMinimalImage( - _Out_ PVOID* Buffer, - _Out_ SIZE_T* BufferSize, - _In_ BOOL ExecutableSection -) -{ - PBYTE base; - IMAGE_DOS_HEADER* dos; - IMAGE_NT_HEADERS64* nth; - IMAGE_SECTION_HEADER* sh; - SIZE_T bufSize; - ULONG optSize; - - bufSize = 0x1000; - *BufferSize = bufSize; - base = (PBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufSize); - *Buffer = base; - if (base == NULL) return; - - dos = (IMAGE_DOS_HEADER*)base; - dos->e_magic = IMAGE_DOS_SIGNATURE; - dos->e_lfanew = 0x80; - - nth = (IMAGE_NT_HEADERS64*)(base + dos->e_lfanew); - nth->Signature = IMAGE_NT_SIGNATURE; - nth->FileHeader.Machine = IMAGE_FILE_MACHINE_AMD64; - nth->FileHeader.NumberOfSections = 1; - optSize = sizeof(IMAGE_OPTIONAL_HEADER64); - nth->FileHeader.SizeOfOptionalHeader = (WORD)optSize; - nth->OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC; - nth->OptionalHeader.SectionAlignment = 0x200; - nth->OptionalHeader.FileAlignment = 0x200; - nth->OptionalHeader.SizeOfImage = (DWORD)bufSize; - nth->OptionalHeader.SizeOfHeaders = 0x200; - - sh = (IMAGE_SECTION_HEADER*)((PBYTE)&nth->OptionalHeader + optSize); - RtlCopyMemory(sh->Name, ".data", 5); - sh->Misc.VirtualSize = 0x100; - sh->VirtualAddress = 0x200; - sh->SizeOfRawData = 0x200; - sh->PointerToRawData = 0x200; - sh->Characteristics = - IMAGE_SCN_CNT_INITIALIZED_DATA | - IMAGE_SCN_MEM_READ | - (ExecutableSection ? (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE) : 0); -} - -VOID HashImageSections_NoExecutableSections(VOID) -{ - PVOID image; - SIZE_T imageSize; - BYTE hash[NTSUPHASH_SHA256_SIZE]; - NTSTATUS status; - - image = NULL; - imageSize = 0; - BuildMinimalImage(&image, &imageSize, FALSE); - TEST_ASSERT(image != NULL); - if (image == NULL) return; - - RtlSecureZeroMemory(hash, sizeof(hash)); - status = ntsupHashImageSections( - image, - imageSize, - hash, - sizeof(hash), - ImageTypeLoaded); - - TEST_ASSERT(status == STATUS_NOT_FOUND); - - HeapFree(GetProcessHeap(), 0, image); -} - -VOID HashImageSections_ExecutableSectionPresent(VOID) -{ - PVOID image; - SIZE_T imageSize; - BYTE hash[NTSUPHASH_SHA256_SIZE]; - NTSTATUS status; - - image = NULL; - imageSize = 0; - BuildMinimalImage(&image, &imageSize, TRUE); - TEST_ASSERT(image != NULL); - if (image == NULL) return; - - RtlSecureZeroMemory(hash, sizeof(hash)); - status = ntsupHashImageSections( - image, - imageSize, - hash, - sizeof(hash), - ImageTypeLoaded); - - TEST_ASSERT(NT_SUCCESS(status)); - - HeapFree(GetProcessHeap(), 0, image); -} - -VOID HashImageSections_InvalidParams(VOID) -{ - BYTE hash[NTSUPHASH_SHA256_SIZE]; - NTSTATUS status; - PVOID image; - SIZE_T imageSize; - - RtlSecureZeroMemory(hash, sizeof(hash)); - - status = ntsupHashImageSections(NULL, 100, hash, sizeof(hash), ImageTypeLoaded); - TEST_ASSERT(status == STATUS_INVALID_PARAMETER); - - status = ntsupHashImageSections(ULongToPtr(0x1), 0, hash, sizeof(hash), ImageTypeLoaded); - TEST_ASSERT(status == STATUS_INVALID_PARAMETER); - - status = ntsupHashImageSections(ULongToPtr(0x1), 100, hash, 1, ImageTypeLoaded); - TEST_ASSERT(status == STATUS_BUFFER_TOO_SMALL); - - image = NULL; - imageSize = 0; - BuildMinimalImage(&image, &imageSize, TRUE); - if (image) { - PIMAGE_NT_HEADERS nth = (PIMAGE_NT_HEADERS)RtlImageNtHeader(image); - if (nth) { - SIZE_T smaller = nth->OptionalHeader.SizeOfImage / 2; - status = ntsupHashImageSections( - image, - smaller, - hash, - sizeof(hash), - ImageTypeLoaded); - TEST_ASSERT(status == STATUS_INVALID_IMAGE_FORMAT); - } - HeapFree(GetProcessHeap(), 0, image); - } -} - -VOID Test_WriteBufferToFile() -{ - g_FailCount = 0; - WriteBufferToFile_WriteNewFile(); - WriteBufferToFile_AppendFile(); - WriteBufferToFile_InvalidPath(); - WriteBufferToFile_ZeroSizeWrite(); - - if (g_Verbose) { - if (g_FailCount == 0) - DbgPrint("[TEST] ntsupWriteBufferToFile PASSED.\n"); - else - DbgPrint("[TEST] ntsupWriteBufferToFile %lu tests FAILED.\n", g_FailCount); - } -} - -VOID Test_FindModuleNameByAddress() -{ - g_FailCount = 0; - FindModuleNameByAddress_ValidModuleName(); - FindModuleNameByAddress_TruncatedBuffer(); - FindModuleNameByAddress_InvalidAddress(); - FindModuleNameByAddress_InvalidBufferArgs(); - - if (g_Verbose) { - if (g_FailCount == 0) - DbgPrint("[TEST] ntsupFindModuleNameByAddress PASSED.\n"); - else - DbgPrint("[TST] ntsupFindModuleNameByAddress %lu tests FAILED.\n", g_FailCount); - } -} - -VOID Test_GetLoadedModulesListEx() -{ - g_FailCount = 0; - - GetLoadedModulesListEx_BasicList(); - GetLoadedModulesListEx_ExtendedList(); - GetLoadedModulesListEx_NullReturnLength(); - GetLoadedModulesListEx_AllocFailure(); - - if (g_Verbose) { - if (g_FailCount == 0) - DbgPrint("[TEST] ntsupGetLoadedModulesListEx PASSED.\n"); - else - DbgPrint("[TEST] ntsupGetLoadedModulesListEx %lu tests FAILED.\n", g_FailCount); - } -} - -VOID Test_GetSystemInfoEx() -{ - g_FailCount = 0; - - GetSystemInfoEx_SystemProcessInformation(); - GetSystemInfoEx_NullReturnLength(); - GetSystemInfoEx_AllocFailure(); - GetSystemInfoEx_InvalidClass(); - - if (g_Verbose) { - if (g_FailCount == 0) - DbgPrint("[TEST] ntsupGetSystemInfoEx tests PASSED.\n"); - else - DbgPrint("[TEST] ntsupGetSystemInfoEx %lu tests FAILED.\n", g_FailCount); - } -} - -VOID Test_HashImageSections() -{ - g_FailCount = 0; - - HashImageSections_LoadedImage(); - HashImageSections_RawFileMapping(); - HashImageSections_NoExecutableSections(); - HashImageSections_ExecutableSectionPresent(); - HashImageSections_InvalidParams(); - - if (g_Verbose) { - if (g_FailCount == 0) - DbgPrint("[TEST] ntsupHashImageSections tests PASSED.\n"); - else - DbgPrint("[TEST] ntsupHashImageSections%lu tests FAILED.\n", g_FailCount); - } -} -#pragma warning(pop) diff --git a/Source/WinObjEx64/tests/ntsup_tests.h b/Source/WinObjEx64/tests/ntsup_tests.h deleted file mode 100644 index f7e92c0..0000000 --- a/Source/WinObjEx64/tests/ntsup_tests.h +++ /dev/null @@ -1,25 +0,0 @@ -/******************************************************************************* -* -* (C) COPYRIGHT AUTHORS, 2015 - 2025 UGN/HE -* -* TITLE: NTSUP_TESTS.H -* -* VERSION: 2.09 -* -* DATE: 10 Aug 2025 -* -* Common header file for NTSUP test code. -* -* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF -* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED -* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A -* PARTICULAR PURPOSE. -* -*******************************************************************************/ -#pragma once - -VOID Test_WriteBufferToFile(); -VOID Test_FindModuleNameByAddress(); -VOID Test_GetLoadedModulesListEx(); -VOID Test_GetSystemInfoEx(); -VOID Test_HashImageSections(); diff --git a/Source/WinObjEx64/tests/testunit.c b/Source/WinObjEx64/tests/testunit.c index 9120880..b9afdd0 100644 --- a/Source/WinObjEx64/tests/testunit.c +++ b/Source/WinObjEx64/tests/testunit.c @@ -4,9 +4,9 @@ * * TITLE: TESTUNIT.C * -* VERSION: 2.10 +* VERSION: 2.12 * -* DATE: 10 Feb 2026 +* DATE: 25 Jul 2026 * * Test code used while debug. * @@ -25,7 +25,6 @@ #include #pragma warning(pop) #include -#include "ntsup_tests.h" HANDLE g_TestNamespace = NULL, g_TestMutex = NULL; HANDLE g_TestMailslot = NULL; @@ -1577,11 +1576,6 @@ VOID TestStart( PreHashTypes(); //TestJob(); //TestDefineDosDevice(); - Test_WriteBufferToFile(); - Test_FindModuleNameByAddress(); - Test_GetLoadedModulesListEx(); - Test_GetSystemInfoEx(); - Test_HashImageSections(); //Test_RegDeleteKeyTree(); } diff --git a/Source/WinObjEx64/ui.h b/Source/WinObjEx64/ui.h index 6e97a88..89f8e01 100644 --- a/Source/WinObjEx64/ui.h +++ b/Source/WinObjEx64/ui.h @@ -4,9 +4,9 @@ * * TITLE: UI.H * -* VERSION: 2.11 +* VERSION: 2.12 * -* DATE: 12 Jul 2026 +* DATE: 28 Jul 2026 * * Common header file for the user interface. * @@ -49,8 +49,8 @@ typedef HWND(WINAPI *pfnHtmlHelpW)( #define PROGRAM_MAJOR_VERSION 2 #define PROGRAM_MINOR_VERSION 1 -#define PROGRAM_REVISION_NUMBER 1 -#define PROGRAM_BUILD_NUMBER 2607 +#define PROGRAM_REVISION_NUMBER 2 +#define PROGRAM_BUILD_NUMBER 2608 #ifdef _USE_OWN_DRIVER #define PROGRAM_NAME L"Windows Object Explorer 64-bit (Non-public version)" @@ -198,6 +198,9 @@ typedef struct _LVCOLUMNS_DATA { #define ErrShadowWin32kOffsetNotFound 11 #define ErrShadowWin32kGetStateNotFound 12 +#define OBEX_DEFAULT_WIDTH 800 +#define OBEX_DEFAULT_HEIGHT 600 + // // Common Dialog handlers. //