├── Compiled ├── NtCall64.exe └── badcalls.ini ├── LICENSE.md ├── NtCall64.sha256 ├── README.md ├── Source ├── NtCall64.sln └── NtCall64 │ ├── blacklist.c │ ├── blacklist.h │ ├── fuzz.c │ ├── fuzz.h │ ├── global.h │ ├── hde │ ├── hde64.c │ ├── hde64.h │ ├── pstdint.h │ └── table64.h │ ├── log.c │ ├── log.h │ ├── main.c │ ├── minirtl │ ├── _filename.c │ ├── _filename.h │ ├── _strcat.c │ ├── _strcmp.c │ ├── _strcmpi.c │ ├── _strcpy.c │ ├── _strend.c │ ├── _strlen.c │ ├── _strncmp.c │ ├── _strncpy.c │ ├── cmdline.c │ ├── cmdline.h │ ├── minirtl.h │ ├── rtltypes.h │ ├── strtou64.c │ ├── strtoul.c │ ├── u64tohex.c │ ├── u64tostr.c │ ├── ultohex.c │ └── ultostr.c │ ├── ntbuilds.h │ ├── ntos.h │ ├── resource.h │ ├── resource.rc │ ├── sup.c │ ├── sup.h │ ├── syscall.asm │ ├── tables.h │ ├── wfuzzer.vcxproj │ ├── wfuzzer.vcxproj.filters │ └── wfuzzer.vcxproj.user └── appveyor.yml /Compiled/NtCall64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hfiref0x/NtCall64/af16a90d95415c59a8c215d18d73b37a90b2deea/Compiled/NtCall64.exe -------------------------------------------------------------------------------- /Compiled/badcalls.ini: -------------------------------------------------------------------------------- 1 | [ntos] 2 | NtClose 3 | NtInitiatePowerAction 4 | NtRaiseHardError 5 | NtReleaseKeyedEvent 6 | NtPropagationComplete 7 | NtShutdownSystem 8 | NtSuspendProcess 9 | NtSuspendThread 10 | NtTerminateProcess 11 | NtTerminateThread 12 | NtWaitForAlertByThreadId 13 | NtWaitForSingleObject 14 | NtWaitForKeyedEvent 15 | 16 | [win32k] 17 | NtUserRealWaitMessageEx 18 | NtUserShowSystemCursor 19 | NtUserSwitchDesktop 20 | NtUserLockWorkStation 21 | NtUserEnumDisplayMonitors 22 | NtUserGetMessage 23 | NtUserWaitMessage 24 | NtUserDoSoundConnect 25 | NtUserRealInternalGetMessage 26 | NtUserBroadcastThemeChangeEvent 27 | NtUserWaitAvailableMessageEx 28 | NtUserMsgWaitForMultipleObjectsEx -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 - 2023, NtCall64 Project 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | * Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /NtCall64.sha256: -------------------------------------------------------------------------------- 1 | 83a3c4632f0f685a56a5c0c54531eba10f32533c74590a011efe439c8a13d83e *Compiled\badcalls.ini 2 | aec6ca2f29b1c474ea1aa8e9a620a557be4391aa951ce35fcc98f45788cf8182 *Compiled\NtCall64.exe 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build status](https://ci.appveyor.com/api/projects/status/7aio324c7pkmqxfm?svg=true)](https://ci.appveyor.com/project/hfiref0x/ntcall64) 2 | 3 | # NTCALL64 4 | ## Windows NT x64 syscall fuzzer. 5 | 6 | This program based on NtCall by Peter Kosyh. It isn't advanced version and its purpose - port NtCall functionality for x64 Windows NT 6+. 7 | 8 | # System Requirements 9 | 10 | + x64 Windows 7/8/8.1/10/11; 11 | + Account with administrative privileges (optional). 12 | 13 | # Usage 14 | NTCALL64 -help[-win32k][-log][-call Id][-pc Value][-wt Value][-s] 15 | 16 | * -help - show program parameters help; 17 | * -log - enable logging via COM1 port, service parameters will be logged (slow), default disabled; 18 | * -pname - port name for logging, default COM1 (-log enabled required, mutual exclusive with -ofile); 19 | * -ofile - file name for logging, default ntcall64.log (-log enabled required, mutual exclusive with -pname); 20 | * -win32k - launch W32pServiceTable services fuzzing (sometimes referenced as Shadow SSDT); 21 | * -call Id - fuzz syscall by supplied id (id can be from any table ntos/win32k); 22 | * -pc Value - set pass count for each syscall (maximum value is limited to ULONG64 max value), default value 65536; 23 | * -wt Value - set wait timeout for calling threads in seconds (except single syscall fuzzing), default value is 30; 24 | * -start Id - Fuzz syscall table starting from given syscall id, mutual exclusive with -call; 25 | * -s - Attempt to run program from LocalSystem account. 26 | 27 | 28 | When used without parameters NtCall64 will start fuzzing services in KiServiceTable (ntos, sometimes referenced as SSDT). 29 | 30 | Default timeout of each fuzzing thread is set to 30 sec. If logging enabled then timeout extended to 120 sec. 31 | 32 | Note that when used with -call option all blacklists will be ignored and fuzzing thread timeout will be set to INFINITE. 33 | 34 | Example: 35 | + ntcall64 -log 36 | + ntcall64 -log -pc 1234 37 | + ntcall64 -log -pc 1234 -call 4096 38 | + ntcall64 -log -ofile mylog.txt 39 | + ntcall64 -win32k -log -pname COM2 40 | + ntcall64 -win32k 41 | + ntcall64 -win32k -log 42 | + ntcall64 -win32k -log -pc 1234 43 | + ntcall64 -call 4097 44 | + ntcall64 -call 4097 -log 45 | + ntcall64 -call 4097 -log -pc 1000 46 | + ntcall64 -pc 1000 47 | + ntcall64 -s 48 | + ntcall64 -pc 1000 -s 49 | 50 | Note: make sure to configure Windows crash dump settings before trying this tool 51 | 52 | (e.g. https://msdn.microsoft.com/en-us/library/windows/hardware/ff542953(v=vs.85).aspx). 53 | 54 | # How it work 55 | 56 | It brute-force through system services and call them multiple times with input parameters randomly taken from predefined "bad arguments" list. 57 | 58 | 59 | # Configuration 60 | 61 | By using badcalls.ini configuration file you can blacklist certain services. To do this - add service name (case sensitive) to the corresponding section of the badcalls.ini, e.g. if you want to blacklist services from KiServiceTable then use [ntos] section. 62 | 63 | Example of badcalls.ini (default config shipped with program) 64 | 65 |
[ntos]
 66 | NtClose
 67 | NtInitiatePowerAction
 68 | NtRaiseHardError
 69 | NtReleaseKeyedEvent
 70 | NtPropagationComplete
 71 | NtShutdownSystem
 72 | NtSuspendProcess
 73 | NtSuspendThread
 74 | NtTerminateProcess
 75 | NtTerminateThread
 76 | NtWaitForAlertByThreadId
 77 | NtWaitForSingleObject
 78 | NtWaitForKeyedEvent
 79 | 
 80 | [win32k]
 81 | NtUserRealWaitMessageEx
 82 | NtUserShowSystemCursor
 83 | NtUserSwitchDesktop
 84 | NtUserLockWorkStation
 85 | NtUserEnumDisplayMonitors
 86 | NtUserGetMessage
 87 | NtUserWaitMessage
 88 | NtUserDoSoundConnect
 89 | NtUserRealInternalGetMessage
 90 | NtUserBroadcastThemeChangeEvent
 91 | NtUserWaitAvailableMessageEx
 92 | NtUserMsgWaitForMultipleObjectsEx
93 | 94 | # Warning 95 | 96 | This program may crash the operation system, affect it stability, which may result in data lost or program crash itself. You use it at your own risk. 97 | 98 | # Bugs found with NtCall64 99 | 100 | * [win32k!NtGdiDdDDISetHwProtectionTeardownRecovery](https://gist.githubusercontent.com/hfiref0x/6901a8e571946e84d8adb1c6f720fdad/raw/63c27cc71828969f7802ad5f7677f2bafe6d84fb/gistfile1.txt) 101 | * [win32k!NtUserCreateActivationObject](https://gist.githubusercontent.com/hfiref0x/23a2331588e7765664f50cac26cf0637/raw/49457ef5e30049b6b4ca392e489aaceaafe2b280/NtUserCreateActivationObject.cpp) 102 | * [win32k!NtUserOpenDesktop](https://gist.githubusercontent.com/hfiref0x/6e726b352da7642fc5b84bf6ebce0007/raw/8df05220f194da4980f401e15a0efdb7694deb26/NtUserOpenDesktop.c) 103 | * [win32k!NtUserSetWindowsHookEx](https://gist.github.com/hfiref0x/8ecfbcc0a7afcc9917cef093ef3a18b2) 104 | * [win32k!NtUserInitialize->win32kbase!Win32kBaseUserInitialize](https://gist.github.com/hfiref0x/f731e690e6155c6763b801ce0e497db7) 105 | * [nt!NtLoadEnclaveData](https://gist.githubusercontent.com/hfiref0x/1ac328a8e73d053012e02955d38e36a8/raw/b26174f8b7b68506d62308ce4327dfc573b8aa26/main.c) 106 | * [nt!NtCreateIoRing](https://gist.github.com/hfiref0x/bd6365a7cfa881da0e9c9e7a917a051b) 107 | * [nt!NtQueryInformationCpuPartition](https://gist.github.com/hfiref0x/48bdc12241d0a981a6da473e979c8aff) 108 | 109 | 110 | # Build 111 | 112 | NTCALL64 comes with full source code written in C with tiny assembler usage. 113 | In order to build from source you need Microsoft Visual Studio 2017 and later versions. 114 | 115 | ## Instructions 116 | 117 | * Select Platform ToolSet first for project in solution you want to build (Project->Properties->General): 118 | * v141 for Visual Studio 2017; 119 | * v142 for Visual Studio 2019; 120 | * v143 for Visual Studio 2022. 121 | * For v140 and above set Target Platform Version (Project->Properties->General): 122 | * If v140 then select 8.1; 123 | * If v141 and above then select 10. 124 | * Minimum required Windows SDK version 8.1 125 | 126 | # Authors 127 | 128 | (c) 2016 - 2023 NTCALL64 Project 129 | 130 | Original NtCall by Peter Kosyh aka Gloomy (c) 2001, http://gl00my.chat.ru/ 131 | -------------------------------------------------------------------------------- /Source/NtCall64.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.168 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NtCall64", "NtCall64\wfuzzer.vcxproj", "{69B98EF8-BA16-40CB-829B-A53D857D0104}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {69B98EF8-BA16-40CB-829B-A53D857D0104}.Debug|x64.ActiveCfg = Debug|x64 15 | {69B98EF8-BA16-40CB-829B-A53D857D0104}.Debug|x64.Build.0 = Debug|x64 16 | {69B98EF8-BA16-40CB-829B-A53D857D0104}.Release|x64.ActiveCfg = Release|x64 17 | {69B98EF8-BA16-40CB-829B-A53D857D0104}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {6324E2D0-006F-4B7F-8920-E4090CD86707} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Source/NtCall64/blacklist.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * 3 | * (C) COPYRIGHT AUTHORS, 2016 - 2021 4 | * 5 | * TITLE: BLACKLIST.C 6 | * 7 | * VERSION: 1.35 8 | * 9 | * DATE: 21 Feb 2021 10 | * 11 | * Syscall blacklist handling. 12 | * 13 | * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 14 | * ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED 15 | * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 16 | * PARTICULAR PURPOSE. 17 | * 18 | *******************************************************************************/ 19 | 20 | #include "global.h" 21 | 22 | /* 23 | * BlackListCreateFromFile 24 | * 25 | * Purpose: 26 | * 27 | * Read blacklist from ini file to allocated memory. 28 | * 29 | */ 30 | BOOL BlackListCreateFromFile( 31 | _In_ BLACKLIST* BlackList, 32 | _In_ LPCSTR ConfigFileName, 33 | _In_ LPCSTR ConfigSectionName 34 | ) 35 | { 36 | BOOL bResult = FALSE; 37 | LPSTR Section = NULL, SectionPtr; 38 | ULONG nSize, SectionSize, BytesRead, Length; 39 | CHAR ConfigFilePath[MAX_PATH + 16]; 40 | 41 | HANDLE BlackListHeap; 42 | 43 | PBL_ENTRY Entry = NULL; 44 | 45 | do { 46 | 47 | RtlSecureZeroMemory(ConfigFilePath, sizeof(ConfigFilePath)); 48 | GetModuleFileNameA(NULL, (LPSTR)&ConfigFilePath, MAX_PATH); 49 | _filepath_a(ConfigFilePath, ConfigFilePath); 50 | _strcat_a(ConfigFilePath, ConfigFileName); 51 | 52 | BlackListHeap = HeapCreate(HEAP_GROWABLE, 0, 0); 53 | if (BlackListHeap == NULL) 54 | break; 55 | 56 | HeapSetInformation(BlackListHeap, HeapEnableTerminationOnCorruption, NULL, 0); 57 | 58 | nSize = 2 * (1024 * 1024); 59 | 60 | Section = (LPSTR)HeapAlloc(BlackListHeap, HEAP_ZERO_MEMORY, nSize); 61 | if (Section == NULL) 62 | break; 63 | 64 | SectionSize = GetPrivateProfileSectionA(ConfigSectionName, Section, nSize, ConfigFilePath); 65 | if (SectionSize == 0) 66 | break; 67 | 68 | BytesRead = 0; 69 | SectionPtr = Section; 70 | 71 | RtlSecureZeroMemory(BlackList, sizeof(BLACKLIST)); 72 | 73 | InitializeListHead(&BlackList->ListHead); 74 | 75 | do { 76 | 77 | if (*SectionPtr == 0) 78 | break; 79 | 80 | Length = (ULONG)_strlen_a(SectionPtr) + 1; 81 | BytesRead += Length; 82 | 83 | Entry = (BL_ENTRY*)HeapAlloc(BlackListHeap, HEAP_ZERO_MEMORY, sizeof(BL_ENTRY)); 84 | if (Entry == NULL) { 85 | goto Cleanup; 86 | } 87 | 88 | Entry->Hash = BlackListHashString(SectionPtr); 89 | 90 | InsertTailList(&BlackList->ListHead, &Entry->ListEntry); 91 | 92 | BlackList->NumberOfEntries += 1; 93 | 94 | SectionPtr += Length; 95 | 96 | } while (BytesRead < SectionSize); 97 | 98 | BlackList->HeapHandle = BlackListHeap; 99 | 100 | bResult = TRUE; 101 | 102 | } while (FALSE); 103 | 104 | Cleanup: 105 | 106 | if (bResult == FALSE) { 107 | if (BlackListHeap) HeapDestroy(BlackListHeap); 108 | } 109 | return bResult; 110 | } 111 | 112 | /* 113 | * BlackListEntryPresent 114 | * 115 | * Purpose: 116 | * 117 | * Return TRUE if syscall is in blacklist. 118 | * 119 | */ 120 | BOOL BlackListEntryPresent( 121 | _In_ BLACKLIST* BlackList, 122 | _In_ LPCSTR SyscallName 123 | ) 124 | { 125 | DWORD Hash = BlackListHashString(SyscallName); 126 | 127 | PLIST_ENTRY Head, Next; 128 | BL_ENTRY* entry; 129 | 130 | Head = &BlackList->ListHead; 131 | Next = Head->Flink; 132 | while ((Next != NULL) && (Next != Head)) { 133 | entry = CONTAINING_RECORD(Next, BL_ENTRY, ListEntry); 134 | if (entry->Hash == Hash) 135 | return TRUE; 136 | 137 | Next = Next->Flink; 138 | } 139 | 140 | return FALSE; 141 | } 142 | 143 | /* 144 | * BlackListHashString 145 | * 146 | * Purpose: 147 | * 148 | * Hash string. 149 | * 150 | */ 151 | DWORD BlackListHashString( 152 | _In_ LPCSTR Name 153 | ) 154 | { 155 | DWORD Hash = 5381; 156 | PCHAR p = (PCHAR)Name; 157 | 158 | while (*p) 159 | Hash = 33 * Hash ^ *p++; 160 | 161 | return Hash; 162 | } 163 | 164 | /* 165 | * BlackListDestroy 166 | * 167 | * Purpose: 168 | * 169 | * Destroy blacklist heap and zero blacklist structure. 170 | * 171 | */ 172 | VOID BlackListDestroy( 173 | _In_ BLACKLIST* BlackList 174 | ) 175 | { 176 | if (BlackList) { 177 | if (BlackList->HeapHandle) HeapDestroy(BlackList->HeapHandle); 178 | RtlSecureZeroMemory(BlackList, sizeof(BLACKLIST)); 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /Source/NtCall64/blacklist.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * 3 | * (C) COPYRIGHT AUTHORS, 2016 - 2021 4 | * 5 | * TITLE: BLACKLIST.H 6 | * 7 | * VERSION: 1.35 8 | * 9 | * DATE: 21 Feb 2021 10 | * 11 | * Syscall blacklist header file. 12 | * 13 | * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 14 | * ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED 15 | * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 16 | * PARTICULAR PURPOSE. 17 | * 18 | *******************************************************************************/ 19 | 20 | #pragma once 21 | 22 | typedef struct _BL_ENTRY { 23 | LIST_ENTRY ListEntry; 24 | DWORD Hash; 25 | } BL_ENTRY, * PBL_ENTRY; 26 | 27 | typedef struct _BLACKLIST { 28 | HANDLE HeapHandle; 29 | ULONG NumberOfEntries; 30 | LIST_ENTRY ListHead; 31 | } BLACKLIST, * PBLACKLIST; 32 | 33 | #define CFG_FILE "badcalls.ini" 34 | 35 | DWORD BlackListHashString( 36 | _In_ LPCSTR Name); 37 | 38 | BOOL BlackListCreateFromFile( 39 | _In_ BLACKLIST* BlackList, 40 | _In_ LPCSTR ConfigFileName, 41 | _In_ LPCSTR ConfigSectionName); 42 | 43 | BOOL BlackListEntryPresent( 44 | _In_ BLACKLIST* BlackList, 45 | _In_ LPCSTR SyscallName); 46 | 47 | VOID BlackListDestroy( 48 | _In_ BLACKLIST* BlackList); 49 | -------------------------------------------------------------------------------- /Source/NtCall64/fuzz.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * 3 | * (C) COPYRIGHT AUTHORS, 2016 - 2023 4 | * 5 | * TITLE: FUZZ.C 6 | * 7 | * VERSION: 1.37 8 | * 9 | * DATE: 04 Aug 2023 10 | * 11 | * Fuzzing routines. 12 | * 13 | * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 14 | * ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED 15 | * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 16 | * PARTICULAR PURPOSE. 17 | * 18 | *******************************************************************************/ 19 | 20 | #include "global.h" 21 | #include "tables.h" 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | NTSTATUS ntSyscallGate(ULONG ServiceId, ULONG ArgumentCount, ULONG_PTR* Arguments); 27 | #ifdef __cplusplus 28 | } 29 | #endif 30 | 31 | #define FUZZDATA_COUNT 13 32 | const ULONG_PTR FuzzData[FUZZDATA_COUNT] = { 33 | 0x0000000000000000, 0x000000000000ffff, 0x000000000000fffe, 0x00007ffffffeffff, 34 | 0x00007ffffffefffe, 0x00007fffffffffff, 0x00007ffffffffffe, 0x0000800000000000, 35 | 0x8000000000000000, 0xffff080000000000, 0xfffff80000000000, 0xffff800000000000, 36 | 0xffff800000000001 37 | }; 38 | 39 | 40 | /* 41 | * FuzzEnumWin32uServices 42 | * 43 | * Purpose: 44 | * 45 | * Enumerate win32u module services to the table. 46 | * 47 | */ 48 | ULONG FuzzEnumWin32uServices( 49 | _In_ HANDLE HeapHandle, 50 | _In_ LPVOID ModuleBase, 51 | _Inout_ PWIN32_SHADOWTABLE* Table 52 | ) 53 | { 54 | ULONG i, j, result = 0, exportSize; 55 | PBYTE fnptr; 56 | PDWORD funcTable, nameTableBase; 57 | PWORD nameOrdinalTableBase; 58 | PWIN32_SHADOWTABLE w32kTableEntry; 59 | PIMAGE_EXPORT_DIRECTORY pImageExportDirectory; 60 | 61 | pImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(ModuleBase, 62 | TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exportSize); 63 | 64 | if (pImageExportDirectory) { 65 | 66 | nameTableBase = (PDWORD)RtlOffsetToPointer(ModuleBase, pImageExportDirectory->AddressOfNames); 67 | nameOrdinalTableBase = (PUSHORT)RtlOffsetToPointer(ModuleBase, pImageExportDirectory->AddressOfNameOrdinals); 68 | funcTable = (PDWORD)RtlOffsetToPointer(ModuleBase, pImageExportDirectory->AddressOfFunctions); 69 | 70 | result = 0; 71 | 72 | for (i = 0; i < pImageExportDirectory->NumberOfFunctions; ++i) { 73 | 74 | fnptr = (PBYTE)RtlOffsetToPointer(ModuleBase, funcTable[nameOrdinalTableBase[i]]); 75 | if (*(PDWORD)fnptr != 0xb8d18b4c) //mov r10, rcx; mov eax 76 | continue; 77 | 78 | w32kTableEntry = (PWIN32_SHADOWTABLE)HeapAlloc(HeapHandle, 79 | HEAP_ZERO_MEMORY, sizeof(WIN32_SHADOWTABLE)); 80 | 81 | if (w32kTableEntry == NULL) 82 | break; 83 | 84 | w32kTableEntry->Index = *(PDWORD)(fnptr + 4); 85 | 86 | for (j = 0; j < pImageExportDirectory->NumberOfNames; ++j) 87 | { 88 | if (nameOrdinalTableBase[j] == i) 89 | { 90 | _strncpy_a(&w32kTableEntry->Name[0], 91 | sizeof(w32kTableEntry->Name), 92 | (LPCSTR)RtlOffsetToPointer(ModuleBase, nameTableBase[j]), 93 | sizeof(w32kTableEntry->Name)); 94 | 95 | break; 96 | } 97 | } 98 | 99 | ++result; 100 | 101 | *Table = w32kTableEntry; 102 | Table = &w32kTableEntry->NextService; 103 | } 104 | } 105 | 106 | return result; 107 | } 108 | 109 | /* 110 | * FuzzResolveW32kServiceNameById 111 | * 112 | * Purpose: 113 | * 114 | * Return service name if found by id in prebuilt lookup table. 115 | * 116 | */ 117 | PCHAR FuzzResolveW32kServiceNameById( 118 | _In_ ULONG ServiceId, 119 | _In_opt_ PWIN32_SHADOWTABLE ShadowTable 120 | ) 121 | { 122 | PWIN32_SHADOWTABLE Entry = ShadowTable; 123 | 124 | while (Entry) { 125 | 126 | if (Entry->Index == ServiceId) { 127 | return Entry->Name; 128 | } 129 | Entry = Entry->NextService; 130 | } 131 | 132 | return NULL; 133 | } 134 | 135 | /* 136 | * FuzzFindKiServiceTable 137 | * 138 | * Purpose: 139 | * 140 | * Locate KiServiceTable in mapped ntoskrnl copy. 141 | * 142 | */ 143 | BOOLEAN FuzzFindKiServiceTable( 144 | _In_ PVOID MappedImageBase, 145 | _In_ PRAW_SERVICE_TABLE ServiceTable 146 | ) 147 | { 148 | ULONG_PTR SectionPtr = 0; 149 | PBYTE ptrCode = (PBYTE)MappedImageBase; 150 | IMAGE_NT_HEADERS* NtHeaders = RtlImageNtHeader(MappedImageBase); 151 | IMAGE_SECTION_HEADER* SectionTableEntry; 152 | ULONG c, p, SectionSize = 0, SectionVA = 0; 153 | 154 | const BYTE KiSystemServiceStartPattern[] = { 0x45, 0x33, 0xC9, 0x44, 0x8B, 0x05 }; 155 | 156 | SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeaders + 157 | sizeof(ULONG) + 158 | sizeof(IMAGE_FILE_HEADER) + 159 | NtHeaders->FileHeader.SizeOfOptionalHeader); 160 | 161 | c = NtHeaders->FileHeader.NumberOfSections; 162 | while (c > 0) { 163 | if (*(PULONG)SectionTableEntry->Name == 'EGAP') 164 | if ((SectionTableEntry->Name[4] == 'L') && 165 | (SectionTableEntry->Name[5] == 'K') && 166 | (SectionTableEntry->Name[6] == 0)) 167 | 168 | { 169 | SectionVA = SectionTableEntry->VirtualAddress; 170 | SectionPtr = (ULONG_PTR)RtlOffsetToPointer(MappedImageBase, SectionVA); 171 | SectionSize = SectionTableEntry->Misc.VirtualSize; 172 | break; 173 | } 174 | c -= 1; 175 | SectionTableEntry += 1; 176 | } 177 | 178 | if ((SectionPtr == 0) || (SectionSize == 0) || (SectionVA == 0)) { 179 | return FALSE; 180 | } 181 | 182 | p = 0; 183 | for (c = 0; c < (SectionSize - sizeof(KiSystemServiceStartPattern)); c++) 184 | if (RtlCompareMemory( 185 | (PVOID)(SectionPtr + c), 186 | KiSystemServiceStartPattern, 187 | sizeof(KiSystemServiceStartPattern)) == sizeof(KiSystemServiceStartPattern)) 188 | { 189 | p = SectionVA + c; 190 | break; 191 | } 192 | 193 | if (p == 0) 194 | return FALSE; 195 | 196 | p += 3; 197 | c = *((PULONG)(ptrCode + p + 3)) + 7 + p; 198 | ServiceTable->CountOfEntries = *((PULONG)(ptrCode + c)); 199 | p += 7; 200 | c = *((PULONG)(ptrCode + p + 3)) + 7 + p; 201 | ServiceTable->StackArgumentTable = (PBYTE)ptrCode + c; 202 | p += 7; 203 | c = *((PULONG)(ptrCode + p + 3)) + 7 + p; 204 | ServiceTable->ServiceTable = (LPVOID*)(ptrCode + c); 205 | 206 | return TRUE; 207 | } 208 | 209 | /* 210 | * FuzzFindW32pServiceTable 211 | * 212 | * Purpose: 213 | * 214 | * Locate shadow table info in mapped win32k copy. 215 | * 216 | */ 217 | BOOLEAN FuzzFindW32pServiceTable( 218 | _In_ PVOID MappedImageBase, 219 | _In_ PRAW_SERVICE_TABLE ServiceTable 220 | ) 221 | { 222 | PULONG ServiceLimit; 223 | 224 | ServiceLimit = (ULONG*)supLdrGetProcAddressEx(MappedImageBase, "W32pServiceLimit"); 225 | if (ServiceLimit == NULL) 226 | return FALSE; 227 | 228 | ServiceTable->CountOfEntries = *ServiceLimit; 229 | ServiceTable->StackArgumentTable = (PBYTE)supLdrGetProcAddressEx(MappedImageBase, "W32pArgumentTable"); 230 | if (ServiceTable->StackArgumentTable == NULL) 231 | return FALSE; 232 | 233 | ServiceTable->ServiceTable = (LPVOID*)supLdrGetProcAddressEx(MappedImageBase, "W32pServiceTable"); 234 | if (ServiceTable->ServiceTable == NULL) 235 | return FALSE; 236 | 237 | return TRUE; 238 | } 239 | 240 | /* 241 | * DoSystemCall 242 | * 243 | * Purpose: 244 | * 245 | * Fuzzing procedure, building parameters list and using syscall gate. 246 | * 247 | */ 248 | VOID DoSystemCall( 249 | _In_ ULONG ServiceId, 250 | _In_ ULONG ParametersInStack, 251 | _In_ PVOID LogParams 252 | ) 253 | { 254 | ULONG c; 255 | ULONG_PTR args[MAX_PARAMETERS]; 256 | 257 | RtlSecureZeroMemory(args, sizeof(args)); 258 | 259 | ParametersInStack /= 4; 260 | 261 | for (c = 0; c < ParametersInStack + 4; c++) { 262 | args[c] = FuzzData[__rdtsc() % FUZZDATA_COUNT]; 263 | } 264 | 265 | if (g_ctx.LogEnabled) { 266 | 267 | FuzzLogCallParameters((PNTCALL_LOG_PARAMS)LogParams, 268 | ServiceId, 269 | ParametersInStack + 4, 270 | (ULONG_PTR*)&args); 271 | 272 | } 273 | 274 | ntSyscallGate(ServiceId, ParametersInStack + 4, args); 275 | } 276 | 277 | /* 278 | * FuzzLookupWin32kNames 279 | * 280 | * Purpose: 281 | * 282 | * Build shadow table service names list. 283 | * 284 | */ 285 | BOOLEAN FuzzLookupWin32kNames( 286 | _Inout_ NTCALL_CONTEXT* Context 287 | ) 288 | { 289 | ULONG dwBuildNumber = 0, i; 290 | PVOID MappedImageBase = Context->SystemModuleBase; 291 | PIMAGE_NT_HEADERS NtHeaders = RtlImageNtHeader((PVOID)MappedImageBase); 292 | PRAW_SERVICE_TABLE ServiceTable = &Context->ServiceTable; 293 | ULONG_PTR Address; 294 | PCHAR* lpServiceNames; 295 | 296 | DWORD64* pW32pServiceTable = NULL; 297 | PCHAR* pszNames = NULL; 298 | PCHAR pfn; 299 | 300 | IMAGE_IMPORT_BY_NAME* ImportEntry; 301 | 302 | HMODULE win32u = NULL; 303 | ULONG win32uLimit; 304 | PWIN32_SHADOWTABLE ShadowTable = NULL; 305 | 306 | PCHAR lpServiceName; 307 | 308 | hde64s hs; 309 | 310 | #ifdef _DEBUG 311 | dwBuildNumber = g_ctx.OsVersion.dwBuildNumber; 312 | #else 313 | dwBuildNumber = g_ctx.OsVersion.dwBuildNumber; 314 | #endif 315 | 316 | switch (dwBuildNumber) { 317 | 318 | case NT_WIN7_RTM: 319 | case NT_WIN7_SP1: 320 | if (ServiceTable->CountOfEntries != W32pServiceTableLimit_7601) 321 | return FALSE; 322 | pszNames = (CHAR**)W32pServiceTableNames_7601; 323 | break; 324 | 325 | case NT_WIN8_RTM: 326 | if (ServiceTable->CountOfEntries != W32pServiceTableLimit_9200) 327 | return FALSE; 328 | pszNames = (CHAR**)W32pServiceTableNames_9200; 329 | break; 330 | 331 | case NT_WIN8_BLUE: 332 | if (ServiceTable->CountOfEntries != W32pServiceTableLimit_9600) 333 | return FALSE; 334 | pszNames = (CHAR**)W32pServiceTableNames_9600; 335 | break; 336 | 337 | default: 338 | if (ServiceTable->CountOfEntries == 0 || ServiceTable->CountOfEntries > 0x10000) 339 | return FALSE; 340 | break; 341 | } 342 | 343 | lpServiceNames = (CHAR**)supHeapAlloc(ServiceTable->CountOfEntries * sizeof(PCHAR)); 344 | 345 | if (lpServiceNames == NULL) 346 | return FALSE; 347 | 348 | Context->Win32pServiceTableNames = lpServiceNames; 349 | 350 | pW32pServiceTable = (DWORD64*)ServiceTable->ServiceTable; 351 | 352 | // 353 | // Query service names. 354 | // If win32k version below 10240 copy them from predefined array. 355 | // Otherwise lookup them dynamically. 356 | // 357 | if (dwBuildNumber < NT_WIN10_THRESHOLD1) { 358 | if (pszNames == NULL) 359 | return FALSE; 360 | 361 | for (i = 0; i < ServiceTable->CountOfEntries; i++) { 362 | lpServiceNames[i] = pszNames[i]; 363 | } 364 | } 365 | else { 366 | 367 | if (dwBuildNumber >= NT_WIN10_REDSTONE1) { 368 | 369 | win32u = GetModuleHandle(TEXT("win32u.dll")); 370 | if (win32u == NULL) { 371 | ConsoleShowMessage("[!] Failed to reference win32u.dll.\r\n", 372 | FOREGROUND_RED | FOREGROUND_INTENSITY); 373 | return FALSE; 374 | } 375 | 376 | win32uLimit = FuzzEnumWin32uServices(GetProcessHeap(), (LPVOID)win32u, &ShadowTable); 377 | 378 | if ((win32uLimit != ServiceTable->CountOfEntries) || (ShadowTable == NULL)) { 379 | ConsoleShowMessage("[!] Win32u services enumeration failed.\r\n", 380 | FOREGROUND_RED | FOREGROUND_INTENSITY); 381 | return FALSE; 382 | } 383 | 384 | } 385 | 386 | for (i = 0; i < ServiceTable->CountOfEntries; i++) { 387 | 388 | lpServiceName = "UnknownName"; 389 | 390 | if (dwBuildNumber <= NT_WIN10_THRESHOLD2) { 391 | pfn = (PCHAR)(pW32pServiceTable[i] - NtHeaders->OptionalHeader.ImageBase + (ULONG_PTR)MappedImageBase); 392 | hde64_disasm((void*)pfn, &hs); 393 | if (hs.flags & F_ERROR) { 394 | 395 | ConsoleShowMessage("[!]FuzzLookupWin32kNames HDE error.\r\n", 396 | FOREGROUND_RED | FOREGROUND_INTENSITY); 397 | 398 | break; 399 | } 400 | Address = (ULONG_PTR)MappedImageBase + *(ULONG_PTR*)(pfn + hs.len + *(DWORD*)(pfn + (hs.len - 4))); 401 | if (Address) { 402 | ImportEntry = (IMAGE_IMPORT_BY_NAME*)Address; 403 | lpServiceName = ImportEntry->Name; 404 | } 405 | } 406 | else if (dwBuildNumber >= NT_WIN10_REDSTONE1) { 407 | 408 | lpServiceName = FuzzResolveW32kServiceNameById(i + W32SYSCALLSTART, ShadowTable); 409 | if (lpServiceName == NULL) 410 | lpServiceName = "UnknownName"; 411 | 412 | } 413 | lpServiceNames[i] = lpServiceName; 414 | } 415 | } 416 | 417 | return TRUE; 418 | } 419 | 420 | /* 421 | * FuzzThreadProc 422 | * 423 | * Purpose: 424 | * 425 | * Handler for fuzzing thread. 426 | * 427 | */ 428 | DWORD WINAPI FuzzThreadProc( 429 | PVOID Parameter 430 | ) 431 | { 432 | ULONG64 i, c; 433 | HMODULE hUser32 = NULL; 434 | CALL_PARAM* Context = (CALL_PARAM*)Parameter; 435 | 436 | if (Context->Syscall >= W32SYSCALLSTART) 437 | hUser32 = LoadLibrary(TEXT("user32.dll")); 438 | 439 | c = Context->NumberOfPassesForCall; 440 | 441 | for (i = 0; i < c; i++) { 442 | DoSystemCall(Context->Syscall, Context->ParametersInStack, Context->LogParams); 443 | } 444 | 445 | if (hUser32) 446 | FreeLibrary(hUser32); 447 | 448 | ExitThread(0); 449 | } 450 | 451 | /* 452 | * PrintServiceInformation 453 | * 454 | * Purpose: 455 | * 456 | * Display service information. 457 | * 458 | */ 459 | void PrintServiceInformation( 460 | _In_ ULONG NumberOfArguments, 461 | _In_ ULONG ServiceId, 462 | _In_opt_ LPCSTR ServiceName, 463 | _In_ BOOL BlackListed) 464 | { 465 | CHAR* pLog; 466 | CHAR szConsoleText[4096]; 467 | WORD wColor = 0; 468 | 469 | _strcpy_a(szConsoleText, "\t#"); 470 | ultostr_a(ServiceId, _strend_a(szConsoleText)); 471 | 472 | pLog = _strcat_a(szConsoleText, "\tArgs(stack): "); 473 | ultostr_a(NumberOfArguments, pLog); 474 | 475 | pLog = _strcat_a(szConsoleText, "\t"); 476 | if (ServiceName) { 477 | _strncpy_a(pLog, MAX_PATH, ServiceName, MAX_PATH); 478 | } 479 | else { 480 | _strcpy_a(pLog, "Unknown"); 481 | } 482 | 483 | if (BlackListed) { 484 | _strcat_a(szConsoleText, " - found in blacklist, skip\r\n"); 485 | wColor = FOREGROUND_GREEN | FOREGROUND_INTENSITY; 486 | } 487 | else { 488 | _strcat_a(szConsoleText, "\r\n"); 489 | } 490 | 491 | ConsoleShowMessage(szConsoleText, wColor); 492 | } 493 | 494 | /* 495 | * FuzzRunThreadWithWait 496 | * 497 | * Purpose: 498 | * 499 | * Run fuzzing thread and wait. 500 | * 501 | */ 502 | VOID FuzzRunThreadWithWait( 503 | _In_ CALL_PARAM* CallParams 504 | ) 505 | { 506 | HANDLE hThread; 507 | DWORD dwThreadId; 508 | CHAR szConsoleText[100]; 509 | 510 | hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)FuzzThreadProc, 511 | (LPVOID)CallParams, 0, &dwThreadId); 512 | 513 | if (hThread) { 514 | if (WaitForSingleObject(hThread, CallParams->ThreadTimeout) == WAIT_TIMEOUT) { 515 | #pragma warning(push) 516 | #pragma warning(disable: 6258) 517 | TerminateThread(hThread, MAXDWORD); 518 | #pragma warning(pop) 519 | _strcpy_a(szConsoleText, "\t^Timeout reached for callproc of service: "); 520 | ultostr_a(CallParams->Syscall, _strend_a(szConsoleText)); 521 | _strcat_a(szConsoleText, "\r\n"); 522 | ConsoleShowMessage(szConsoleText, 0); 523 | } 524 | CloseHandle(hThread); 525 | } 526 | } 527 | 528 | /* 529 | * FuzzRun 530 | * 531 | * Purpose: 532 | * 533 | * Perform syscall table fuzzing. 534 | * 535 | */ 536 | VOID FuzzRun( 537 | _In_ NTCALL_CONTEXT* Context 538 | ) 539 | { 540 | BOOL probeWin32k = Context->ProbeWin32k, bSkip = FALSE; 541 | BLACKLIST* BlackList = &Context->BlackList; 542 | PVOID ntdllBase = Context->NtdllBase; 543 | PRAW_SERVICE_TABLE ServiceTable = &Context->ServiceTable; 544 | ULONG c, sid; 545 | 546 | CALL_PARAM CallParams; 547 | 548 | PCHAR lpServiceName, pLog; 549 | 550 | CHAR szOut[MAX_PATH * 2]; 551 | 552 | ConsoleShowMessage("[+] Entering FuzzRun()\r\n", 553 | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); 554 | 555 | // 556 | // If single syscall mode, just call it. 557 | // 558 | if (Context->ProbeSingleSyscall) { 559 | 560 | // 561 | // Query service name. 562 | // 563 | if (probeWin32k) { 564 | sid = Context->u1.SingleSyscallId - W32SYSCALLSTART; 565 | lpServiceName = Context->Win32pServiceTableNames[sid]; 566 | } 567 | else { 568 | sid = Context->u1.SingleSyscallId; 569 | lpServiceName = supLdrGetProcNameBySDTIndex(ntdllBase, sid); 570 | } 571 | 572 | // 573 | // Output service information to console. 574 | // 575 | _strcpy_a(szOut, "\tProbing #"); 576 | ultostr_a(Context->u1.SingleSyscallId, _strend_a(szOut)); 577 | pLog = _strcat_a(szOut, "\t"); 578 | if (lpServiceName) { 579 | _strncpy_a(pLog, MAX_PATH, lpServiceName, MAX_PATH); 580 | } 581 | else { 582 | _strcpy_a(pLog, "Unknown"); 583 | } 584 | _strcat_a(pLog, "\r\n"); 585 | ConsoleShowMessage(szOut, 0); 586 | 587 | // 588 | // Setup service call parameters and call it in separate thread. 589 | // 590 | CallParams.ParametersInStack = Context->ServiceTable.StackArgumentTable[sid]; 591 | CallParams.Syscall = Context->u1.SingleSyscallId; 592 | CallParams.ThreadTimeout = INFINITE; 593 | CallParams.NumberOfPassesForCall = Context->SyscallPassCount; 594 | CallParams.LogParams = &g_Log; 595 | 596 | FuzzRunThreadWithWait(&CallParams); 597 | } 598 | else { 599 | 600 | c = 0; 601 | if (Context->ProbeFromSyscallId) { 602 | if (Context->ProbeWin32k) 603 | c = Context->u1.StartingSyscallId - W32SYSCALLSTART; 604 | else 605 | c = Context->u1.StartingSyscallId; 606 | } 607 | 608 | for (; c < ServiceTable->CountOfEntries; c++) { 609 | 610 | // 611 | // Query service name. 612 | // 613 | if (probeWin32k) { 614 | lpServiceName = Context->Win32pServiceTableNames[c]; 615 | sid = W32SYSCALLSTART + c; 616 | } 617 | else { 618 | lpServiceName = supLdrGetProcNameBySDTIndex(ntdllBase, c); 619 | sid = c; 620 | } 621 | 622 | if (lpServiceName) { 623 | bSkip = BlackListEntryPresent(BlackList, (LPCSTR)lpServiceName); 624 | } 625 | 626 | // 627 | // Output service information to console. 628 | // 629 | PrintServiceInformation(ServiceTable->StackArgumentTable[c] / 4, 630 | sid, 631 | lpServiceName, 632 | bSkip); 633 | 634 | if (bSkip) { 635 | bSkip = FALSE; 636 | continue; 637 | } 638 | 639 | // 640 | // Log service name. 641 | // 642 | /* 643 | if (Context->LogEnabled) 644 | FuzzLogCallName(Context->LogHandle, ServiceName); 645 | */ 646 | 647 | // 648 | // Setup service call parameters and call it in separate thread. 649 | // 650 | CallParams.Syscall = sid; 651 | CallParams.ParametersInStack = Context->ServiceTable.StackArgumentTable[c]; 652 | CallParams.ThreadTimeout = (Context->ThreadWaitTimeout * 1000); 653 | CallParams.NumberOfPassesForCall = Context->SyscallPassCount; 654 | CallParams.LogParams = &g_Log; 655 | 656 | if (Context->LogEnabled) 657 | CallParams.ThreadTimeout *= 4; //extend timeout with logging 658 | 659 | FuzzRunThreadWithWait(&CallParams); 660 | 661 | } 662 | 663 | } 664 | 665 | ConsoleShowMessage("[-] Leaving FuzzRun()\r\n", 666 | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); 667 | } 668 | -------------------------------------------------------------------------------- /Source/NtCall64/fuzz.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * 3 | * (C) COPYRIGHT AUTHORS, 2016 - 2023 4 | * 5 | * TITLE: FUZZ.H 6 | * 7 | * VERSION: 1.37 8 | * 9 | * DATE: 04 Aug 2023 10 | * 11 | * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 12 | * ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED 13 | * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 14 | * PARTICULAR PURPOSE. 15 | * 16 | *******************************************************************************/ 17 | #pragma once 18 | 19 | #define W32SYSCALLSTART 0x1000 20 | #define MAX_PARAMETERS 32 21 | 22 | #define FUZZ_THREAD_TIMEOUT_SEC (30) 23 | #define FUZZ_PASS_COUNT (64) * (1024) 24 | 25 | VOID FuzzRun( 26 | _In_ NTCALL_CONTEXT *Context); 27 | 28 | BOOLEAN FuzzLookupWin32kNames( 29 | _Inout_ NTCALL_CONTEXT *Context); 30 | 31 | BOOLEAN FuzzFindW32pServiceTable( 32 | _In_ PVOID MappedImageBase, 33 | _In_ PRAW_SERVICE_TABLE ServiceTable); 34 | 35 | BOOLEAN FuzzFindKiServiceTable( 36 | _In_ PVOID MappedImageBase, 37 | _In_ PRAW_SERVICE_TABLE ServiceTable); 38 | -------------------------------------------------------------------------------- /Source/NtCall64/global.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * 3 | * (C) COPYRIGHT AUTHORS, 2016 - 2023 4 | * 5 | * TITLE: GLOBAL.H 6 | * 7 | * VERSION: 1.37 8 | * 9 | * DATE: 04 Aug 2023 10 | * 11 | * Global definitions. 12 | * 13 | * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 14 | * ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED 15 | * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 16 | * PARTICULAR PURPOSE. 17 | * 18 | *******************************************************************************/ 19 | #pragma once 20 | 21 | #if !defined UNICODE 22 | #error ANSI build is not supported 23 | #endif 24 | 25 | #if defined (_MSC_VER) 26 | #if (_MSC_VER >= 1900) 27 | #ifdef _DEBUG 28 | #pragma comment(lib, "vcruntimed.lib") 29 | #pragma comment(lib, "ucrtd.lib") 30 | #pragma comment(lib, "ucrt.lib") 31 | #else 32 | #pragma comment(lib, "libucrt.lib") 33 | #pragma comment(lib, "libvcruntime.lib") 34 | #endif 35 | #endif 36 | #endif 37 | 38 | #pragma warning(disable: 4005) // macro redefinition 39 | 40 | #include 41 | #include 42 | #include 43 | #include "ntos.h" 44 | #include "ntbuilds.h" 45 | #include "hde\hde64.h" 46 | #include "minirtl\minirtl.h" 47 | #include "minirtl\_filename.h" 48 | #include "minirtl\cmdline.h" 49 | #include "blacklist.h" 50 | #include "sup.h" 51 | #include "log.h" 52 | 53 | #pragma comment(lib, "Version.lib") 54 | 55 | typedef struct _RAW_SERVICE_TABLE { 56 | ULONG CountOfEntries; 57 | LPVOID* ServiceTable; 58 | PBYTE StackArgumentTable; 59 | } RAW_SERVICE_TABLE, * PRAW_SERVICE_TABLE; 60 | 61 | typedef struct _CALL_PARAM { 62 | ULONG Syscall; 63 | ULONG ParametersInStack; 64 | ULONG ThreadTimeout; 65 | ULONG64 NumberOfPassesForCall; 66 | PVOID LogParams; 67 | } CALL_PARAM, *PCALL_PARAM; 68 | 69 | typedef struct _NTCALL_CONTEXT { 70 | BOOLEAN LogEnabled; 71 | BOOLEAN ProbeWin32k; 72 | BOOLEAN ProbeSingleSyscall; 73 | BOOLEAN ProbeFromSyscallId; 74 | BOOLEAN IsUserFullAdmin; 75 | BOOLEAN IsLocalSystem; 76 | BOOLEAN IsElevated; 77 | union { 78 | ULONG SingleSyscallId; 79 | ULONG StartingSyscallId; 80 | } u1; 81 | ULONG ThreadWaitTimeout; 82 | ULONG64 SyscallPassCount; 83 | PVOID NtdllBase; 84 | PVOID SystemModuleBase; 85 | PCHAR *Win32pServiceTableNames; 86 | RAW_SERVICE_TABLE ServiceTable; 87 | BLACKLIST BlackList; 88 | RTL_OSVERSIONINFOW OsVersion; 89 | } NTCALL_CONTEXT, *PNTCALL_CONTEXT; 90 | 91 | typedef struct _NTCALL_FUZZ_PARAMS { 92 | BOOLEAN LogEnabled; 93 | BOOLEAN LogToFile; 94 | BOOLEAN ProbeWin32k; 95 | BOOLEAN ProbeSingleSyscall; 96 | BOOLEAN ProbeFromSyscallId; 97 | union { 98 | ULONG SingleSyscallId; 99 | ULONG StartingSyscallId; 100 | } u1; 101 | ULONG ThreadWaitTimeout; 102 | ULONG64 SyscallPassCount; 103 | WCHAR szLogDeviceOrFile[MAX_PATH + 1]; 104 | } NTCALL_FUZZ_PARAMS, *PNTCALL_FUZZ_PARAMS; 105 | 106 | extern NTCALL_CONTEXT g_ctx; 107 | extern NTCALL_LOG_PARAMS g_Log; 108 | 109 | #include "fuzz.h" 110 | -------------------------------------------------------------------------------- /Source/NtCall64/hde/hde64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 64 C 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | */ 7 | 8 | #include "hde64.h" 9 | #include "table64.h" 10 | 11 | #pragma warning(push) 12 | #pragma warning(disable:4701) 13 | #pragma warning(disable:4706) 14 | 15 | unsigned int hde64_disasm(const void *code, hde64s *hs) 16 | { 17 | uint8_t x, c = 0, *p = (uint8_t *)code, cflags, opcode, pref = 0; 18 | uint8_t *ht = hde64_table, m_mod, m_reg, m_rm, disp_size = 0; 19 | uint8_t op64 = 0; 20 | 21 | // Avoid using memset to reduce the footprint. 22 | #ifndef _MSC_VER 23 | memset((LPBYTE)hs, 0, sizeof(hde64s)); 24 | #else 25 | __stosb((LPBYTE)hs, 0, sizeof(hde64s)); 26 | #endif 27 | 28 | for (x = 16; x; x--) 29 | switch (c = *p++) { 30 | case 0xf3: 31 | hs->p_rep = c; 32 | pref |= PRE_F3; 33 | break; 34 | case 0xf2: 35 | hs->p_rep = c; 36 | pref |= PRE_F2; 37 | break; 38 | case 0xf0: 39 | hs->p_lock = c; 40 | pref |= PRE_LOCK; 41 | break; 42 | case 0x26: case 0x2e: case 0x36: 43 | case 0x3e: case 0x64: case 0x65: 44 | hs->p_seg = c; 45 | pref |= PRE_SEG; 46 | break; 47 | case 0x66: 48 | hs->p_66 = c; 49 | pref |= PRE_66; 50 | break; 51 | case 0x67: 52 | hs->p_67 = c; 53 | pref |= PRE_67; 54 | break; 55 | default: 56 | goto pref_done; 57 | } 58 | pref_done: 59 | 60 | hs->flags = (uint32_t)pref << 23; 61 | 62 | if (!pref) 63 | pref |= PRE_NONE; 64 | 65 | if ((c & 0xf0) == 0x40) { 66 | hs->flags |= F_PREFIX_REX; 67 | if ((hs->rex_w = (c & 0xf) >> 3) && (*p & 0xf8) == 0xb8) 68 | op64++; 69 | hs->rex_r = (c & 7) >> 2; 70 | hs->rex_x = (c & 3) >> 1; 71 | hs->rex_b = c & 1; 72 | if (((c = *p++) & 0xf0) == 0x40) { 73 | opcode = c; 74 | goto error_opcode; 75 | } 76 | } 77 | 78 | if ((hs->opcode = c) == 0x0f) { 79 | hs->opcode2 = c = *p++; 80 | ht += DELTA_OPCODES; 81 | } else if (c >= 0xa0 && c <= 0xa3) { 82 | op64++; 83 | if (pref & PRE_67) 84 | pref |= PRE_66; 85 | else 86 | pref &= ~PRE_66; 87 | } 88 | 89 | opcode = c; 90 | cflags = ht[ht[opcode / 4] + (opcode % 4)]; 91 | 92 | if (cflags == C_ERROR) { 93 | error_opcode: 94 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 95 | cflags = 0; 96 | if ((opcode & -3) == 0x24) 97 | cflags++; 98 | } 99 | 100 | x = 0; 101 | if (cflags & C_GROUP) { 102 | uint16_t t; 103 | t = *(uint16_t *)(ht + (cflags & 0x7f)); 104 | cflags = (uint8_t)t; 105 | x = (uint8_t)(t >> 8); 106 | } 107 | 108 | if (hs->opcode2) { 109 | ht = hde64_table + DELTA_PREFIXES; 110 | if (ht[ht[opcode / 4] + (opcode % 4)] & pref) 111 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 112 | } 113 | 114 | if (cflags & C_MODRM) { 115 | hs->flags |= F_MODRM; 116 | hs->modrm = c = *p++; 117 | hs->modrm_mod = m_mod = c >> 6; 118 | hs->modrm_rm = m_rm = c & 7; 119 | hs->modrm_reg = m_reg = (c & 0x3f) >> 3; 120 | 121 | if (x && ((x << m_reg) & 0x80)) 122 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 123 | 124 | if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) { 125 | uint8_t t = opcode - 0xd9; 126 | if (m_mod == 3) { 127 | ht = hde64_table + DELTA_FPU_MODRM + t*8; 128 | t = ht[m_reg] << m_rm; 129 | } else { 130 | ht = hde64_table + DELTA_FPU_REG; 131 | t = ht[t] << m_reg; 132 | } 133 | if (t & 0x80) 134 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 135 | } 136 | 137 | if (pref & PRE_LOCK) { 138 | if (m_mod == 3) { 139 | hs->flags |= F_ERROR | F_ERROR_LOCK; 140 | } else { 141 | uint8_t *table_end, op = opcode; 142 | if (hs->opcode2) { 143 | ht = hde64_table + DELTA_OP2_LOCK_OK; 144 | table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK; 145 | } else { 146 | ht = hde64_table + DELTA_OP_LOCK_OK; 147 | table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK; 148 | op &= -2; 149 | } 150 | for (; ht != table_end; ht++) 151 | if (*ht++ == op) { 152 | if (!((*ht << m_reg) & 0x80)) 153 | goto no_lock_error; 154 | else 155 | break; 156 | } 157 | hs->flags |= F_ERROR | F_ERROR_LOCK; 158 | no_lock_error: 159 | ; 160 | } 161 | } 162 | 163 | if (hs->opcode2) { 164 | switch (opcode) { 165 | case 0x20: case 0x22: 166 | m_mod = 3; 167 | if (m_reg > 4 || m_reg == 1) 168 | goto error_operand; 169 | else 170 | goto no_error_operand; 171 | case 0x21: case 0x23: 172 | m_mod = 3; 173 | if (m_reg == 4 || m_reg == 5) 174 | goto error_operand; 175 | else 176 | goto no_error_operand; 177 | } 178 | } else { 179 | switch (opcode) { 180 | case 0x8c: 181 | if (m_reg > 5) 182 | goto error_operand; 183 | else 184 | goto no_error_operand; 185 | case 0x8e: 186 | if (m_reg == 1 || m_reg > 5) 187 | goto error_operand; 188 | else 189 | goto no_error_operand; 190 | } 191 | } 192 | 193 | if (m_mod == 3) { 194 | uint8_t *table_end; 195 | if (hs->opcode2) { 196 | ht = hde64_table + DELTA_OP2_ONLY_MEM; 197 | table_end = ht + sizeof(hde64_table) - DELTA_OP2_ONLY_MEM; 198 | } else { 199 | ht = hde64_table + DELTA_OP_ONLY_MEM; 200 | table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM; 201 | } 202 | for (; ht != table_end; ht += 2) 203 | if (*ht++ == opcode) { 204 | if (*ht++ & pref && !((*ht << m_reg) & 0x80)) 205 | goto error_operand; 206 | else 207 | break; 208 | } 209 | goto no_error_operand; 210 | } else if (hs->opcode2) { 211 | switch (opcode) { 212 | case 0x50: case 0xd7: case 0xf7: 213 | if (pref & (PRE_NONE | PRE_66)) 214 | goto error_operand; 215 | break; 216 | case 0xd6: 217 | if (pref & (PRE_F2 | PRE_F3)) 218 | goto error_operand; 219 | break; 220 | case 0xc5: 221 | goto error_operand; 222 | } 223 | goto no_error_operand; 224 | } else 225 | goto no_error_operand; 226 | 227 | error_operand: 228 | hs->flags |= F_ERROR | F_ERROR_OPERAND; 229 | no_error_operand: 230 | 231 | c = *p++; 232 | if (m_reg <= 1) { 233 | if (opcode == 0xf6) 234 | cflags |= C_IMM8; 235 | else if (opcode == 0xf7) 236 | cflags |= C_IMM_P66; 237 | } 238 | 239 | switch (m_mod) { 240 | case 0: 241 | if (pref & PRE_67) { 242 | if (m_rm == 6) 243 | disp_size = 2; 244 | } else 245 | if (m_rm == 5) 246 | disp_size = 4; 247 | break; 248 | case 1: 249 | disp_size = 1; 250 | break; 251 | case 2: 252 | disp_size = 2; 253 | if (!(pref & PRE_67)) 254 | disp_size <<= 1; 255 | } 256 | 257 | if (m_mod != 3 && m_rm == 4) { 258 | hs->flags |= F_SIB; 259 | p++; 260 | hs->sib = c; 261 | hs->sib_scale = c >> 6; 262 | hs->sib_index = (c & 0x3f) >> 3; 263 | if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1)) 264 | disp_size = 4; 265 | } 266 | 267 | p--; 268 | switch (disp_size) { 269 | case 1: 270 | hs->flags |= F_DISP8; 271 | hs->disp.disp8 = *p; 272 | break; 273 | case 2: 274 | hs->flags |= F_DISP16; 275 | hs->disp.disp16 = *(uint16_t *)p; 276 | break; 277 | case 4: 278 | hs->flags |= F_DISP32; 279 | hs->disp.disp32 = *(uint32_t *)p; 280 | } 281 | p += disp_size; 282 | } else if (pref & PRE_LOCK) 283 | hs->flags |= F_ERROR | F_ERROR_LOCK; 284 | 285 | if (cflags & C_IMM_P66) { 286 | if (cflags & C_REL32) { 287 | if (pref & PRE_66) { 288 | hs->flags |= F_IMM16 | F_RELATIVE; 289 | hs->imm.imm16 = *(uint16_t *)p; 290 | p += 2; 291 | goto disasm_done; 292 | } 293 | goto rel32_ok; 294 | } 295 | if (op64) { 296 | hs->flags |= F_IMM64; 297 | hs->imm.imm64 = *(uint64_t *)p; 298 | p += 8; 299 | } else if (!(pref & PRE_66)) { 300 | hs->flags |= F_IMM32; 301 | hs->imm.imm32 = *(uint32_t *)p; 302 | p += 4; 303 | } else 304 | goto imm16_ok; 305 | } 306 | 307 | 308 | if (cflags & C_IMM16) { 309 | imm16_ok: 310 | hs->flags |= F_IMM16; 311 | hs->imm.imm16 = *(uint16_t *)p; 312 | p += 2; 313 | } 314 | if (cflags & C_IMM8) { 315 | hs->flags |= F_IMM8; 316 | hs->imm.imm8 = *p++; 317 | } 318 | 319 | if (cflags & C_REL32) { 320 | rel32_ok: 321 | hs->flags |= F_IMM32 | F_RELATIVE; 322 | hs->imm.imm32 = *(uint32_t *)p; 323 | p += 4; 324 | } else if (cflags & C_REL8) { 325 | hs->flags |= F_IMM8 | F_RELATIVE; 326 | hs->imm.imm8 = *p++; 327 | } 328 | 329 | disasm_done: 330 | 331 | if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) { 332 | hs->flags |= F_ERROR | F_ERROR_LENGTH; 333 | hs->len = 15; 334 | } 335 | 336 | return (unsigned int)hs->len; 337 | } 338 | #pragma warning(pop) 339 | -------------------------------------------------------------------------------- /Source/NtCall64/hde/hde64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 64 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | * hde64.h: C/C++ header file 7 | * 8 | */ 9 | 10 | #ifndef _HDE64_H_ 11 | #define _HDE64_H_ 12 | 13 | /* stdint.h - C99 standard header 14 | * http://en.wikipedia.org/wiki/stdint.h 15 | * 16 | * if your compiler doesn't contain "stdint.h" header (for 17 | * example, Microsoft Visual C++), you can download file: 18 | * http://www.azillionmonkeys.com/qed/pstdint.h 19 | * and change next line to: 20 | * #include "pstdint.h" 21 | */ 22 | #include "pstdint.h" 23 | 24 | #define F_MODRM 0x00000001 25 | #define F_SIB 0x00000002 26 | #define F_IMM8 0x00000004 27 | #define F_IMM16 0x00000008 28 | #define F_IMM32 0x00000010 29 | #define F_IMM64 0x00000020 30 | #define F_DISP8 0x00000040 31 | #define F_DISP16 0x00000080 32 | #define F_DISP32 0x00000100 33 | #define F_RELATIVE 0x00000200 34 | #define F_ERROR 0x00001000 35 | #define F_ERROR_OPCODE 0x00002000 36 | #define F_ERROR_LENGTH 0x00004000 37 | #define F_ERROR_LOCK 0x00008000 38 | #define F_ERROR_OPERAND 0x00010000 39 | #define F_PREFIX_REPNZ 0x01000000 40 | #define F_PREFIX_REPX 0x02000000 41 | #define F_PREFIX_REP 0x03000000 42 | #define F_PREFIX_66 0x04000000 43 | #define F_PREFIX_67 0x08000000 44 | #define F_PREFIX_LOCK 0x10000000 45 | #define F_PREFIX_SEG 0x20000000 46 | #define F_PREFIX_REX 0x40000000 47 | #define F_PREFIX_ANY 0x7f000000 48 | 49 | #define PREFIX_SEGMENT_CS 0x2e 50 | #define PREFIX_SEGMENT_SS 0x36 51 | #define PREFIX_SEGMENT_DS 0x3e 52 | #define PREFIX_SEGMENT_ES 0x26 53 | #define PREFIX_SEGMENT_FS 0x64 54 | #define PREFIX_SEGMENT_GS 0x65 55 | #define PREFIX_LOCK 0xf0 56 | #define PREFIX_REPNZ 0xf2 57 | #define PREFIX_REPX 0xf3 58 | #define PREFIX_OPERAND_SIZE 0x66 59 | #define PREFIX_ADDRESS_SIZE 0x67 60 | 61 | #pragma pack(push,1) 62 | 63 | typedef struct { 64 | uint8_t len; 65 | uint8_t p_rep; 66 | uint8_t p_lock; 67 | uint8_t p_seg; 68 | uint8_t p_66; 69 | uint8_t p_67; 70 | uint8_t rex; 71 | uint8_t rex_w; 72 | uint8_t rex_r; 73 | uint8_t rex_x; 74 | uint8_t rex_b; 75 | uint8_t opcode; 76 | uint8_t opcode2; 77 | uint8_t modrm; 78 | uint8_t modrm_mod; 79 | uint8_t modrm_reg; 80 | uint8_t modrm_rm; 81 | uint8_t sib; 82 | uint8_t sib_scale; 83 | uint8_t sib_index; 84 | uint8_t sib_base; 85 | union { 86 | uint8_t imm8; 87 | uint16_t imm16; 88 | uint32_t imm32; 89 | uint64_t imm64; 90 | } imm; 91 | union { 92 | uint8_t disp8; 93 | uint16_t disp16; 94 | uint32_t disp32; 95 | } disp; 96 | uint32_t flags; 97 | } hde64s; 98 | 99 | #pragma pack(pop) 100 | 101 | #ifdef __cplusplus 102 | extern "C" { 103 | #endif 104 | 105 | /* __cdecl */ 106 | unsigned int hde64_disasm(const void *code, hde64s *hs); 107 | 108 | #ifdef __cplusplus 109 | } 110 | #endif 111 | 112 | #endif /* _HDE64_H_ */ 113 | -------------------------------------------------------------------------------- /Source/NtCall64/hde/pstdint.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2015 Tsuda Kageyu. All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #pragma once 28 | 29 | #include 30 | 31 | // Integer types for HDE. 32 | typedef INT8 int8_t; 33 | typedef INT16 int16_t; 34 | typedef INT32 int32_t; 35 | typedef INT64 int64_t; 36 | typedef UINT8 uint8_t; 37 | typedef UINT16 uint16_t; 38 | typedef UINT32 uint32_t; 39 | typedef UINT64 uint64_t; 40 | -------------------------------------------------------------------------------- /Source/NtCall64/hde/table64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 64 C 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | */ 7 | 8 | #define C_NONE 0x00 9 | #define C_MODRM 0x01 10 | #define C_IMM8 0x02 11 | #define C_IMM16 0x04 12 | #define C_IMM_P66 0x10 13 | #define C_REL8 0x20 14 | #define C_REL32 0x40 15 | #define C_GROUP 0x80 16 | #define C_ERROR 0xff 17 | 18 | #define PRE_ANY 0x00 19 | #define PRE_NONE 0x01 20 | #define PRE_F2 0x02 21 | #define PRE_F3 0x04 22 | #define PRE_66 0x08 23 | #define PRE_67 0x10 24 | #define PRE_LOCK 0x20 25 | #define PRE_SEG 0x40 26 | #define PRE_ALL 0xff 27 | 28 | #define DELTA_OPCODES 0x4a 29 | #define DELTA_FPU_REG 0xfd 30 | #define DELTA_FPU_MODRM 0x104 31 | #define DELTA_PREFIXES 0x13c 32 | #define DELTA_OP_LOCK_OK 0x1ae 33 | #define DELTA_OP2_LOCK_OK 0x1c6 34 | #define DELTA_OP_ONLY_MEM 0x1d8 35 | #define DELTA_OP2_ONLY_MEM 0x1e7 36 | 37 | unsigned char hde64_table[] = { 38 | 0xa5,0xaa,0xa5,0xb8,0xa5,0xaa,0xa5,0xaa,0xa5,0xb8,0xa5,0xb8,0xa5,0xb8,0xa5, 39 | 0xb8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xac,0xc0,0xcc,0xc0,0xa1,0xa1, 40 | 0xa1,0xa1,0xb1,0xa5,0xa5,0xa6,0xc0,0xc0,0xd7,0xda,0xe0,0xc0,0xe4,0xc0,0xea, 41 | 0xea,0xe0,0xe0,0x98,0xc8,0xee,0xf1,0xa5,0xd3,0xa5,0xa5,0xa1,0xea,0x9e,0xc0, 42 | 0xc0,0xc2,0xc0,0xe6,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0xab, 43 | 0x8b,0x90,0x64,0x5b,0x5b,0x5b,0x5b,0x5b,0x92,0x5b,0x5b,0x76,0x90,0x92,0x92, 44 | 0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x6a,0x73,0x90, 45 | 0x5b,0x52,0x52,0x52,0x52,0x5b,0x5b,0x5b,0x5b,0x77,0x7c,0x77,0x85,0x5b,0x5b, 46 | 0x70,0x5b,0x7a,0xaf,0x76,0x76,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b, 47 | 0x5b,0x5b,0x86,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xd5,0x03,0xcc,0x01,0xbc, 48 | 0x03,0xf0,0x03,0x03,0x04,0x00,0x50,0x50,0x50,0x50,0xff,0x20,0x20,0x20,0x20, 49 | 0x01,0x01,0x01,0x01,0xc4,0x02,0x10,0xff,0xff,0xff,0x01,0x00,0x03,0x11,0xff, 50 | 0x03,0xc4,0xc6,0xc8,0x02,0x10,0x00,0xff,0xcc,0x01,0x01,0x01,0x00,0x00,0x00, 51 | 0x00,0x01,0x01,0x03,0x01,0xff,0xff,0xc0,0xc2,0x10,0x11,0x02,0x03,0x01,0x01, 52 | 0x01,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x10, 53 | 0x10,0x10,0x10,0x02,0x10,0x00,0x00,0xc6,0xc8,0x02,0x02,0x02,0x02,0x06,0x00, 54 | 0x04,0x00,0x02,0xff,0x00,0xc0,0xc2,0x01,0x01,0x03,0x03,0x03,0xca,0x40,0x00, 55 | 0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,0x00,0x00,0x00, 56 | 0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0xff,0x00, 57 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, 58 | 0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00, 59 | 0xff,0x40,0x40,0x40,0x40,0x41,0x49,0x40,0x40,0x40,0x40,0x4c,0x42,0x40,0x40, 60 | 0x40,0x40,0x40,0x40,0x40,0x40,0x4f,0x44,0x53,0x40,0x40,0x40,0x44,0x57,0x43, 61 | 0x5c,0x40,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, 62 | 0x40,0x40,0x64,0x66,0x6e,0x6b,0x40,0x40,0x6a,0x46,0x40,0x40,0x44,0x46,0x40, 63 | 0x40,0x5b,0x44,0x40,0x40,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x01,0x06, 64 | 0x06,0x02,0x06,0x06,0x00,0x06,0x00,0x0a,0x0a,0x00,0x00,0x00,0x02,0x07,0x07, 65 | 0x06,0x02,0x0d,0x06,0x06,0x06,0x0e,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04, 66 | 0x04,0x04,0x05,0x06,0x06,0x06,0x00,0x00,0x00,0x0e,0x00,0x00,0x08,0x00,0x10, 67 | 0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,0x86,0x00, 68 | 0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,0xf8,0xbb, 69 | 0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,0xc4,0xff, 70 | 0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,0x13,0x09, 71 | 0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,0xb2,0xff, 72 | 0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,0xe7,0x08, 73 | 0x00,0xf0,0x02,0x00 74 | }; 75 | -------------------------------------------------------------------------------- /Source/NtCall64/log.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * 3 | * (C) COPYRIGHT AUTHORS, 2016 - 2021 4 | * 5 | * TITLE: LOG.C 6 | * 7 | * VERSION: 1.35 8 | * 9 | * DATE: 21 Feb 2021 10 | * 11 | * Log support. 12 | * 13 | * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 14 | * ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED 15 | * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 16 | * PARTICULAR PURPOSE. 17 | * 18 | *******************************************************************************/ 19 | 20 | #include "global.h" 21 | 22 | /* 23 | * FuzzOpenLog 24 | * 25 | * Purpose: 26 | * 27 | * Open port/file for logging. 28 | * 29 | */ 30 | BOOLEAN FuzzOpenLog( 31 | _In_ LPWSTR LogDeviceFileName, 32 | _In_ PNTCALL_LOG_PARAMS LogParams 33 | ) 34 | { 35 | HANDLE hFile; 36 | CHAR szWelcome[128]; 37 | DWORD bytesIO; 38 | DWORD openFlags = OPEN_EXISTING; 39 | 40 | if (LogParams->LogToFile) openFlags = CREATE_ALWAYS; //always overwrite existing log file. 41 | 42 | hFile = CreateFile(LogDeviceFileName, 43 | GENERIC_WRITE | SYNCHRONIZE, 44 | FILE_SHARE_READ | FILE_SHARE_WRITE, 45 | NULL, 46 | openFlags, 47 | FILE_FLAG_WRITE_THROUGH, 48 | NULL); 49 | 50 | if (hFile != INVALID_HANDLE_VALUE) { 51 | 52 | _strcpy_a(szWelcome, "\r\n[NC64] Logging start.\r\n"); 53 | WriteFile(hFile, (LPCVOID)&szWelcome, 54 | (DWORD)_strlen_a(szWelcome), &bytesIO, NULL); 55 | 56 | LogParams->LogHandle = hFile; 57 | 58 | return TRUE; 59 | } 60 | 61 | return FALSE; 62 | } 63 | 64 | /* 65 | * FuzzCloseLog 66 | * 67 | * Purpose: 68 | * 69 | * Close log file or port handle. 70 | * 71 | */ 72 | VOID FuzzCloseLog( 73 | _In_ PNTCALL_LOG_PARAMS LogParams 74 | ) 75 | { 76 | CHAR szBye[128]; 77 | DWORD bytesIO; 78 | 79 | HANDLE logHandle = LogParams->LogHandle; 80 | 81 | if (logHandle == INVALID_HANDLE_VALUE) 82 | return; 83 | 84 | _strcpy_a(szBye, "\r\n[NC64] Log stop.\r\n"); 85 | WriteFile(logHandle, 86 | (LPCVOID)&szBye, (DWORD)_strlen_a(szBye), &bytesIO, NULL); 87 | 88 | CloseHandle(logHandle); 89 | LogParams->LogHandle = INVALID_HANDLE_VALUE; 90 | } 91 | 92 | /* 93 | * FuzzLogCallName 94 | * 95 | * Purpose: 96 | * 97 | * Send syscall name to the log before it is not too late. 98 | * 99 | */ 100 | VOID FuzzLogCallName( 101 | _In_ PNTCALL_LOG_PARAMS LogParams, 102 | _In_ LPCSTR ServiceName 103 | ) 104 | { 105 | ULONG bytesIO; 106 | HANDLE logHandle = LogParams->LogHandle; 107 | CHAR szLog[128]; 108 | 109 | if (logHandle != INVALID_HANDLE_VALUE) { 110 | WriteFile(logHandle, (LPCVOID)ServiceName, 111 | (DWORD)_strlen_a(ServiceName), &bytesIO, NULL); 112 | 113 | _strcpy_a(szLog, "\r\n"); 114 | WriteFile(logHandle, (LPCVOID)&szLog, 115 | (DWORD)_strlen_a(szLog), &bytesIO, NULL); 116 | } 117 | } 118 | 119 | /* 120 | * FuzzLogCallParameters 121 | * 122 | * Purpose: 123 | * 124 | * Send syscall parameters to the log before it is not too late. 125 | * 126 | */ 127 | VOID FuzzLogCallParameters( 128 | _In_ PNTCALL_LOG_PARAMS LogParams, 129 | _In_ ULONG ServiceId, 130 | _In_ ULONG NumberOfArguments, 131 | _In_ ULONG_PTR* Arguments 132 | ) 133 | { 134 | ULONG i; 135 | DWORD bytesIO; 136 | HANDLE logHandle = LogParams->LogHandle; 137 | BOOL logToFile = LogParams->LogToFile; 138 | CHAR szLog[2048]; 139 | 140 | if (logHandle == INVALID_HANDLE_VALUE) 141 | return; 142 | 143 | _strcpy_a(szLog, "[NC64] "); 144 | ultostr_a(ServiceId, _strend_a(szLog)); 145 | ultostr_a(NumberOfArguments, _strcat_a(szLog, "\t")); 146 | _strcat_a(szLog, "\t"); 147 | 148 | for (i = 0; i < NumberOfArguments; i++) { 149 | u64tohex_a(Arguments[i], _strcat_a(szLog, " ")); 150 | } 151 | _strcat_a(szLog, "\r\n"); 152 | WriteFile(logHandle, (LPCVOID)&szLog, 153 | (DWORD)_strlen_a(szLog), &bytesIO, NULL); 154 | 155 | if (logToFile) 156 | FlushFileBuffers(logHandle); 157 | } 158 | -------------------------------------------------------------------------------- /Source/NtCall64/log.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * 3 | * (C) COPYRIGHT AUTHORS, 2016 - 2023 4 | * 5 | * TITLE: LOG.H 6 | * 7 | * VERSION: 1.37 8 | * 9 | * DATE: 04 Aug 2023 10 | * 11 | * Log support header file. 12 | * 13 | * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 14 | * ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED 15 | * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 16 | * PARTICULAR PURPOSE. 17 | * 18 | *******************************************************************************/ 19 | 20 | #pragma once 21 | 22 | typedef struct _NTCALL_LOG_PARAMS { 23 | BOOL LogToFile; 24 | HANDLE LogHandle; 25 | } NTCALL_LOG_PARAMS, * PNTCALL_LOG_PARAMS; 26 | 27 | BOOLEAN FuzzOpenLog( 28 | _In_ LPWSTR LogDeviceFileName, 29 | _In_ PNTCALL_LOG_PARAMS LogParams); 30 | 31 | VOID FuzzCloseLog( 32 | _In_ PNTCALL_LOG_PARAMS LogParams); 33 | 34 | VOID FuzzLogCallName( 35 | _In_ PNTCALL_LOG_PARAMS LogParams, 36 | _In_ LPCSTR ServiceName); 37 | 38 | VOID FuzzLogCallParameters( 39 | _In_ PNTCALL_LOG_PARAMS LogParams, 40 | _In_ ULONG ServiceId, 41 | _In_ ULONG NumberOfArguments, 42 | _In_ ULONG_PTR* Arguments); 43 | -------------------------------------------------------------------------------- /Source/NtCall64/main.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * 3 | * (C) COPYRIGHT AUTHORS, 2016 - 2023 4 | * 5 | * TITLE: MAIN.C 6 | * 7 | * VERSION: 1.37 8 | * 9 | * DATE: 04 Aug 2023 10 | * 11 | * Program entry point. 12 | * 13 | * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 14 | * ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED 15 | * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 16 | * PARTICULAR PURPOSE. 17 | * 18 | *******************************************************************************/ 19 | 20 | #include "global.h" 21 | 22 | #define PARAM_LOG TEXT("-log") 23 | #define PARAM_LOGPORT TEXT("-pname") 24 | #define PARAM_LOGFILE TEXT("-ofile") 25 | #define PARAM_WIN32K TEXT("-win32k") 26 | #define PARAM_SYSCALL TEXT("-call") 27 | #define PARAM_PASSCOUNT TEXT("-pc") 28 | #define PARAM_WAITTIMEOUT TEXT("-wt") 29 | #define PARAM_HELP TEXT("-help") 30 | #define PARAM_LOCALSYSTEM TEXT("-s") 31 | #define PARAM_SYSCALL_START TEXT("-start") 32 | 33 | #define DEFAULT_LOG_PORT TEXT("COM1") 34 | #define DEFAULT_LOG_FILE TEXT("ntcall64.log") 35 | 36 | #define WELCOME_BANNER "NtCall64, Windows NT x64 syscall fuzzer, based on NtCall by Peter Kosyh.\r\n" 37 | #define VERSION_BANNER "Version 1.3.7 from 04 Aug 2023\r\n\n" 38 | 39 | // 40 | // Help output. 41 | // 42 | #define T_HELP "Usage: -help [-win32k][-log [-pname][-ofile]][-call Id][-pc Value][-wt Value][-s]\r\n\ 43 | -help - Show this help information;\r\n\ 44 | -log - Enable logging to file last call parameters, use -ofile to specify file otherwise COM port will be used;\r\n\ 45 | -pname - Port name for logging, default COM1 (-log enabled required, mutual exclusive with -ofile);\r\n\ 46 | -ofile - File name for logging, default ntcall64.log (-log enabled required, mutual exclusive with -pname);\r\n\ 47 | -win32k - Fuzz win32k graphical subsystem table, otherwise fuzz ntos table;\r\n\ 48 | -call Id - Fuzz syscall by supplied numeric (can be from any table). All blacklists are ignored;\r\n\ 49 | -pc Value - Set number of passes for each service to , default value 65536;\r\n\ 50 | -wt Value - Set wait timeout for calling threads in seconds (except single syscall fuzzing), default value is 30;\r\n\ 51 | -start Id - Fuzz syscall table starting from given syscall id, mutual exclusive with -call;\r\n\ 52 | -s - Attempt to run program from LocalSystem account.\r\n\n\ 53 | Example: ntcall64.exe -win32k -log" 54 | 55 | // 56 | // Global context. 57 | // 58 | NTCALL_CONTEXT g_ctx; 59 | NTCALL_LOG_PARAMS g_Log; 60 | 61 | typedef struct _PRIVSET { 62 | ULONG Privilege; 63 | LPCSTR Name; 64 | } PRIVSET, * PPRIVSET; 65 | 66 | PRIVSET g_privs[] = { 67 | { SE_CREATE_TOKEN_PRIVILEGE, "SE_CREATE_TOKEN_PRIVILEGE" }, 68 | { SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, "SE_ASSIGNPRIMARYTOKEN_PRIVILEGE" }, 69 | { SE_LOCK_MEMORY_PRIVILEGE, "SE_LOCK_MEMORY_PRIVILEGE" }, 70 | { SE_INCREASE_QUOTA_PRIVILEGE, "SE_INCREASE_QUOTA_PRIVILEGE" }, 71 | { SE_MACHINE_ACCOUNT_PRIVILEGE, "SE_MACHINE_ACCOUNT_PRIVILEGE" }, 72 | { SE_TCB_PRIVILEGE, "SE_TCB_PRIVILEGE" }, 73 | { SE_SECURITY_PRIVILEGE, "SE_SECURITY_PRIVILEGE" }, 74 | { SE_TAKE_OWNERSHIP_PRIVILEGE, "SE_TAKE_OWNERSHIP_PRIVILEGE" }, 75 | { SE_LOAD_DRIVER_PRIVILEGE, "SE_LOAD_DRIVER_PRIVILEGE"}, 76 | { SE_SYSTEM_PROFILE_PRIVILEGE, "SE_SYSTEM_PROFILE_PRIVILEGE"}, 77 | { SE_SYSTEMTIME_PRIVILEGE, "SE_SYSTEMTIME_PRIVILEGE"}, 78 | { SE_PROF_SINGLE_PROCESS_PRIVILEGE, "SE_PROF_SINGLE_PROCESS_PRIVILEGE" }, 79 | { SE_INC_BASE_PRIORITY_PRIVILEGE, "SE_INC_BASE_PRIORITY_PRIVILEGE" }, 80 | { SE_CREATE_PAGEFILE_PRIVILEGE, "SE_CREATE_PAGEFILE_PRIVILEGE" }, 81 | { SE_CREATE_PERMANENT_PRIVILEGE, "SE_CREATE_PERMANENT_PRIVILEGE" }, 82 | { SE_BACKUP_PRIVILEGE, "SE_BACKUP_PRIVILEGE" }, 83 | { SE_RESTORE_PRIVILEGE, "SE_RESTORE_PRIVILEGE" }, 84 | { SE_SHUTDOWN_PRIVILEGE, "SE_SHUTDOWN_PRIVILEGE" }, 85 | { SE_DEBUG_PRIVILEGE, "SE_DEBUG_PRIVILEGE" }, 86 | { SE_AUDIT_PRIVILEGE, "SE_AUDIT_PRIVILEGE" }, 87 | { SE_SYSTEM_ENVIRONMENT_PRIVILEGE, "SE_SYSTEM_ENVIRONMENT_PRIVILEGE" }, 88 | { SE_CHANGE_NOTIFY_PRIVILEGE, "SE_CHANGE_NOTIFY_PRIVILEGE" }, 89 | { SE_REMOTE_SHUTDOWN_PRIVILEGE, "SE_REMOTE_SHUTDOWN_PRIVILEGE" }, 90 | { SE_UNDOCK_PRIVILEGE, "SE_UNDOCK_PRIVILEGE" }, 91 | { SE_SYNC_AGENT_PRIVILEGE, "SE_SYNC_AGENT_PRIVILEGE" }, 92 | { SE_ENABLE_DELEGATION_PRIVILEGE, "SE_ENABLE_DELEGATION_PRIVILEGE" }, 93 | { SE_MANAGE_VOLUME_PRIVILEGE, "SE_MANAGE_VOLUME_PRIVILEGE" }, 94 | { SE_IMPERSONATE_PRIVILEGE, "SE_IMPERSONATE_PRIVILEGE" }, 95 | { SE_CREATE_GLOBAL_PRIVILEGE, "SE_CREATE_GLOBAL_PRIVILEGE" }, 96 | { SE_TRUSTED_CREDMAN_ACCESS_PRIVILEGE, "SE_TRUSTED_CREDMAN_ACCESS_PRIVILEGE" }, 97 | { SE_RELABEL_PRIVILEGE, "SE_RELABEL_PRIVILEGE" }, 98 | { SE_INC_WORKING_SET_PRIVILEGE, "SE_INC_WORKING_SET_PRIVILEGE" }, 99 | { SE_TIME_ZONE_PRIVILEGE, "SE_TIME_ZONE_PRIVILEGE" }, 100 | { SE_CREATE_SYMBOLIC_LINK_PRIVILEGE, "SE_CREATE_SYMBOLIC_LINK_PRIVILEGE" } 101 | }; 102 | 103 | 104 | /* 105 | * VehHandler 106 | * 107 | * Purpose: 108 | * 109 | * Vectored exception handler. 110 | * 111 | */ 112 | LONG CALLBACK VehHandler( 113 | EXCEPTION_POINTERS* ExceptionInfo 114 | ) 115 | { 116 | HMODULE hModule = GetModuleHandle(TEXT("kernel32.dll")); 117 | if (hModule) { 118 | ExceptionInfo->ContextRecord->Rip = (DWORD64)GetProcAddress(hModule, "ExitThread"); 119 | } 120 | return EXCEPTION_CONTINUE_EXECUTION; 121 | } 122 | 123 | /* 124 | * FuzzInitPhase2 125 | * 126 | * Purpose: 127 | * 128 | * Load system image, locate table and start fuzzing. 129 | * 130 | */ 131 | void FuzzInitPhase2( 132 | _In_ NTCALL_CONTEXT* Context 133 | ) 134 | { 135 | BOOL probeWin32k = Context->ProbeWin32k; 136 | ULONG d; 137 | 138 | NTSTATUS ntStatus; 139 | UNICODE_STRING usModule; 140 | 141 | WCHAR szBuffer[MAX_PATH * 2]; 142 | 143 | ConsoleShowMessage("[+] Entering FuzzInitPhase2()\r\n", 144 | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); 145 | 146 | _strcpy(szBuffer, L"\\systemroot\\system32\\"); 147 | if (probeWin32k) { 148 | _strcat(szBuffer, TEXT("win32k.sys")); 149 | } 150 | else { 151 | _strcat(szBuffer, TEXT("ntoskrnl.exe")); 152 | } 153 | 154 | RtlInitUnicodeString(&usModule, szBuffer); 155 | 156 | ntStatus = supMapImageNoExecute(&usModule, &Context->SystemModuleBase); 157 | 158 | if (!NT_SUCCESS(ntStatus) || (Context->SystemModuleBase == NULL)) { 159 | supShowNtStatus("[!] Could not preload system image, abort!\r\n", ntStatus); 160 | return; 161 | } 162 | 163 | if (probeWin32k) { 164 | 165 | if (!FuzzFindW32pServiceTable(Context->SystemModuleBase, &Context->ServiceTable)) { 166 | ConsoleShowMessage("[!] Could not find W32pServiceTable, abort!\r\n", 167 | FOREGROUND_RED | FOREGROUND_INTENSITY); 168 | return; 169 | } 170 | 171 | if (!FuzzLookupWin32kNames(Context)) { 172 | ConsoleShowMessage("[!] Win32k names query error, abort!\r\n", 173 | FOREGROUND_RED | FOREGROUND_INTENSITY); 174 | return; 175 | } 176 | } 177 | else { 178 | 179 | Context->NtdllBase = (PVOID)GetModuleHandle(TEXT("ntdll.dll")); 180 | if (Context->NtdllBase == NULL) { 181 | ConsoleShowMessage("[!] NTDLL not found, abort!\r\n", 182 | FOREGROUND_RED | FOREGROUND_INTENSITY); 183 | return; 184 | } 185 | 186 | if (!FuzzFindKiServiceTable(Context->SystemModuleBase, &Context->ServiceTable)) { 187 | ConsoleShowMessage("[!] KiServiceTable not found, abort!\r\n", 188 | FOREGROUND_RED | FOREGROUND_INTENSITY); 189 | return; 190 | } 191 | } 192 | 193 | // 194 | // Validate syscall id. 195 | // 196 | if (Context->ProbeSingleSyscall) { 197 | 198 | d = Context->u1.SingleSyscallId; 199 | 200 | if (Context->ProbeWin32k) { 201 | d -= W32SYSCALLSTART; 202 | } 203 | 204 | if (d >= Context->ServiceTable.CountOfEntries) { 205 | 206 | ConsoleShowMessage("[!] Syscall number exceeds current system available range.\r\n", 207 | FOREGROUND_RED | FOREGROUND_INTENSITY); 208 | return; 209 | 210 | } 211 | 212 | } 213 | 214 | FuzzRun(Context); 215 | 216 | NtUnmapViewOfSection(NtCurrentProcess(), Context->SystemModuleBase); 217 | 218 | ConsoleShowMessage("[-] Leaving FuzzInitPhase2()\r\n", 219 | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); 220 | } 221 | 222 | /* 223 | * FuzzInitPhase1 224 | * 225 | * Purpose: 226 | * 227 | * Initial preparations for probing. 228 | * 229 | */ 230 | VOID FuzzInitPhase1( 231 | _In_ NTCALL_FUZZ_PARAMS* FuzzParams 232 | ) 233 | { 234 | BOOLEAN LogEnabled = FALSE; 235 | BOOLEAN bWasEnabled = FALSE; 236 | WORD wColor = 0; 237 | UINT i; 238 | 239 | CHAR szOut[MAX_PATH * 2]; 240 | 241 | ConsoleShowMessage("[+] Entering FuzzInitPhase1()\r\n", 242 | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); 243 | 244 | g_ctx.ThreadWaitTimeout = FuzzParams->ThreadWaitTimeout; 245 | 246 | if (g_ctx.IsLocalSystem) 247 | ConsoleShowMessage("[+] LocalSystem account\r\n", 0); 248 | 249 | if (g_ctx.IsUserFullAdmin) { 250 | ConsoleShowMessage("[+] User is with admin privileges\r\n", 0); 251 | 252 | if (g_ctx.IsElevated) { 253 | ConsoleShowMessage("[+] NtCall64 runs elevated.\r\n", 0); 254 | } 255 | else { 256 | ConsoleShowMessage("[+] NtCall64 is not elevated, some privileges can not be adjusted.\r\n", 0); 257 | } 258 | } 259 | 260 | // 261 | // Show current directory. 262 | // 263 | RtlSecureZeroMemory(szOut, sizeof(szOut)); 264 | _strcpy_a(szOut, "[+] Current directory: "); 265 | GetCurrentDirectoryA(MAX_PATH, _strend_a(szOut)); 266 | _strcat_a(szOut, "\r\n"); 267 | ConsoleShowMessage(szOut, 0); 268 | 269 | // 270 | // Show command line. 271 | // 272 | ConsoleShowMessage("[+] Command line -> \r\n\r\n", 0); 273 | ConsoleShowMessage(GetCommandLineA(), 0); 274 | ConsoleShowMessage("\r\n\r\n", 0); 275 | 276 | // 277 | // Show version logo if possible. 278 | // 279 | g_ctx.OsVersion.dwOSVersionInfoSize = sizeof(g_ctx.OsVersion); 280 | RtlGetVersion(&g_ctx.OsVersion); 281 | 282 | _strcpy_a(szOut, "[~] Windows version: "); 283 | ultostr_a(g_ctx.OsVersion.dwMajorVersion, _strend_a(szOut)); 284 | ultostr_a(g_ctx.OsVersion.dwMinorVersion, _strcat_a(szOut, ".")); 285 | ultostr_a(g_ctx.OsVersion.dwBuildNumber, _strcat_a(szOut, ".")); 286 | _strcat_a(szOut, "\r\n"); 287 | ConsoleShowMessage(szOut, 0); 288 | 289 | if (FuzzParams->LogEnabled) { 290 | 291 | g_Log.LogHandle = INVALID_HANDLE_VALUE; 292 | g_Log.LogToFile = FuzzParams->LogToFile; 293 | 294 | LogEnabled = FuzzOpenLog(FuzzParams->szLogDeviceOrFile, &g_Log); 295 | if (!LogEnabled) { 296 | 297 | _strcpy_a(szOut, "[!] Log open error, GetLastError() = "); 298 | ultostr_a(GetLastError(), _strend_a(szOut)); 299 | _strcat_a(szOut, ", logging is disabled\r\n"); 300 | 301 | ConsoleShowMessage(szOut, FOREGROUND_RED | FOREGROUND_INTENSITY); 302 | 303 | } 304 | else { 305 | _strcpy_a(szOut, "[+] Logging is enabled, output will be written to "); 306 | 307 | WideCharToMultiByte(CP_ACP, 0, FuzzParams->szLogDeviceOrFile, -1, 308 | _strend_a(szOut), MAX_PATH, NULL, NULL); 309 | 310 | _strcat_a(szOut, "\r\n"); 311 | 312 | ConsoleShowMessage(szOut, 313 | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); 314 | } 315 | 316 | g_ctx.LogEnabled = LogEnabled; 317 | 318 | } 319 | else { 320 | g_ctx.LogEnabled = FALSE; 321 | } 322 | 323 | // 324 | // Handle single system call. 325 | // 326 | if (FuzzParams->ProbeSingleSyscall) { 327 | g_ctx.ProbeWin32k = (FuzzParams->u1.SingleSyscallId >= W32SYSCALLSTART); 328 | g_ctx.ProbeSingleSyscall = TRUE; 329 | g_ctx.u1.SingleSyscallId = FuzzParams->u1.SingleSyscallId; 330 | } 331 | else { 332 | g_ctx.ProbeWin32k = FuzzParams->ProbeWin32k; 333 | } 334 | 335 | // 336 | // Remember pass count. 337 | // 338 | g_ctx.SyscallPassCount = FuzzParams->SyscallPassCount; 339 | _strcpy_a(szOut, "[+] Number of passes for each syscall = "); 340 | u64tostr_a(g_ctx.SyscallPassCount, _strend_a(szOut)); 341 | _strcat_a(szOut, "\r\n"); 342 | ConsoleShowMessage(szOut, 0); 343 | 344 | // 345 | // Show wait timeout. 346 | // 347 | _strcpy_a(szOut, "[+] Wait timeout for caller threads (seconds) = "); 348 | ultostr_a(g_ctx.ThreadWaitTimeout, _strend_a(szOut)); 349 | _strcat_a(szOut, "\r\n"); 350 | ConsoleShowMessage(szOut, 0); 351 | 352 | // 353 | // Show probe from syscall id. 354 | // 355 | g_ctx.ProbeFromSyscallId = FuzzParams->ProbeFromSyscallId; 356 | g_ctx.u1.StartingSyscallId = FuzzParams->u1.StartingSyscallId; 357 | if (g_ctx.ProbeFromSyscallId) { 358 | _strcpy_a(szOut, "[+] Starting syscall id "); 359 | ultostr_a(g_ctx.u1.StartingSyscallId, _strend_a(szOut)); 360 | _strcat_a(szOut, "\r\n"); 361 | ConsoleShowMessage(szOut, 0); 362 | } 363 | 364 | // 365 | // Assign much possible privileges if can. 366 | // 367 | for (i = 0; i < _countof(g_privs); i++) { 368 | _strcpy_a(szOut, "[*] Privilege "); 369 | _strcat_a(szOut, g_privs[i].Name); 370 | 371 | if (NT_SUCCESS(RtlAdjustPrivilege(g_privs[i].Privilege, TRUE, FALSE, &bWasEnabled))) { 372 | _strcat_a(szOut, " adjusted\r\n"); 373 | wColor = FOREGROUND_GREEN | FOREGROUND_INTENSITY; 374 | } 375 | else { 376 | _strcat_a(szOut, " not adjusted\r\n"); 377 | wColor = FOREGROUND_RED | FOREGROUND_BLUE; 378 | } 379 | ConsoleShowMessage(szOut, wColor); 380 | } 381 | 382 | if (g_ctx.ProbeWin32k) { 383 | 384 | ConsoleShowMessage("[*] Win32k table probe mode.\r\n", 385 | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); 386 | Sleep(1000); 387 | 388 | BlackListCreateFromFile(&g_ctx.BlackList, CFG_FILE, (LPCSTR)"win32k"); 389 | } 390 | else { 391 | 392 | ConsoleShowMessage("[*] Ntoskrnl table probe mode.\r\n", 393 | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); 394 | Sleep(1000); 395 | 396 | BlackListCreateFromFile(&g_ctx.BlackList, CFG_FILE, (LPCSTR)"ntos"); 397 | } 398 | 399 | FuzzInitPhase2(&g_ctx); 400 | 401 | // 402 | // Cleanup. 403 | // 404 | 405 | BlackListDestroy(&g_ctx.BlackList); 406 | 407 | if (LogEnabled) { 408 | ConsoleShowMessage("[-] Logging stop\r\n", 0); 409 | FuzzCloseLog(&g_Log); 410 | } 411 | 412 | if (g_ctx.Win32pServiceTableNames) 413 | supHeapFree(g_ctx.Win32pServiceTableNames); 414 | 415 | ConsoleShowMessage("[-] Leaving FuzzInitPhase1()\r\n", 416 | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); 417 | } 418 | 419 | /* 420 | * FuzzInitPhase0 421 | * 422 | * Purpose: 423 | * 424 | * Parse command line options. 425 | * 426 | */ 427 | VOID FuzzInitPhase0( 428 | VOID 429 | ) 430 | { 431 | ULONG rLen; 432 | NTCALL_FUZZ_PARAMS fuzzParams; 433 | HANDLE hToken; 434 | NTSTATUS ntStatus; 435 | 436 | WCHAR szTextBuf[MAX_PATH + 1]; 437 | 438 | do { 439 | 440 | ConsoleShowMessage("[+] Entering FuzzInitPhase0()\r\n", 441 | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); 442 | 443 | RtlSecureZeroMemory(&fuzzParams, sizeof(fuzzParams)); 444 | fuzzParams.ThreadWaitTimeout = FUZZ_THREAD_TIMEOUT_SEC; 445 | fuzzParams.SyscallPassCount = FUZZ_PASS_COUNT; 446 | 447 | RtlSecureZeroMemory(&g_ctx, sizeof(g_ctx)); 448 | 449 | ntStatus = NtOpenProcessToken(NtCurrentProcess(), TOKEN_QUERY, &hToken); 450 | if (NT_SUCCESS(ntStatus)) { 451 | 452 | ntStatus = supIsLocalSystem(hToken, &g_ctx.IsLocalSystem); 453 | if (NT_SUCCESS(ntStatus)) { 454 | if (g_ctx.IsLocalSystem) { 455 | g_ctx.IsElevated = TRUE; 456 | g_ctx.IsUserFullAdmin = TRUE; 457 | } 458 | else { 459 | g_ctx.IsUserFullAdmin = supUserIsFullAdmin(hToken); 460 | if (g_ctx.IsUserFullAdmin) { 461 | g_ctx.IsElevated = supIsClientElevated(NtCurrentProcess()); 462 | } 463 | } 464 | } 465 | else { 466 | supShowNtStatus("[!] Failed to query process token information\r\n", ntStatus); 467 | return; 468 | } 469 | 470 | NtClose(hToken); 471 | } 472 | else { 473 | supShowNtStatus("[!] Failed to open self process token\r\n", ntStatus); 474 | return; 475 | } 476 | 477 | // 478 | // -s (System) param. 479 | // 480 | if (supGetCommandLineOption(PARAM_LOCALSYSTEM, FALSE, NULL, 0, NULL)) { 481 | if (g_ctx.IsLocalSystem == FALSE) { 482 | if (g_ctx.IsUserFullAdmin == FALSE) { 483 | ConsoleShowMessage("[~] Administrative privileges are required for this operation\r\n", 0); 484 | break; 485 | } 486 | if (g_ctx.IsElevated == FALSE) { 487 | ConsoleShowMessage("[~] Elevation required to start as LocalSystem\r\n", 0); 488 | break; 489 | } 490 | ConsoleShowMessage("[~] Restarting as LocalSystem\r\n", 0); 491 | supRunAsLocalSystem(); 492 | break; 493 | } 494 | // 495 | // Already LocalSystem, skip. 496 | // 497 | } 498 | 499 | // 500 | // -win32k param. 501 | // 502 | fuzzParams.ProbeWin32k = supGetCommandLineOption(PARAM_WIN32K, FALSE, NULL, 0, NULL); 503 | 504 | // 505 | // -log param. 506 | // 507 | fuzzParams.LogEnabled = supGetCommandLineOption(PARAM_LOG, FALSE, NULL, 0, NULL); 508 | if (fuzzParams.LogEnabled) { 509 | 510 | _strcpy(fuzzParams.szLogDeviceOrFile, DEFAULT_LOG_PORT); 511 | fuzzParams.LogToFile = FALSE; 512 | 513 | // 514 | // Check log port name (-pname). 515 | // 516 | rLen = 0; 517 | RtlSecureZeroMemory(szTextBuf, sizeof(szTextBuf)); 518 | if (supGetCommandLineOption(PARAM_LOGPORT, 519 | TRUE, 520 | szTextBuf, 521 | RTL_NUMBER_OF(szTextBuf), 522 | &rLen)) 523 | { 524 | if (rLen) { 525 | _strcpy(fuzzParams.szLogDeviceOrFile, szTextBuf); 526 | } 527 | } 528 | else { 529 | 530 | // 531 | // Check log file name (-ofile). 532 | // 533 | rLen = 0; 534 | RtlSecureZeroMemory(szTextBuf, sizeof(szTextBuf)); 535 | if (supGetCommandLineOption(PARAM_LOGFILE, 536 | TRUE, 537 | szTextBuf, 538 | RTL_NUMBER_OF(szTextBuf), 539 | &rLen)) 540 | { 541 | if (rLen) { 542 | _strcpy(fuzzParams.szLogDeviceOrFile, szTextBuf); 543 | } 544 | else { 545 | _strcpy(fuzzParams.szLogDeviceOrFile, DEFAULT_LOG_FILE); 546 | } 547 | fuzzParams.LogToFile = TRUE; 548 | } 549 | 550 | } 551 | } 552 | 553 | // 554 | // -call (SyscallId) param. 555 | // 556 | RtlSecureZeroMemory(szTextBuf, sizeof(szTextBuf)); 557 | if (supGetCommandLineOption(PARAM_SYSCALL, 558 | TRUE, 559 | szTextBuf, 560 | RTL_NUMBER_OF(szTextBuf), 561 | NULL)) 562 | { 563 | fuzzParams.ProbeSingleSyscall = TRUE; 564 | fuzzParams.u1.SingleSyscallId = _strtoul(szTextBuf); 565 | } 566 | 567 | if (fuzzParams.ProbeSingleSyscall == FALSE) { 568 | // 569 | // -start (SyscallId) param. 570 | // 571 | RtlSecureZeroMemory(szTextBuf, sizeof(szTextBuf)); 572 | if (supGetCommandLineOption(PARAM_SYSCALL_START, 573 | TRUE, 574 | szTextBuf, 575 | RTL_NUMBER_OF(szTextBuf), 576 | NULL)) 577 | { 578 | fuzzParams.ProbeFromSyscallId = TRUE; 579 | fuzzParams.u1.StartingSyscallId = _strtoul(szTextBuf); 580 | } 581 | } 582 | 583 | // 584 | // -pc (PassCount) param. 585 | // 586 | RtlSecureZeroMemory(szTextBuf, sizeof(szTextBuf)); 587 | if (supGetCommandLineOption(PARAM_PASSCOUNT, 588 | TRUE, 589 | szTextBuf, 590 | RTL_NUMBER_OF(szTextBuf), 591 | NULL)) 592 | { 593 | fuzzParams.SyscallPassCount = strtou64(szTextBuf); 594 | } 595 | 596 | if (fuzzParams.SyscallPassCount == 0) 597 | fuzzParams.SyscallPassCount = FUZZ_PASS_COUNT; 598 | 599 | if (fuzzParams.ProbeSingleSyscall && fuzzParams.ProbeWin32k) { 600 | ConsoleShowMessage("Invalid combination of command line arguments.\r\n", 0); 601 | break; 602 | } 603 | 604 | // 605 | // -wt (WaitTimeout) param. 606 | // 607 | RtlSecureZeroMemory(szTextBuf, sizeof(szTextBuf)); 608 | if (supGetCommandLineOption(PARAM_WAITTIMEOUT, 609 | TRUE, 610 | szTextBuf, 611 | RTL_NUMBER_OF(szTextBuf), 612 | NULL)) 613 | { 614 | fuzzParams.ThreadWaitTimeout = _strtoul(szTextBuf); 615 | } 616 | 617 | if (fuzzParams.ThreadWaitTimeout == 0) 618 | fuzzParams.ThreadWaitTimeout = FUZZ_THREAD_TIMEOUT_SEC; 619 | 620 | FuzzInitPhase1(&fuzzParams); 621 | 622 | } while (FALSE); 623 | 624 | ConsoleShowMessage("[-] Leaving FuzzInitPhase0()\r\n", 625 | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); 626 | } 627 | 628 | 629 | /* 630 | * main 631 | * 632 | * Purpose: 633 | * 634 | * Program main, process command line options and run fuzzing. 635 | * 636 | */ 637 | UINT NtCall64Main() 638 | { 639 | PVOID ExceptionHandler; 640 | 641 | ConsoleInit(); 642 | ConsoleShowMessage(WELCOME_BANNER, 0); 643 | ConsoleShowMessage(VERSION_BANNER, 0); 644 | 645 | ExceptionHandler = RtlAddVectoredExceptionHandler(1, &VehHandler); 646 | if (ExceptionHandler) { 647 | 648 | do { 649 | 650 | if (supGetCommandLineOption(PARAM_HELP, FALSE, NULL, 0, NULL)) { 651 | ConsoleShowMessage(T_HELP, 0); 652 | break; 653 | } 654 | 655 | FuzzInitPhase0(); 656 | ConsoleShowMessage("Bye!\r\n", 0); 657 | 658 | } while (FALSE); 659 | 660 | RtlRemoveVectoredExceptionHandler(ExceptionHandler); 661 | } 662 | 663 | return 0; 664 | } 665 | 666 | /* 667 | * main 668 | * 669 | * Purpose: 670 | * 671 | * Program EntryPoint. 672 | * 673 | */ 674 | #if !defined(__cplusplus) 675 | #pragma comment(linker, "/ENTRY:main") 676 | void main() 677 | { 678 | ExitProcess(NtCall64Main()); 679 | } 680 | #else 681 | #pragma comment(linker, "/ENTRY:WinMain") 682 | int CALLBACK WinMain( 683 | _In_ HINSTANCE hInstance, 684 | _In_opt_ HINSTANCE hPrevInstance, 685 | _In_ LPSTR lpCmdLine, 686 | _In_ int nCmdShow 687 | ) 688 | { 689 | UNREFERENCED_PARAMETER(hInstance); 690 | UNREFERENCED_PARAMETER(hPrevInstance); 691 | UNREFERENCED_PARAMETER(lpCmdLine); 692 | UNREFERENCED_PARAMETER(nCmdShow); 693 | ExitProcess(NtCall64Main()); 694 | } 695 | #endif 696 | -------------------------------------------------------------------------------- /Source/NtCall64/minirtl/_filename.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "minirtl.h" 3 | 4 | char *_filename_a(const char *f) 5 | { 6 | char *p = (char *)f; 7 | 8 | if (f == 0) 9 | return 0; 10 | 11 | while (*f != (char)0) { 12 | if (*f == '\\') 13 | p = (char *)f + 1; 14 | f++; 15 | } 16 | return p; 17 | } 18 | 19 | wchar_t *_filename_w(const wchar_t *f) 20 | { 21 | wchar_t *p = (wchar_t *)f; 22 | 23 | if (f == 0) 24 | return 0; 25 | 26 | while (*f != (wchar_t)0) { 27 | if (*f == (wchar_t)'\\') 28 | p = (wchar_t *)f + 1; 29 | f++; 30 | } 31 | return p; 32 | } 33 | 34 | char *_fileext_a(const char *f) 35 | { 36 | char *p = 0; 37 | 38 | if (f == 0) 39 | return 0; 40 | 41 | while (*f != (char)0) { 42 | if (*f == '.') 43 | p = (char *)f; 44 | f++; 45 | } 46 | 47 | if (p == 0) 48 | p = (char *)f; 49 | 50 | return p; 51 | } 52 | 53 | wchar_t *_fileext_w(const wchar_t *f) 54 | { 55 | wchar_t *p = 0; 56 | 57 | if (f == 0) 58 | return 0; 59 | 60 | while (*f != (wchar_t)0) { 61 | if (*f == (wchar_t)'.') 62 | p = (wchar_t *)f; 63 | f++; 64 | } 65 | 66 | if (p == 0) 67 | p = (wchar_t *)f; 68 | 69 | return p; 70 | } 71 | 72 | char *_filename_noext_a(char *dest, const char *f) 73 | { 74 | char *p, *l, *dot; 75 | 76 | if ((f == 0) || (dest == 0)) 77 | return 0; 78 | 79 | p = _filename_a(f); 80 | if (p == 0) 81 | return 0; 82 | 83 | dot = _strend_a(p); 84 | if (dot == 0) 85 | return 0; 86 | 87 | l = p; 88 | 89 | while (*l != (char)0) 90 | { 91 | if (*l == '.') 92 | dot = l; 93 | l++; 94 | } 95 | 96 | while (p0) ); 26 | 27 | return (int)(c1 - c2); 28 | } 29 | 30 | int _strncmp_w(const wchar_t *s1, const wchar_t *s2, size_t cchars) 31 | { 32 | wchar_t c1, c2; 33 | 34 | if ( s1==s2 ) 35 | return 0; 36 | 37 | if ( s1==0 ) 38 | return -1; 39 | 40 | if ( s2==0 ) 41 | return 1; 42 | 43 | if ( cchars==0 ) 44 | return 0; 45 | 46 | do { 47 | c1 = *s1; 48 | c2 = *s2; 49 | s1++; 50 | s2++; 51 | cchars--; 52 | } while ( (c1 != 0) && (c1 == c2) && (cchars>0) ); 53 | 54 | return (int)(c1 - c2); 55 | } 56 | -------------------------------------------------------------------------------- /Source/NtCall64/minirtl/_strncpy.c: -------------------------------------------------------------------------------- 1 | #include "rtltypes.h" 2 | 3 | char *_strncpy_a(char *dest, size_t ccdest, const char *src, size_t ccsrc) 4 | { 5 | char *p; 6 | 7 | if ( (dest==0) || (src==0) || (ccdest==0) ) 8 | return dest; 9 | 10 | ccdest--; 11 | p = dest; 12 | 13 | while ( (*src!=0) && (ccdest>0) && (ccsrc>0) ) { 14 | *p = *src; 15 | p++; 16 | src++; 17 | ccdest--; 18 | ccsrc--; 19 | } 20 | 21 | *p = 0; 22 | return dest; 23 | } 24 | 25 | wchar_t *_strncpy_w(wchar_t *dest, size_t ccdest, const wchar_t *src, size_t ccsrc) 26 | { 27 | wchar_t *p; 28 | 29 | if ( (dest==0) || (src==0) || (ccdest==0) ) 30 | return dest; 31 | 32 | ccdest--; 33 | p = dest; 34 | 35 | while ( (*src!=0) && (ccdest>0) && (ccsrc>0) ) { 36 | *p = *src; 37 | p++; 38 | src++; 39 | ccdest--; 40 | ccsrc--; 41 | } 42 | 43 | *p = 0; 44 | return dest; 45 | } 46 | -------------------------------------------------------------------------------- /Source/NtCall64/minirtl/cmdline.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | BOOL GetCommandLineParamW( 4 | IN LPCWSTR CmdLine, 5 | IN ULONG ParamIndex, 6 | OUT LPWSTR Buffer, 7 | IN ULONG BufferSize, 8 | OUT PULONG ParamLen 9 | ) 10 | { 11 | ULONG c, plen = 0; 12 | TCHAR divider; 13 | 14 | if (ParamLen != NULL) 15 | *ParamLen = 0; 16 | 17 | if (CmdLine == NULL) { 18 | if ((Buffer != NULL) && (BufferSize > 0)) 19 | *Buffer = 0; 20 | return FALSE; 21 | } 22 | 23 | for (c = 0; c <= ParamIndex; c++) { 24 | plen = 0; 25 | 26 | while (*CmdLine == ' ') 27 | CmdLine++; 28 | 29 | switch (*CmdLine) { 30 | case 0: 31 | goto zero_term_exit; 32 | 33 | case '"': 34 | CmdLine++; 35 | divider = '"'; 36 | break; 37 | 38 | default: 39 | divider = ' '; 40 | } 41 | 42 | while ((*CmdLine != '"') && (*CmdLine != divider) && (*CmdLine != 0)) { 43 | plen++; 44 | if (c == ParamIndex) 45 | if ((plen < BufferSize) && (Buffer != NULL)) { 46 | *Buffer = *CmdLine; 47 | Buffer++; 48 | } 49 | CmdLine++; 50 | } 51 | 52 | if (*CmdLine != 0) 53 | CmdLine++; 54 | } 55 | 56 | zero_term_exit: 57 | 58 | if ((Buffer != NULL) && (BufferSize > 0)) 59 | *Buffer = 0; 60 | 61 | if (ParamLen != NULL) 62 | *ParamLen = plen; 63 | 64 | if (plen < BufferSize) 65 | return TRUE; 66 | else 67 | return FALSE; 68 | } 69 | 70 | BOOL GetCommandLineParamA( 71 | IN LPCSTR CmdLine, 72 | IN ULONG ParamIndex, 73 | OUT LPSTR Buffer, 74 | IN ULONG BufferSize, 75 | OUT PULONG ParamLen 76 | ) 77 | { 78 | ULONG c, plen = 0; 79 | TCHAR divider; 80 | 81 | if (CmdLine == NULL) 82 | return FALSE; 83 | 84 | if (ParamLen != NULL) 85 | *ParamLen = 0; 86 | 87 | for (c = 0; c <= ParamIndex; c++) { 88 | plen = 0; 89 | 90 | while (*CmdLine == ' ') 91 | CmdLine++; 92 | 93 | switch (*CmdLine) { 94 | case 0: 95 | goto zero_term_exit; 96 | 97 | case '"': 98 | CmdLine++; 99 | divider = '"'; 100 | break; 101 | 102 | default: 103 | divider = ' '; 104 | } 105 | 106 | while ((*CmdLine != '"') && (*CmdLine != divider) && (*CmdLine != 0)) { 107 | plen++; 108 | if (c == ParamIndex) 109 | if ((plen < BufferSize) && (Buffer != NULL)) { 110 | *Buffer = *CmdLine; 111 | Buffer++; 112 | } 113 | CmdLine++; 114 | } 115 | 116 | if (*CmdLine != 0) 117 | CmdLine++; 118 | } 119 | 120 | zero_term_exit: 121 | 122 | if ((Buffer != NULL) && (BufferSize > 0)) 123 | *Buffer = 0; 124 | 125 | if (ParamLen != NULL) 126 | *ParamLen = plen; 127 | 128 | if (plen < BufferSize) 129 | return TRUE; 130 | else 131 | return FALSE; 132 | } 133 | 134 | char *ExtractFilePathA(const char *FileName, char *FilePath) 135 | { 136 | char *p = (char *)FileName, *p0 = (char *)FileName; 137 | 138 | if ((FileName == 0) || (FilePath == 0)) 139 | return 0; 140 | 141 | while (*FileName != 0) { 142 | if (*FileName == '\\') 143 | p = (char *)FileName + 1; 144 | FileName++; 145 | } 146 | 147 | while (p0 < p) { 148 | *FilePath = *p0; 149 | FilePath++; 150 | p0++; 151 | } 152 | 153 | *FilePath = 0; 154 | 155 | return FilePath; 156 | } 157 | 158 | wchar_t *ExtractFilePathW(const wchar_t *FileName, wchar_t *FilePath) 159 | { 160 | wchar_t *p = (wchar_t *)FileName, *p0 = (wchar_t *)FileName; 161 | 162 | if ((FileName == 0) || (FilePath == 0)) 163 | return 0; 164 | 165 | while (*FileName != 0) { 166 | if (*FileName == '\\') 167 | p = (wchar_t *)FileName + 1; 168 | FileName++; 169 | } 170 | 171 | while (p0 < p) { 172 | *FilePath = *p0; 173 | FilePath++; 174 | p0++; 175 | } 176 | 177 | *FilePath = 0; 178 | 179 | return FilePath; 180 | } 181 | -------------------------------------------------------------------------------- /Source/NtCall64/minirtl/cmdline.h: -------------------------------------------------------------------------------- 1 | #ifndef _CMDLINEH_ 2 | #define _CMDLINEH_ 3 | 4 | BOOL GetCommandLineParamW( 5 | IN LPCWSTR CmdLine, 6 | IN ULONG ParamIndex, 7 | OUT LPWSTR Buffer, 8 | IN ULONG BufferSize, 9 | OUT PULONG ParamLen 10 | ); 11 | 12 | BOOL GetCommandLineParamA( 13 | IN LPCSTR CmdLine, 14 | IN ULONG ParamIndex, 15 | OUT LPSTR Buffer, 16 | IN ULONG BufferSize, 17 | OUT PULONG ParamLen 18 | ); 19 | 20 | char *ExtractFilePathA(const char *FileName, char *FilePath); 21 | wchar_t *ExtractFilePathW(const wchar_t *FileName, wchar_t *FilePath); 22 | 23 | #ifdef UNICODE 24 | 25 | #define ExtractFilePath ExtractFilePathW 26 | #define GetCommandLineParam GetCommandLineParamW 27 | 28 | #else // ANSI 29 | 30 | #define ExtractFilePath ExtractFilePathA 31 | #define GetCommandLineParam GetCommandLineParamA 32 | 33 | #endif 34 | 35 | #endif /* _CMDLINEH_ */ 36 | -------------------------------------------------------------------------------- /Source/NtCall64/minirtl/minirtl.h: -------------------------------------------------------------------------------- 1 | /* 2 | Module name: 3 | minirtl.h 4 | 5 | Description: 6 | header for string handling and conversion routines 7 | 8 | Date: 9 | 4 Oct 2020 10 | */ 11 | 12 | #pragma once 13 | 14 | #ifndef _MINIRTL_ 15 | #define _MINIRTL_ 16 | 17 | // string copy/concat/length 18 | 19 | char *_strend_a(const char *s); 20 | wchar_t *_strend_w(const wchar_t *s); 21 | 22 | char *_strcpy_a(char *dest, const char *src); 23 | wchar_t *_strcpy_w(wchar_t *dest, const wchar_t *src); 24 | 25 | char *_strcat_a(char *dest, const char *src); 26 | wchar_t *_strcat_w(wchar_t *dest, const wchar_t *src); 27 | 28 | char *_strncpy_a(char *dest, size_t ccdest, const char *src, size_t ccsrc); 29 | wchar_t *_strncpy_w(wchar_t *dest, size_t ccdest, const wchar_t *src, size_t ccsrc); 30 | 31 | char *_strcpyn_a(char* dest, const char* src, size_t n); 32 | wchar_t *_strcpyn_w(wchar_t* dest, const wchar_t* src, size_t n); 33 | 34 | size_t _strlen_a(const char *s); 35 | size_t _strlen_w(const wchar_t *s); 36 | 37 | // comparing 38 | 39 | int _strcmp_a(const char *s1, const char *s2); 40 | int _strcmp_w(const wchar_t *s1, const wchar_t *s2); 41 | 42 | int _strncmp_a(const char *s1, const char *s2, size_t cchars); 43 | int _strncmp_w(const wchar_t *s1, const wchar_t *s2, size_t cchars); 44 | 45 | int _strcmpi_a(const char *s1, const char *s2); 46 | int _strcmpi_w(const wchar_t *s1, const wchar_t *s2); 47 | 48 | int _strncmpi_a(const char *s1, const char *s2, size_t cchars); 49 | int _strncmpi_w(const wchar_t *s1, const wchar_t *s2, size_t cchars); 50 | 51 | char *_strstr_a(const char *s, const char *sub_s); 52 | wchar_t *_strstr_w(const wchar_t *s, const wchar_t *sub_s); 53 | 54 | char *_strstri_a(const char *s, const char *sub_s); 55 | wchar_t *_strstri_w(const wchar_t *s, const wchar_t *sub_s); 56 | 57 | char *_strchr_a(const char *s, const char ch); 58 | wchar_t *_strchr_w(const wchar_t *s, const wchar_t ch); 59 | 60 | 61 | // conversion of integer types to string, returning string length 62 | 63 | size_t ultostr_a(unsigned long x, char *s); 64 | size_t ultostr_w(unsigned long x, wchar_t *s); 65 | 66 | size_t ultohex_a(unsigned long x, char *s); 67 | size_t ultohex_w(unsigned long x, wchar_t *s); 68 | 69 | size_t itostr_a(int x, char *s); 70 | size_t itostr_w(int x, wchar_t *s); 71 | 72 | size_t i64tostr_a(signed long long x, char *s); 73 | size_t i64tostr_w(signed long long x, wchar_t *s); 74 | 75 | size_t u64tostr_a(unsigned long long x, char *s); 76 | size_t u64tostr_w(unsigned long long x, wchar_t *s); 77 | 78 | size_t u64tohex_a(unsigned long long x, char *s); 79 | size_t u64tohex_w(unsigned long long x, wchar_t *s); 80 | 81 | // string to integers conversion 82 | 83 | unsigned long strtoul_a(char *s); 84 | unsigned long strtoul_w(wchar_t *s); 85 | 86 | unsigned long long strtou64_a(char *s); 87 | unsigned long long strtou64_w(wchar_t *s); 88 | 89 | unsigned long hextoul_a(char *s); 90 | unsigned long hextoul_w(wchar_t *s); 91 | 92 | int strtoi_a(char *s); 93 | int strtoi_w(wchar_t *s); 94 | 95 | signed long long strtoi64_a(char *s); 96 | signed long long strtoi64_w(wchar_t *s); 97 | 98 | unsigned long long hextou64_a(char *s); 99 | unsigned long long hextou64_w(wchar_t *s); 100 | 101 | /* =================================== */ 102 | 103 | #ifdef UNICODE 104 | 105 | #define _strend _strend_w 106 | #define _strcpy _strcpy_w 107 | #define _strcat _strcat_w 108 | #define _strlen _strlen_w 109 | #define _strncpy _strncpy_w 110 | #define _strcpyn _strcpyn_w 111 | 112 | #define _strcmp _strcmp_w 113 | #define _strncmp _strncmp_w 114 | #define _strcmpi _strcmpi_w 115 | #define _strncmpi _strncmpi_w 116 | #define _strstr _strstr_w 117 | #define _strstri _strstri_w 118 | #define _strchr _strchr_w 119 | 120 | #define ultostr ultostr_w 121 | #define ultohex ultohex_w 122 | #define itostr itostr_w 123 | #define i64tostr i64tostr_w 124 | #define u64tostr u64tostr_w 125 | #define u64tohex u64tohex_w 126 | 127 | #define _strtoul strtoul_w 128 | #define hextoul hextoul_w 129 | #define strtoi strtoi_w 130 | #define strtoi64 strtoi64_w 131 | #define strtou64 strtou64_w 132 | #define hextou64 hextou64_w 133 | 134 | #else // ANSI 135 | 136 | #define _strend _strend_a 137 | #define _strcpy _strcpy_a 138 | #define _strcat _strcat_a 139 | #define _strlen _strlen_a 140 | #define _strncpy _strncpy_a 141 | #define _strcpyn _strcpyn_a 142 | 143 | #define _strcmp _strcmp_a 144 | #define _strncmp _strncmp_a 145 | #define _strcmpi _strcmpi_a 146 | #define _strncmpi _strncmpi_a 147 | #define _strstr _strstr_a 148 | #define _strstri _strstri_a 149 | #define _strchr _strchr_a 150 | 151 | #define ultostr ultostr_a 152 | #define ultohex ultohex_a 153 | #define itostr itostr_a 154 | #define i64tostr i64tostr_a 155 | #define u64tostr u64tostr_a 156 | #define u64tohex u64tohex_a 157 | 158 | #define _strtoul strtoul_a 159 | #define hextoul hextoul_a 160 | #define strtoi strtoi_a 161 | #define strtoi64 strtoi64_a 162 | #define strtou64 strtou64_a 163 | #define hextou64 hextou64_a 164 | 165 | #endif 166 | 167 | #endif /* _MINIRTL_ */ 168 | -------------------------------------------------------------------------------- /Source/NtCall64/minirtl/rtltypes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef _WCHAR_T_DEFINED 4 | typedef unsigned short wchar_t; 5 | #define _WCHAR_T_DEFINED 6 | #endif /* _WCHAR_T_DEFINED */ 7 | 8 | #ifndef _SIZE_T_DEFINED 9 | #ifdef _WIN64 10 | typedef unsigned __int64 size_t; 11 | #else /* _WIN64 */ 12 | typedef __w64 unsigned int size_t; 13 | #endif /* _WIN64 */ 14 | #define _SIZE_T_DEFINED 15 | #endif /* _SIZE_T_DEFINED */ 16 | 17 | __forceinline char locase_a(char c) 18 | { 19 | if ((c >= 'A') && (c <= 'Z')) 20 | return c + 0x20; 21 | else 22 | return c; 23 | } 24 | 25 | __forceinline wchar_t locase_w(wchar_t c) 26 | { 27 | if ((c >= 'A') && (c <= 'Z')) 28 | return c + 0x20; 29 | else 30 | return c; 31 | } 32 | 33 | __forceinline char byteabs(char x) { 34 | if (x < 0) 35 | return -x; 36 | return x; 37 | } 38 | 39 | __forceinline int _isdigit_a(char x) { 40 | return ((x >= '0') && (x <= '9')); 41 | } 42 | 43 | __forceinline int _isdigit_w(wchar_t x) { 44 | return ((x >= L'0') && (x <= L'9')); 45 | } 46 | -------------------------------------------------------------------------------- /Source/NtCall64/minirtl/strtou64.c: -------------------------------------------------------------------------------- 1 | #include "rtltypes.h" 2 | 3 | unsigned long long strtou64_a(char *s) 4 | { 5 | unsigned long long a = 0; 6 | char c; 7 | 8 | if (s == 0) 9 | return 0; 10 | 11 | while (*s != 0) { 12 | c = *s; 13 | if (_isdigit_w(c)) 14 | a = (a*10)+((unsigned long long)c-'0'); 15 | else 16 | break; 17 | s++; 18 | } 19 | return a; 20 | } 21 | 22 | unsigned long long strtou64_w(wchar_t *s) 23 | { 24 | unsigned long long a = 0; 25 | wchar_t c; 26 | 27 | if (s == 0) 28 | return 0; 29 | 30 | while (*s != 0) { 31 | c = *s; 32 | if (_isdigit_w(c)) 33 | a = (a*10)+((unsigned long long)c-L'0'); 34 | else 35 | break; 36 | s++; 37 | } 38 | return a; 39 | } 40 | -------------------------------------------------------------------------------- /Source/NtCall64/minirtl/strtoul.c: -------------------------------------------------------------------------------- 1 | #include "rtltypes.h" 2 | 3 | unsigned long strtoul_a(char *s) 4 | { 5 | unsigned long a = 0; 6 | char c; 7 | 8 | if (s == 0) 9 | return 0; 10 | 11 | while (*s != 0) { 12 | c = *s; 13 | if (_isdigit_a(c)) 14 | a = (a*10)+(c-'0'); 15 | else 16 | break; 17 | s++; 18 | } 19 | return a; 20 | } 21 | 22 | unsigned long strtoul_w(wchar_t *s) 23 | { 24 | unsigned long a = 0; 25 | wchar_t c; 26 | 27 | if (s == 0) 28 | return 0; 29 | 30 | while (*s != 0) { 31 | c = *s; 32 | if (_isdigit_w(c)) 33 | a = (a*10)+(c-L'0'); 34 | else 35 | break; 36 | s++; 37 | } 38 | return a; 39 | } 40 | -------------------------------------------------------------------------------- /Source/NtCall64/minirtl/u64tohex.c: -------------------------------------------------------------------------------- 1 | #include "rtltypes.h" 2 | 3 | size_t u64tohex_a(unsigned long long x, char *s) 4 | { 5 | char p; 6 | size_t c; 7 | 8 | if (s==0) 9 | return 16; 10 | 11 | for (c=0; c<16; c++) { 12 | p = (char)(x & 0xf); 13 | x >>= 4; 14 | 15 | if (p<10) 16 | p += '0'; 17 | else 18 | p = 'A' + (p-10); 19 | 20 | s[15-c] = p; 21 | } 22 | 23 | s[16] = 0; 24 | return 16; 25 | } 26 | 27 | size_t u64tohex_w(unsigned long long x, wchar_t *s) 28 | { 29 | wchar_t p; 30 | size_t c; 31 | 32 | if (s==0) 33 | return 16; 34 | 35 | for (c = 0; c<16; c++) { 36 | p = (wchar_t)(x & 0xf); 37 | x >>= 4; 38 | 39 | if (p<10) 40 | p += L'0'; 41 | else 42 | p = L'A' + (p-10); 43 | 44 | s[15-c] = p; 45 | } 46 | 47 | s[16] = 0; 48 | return 16; 49 | } 50 | -------------------------------------------------------------------------------- /Source/NtCall64/minirtl/u64tostr.c: -------------------------------------------------------------------------------- 1 | #include "rtltypes.h" 2 | 3 | size_t u64tostr_a(unsigned long long x, char *s) 4 | { 5 | unsigned long long t = x; 6 | size_t i, r=1; 7 | 8 | while ( t >= 10 ) { 9 | t /= 10; 10 | r++; 11 | } 12 | 13 | if (s == 0) 14 | return r; 15 | 16 | for (i = r; i != 0; i--) { 17 | s[i-1] = (char)(x % 10) + '0'; 18 | x /= 10; 19 | } 20 | 21 | s[r] = (char)0; 22 | return r; 23 | } 24 | 25 | size_t u64tostr_w(unsigned long long x, wchar_t *s) 26 | { 27 | unsigned long long t = x; 28 | size_t i, r=1; 29 | 30 | while ( t >= 10 ) { 31 | t /= 10; 32 | r++; 33 | } 34 | 35 | if (s == 0) 36 | return r; 37 | 38 | for (i = r; i != 0; i--) { 39 | s[i-1] = (wchar_t)(x % 10) + L'0'; 40 | x /= 10; 41 | } 42 | 43 | s[r] = (wchar_t)0; 44 | return r; 45 | } 46 | -------------------------------------------------------------------------------- /Source/NtCall64/minirtl/ultohex.c: -------------------------------------------------------------------------------- 1 | #include "rtltypes.h" 2 | 3 | size_t ultohex_a(unsigned long x, char *s) 4 | { 5 | char p; 6 | size_t c; 7 | 8 | if (s==0) 9 | return 8; 10 | 11 | for (c=0; c<8; c++) { 12 | p = (char)(x & 0xf); 13 | x >>= 4; 14 | 15 | if (p<10) 16 | p += '0'; 17 | else 18 | p = 'A' + (p-10); 19 | 20 | s[7-c] = p; 21 | } 22 | 23 | s[8] = 0; 24 | return 8; 25 | } 26 | 27 | size_t ultohex_w(unsigned long x, wchar_t *s) 28 | { 29 | wchar_t p; 30 | size_t c; 31 | 32 | if (s==0) 33 | return 8; 34 | 35 | for (c=0; c<8; c++) { 36 | p = (wchar_t)(x & 0xf); 37 | x >>= 4; 38 | 39 | if (p<10) 40 | p += L'0'; 41 | else 42 | p = L'A' + (p-10); 43 | 44 | s[7-c] = p; 45 | } 46 | 47 | s[8] = 0; 48 | return 8; 49 | } 50 | -------------------------------------------------------------------------------- /Source/NtCall64/minirtl/ultostr.c: -------------------------------------------------------------------------------- 1 | #include "rtltypes.h" 2 | 3 | size_t ultostr_a(unsigned long x, char *s) 4 | { 5 | unsigned long t=x; 6 | size_t i, r=1; 7 | 8 | while ( t >= 10 ) { 9 | t /= 10; 10 | r++; 11 | } 12 | 13 | if (s == 0) 14 | return r; 15 | 16 | for (i = r; i != 0; i--) { 17 | s[i-1] = (char)(x % 10) + '0'; 18 | x /= 10; 19 | } 20 | 21 | s[r] = (char)0; 22 | return r; 23 | } 24 | 25 | size_t ultostr_w(unsigned long x, wchar_t *s) 26 | { 27 | unsigned long t=x; 28 | size_t i, r=1; 29 | 30 | while ( t >= 10 ) { 31 | t /= 10; 32 | r++; 33 | } 34 | 35 | if (s == 0) 36 | return r; 37 | 38 | for (i = r; i != 0; i--) { 39 | s[i-1] = (wchar_t)(x % 10) + L'0'; 40 | x /= 10; 41 | } 42 | 43 | s[r] = (wchar_t)0; 44 | return r; 45 | } 46 | -------------------------------------------------------------------------------- /Source/NtCall64/ntbuilds.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * 3 | * (C) COPYRIGHT AUTHORS, 2021 - 2023 4 | * 5 | * TITLE: NTBUILDS.H 6 | * 7 | * VERSION: 1.18 8 | * 9 | * DATE: 21 Jul 2023 10 | * 11 | * Windows NT builds definition file. 12 | * 13 | * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 14 | * ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED 15 | * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 16 | * PARTICULAR PURPOSE. 17 | * 18 | *******************************************************************************/ 19 | #pragma once 20 | 21 | // 22 | // Defines for Major Windows NT release builds 23 | // 24 | 25 | // Windows 7 RTM 26 | #define NT_WIN7_RTM 7600 27 | 28 | // Windows 7 SP1 29 | #define NT_WIN7_SP1 7601 30 | 31 | // Windows 8 RTM 32 | #define NT_WIN8_RTM 9200 33 | 34 | // Windows 8.1 35 | #define NT_WIN8_BLUE 9600 36 | 37 | // Windows 10 TH1 38 | #define NT_WIN10_THRESHOLD1 10240 39 | 40 | // Windows 10 TH2 41 | #define NT_WIN10_THRESHOLD2 10586 42 | 43 | // Windows 10 RS1 44 | #define NT_WIN10_REDSTONE1 14393 45 | 46 | // Windows 10 RS2 47 | #define NT_WIN10_REDSTONE2 15063 48 | 49 | // Windows 10 RS3 50 | #define NT_WIN10_REDSTONE3 16299 51 | 52 | // Windows 10 RS4 53 | #define NT_WIN10_REDSTONE4 17134 54 | 55 | // Windows 10 RS5 56 | #define NT_WIN10_REDSTONE5 17763 57 | 58 | // Windows 10 19H1 59 | #define NT_WIN10_19H1 18362 60 | 61 | // Windows 10 19H2 62 | #define NT_WIN10_19H2 18363 63 | 64 | // Windows 10 20H1 65 | #define NT_WIN10_20H1 19041 66 | 67 | // Windows 10 20H2 68 | #define NT_WIN10_20H2 19042 69 | 70 | // Windows 10 21H1 71 | #define NT_WIN10_21H1 19043 72 | 73 | // Windows 10 21H2 74 | #define NT_WIN10_21H2 19044 75 | 76 | // Windows 10 22H2 77 | #define NT_WIN10_22H2 19045 78 | 79 | // Windows Server 2022 80 | #define NT_WINSRV_21H1 20348 81 | 82 | // Windows 11 21H2 83 | #define NT_WIN11_21H2 22000 84 | 85 | // Windows 11 22H2 86 | #define NT_WIN11_22H2 22621 87 | 88 | // Windows 11 Active Develepment Branch 89 | #define NT_WIN11_23H2 22631 90 | #define NT_WIN11_24H2 25905 //canary (24H2) 91 | -------------------------------------------------------------------------------- /Source/NtCall64/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by resource.rc 4 | 5 | // Next default values for new objects 6 | // 7 | #ifdef APSTUDIO_INVOKED 8 | #ifndef APSTUDIO_READONLY_SYMBOLS 9 | #define _APS_NEXT_RESOURCE_VALUE 101 10 | #define _APS_NEXT_COMMAND_VALUE 40001 11 | #define _APS_NEXT_CONTROL_VALUE 1001 12 | #define _APS_NEXT_SYMED_VALUE 101 13 | #endif 14 | #endif 15 | -------------------------------------------------------------------------------- /Source/NtCall64/resource.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hfiref0x/NtCall64/af16a90d95415c59a8c215d18d73b37a90b2deea/Source/NtCall64/resource.rc -------------------------------------------------------------------------------- /Source/NtCall64/sup.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * 3 | * (C) COPYRIGHT AUTHORS, 2016 - 2023 4 | * 5 | * TITLE: SUP.C 6 | * 7 | * VERSION: 1.37 8 | * 9 | * DATE: 04 Aug 2023 10 | * 11 | * Support routines. 12 | * 13 | * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 14 | * ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED 15 | * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 16 | * PARTICULAR PURPOSE. 17 | * 18 | *******************************************************************************/ 19 | 20 | #include "global.h" 21 | 22 | VOID ConsoleInit( 23 | VOID) 24 | { 25 | COORD coordScreen = { 0, 0 }; 26 | DWORD cCharsWritten; 27 | CONSOLE_SCREEN_BUFFER_INFO csbi; 28 | DWORD dwConSize; 29 | HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); 30 | 31 | if (!GetConsoleScreenBufferInfo(hConsole, &csbi)) 32 | return; 33 | 34 | SetConsoleTextAttribute(hConsole, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED); 35 | 36 | dwConSize = csbi.dwSize.X * csbi.dwSize.Y; 37 | 38 | if (!FillConsoleOutputCharacter(hConsole, (TCHAR)' ', 39 | dwConSize, coordScreen, &cCharsWritten)) 40 | return; 41 | 42 | if (!GetConsoleScreenBufferInfo(hConsole, &csbi)) 43 | return; 44 | 45 | if (!FillConsoleOutputAttribute(hConsole, csbi.wAttributes, 46 | dwConSize, coordScreen, &cCharsWritten)) 47 | return; 48 | 49 | SetConsoleCursorPosition(hConsole, coordScreen); 50 | } 51 | 52 | /* 53 | * ConsoleShowMessage 54 | * 55 | * Purpose: 56 | * 57 | * Output text to screen. 58 | * 59 | */ 60 | VOID ConsoleShowMessage( 61 | _In_ LPCSTR lpMessage, 62 | _In_opt_ WORD wColor 63 | ) 64 | { 65 | CONSOLE_SCREEN_BUFFER_INFO csbi; 66 | 67 | ULONG r, sz; 68 | 69 | WORD SavedAttributes = 0; 70 | 71 | HANDLE hStdHandle = GetStdHandle(STD_OUTPUT_HANDLE); 72 | 73 | 74 | sz = (DWORD)_strlen_a(lpMessage); 75 | if (sz == 0) 76 | return; 77 | 78 | if (wColor) { 79 | 80 | RtlSecureZeroMemory(&csbi, sizeof(csbi)); 81 | 82 | GetConsoleScreenBufferInfo(hStdHandle, &csbi); 83 | 84 | SavedAttributes = csbi.wAttributes; 85 | 86 | SetConsoleTextAttribute(hStdHandle, wColor); 87 | 88 | } 89 | 90 | WriteFile(hStdHandle, lpMessage, sz, &r, NULL); 91 | 92 | if (wColor) { 93 | SetConsoleTextAttribute(hStdHandle, SavedAttributes); 94 | } 95 | } 96 | 97 | /* 98 | * supGetCommandLineOption 99 | * 100 | * Purpose: 101 | * 102 | * Parse command line options. 103 | * 104 | */ 105 | BOOLEAN supGetCommandLineOption( 106 | _In_ LPCWSTR OptionName, 107 | _In_ BOOLEAN IsParametric, 108 | _Out_writes_opt_z_(ValueSize) LPWSTR OptionValue, 109 | _In_ ULONG ValueSize, 110 | _Out_opt_ PULONG ParamLength 111 | ) 112 | { 113 | BOOLEAN bResult; 114 | LPWSTR cmdline = GetCommandLine(); 115 | WCHAR szParam[MAX_PATH + 1]; 116 | ULONG rlen; 117 | INT i = 0; 118 | 119 | if (ParamLength) 120 | *ParamLength = 0; 121 | 122 | RtlSecureZeroMemory(szParam, sizeof(szParam)); 123 | while (GetCommandLineParam( 124 | cmdline, 125 | i, 126 | szParam, 127 | MAX_PATH, 128 | &rlen)) 129 | { 130 | if (rlen == 0) 131 | break; 132 | 133 | if (_strcmp(szParam, OptionName) == 0) { 134 | if (IsParametric) { 135 | bResult = (BOOLEAN)GetCommandLineParam(cmdline, i + 1, OptionValue, ValueSize, &rlen); 136 | if (ParamLength) 137 | *ParamLength = rlen; 138 | return bResult; 139 | } 140 | 141 | return TRUE; 142 | } 143 | ++i; 144 | } 145 | 146 | return FALSE; 147 | } 148 | 149 | /* 150 | * supUserIsFullAdmin 151 | * 152 | * Purpose: 153 | * 154 | * Tests if the current user is admin with full access token. 155 | * 156 | */ 157 | BOOLEAN supUserIsFullAdmin( 158 | _In_ HANDLE hToken 159 | ) 160 | { 161 | BOOLEAN bResult = FALSE; 162 | NTSTATUS status; 163 | DWORD i, Attributes; 164 | ULONG ReturnLength = 0; 165 | 166 | PTOKEN_GROUPS pTkGroups; 167 | 168 | SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY; 169 | PSID adminGroup = NULL; 170 | 171 | do { 172 | if (!NT_SUCCESS(RtlAllocateAndInitializeSid( 173 | &ntAuthority, 174 | 2, 175 | SECURITY_BUILTIN_DOMAIN_RID, 176 | DOMAIN_ALIAS_RID_ADMINS, 177 | 0, 0, 0, 0, 0, 0, 178 | &adminGroup))) 179 | { 180 | break; 181 | } 182 | 183 | status = NtQueryInformationToken(hToken, TokenGroups, NULL, 0, &ReturnLength); 184 | if (status != STATUS_BUFFER_TOO_SMALL) 185 | break; 186 | 187 | pTkGroups = (PTOKEN_GROUPS)supHeapAlloc((SIZE_T)ReturnLength); 188 | if (pTkGroups == NULL) 189 | break; 190 | 191 | status = NtQueryInformationToken(hToken, TokenGroups, pTkGroups, ReturnLength, &ReturnLength); 192 | if (NT_SUCCESS(status)) { 193 | if (pTkGroups->GroupCount > 0) 194 | for (i = 0; i < pTkGroups->GroupCount; i++) { 195 | Attributes = pTkGroups->Groups[i].Attributes; 196 | if (RtlEqualSid(adminGroup, pTkGroups->Groups[i].Sid)) 197 | if ( 198 | (Attributes & SE_GROUP_ENABLED) && 199 | (!(Attributes & SE_GROUP_USE_FOR_DENY_ONLY)) 200 | ) 201 | { 202 | bResult = TRUE; 203 | break; 204 | } 205 | } 206 | } 207 | supHeapFree(pTkGroups); 208 | 209 | } while (FALSE); 210 | 211 | if (adminGroup != NULL) { 212 | RtlFreeSid(adminGroup); 213 | } 214 | 215 | return bResult; 216 | } 217 | 218 | /* 219 | * supIsClientElevated 220 | * 221 | * Purpose: 222 | * 223 | * Returns TRUE if process runs elevated. 224 | * 225 | */ 226 | BOOLEAN supIsClientElevated( 227 | _In_ HANDLE ProcessHandle 228 | ) 229 | { 230 | HANDLE hToken = NULL, processHandle = ProcessHandle; 231 | NTSTATUS Status; 232 | ULONG BytesRead = 0; 233 | TOKEN_ELEVATION te; 234 | 235 | te.TokenIsElevated = 0; 236 | 237 | Status = NtOpenProcessToken(processHandle, TOKEN_QUERY, &hToken); 238 | if (NT_SUCCESS(Status)) { 239 | 240 | Status = NtQueryInformationToken(hToken, TokenElevation, &te, 241 | sizeof(TOKEN_ELEVATION), &BytesRead); 242 | 243 | NtClose(hToken); 244 | } 245 | 246 | return (te.TokenIsElevated > 0); 247 | } 248 | 249 | /* 250 | * supLdrGetProcNameBySDTIndex 251 | * 252 | * Purpose: 253 | * 254 | * Return name of service from ntdll by given syscall id. 255 | * 256 | */ 257 | PCHAR supLdrGetProcNameBySDTIndex( 258 | _In_ PVOID ModuleBase, 259 | _In_ ULONG SDTIndex 260 | ) 261 | { 262 | PIMAGE_EXPORT_DIRECTORY pImageExportDirectory; 263 | PULONG nameTableBase; 264 | PUSHORT nameOrdinalTableBase; 265 | PULONG funcTable; 266 | PBYTE pfn; 267 | ULONG c, exportSize; 268 | 269 | pImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(ModuleBase, 270 | TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exportSize); 271 | 272 | if (pImageExportDirectory) { 273 | 274 | nameTableBase = (PDWORD)RtlOffsetToPointer(ModuleBase, pImageExportDirectory->AddressOfNames); 275 | nameOrdinalTableBase = (PUSHORT)RtlOffsetToPointer(ModuleBase, pImageExportDirectory->AddressOfNameOrdinals); 276 | funcTable = (PDWORD)RtlOffsetToPointer(ModuleBase, pImageExportDirectory->AddressOfFunctions); 277 | 278 | for (c = 0; c < pImageExportDirectory->NumberOfNames; c++) { 279 | pfn = (PBYTE)RtlOffsetToPointer(ModuleBase, funcTable[nameOrdinalTableBase[c]]); 280 | if (*((PULONG)pfn) == 0xb8d18b4c) 281 | if (*((PULONG)(pfn + 4)) == SDTIndex) 282 | return (PCHAR)RtlOffsetToPointer(ModuleBase, nameTableBase[c]); 283 | } 284 | 285 | } 286 | 287 | return NULL; 288 | } 289 | 290 | /* 291 | * supPrivilegeEnabled 292 | * 293 | * Purpose: 294 | * 295 | * Tests if the given token has the given privilege enabled/enabled by default. 296 | * 297 | */ 298 | NTSTATUS supPrivilegeEnabled( 299 | _In_ HANDLE ClientToken, 300 | _In_ ULONG Privilege, 301 | _Out_ PBOOLEAN pfResult 302 | ) 303 | { 304 | NTSTATUS status; 305 | PRIVILEGE_SET Privs; 306 | BOOLEAN bResult = FALSE; 307 | 308 | Privs.Control = PRIVILEGE_SET_ALL_NECESSARY; 309 | Privs.PrivilegeCount = 1; 310 | Privs.Privilege[0].Luid.LowPart = Privilege; 311 | Privs.Privilege[0].Luid.HighPart = 0; 312 | Privs.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT | SE_PRIVILEGE_ENABLED; 313 | 314 | status = NtPrivilegeCheck(ClientToken, &Privs, &bResult); 315 | 316 | *pfResult = bResult; 317 | 318 | return status; 319 | } 320 | 321 | /* 322 | * supQueryTokenUserSid 323 | * 324 | * Purpose: 325 | * 326 | * Return SID of given token. 327 | * 328 | * Use supHeapFree to free memory allocated for result. 329 | * 330 | */ 331 | PSID supQueryTokenUserSid( 332 | _In_ HANDLE hProcessToken 333 | ) 334 | { 335 | PSID result = NULL; 336 | PTOKEN_USER ptu; 337 | NTSTATUS status; 338 | ULONG SidLength = 0, Length; 339 | 340 | status = NtQueryInformationToken(hProcessToken, TokenUser, 341 | NULL, 0, &SidLength); 342 | 343 | if (status == STATUS_BUFFER_TOO_SMALL) { 344 | 345 | ptu = (PTOKEN_USER)supHeapAlloc(SidLength); 346 | 347 | if (ptu) { 348 | 349 | status = NtQueryInformationToken(hProcessToken, TokenUser, 350 | ptu, SidLength, &SidLength); 351 | 352 | if (NT_SUCCESS(status)) { 353 | Length = SECURITY_MAX_SID_SIZE; 354 | if (SidLength > Length) 355 | Length = SidLength; 356 | result = supHeapAlloc(Length); 357 | if (result) { 358 | status = RtlCopySid(Length, result, ptu->User.Sid); 359 | } 360 | } 361 | 362 | supHeapFree(ptu); 363 | } 364 | } 365 | 366 | return (NT_SUCCESS(status)) ? result : NULL; 367 | } 368 | 369 | /* 370 | * supQueryProcessSid 371 | * 372 | * Purpose: 373 | * 374 | * Return SID for the given process. 375 | * 376 | * Use supHeapFree to free memory allocated for result. 377 | * 378 | */ 379 | PSID supQueryProcessSid( 380 | _In_ HANDLE hProcess 381 | ) 382 | { 383 | HANDLE hProcessToken = NULL; 384 | PSID result = NULL; 385 | 386 | if (NT_SUCCESS(NtOpenProcessToken(hProcess, TOKEN_QUERY, &hProcessToken))) { 387 | 388 | result = supQueryTokenUserSid(hProcessToken); 389 | 390 | NtClose(hProcessToken); 391 | } 392 | 393 | return result; 394 | } 395 | 396 | /* 397 | * supIsLocalSystem 398 | * 399 | * Purpose: 400 | * 401 | * pbResult will be set to TRUE if current account is run by system user, FALSE otherwise. 402 | * 403 | * Function return operation status code. 404 | * 405 | */ 406 | NTSTATUS supIsLocalSystem( 407 | _In_ HANDLE hToken, 408 | _Out_ PBOOLEAN pbResult) 409 | { 410 | BOOLEAN bResult = FALSE; 411 | NTSTATUS status = STATUS_UNSUCCESSFUL; 412 | PSID SystemSid = NULL, TokenSid = NULL; 413 | SID_IDENTIFIER_AUTHORITY NtAuth = SECURITY_NT_AUTHORITY; 414 | 415 | TokenSid = supQueryTokenUserSid(hToken); 416 | if (TokenSid == NULL) 417 | return status; 418 | 419 | status = RtlAllocateAndInitializeSid( 420 | &NtAuth, 421 | 1, 422 | SECURITY_LOCAL_SYSTEM_RID, 423 | 0, 0, 0, 0, 0, 0, 0, 424 | &SystemSid); 425 | 426 | if (NT_SUCCESS(status)) { 427 | bResult = RtlEqualSid(TokenSid, SystemSid); 428 | RtlFreeSid(SystemSid); 429 | } 430 | 431 | supHeapFree(TokenSid); 432 | 433 | if (pbResult) 434 | *pbResult = bResult; 435 | 436 | return status; 437 | } 438 | 439 | /* 440 | * supOpenProcess 441 | * 442 | * Purpose: 443 | * 444 | * NtOpenProcess wrapper. 445 | * 446 | */ 447 | NTSTATUS supOpenProcess( 448 | _In_ HANDLE UniqueProcessId, 449 | _In_ ACCESS_MASK DesiredAccess, 450 | _Out_ PHANDLE ProcessHandle 451 | ) 452 | { 453 | NTSTATUS Status; 454 | HANDLE Handle = NULL; 455 | OBJECT_ATTRIBUTES ObjectAttributes = RTL_INIT_OBJECT_ATTRIBUTES((PUNICODE_STRING)NULL, 0); 456 | CLIENT_ID ClientId; 457 | 458 | ClientId.UniqueProcess = UniqueProcessId; 459 | ClientId.UniqueThread = NULL; 460 | 461 | Status = NtOpenProcess(&Handle, DesiredAccess, &ObjectAttributes, &ClientId); 462 | 463 | if (NT_SUCCESS(Status)) { 464 | *ProcessHandle = Handle; 465 | } 466 | 467 | return Status; 468 | } 469 | 470 | /* 471 | * supxGetSystemToken 472 | * 473 | * Purpose: 474 | * 475 | * Find winlogon process and duplicate it token. 476 | * 477 | */ 478 | NTSTATUS supxGetSystemToken( 479 | _In_ PVOID ProcessList, 480 | _Out_ PHANDLE SystemToken) 481 | { 482 | BOOLEAN bSystemToken = FALSE, bEnabled = FALSE; 483 | NTSTATUS Status = STATUS_UNSUCCESSFUL; 484 | ULONG NextEntryDelta = 0; 485 | HANDLE hObject = NULL; 486 | HANDLE hToken = NULL; 487 | 488 | ULONG WinlogonSessionId; 489 | UNICODE_STRING usWinlogon = RTL_CONSTANT_STRING(L"winlogon.exe"); 490 | 491 | union { 492 | PSYSTEM_PROCESSES_INFORMATION Processes; 493 | PBYTE ListRef; 494 | } List; 495 | 496 | *SystemToken = NULL; 497 | 498 | WinlogonSessionId = WTSGetActiveConsoleSessionId(); 499 | if (WinlogonSessionId == 0xFFFFFFFF) 500 | return STATUS_INVALID_SESSION; 501 | 502 | List.ListRef = (PBYTE)ProcessList; 503 | 504 | do { 505 | 506 | List.ListRef += NextEntryDelta; 507 | 508 | if (RtlEqualUnicodeString(&usWinlogon, &List.Processes->ImageName, TRUE)) { 509 | 510 | if (List.Processes->SessionId == WinlogonSessionId) { 511 | 512 | Status = supOpenProcess( 513 | List.Processes->UniqueProcessId, 514 | PROCESS_QUERY_LIMITED_INFORMATION, 515 | &hObject); 516 | 517 | if (NT_SUCCESS(Status)) { 518 | 519 | Status = NtOpenProcessToken( 520 | hObject, 521 | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_IMPERSONATE | TOKEN_QUERY, 522 | &hToken); 523 | 524 | if (NT_SUCCESS(Status)) { 525 | 526 | Status = supIsLocalSystem(hToken, &bSystemToken); 527 | 528 | if (NT_SUCCESS(Status) && (bSystemToken)) { 529 | 530 | Status = supPrivilegeEnabled(hToken, SE_TCB_PRIVILEGE, &bEnabled); 531 | if (NT_SUCCESS(Status)) { 532 | if (bEnabled) { 533 | NtClose(hObject); 534 | *SystemToken = hToken; 535 | return STATUS_SUCCESS; 536 | } 537 | else { 538 | Status = STATUS_PRIVILEGE_NOT_HELD; 539 | } 540 | } 541 | } 542 | NtClose(hToken); 543 | } 544 | 545 | NtClose(hObject); 546 | } 547 | 548 | } 549 | } 550 | 551 | NextEntryDelta = List.Processes->NextEntryDelta; 552 | 553 | } while (NextEntryDelta); 554 | 555 | return Status; 556 | } 557 | 558 | /* 559 | * supShowNtStatus 560 | * 561 | * Purpose: 562 | * 563 | * Display detailed last nt status to user. 564 | * 565 | */ 566 | VOID supShowNtStatus( 567 | _In_ LPCSTR lpText, 568 | _In_ NTSTATUS Status 569 | ) 570 | { 571 | PCHAR lpMsg; 572 | SIZE_T Length = _strlen_a(lpText); 573 | lpMsg = (PCHAR)supHeapAlloc(Length + 200); 574 | if (lpMsg) { 575 | _strcpy_a(lpMsg, "[!] "); 576 | _strcat_a(lpMsg, lpText); 577 | ultohex_a((ULONG)Status, _strend_a(lpMsg)); 578 | _strcat_a(lpMsg, "\r\n"); 579 | ConsoleShowMessage(lpMsg, FOREGROUND_RED | FOREGROUND_INTENSITY); 580 | supHeapFree(lpMsg); 581 | } 582 | } 583 | 584 | #define SI_MAX_BUFFER_LENGTH (512 * 1024 * 1024) 585 | 586 | /* 587 | * supGetSystemInfo 588 | * 589 | * Purpose: 590 | * 591 | * Returns buffer with system information by given InfoClass. 592 | * 593 | * Returned buffer must be freed with supHeapFree after usage. 594 | * 595 | */ 596 | PVOID supGetSystemInfo( 597 | _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass 598 | ) 599 | { 600 | PVOID buffer = NULL; 601 | ULONG bufferSize = PAGE_SIZE; 602 | NTSTATUS ntStatus; 603 | ULONG returnedLength = 0; 604 | 605 | buffer = supHeapAlloc((SIZE_T)bufferSize); 606 | if (buffer == NULL) 607 | return NULL; 608 | 609 | while ((ntStatus = NtQuerySystemInformation( 610 | SystemInformationClass, 611 | buffer, 612 | bufferSize, 613 | &returnedLength)) == STATUS_INFO_LENGTH_MISMATCH) 614 | { 615 | supHeapFree(buffer); 616 | bufferSize <<= 1; 617 | 618 | if (bufferSize > SI_MAX_BUFFER_LENGTH) 619 | return NULL; 620 | 621 | buffer = supHeapAlloc((SIZE_T)bufferSize); 622 | } 623 | 624 | if (NT_SUCCESS(ntStatus)) { 625 | return buffer; 626 | } 627 | 628 | if (buffer) 629 | supHeapFree(buffer); 630 | 631 | return NULL; 632 | } 633 | 634 | /* 635 | * supEnablePrivilege 636 | * 637 | * Purpose: 638 | * 639 | * Enable/Disable given privilege. 640 | * 641 | * Return FALSE on any error. 642 | * 643 | */ 644 | BOOL supEnablePrivilege( 645 | _In_ DWORD PrivilegeName, 646 | _In_ BOOL fEnable 647 | ) 648 | { 649 | NTSTATUS status; 650 | ULONG dummy; 651 | HANDLE hToken; 652 | TOKEN_PRIVILEGES tkPrivs; 653 | 654 | status = NtOpenProcessToken( 655 | NtCurrentProcess(), 656 | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 657 | &hToken); 658 | 659 | if (!NT_SUCCESS(status)) { 660 | return FALSE; 661 | } 662 | 663 | tkPrivs.PrivilegeCount = 1; 664 | tkPrivs.Privileges[0].Luid.LowPart = PrivilegeName; 665 | tkPrivs.Privileges[0].Luid.HighPart = 0; 666 | tkPrivs.Privileges[0].Attributes = (fEnable) ? SE_PRIVILEGE_ENABLED : 0; 667 | status = NtAdjustPrivilegesToken(hToken, FALSE, &tkPrivs, 668 | sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PULONG)&dummy); 669 | if (status == STATUS_NOT_ALL_ASSIGNED) { 670 | status = STATUS_PRIVILEGE_NOT_HELD; 671 | } 672 | NtClose(hToken); 673 | return NT_SUCCESS(status); 674 | } 675 | 676 | /* 677 | * supRunAsLocalSystem 678 | * 679 | * Purpose: 680 | * 681 | * Restart program in local system account. 682 | * 683 | * Note: Elevated instance required. 684 | * 685 | */ 686 | VOID supRunAsLocalSystem( 687 | VOID 688 | ) 689 | { 690 | BOOL bSuccess = FALSE; 691 | NTSTATUS Status; 692 | PVOID ProcessList; 693 | ULONG SessionId = NtCurrentPeb()->SessionId, dummy; 694 | 695 | HANDLE hSystemToken = NULL, hPrimaryToken = NULL, hImpersonationToken = NULL; 696 | 697 | BOOLEAN bThreadImpersonated = FALSE; 698 | 699 | PROCESS_INFORMATION pi; 700 | STARTUPINFO si; 701 | 702 | SECURITY_QUALITY_OF_SERVICE sqos; 703 | OBJECT_ATTRIBUTES obja; 704 | TOKEN_PRIVILEGES* TokenPrivileges; 705 | 706 | BYTE TokenPrivBufffer[sizeof(TOKEN_PRIVILEGES) + 707 | (1 * sizeof(LUID_AND_ATTRIBUTES))]; 708 | 709 | WCHAR szApplication[MAX_PATH * 2]; 710 | 711 | // 712 | // Remember our application name. 713 | // 714 | RtlSecureZeroMemory(szApplication, sizeof(szApplication)); 715 | GetModuleFileName(NULL, szApplication, MAX_PATH); 716 | 717 | sqos.Length = sizeof(sqos); 718 | sqos.ImpersonationLevel = SecurityImpersonation; 719 | sqos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; 720 | sqos.EffectiveOnly = FALSE; 721 | InitializeObjectAttributes(&obja, NULL, 0, NULL, NULL); 722 | obja.SecurityQualityOfService = &sqos; 723 | 724 | ProcessList = supGetSystemInfo(SystemProcessInformation); 725 | if (ProcessList == NULL) { 726 | return; 727 | } 728 | 729 | // 730 | // Optionally, enable debug privileges. 731 | // 732 | supEnablePrivilege(SE_DEBUG_PRIVILEGE, TRUE); 733 | 734 | // 735 | // Get LocalSystem token from winlogon. 736 | // 737 | Status = supxGetSystemToken(ProcessList, &hSystemToken); 738 | 739 | supHeapFree(ProcessList); 740 | 741 | do { 742 | // 743 | // Check supxGetSystemToken result. 744 | // 745 | if (!NT_SUCCESS(Status) || (hSystemToken == NULL)) { 746 | 747 | supShowNtStatus( 748 | "No suitable system token found. Make sure you are running as administrator, code 0x", 749 | Status); 750 | 751 | break; 752 | } 753 | 754 | // 755 | // Duplicate as impersonation token. 756 | // 757 | Status = NtDuplicateToken( 758 | hSystemToken, 759 | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | 760 | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_PRIVILEGES, 761 | &obja, 762 | FALSE, 763 | TokenImpersonation, 764 | &hImpersonationToken); 765 | 766 | if (!NT_SUCCESS(Status)) { 767 | 768 | supShowNtStatus("Error duplicating impersonation token, code 0x", Status); 769 | break; 770 | } 771 | 772 | // 773 | // Duplicate as primary token. 774 | // 775 | Status = NtDuplicateToken( 776 | hSystemToken, 777 | TOKEN_ALL_ACCESS, 778 | &obja, 779 | FALSE, 780 | TokenPrimary, 781 | &hPrimaryToken); 782 | 783 | if (!NT_SUCCESS(Status)) { 784 | 785 | supShowNtStatus("Error duplicating primary token, code 0x", Status); 786 | break; 787 | } 788 | 789 | // 790 | // Impersonate system token. 791 | // 792 | Status = NtSetInformationThread( 793 | NtCurrentThread(), 794 | ThreadImpersonationToken, 795 | &hImpersonationToken, 796 | sizeof(HANDLE)); 797 | 798 | if (!NT_SUCCESS(Status)) { 799 | 800 | supShowNtStatus("Error while impersonating primary token, code 0x", Status); 801 | break; 802 | } 803 | 804 | bThreadImpersonated = TRUE; 805 | 806 | // 807 | // Turn on AssignPrimaryToken privilege in impersonated token. 808 | // 809 | TokenPrivileges = (TOKEN_PRIVILEGES*)&TokenPrivBufffer; 810 | TokenPrivileges->PrivilegeCount = 1; 811 | TokenPrivileges->Privileges[0].Luid.LowPart = SE_ASSIGNPRIMARYTOKEN_PRIVILEGE; 812 | TokenPrivileges->Privileges[0].Luid.HighPart = 0; 813 | TokenPrivileges->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 814 | 815 | Status = NtAdjustPrivilegesToken( 816 | hImpersonationToken, 817 | FALSE, 818 | TokenPrivileges, 819 | 0, 820 | NULL, 821 | (PULONG)&dummy); 822 | 823 | if (!NT_SUCCESS(Status)) { 824 | supShowNtStatus("Error adjusting token privileges, code 0x", Status); 825 | break; 826 | } 827 | 828 | // 829 | // Set session id to primary token. 830 | // 831 | Status = NtSetInformationToken( 832 | hPrimaryToken, 833 | TokenSessionId, 834 | &SessionId, 835 | sizeof(ULONG)); 836 | 837 | if (!NT_SUCCESS(Status)) { 838 | supShowNtStatus("Error setting session id, code 0x", Status); 839 | break; 840 | } 841 | 842 | si.cb = sizeof(si); 843 | GetStartupInfo(&si); 844 | 845 | si.dwFlags = STARTF_USESHOWWINDOW; 846 | si.wShowWindow = SW_SHOWNORMAL; 847 | 848 | // 849 | // Run new instance with prepared primary token. 850 | // 851 | bSuccess = CreateProcessAsUser( 852 | hPrimaryToken, 853 | szApplication, 854 | GetCommandLine(), 855 | NULL, 856 | NULL, 857 | FALSE, 858 | CREATE_DEFAULT_ERROR_MODE, 859 | NULL, 860 | NULL, 861 | &si, 862 | &pi); 863 | 864 | if (bSuccess) { 865 | CloseHandle(pi.hProcess); 866 | CloseHandle(pi.hThread); 867 | } 868 | else { 869 | supShowNtStatus("Run as LocalSystem, code 0x", GetLastError()); 870 | } 871 | 872 | } while (FALSE); 873 | 874 | if (hImpersonationToken) { 875 | NtClose(hImpersonationToken); 876 | } 877 | 878 | // 879 | // Revert To Self. 880 | // 881 | if (bThreadImpersonated) { 882 | hImpersonationToken = NULL; 883 | NtSetInformationThread( 884 | NtCurrentThread(), 885 | ThreadImpersonationToken, 886 | (PVOID)&hImpersonationToken, 887 | sizeof(HANDLE)); 888 | } 889 | 890 | if (hPrimaryToken) NtClose(hPrimaryToken); 891 | if (hSystemToken) NtClose(hSystemToken); 892 | 893 | // 894 | // Quit. 895 | // 896 | if (bSuccess) 897 | PostQuitMessage(0); 898 | } 899 | 900 | /* 901 | * supGetCurrentProcessToken 902 | * 903 | * Purpose: 904 | * 905 | * Return current process token value with TOKEN_QUERY access right. 906 | * 907 | */ 908 | HANDLE supGetCurrentProcessToken( 909 | VOID) 910 | { 911 | HANDLE hToken = NULL; 912 | 913 | if (NT_SUCCESS(NtOpenProcessToken( 914 | NtCurrentProcess(), 915 | TOKEN_QUERY, 916 | &hToken))) 917 | { 918 | return hToken; 919 | } 920 | return NULL; 921 | } 922 | 923 | /* 924 | * supMapImageNoExecute 925 | * 926 | * Purpose: 927 | * 928 | * Map image with SEC_IMAGE_NO_EXECUTE. 929 | * 930 | */ 931 | NTSTATUS supMapImageNoExecute( 932 | _In_ PUNICODE_STRING ImagePath, 933 | _Out_ PVOID* BaseAddress 934 | ) 935 | { 936 | NTSTATUS ntStatus = STATUS_UNSUCCESSFUL; 937 | SIZE_T fileSize = 0; 938 | HANDLE hFile = NULL, hSection = NULL; 939 | OBJECT_ATTRIBUTES obja; 940 | IO_STATUS_BLOCK iost; 941 | LARGE_INTEGER li; 942 | 943 | *BaseAddress = NULL; 944 | 945 | do { 946 | 947 | InitializeObjectAttributes(&obja, ImagePath, 948 | OBJ_CASE_INSENSITIVE, NULL, NULL); 949 | 950 | RtlSecureZeroMemory(&iost, sizeof(iost)); 951 | ntStatus = NtCreateFile(&hFile, 952 | SYNCHRONIZE | FILE_READ_DATA, 953 | &obja, 954 | &iost, 955 | NULL, 956 | 0, 957 | FILE_SHARE_READ, 958 | FILE_OPEN, 959 | FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE, 960 | NULL, 961 | 0); 962 | 963 | if (!NT_SUCCESS(ntStatus)) 964 | break; 965 | 966 | obja.ObjectName = NULL; 967 | 968 | ntStatus = NtCreateSection(&hSection, 969 | SECTION_MAP_READ, 970 | &obja, 971 | NULL, 972 | PAGE_READONLY, 973 | SEC_IMAGE_NO_EXECUTE, 974 | hFile); 975 | 976 | if (!NT_SUCCESS(ntStatus)) 977 | break; 978 | 979 | li.QuadPart = 0; 980 | 981 | ntStatus = NtMapViewOfSection(hSection, 982 | NtCurrentProcess(), 983 | BaseAddress, 984 | 0, 985 | 0, 986 | &li, 987 | &fileSize, 988 | ViewShare, 989 | 0, 990 | PAGE_READONLY); 991 | 992 | if (!NT_SUCCESS(ntStatus)) 993 | break; 994 | 995 | } while (FALSE); 996 | 997 | if (hFile) NtClose(hFile); 998 | if (hSection) NtClose(hSection); 999 | return ntStatus; 1000 | } 1001 | 1002 | /* 1003 | * supLdrGetProcAddressEx 1004 | * 1005 | * Purpose: 1006 | * 1007 | * Simplified GetProcAddress reimplementation. 1008 | * 1009 | */ 1010 | LPVOID supLdrGetProcAddressEx( 1011 | _In_ LPVOID ImageBase, 1012 | _In_ LPCSTR RoutineName 1013 | ) 1014 | { 1015 | PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL; 1016 | USHORT OrdinalNumber; 1017 | PULONG NameTableBase; 1018 | PUSHORT NameOrdinalTableBase; 1019 | PULONG Addr; 1020 | LONG Result; 1021 | ULONG High, Low, Middle = 0; 1022 | 1023 | union { 1024 | PIMAGE_NT_HEADERS64 nt64; 1025 | PIMAGE_NT_HEADERS32 nt32; 1026 | PIMAGE_NT_HEADERS nt; 1027 | } NtHeaders; 1028 | 1029 | if (!NT_SUCCESS(RtlImageNtHeaderEx(RTL_IMAGE_NT_HEADER_EX_FLAG_NO_RANGE_CHECK, 1030 | ImageBase, 0, &NtHeaders.nt))) 1031 | { 1032 | return NULL; 1033 | } 1034 | 1035 | if (NtHeaders.nt == NULL) { 1036 | return NULL; 1037 | } 1038 | 1039 | if (NtHeaders.nt->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) { 1040 | 1041 | ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)RtlOffsetToPointer(ImageBase, 1042 | NtHeaders.nt64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); 1043 | 1044 | } 1045 | else if (NtHeaders.nt->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) { 1046 | 1047 | ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)RtlOffsetToPointer(ImageBase, 1048 | NtHeaders.nt32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); 1049 | } 1050 | else 1051 | { 1052 | return NULL; 1053 | } 1054 | 1055 | NameTableBase = (PULONG)RtlOffsetToPointer(ImageBase, (ULONG)ExportDirectory->AddressOfNames); 1056 | NameOrdinalTableBase = (PUSHORT)RtlOffsetToPointer(ImageBase, (ULONG)ExportDirectory->AddressOfNameOrdinals); 1057 | Low = 0; 1058 | High = ExportDirectory->NumberOfNames - 1; 1059 | while (High >= Low) { 1060 | 1061 | Middle = (Low + High) >> 1; 1062 | 1063 | Result = _strcmp_a( 1064 | RoutineName, 1065 | (char*)RtlOffsetToPointer(ImageBase, NameTableBase[Middle])); 1066 | 1067 | if (Result < 0) { 1068 | High = Middle - 1; 1069 | } 1070 | else { 1071 | if (Result > 0) { 1072 | Low = Middle + 1; 1073 | } 1074 | else { 1075 | break; 1076 | } 1077 | } 1078 | } 1079 | if (High < Low) 1080 | return NULL; 1081 | 1082 | OrdinalNumber = NameOrdinalTableBase[Middle]; 1083 | if ((ULONG)OrdinalNumber >= ExportDirectory->NumberOfFunctions) 1084 | return NULL; 1085 | 1086 | Addr = (PULONG)RtlOffsetToPointer(ImageBase, (ULONG)ExportDirectory->AddressOfFunctions); 1087 | return (LPVOID)RtlOffsetToPointer(ImageBase, Addr[OrdinalNumber]); 1088 | } 1089 | -------------------------------------------------------------------------------- /Source/NtCall64/sup.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * 3 | * (C) COPYRIGHT AUTHORS, 2016 - 2023 4 | * 5 | * TITLE: SUP.H 6 | * 7 | * VERSION: 1.37 8 | * 9 | * DATE: 04 Aug 2023 10 | * 11 | * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 12 | * ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED 13 | * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 14 | * PARTICULAR PURPOSE. 15 | * 16 | *******************************************************************************/ 17 | #pragma once 18 | 19 | typedef struct _WIN32_SHADOWTABLE { 20 | ULONG Index; 21 | CHAR Name[256]; 22 | struct _WIN32_SHADOWTABLE *NextService; 23 | } WIN32_SHADOWTABLE, *PWIN32_SHADOWTABLE; 24 | 25 | #define supHeapAlloc(Size) RtlAllocateHeap(NtCurrentPeb()->ProcessHeap, HEAP_ZERO_MEMORY, Size) 26 | #define supHeapFree(Memory) RtlFreeHeap(NtCurrentPeb()->ProcessHeap, 0, Memory) 27 | 28 | VOID supShowNtStatus( 29 | _In_ LPCSTR lpText, 30 | _In_ NTSTATUS Status); 31 | 32 | VOID ConsoleInit( 33 | VOID); 34 | 35 | VOID ConsoleShowMessage( 36 | _In_ LPCSTR lpMessage, 37 | _In_opt_ WORD wColor); 38 | 39 | BOOLEAN supGetCommandLineOption( 40 | _In_ LPCWSTR OptionName, 41 | _In_ BOOLEAN IsParametric, 42 | _Out_writes_opt_z_(ValueSize) LPWSTR OptionValue, 43 | _In_ ULONG ValueSize, 44 | _Out_opt_ PULONG ParamLength); 45 | 46 | NTSTATUS supIsLocalSystem( 47 | _In_ HANDLE hToken, 48 | _Out_ PBOOLEAN pbResult); 49 | 50 | BOOLEAN supUserIsFullAdmin( 51 | _In_ HANDLE hToken); 52 | 53 | VOID supRunAsLocalSystem(VOID); 54 | 55 | BOOLEAN supIsClientElevated( 56 | _In_ HANDLE ProcessHandle); 57 | 58 | PCHAR supLdrGetProcNameBySDTIndex( 59 | _In_ PVOID MappedImageBase, 60 | _In_ ULONG SDTIndex); 61 | 62 | NTSTATUS supMapImageNoExecute( 63 | _In_ PUNICODE_STRING ImagePath, 64 | _Out_ PVOID* BaseAddress); 65 | 66 | LPVOID supLdrGetProcAddressEx( 67 | _In_ LPVOID ImageBase, 68 | _In_ LPCSTR RoutineName); 69 | -------------------------------------------------------------------------------- /Source/NtCall64/syscall.asm: -------------------------------------------------------------------------------- 1 | ;******************************************************************************* 2 | ; 3 | ; (C) COPYRIGHT AUTHORS, 2016 4 | ; 5 | ; TITLE: SYSCALL.ASM 6 | ; 7 | ; VERSION: 1.00 8 | ; 9 | ; DATE: 11 July 2016 10 | ; 11 | ; Syscall gate implementation. 12 | ; 13 | ; THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 14 | ; ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED 15 | ; TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 16 | ; PARTICULAR PURPOSE. 17 | ; 18 | ;*******************************************************************************/ 19 | public ntSyscallGate 20 | 21 | _TEXT$00 segment para 'CODE' 22 | 23 | ALIGN 16 24 | PUBLIC ntSyscallGate 25 | 26 | ; param 1 (rcx) service ID 27 | ; param 2 (rdx) service arguments count 28 | ; param 3 (r8) pointer to array of arguments 29 | 30 | ntSyscallGate PROC 31 | cmp rdx, 5 32 | jl @@nostack 33 | 34 | sub rdx, 4 35 | xor r9, r9 36 | @@fillstack: 37 | mov rax,[r9*8+r8+020h] 38 | mov [r9*8+rsp+028h], rax 39 | inc r9 40 | dec rdx 41 | jne @@fillstack 42 | 43 | @@nostack: 44 | mov r10, r8 45 | mov rax, rcx 46 | mov rcx, [r10] 47 | mov rdx, [r10+08h] 48 | mov r8, [r10+10h] 49 | mov r9, [r10+18h] 50 | mov r10, rcx 51 | syscall 52 | ret 53 | ntSyscallGate ENDP 54 | 55 | _TEXT$00 ENDS 56 | 57 | END -------------------------------------------------------------------------------- /Source/NtCall64/wfuzzer.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | {69B98EF8-BA16-40CB-829B-A53D857D0104} 15 | wfuzzer 16 | 10.0 17 | NtCall64 18 | 19 | 20 | 21 | Application 22 | true 23 | v143 24 | Unicode 25 | false 26 | 27 | 28 | Application 29 | false 30 | v143 31 | true 32 | Unicode 33 | false 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | NativeRecommendedRules.ruleset 50 | .\output\$(Platform)\$(Configuration)\ 51 | .\output\$(Platform)\$(Configuration)\ 52 | false 53 | false 54 | 55 | 56 | AllRules.ruleset 57 | .\output\$(Platform)\$(Configuration)\ 58 | .\output\$(Platform)\$(Configuration)\ 59 | true 60 | false 61 | 62 | 63 | 64 | Level4 65 | true 66 | All 67 | true 68 | CompileAsC 69 | false 70 | false 71 | Default 72 | true 73 | false 74 | 75 | 76 | 6.0 77 | 78 | 79 | false 80 | true 81 | true 82 | true 83 | Console 84 | true 85 | 86 | 87 | false 88 | 89 | 90 | false 91 | 92 | 93 | false 94 | 95 | 96 | 97 | 98 | Level4 99 | MinSpace 100 | true 101 | true 102 | true 103 | All 104 | true 105 | CompileAsC 106 | false 107 | MultiThreaded 108 | false 109 | false 110 | true 111 | true 112 | 113 | 114 | true 115 | true 116 | 6.0 117 | true 118 | true 119 | true 120 | true 121 | Console 122 | false 123 | 124 | 125 | true 126 | true 127 | /NOCOFFGRPINFO %(AdditionalOptions) 128 | 129 | 130 | false 131 | 132 | 133 | false 134 | 135 | 136 | false 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | Document 184 | .\output\$(Platform)\$(Configuration)\syscall.lst 185 | .\output\$(Platform)\$(Configuration)\syscall.lst 186 | false 187 | false 188 | false 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | -------------------------------------------------------------------------------- /Source/NtCall64/wfuzzer.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {380df33f-96ba-42ba-959c-0b631d9b0b24} 18 | 19 | 20 | {2f4e4843-4b3c-4e51-bf4e-27cd8e8dc260} 21 | 22 | 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | hde 32 | 33 | 34 | Source Files 35 | 36 | 37 | minirtl 38 | 39 | 40 | minirtl 41 | 42 | 43 | minirtl 44 | 45 | 46 | minirtl 47 | 48 | 49 | minirtl 50 | 51 | 52 | minirtl 53 | 54 | 55 | minirtl 56 | 57 | 58 | minirtl 59 | 60 | 61 | minirtl 62 | 63 | 64 | minirtl 65 | 66 | 67 | minirtl 68 | 69 | 70 | minirtl 71 | 72 | 73 | minirtl 74 | 75 | 76 | minirtl 77 | 78 | 79 | minirtl 80 | 81 | 82 | minirtl 83 | 84 | 85 | Source Files 86 | 87 | 88 | Source Files 89 | 90 | 91 | 92 | 93 | Header Files 94 | 95 | 96 | Header Files 97 | 98 | 99 | Header Files 100 | 101 | 102 | Header Files 103 | 104 | 105 | Header Files 106 | 107 | 108 | hde 109 | 110 | 111 | hde 112 | 113 | 114 | hde 115 | 116 | 117 | minirtl 118 | 119 | 120 | minirtl 121 | 122 | 123 | minirtl 124 | 125 | 126 | minirtl 127 | 128 | 129 | Header Files 130 | 131 | 132 | Header Files 133 | 134 | 135 | Header Files 136 | 137 | 138 | Header Files 139 | 140 | 141 | 142 | 143 | Source Files 144 | 145 | 146 | 147 | 148 | Resource Files 149 | 150 | 151 | -------------------------------------------------------------------------------- /Source/NtCall64/wfuzzer.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -win32k -start 4993 5 | WindowsLocalDebugger 6 | 7 | 8 | 9 | 10 | WindowsLocalDebugger 11 | 12 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.0.{build} 2 | branches: 3 | only: 4 | - master 5 | image: Visual Studio 2022 6 | configuration: Release 7 | platform: x64 8 | clone_folder: c:\projects\ntcall64 9 | build: 10 | project: Source/NtCall64.sln 11 | verbosity: normal --------------------------------------------------------------------------------