NtCall64 fuzzes the Windows NT syscall table on x64 with an inherited blacklist
Windows NT x64 syscall fuzzer
At a glance
- What is it?
- NtCall64 is a C fuzzer that calls Windows NT system calls with generated arguments to shake out crashes in ntoskrnl and, optionally, the win32k subsystem, and it extends Peter Kosyh's original 32-bit NtCall. It suits kernel and driver researchers on a disposable Windows 10 or 11 machine, and it is a tool that will crash the box it runs on.
- Who is it for?
- Kernel and driver researchers who need to find crashes in the Windows syscall layer, and who have a spare Windows 10 or 11 machine they are willing to lose, are the people NtCall64 is for, and the list of bugs it has already turned up in win32k and ntoskrnl is the evidence that it works.
- Can I use it commercially?
- Yes. BSD-2-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 41 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
It calls system calls with generated arguments and watches what breaks
The mechanism is direct and blunt. NtCall64 walks a Windows NT system call table and invokes each entry with parameters it constructs, over and over, to find inputs that the kernel does not handle. The README states the purpose plainly, which is to port and extend the functionality of NtCall for x64 Windows and let researchers fuzz the system call tables, ntoskrnl and optionally win32k, for vulnerabilities and stability issues. The target is Windows NT 6 and later, which the documentation lists as Windows 7 and later, and the system requirements ask for the x64 version of Windows 10 or 11 with administrative privileges recommended for full functionality. The idea is inherited rather than invented. The tool descends from NtCall by Peter Kosyh, also known as Gloomy, from 2001, and the authors section credits the original work separately from the 2016 to 2026 NtCall64 project.
The command line is a dozen switches, and two of them change what you fuzz
Everything is driven from one executable, and the switch list is short enough to read in full. The usage line below shows the whole surface, and the options table that follows it explains each one.
ntcall64.exe -help [-win32k] [-log [-o <file_or_port>]] [-call Id] [-pc Value] [-wt Value] [-sc Value] [-s] [-h]Two switches change the target rather than the behaviour. Without any parameters the tool fuzzes all the ntoskrnl services in the KiServiceTable, and the -win32k switch moves the target to the win32k graphical subsystem service table, described as the Shadow SSDT. The -call switch narrows the run to a single syscall by numeric ID, from any table, and it has two side effects worth knowing, because blacklists are ignored and the thread timeout becomes infinite. The -pc switch sets the number of passes for each syscall, defaulting to 65536, and -sc sets the table index to start from, defaulting to 0. A handful of documented invocations show the combinations that matter.
ntcall64.exe -win32k
ntcall64.exe -log -o COM2
ntcall64.exe -win32k -log -pc 1234
ntcall64.exe -call 4097 -log -pc 1000
ntcall64.exe -sThe blacklist is a file of service names you edit by hand
The one piece of configuration is badcalls.ini, and it is deliberately a plain text file so you can adapt it. You add service names, case-sensitively, to the appropriate section, either ntos or win32k, and the tool skips them. The example file in the documentation lists a set of ntos entries that are plainly expected to be destructive or to hang, such as NtDelayExecution, NtRaiseHardError, NtSetSystemPowerState, NtShutdownSystem, NtSuspendProcess, NtTerminateProcess, NtWaitForSingleObject, and a win32k section with entries like NtUserLockWorkStation, NtUserSwitchDesktop and NtUserWaitMessage. The list is a starting point rather than a complete set, and the gap is the practical risk. A call you did not think of, on a table you did not fully enumerate, is exactly the kind of input that hangs the machine, and the tool does not tell you in advance which ones those are.
Logging to a serial port points the fuzzer at real hardware
The -log switch turns on logging of call parameters, and the documentation says plainly that this reduces performance. The -o switch sets the destination, either a COM port name such as COM1 or COM2, or a file name, and the default file is ntcall64.log. The serial port option is described as being for hardware debugging, which tells you who this feature is for. When the kernel crashes in a way that takes the debugger with it, the last thing printed to a file may be lost with the system, whereas a log written over a serial line to a second machine survives the crash. The thread wait timeout also changes with logging on, with the default being 30 seconds and 240 seconds when logging is enabled, which is a sensible adjustment since writing every parameter set is far slower than discarding them.
Heuristics and LocalSystem change how the parameters are built
The -h switch enables heuristics when building syscall parameters, and that is the difference between a fuzzer that produces plausible arguments and one that sprays random values into a kernel interface. Kernel routines are often written assuming a caller passes a structure of the right shape with plausible contents, and a fuzzer that only randomises the values tends to find the shallow argument validation bugs while missing the deeper ones. The -s switch asks the program to run from the LocalSystem account, which gives the calls the highest privilege context available on the machine. Both options push the tool further from a safe default, and both are opt-in, which tells you the author expects people to run it deliberately rather than by accident.
Building means Visual Studio with a specific toolset and SDK
The build is a Visual Studio solution, and the documentation is specific about the settings because the defaults will not work. You need Microsoft Visual Studio 2017 or later, and the platform toolset has to be set to match your Visual Studio version, with v141 for VS 2017, v142 for VS 2019, v143 for VS 2022 and v145 for VS 2026. The target platform version should be 10 for v141 and above, or 8.1 for v140, and the minimum required Windows SDK version is 8.1. The code is C with minimal assembler use, and the repository layout is small, with a Source directory, an appveyor.yml continuous integration file and the licence and readme. A build matrix that reaches VS 2026 with a v145 toolset is worth noting, because it says the project still compiles against current tooling rather than being frozen on an older platform.
The bugs it has already found are in win32k and in ntoskrnl
The documentation closes with a list of bugs found using the tool, and that list is the strongest argument for the project. Almost all of them are in win32k, including NtGdiDdDDISetHwProtectionTeardownRecovery, NtUserCreateActivationObject, NtUserOpenDesktop, NtUserSetWindowsHookEx, NtUserRegisterCoreMessagingEndPoint and a path through NtUserInitialize into win32kbase!Win32kBaseUserInitialize, each with a linked analysis. Three are in the kernel itself, namely NtLoadEnclaveData, NtCreateIoRing and NtQueryInformationCpuPartition. A pattern is visible, and it is not a random one. The wins cluster around handle and object lifetime paths, where a reference counting mistake or a use after free is easy to trigger, and the presence of NtUserSetWindowsHookEx among them says something about how much surface the win32k table exposes.
Where this fuzzer is the wrong choice
The first wrong choice is running it anywhere you care about. The warning is unambiguous, saying the tool is for research and development, that it may crash your system, cause instability or cause data loss, that it should be used only in a controlled environment, and that you are responsible for any damage caused by running it. A fuzzing harness that calls into the kernel with arbitrary arguments has no way to promise the machine survives, so a laptop with your work on it is the wrong host even if the crash is unlikely. The second wrong choice is expecting coverage of modern Windows without preparation, because the blacklist shipped in the documentation reflects the calls that were known to misbehave when the tool was written, and the tables grow with every Windows release. The third is treating it as a general vulnerability scanner, since it does not model the arguments, so it finds crashes and stability problems rather than logic flaws, and a tool that a kernel vendor has to analyse crash by crash is a research instrument rather than a product.
Editorial conclusion
Kernel and driver researchers who need to find crashes in the Windows syscall layer, and who have a spare Windows 10 or 11 machine they are willing to lose, are the people NtCall64 is for, and the list of bugs it has already turned up in win32k and ntoskrnl is the evidence that it works. It is the wrong tool for a production machine, a shared workstation, or anyone who needs the system to stay up, because the tool warns in terms that it may crash the system, cause instability or cause data loss, and because fuzzing a syscall table requires the crash dump configuration the documentation asks you to set up first. Check three things before you run it: that your platform toolset matches your Visual Studio version, since the documentation maps v141 through v145 to VS 2017 through 2026, that the Windows SDK is at least 8.1, and that your badcalls.ini covers the services you know will misbehave, since the default run touches every entry in the ntoskrnl table. The licence is BSD-2-Clause, the newest release is v2.1.0 from 2026-09-12, and the project credits the original NtCall by Peter Kosyh from 2001.
Frequently asked questions
What does NtCall64 actually fuzz?
Windows NT system calls. With no parameters it fuzzes all the ntoskrnl services in the KiServiceTable, and the -win32k switch targets the win32k graphical subsystem service table instead, the Shadow SSDT.
How do I stop NtCall64 from calling the services that will hang my machine?
You add service names, case-sensitively, to the ntos or win32k section of the badcalls.ini configuration file. The example in the documentation lists entries such as NtDelayExecution, NtShutdownSystem and NtWaitForSingleObject under ntos.
What do the NtCall64 command line switches control?
-win32k selects the win32k table, -log enables parameter logging, -o sets the output file or COM port, -call fuzzes a single syscall by ID and ignores blacklists, -pc sets the number of passes per syscall, -wt sets the thread wait timeout, -sc sets the starting table index, -h enables heuristics, and -s attempts to run from the LocalSystem account.
What do I need to build NtCall64?
Microsoft Visual Studio 2017 or later, with the platform toolset set to match your Visual Studio version, v141 for 2017, v142 for 2019, v143 for 2022 and v145 for 2026. The target platform version should be 10 for v141 and above, and the minimum required Windows SDK version is 8.1.
Is NtCall64 based on an older tool?
Yes. It is based on the original NtCall by Peter Kosyh from 2001, and the project credits the original work separately. The stated purpose is to port and extend that functionality for x64 Windows.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/hfiref0x-ntcall64)Was this useful?