diff --git a/Compiled/NtCall64.exe b/Compiled/NtCall64.exe index c444a1f..85e2a0a 100644 Binary files a/Compiled/NtCall64.exe and b/Compiled/NtCall64.exe differ diff --git a/Compiled/badcalls.ini b/Compiled/badcalls.ini index e4ce0bd..ac194ce 100644 --- a/Compiled/badcalls.ini +++ b/Compiled/badcalls.ini @@ -1,5 +1,6 @@ [ntos] NtClose +NtInitiatePowerAction NtRaiseHardError NtReleaseKeyedEvent NtPropagationComplete diff --git a/LICENSE.md b/LICENSE.md index 3e1525a..a089817 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,4 +1,4 @@ -Copyright (c) 2016 - 2022, NtCall64 Project +Copyright (c) 2016 - 2023, NtCall64 Project Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/NtCall64.sha256 b/NtCall64.sha256 index d5f4c6b..b250db9 100644 --- a/NtCall64.sha256 +++ b/NtCall64.sha256 @@ -1,45 +1,2 @@ -ddc4a319b3ce482f7e57cd8291994045c41ad62fbcb5a26b03b69a713bea2e4a *Compiled\badcalls.ini -723e1dee6c66b9cbce5dfb87e489ebb70b41e607971393f391b8dba53e6b8734 *Compiled\NtCall64.exe -9c41705a8efa0c845867b4b7d6f9771f2172c15d55e1f00f5de6ef3e4509693b *Source\NtCall64.sln -fad664ec0d0c25531e5564889edeadfca4d47efe763d6536afeaf2d2eedd64d6 *Source\NtCall64\blacklist.c -b48096900363f68a5eb0b395c9b86b133497f1a5725bf481dbe230d39802c906 *Source\NtCall64\blacklist.h -dd32fab74b8aa7a2ac673ee4a6c76e4e852ee0bf9e1a6e0f31ca5f443a87557a *Source\NtCall64\fuzz.c -9d985200820ae2fb844af24010a3addf38492d2d04c760716ed97494b620b847 *Source\NtCall64\fuzz.h -e19447618ecf1721c7f7c94df27ebe78662c0966f0bb86af7399bbbfb7c493c4 *Source\NtCall64\global.h -648ac51015c09a80c88aa4ffe1cc51d8dd08109a5d8ba06473e6ee68a751a475 *Source\NtCall64\log.c -c1f0eb28ee9abc0c371c0ba6a1208b3d5821b20eace4a5a61aab821dbacb9a33 *Source\NtCall64\log.h -5c2b48a253a178a79af61e713e16faeff3cab99f705ac92b57614556960fcdd8 *Source\NtCall64\main.c -0078fbdb03efa638ecf840f776afd4fc4f69e0e96c6bd48363a51350f4321266 *Source\NtCall64\ntos.h -d1130a87d31c6f62387dcfd5ce1449a68c8dad2bc62674d1cc887804758615ae *Source\NtCall64\resource.h -dc8498bc0d0bd32ae2afe115bc5e5a4f885e0aa3608f28693d423fddff151789 *Source\NtCall64\resource.rc -3957bcebe3741c99439bbcd0a4a56643ae5e5dae7139a25e2fea2f0c27ba784d *Source\NtCall64\syscall.asm -062ac9e7119cb058554ec698e9f025e2976dae1a8a838bd5fbd443bdde763148 *Source\NtCall64\tables.h -8b6fb6ce675dd79d355ab39bfe05cb4d9ca08c5ffe9268c838be7b37982e2f76 *Source\NtCall64\util.c -86726b76f7e3456e4a827d43f3db5fce751e571c5969c6902607d5b95dd5e168 *Source\NtCall64\util.h -6461b2932f106c395720cdcaaa834dc181bb1672646ce50984b318c719f50541 *Source\NtCall64\wfuzzer.vcxproj -80f43d7f81eec7648ef4dde1dc4c39b2635becdf64c359441a35512f4bcf5c95 *Source\NtCall64\wfuzzer.vcxproj.filters -5bb622e3b2e91f8ccc320d1cac51113009a3845c05d3de39c3a28b62f627c1f5 *Source\NtCall64\wfuzzer.vcxproj.user -53a7ce27591e040b63880a3dd326b8ba8c97a0fa34d5e2d32aba89a0147434f6 *Source\NtCall64\hde\hde64.c -e99aa4997bda14b534c614c3d8cb78a72c4aca91a1212c8b03ec605d1d75e36e *Source\NtCall64\hde\hde64.h -f8e6a0be357726bee35c7247b57408b54bb38d94e8324a6bb84b91c462b2be30 *Source\NtCall64\hde\pstdint.h -b774446d2f110ce954fb0a710f4693c5562ddbd8d56fe84106f2ee80db8b50a2 *Source\NtCall64\hde\table64.h -893b90b942372928009bad64f166c7018701497e4f7cd1753cdc44f76da06707 *Source\NtCall64\minirtl\cmdline.c -bd6fe82852c4fcdfab559defa33ea394b752a4e4a5ac0653ae20c4a94b0175ed *Source\NtCall64\minirtl\cmdline.h -2a08385892845104b4f07d693ca395eba3a09e4aa89ad791be3807919316ed67 *Source\NtCall64\minirtl\minirtl.h -d7fbfd69df3840022dab1f8f2d529ce04abac8cee0234448bfd0a67feb6aea22 *Source\NtCall64\minirtl\rtltypes.h -0320808115d42f04f63a382e8f386aa9bc77ba879892f5ccc94c40378b5131c8 *Source\NtCall64\minirtl\strtou64.c -f4763588a79859ba8a84e3be35fa1e4b0b8bf95f547a4fee5ae4612978c0787b *Source\NtCall64\minirtl\strtoul.c -e56e67b10a67f0d5ef4128c7ab0c6cb9ba9966916720525edfa6abf3101dfe13 *Source\NtCall64\minirtl\u64tohex.c -4d15af5a22467795c5367c3956746d01424795784f62ca3f30e4619c063338a5 *Source\NtCall64\minirtl\u64tostr.c -f81c975acd016c97776dd3a8e3218e148682b0336ff3fcd77fad6d9b86ddf107 *Source\NtCall64\minirtl\ultohex.c -9cbedf9b92abaef3ea28de28dd523ac44079592178ef727c7003c339a5a54712 *Source\NtCall64\minirtl\ultostr.c -c1405b280bacc7566ccd041a74461de3f8496128fd71e39368905cf8d95268f6 *Source\NtCall64\minirtl\_filename.c -9e3f1386bfb64dbaa3cbb12fd3bf51c734872c2fdf15cf1aaeca52a515767519 *Source\NtCall64\minirtl\_filename.h -83772aa217508279294d91af5cfabec9b5e00b836a2e2f5fe37cf1ebc2905a52 *Source\NtCall64\minirtl\_strcat.c -2a67c7690ec6df8e233207116b0e4fe76c02ae43595d9e606e123572b6ac88a1 *Source\NtCall64\minirtl\_strcmp.c -ef1b18997ea473ac8d516ef60efc64b9175418b8f078e088d783fdaef2544969 *Source\NtCall64\minirtl\_strcmpi.c -969b35213fa23ff50a169e5498a97f28bc6f5820b447b78ec9dc6910dd8cc3e8 *Source\NtCall64\minirtl\_strcpy.c -27159b8ff67d3f8e6c7fdb4b57b9f57f899bdfedf92cf10276269245c6f4e066 *Source\NtCall64\minirtl\_strend.c -60f19c6b805801e13824c4d9d44748da8245cd936971411d3d36b873121888eb *Source\NtCall64\minirtl\_strlen.c -97e0720ed22d2d99e8148aab7ab2cb2cc3df278225669828b2d8d4d9ef856d94 *Source\NtCall64\minirtl\_strncmp.c -0434d69daa20fbf87d829ffc17e43dcc2db3386aff434af888011fdec2f645a4 *Source\NtCall64\minirtl\_strncpy.c +83a3c4632f0f685a56a5c0c54531eba10f32533c74590a011efe439c8a13d83e *Compiled\badcalls.ini +aec6ca2f29b1c474ea1aa8e9a620a557be4391aa951ce35fcc98f45788cf8182 *Compiled\NtCall64.exe diff --git a/README.md b/README.md index bb45ef7..709e228 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ NTCALL64 -help[-win32k][-log][-call Id][-pc Value][-wt Value][-s] * -call Id - fuzz syscall by supplied id (id can be from any table ntos/win32k); * -pc Value - set pass count for each syscall (maximum value is limited to ULONG64 max value), default value 65536; * -wt Value - set wait timeout for calling threads in seconds (except single syscall fuzzing), default value is 30; +* -start Id - Fuzz syscall table starting from given syscall id, mutual exclusive with -call; * -s - Attempt to run program from LocalSystem account. @@ -62,6 +63,7 @@ Example of badcalls.ini (default config shipped with program)
[ntos]
 NtClose
+NtInitiatePowerAction
 NtRaiseHardError
 NtReleaseKeyedEvent
 NtPropagationComplete
