├── 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 | [](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
--------------------------------------------------------------------------------