@@ -98,6 +100,7 @@ This program may crash the operation system, affect it stability, which may resu
 * [win32k!NtUserCreateActivationObject](https://gist.githubusercontent.com/hfiref0x/23a2331588e7765664f50cac26cf0637/raw/49457ef5e30049b6b4ca392e489aaceaafe2b280/NtUserCreateActivationObject.cpp)
 * [win32k!NtUserOpenDesktop](https://gist.githubusercontent.com/hfiref0x/6e726b352da7642fc5b84bf6ebce0007/raw/8df05220f194da4980f401e15a0efdb7694deb26/NtUserOpenDesktop.c)
 * [win32k!NtUserSetWindowsHookEx](https://gist.github.com/hfiref0x/8ecfbcc0a7afcc9917cef093ef3a18b2)
+* [win32k!NtUserInitialize -> win32kbase!Win32kBaseUserInitialize] (https://gist.github.com/hfiref0x/f731e690e6155c6763b801ce0e497db7)
 * [nt!NtLoadEnclaveData](https://gist.githubusercontent.com/hfiref0x/1ac328a8e73d053012e02955d38e36a8/raw/b26174f8b7b68506d62308ce4327dfc573b8aa26/main.c)
 * [nt!NtCreateIoRing](https://gist.github.com/hfiref0x/bd6365a7cfa881da0e9c9e7a917a051b)
 * [nt!NtQueryInformationCpuPartition](https://gist.github.com/hfiref0x/48bdc12241d0a981a6da473e979c8aff)
@@ -106,13 +109,11 @@ This program may crash the operation system, affect it stability, which may resu
 # Build
 
 NTCALL64 comes with full source code written in C with tiny assembler usage.
-In order to build from source you need Microsoft Visual Studio 2015 and later versions.
+In order to build from source you need Microsoft Visual Studio 2017 and later versions.
 
 ## Instructions
 
 * Select Platform ToolSet first for project in solution you want to build (Project->Properties->General): 
-  * v120 for Visual Studio 2013;
-  * v140 for Visual Studio 2015; 
   * v141 for Visual Studio 2017;
   * v142 for Visual Studio 2019;
   * v143 for Visual Studio 2022.
@@ -123,6 +124,6 @@ In order to build from source you need Microsoft Visual Studio 2015 and later ve
 
 # Authors
 
-(c) 2016 - 2022 NTCALL64 Project
+(c) 2016 - 2023 NTCALL64 Project
 
 Original NtCall by Peter Kosyh aka Gloomy (c) 2001, http://gl00my.chat.ru/ 
diff --git a/Source/NtCall64/fuzz.c b/Source/NtCall64/fuzz.c
index 39dd314..9b83687 100644
--- a/Source/NtCall64/fuzz.c
+++ b/Source/NtCall64/fuzz.c
@@ -1,12 +1,12 @@
 /*******************************************************************************
 *
-*  (C) COPYRIGHT AUTHORS, 2016 - 2021
+*  (C) COPYRIGHT AUTHORS, 2016 - 2023
 *
 *  TITLE:       FUZZ.C
 *
-*  VERSION:     1.35
+*  VERSION:     1.37
 *
-*  DATE:        21 Feb 2021
+*  DATE:        04 Aug 2023
 *
 *  Fuzzing routines.
 *
@@ -23,11 +23,20 @@
 #ifdef __cplusplus 
 extern "C" {
 #endif
-    NTSTATUS ntSyscallGate(ULONG ServiceId, ULONG ArgumentCount, ULONG_PTR *Arguments);
+    NTSTATUS ntSyscallGate(ULONG ServiceId, ULONG ArgumentCount, ULONG_PTR* Arguments);
 #ifdef __cplusplus
 }
 #endif
 
+#define FUZZDATA_COUNT 13
+const ULONG_PTR FuzzData[FUZZDATA_COUNT] = {
+    0x0000000000000000, 0x000000000000ffff, 0x000000000000fffe, 0x00007ffffffeffff,
+    0x00007ffffffefffe, 0x00007fffffffffff, 0x00007ffffffffffe, 0x0000800000000000,
+    0x8000000000000000, 0xffff080000000000, 0xfffff80000000000, 0xffff800000000000,
+    0xffff800000000001
+};
+
+
 /*
 * FuzzEnumWin32uServices
 *
@@ -36,69 +45,62 @@ extern "C" {
 * Enumerate win32u module services to the table.
 *
 */
-_Success_(return != 0)
 ULONG FuzzEnumWin32uServices(
     _In_ HANDLE HeapHandle,
-    _In_ LPVOID Module,
-    _Out_ PWIN32_SHADOWTABLE * Table
+    _In_ LPVOID ModuleBase,
+    _Inout_ PWIN32_SHADOWTABLE* Table
 )
 {
-    PIMAGE_NT_HEADERS           NtHeaders;
-    PIMAGE_EXPORT_DIRECTORY		exp;
-    PDWORD						FnPtrTable, NameTable;
-    PWORD						NameOrdTable;
-    ULONG_PTR					fnptr, exprva, expsize;
-    ULONG						c, n, result;
-    PWIN32_SHADOWTABLE			NewEntry;
+    ULONG i, j, result = 0, exportSize;
+    PBYTE fnptr;
+    PDWORD funcTable, nameTableBase;
+    PWORD nameOrdinalTableBase;
+    PWIN32_SHADOWTABLE w32kTableEntry;
+    PIMAGE_EXPORT_DIRECTORY pImageExportDirectory;
 
-    NtHeaders = RtlImageNtHeader(Module);
-    if (NtHeaders->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_EXPORT)
-        return 0;
+    pImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(ModuleBase,
+        TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exportSize);
 
-    exprva = NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
-    if (exprva == 0)
-        return 0;
+    if (pImageExportDirectory) {
 
-    expsize = NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
+        nameTableBase = (PDWORD)RtlOffsetToPointer(ModuleBase, pImageExportDirectory->AddressOfNames);
+        nameOrdinalTableBase = (PUSHORT)RtlOffsetToPointer(ModuleBase, pImageExportDirectory->AddressOfNameOrdinals);
+        funcTable = (PDWORD)RtlOffsetToPointer(ModuleBase, pImageExportDirectory->AddressOfFunctions);
 
-    exp = (PIMAGE_EXPORT_DIRECTORY)((ULONG_PTR)Module + exprva);
-    FnPtrTable = (PDWORD)((ULONG_PTR)Module + exp->AddressOfFunctions);
-    NameTable = (PDWORD)((ULONG_PTR)Module + exp->AddressOfNames);
-    NameOrdTable = (PWORD)((ULONG_PTR)Module + exp->AddressOfNameOrdinals);
+        result = 0;
 
-    result = 0;
+        for (i = 0; i < pImageExportDirectory->NumberOfFunctions; ++i) {
 
-    for (c = 0; c < exp->NumberOfFunctions; ++c)
-    {
-        fnptr = (ULONG_PTR)Module + FnPtrTable[c];
-        if (*(PDWORD)fnptr != 0xb8d18b4c) //mov r10, rcx; mov eax
-            continue;
+            fnptr = (PBYTE)RtlOffsetToPointer(ModuleBase, funcTable[nameOrdinalTableBase[i]]);
+            if (*(PDWORD)fnptr != 0xb8d18b4c) //mov r10, rcx; mov eax
+                continue;
 
-        NewEntry = (PWIN32_SHADOWTABLE)HeapAlloc(HeapHandle,
-            HEAP_ZERO_MEMORY, sizeof(WIN32_SHADOWTABLE));
+            w32kTableEntry = (PWIN32_SHADOWTABLE)HeapAlloc(HeapHandle,
+                HEAP_ZERO_MEMORY, sizeof(WIN32_SHADOWTABLE));
 
-        if (NewEntry == NULL)
-            break;
+            if (w32kTableEntry == NULL)
+                break;
 
-        NewEntry->Index = *(PDWORD)(fnptr + 4);
+            w32kTableEntry->Index = *(PDWORD)(fnptr + 4);
 
-        for (n = 0; n < exp->NumberOfNames; ++n)
-        {
-            if (NameOrdTable[n] == c)
+            for (j = 0; j < pImageExportDirectory->NumberOfNames; ++j)
             {
-                _strncpy_a(&NewEntry->Name[0],
-                    sizeof(NewEntry->Name),
-                    (LPCSTR)((ULONG_PTR)Module + NameTable[n]),
-                    sizeof(NewEntry->Name));
+                if (nameOrdinalTableBase[j] == i)
+                {
+                    _strncpy_a(&w32kTableEntry->Name[0],
+                        sizeof(w32kTableEntry->Name),
+                        (LPCSTR)RtlOffsetToPointer(ModuleBase, nameTableBase[j]),
+                        sizeof(w32kTableEntry->Name));
 
-                break;
+                    break;
+                }
             }
-        }
 
-        ++result;
+            ++result;
 
-        *Table = NewEntry;
-        Table = &NewEntry->NextService;
+            *Table = w32kTableEntry;
+            Table = &w32kTableEntry->NextService;
+        }
     }
 
     return result;
@@ -138,17 +140,18 @@ PCHAR FuzzResolveW32kServiceNameById(
 * Locate KiServiceTable in mapped ntoskrnl copy.
 *
 */
-BOOL FuzzFindKiServiceTable(
-    _In_ ULONG_PTR MappedImageBase,
+BOOLEAN FuzzFindKiServiceTable(
+    _In_ PVOID MappedImageBase,
     _In_ PRAW_SERVICE_TABLE ServiceTable
 )
 {
-    ULONG_PTR             SectionPtr = 0;
-    IMAGE_NT_HEADERS* NtHeaders = RtlImageNtHeader((PVOID)MappedImageBase);
+    ULONG_PTR SectionPtr = 0;
+    PBYTE ptrCode = (PBYTE)MappedImageBase;
+    IMAGE_NT_HEADERS* NtHeaders = RtlImageNtHeader(MappedImageBase);
     IMAGE_SECTION_HEADER* SectionTableEntry;
-    ULONG                 c, p, SectionSize = 0, SectionVA = 0;
+    ULONG c, p, SectionSize = 0, SectionVA = 0;
 
-    const BYTE  KiSystemServiceStartPattern[] = { 0x45, 0x33, 0xC9, 0x44, 0x8B, 0x05 };
+    const BYTE KiSystemServiceStartPattern[] = { 0x45, 0x33, 0xC9, 0x44, 0x8B, 0x05 };
 
     SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeaders +
         sizeof(ULONG) +
@@ -164,7 +167,7 @@ BOOL FuzzFindKiServiceTable(
 
             {
                 SectionVA = SectionTableEntry->VirtualAddress;
-                SectionPtr = (ULONG_PTR)(MappedImageBase + SectionVA);
+                SectionPtr = (ULONG_PTR)RtlOffsetToPointer(MappedImageBase, SectionVA);
                 SectionSize = SectionTableEntry->Misc.VirtualSize;
                 break;
             }
@@ -191,14 +194,14 @@ BOOL FuzzFindKiServiceTable(
         return FALSE;
 
     p += 3;
-    c = *((PULONG)(MappedImageBase + p + 3)) + 7 + p;
-    ServiceTable->CountOfEntries = *((PULONG)(MappedImageBase + c));
+    c = *((PULONG)(ptrCode + p + 3)) + 7 + p;
+    ServiceTable->CountOfEntries = *((PULONG)(ptrCode + c));
     p += 7;
-    c = *((PULONG)(MappedImageBase + p + 3)) + 7 + p;
-    ServiceTable->StackArgumentTable = (PBYTE)MappedImageBase + c;
+    c = *((PULONG)(ptrCode + p + 3)) + 7 + p;
+    ServiceTable->StackArgumentTable = (PBYTE)ptrCode + c;
     p += 7;
-    c = *((PULONG)(MappedImageBase + p + 3)) + 7 + p;
-    ServiceTable->ServiceTable = (LPVOID*)(MappedImageBase + c);
+    c = *((PULONG)(ptrCode + p + 3)) + 7 + p;
+    ServiceTable->ServiceTable = (LPVOID*)(ptrCode + c);
 
     return TRUE;
 }
@@ -211,23 +214,23 @@ BOOL FuzzFindKiServiceTable(
 * Locate shadow table info in mapped win32k copy.
 *
 */
-BOOL FuzzFindW32pServiceTable(
-    _In_ HMODULE MappedImageBase,
+BOOLEAN FuzzFindW32pServiceTable(
+    _In_ PVOID MappedImageBase,
     _In_ PRAW_SERVICE_TABLE ServiceTable
 )
 {
     PULONG ServiceLimit;
 
-    ServiceLimit = (ULONG*)GetProcAddress(MappedImageBase, "W32pServiceLimit");
+    ServiceLimit = (ULONG*)supLdrGetProcAddressEx(MappedImageBase, "W32pServiceLimit");
     if (ServiceLimit == NULL)
         return FALSE;
 
     ServiceTable->CountOfEntries = *ServiceLimit;
-    ServiceTable->StackArgumentTable = (PBYTE)GetProcAddress(MappedImageBase, "W32pArgumentTable");
+    ServiceTable->StackArgumentTable = (PBYTE)supLdrGetProcAddressEx(MappedImageBase, "W32pArgumentTable");
     if (ServiceTable->StackArgumentTable == NULL)
         return FALSE;
 
-    ServiceTable->ServiceTable = (LPVOID*)GetProcAddress(MappedImageBase, "W32pServiceTable");
+    ServiceTable->ServiceTable = (LPVOID*)supLdrGetProcAddressEx(MappedImageBase, "W32pServiceTable");
     if (ServiceTable->ServiceTable == NULL)
         return FALSE;
 
@@ -242,23 +245,21 @@ BOOL FuzzFindW32pServiceTable(
 * Fuzzing procedure, building parameters list and using syscall gate.
 *
 */
-void DoSystemCall(
+VOID DoSystemCall(
     _In_ ULONG ServiceId,
     _In_ ULONG ParametersInStack,
     _In_ PVOID LogParams
 )
 {
-    ULONG		c;
-    ULONG_PTR	Arguments[MAX_PARAMETERS];
-    ULONG64     u_rand;
+    ULONG c;
+    ULONG_PTR args[MAX_PARAMETERS];
 
-    RtlSecureZeroMemory(Arguments, sizeof(Arguments));
+    RtlSecureZeroMemory(args, sizeof(args));
 
     ParametersInStack /= 4;
 
     for (c = 0; c < ParametersInStack + 4; c++) {
-        u_rand = __rdtsc();
-        Arguments[c] = fuzzdata[u_rand % SIZEOF_FUZZDATA];
+        args[c] = FuzzData[__rdtsc() % FUZZDATA_COUNT];
     }
 
     if (g_ctx.LogEnabled) {
@@ -266,12 +267,11 @@ void DoSystemCall(
         FuzzLogCallParameters((PNTCALL_LOG_PARAMS)LogParams,
             ServiceId,
             ParametersInStack + 4,
-            (ULONG_PTR*)&Arguments);
+            (ULONG_PTR*)&args);
 
     }
 
-    ntSyscallGate(ServiceId, ParametersInStack + 4, Arguments);
-
+    ntSyscallGate(ServiceId, ParametersInStack + 4, args);
 }
 
 /*
@@ -282,57 +282,56 @@ void DoSystemCall(
 * Build shadow table service names list.
 *
 */
-BOOL FuzzLookupWin32kNames(
-    _In_ LPWSTR ModuleName,
-    _Inout_ NTCALL_CONTEXT *Context
+BOOLEAN FuzzLookupWin32kNames(
+    _Inout_ NTCALL_CONTEXT* Context
 )
 {
-    ULONG                   BuildNumber = 0, i;
-    ULONG_PTR               MappedImageBase = Context->SystemImageBase;
-    PIMAGE_NT_HEADERS       NtHeaders = RtlImageNtHeader((PVOID)MappedImageBase);
-    PRAW_SERVICE_TABLE      ServiceTable = &Context->ServiceTable;
-    ULONG_PTR	            Address;
-    CHAR                  **lpServiceNames;
+    ULONG dwBuildNumber = 0, i;
+    PVOID MappedImageBase = Context->SystemModuleBase;
+    PIMAGE_NT_HEADERS NtHeaders = RtlImageNtHeader((PVOID)MappedImageBase);
+    PRAW_SERVICE_TABLE ServiceTable = &Context->ServiceTable;
+    ULONG_PTR Address;
+    PCHAR* lpServiceNames;
 
-    DWORD64  *pW32pServiceTable = NULL;
-    CHAR    **Names = NULL;
-    PCHAR     pfn;
+    DWORD64* pW32pServiceTable = NULL;
+    PCHAR* pszNames = NULL;
+    PCHAR pfn;
 
-    IMAGE_IMPORT_BY_NAME *ImportEntry;
+    IMAGE_IMPORT_BY_NAME* ImportEntry;
 
     HMODULE win32u = NULL;
     ULONG win32uLimit;
     PWIN32_SHADOWTABLE ShadowTable = NULL;
 
-    PCHAR ServiceName;
+    PCHAR lpServiceName;
 
     hde64s hs;
 
-    if (!GetImageVersionInfo(ModuleName, NULL, NULL, &BuildNumber, NULL)) {
-        ConsoleShowMessage("[!] Failed to query win32k.sys version information.\r\n",
-            FOREGROUND_RED | FOREGROUND_INTENSITY);
-        return FALSE;
-    }
+#ifdef _DEBUG
+    dwBuildNumber = g_ctx.OsVersion.dwBuildNumber;
+#else
+    dwBuildNumber = g_ctx.OsVersion.dwBuildNumber;
+#endif
 
-    switch (BuildNumber) {
+    switch (dwBuildNumber) {
 
-    case 7600:
-    case 7601:
+    case NT_WIN7_RTM:
+    case NT_WIN7_SP1:
         if (ServiceTable->CountOfEntries != W32pServiceTableLimit_7601)
             return FALSE;
-        Names = (CHAR**)W32pServiceTableNames_7601;
+        pszNames = (CHAR**)W32pServiceTableNames_7601;
         break;
 
-    case 9200:
+    case NT_WIN8_RTM:
         if (ServiceTable->CountOfEntries != W32pServiceTableLimit_9200)
             return FALSE;
-        Names = (CHAR**)W32pServiceTableNames_9200;
+        pszNames = (CHAR**)W32pServiceTableNames_9200;
         break;
 
-    case 9600:
+    case NT_WIN8_BLUE:
         if (ServiceTable->CountOfEntries != W32pServiceTableLimit_9600)
             return FALSE;
-        Names = (CHAR**)W32pServiceTableNames_9600;
+        pszNames = (CHAR**)W32pServiceTableNames_9600;
         break;
 
     default:
@@ -341,9 +340,7 @@ BOOL FuzzLookupWin32kNames(
         break;
     }
 
-    lpServiceNames = (CHAR**)HeapAlloc(GetProcessHeap(),
-        HEAP_ZERO_MEMORY,
-        ServiceTable->CountOfEntries * sizeof(PCHAR));
+    lpServiceNames = (CHAR**)supHeapAlloc(ServiceTable->CountOfEntries * sizeof(PCHAR));
 
     if (lpServiceNames == NULL)
         return FALSE;
@@ -357,24 +354,21 @@ BOOL FuzzLookupWin32kNames(
     // If win32k version below 10240 copy them from predefined array.
     // Otherwise lookup them dynamically.
     //
-    if (BuildNumber < 10240) {
-        if (Names == NULL)
+    if (dwBuildNumber < NT_WIN10_THRESHOLD1) {
+        if (pszNames == NULL)
             return FALSE;
 
         for (i = 0; i < ServiceTable->CountOfEntries; i++) {
-            lpServiceNames[i] = Names[i];
+            lpServiceNames[i] = pszNames[i];
         }
     }
     else {
 
-        //
-        // 
-        //
-        if (BuildNumber >= 14393) {
+        if (dwBuildNumber >= NT_WIN10_REDSTONE1) {
 
-            win32u = LoadLibraryEx(TEXT("win32u.dll"), NULL, 0);
+            win32u = GetModuleHandle(TEXT("win32u.dll"));
             if (win32u == NULL) {
-                ConsoleShowMessage("[!] Failed to load win32u.dll.\r\n",
+                ConsoleShowMessage("[!] Failed to reference win32u.dll.\r\n",
                     FOREGROUND_RED | FOREGROUND_INTENSITY);
                 return FALSE;
             }
@@ -391,10 +385,10 @@ BOOL FuzzLookupWin32kNames(
 
         for (i = 0; i < ServiceTable->CountOfEntries; i++) {
 
-            ServiceName = "UnknownName";
+            lpServiceName = "UnknownName";
 
-            if (BuildNumber <= 10586) {
-                pfn = (PCHAR)(pW32pServiceTable[i] - NtHeaders->OptionalHeader.ImageBase + MappedImageBase);
+            if (dwBuildNumber <= NT_WIN10_THRESHOLD2) {
+                pfn = (PCHAR)(pW32pServiceTable[i] - NtHeaders->OptionalHeader.ImageBase + (ULONG_PTR)MappedImageBase);
                 hde64_disasm((void*)pfn, &hs);
                 if (hs.flags & F_ERROR) {
 
@@ -403,24 +397,23 @@ BOOL FuzzLookupWin32kNames(
 
                     break;
                 }
-                Address = MappedImageBase + *(ULONG_PTR*)(pfn + hs.len + *(DWORD*)(pfn + (hs.len - 4)));
+                Address = (ULONG_PTR)MappedImageBase + *(ULONG_PTR*)(pfn + hs.len + *(DWORD*)(pfn + (hs.len - 4)));
                 if (Address) {
-                    ImportEntry = (IMAGE_IMPORT_BY_NAME *)Address;
-                    ServiceName = ImportEntry->Name;
+                    ImportEntry = (IMAGE_IMPORT_BY_NAME*)Address;
+                    lpServiceName = ImportEntry->Name;
                 }
             }
-            else if (BuildNumber >= 14393) {
+            else if (dwBuildNumber >= NT_WIN10_REDSTONE1) {
 
-                ServiceName = FuzzResolveW32kServiceNameById(i + 0x1000, ShadowTable);
-                if (ServiceName == NULL) ServiceName = "UnknownName";
+                lpServiceName = FuzzResolveW32kServiceNameById(i + W32SYSCALLSTART, ShadowTable);
+                if (lpServiceName == NULL)
+                    lpServiceName = "UnknownName";
 
             }
-            lpServiceNames[i] = ServiceName;
+            lpServiceNames[i] = lpServiceName;
         }
     }
 
-    if (win32u) FreeLibrary(win32u);
-
     return TRUE;
 }
 
@@ -438,7 +431,7 @@ DWORD WINAPI FuzzThreadProc(
 {
     ULONG64 i, c;
     HMODULE hUser32 = NULL;
-    CALL_PARAM *Context = (CALL_PARAM*)Parameter;
+    CALL_PARAM* Context = (CALL_PARAM*)Parameter;
 
     if (Context->Syscall >= W32SYSCALLSTART)
         hUser32 = LoadLibrary(TEXT("user32.dll"));
@@ -469,7 +462,7 @@ void PrintServiceInformation(
     _In_opt_ LPCSTR ServiceName,
     _In_ BOOL BlackListed)
 {
-    CHAR *pLog;
+    CHAR* pLog;
     CHAR szConsoleText[4096];
     WORD wColor = 0;
 
@@ -507,7 +500,7 @@ void PrintServiceInformation(
 *
 */
 VOID FuzzRunThreadWithWait(
-    _In_ CALL_PARAM *CallParams
+    _In_ CALL_PARAM* CallParams
 )
 {
     HANDLE hThread;
@@ -541,18 +534,18 @@ VOID FuzzRunThreadWithWait(
 *
 */
 VOID FuzzRun(
-    _In_ NTCALL_CONTEXT *Context
+    _In_ NTCALL_CONTEXT* Context
 )
 {
     BOOL probeWin32k = Context->ProbeWin32k, bSkip = FALSE;
-    BLACKLIST *BlackList = &Context->BlackList;
-    ULONG_PTR hNtdll = Context->hNtdll;
+    BLACKLIST* BlackList = &Context->BlackList;
+    PVOID ntdllBase = Context->NtdllBase;
     PRAW_SERVICE_TABLE ServiceTable = &Context->ServiceTable;
     ULONG c, sid;
 
     CALL_PARAM CallParams;
 
-    PCHAR  ServiceName, pLog;
+    PCHAR lpServiceName, pLog;
 
     CHAR szOut[MAX_PATH * 2];
 
@@ -568,22 +561,22 @@ VOID FuzzRun(
         // Query service name.
         //
         if (probeWin32k) {
-            sid = Context->SingleSyscallId - W32SYSCALLSTART;
-            ServiceName = Context->Win32pServiceTableNames[sid];
+            sid = Context->u1.SingleSyscallId - W32SYSCALLSTART;
+            lpServiceName = Context->Win32pServiceTableNames[sid];
         }
         else {
-            sid = Context->SingleSyscallId;
-            ServiceName = (PCHAR)PELoaderGetProcNameBySDTIndex(hNtdll, sid);
+            sid = Context->u1.SingleSyscallId;
+            lpServiceName = supLdrGetProcNameBySDTIndex(ntdllBase, sid);
         }
 
         //
         // Output service information to console.
         //
         _strcpy_a(szOut, "\tProbing #");
-        ultostr_a(Context->SingleSyscallId, _strend_a(szOut));
+        ultostr_a(Context->u1.SingleSyscallId, _strend_a(szOut));
         pLog = _strcat_a(szOut, "\t");
-        if (ServiceName) {
-            _strncpy_a(pLog, MAX_PATH, ServiceName, MAX_PATH);
+        if (lpServiceName) {
+            _strncpy_a(pLog, MAX_PATH, lpServiceName, MAX_PATH);
         }
         else {
             _strcpy_a(pLog, "Unknown");
@@ -595,7 +588,7 @@ VOID FuzzRun(
         // Setup service call parameters and call it in separate thread.
         //
         CallParams.ParametersInStack = Context->ServiceTable.StackArgumentTable[sid];
-        CallParams.Syscall = Context->SingleSyscallId;
+        CallParams.Syscall = Context->u1.SingleSyscallId;
         CallParams.ThreadTimeout = INFINITE;
         CallParams.NumberOfPassesForCall = Context->SyscallPassCount;
         CallParams.LogParams = &g_Log;
@@ -604,22 +597,30 @@ VOID FuzzRun(
     }
     else {
 
-        for (c = 0; c < ServiceTable->CountOfEntries; c++) {
+        c = 0;
+        if (Context->ProbeFromSyscallId) {
+            if (Context->ProbeWin32k)
+                c = Context->u1.StartingSyscallId - W32SYSCALLSTART;
+            else
+                c = Context->u1.StartingSyscallId;
+        }
+
+        for (; c < ServiceTable->CountOfEntries; c++) {
 
             //
             // Query service name.
             //
             if (probeWin32k) {
-                ServiceName = Context->Win32pServiceTableNames[c];
+                lpServiceName = Context->Win32pServiceTableNames[c];
                 sid = W32SYSCALLSTART + c;
             }
             else {
-                ServiceName = (PCHAR)PELoaderGetProcNameBySDTIndex(hNtdll, c);
+                lpServiceName = supLdrGetProcNameBySDTIndex(ntdllBase, c);
                 sid = c;
             }
 
-            if (ServiceName) {
-                bSkip = BlackListEntryPresent(BlackList, (LPCSTR)ServiceName);
+            if (lpServiceName) {
+                bSkip = BlackListEntryPresent(BlackList, (LPCSTR)lpServiceName);
             }
 
             //
@@ -627,7 +628,7 @@ VOID FuzzRun(
             //
             PrintServiceInformation(ServiceTable->StackArgumentTable[c] / 4,
                 sid,
-                ServiceName,
+                lpServiceName,
                 bSkip);
 
             if (bSkip) {
diff --git a/Source/NtCall64/fuzz.h b/Source/NtCall64/fuzz.h
index 0b0a74f..2f10f02 100644
--- a/Source/NtCall64/fuzz.h
+++ b/Source/NtCall64/fuzz.h
@@ -1,12 +1,12 @@
 /*******************************************************************************
 *
-*  (C) COPYRIGHT AUTHORS, 2016 - 2021
+*  (C) COPYRIGHT AUTHORS, 2016 - 2023
 *
 *  TITLE:       FUZZ.H
 *
-*  VERSION:     1.35
+*  VERSION:     1.37
 *
-*  DATE:        21 Feb 2021
+*  DATE:        04 Aug 2023
 *
 * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
 * ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
@@ -17,30 +17,21 @@
 #pragma once
 
 #define W32SYSCALLSTART     0x1000
-#define MAX_PARAMETERS		32
-#define SIZEOF_FUZZDATA		13
+#define MAX_PARAMETERS      32
 
 #define FUZZ_THREAD_TIMEOUT_SEC (30)
 #define FUZZ_PASS_COUNT         (64) * (1024)
 
-static const ULONG_PTR fuzzdata[SIZEOF_FUZZDATA] = {
-    0x0000000000000000, 0x000000000000ffff, 0x000000000000fffe, 0x00007ffffffeffff,
-    0x00007ffffffefffe, 0x00007fffffffffff, 0x00007ffffffffffe, 0x0000800000000000,
-    0x8000000000000000, 0xffff080000000000, 0xfffff80000000000, 0xffff800000000000,
-    0xffff800000000001
-};
-
 VOID FuzzRun(
     _In_ NTCALL_CONTEXT *Context);
 
-BOOL FuzzLookupWin32kNames(
-    _In_ LPWSTR ModuleName,
+BOOLEAN FuzzLookupWin32kNames(
     _Inout_ NTCALL_CONTEXT *Context);
 
-BOOL FuzzFindW32pServiceTable(
-    _In_ HMODULE MappedImageBase,
+BOOLEAN FuzzFindW32pServiceTable(
+    _In_ PVOID MappedImageBase,
     _In_ PRAW_SERVICE_TABLE ServiceTable);
 
-BOOL FuzzFindKiServiceTable(
-    _In_ ULONG_PTR MappedImageBase,
+BOOLEAN FuzzFindKiServiceTable(
+    _In_ PVOID MappedImageBase,
     _In_ PRAW_SERVICE_TABLE ServiceTable);
diff --git a/Source/NtCall64/global.h b/Source/NtCall64/global.h
index 9bb2365..2bae109 100644
--- a/Source/NtCall64/global.h
+++ b/Source/NtCall64/global.h
@@ -1,12 +1,12 @@
 /*******************************************************************************
 *
-*  (C) COPYRIGHT AUTHORS, 2016 - 2021
+*  (C) COPYRIGHT AUTHORS, 2016 - 2023
 *
 *  TITLE:       GLOBAL.H
 *
-*  VERSION:     1.35
+*  VERSION:     1.37
 *
-*  DATE:        21 Feb 2021
+*  DATE:        04 Aug 2023
 *
 *  Global definitions.
 *
@@ -41,12 +41,13 @@
 #include 
 #include 
 #include "ntos.h"
+#include "ntbuilds.h"
 #include "hde\hde64.h"
 #include "minirtl\minirtl.h"
 #include "minirtl\_filename.h"
 #include "minirtl\cmdline.h"
 #include "blacklist.h"
-#include "util.h"
+#include "sup.h"
 #include "log.h"
 
 #pragma comment(lib, "Version.lib")
@@ -66,29 +67,37 @@ typedef struct _CALL_PARAM {
 } CALL_PARAM, *PCALL_PARAM;
 
 typedef struct _NTCALL_CONTEXT {
-    BOOL LogEnabled;
-    BOOL ProbeWin32k;
-    BOOL ProbeSingleSyscall;
-    BOOL IsUserInAdminGroup;
-    BOOL IsLocalSystem;
-    BOOL IsElevated;
-    ULONG SingleSyscallId;
+    BOOLEAN LogEnabled;
+    BOOLEAN ProbeWin32k;
+    BOOLEAN ProbeSingleSyscall;
+    BOOLEAN ProbeFromSyscallId;
+    BOOLEAN IsUserFullAdmin;
+    BOOLEAN IsLocalSystem;
+    BOOLEAN IsElevated;
+    union {
+        ULONG SingleSyscallId;
+        ULONG StartingSyscallId;
+    } u1;
     ULONG ThreadWaitTimeout;
     ULONG64 SyscallPassCount;
-    ULONG_PTR hNtdll;
-    ULONG_PTR SystemImageBase;
-    CHAR **Win32pServiceTableNames;
+    PVOID NtdllBase;
+    PVOID SystemModuleBase;
+    PCHAR *Win32pServiceTableNames;
     RAW_SERVICE_TABLE ServiceTable;
     BLACKLIST BlackList;
-    WCHAR szSystemDirectory[MAX_PATH + 1];
+    RTL_OSVERSIONINFOW OsVersion;
 } NTCALL_CONTEXT, *PNTCALL_CONTEXT;
 
 typedef struct _NTCALL_FUZZ_PARAMS {
-    BOOL EnableLog;
-    BOOL LogToFile;
-    BOOL ProbeWin32k;
-    BOOL ProbeSingleSyscall;
-    ULONG SingleSyscallId;
+    BOOLEAN LogEnabled;
+    BOOLEAN LogToFile;
+    BOOLEAN ProbeWin32k;
+    BOOLEAN ProbeSingleSyscall;
+    BOOLEAN ProbeFromSyscallId;
+    union {
+        ULONG SingleSyscallId;
+        ULONG StartingSyscallId;
+    } u1;
     ULONG ThreadWaitTimeout;
     ULONG64 SyscallPassCount;
     WCHAR szLogDeviceOrFile[MAX_PATH + 1];
diff --git a/Source/NtCall64/log.c b/Source/NtCall64/log.c
index d61dbdf..dec2f63 100644
--- a/Source/NtCall64/log.c
+++ b/Source/NtCall64/log.c
@@ -27,15 +27,15 @@
 * Open port/file for logging.
 *
 */
-BOOL FuzzOpenLog(
+BOOLEAN FuzzOpenLog(
     _In_ LPWSTR LogDeviceFileName,
     _In_ PNTCALL_LOG_PARAMS LogParams
 )
 {
-    HANDLE	hFile;
-    CHAR	szWelcome[128];
-    DWORD	bytesIO;
-    DWORD   openFlags = OPEN_EXISTING;
+    HANDLE hFile;
+    CHAR szWelcome[128];
+    DWORD bytesIO;
+    DWORD openFlags = OPEN_EXISTING;
 
     if (LogParams->LogToFile) openFlags = CREATE_ALWAYS; //always overwrite existing log file.
 
diff --git a/Source/NtCall64/log.h b/Source/NtCall64/log.h
index ad35a93..ae70cad 100644
--- a/Source/NtCall64/log.h
+++ b/Source/NtCall64/log.h
@@ -1,12 +1,12 @@
 /*******************************************************************************
 *
-*  (C) COPYRIGHT AUTHORS, 2016 - 2021
+*  (C) COPYRIGHT AUTHORS, 2016 - 2023
 *
 *  TITLE:       LOG.H
 *
-*  VERSION:     1.35
+*  VERSION:     1.37
 *
-*  DATE:        21 Feb 2021
+*  DATE:        04 Aug 2023
 *
 *  Log support header file.
 *
@@ -24,7 +24,7 @@ typedef struct _NTCALL_LOG_PARAMS {
     HANDLE LogHandle;
 } NTCALL_LOG_PARAMS, * PNTCALL_LOG_PARAMS;
 
-BOOL FuzzOpenLog(
+BOOLEAN FuzzOpenLog(
     _In_ LPWSTR LogDeviceFileName,
     _In_ PNTCALL_LOG_PARAMS LogParams);
 
diff --git a/Source/NtCall64/main.c b/Source/NtCall64/main.c
index 6ac75d7..9999a2e 100644
--- a/Source/NtCall64/main.c
+++ b/Source/NtCall64/main.c
@@ -1,12 +1,12 @@
 /*******************************************************************************
 *
-*  (C) COPYRIGHT AUTHORS, 2016 - 2022
+*  (C) COPYRIGHT AUTHORS, 2016 - 2023
 *
 *  TITLE:       MAIN.C
 *
-*  VERSION:     1.36
+*  VERSION:     1.37
 *
-*  DATE:        04 Sep 2022
+*  DATE:        04 Aug 2023
 *
 *  Program entry point.
 *
@@ -28,25 +28,27 @@
 #define PARAM_WAITTIMEOUT   TEXT("-wt")
 #define PARAM_HELP          TEXT("-help")
 #define PARAM_LOCALSYSTEM   TEXT("-s")
+#define PARAM_SYSCALL_START TEXT("-start")
 
 #define DEFAULT_LOG_PORT    TEXT("COM1")
 #define DEFAULT_LOG_FILE    TEXT("ntcall64.log")
 
 #define WELCOME_BANNER      "NtCall64, Windows NT x64 syscall fuzzer, based on NtCall by Peter Kosyh.\r\n"
-#define VERSION_BANNER      "Version 1.3.6 from 04 Sep 2022\r\n\n"
+#define VERSION_BANNER      "Version 1.3.7 from 04 Aug 2023\r\n\n"
 
 //
 // Help output.
 //
 #define T_HELP	"Usage: -help [-win32k][-log [-pname][-ofile]][-call Id][-pc Value][-wt Value][-s]\r\n\
   -help     - Show this help information;\r\n\
-  -log      - Enable logging to file last call parameters;\r\n\
+  -log      - Enable logging to file last call parameters, use -ofile to specify file otherwise COM port will be used;\r\n\
   -pname    - Port name for logging, default COM1 (-log enabled required, mutual exclusive with -ofile);\r\n\
   -ofile    - File name for logging, default ntcall64.log (-log enabled required, mutual exclusive with -pname);\r\n\
   -win32k   - Fuzz win32k graphical subsystem table, otherwise fuzz ntos table;\r\n\
   -call Id  - Fuzz syscall by supplied numeric  (can be from any table). All blacklists are ignored;\r\n\
   -pc Value - Set number of passes for each service to , default value 65536;\r\n\
   -wt Value - Set wait timeout for calling threads in seconds (except single syscall fuzzing), default value is 30;\r\n\
+  -start Id - Fuzz syscall table starting from given syscall id, mutual exclusive with -call;\r\n\
   -s        - Attempt to run program from LocalSystem account.\r\n\n\
 Example: ntcall64.exe -win32k -log"
 
@@ -133,36 +135,40 @@ void FuzzInitPhase2(
     BOOL probeWin32k = Context->ProbeWin32k;
     ULONG d;
 
+    NTSTATUS ntStatus;
+    UNICODE_STRING usModule;
+
     WCHAR szBuffer[MAX_PATH * 2];
 
     ConsoleShowMessage("[+] Entering FuzzInitPhase2()\r\n",
         FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
 
-    _strcpy(szBuffer, Context->szSystemDirectory);
+    _strcpy(szBuffer, L"\\systemroot\\system32\\");
     if (probeWin32k) {
-        _strcat(szBuffer, TEXT("\\win32k.sys"));
+        _strcat(szBuffer, TEXT("win32k.sys"));
     }
     else {
-        _strcat(szBuffer, TEXT("\\ntoskrnl.exe"));
+        _strcat(szBuffer, TEXT("ntoskrnl.exe"));
     }
 
-    Context->SystemImageBase = (ULONG_PTR)LoadLibraryEx(szBuffer, NULL, 0);
+    RtlInitUnicodeString(&usModule, szBuffer);
+
+    ntStatus = supMapImageNoExecute(&usModule, &Context->SystemModuleBase);
 
-    if (Context->SystemImageBase == 0) {
-        ConsoleShowMessage("[!] Could not preload system image, abort!\r\n",
-            FOREGROUND_RED | FOREGROUND_INTENSITY);
+    if (!NT_SUCCESS(ntStatus) || (Context->SystemModuleBase == NULL)) {
+        supShowNtStatus("[!] Could not preload system image, abort!\r\n", ntStatus);
         return;
     }
 
     if (probeWin32k) {
 
-        if (!FuzzFindW32pServiceTable((HMODULE)Context->SystemImageBase, &Context->ServiceTable)) {
+        if (!FuzzFindW32pServiceTable(Context->SystemModuleBase, &Context->ServiceTable)) {
             ConsoleShowMessage("[!] Could not find W32pServiceTable, abort!\r\n",
                 FOREGROUND_RED | FOREGROUND_INTENSITY);
             return;
         }
 
-        if (!FuzzLookupWin32kNames(szBuffer, Context)) {
+        if (!FuzzLookupWin32kNames(Context)) {
             ConsoleShowMessage("[!] Win32k names query error, abort!\r\n",
                 FOREGROUND_RED | FOREGROUND_INTENSITY);
             return;
@@ -170,14 +176,14 @@ void FuzzInitPhase2(
     }
     else {
 
-        Context->hNtdll = (ULONG_PTR)GetModuleHandle(TEXT("ntdll.dll"));
-        if (Context->hNtdll == 0) {
-            ConsoleShowMessage("[!] Ntdll not found, abort!\r\n",
+        Context->NtdllBase = (PVOID)GetModuleHandle(TEXT("ntdll.dll"));
+        if (Context->NtdllBase == NULL) {
+            ConsoleShowMessage("[!] NTDLL not found, abort!\r\n",
                 FOREGROUND_RED | FOREGROUND_INTENSITY);
             return;
         }
 
-        if (!FuzzFindKiServiceTable(Context->SystemImageBase, &Context->ServiceTable)) {
+        if (!FuzzFindKiServiceTable(Context->SystemModuleBase, &Context->ServiceTable)) {
             ConsoleShowMessage("[!] KiServiceTable not found, abort!\r\n",
                 FOREGROUND_RED | FOREGROUND_INTENSITY);
             return;
@@ -189,7 +195,7 @@ void FuzzInitPhase2(
     //
     if (Context->ProbeSingleSyscall) {
 
-        d = Context->SingleSyscallId;
+        d = Context->u1.SingleSyscallId;
 
         if (Context->ProbeWin32k) {
             d -= W32SYSCALLSTART;
@@ -207,7 +213,7 @@ void FuzzInitPhase2(
 
     FuzzRun(Context);
 
-    FreeLibrary((HMODULE)Context->SystemImageBase);
+    NtUnmapViewOfSection(NtCurrentProcess(), Context->SystemModuleBase);
 
     ConsoleShowMessage("[-] Leaving FuzzInitPhase2()\r\n",
         FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
@@ -225,14 +231,12 @@ VOID FuzzInitPhase1(
     _In_ NTCALL_FUZZ_PARAMS* FuzzParams
 )
 {
+    BOOLEAN LogEnabled = FALSE;
     BOOLEAN bWasEnabled = FALSE;
     WORD wColor = 0;
     UINT i;
 
-    BOOL LogEnabled = FALSE;
     CHAR szOut[MAX_PATH * 2];
-    RTL_OSVERSIONINFOW osver;
-
 
     ConsoleShowMessage("[+] Entering FuzzInitPhase1()\r\n",
         FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
@@ -242,8 +246,8 @@ VOID FuzzInitPhase1(
     if (g_ctx.IsLocalSystem)
         ConsoleShowMessage("[+] LocalSystem account\r\n", 0);
 
-    if (g_ctx.IsUserInAdminGroup) {
-        ConsoleShowMessage("[+] User is admin\r\n", 0);
+    if (g_ctx.IsUserFullAdmin) {
+        ConsoleShowMessage("[+] User is with admin privileges\r\n", 0);
 
         if (g_ctx.IsElevated) {
             ConsoleShowMessage("[+] NtCall64 runs elevated.\r\n", 0);
@@ -253,13 +257,6 @@ VOID FuzzInitPhase1(
         }
     }
 
-    RtlSecureZeroMemory(g_ctx.szSystemDirectory, sizeof(g_ctx.szSystemDirectory));
-    if (!GetSystemDirectory(g_ctx.szSystemDirectory, MAX_PATH)) {
-        ConsoleShowMessage("[!] Could not query system directory, abort!\r\n",
-            FOREGROUND_RED | FOREGROUND_INTENSITY);
-        return;
-    }
-
     //
     // Show current directory.
     //
@@ -279,17 +276,17 @@ VOID FuzzInitPhase1(
     //
     // Show version logo if possible.
     //
-    osver.dwOSVersionInfoSize = sizeof(osver);
-    RtlGetVersion(&osver);
+    g_ctx.OsVersion.dwOSVersionInfoSize = sizeof(g_ctx.OsVersion);
+    RtlGetVersion(&g_ctx.OsVersion);
 
     _strcpy_a(szOut, "[~] Windows version: ");
-    ultostr_a(osver.dwMajorVersion, _strend_a(szOut));
-    ultostr_a(osver.dwMinorVersion, _strcat_a(szOut, "."));
-    ultostr_a(osver.dwBuildNumber, _strcat_a(szOut, "."));
+    ultostr_a(g_ctx.OsVersion.dwMajorVersion, _strend_a(szOut));
+    ultostr_a(g_ctx.OsVersion.dwMinorVersion, _strcat_a(szOut, "."));
+    ultostr_a(g_ctx.OsVersion.dwBuildNumber, _strcat_a(szOut, "."));
     _strcat_a(szOut, "\r\n");
     ConsoleShowMessage(szOut, 0);
 
-    if (FuzzParams->EnableLog) {
+    if (FuzzParams->LogEnabled) {
 
         g_Log.LogHandle = INVALID_HANDLE_VALUE;
         g_Log.LogToFile = FuzzParams->LogToFile;
@@ -304,9 +301,17 @@ VOID FuzzInitPhase1(
             ConsoleShowMessage(szOut, FOREGROUND_RED | FOREGROUND_INTENSITY);
 
         }
-        else
-            ConsoleShowMessage("[+] Logging is enabled\r\n",
+        else {
+            _strcpy_a(szOut, "[+] Logging is enabled, output will be written to ");
+
+            WideCharToMultiByte(CP_ACP, 0, FuzzParams->szLogDeviceOrFile, -1, 
+                _strend_a(szOut), MAX_PATH, NULL, NULL);
+
+            _strcat_a(szOut, "\r\n");
+            
+            ConsoleShowMessage(szOut,
                 FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
+        }
 
         g_ctx.LogEnabled = LogEnabled;
 
@@ -319,9 +324,9 @@ VOID FuzzInitPhase1(
     // Handle single system call.
     //
     if (FuzzParams->ProbeSingleSyscall) {
-        g_ctx.ProbeWin32k = (FuzzParams->SingleSyscallId >= W32SYSCALLSTART);
+        g_ctx.ProbeWin32k = (FuzzParams->u1.SingleSyscallId >= W32SYSCALLSTART);
         g_ctx.ProbeSingleSyscall = TRUE;
-        g_ctx.SingleSyscallId = FuzzParams->SingleSyscallId;
+        g_ctx.u1.SingleSyscallId = FuzzParams->u1.SingleSyscallId;
     }
     else {
         g_ctx.ProbeWin32k = FuzzParams->ProbeWin32k;
@@ -344,6 +349,18 @@ VOID FuzzInitPhase1(
     _strcat_a(szOut, "\r\n");
     ConsoleShowMessage(szOut, 0);
 
+    //
+    // Show probe from syscall id.
+    //
+    g_ctx.ProbeFromSyscallId = FuzzParams->ProbeFromSyscallId;
+    g_ctx.u1.StartingSyscallId = FuzzParams->u1.StartingSyscallId;
+    if (g_ctx.ProbeFromSyscallId) {
+        _strcpy_a(szOut, "[+] Starting syscall id ");
+        ultostr_a(g_ctx.u1.StartingSyscallId, _strend_a(szOut));
+        _strcat_a(szOut, "\r\n");
+        ConsoleShowMessage(szOut, 0);
+    }
+
     //
     // Assign much possible privileges if can.
     //
@@ -393,7 +410,7 @@ VOID FuzzInitPhase1(
     }
 
     if (g_ctx.Win32pServiceTableNames)
-        HeapFree(GetProcessHeap(), 0, g_ctx.Win32pServiceTableNames);
+        supHeapFree(g_ctx.Win32pServiceTableNames);
 
     ConsoleShowMessage("[-] Leaving FuzzInitPhase1()\r\n",
         FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
@@ -413,8 +430,10 @@ VOID FuzzInitPhase0(
 {
     ULONG rLen;
     NTCALL_FUZZ_PARAMS fuzzParams;
+    HANDLE hToken;
+    NTSTATUS ntStatus;
 
-    TCHAR szTextBuf[MAX_PATH + 1];
+    WCHAR szTextBuf[MAX_PATH + 1];
 
     do {
 
@@ -426,22 +445,42 @@ VOID FuzzInitPhase0(
         fuzzParams.SyscallPassCount = FUZZ_PASS_COUNT;
 
         RtlSecureZeroMemory(&g_ctx, sizeof(g_ctx));
-        g_ctx.IsLocalSystem = IsLocalSystem();
-        if (g_ctx.IsLocalSystem) {
-            g_ctx.IsElevated = TRUE;
-            g_ctx.IsUserInAdminGroup = TRUE;
+
+        ntStatus = NtOpenProcessToken(NtCurrentProcess(), TOKEN_QUERY, &hToken);
+        if (NT_SUCCESS(ntStatus)) {
+
+            ntStatus = supIsLocalSystem(hToken, &g_ctx.IsLocalSystem);
+            if (NT_SUCCESS(ntStatus)) {
+                if (g_ctx.IsLocalSystem) {
+                    g_ctx.IsElevated = TRUE;
+                    g_ctx.IsUserFullAdmin = TRUE;
+                }
+                else {
+                    g_ctx.IsUserFullAdmin = supUserIsFullAdmin(hToken);
+                    if (g_ctx.IsUserFullAdmin) {
+                        g_ctx.IsElevated = supIsClientElevated(NtCurrentProcess());
+                    }
+                }
+            }
+            else {
+                supShowNtStatus("[!] Failed to query process token information\r\n", ntStatus);
+                return;
+            }
+
+            NtClose(hToken);
         }
         else {
-            g_ctx.IsUserInAdminGroup = IsUserInAdminGroup();
-            if (g_ctx.IsUserInAdminGroup) {
-                g_ctx.IsElevated = IsElevated(NULL);
-            }
+            supShowNtStatus("[!] Failed to open self process token\r\n", ntStatus);
+            return;
         }
 
-        if (GetCommandLineOption(PARAM_LOCALSYSTEM, FALSE, NULL, 0, NULL)) {
+        //
+        // -s (System) param.
+        //
+        if (supGetCommandLineOption(PARAM_LOCALSYSTEM, FALSE, NULL, 0, NULL)) {
             if (g_ctx.IsLocalSystem == FALSE) {
-                if (g_ctx.IsUserInAdminGroup == FALSE) {
-                    ConsoleShowMessage("[~] Administrative privileges reqruied for this operation\r\n", 0);
+                if (g_ctx.IsUserFullAdmin == FALSE) {
+                    ConsoleShowMessage("[~] Administrative privileges are required for this operation\r\n", 0);
                     break;
                 }
                 if (g_ctx.IsElevated == FALSE) {
@@ -449,7 +488,7 @@ VOID FuzzInitPhase0(
                     break;
                 }
                 ConsoleShowMessage("[~] Restarting as LocalSystem\r\n", 0);
-                RunAsLocalSystem();
+                supRunAsLocalSystem();
                 break;
             }
             //
@@ -457,19 +496,31 @@ VOID FuzzInitPhase0(
             //
         }
 
-        fuzzParams.ProbeWin32k = GetCommandLineOption(PARAM_WIN32K, FALSE, NULL, 0, NULL);
-        fuzzParams.EnableLog = GetCommandLineOption(PARAM_LOG, FALSE, NULL, 0, NULL);
-        if (fuzzParams.EnableLog) {
+        //
+        // -win32k param.
+        //
+        fuzzParams.ProbeWin32k = supGetCommandLineOption(PARAM_WIN32K, FALSE, NULL, 0, NULL);
+
+        //
+        // -log param.
+        //
+        fuzzParams.LogEnabled = supGetCommandLineOption(PARAM_LOG, FALSE, NULL, 0, NULL);
+        if (fuzzParams.LogEnabled) {
 
             _strcpy(fuzzParams.szLogDeviceOrFile, DEFAULT_LOG_PORT);
             fuzzParams.LogToFile = FALSE;
 
             //
-            // Check log port name.
+            // Check log port name (-pname).
             //
             rLen = 0;
             RtlSecureZeroMemory(szTextBuf, sizeof(szTextBuf));
-            if (GetCommandLineOption(PARAM_LOGPORT, TRUE, szTextBuf, sizeof(szTextBuf) / sizeof(TCHAR), &rLen)) {
+            if (supGetCommandLineOption(PARAM_LOGPORT,
+                TRUE, 
+                szTextBuf, 
+                RTL_NUMBER_OF(szTextBuf), 
+                &rLen)) 
+            {
                 if (rLen) {
                     _strcpy(fuzzParams.szLogDeviceOrFile, szTextBuf);
                 }
@@ -477,11 +528,16 @@ VOID FuzzInitPhase0(
             else {
 
                 //
-                // Check log file name.
+                // Check log file name (-ofile).
                 //
                 rLen = 0;
                 RtlSecureZeroMemory(szTextBuf, sizeof(szTextBuf));
-                if (GetCommandLineOption(PARAM_LOGFILE, TRUE, szTextBuf, sizeof(szTextBuf) / sizeof(TCHAR), &rLen)) {
+                if (supGetCommandLineOption(PARAM_LOGFILE,
+                    TRUE, 
+                    szTextBuf, 
+                    RTL_NUMBER_OF(szTextBuf),
+                    &rLen)) 
+                {
                     if (rLen) {
                         _strcpy(fuzzParams.szLogDeviceOrFile, szTextBuf);
                     }
@@ -494,15 +550,45 @@ VOID FuzzInitPhase0(
             }
         }
 
+        //
+        // -call (SyscallId) param.
+        //
         RtlSecureZeroMemory(szTextBuf, sizeof(szTextBuf));
-        if (GetCommandLineOption(PARAM_SYSCALL, TRUE, szTextBuf, sizeof(szTextBuf) / sizeof(TCHAR), NULL))
+        if (supGetCommandLineOption(PARAM_SYSCALL,
+            TRUE, 
+            szTextBuf, 
+            RTL_NUMBER_OF(szTextBuf), 
+            NULL))
         {
             fuzzParams.ProbeSingleSyscall = TRUE;
-            fuzzParams.SingleSyscallId = _strtoul(szTextBuf);
+            fuzzParams.u1.SingleSyscallId = _strtoul(szTextBuf);
+        }
+
+        if (fuzzParams.ProbeSingleSyscall == FALSE) {
+            //
+            // -start (SyscallId) param.
+            //
+            RtlSecureZeroMemory(szTextBuf, sizeof(szTextBuf));
+            if (supGetCommandLineOption(PARAM_SYSCALL_START,
+                TRUE,
+                szTextBuf,
+                RTL_NUMBER_OF(szTextBuf),
+                NULL))
+            {
+                fuzzParams.ProbeFromSyscallId = TRUE;
+                fuzzParams.u1.StartingSyscallId = _strtoul(szTextBuf);
+            }
         }
 
+        //
+        // -pc (PassCount) param.
+        //
         RtlSecureZeroMemory(szTextBuf, sizeof(szTextBuf));
-        if (GetCommandLineOption(PARAM_PASSCOUNT, TRUE, szTextBuf, sizeof(szTextBuf) / sizeof(TCHAR), NULL))
+        if (supGetCommandLineOption(PARAM_PASSCOUNT,
+            TRUE, 
+            szTextBuf, 
+            RTL_NUMBER_OF(szTextBuf), 
+            NULL))
         {
             fuzzParams.SyscallPassCount = strtou64(szTextBuf);
         }
@@ -515,8 +601,15 @@ VOID FuzzInitPhase0(
             break;
         }
 
+        //
+        // -wt (WaitTimeout) param.
+        //
         RtlSecureZeroMemory(szTextBuf, sizeof(szTextBuf));
-        if (GetCommandLineOption(PARAM_WAITTIMEOUT, TRUE, szTextBuf, sizeof(szTextBuf) / sizeof(TCHAR), NULL))
+        if (supGetCommandLineOption(PARAM_WAITTIMEOUT,
+            TRUE, 
+            szTextBuf, 
+            RTL_NUMBER_OF(szTextBuf),
+            NULL))
         {
             fuzzParams.ThreadWaitTimeout = _strtoul(szTextBuf);
         }
@@ -554,7 +647,7 @@ UINT NtCall64Main()
 
         do {
 
-            if (GetCommandLineOption(PARAM_HELP, FALSE, NULL, 0, NULL)) {
+            if (supGetCommandLineOption(PARAM_HELP, FALSE, NULL, 0, NULL)) {
                 ConsoleShowMessage(T_HELP, 0);
                 break;
             }
diff --git a/Source/NtCall64/minirtl/strtou64.c b/Source/NtCall64/minirtl/strtou64.c
index 1ec829c..fad5eb3 100644
--- a/Source/NtCall64/minirtl/strtou64.c
+++ b/Source/NtCall64/minirtl/strtou64.c
@@ -11,7 +11,7 @@ unsigned long long strtou64_a(char *s)
 	while (*s != 0) {
 		c = *s;
 		if (_isdigit_w(c))
-			a = (a*10)+(c-'0');
+			a = (a*10)+((unsigned long long)c-'0');
 		else
 			break;
 		s++;
@@ -30,7 +30,7 @@ unsigned long long strtou64_w(wchar_t *s)
 	while (*s != 0) {
 		c = *s;
 		if (_isdigit_w(c))
-			a = (a*10)+(c-L'0');
+			a = (a*10)+((unsigned long long)c-L'0');
 		else
 			break;
 		s++;
diff --git a/Source/NtCall64/minirtl/strtoul.c b/Source/NtCall64/minirtl/strtoul.c
index 3250d74..4fcd0bb 100644
--- a/Source/NtCall64/minirtl/strtoul.c
+++ b/Source/NtCall64/minirtl/strtoul.c
@@ -1,49 +1,39 @@
 #include "rtltypes.h"
 
-#define ULONG_MAX_VALUE 0xffffffffUL
-
 unsigned long strtoul_a(char *s)
 {
-    unsigned long long  a = 0;
-    char                c;
-
-    if (s == 0)
-        return 0;
-
-    while (*s != 0) {
-        c = *s;
-        if (_isdigit_a(c))
-            a = (a*10)+(c-'0');
-        else
-            break;
-
-        if (a > ULONG_MAX_VALUE)
-            return ULONG_MAX_VALUE;
-
-        s++;
-    }
-    return (unsigned long)a;
+	unsigned long	a = 0;
+	char			c;
+
+	if (s == 0)
+		return 0;
+
+	while (*s != 0) {
+		c = *s;
+		if (_isdigit_a(c))
+			a = (a*10)+(c-'0');
+		else
+			break;
+		s++;
+	}
+	return a;
 }
 
 unsigned long strtoul_w(wchar_t *s)
 {
-    unsigned long long	a = 0;
-    wchar_t			c;
-
-    if (s == 0)
-        return 0;
-
-    while (*s != 0) {
-        c = *s;
-        if (_isdigit_w(c))
-            a = (a * 10) + (c - L'0');
-        else
-            break;
-
-        if (a > ULONG_MAX_VALUE)
-            return ULONG_MAX_VALUE;
-
-        s++;
-    }
-    return (unsigned long)a;
+	unsigned long	a = 0;
+	wchar_t			c;
+
+	if (s == 0)
+		return 0;
+
+	while (*s != 0) {
+		c = *s;
+		if (_isdigit_w(c))
+			a = (a*10)+(c-L'0');
+		else
+			break;
+		s++;
+	}
+	return a;
 }
diff --git a/Source/NtCall64/ntbuilds.h b/Source/NtCall64/ntbuilds.h
new file mode 100644
index 0000000..f92204d
--- /dev/null
+++ b/Source/NtCall64/ntbuilds.h
@@ -0,0 +1,90 @@
+/*******************************************************************************
+*
+*  (C) COPYRIGHT AUTHORS, 2021 - 2023
+*
+*  TITLE:       NTBUILDS.H
+*
+*  VERSION:     1.18
+*
+*  DATE:        21 Jul 2023
+*
+*  Windows NT builds definition file.
+*
+* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
+* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+* PARTICULAR PURPOSE.
+*
+*******************************************************************************/
+#pragma once
+
+//
+// Defines for Major Windows NT release builds
+//
+
+// Windows 7 RTM
+#define NT_WIN7_RTM             7600
+
+// Windows 7 SP1
+#define NT_WIN7_SP1             7601
+
+// Windows 8 RTM
+#define NT_WIN8_RTM             9200
+
+// Windows 8.1
+#define NT_WIN8_BLUE            9600
+
+// Windows 10 TH1
+#define NT_WIN10_THRESHOLD1     10240
+
+// Windows 10 TH2
+#define NT_WIN10_THRESHOLD2     10586
+
+// Windows 10 RS1
+#define NT_WIN10_REDSTONE1      14393
+
+// Windows 10 RS2
+#define NT_WIN10_REDSTONE2      15063
+
+// Windows 10 RS3
+#define NT_WIN10_REDSTONE3      16299
+
+// Windows 10 RS4
+#define NT_WIN10_REDSTONE4      17134
+
+// Windows 10 RS5
+#define NT_WIN10_REDSTONE5      17763
+
+// Windows 10 19H1
+#define NT_WIN10_19H1           18362
+
+// Windows 10 19H2
+#define NT_WIN10_19H2           18363
+
+// Windows 10 20H1
+#define NT_WIN10_20H1           19041
+
+// Windows 10 20H2
+#define NT_WIN10_20H2           19042
+
+// Windows 10 21H1
+#define NT_WIN10_21H1           19043
+
+// Windows 10 21H2
+#define NT_WIN10_21H2           19044
+
+// Windows 10 22H2
+#define NT_WIN10_22H2           19045
+
+// Windows Server 2022
+#define NT_WINSRV_21H1          20348
+
+// Windows 11 21H2
+#define NT_WIN11_21H2           22000
+
+// Windows 11 22H2
+#define NT_WIN11_22H2           22621
+
+// Windows 11 Active Develepment Branch
+#define NT_WIN11_23H2           22631
+#define NT_WIN11_24H2           25905 //canary (24H2)
diff --git a/Source/NtCall64/resource.rc b/Source/NtCall64/resource.rc
index fe710be..594a216 100644
Binary files a/Source/NtCall64/resource.rc and b/Source/NtCall64/resource.rc differ
diff --git a/Source/NtCall64/util.c b/Source/NtCall64/sup.c
similarity index 68%
rename from Source/NtCall64/util.c
rename to Source/NtCall64/sup.c
index 2100606..d7e46c3 100644
--- a/Source/NtCall64/util.c
+++ b/Source/NtCall64/sup.c
@@ -1,12 +1,12 @@
 /*******************************************************************************
 *
-*  (C) COPYRIGHT AUTHORS, 2016 - 2022
+*  (C) COPYRIGHT AUTHORS, 2016 - 2023
 *
-*  TITLE:       UTIL.C
+*  TITLE:       SUP.C
 *
-*  VERSION:     1.36
+*  VERSION:     1.37
 *
-*  DATE:        04 Sep 2022
+*  DATE:        04 Aug 2023
 *
 *  Support routines.
 *
@@ -19,64 +19,6 @@
 
 #include "global.h"
 
-/*
-* GetImageVersionInfo
-*
-* Purpose:
-*
-* Return version numbers from version info.
-*
-*/
-BOOL GetImageVersionInfo(
-    _In_ LPWSTR lpFileName,
-    _Out_opt_ ULONG *MajorVersion,
-    _Out_opt_ ULONG *MinorVersion,
-    _Out_opt_ ULONG *Build,
-    _Out_opt_ ULONG *Revision
-)
-{
-    BOOL bResult = FALSE;
-    DWORD dwHandle, dwSize;
-    PVOID vinfo = NULL;
-    UINT Length;
-    VS_FIXEDFILEINFO *pFileInfo;
-
-    //
-    // Assume failure.
-    //
-    if (MajorVersion)
-        *MajorVersion = 0;
-    if (MinorVersion)
-        *MinorVersion = 0;
-    if (Build)
-        *Build = 0;
-    if (Revision)
-        *Revision = 0;
-
-    dwHandle = 0;
-    dwSize = GetFileVersionInfoSize(lpFileName, &dwHandle);
-    if (dwSize) {
-        vinfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
-        if (vinfo) {
-            if (GetFileVersionInfo(lpFileName, 0, dwSize, vinfo)) {
-                bResult = VerQueryValue(vinfo, TEXT("\\"), (LPVOID *)&pFileInfo, (PUINT)&Length);
-                if (bResult) {
-                    if (MajorVersion)
-                        *MajorVersion = HIWORD(pFileInfo->dwFileVersionMS);
-                    if (MinorVersion)
-                        *MinorVersion = LOWORD(pFileInfo->dwFileVersionMS);
-                    if (Build)
-                        *Build = HIWORD(pFileInfo->dwFileVersionLS);
-                    if (Revision)
-                        *Revision = LOWORD(pFileInfo->dwFileVersionLS);
-                }
-            }
-            HeapFree(GetProcessHeap(), 0, vinfo);
-        }
-    }
-    return bResult;
-}
-
 VOID ConsoleInit(
     VOID)
 {
@@ -153,40 +95,44 @@ VOID ConsoleShowMessage(
 }
 
 /*
-* GetCommandLineOption
+* supGetCommandLineOption
 *
 * Purpose:
 *
 * Parse command line options.
 *
 */
-BOOL GetCommandLineOption(
-    _In_ LPCTSTR OptionName,
-    _In_ BOOL IsParametric,
-    _Out_writes_opt_z_(ValueSize) LPTSTR OptionValue,
+BOOLEAN supGetCommandLineOption(
+    _In_ LPCWSTR OptionName,
+    _In_ BOOLEAN IsParametric,
+    _Out_writes_opt_z_(ValueSize) LPWSTR OptionValue,
     _In_ ULONG ValueSize,
     _Out_opt_ PULONG ParamLength
 )
 {
-    BOOL    bResult;
-    LPTSTR	cmdline = GetCommandLine();
-    TCHAR   Param[MAX_PATH + 1];
-    ULONG   rlen;
-    int		i = 0;
+    BOOLEAN bResult;
+    LPWSTR cmdline = GetCommandLine();
+    WCHAR szParam[MAX_PATH + 1];
+    ULONG rlen;
+    INT	i = 0;
 
     if (ParamLength)
         *ParamLength = 0;
 
-    RtlSecureZeroMemory(Param, sizeof(Param));
-    while (GetCommandLineParam(cmdline, i, Param, MAX_PATH, &rlen))
+    RtlSecureZeroMemory(szParam, sizeof(szParam));
+    while (GetCommandLineParam(
+        cmdline, 
+        i, 
+        szParam, 
+        MAX_PATH, 
+        &rlen)) 
     {
         if (rlen == 0)
             break;
 
-        if (_strcmp(Param, OptionName) == 0)
-        {
+        if (_strcmp(szParam, OptionName) == 0) {
             if (IsParametric) {
-                bResult = GetCommandLineParam(cmdline, i + 1, OptionValue, ValueSize, &rlen);
+                bResult = (BOOLEAN)GetCommandLineParam(cmdline, i + 1, OptionValue, ValueSize, &rlen);
                 if (ParamLength)
                     *ParamLength = rlen;
                 return bResult;
@@ -200,83 +146,85 @@ BOOL GetCommandLineOption(
     return FALSE;
 }
 
-
 /*
-* IsUserInAdminGroup
+* supUserIsFullAdmin
 *
 * Purpose:
 *
-* Returns TRUE if current user is in admin group.
+* Tests if the current user is admin with full access token.
 *
 */
-BOOLEAN IsUserInAdminGroup(
-    VOID
+BOOLEAN supUserIsFullAdmin(
+    _In_ HANDLE hToken
 )
 {
     BOOLEAN bResult = FALSE;
-    HANDLE hToken;
+    NTSTATUS status;
+    DWORD i, Attributes;
+    ULONG ReturnLength = 0;
+
+    PTOKEN_GROUPS pTkGroups;
+
+    SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY;
+    PSID adminGroup = NULL;
+
+    do {
+        if (!NT_SUCCESS(RtlAllocateAndInitializeSid(
+            &ntAuthority,
+            2,
+            SECURITY_BUILTIN_DOMAIN_RID,
+            DOMAIN_ALIAS_RID_ADMINS,
+            0, 0, 0, 0, 0, 0,
+            &adminGroup)))
+        {
+            break;
+        }
 
-    ULONG returnLength, i;
-
-    PSID pSid = NULL;
-
-    PTOKEN_GROUPS ptg = NULL;
-
-    SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
-
-    if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
-
-        GetTokenInformation(hToken, TokenGroups, NULL, 0, &returnLength);
-
-        ptg = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (SIZE_T)returnLength);
-        if (ptg) {
-
-            if (GetTokenInformation(hToken,
-                TokenGroups,
-                ptg,
-                returnLength,
-                &returnLength))
-            {
-                if (AllocateAndInitializeSid(&NtAuthority,
-                    2,
-                    SECURITY_BUILTIN_DOMAIN_RID,
-                    DOMAIN_ALIAS_RID_ADMINS,
-                    0,
-                    0,
-                    0,
-                    0,
-                    0,
-                    0,
-                    &pSid))
-                {
-                    for (i = 0; i < ptg->GroupCount; i++) {
-                        if (EqualSid(pSid, ptg->Groups[i].Sid)) {
+        status = NtQueryInformationToken(hToken, TokenGroups, NULL, 0, &ReturnLength);
+        if (status != STATUS_BUFFER_TOO_SMALL)
+            break;
+
+        pTkGroups = (PTOKEN_GROUPS)supHeapAlloc((SIZE_T)ReturnLength);
+        if (pTkGroups == NULL)
+            break;
+
+        status = NtQueryInformationToken(hToken, TokenGroups, pTkGroups, ReturnLength, &ReturnLength);
+        if (NT_SUCCESS(status)) {
+            if (pTkGroups->GroupCount > 0)
+                for (i = 0; i < pTkGroups->GroupCount; i++) {
+                    Attributes = pTkGroups->Groups[i].Attributes;
+                    if (RtlEqualSid(adminGroup, pTkGroups->Groups[i].Sid))
+                        if (
+                            (Attributes & SE_GROUP_ENABLED) &&
+                            (!(Attributes & SE_GROUP_USE_FOR_DENY_ONLY))
+                            )
+                        {
                             bResult = TRUE;
                             break;
                         }
-                    }
-
-                    FreeSid(pSid);
                 }
-            }
-
-            HeapFree(GetProcessHeap(), 0, ptg);
         }
-        CloseHandle(hToken);
+        supHeapFree(pTkGroups);
+
+    } while (FALSE);
+
+    if (adminGroup != NULL) {
+        RtlFreeSid(adminGroup);
     }
+
     return bResult;
 }
 
 /*
-* IsElevated
+* supIsClientElevated
 *
 * Purpose:
 *
 * Returns TRUE if process runs elevated.
 *
 */
-BOOL IsElevated(
-    _In_opt_ HANDLE ProcessHandle
+BOOLEAN supIsClientElevated(
+    _In_ HANDLE ProcessHandle
 )
 {
     HANDLE hToken = NULL, processHandle = ProcessHandle;
@@ -284,10 +232,6 @@ BOOL IsElevated(
     ULONG BytesRead = 0;
     TOKEN_ELEVATION te;
 
-    if (ProcessHandle == NULL) {
-        processHandle = GetCurrentProcess();
-    }
-
     te.TokenIsElevated = 0;
 
     Status = NtOpenProcessToken(processHandle, TOKEN_QUERY, &hToken);
@@ -303,78 +247,46 @@ BOOL IsElevated(
 }
 
 /*
-* PELoaderGetProcNameBySDTIndex
+* supLdrGetProcNameBySDTIndex
 *
 * Purpose:
 *
 * Return name of service from ntdll by given syscall id.
 *
 */
-PCHAR PELoaderGetProcNameBySDTIndex(
-    _In_ ULONG_PTR MappedImageBase,
+PCHAR supLdrGetProcNameBySDTIndex(
+    _In_ PVOID ModuleBase,
     _In_ ULONG SDTIndex
 )
 {
+    PIMAGE_EXPORT_DIRECTORY pImageExportDirectory;
+    PULONG nameTableBase;
+    PUSHORT nameOrdinalTableBase;
+    PULONG funcTable;
+    PBYTE pfn;
+    ULONG c, exportSize;
+
+    pImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(ModuleBase,
+        TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exportSize);
+
+    if (pImageExportDirectory) {
+
+        nameTableBase = (PDWORD)RtlOffsetToPointer(ModuleBase, pImageExportDirectory->AddressOfNames);
+        nameOrdinalTableBase = (PUSHORT)RtlOffsetToPointer(ModuleBase, pImageExportDirectory->AddressOfNameOrdinals);
+        funcTable = (PDWORD)RtlOffsetToPointer(ModuleBase, pImageExportDirectory->AddressOfFunctions);
+
+        for (c = 0; c < pImageExportDirectory->NumberOfNames; c++) {
+            pfn = (PBYTE)RtlOffsetToPointer(ModuleBase, funcTable[nameOrdinalTableBase[c]]);
+            if (*((PULONG)pfn) == 0xb8d18b4c)
+                if (*((PULONG)(pfn + 4)) == SDTIndex)
+                    return (PCHAR)RtlOffsetToPointer(ModuleBase, nameTableBase[c]);
+        }
 
-    PIMAGE_NT_HEADERS       nthdr = RtlImageNtHeader((PVOID)MappedImageBase);
-    PIMAGE_EXPORT_DIRECTORY ExportDirectory;
-
-    ULONG_PTR   ExportDirectoryOffset;
-    PULONG      NameTableBase;
-    PUSHORT     NameOrdinalTableBase;
-    PULONG      Addr;
-    PBYTE       pfn;
-    ULONG       c;
-
-    ExportDirectoryOffset =
-        nthdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
-
-    if (ExportDirectoryOffset == 0)
-        return NULL;
-
-    ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(MappedImageBase + ExportDirectoryOffset);
-    NameTableBase = (PULONG)(MappedImageBase + (ULONG)ExportDirectory->AddressOfNames);
-    NameOrdinalTableBase = (PUSHORT)(MappedImageBase + (ULONG)ExportDirectory->AddressOfNameOrdinals);
-    Addr = (PULONG)(MappedImageBase + (ULONG)ExportDirectory->AddressOfFunctions);
-
-    for (c = 0; c < ExportDirectory->NumberOfNames; c++) {
-        pfn = (PBYTE)(MappedImageBase + Addr[NameOrdinalTableBase[c]]);
-        if (*((PULONG)pfn) == 0xb8d18b4c)
-            if (*((PULONG)(pfn + 4)) == SDTIndex)
-                return (PCHAR)(MappedImageBase + NameTableBase[c]);
     }
 
     return NULL;
 }
 
-/*
-* supHeapAlloc
-*
-* Purpose:
-*
-* Wrapper for RtlAllocateHeap.
-*
-*/
-FORCEINLINE PVOID supHeapAlloc(
-    _In_ SIZE_T Size)
-{
-    return RtlAllocateHeap(NtCurrentPeb()->ProcessHeap, HEAP_ZERO_MEMORY, Size);
-}
-
-/*
-* supHeapFree
-*
-* Purpose:
-*
-* Wrapper for RtlFreeHeap.
-*
-*/
-FORCEINLINE BOOL supHeapFree(
-    _In_ PVOID Memory)
-{
-    return RtlFreeHeap(NtCurrentPeb()->ProcessHeap, 0, Memory);
-}
-
 /*
 * supPrivilegeEnabled
 *
@@ -495,9 +407,9 @@ NTSTATUS supIsLocalSystem(
     _In_ HANDLE hToken,
     _Out_ PBOOLEAN pbResult)
 {
-    BOOLEAN                  bResult = FALSE;
-    NTSTATUS                 status = STATUS_UNSUCCESSFUL;
-    PSID                     SystemSid = NULL, TokenSid = NULL;
+    BOOLEAN bResult = FALSE;
+    NTSTATUS status = STATUS_UNSUCCESSFUL;
+    PSID SystemSid = NULL, TokenSid = NULL;
     SID_IDENTIFIER_AUTHORITY NtAuth = SECURITY_NT_AUTHORITY;
 
     TokenSid = supQueryTokenUserSid(hToken);
@@ -701,7 +613,7 @@ PVOID supGetSystemInfo(
         &returnedLength)) == STATUS_INFO_LENGTH_MISMATCH)
     {
         supHeapFree(buffer);
-        bufferSize *= 2;
+        bufferSize <<= 1;
 
         if (bufferSize > SI_MAX_BUFFER_LENGTH)
             return NULL;
@@ -734,11 +646,10 @@ BOOL supEnablePrivilege(
     _In_ BOOL fEnable
 )
 {
-    BOOL             bResult = FALSE;
-    NTSTATUS         status;
-    ULONG            dummy;
-    HANDLE           hToken;
-    TOKEN_PRIVILEGES TokenPrivileges;
+    NTSTATUS status;
+    ULONG dummy;
+    HANDLE hToken;
+    TOKEN_PRIVILEGES tkPrivs;
 
     status = NtOpenProcessToken(
         NtCurrentProcess(),
@@ -746,25 +657,24 @@ BOOL supEnablePrivilege(
         &hToken);
 
     if (!NT_SUCCESS(status)) {
-        return bResult;
+        return FALSE;
     }
 
-    TokenPrivileges.PrivilegeCount = 1;
-    TokenPrivileges.Privileges[0].Luid.LowPart = PrivilegeName;
-    TokenPrivileges.Privileges[0].Luid.HighPart = 0;
-    TokenPrivileges.Privileges[0].Attributes = (fEnable) ? SE_PRIVILEGE_ENABLED : 0;
-    status = NtAdjustPrivilegesToken(hToken, FALSE, &TokenPrivileges,
+    tkPrivs.PrivilegeCount = 1;
+    tkPrivs.Privileges[0].Luid.LowPart = PrivilegeName;
+    tkPrivs.Privileges[0].Luid.HighPart = 0;
+    tkPrivs.Privileges[0].Attributes = (fEnable) ? SE_PRIVILEGE_ENABLED : 0;
+    status = NtAdjustPrivilegesToken(hToken, FALSE, &tkPrivs,
         sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PULONG)&dummy);
     if (status == STATUS_NOT_ALL_ASSIGNED) {
         status = STATUS_PRIVILEGE_NOT_HELD;
     }
-    bResult = NT_SUCCESS(status);
     NtClose(hToken);
-    return bResult;
+    return NT_SUCCESS(status);
 }
 
 /*
-* RunAsLocalSystem
+* supRunAsLocalSystem
 *
 * Purpose:
 *
@@ -773,7 +683,7 @@ BOOL supEnablePrivilege(
 * Note: Elevated instance required.
 *
 */
-VOID RunAsLocalSystem(
+VOID supRunAsLocalSystem(
     VOID
 )
 {
@@ -1011,25 +921,168 @@ HANDLE supGetCurrentProcessToken(
 }
 
 /*
-* IsLocalSystem
+* supMapImageNoExecute
 *
 * Purpose:
 *
-* Returns TRUE if current user is LocalSystem.
+* Map image with SEC_IMAGE_NO_EXECUTE.
 *
 */
-BOOLEAN IsLocalSystem(
-    VOID
+NTSTATUS supMapImageNoExecute(
+    _In_ PUNICODE_STRING ImagePath,
+    _Out_ PVOID* BaseAddress
 )
 {
-    BOOLEAN bResult = FALSE;
-    HANDLE hToken;
+    NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
+    SIZE_T fileSize = 0;
+    HANDLE hFile = NULL, hSection = NULL;
+    OBJECT_ATTRIBUTES obja;
+    IO_STATUS_BLOCK iost;
+    LARGE_INTEGER li;
 
-    hToken = supGetCurrentProcessToken();
-    if (hToken) {
-        supIsLocalSystem(hToken, &bResult);
-        NtClose(hToken);
+    *BaseAddress = NULL;
+
+    do {
+
+        InitializeObjectAttributes(&obja, ImagePath,
+            OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+        RtlSecureZeroMemory(&iost, sizeof(iost));
+        ntStatus = NtCreateFile(&hFile,
+            SYNCHRONIZE | FILE_READ_DATA,
+            &obja,
+            &iost,
+            NULL,
+            0,
+            FILE_SHARE_READ,
+            FILE_OPEN,
+            FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE,
+            NULL,
+            0);
+
+        if (!NT_SUCCESS(ntStatus))
+            break;
+
+        obja.ObjectName = NULL;
+
+        ntStatus = NtCreateSection(&hSection,
+            SECTION_MAP_READ,
+            &obja,
+            NULL,
+            PAGE_READONLY,
+            SEC_IMAGE_NO_EXECUTE,
+            hFile);
+
+        if (!NT_SUCCESS(ntStatus))
+            break;
+
+        li.QuadPart = 0;
+
+        ntStatus = NtMapViewOfSection(hSection,
+            NtCurrentProcess(),
+            BaseAddress,
+            0,
+            0,
+            &li,
+            &fileSize,
+            ViewShare,
+            0,
+            PAGE_READONLY);
+
+        if (!NT_SUCCESS(ntStatus))
+            break;
+
+    } while (FALSE);
+
+    if (hFile) NtClose(hFile);
+    if (hSection) NtClose(hSection);
+    return ntStatus;
+}
+
+/*
+* supLdrGetProcAddressEx
+*
+* Purpose:
+*
+* Simplified GetProcAddress reimplementation.
+*
+*/
+LPVOID supLdrGetProcAddressEx(
+    _In_ LPVOID ImageBase,
+    _In_ LPCSTR RoutineName
+)
+{
+    PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL;
+    USHORT OrdinalNumber;
+    PULONG NameTableBase;
+    PUSHORT NameOrdinalTableBase;
+    PULONG Addr;
+    LONG Result;
+    ULONG High, Low, Middle = 0;
+
+    union {
+        PIMAGE_NT_HEADERS64 nt64;
+        PIMAGE_NT_HEADERS32 nt32;
+        PIMAGE_NT_HEADERS nt;
+    } NtHeaders;
+
+    if (!NT_SUCCESS(RtlImageNtHeaderEx(RTL_IMAGE_NT_HEADER_EX_FLAG_NO_RANGE_CHECK,
+        ImageBase, 0, &NtHeaders.nt)))
+    {
+        return NULL;
     }
 
-    return bResult;
+    if (NtHeaders.nt == NULL) {
+        return NULL;
+    }
+
+    if (NtHeaders.nt->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) {
+
+        ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)RtlOffsetToPointer(ImageBase,
+            NtHeaders.nt64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
+
+    }
+    else if (NtHeaders.nt->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) {
+
+        ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)RtlOffsetToPointer(ImageBase,
+            NtHeaders.nt32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
+    }
+    else
+    {
+        return NULL;
+    }
+
+    NameTableBase = (PULONG)RtlOffsetToPointer(ImageBase, (ULONG)ExportDirectory->AddressOfNames);
+    NameOrdinalTableBase = (PUSHORT)RtlOffsetToPointer(ImageBase, (ULONG)ExportDirectory->AddressOfNameOrdinals);
+    Low = 0;
+    High = ExportDirectory->NumberOfNames - 1;
+    while (High >= Low) {
+
+        Middle = (Low + High) >> 1;
+
+        Result = _strcmp_a(
+            RoutineName,
+            (char*)RtlOffsetToPointer(ImageBase, NameTableBase[Middle]));
+
+        if (Result < 0) {
+            High = Middle - 1;
+        }
+        else {
+            if (Result > 0) {
+                Low = Middle + 1;
+            }
+            else {
+                break;
+            }
+        }
+    }
+    if (High < Low)
+        return NULL;
+
+    OrdinalNumber = NameOrdinalTableBase[Middle];
+    if ((ULONG)OrdinalNumber >= ExportDirectory->NumberOfFunctions)
+        return NULL;
+
+    Addr = (PULONG)RtlOffsetToPointer(ImageBase, (ULONG)ExportDirectory->AddressOfFunctions);
+    return (LPVOID)RtlOffsetToPointer(ImageBase, Addr[OrdinalNumber]);
 }
diff --git a/Source/NtCall64/sup.h b/Source/NtCall64/sup.h
new file mode 100644
index 0000000..ae3b645
--- /dev/null
+++ b/Source/NtCall64/sup.h
@@ -0,0 +1,68 @@
+/*******************************************************************************
+*
+*  (C) COPYRIGHT AUTHORS, 2016 - 2023
+*
+*  TITLE:       SUP.H
+*
+*  VERSION:     1.37
+*
+*  DATE:        04 Aug 2023
+*
+* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
+* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+* PARTICULAR PURPOSE.
+*
+*******************************************************************************/
+#pragma once
+
+typedef struct _WIN32_SHADOWTABLE {
+    ULONG Index;
+    CHAR Name[256];
+    struct _WIN32_SHADOWTABLE *NextService;
+} WIN32_SHADOWTABLE, *PWIN32_SHADOWTABLE;
+
+#define supHeapAlloc(Size) RtlAllocateHeap(NtCurrentPeb()->ProcessHeap, HEAP_ZERO_MEMORY, Size)
+#define supHeapFree(Memory) RtlFreeHeap(NtCurrentPeb()->ProcessHeap, 0, Memory)
+
+VOID supShowNtStatus(
+    _In_ LPCSTR lpText,
+    _In_ NTSTATUS Status);
+
+VOID ConsoleInit(
+    VOID);
+
+VOID ConsoleShowMessage(
+    _In_ LPCSTR lpMessage,
+    _In_opt_ WORD wColor);
+
+BOOLEAN supGetCommandLineOption(
+    _In_ LPCWSTR OptionName,
+    _In_ BOOLEAN IsParametric,
+    _Out_writes_opt_z_(ValueSize) LPWSTR OptionValue,
+    _In_ ULONG ValueSize,
+    _Out_opt_ PULONG ParamLength);
+
+NTSTATUS supIsLocalSystem(
+    _In_ HANDLE hToken,
+    _Out_ PBOOLEAN pbResult);
+
+BOOLEAN supUserIsFullAdmin(
+    _In_ HANDLE hToken);
+
+VOID supRunAsLocalSystem(VOID);
+
+BOOLEAN supIsClientElevated(
+    _In_ HANDLE ProcessHandle);
+
+PCHAR supLdrGetProcNameBySDTIndex(
+    _In_ PVOID MappedImageBase,
+    _In_ ULONG SDTIndex);
+
+NTSTATUS supMapImageNoExecute(
+    _In_ PUNICODE_STRING ImagePath,
+    _Out_ PVOID* BaseAddress);
+
+LPVOID supLdrGetProcAddressEx(
+    _In_ LPVOID ImageBase,
+    _In_ LPCSTR RoutineName);
diff --git a/Source/NtCall64/util.h b/Source/NtCall64/util.h
deleted file mode 100644
index 055be88..0000000
--- a/Source/NtCall64/util.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*******************************************************************************
-*
-*  (C) COPYRIGHT AUTHORS, 2016 - 2022
-*
-*  TITLE:       UTIL.H
-*
-*  VERSION:     1.36
-*
-*  DATE:        04 Sep 2022
-*
-* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
-* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
-* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
-* PARTICULAR PURPOSE.
-*
-*******************************************************************************/
-#pragma once
-
-typedef struct _WIN32_SHADOWTABLE {
-    ULONG Index;
-    CHAR Name[256];
-    struct _WIN32_SHADOWTABLE *NextService;
-} WIN32_SHADOWTABLE, *PWIN32_SHADOWTABLE;
-
-BOOL GetImageVersionInfo(
-    _In_ LPWSTR lpFileName,
-    _Out_opt_ ULONG *MajorVersion,
-    _Out_opt_ ULONG *MinorVersion,
-    _Out_opt_ ULONG *Build,
-    _Out_opt_ ULONG *Revision);
-
-VOID ConsoleInit(
-    VOID);
-
-VOID ConsoleShowMessage(
-    _In_ LPCSTR lpMessage,
-    _In_opt_ WORD wColor);
-
-BOOL GetCommandLineOption(
-    _In_ LPCTSTR OptionName,
-    _In_ BOOL IsParametric,
-    _Out_writes_opt_z_(ValueSize) LPTSTR OptionValue,
-    _In_ ULONG ValueSize,
-    _Out_opt_ PULONG ParamLength);
-
-BOOLEAN IsLocalSystem(VOID);
-BOOLEAN IsUserInAdminGroup(VOID);
-VOID RunAsLocalSystem(VOID);
-
-BOOL IsElevated(
-    _In_opt_ HANDLE ProcessHandle);
-
-PCHAR PELoaderGetProcNameBySDTIndex(
-    _In_ ULONG_PTR MappedImageBase,
-    _In_ ULONG SDTIndex);
diff --git a/Source/NtCall64/wfuzzer.vcxproj b/Source/NtCall64/wfuzzer.vcxproj
index 30dd8dd..3f139eb 100644
--- a/Source/NtCall64/wfuzzer.vcxproj
+++ b/Source/NtCall64/wfuzzer.vcxproj
@@ -158,7 +158,7 @@
     
     
     
-    
+    
   
   
     
@@ -172,10 +172,11 @@
     
     
     
+    
     
     
     
-    
+    
   
   
     
diff --git a/Source/NtCall64/wfuzzer.vcxproj.filters b/Source/NtCall64/wfuzzer.vcxproj.filters
index 72f5d0b..4d0fc1f 100644
--- a/Source/NtCall64/wfuzzer.vcxproj.filters
+++ b/Source/NtCall64/wfuzzer.vcxproj.filters
@@ -24,7 +24,7 @@
     
       Source Files
     
-    
+    
       Source Files
     
     
@@ -95,7 +95,7 @@
     
       Header Files
     
-    
+    
       Header Files
     
     
@@ -134,6 +134,9 @@
     
       Header Files
     
+    
+      Header Files
+    
   
   
     
diff --git a/Source/NtCall64/wfuzzer.vcxproj.user b/Source/NtCall64/wfuzzer.vcxproj.user
index 4967d14..66da31c 100644
--- a/Source/NtCall64/wfuzzer.vcxproj.user
+++ b/Source/NtCall64/wfuzzer.vcxproj.user
@@ -1,7 +1,7 @@
 
 
   
-    -win32k
+    -win32k -start 4993
     WindowsLocalDebugger