Add SysWhispers3 to repo as non-submodule

This commit is contained in:
tdeerenberg
2025-04-08 16:53:12 +02:00
parent b09acac11d
commit 47adf61229
7 changed files with 18156 additions and 0 deletions

7
SysWhispers3/.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
.idea
!data/*
!example-output/*
__pycache__
*.asm
*.c
*.h

201
SysWhispers3/LICENSE Normal file
View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2019 Jackson T.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

252
SysWhispers3/README.md Normal file
View File

@ -0,0 +1,252 @@
# SysWhispers3
SysWhispers helps with evasion by generating header/ASM files implants can use to make direct system calls.
## Official Discord Channel
Come hang out on Discord!
[![Inceptor Server](https://discordapp.com/api/guilds/1155753953108164628/widget.png?style=banner3)](https://discord.gg/f6w6dwZq)
### Why on earth didn't I create a PR to SysWhispers2?
The reason for SysWhispers3 to be a standalone version are many, but the most important are:
* SysWhispers3 is the de-facto "fork" used by [Inceptor][1], and implements some utils class which are not relevant to the
original version of the tool.
* SysWhispers2 is moving towards supporting NASM compilation (for gcc/mingw), while this version is specifically designed and
tested to support MSVC (because [Inceptor][1] will stay a Windows-only framework for the near future).
* SysWhispers3 contains partially implemented features (such as egg-hunting) which would not be sensible to include
in the original version of the tool.
## Differences with SysWhispers2
The usage is pretty similar to [SysWhispers2](https://github.com/jthuraisamy/SysWhispers2), with the following exceptions:
* It also supports x86/WoW64
* It supports syscalls instruction replacement with an EGG (to be dynamically replaced)
* It supports direct jumps to syscalls in x86/x64 mode (in WOW64 it's almost standard)
* It supports direct jumps to random syscalls (borrowing [@ElephantSeal's idea](https://twitter.com/ElephantSe4l/status/1488464546746540042))
A better explanation of these features are better outlined i the blog post [SysWhispers is dead, long live SysWhispers!][2]
## Introduction
Security products, such as AVs and EDRs, usually place hooks in user-mode API functions to analyse a program execution
flow, in order to detect potentially malicious activities.
SysWhispers2 is a tool designed to generate header/ASM pairs for any system call in the core kernel image
(`ntoskrnl.exe`), which can then be integrated and called directly from C/C++ code, evading user-lands hooks.
The tool, however, generates some patters which can be included in signatures, or behaviour which can be detected
at runtime.
SysWhispers3 is built on top of SysWhispers2, and integrates some helpful features to bypass these forms of detection.
## Installation
```
C:\> git clone https://github.com/klezVirus/SysWhispers3.git
C:\> cd SysWhispers3
C:\> python .\syswhispers.py --help
```
## Usage and Examples
The help shows all the available commands and features of the tool:
```
C:\>python syswhispers.py -h
usage: syswhispers.py [-h] [-p PRESET] [-a {x86,x64}] [-m {embedded,egg_hunter,jumper,jumper_randomized}] [-f FUNCTIONS] -o OUT_FILE [--int2eh] [--wow64] [-v] [-d]
SysWhispers3 - SysWhispers on steroids
optional arguments:
-h, --help show this help message and exit
-p PRESET, --preset PRESET
Preset ("all", "common")
-a {x86,x64}, --arch {x86,x64}
Architecture
-c {msvc,mingw,all}, --compiler {msvc,mingw,all}
Compiler
-m {embedded,egg_hunter,jumper,jumper_randomized}, --method {embedded,egg_hunter,jumper,jumper_randomized}
Syscall recovery method
-f FUNCTIONS, --functions FUNCTIONS
Comma-separated functions
-o OUT_FILE, --out-file OUT_FILE
Output basename (w/o extension)
--int2eh Use the old `int 2eh` instruction in place of `syscall`
--wow64 Use Wow64 to run x86 on x64 (only usable with x86 architecture)
-v, --verbose Enable debug output
-d, --debug Enable syscall debug (insert software breakpoint)
```
### Command Lines
#### Standard SysWhispers, embedded system calls (x64)
```powershell
# Export all functions with compatibility for all supported Windows versions (see example-output/).
py .\syswhispers.py --preset all -o syscalls_all
# Export just the common functions (see below for list).
py .\syswhispers.py --preset common -o syscalls_common
# Export NtProtectVirtualMemory and NtWriteVirtualMemory with compatibility for all versions.
py .\syswhispers.py --functions NtProtectVirtualMemory,NtWriteVirtualMemory -o syscalls_mem
```
#### SysWhispers3-only samples
```powershell
# Normal SysWhispers, 32-bits mode
py .\syswhispers.py --preset all -o syscalls_all -m jumper --arch x86
# Normal SysWhispers, using WOW64 in 32-bits mode (only specific functions)
py .\syswhispers.py --functions NtProtectVirtualMemory,NtWriteVirtualMemory -o syscalls_mem --arch x86 --wow64
# Egg-Hunting SysWhispers, to bypass the "mark of the sycall" (common function)
py .\syswhispers.py --preset common -o syscalls_common -m egg_hunter
# Jumping/Jumping Randomized SysWhispers, to bypass dynamic RIP validation (all functions) using MinGW as the compiler
py .\syswhispers.py --preset all -o syscalls_all -m jumper -c mingw
```
### Script Output
```
PS C:\Projects\SysWhispers2> py .\syswhispers.py --preset common --out-file temp\syscalls_common -v
. ,--.
,-. . . ,-. . , , |-. o ,-. ,-. ,-. ,-. ,-. __/
`-. | | `-. |/|/ | | | `-. | | |-' | `-. . \
`-' `-| `-' ' ' ' ' ' `-' |-' `-' ' `-' '''
/| | @Jackson_T
`-' ' @modexpblog, 2021
Edits by @klezVirus, 2022
SysWhispers3: Why call the kernel when you can whisper?
Common functions selected.
Complete! Files written to:
temp\syscalls_common.h
temp\syscalls_common.c
temp\syscalls_common_.asm
Press a key to continue...
```
## Importing into Visual Studio
1. Copy the generated H/C/ASM files into the project folder.
2. In Visual Studio, go to *Project**Build Customizations...* and enable MASM.
3. In the *Solution Explorer*, add the .h and .c/.asm files to the project as header and source files, respectively.
4. Go to the properties of the ASM file, and set the *Item Type* to *Microsoft Macro Assembler*.
## Compiling outside of Visual Studio
### Windows
Makefile for 64 bits:
`Makefile.msvc`
```
OPTIONS = -Zp8 -c -nologo -Gy -Os -O1 -GR- -EHa -Oi -GS-
LIBS = libvcruntime.lib libcmt.lib ucrt.lib kernel32.lib
program:
ML64 /c syscalls-asm.x64.asm /link /NODEFAULTLIB /RELEASE /MACHINE:X64
cl.exe $(OPTIONS) syscalls.c program.c
link.exe /OUT:program.x64.exe -nologo $(LIBS) /MACHINE:X64 -subsystem:console -nodefaultlib syscalls-asm.x64.obj syscalls.obj program.obj
```
Makefile for 32 bits:
`Makefile.msvc`
```
OPTIONS = -Zp8 -c -nologo -Gy -Os -O1 -GR- -EHa -Oi -GS-
LIBS = libvcruntime.lib libcmt.lib ucrt.lib kernel32.lib
program:
ML /c syscalls-asm.x86.asm /link /NODEFAULTLIB /RELEASE /MACHINE:X86
cl.exe $(OPTIONS) syscalls.c program.c
link.exe /OUT:program.x86.exe -nologo $(LIBS) /MACHINE:X86 -subsystem:console -nodefaultlib syscalls-asm.x86.obj syscalls.obj program.obj
```
Compile with nmake:
```
nmake -f Makefile.msvc
```
### Linux
Makefile for both 64 and 32 bits:
`Makefile.mingw`
```
CC_x64 := x86_64-w64-mingw32-gcc
CC_x86 := i686-w64-mingw32-gcc
OPTIONS := -masm=intel -Wall
program:
$(CC_x64) syscalls.c program.c -o program.x64.exe $(OPTIONS)
$(CC_x86) syscalls.c program.c -o program.x86.exe $(OPTIONS)
```
Compile with make:
```
make -f Makefile.mingw
```
## Caveats and Limitations
- The Egg-Hunter functionality is not implemented within this tool, it is in [Inceptor][1].
- System calls from the graphical subsystem (`win32k.sys`) are not supported.
- Tested on Visual Studio 2019/2022 with Windows 10 SDK.
- Support for NASM is not guaranteed.
- Support for GCC and MinGW is not guaranteed.
## Troubleshooting
#### From SysWhispers2
- Type redefinitions errors: a project may not compile if typedefs in `syscalls.h` have already been defined.
- Ensure that only required functions are included (i.e. `--preset all` is rarely necessary).
- If a typedef is already defined in another used header, then it could be removed from `syscalls.h`.
#### New
- With `--verbose`, it is possible to enable troubleshooting output during code generation.
- With `--debug`, the tool will insert a software breakpoint in the syscall stub, to ease the debugging in WinDbg.
- If you get a `error A2084:constant value too large` during compilation, regenerates the stubs.
## Credits
#### SysWhispers2
Developed by [@Jackson_T](https://twitter.com/Jackson_T) and [@modexpblog](https://twitter.com/modexpblog),
but builds upon the work of many others:
- [@FoxHex0ne](https://twitter.com/FoxHex0ne) for cataloguing many function prototypes and typedefs in a machine-readable format.
- [@PetrBenes](https://twitter.com/PetrBenes), [NTInternals.net team](https://undocumented.ntinternals.net/), and [MSDN](https://docs.microsoft.com/en-us/windows/) for additional prototypes and typedefs.
- [@Cn33liz](https://twitter.com/Cneelis) for the initial [Dumpert](https://github.com/outflanknl/Dumpert) POC implementation.
#### SysWhispers2 (x86/WOW64)
- [@rooster](https://github.com/mai1zhi2) for creating a sample x86/WOW64 compatible fork.
#### Others
- [@ElephantSe4l](https://mobile.twitter.com/elephantse4l) for the idea about randomizing the jumps to the syscalls.
- [@S4ntiagoP](https://twitter.com/s4ntiago_p) for the incredible work on [nanodump](https://github.com/helpsystems/nanodump), which gave me tons of ideas.
## Licence
As the original, this project is also licensed under the Apache License 2.0.
[1]: https://github.com/klezVirus/inceptor
[2]: https://klezvirus.github.io/RedTeaming/AV_Evasion/NoSysWhisper/

0
SysWhispers3/__init__.py Normal file
View File

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,503 @@
[
{
"identifiers": ["MEM_EXTENDED_PARAMETER_TYPE", "PMEM_EXTENDED_PARAMETER_TYPE"],
"dependencies": [],
"definition": "typedef enum _MEM_EXTENDED_PARAMETER_TYPE\n{\n\tMemExtendedParameterInvalidType,\n\tMemExtendedParameterAddressRequirements,\n\tMemExtendedParameterNumaNode,\n\tMemExtendedParameterPartitionHandle,\n\tMemExtendedParameterUserPhysicalHandle,\n\tMemExtendedParameterAttributeFlags,\n\tMemExtendedParameterMax\n} MEM_EXTENDED_PARAMETER_TYPE, *PMEM_EXTENDED_PARAMETER_TYPE;"
},
{
"identifiers": ["IO_STATUS_BLOCK", "PIO_STATUS_BLOCK"],
"dependencies": [],
"definition": "typedef struct _IO_STATUS_BLOCK\n{\n\tunion\n\t{\n\t\tNTSTATUS Status;\n\t\tVOID* Pointer;\n\t};\n\tULONG_PTR Information;\n} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;"
},
{
"identifiers": ["KEY_VALUE_ENTRY", "PKEY_VALUE_ENTRY"],
"dependencies": ["PUNICODE_STRING"],
"definition": "typedef struct _KEY_VALUE_ENTRY\n{\n\tPUNICODE_STRING ValueName;\n\tULONG DataLength;\n\tULONG DataOffset;\n\tULONG Type;\n} KEY_VALUE_ENTRY, *PKEY_VALUE_ENTRY;"
},
{
"identifiers": ["KEY_SET_INFORMATION_CLASS", "PKEY_SET_INFORMATION_CLASS"],
"dependencies": [],
"definition": "typedef enum _KEY_SET_INFORMATION_CLASS\n{\n\tKeyWriteTimeInformation,\n\tKeyWow64FlagsInformation,\n\tKeyControlFlagsInformation,\n\tKeySetVirtualizationInformation,\n\tKeySetDebugInformation,\n\tKeySetHandleTagsInformation,\n\tMaxKeySetInfoClass // MaxKeySetInfoClass should always be the last enum.\n} KEY_SET_INFORMATION_CLASS, *PKEY_SET_INFORMATION_CLASS;"
},
{
"identifiers": ["SYSTEM_HANDLE", "PSYSTEM_HANDLE"],
"dependencies": [],
"definition": "typedef struct _SYSTEM_HANDLE\n{\n\tULONG ProcessId;\n\tBYTE ObjectTypeNumber;\n\tBYTE Flags;\n\tUSHORT Handle;\n\tPVOID Object;\n\tACCESS_MASK GrantedAccess;\n} SYSTEM_HANDLE, *PSYSTEM_HANDLE;"
},
{
"identifiers": ["SYSTEM_HANDLE_INFORMATION", "PSYSTEM_HANDLE_INFORMATION"],
"dependencies": ["SYSTEM_HANDLE"],
"definition": "typedef struct _SYSTEM_HANDLE_INFORMATION\n{\n\tULONG HandleCount;\n\tSYSTEM_HANDLE Handles[1];\n} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;"
},
{
"identifiers": ["SYSTEM_INFORMATION_CLASS", "PSYSTEM_INFORMATION_CLASS"],
"dependencies": ["SYSTEM_HANDLE_INFORMATION"],
"definition": "typedef enum _SYSTEM_INFORMATION_CLASS\n{\n\tSystemBasicInformation = 0,\n\tSystemPerformanceInformation = 2,\n\tSystemTimeOfDayInformation = 3,\n\tSystemProcessInformation = 5,\n\tSystemProcessorPerformanceInformation = 8,\n\tSystemHandleInformation = 16,\n\tSystemInterruptInformation = 23,\n\tSystemExceptionInformation = 33,\n\tSystemRegistryQuotaInformation = 37,\n\tSystemLookasideInformation = 45,\n\tSystemCodeIntegrityInformation = 103,\n\tSystemPolicyInformation = 134,\n} SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS;"
},
{
"identifiers": ["PROCESSINFOCLASS", "PPROCESSINFOCLASS"],
"dependencies": [],
"definition": "typedef enum _PROCESSINFOCLASS\n{\n\tProcessBasicInformation = 0,\n\tProcessDebugPort = 7,\n\tProcessWow64Information = 26,\n\tProcessImageFileName = 27,\n\tProcessBreakOnTermination = 29\n} PROCESSINFOCLASS, *PPROCESSINFOCLASS;"
},
{
"identifiers": ["MEMORY_RANGE_ENTRY", "PMEMORY_RANGE_ENTRY"],
"dependencies": [],
"definition": "typedef struct _MEMORY_RANGE_ENTRY\n{\n\tPVOID VirtualAddress;\n\tSIZE_T NumberOfBytes;\n} MEMORY_RANGE_ENTRY, *PMEMORY_RANGE_ENTRY;"
},
{
"identifiers": ["T2_SET_PARAMETERS", "PT2_SET_PARAMETERS"],
"dependencies": [],
"definition": "typedef struct _T2_SET_PARAMETERS_V0\n{\n\tULONG Version;\n\tULONG Reserved;\n\tLONGLONG NoWakeTolerance;\n} T2_SET_PARAMETERS, *PT2_SET_PARAMETERS;"
},
{
"identifiers": ["FILE_PATH", "PFILE_PATH"],
"dependencies": [],
"definition": "typedef struct _FILE_PATH\n{\n\tULONG Version;\n\tULONG Length;\n\tULONG Type;\n\tCHAR FilePath[1];\n} FILE_PATH, *PFILE_PATH;"
},
{
"identifiers": ["FILE_USER_QUOTA_INFORMATION", "PFILE_USER_QUOTA_INFORMATION"],
"dependencies": [],
"definition": "typedef struct _FILE_USER_QUOTA_INFORMATION\n{\n\tULONG NextEntryOffset;\n\tULONG SidLength;\n\tLARGE_INTEGER ChangeTime;\n\tLARGE_INTEGER QuotaUsed;\n\tLARGE_INTEGER QuotaThreshold;\n\tLARGE_INTEGER QuotaLimit;\n\tSID Sid[1];\n} FILE_USER_QUOTA_INFORMATION, *PFILE_USER_QUOTA_INFORMATION;"
},
{
"identifiers": ["FILE_QUOTA_LIST_INFORMATION", "PFILE_QUOTA_LIST_INFORMATION"],
"dependencies": [],
"definition": "typedef struct _FILE_QUOTA_LIST_INFORMATION\n{\n\tULONG NextEntryOffset;\n\tULONG SidLength;\n\tSID Sid[1];\n} FILE_QUOTA_LIST_INFORMATION, *PFILE_QUOTA_LIST_INFORMATION;"
},
{
"identifiers": ["FILE_NETWORK_OPEN_INFORMATION", "PFILE_NETWORK_OPEN_INFORMATION"],
"dependencies": [],
"definition": "typedef struct _FILE_NETWORK_OPEN_INFORMATION\n{\n\tLARGE_INTEGER CreationTime;\n\tLARGE_INTEGER LastAccessTime;\n\tLARGE_INTEGER LastWriteTime;\n\tLARGE_INTEGER ChangeTime;\n\tLARGE_INTEGER AllocationSize;\n\tLARGE_INTEGER EndOfFile;\n\tULONG FileAttributes;\n\tULONG Unknown;\n} FILE_NETWORK_OPEN_INFORMATION, *PFILE_NETWORK_OPEN_INFORMATION;"
},
{
"identifiers": ["FILTER_BOOT_OPTION_OPERATION", "PFILTER_BOOT_OPTION_OPERATION"],
"dependencies": [],
"definition": "typedef enum _FILTER_BOOT_OPTION_OPERATION\n{\n\tFilterBootOptionOperationOpenSystemStore,\n\tFilterBootOptionOperationSetElement,\n\tFilterBootOptionOperationDeleteElement,\n\tFilterBootOptionOperationMax\n} FILTER_BOOT_OPTION_OPERATION, *PFILTER_BOOT_OPTION_OPERATION;"
},
{
"identifiers": ["EVENT_TYPE", "PEVENT_TYPE"],
"dependencies": [],
"definition": "typedef enum _EVENT_TYPE\n{\n\tNotificationEvent = 0,\n\tSynchronizationEvent = 1,\n} EVENT_TYPE, *PEVENT_TYPE;"
},
{
"identifiers": ["FILE_FULL_EA_INFORMATION", "PFILE_FULL_EA_INFORMATION"],
"dependencies": [],
"definition": "typedef struct _FILE_FULL_EA_INFORMATION\n{\n\tULONG NextEntryOffset;\n\tUCHAR Flags;\n\tUCHAR EaNameLength;\n\tUSHORT EaValueLength;\n\tCHAR EaName[1];\n} FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION;"
},
{
"identifiers": ["FILE_GET_EA_INFORMATION", "PFILE_GET_EA_INFORMATION"],
"dependencies": [],
"definition": "typedef struct _FILE_GET_EA_INFORMATION\n{\n\tULONG NextEntryOffset;\n\tBYTE EaNameLength;\n\tCHAR EaName[1];\n} FILE_GET_EA_INFORMATION, *PFILE_GET_EA_INFORMATION;"
},
{
"identifiers": ["BOOT_OPTIONS", "PBOOT_OPTIONS"],
"dependencies": [],
"definition": "typedef struct _BOOT_OPTIONS\n{\n\tULONG Version;\n\tULONG Length;\n\tULONG Timeout;\n\tULONG CurrentBootEntryId;\n\tULONG NextBootEntryId;\n\tWCHAR HeadlessRedirection[1];\n} BOOT_OPTIONS, *PBOOT_OPTIONS;"
},
{
"identifiers": ["WNF_CHANGE_STAMP", "PWNF_CHANGE_STAMP"],
"dependencies": [],
"definition": "typedef ULONG WNF_CHANGE_STAMP, *PWNF_CHANGE_STAMP;"
},
{
"identifiers": ["WNF_DATA_SCOPE", "PWNF_DATA_SCOPE"],
"dependencies": [],
"definition": "typedef enum _WNF_DATA_SCOPE\n{\n\tWnfDataScopeSystem = 0,\n\tWnfDataScopeSession = 1,\n\tWnfDataScopeUser = 2,\n\tWnfDataScopeProcess = 3,\n\tWnfDataScopeMachine = 4\n} WNF_DATA_SCOPE, *PWNF_DATA_SCOPE;"
},
{
"identifiers": ["WNF_STATE_NAME_LIFETIME", "PWNF_STATE_NAME_LIFETIME"],
"dependencies": [],
"definition": "typedef enum _WNF_STATE_NAME_LIFETIME\n{\n\tWnfWellKnownStateName = 0,\n\tWnfPermanentStateName = 1,\n\tWnfPersistentStateName = 2,\n\tWnfTemporaryStateName = 3\n} WNF_STATE_NAME_LIFETIME, *PWNF_STATE_NAME_LIFETIME;"
},
{
"identifiers": ["VIRTUAL_MEMORY_INFORMATION_CLASS", "PVIRTUAL_MEMORY_INFORMATION_CLASS"],
"dependencies": [],
"definition": "typedef enum _VIRTUAL_MEMORY_INFORMATION_CLASS\n{\n\tVmPrefetchInformation,\n\tVmPagePriorityInformation,\n\tVmCfgCallTargetInformation\n} VIRTUAL_MEMORY_INFORMATION_CLASS, *PVIRTUAL_MEMORY_INFORMATION_CLASS;"
},
{
"identifiers": ["IO_SESSION_EVENT", "PIO_SESSION_EVENT"],
"dependencies": [],
"definition": "typedef enum _IO_SESSION_EVENT\n{\n\tIoSessionEventIgnore,\n\tIoSessionEventCreated,\n\tIoSessionEventTerminated,\n\tIoSessionEventConnected,\n\tIoSessionEventDisconnected,\n\tIoSessionEventLogon,\n\tIoSessionEventLogoff,\n\tIoSessionEventMax\n} IO_SESSION_EVENT, *PIO_SESSION_EVENT;"
},
{
"identifiers": ["PORT_INFORMATION_CLASS", "PPORT_INFORMATION_CLASS"],
"dependencies": [],
"definition": "typedef enum _PORT_INFORMATION_CLASS\n{\n\tPortBasicInformation,\n#if DEVL\n\tPortDumpInformation\n#endif\n} PORT_INFORMATION_CLASS, *PPORT_INFORMATION_CLASS;"
},
{
"identifiers": ["PLUGPLAY_CONTROL_CLASS", "PPLUGPLAY_CONTROL_CLASS"],
"dependencies": [],
"definition": "typedef enum _PLUGPLAY_CONTROL_CLASS\n{\n\tPlugPlayControlEnumerateDevice,\n\tPlugPlayControlRegisterNewDevice,\n\tPlugPlayControlDeregisterDevice,\n\tPlugPlayControlInitializeDevice,\n\tPlugPlayControlStartDevice,\n\tPlugPlayControlUnlockDevice,\n\tPlugPlayControlQueryAndRemoveDevice,\n\tPlugPlayControlUserResponse,\n\tPlugPlayControlGenerateLegacyDevice,\n\tPlugPlayControlGetInterfaceDeviceList,\n\tPlugPlayControlProperty,\n\tPlugPlayControlDeviceClassAssociation,\n\tPlugPlayControlGetRelatedDevice,\n\tPlugPlayControlGetInterfaceDeviceAlias,\n\tPlugPlayControlDeviceStatus,\n\tPlugPlayControlGetDeviceDepth,\n\tPlugPlayControlQueryDeviceRelations,\n\tPlugPlayControlTargetDeviceRelation,\n\tPlugPlayControlQueryConflictList,\n\tPlugPlayControlRetrieveDock,\n\tPlugPlayControlResetDevice,\n\tPlugPlayControlHaltDevice,\n\tPlugPlayControlGetBlockedDriverList,\n\tMaxPlugPlayControl\n} PLUGPLAY_CONTROL_CLASS, *PPLUGPLAY_CONTROL_CLASS;"
},
{
"identifiers": ["IO_COMPLETION_INFORMATION_CLASS", "PIO_COMPLETION_INFORMATION_CLASS"],
"dependencies": [],
"definition": "typedef enum _IO_COMPLETION_INFORMATION_CLASS\n{\n\tIoCompletionBasicInformation\n} IO_COMPLETION_INFORMATION_CLASS, *PIO_COMPLETION_INFORMATION_CLASS;"
},
{
"identifiers": ["SECTION_INHERIT", "PSECTION_INHERIT"],
"dependencies": [],
"definition": "typedef enum _SECTION_INHERIT\n{\n\tViewShare = 1,\n\tViewUnmap = 2\n} SECTION_INHERIT, *PSECTION_INHERIT;"
},
{
"identifiers": ["PS_ATTRIBUTE", "PPS_ATTRIBUTE"],
"dependencies": [],
"definition": "typedef struct _PS_ATTRIBUTE\n{\n\tULONG Attribute;\n\tSIZE_T Size;\n\tunion\n\t{\n\t\tULONG Value;\n\t\tPVOID ValuePtr;\n\t} u1;\n\tPSIZE_T ReturnLength;\n} PS_ATTRIBUTE, *PPS_ATTRIBUTE;"
},
{
"identifiers": ["DEBUGOBJECTINFOCLASS", "PDEBUGOBJECTINFOCLASS"],
"dependencies": [],
"definition": "typedef enum _DEBUGOBJECTINFOCLASS\n{\n\tDebugObjectFlags = 1,\n\tMaxDebugObjectInfoClass\n} DEBUGOBJECTINFOCLASS, *PDEBUGOBJECTINFOCLASS;"
},
{
"identifiers": ["SEMAPHORE_INFORMATION_CLASS", "PSEMAPHORE_INFORMATION_CLASS"],
"dependencies": [],
"definition": "typedef enum _SEMAPHORE_INFORMATION_CLASS\n{\n\tSemaphoreBasicInformation\n} SEMAPHORE_INFORMATION_CLASS, *PSEMAPHORE_INFORMATION_CLASS;"
},
{
"identifiers": ["PS_ATTRIBUTE_LIST", "PPS_ATTRIBUTE_LIST"],
"dependencies": ["PS_ATTRIBUTE"],
"definition": "typedef struct _PS_ATTRIBUTE_LIST\n{\n\tSIZE_T TotalLength;\n\tPS_ATTRIBUTE Attributes[1];\n} PS_ATTRIBUTE_LIST, *PPS_ATTRIBUTE_LIST;"
},
{
"identifiers": ["VDMSERVICECLASS"],
"dependencies": [],
"definition": "typedef enum _VDMSERVICECLASS\n{\n\tVdmStartExecution,\n\tVdmQueueInterrupt,\n\tVdmDelayInterrupt,\n\tVdmInitialize,\n\tVdmFeatures,\n\tVdmSetInt21Handler,\n\tVdmQueryDir,\n\tVdmPrinterDirectIoOpen,\n\tVdmPrinterDirectIoClose,\n\tVdmPrinterInitialize,\n\tVdmSetLdtEntries,\n\tVdmSetProcessLdtInfo,\n\tVdmAdlibEmulation,\n\tVdmPMCliControl,\n\tVdmQueryVdmProcess\n} VDMSERVICECLASS, *PVDMSERVICECLASS;"
},
{
"identifiers": ["PS_CREATE_STATE", "PPS_CREATE_STATE"],
"dependencies": [],
"definition": "typedef enum _PS_CREATE_STATE\n{\n\tPsCreateInitialState,\n\tPsCreateFailOnFileOpen,\n\tPsCreateFailOnSectionCreate,\n\tPsCreateFailExeFormat,\n\tPsCreateFailMachineMismatch,\n\tPsCreateFailExeName,\n\tPsCreateSuccess,\n\tPsCreateMaximumStates\n} PS_CREATE_STATE, *PPS_CREATE_STATE;"
},
{
"identifiers": ["PS_CREATE_INFO", "PPS_CREATE_INFO"],
"dependencies": ["PS_CREATE_STATE"],
"definition": "typedef struct _PS_CREATE_INFO\n{\n\tSIZE_T Size;\n\tPS_CREATE_STATE State;\n\tunion\n\t{\n\t\t// PsCreateInitialState\n\t\tstruct {\n\t\t\tunion {\n\t\t\t\tULONG InitFlags;\n\t\t\t\tstruct {\n\t\t\t\t\tUCHAR WriteOutputOnExit : 1;\n\t\t\t\t\tUCHAR DetectManifest : 1;\n\t\t\t\t\tUCHAR IFEOSkipDebugger : 1;\n\t\t\t\t\tUCHAR IFEODoNotPropagateKeyState : 1;\n\t\t\t\t\tUCHAR SpareBits1 : 4;\n\t\t\t\t\tUCHAR SpareBits2 : 8;\n\t\t\t\t\tUSHORT ProhibitedImageCharacteristics : 16;\n\t\t\t\t};\n\t\t\t};\n\t\t\tACCESS_MASK AdditionalFileAccess;\n\t\t} InitState;\n\t\t// PsCreateFailOnSectionCreate\n\t\tstruct {\n\t\t\tHANDLE FileHandle;\n\t\t} FailSection;\n\t\t// PsCreateFailExeFormat\n\t\tstruct {\n\t\t\tUSHORT DllCharacteristics;\n\t\t} ExeFormat;\n\t\t// PsCreateFailExeName\n\t\tstruct {\n\t\t\tHANDLE IFEOKey;\n\t\t} ExeName;\n\t\t// PsCreateSuccess\n\t\tstruct {\n\t\t\tunion {\n\t\t\t\tULONG OutputFlags;\n\t\t\t\tstruct {\n\t\t\t\t\tUCHAR ProtectedProcess : 1;\n\t\t\t\t\tUCHAR AddressSpaceOverride : 1;\n\t\t\t\t\tUCHAR DevOverrideEnabled : 1; // from Image File Execution Options\n\t\t\t\t\tUCHAR ManifestDetected : 1;\n\t\t\t\t\tUCHAR ProtectedProcessLight : 1;\n\t\t\t\t\tUCHAR SpareBits1 : 3;\n\t\t\t\t\tUCHAR SpareBits2 : 8;\n\t\t\t\t\tUSHORT SpareBits3 : 16;\n\t\t\t\t};\n\t\t\t};\n\t\t\tHANDLE FileHandle;\n\t\t\tHANDLE SectionHandle;\n\t\t\tULONGLONG UserProcessParametersNative;\n\t\t\tULONG UserProcessParametersWow64;\n\t\t\tULONG CurrentParameterFlags;\n\t\t\tULONGLONG PebAddressNative;\n\t\t\tULONG PebAddressWow64;\n\t\t\tULONGLONG ManifestAddress;\n\t\t\tULONG ManifestSize;\n\t\t} SuccessState;\n\t};\n} PS_CREATE_INFO, *PPS_CREATE_INFO;"
},
{
"identifiers": ["MEMORY_INFORMATION_CLASS", "PMEMORY_INFORMATION_CLASS"],
"dependencies": [],
"definition": "typedef enum _MEMORY_INFORMATION_CLASS\n{\n\tMemoryBasicInformation,\n\tMemoryWorkingSetInformation,\n\tMemoryMappedFilenameInformation,\n\tMemoryRegionInformation,\n\tMemoryWorkingSetExInformation,\n\tMemorySharedCommitInformation,\n\tMemoryImageInformation,\n\tMemoryRegionInformationEx,\n\tMemoryPrivilegedBasicInformation,\n\tMemoryEnclaveImageInformation,\n\tMemoryBasicInformationCapped\n} MEMORY_INFORMATION_CLASS, *PMEMORY_INFORMATION_CLASS;"
},
{
"identifiers": ["MEMORY_RESERVE_TYPE", "PMEMORY_RESERVE_TYPE"],
"dependencies": [],
"definition": "typedef enum _MEMORY_RESERVE_TYPE\n{\n\tMemoryReserveUserApc,\n\tMemoryReserveIoCompletion,\n\tMemoryReserveTypeMax\n} MEMORY_RESERVE_TYPE, *PMEMORY_RESERVE_TYPE;"
},
{
"identifiers": ["ALPC_PORT_INFORMATION_CLASS", "PALPC_PORT_INFORMATION_CLASS"],
"dependencies": [],
"definition": "typedef enum _ALPC_PORT_INFORMATION_CLASS\n{\n\tAlpcBasicInformation,\n\tAlpcPortInformation,\n\tAlpcAssociateCompletionPortInformation,\n\tAlpcConnectedSIDInformation,\n\tAlpcServerInformation,\n\tAlpcMessageZoneInformation,\n\tAlpcRegisterCompletionListInformation,\n\tAlpcUnregisterCompletionListInformation,\n\tAlpcAdjustCompletionListConcurrencyCountInformation,\n\tAlpcRegisterCallbackInformation,\n\tAlpcCompletionListRundownInformation\n} ALPC_PORT_INFORMATION_CLASS, *PALPC_PORT_INFORMATION_CLASS;"
},
{
"identifiers": ["ALPC_CONTEXT_ATTR", "PALPC_CONTEXT_ATTR"],
"dependencies": [],
"definition": "typedef struct _ALPC_CONTEXT_ATTR\n{\n\tPVOID PortContext;\n\tPVOID MessageContext;\n\tULONG SequenceNumber;\n\tULONG MessageID;\n\tULONG CallbackID;\n} ALPC_CONTEXT_ATTR, *PALPC_CONTEXT_ATTR;"
},
{
"identifiers": ["ALPC_DATA_VIEW_ATTR", "PALPC_DATA_VIEW_ATTR"],
"dependencies": [],
"definition": "typedef struct _ALPC_DATA_VIEW_ATTR\n{\n\tULONG Flags;\n\tHANDLE SectionHandle;\n\tPVOID ViewBase;\n\tSIZE_T ViewSize;\n} ALPC_DATA_VIEW_ATTR, *PALPC_DATA_VIEW_ATTR;"
},
{
"identifiers": ["ALPC_SECURITY_ATTR", "PALPC_SECURITY_ATTR"],
"dependencies": [],
"definition": "typedef struct _ALPC_SECURITY_ATTR\n{\n\tULONG Flags;\n\tPSECURITY_QUALITY_OF_SERVICE SecurityQos;\n\tHANDLE ContextHandle;\n\tULONG Reserved1;\n\tULONG Reserved2;\n} ALPC_SECURITY_ATTR, *PALPC_SECURITY_ATTR;"
},
{
"identifiers": ["PPVOID"],
"dependencies": [],
"definition": "typedef PVOID* PPVOID;"
},
{
"identifiers": ["KPROFILE_SOURCE", "PKPROFILE_SOURCE"],
"dependencies": [],
"definition": "typedef enum _KPROFILE_SOURCE\n{\n\tProfileTime = 0,\n\tProfileAlignmentFixup = 1,\n\tProfileTotalIssues = 2,\n\tProfilePipelineDry = 3,\n\tProfileLoadInstructions = 4,\n\tProfilePipelineFrozen = 5,\n\tProfileBranchInstructions = 6,\n\tProfileTotalNonissues = 7,\n\tProfileDcacheMisses = 8,\n\tProfileIcacheMisses = 9,\n\tProfileCacheMisses = 10,\n\tProfileBranchMispredictions = 11,\n\tProfileStoreInstructions = 12,\n\tProfileFpInstructions = 13,\n\tProfileIntegerInstructions = 14,\n\tProfile2Issue = 15,\n\tProfile3Issue = 16,\n\tProfile4Issue = 17,\n\tProfileSpecialInstructions = 18,\n\tProfileTotalCycles = 19,\n\tProfileIcacheIssues = 20,\n\tProfileDcacheAccesses = 21,\n\tProfileMemoryBarrierCycles = 22,\n\tProfileLoadLinkedIssues = 23,\n\tProfileMaximum = 24,\n} KPROFILE_SOURCE, *PKPROFILE_SOURCE;"
},
{
"identifiers": ["ALPC_MESSAGE_INFORMATION_CLASS", "PALPC_MESSAGE_INFORMATION_CLASS"],
"dependencies": [],
"definition": "typedef enum _ALPC_MESSAGE_INFORMATION_CLASS\n{\n\tAlpcMessageSidInformation,\n\tAlpcMessageTokenModifiedIdInformation\n} ALPC_MESSAGE_INFORMATION_CLASS, *PALPC_MESSAGE_INFORMATION_CLASS;"
},
{
"identifiers": ["WORKERFACTORYINFOCLASS", "PWORKERFACTORYINFOCLASS"],
"dependencies": [],
"definition": "typedef enum _WORKERFACTORYINFOCLASS\n{\n\tWorkerFactoryTimeout,\n\tWorkerFactoryRetryTimeout,\n\tWorkerFactoryIdleTimeout,\n\tWorkerFactoryBindingCount,\n\tWorkerFactoryThreadMinimum,\n\tWorkerFactoryThreadMaximum,\n\tWorkerFactoryPaused,\n\tWorkerFactoryBasicInformation,\n\tWorkerFactoryAdjustThreadGoal,\n\tWorkerFactoryCallbackType,\n\tWorkerFactoryStackInformation,\n\tMaxWorkerFactoryInfoClass\n} WORKERFACTORYINFOCLASS, *PWORKERFACTORYINFOCLASS;"
},
{
"identifiers": ["MEMORY_PARTITION_INFORMATION_CLASS", "PMEMORY_PARTITION_INFORMATION_CLASS"],
"dependencies": [],
"definition": "typedef enum _MEMORY_PARTITION_INFORMATION_CLASS\n{\n\tSystemMemoryPartitionInformation,\n\tSystemMemoryPartitionMoveMemory,\n\tSystemMemoryPartitionAddPagefile,\n\tSystemMemoryPartitionCombineMemory,\n\tSystemMemoryPartitionInitialAddMemory,\n\tSystemMemoryPartitionGetMemoryEvents,\n\tSystemMemoryPartitionMax\n} MEMORY_PARTITION_INFORMATION_CLASS, *PMEMORY_PARTITION_INFORMATION_CLASS;"
},
{
"identifiers": ["MUTANT_INFORMATION_CLASS", "PMUTANT_INFORMATION_CLASS"],
"dependencies": [],
"definition": "typedef enum _MUTANT_INFORMATION_CLASS\n{\n\tMutantBasicInformation,\n\tMutantOwnerInformation\n} MUTANT_INFORMATION_CLASS, *PMUTANT_INFORMATION_CLASS;"
},
{
"identifiers": ["ATOM_INFORMATION_CLASS", "PATOM_INFORMATION_CLASS"],
"dependencies": [],
"definition": "typedef enum _ATOM_INFORMATION_CLASS\n{\n\tAtomBasicInformation,\n\tAtomTableInformation\n} ATOM_INFORMATION_CLASS, *PATOM_INFORMATION_CLASS;"
},
{
"identifiers": ["SHUTDOWN_ACTION"],
"dependencies": [],
"definition": "typedef enum _SHUTDOWN_ACTION {\n\tShutdownNoReboot,\n\tShutdownReboot,\n\tShutdownPowerOff\n} SHUTDOWN_ACTION;"
},
{
"identifiers": ["PTIMER_APC_ROUTINE"],
"dependencies": [],
"definition": "typedef VOID(CALLBACK* PTIMER_APC_ROUTINE)(\n\tIN PVOID TimerContext,\n\tIN ULONG TimerLowValue,\n\tIN LONG TimerHighValue);"
},
{
"identifiers": ["KEY_VALUE_INFORMATION_CLASS"],
"dependencies": [],
"definition": "typedef enum _KEY_VALUE_INFORMATION_CLASS {\n\tKeyValueBasicInformation = 0,\n\tKeyValueFullInformation,\n\tKeyValuePartialInformation,\n\tKeyValueFullInformationAlign64,\n\tKeyValuePartialInformationAlign64,\n\tMaxKeyValueInfoClass\n} KEY_VALUE_INFORMATION_CLASS;"
},
{
"identifiers": ["PLANGID"],
"dependencies": [],
"definition": "typedef LANGID* PLANGID;"
},
{
"identifiers": ["PLUGPLAY_EVENT_CATEGORY", "PPLUGPLAY_EVENT_CATEGORY"],
"dependencies": [],
"definition": "typedef enum _PLUGPLAY_EVENT_CATEGORY\n{\n\tHardwareProfileChangeEvent,\n\tTargetDeviceChangeEvent,\n\tDeviceClassChangeEvent,\n\tCustomDeviceEvent,\n\tDeviceInstallEvent,\n\tDeviceArrivalEvent,\n\tPowerEvent,\n\tVetoEvent,\n\tBlockedDriverEvent,\n\tInvalidIDEvent,\n\tMaxPlugEventCategory\n} PLUGPLAY_EVENT_CATEGORY, *PPLUGPLAY_EVENT_CATEGORY;"
},
{
"identifiers": ["PNP_VETO_TYPE", "PPNP_VETO_TYPE"],
"dependencies": [],
"definition": "typedef enum _PNP_VETO_TYPE\n{\n\tPNP_VetoTypeUnknown, // unspecified\n\tPNP_VetoLegacyDevice, // instance path\n\tPNP_VetoPendingClose, // instance path\n\tPNP_VetoWindowsApp, // module\n\tPNP_VetoWindowsService, // service\n\tPNP_VetoOutstandingOpen, // instance path\n\tPNP_VetoDevice, // instance path\n\tPNP_VetoDriver, // driver service name\n\tPNP_VetoIllegalDeviceRequest, // instance path\n\tPNP_VetoInsufficientPower, // unspecified\n\tPNP_VetoNonDisableable, // instance path\n\tPNP_VetoLegacyDriver, // service\n\tPNP_VetoInsufficientRights // unspecified\n} PNP_VETO_TYPE, *PPNP_VETO_TYPE;"
},
{
"identifiers": ["PLUGPLAY_EVENT_BLOCK", "PPLUGPLAY_EVENT_BLOCK"],
"dependencies": ["PLUGPLAY_EVENT_CATEGORY", "PNP_VETO_TYPE"],
"definition": "typedef struct _PLUGPLAY_EVENT_BLOCK\n{\n\tGUID EventGuid;\n\tPLUGPLAY_EVENT_CATEGORY EventCategory;\n\tPULONG Result;\n\tULONG Flags;\n\tULONG TotalSize;\n\tPVOID DeviceObject;\n\n\tunion\n\t{\n\t\tstruct\n\t\t{\n\t\t\tGUID ClassGuid;\n\t\t\tWCHAR SymbolicLinkName[1];\n\t\t} DeviceClass;\n\t\tstruct\n\t\t{\n\t\t\tWCHAR DeviceIds[1];\n\t\t} TargetDevice;\n\t\tstruct\n\t\t{\n\t\t\tWCHAR DeviceId[1];\n\t\t} InstallDevice;\n\t\tstruct\n\t\t{\n\t\t\tPVOID NotificationStructure;\n\t\t\tWCHAR DeviceIds[1];\n\t\t} CustomNotification;\n\t\tstruct\n\t\t{\n\t\t\tPVOID Notification;\n\t\t} ProfileNotification;\n\t\tstruct\n\t\t{\n\t\t\tULONG NotificationCode;\n\t\t\tULONG NotificationData;\n\t\t} PowerNotification;\n\t\tstruct\n\t\t{\n\t\t\tPNP_VETO_TYPE VetoType;\n\t\t\tWCHAR DeviceIdVetoNameBuffer[1]; // DeviceId<null>VetoName<null><null>\n\t\t} VetoNotification;\n\t\tstruct\n\t\t{\n\t\t\tGUID BlockedDriverGuid;\n\t\t} BlockedDriverNotification;\n\t\tstruct\n\t\t{\n\t\t\tWCHAR ParentId[1];\n\t\t} InvalidIDNotification;\n\t} u;\n} PLUGPLAY_EVENT_BLOCK, *PPLUGPLAY_EVENT_BLOCK;"
},
{
"identifiers": ["PIO_APC_ROUTINE"],
"dependencies": ["PIO_STATUS_BLOCK"],
"definition": "typedef VOID(NTAPI* PIO_APC_ROUTINE) (\n\tIN PVOID ApcContext,\n\tIN PIO_STATUS_BLOCK IoStatusBlock,\n\tIN ULONG Reserved);"
},
{
"identifiers": ["KNORMAL_ROUTINE"],
"dependencies": [],
"definition": "typedef VOID(KNORMAL_ROUTINE) (\n\tIN PVOID NormalContext,\n\tIN PVOID SystemArgument1,\n\tIN PVOID SystemArgument2);"
},
{
"identifiers": ["PKNORMAL_ROUTINE"],
"dependencies": ["KNORMAL_ROUTINE"],
"definition": "typedef KNORMAL_ROUTINE* PKNORMAL_ROUTINE;"
},
{
"identifiers": ["DIRECTORY_NOTIFY_INFORMATION_CLASS", "PDIRECTORY_NOTIFY_INFORMATION_CLASS"],
"dependencies": [],
"definition": "typedef enum _DIRECTORY_NOTIFY_INFORMATION_CLASS\n{\n\tDirectoryNotifyInformation = 1,\n\tDirectoryNotifyExtendedInformation = 2,\n} DIRECTORY_NOTIFY_INFORMATION_CLASS, *PDIRECTORY_NOTIFY_INFORMATION_CLASS;"
},
{
"identifiers": ["EVENT_INFORMATION_CLASS", "PEVENT_INFORMATION_CLASS"],
"dependencies": [],
"definition": "typedef enum _EVENT_INFORMATION_CLASS\n{\n\tEventBasicInformation\n} EVENT_INFORMATION_CLASS, *PEVENT_INFORMATION_CLASS;"
},
{
"identifiers": ["ALPC_MESSAGE_ATTRIBUTES", "PALPC_MESSAGE_ATTRIBUTES"],
"dependencies": [],
"definition": "typedef struct _ALPC_MESSAGE_ATTRIBUTES\n{\n\tunsigned long AllocatedAttributes;\n\tunsigned long ValidAttributes;\n} ALPC_MESSAGE_ATTRIBUTES, *PALPC_MESSAGE_ATTRIBUTES;"
},
{
"identifiers": ["ALPC_PORT_ATTRIBUTES", "PALPC_PORT_ATTRIBUTES"],
"dependencies": [],
"definition": "typedef struct _ALPC_PORT_ATTRIBUTES\n{\n\tULONG Flags;\n\tSECURITY_QUALITY_OF_SERVICE SecurityQos;\n\tSIZE_T MaxMessageLength;\n\tSIZE_T MemoryBandwidth;\n\tSIZE_T MaxPoolUsage;\n\tSIZE_T MaxSectionSize;\n\tSIZE_T MaxViewSize;\n\tSIZE_T MaxTotalSectionSize;\n\tULONG DupObjectTypes;\n#ifdef _WIN64\n\tULONG Reserved;\n#endif\n} ALPC_PORT_ATTRIBUTES, *PALPC_PORT_ATTRIBUTES;"
},
{
"identifiers": ["IO_SESSION_STATE", "PIO_SESSION_STATE"],
"dependencies": [],
"definition": "typedef enum _IO_SESSION_STATE\n{\n\tIoSessionStateCreated = 1,\n\tIoSessionStateInitialized = 2,\n\tIoSessionStateConnected = 3,\n\tIoSessionStateDisconnected = 4,\n\tIoSessionStateDisconnectedLoggedOn = 5,\n\tIoSessionStateLoggedOn = 6,\n\tIoSessionStateLoggedOff = 7,\n\tIoSessionStateTerminated = 8,\n\tIoSessionStateMax = 9,\n} IO_SESSION_STATE, *PIO_SESSION_STATE;"
},
{
"identifiers": ["WNF_STATE_NAME", "PWNF_STATE_NAME"],
"dependencies": [],
"definition": "typedef struct _WNF_STATE_NAME\n{\n\tULONG Data[2];\n} WNF_STATE_NAME, *PWNF_STATE_NAME;"
},
{
"identifiers": ["PCWNF_STATE_NAME"],
"dependencies": ["WNF_STATE_NAME"],
"definition": "typedef const WNF_STATE_NAME *PCWNF_STATE_NAME;"
},
{
"identifiers": ["WNF_TYPE_ID", "PWNF_TYPE_ID"],
"dependencies": [],
"definition": "typedef struct _WNF_TYPE_ID\n{\n\tGUID TypeId;\n} WNF_TYPE_ID, *PWNF_TYPE_ID;"
},
{
"identifiers": ["PCWNF_TYPE_ID"],
"dependencies": ["WNF_TYPE_ID"],
"definition": "typedef const WNF_TYPE_ID *PCWNF_TYPE_ID;"
},
{
"identifiers": ["WNF_DELIVERY_DESCRIPTOR", "PWNF_DELIVERY_DESCRIPTOR"],
"dependencies": ["WNF_STATE_NAME", "WNF_TYPE_ID"],
"definition": "typedef struct _WNF_DELIVERY_DESCRIPTOR\n{\n\tunsigned __int64 SubscriptionId;\n\tWNF_STATE_NAME StateName;\n\tunsigned long ChangeStamp;\n\tunsigned long StateDataSize;\n\tunsigned long EventMask;\n\tWNF_TYPE_ID TypeId;\n\tunsigned long StateDataOffset;\n} WNF_DELIVERY_DESCRIPTOR, *PWNF_DELIVERY_DESCRIPTOR;"
},
{
"identifiers": ["DEBUG_CONTROL_CODE", "PPDEBUG_CONTROL_CODE"],
"dependencies": [],
"definition": "typedef enum _DEBUG_CONTROL_CODE\n{\n\tSysDbgQueryModuleInformation = 0,\n\tSysDbgQueryTraceInformation = 1,\n\tSysDbgSetTracePoint = 2,\n\tSysDbgSetSpecialCall = 3,\n\tSysDbgClearSpecialCalls = 4,\n\tSysDbgQuerySpecialCalls = 5,\n\tSysDbgBreakPoint = 6,\n\tSysDbgQueryVersion = 7,\n\tSysDbgReadVirtual = 8,\n\tSysDbgWriteVirtual = 9,\n\tSysDbgReadPhysical = 10,\n\tSysDbgWritePhysical = 11,\n\tSysDbgReadControlSpace = 12,\n\tSysDbgWriteControlSpace = 13,\n\tSysDbgReadIoSpace = 14,\n\tSysDbgWriteIoSpace = 15,\n\tSysDbgReadMsr = 16,\n\tSysDbgWriteMsr = 17,\n\tSysDbgReadBusData = 18,\n\tSysDbgWriteBusData = 19,\n\tSysDbgCheckLowMemory = 20,\n\tSysDbgEnableKernelDebugger = 21,\n\tSysDbgDisableKernelDebugger = 22,\n\tSysDbgGetAutoKdEnable = 23,\n\tSysDbgSetAutoKdEnable = 24,\n\tSysDbgGetPrintBufferSize = 25,\n\tSysDbgSetPrintBufferSize = 26,\n\tSysDbgGetKdUmExceptionEnable = 27,\n\tSysDbgSetKdUmExceptionEnable = 28,\n\tSysDbgGetTriageDump = 29,\n\tSysDbgGetKdBlockEnable = 30,\n\tSysDbgSetKdBlockEnable = 31\n} DEBUG_CONTROL_CODE, *PDEBUG_CONTROL_CODE;"
},
{
"identifiers": ["CLIENT_ID", "PCLIENT_ID"],
"dependencies": [],
"definition": "typedef struct _CLIENT_ID\n{\n\tHANDLE UniqueProcess;\n\tHANDLE UniqueThread;\n} CLIENT_ID, *PCLIENT_ID;"
},
{
"identifiers": ["PORT_MESSAGE", "PPORT_MESSAGE"],
"dependencies": ["CLIENT_ID"],
"definition": "typedef struct _PORT_MESSAGE\n{\n\tunion\n\t{\n\t\tunion\n\t\t{\n\t\t\tstruct\n\t\t\t{\n\t\t\t\tshort DataLength;\n\t\t\t\tshort TotalLength;\n\t\t\t} s1;\n\t\t\tunsigned long Length;\n\t\t};\n\t} u1;\n\tunion\n\t{\n\t\tunion\n\t\t{\n\t\t\tstruct\n\t\t\t{\n\t\t\t\tshort Type;\n\t\t\t\tshort DataInfoOffset;\n\t\t\t} s2;\n\t\t\tunsigned long ZeroInit;\n\t\t};\n\t} u2;\n\tunion\n\t{\n\t\tCLIENT_ID ClientId;\n\t\tdouble DoNotUseThisField;\n\t};\n\tunsigned long MessageId;\n\tunion\n\t{\n\t\tunsigned __int64 ClientViewSize;\n\t\tstruct\n\t\t{\n\t\t\tunsigned long CallbackId;\n\t\t\tlong __PADDING__[1];\n\t\t};\n\t};\n} PORT_MESSAGE, *PPORT_MESSAGE;"
},
{
"identifiers": ["FILE_BASIC_INFORMATION", "PFILE_BASIC_INFORMATION"],
"dependencies": [],
"definition": "typedef struct _FILE_BASIC_INFORMATION\n{\n\tLARGE_INTEGER CreationTime;\n\tLARGE_INTEGER LastAccessTime;\n\tLARGE_INTEGER LastWriteTime;\n\tLARGE_INTEGER ChangeTime;\n\tULONG FileAttributes;\n} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;"
},
{
"identifiers": ["PORT_SECTION_READ", "PPORT_SECTION_READ"],
"dependencies": [],
"definition": "typedef struct _PORT_SECTION_READ\n{\n\tULONG Length;\n\tULONG ViewSize;\n\tULONG ViewBase;\n} PORT_SECTION_READ, *PPORT_SECTION_READ;"
},
{
"identifiers": ["PORT_SECTION_WRITE", "PPORT_SECTION_WRITE"],
"dependencies": [],
"definition": "typedef struct _PORT_SECTION_WRITE\n{\n\tULONG Length;\n\tHANDLE SectionHandle;\n\tULONG SectionOffset;\n\tULONG ViewSize;\n\tPVOID ViewBase;\n\tPVOID TargetViewBase;\n} PORT_SECTION_WRITE, *PPORT_SECTION_WRITE;"
},
{
"identifiers": ["TIMER_TYPE", "PTIMER_TYPE"],
"dependencies": [],
"definition": "typedef enum _TIMER_TYPE\n{\n\tNotificationTimer,\n\tSynchronizationTimer\n} TIMER_TYPE, *PTIMER_TYPE;"
},
{
"identifiers": ["BOOT_ENTRY", "PBOOT_ENTRY"],
"dependencies": [],
"definition": "typedef struct _BOOT_ENTRY\n{\n\tULONG Version;\n\tULONG Length;\n\tULONG Id;\n\tULONG Attributes;\n\tULONG FriendlyNameOffset;\n\tULONG BootFilePathOffset;\n\tULONG OsOptionsLength;\n\tUCHAR OsOptions[ANYSIZE_ARRAY];\n} BOOT_ENTRY, *PBOOT_ENTRY;"
},
{
"identifiers": ["EFI_DRIVER_ENTRY", "PEFI_DRIVER_ENTRY"],
"dependencies": [],
"definition": "typedef struct _EFI_DRIVER_ENTRY\n{\n\tULONG Version;\n\tULONG Length;\n\tULONG Id;\n\tULONG Attributes;\n\tULONG FriendlyNameOffset;\n\tULONG DriverFilePathOffset;\n} EFI_DRIVER_ENTRY, *PEFI_DRIVER_ENTRY;"
},
{
"identifiers": ["RTL_ATOM", "PRTL_ATOM"],
"dependencies": [],
"definition": "typedef USHORT RTL_ATOM, *PRTL_ATOM;"
},
{
"identifiers": ["TIMER_SET_INFORMATION_CLASS", "PTIMER_SET_INFORMATION_CLASS"],
"dependencies": [],
"definition": "typedef enum _TIMER_SET_INFORMATION_CLASS\n{\n\tTimerSetCoalescableTimer,\n\tMaxTimerInfoClass\n} TIMER_SET_INFORMATION_CLASS, *PTIMER_SET_INFORMATION_CLASS;"
},
{
"identifiers": ["FSINFOCLASS", "PFSINFOCLASS"],
"dependencies": [],
"definition": "typedef enum _FSINFOCLASS\n{\n\tFileFsVolumeInformation = 1,\n\tFileFsLabelInformation = 2,\n\tFileFsSizeInformation = 3,\n\tFileFsDeviceInformation = 4,\n\tFileFsAttributeInformation = 5,\n\tFileFsControlInformation = 6,\n\tFileFsFullSizeInformation = 7,\n\tFileFsObjectIdInformation = 8,\n\tFileFsDriverPathInformation = 9,\n\tFileFsVolumeFlagsInformation = 10,\n\tFileFsSectorSizeInformation = 11,\n\tFileFsDataCopyInformation = 12,\n\tFileFsMetadataSizeInformation = 13,\n\tFileFsFullSizeInformationEx = 14,\n\tFileFsMaximumInformation = 15,\n} FSINFOCLASS, *PFSINFOCLASS;"
},
{
"identifiers": ["WAIT_TYPE", "PWAIT_TYPE"],
"dependencies": [],
"definition": "typedef enum _WAIT_TYPE\n{\n\tWaitAll = 0,\n\tWaitAny = 1\n} WAIT_TYPE, *PWAIT_TYPE;"
},
{
"identifiers": ["USER_STACK", "PUSER_STACK"],
"dependencies": [],
"definition": "typedef struct _USER_STACK\n{\n\tPVOID FixedStackBase;\n\tPVOID FixedStackLimit;\n\tPVOID ExpandableStackBase;\n\tPVOID ExpandableStackLimit;\n\tPVOID ExpandableStackBottom;\n} USER_STACK, *PUSER_STACK;"
},
{
"identifiers": ["SECTION_INFORMATION_CLASS", "PSECTION_INFORMATION_CLASS"],
"dependencies": [],
"definition": "typedef enum _SECTION_INFORMATION_CLASS\n{\n\tSectionBasicInformation,\n\tSectionImageInformation,\n} SECTION_INFORMATION_CLASS, *PSECTION_INFORMATION_CLASS;"
},
{
"identifiers": ["APPHELPCACHESERVICECLASS", "PAPPHELPCACHESERVICECLASS"],
"dependencies": [],
"definition": "typedef enum _APPHELPCACHESERVICECLASS\n{\n\tApphelpCacheServiceLookup = 0,\n\tApphelpCacheServiceRemove = 1,\n\tApphelpCacheServiceUpdate = 2,\n\tApphelpCacheServiceFlush = 3,\n\tApphelpCacheServiceDump = 4,\n\tApphelpDBGReadRegistry = 0x100,\n\tApphelpDBGWriteRegistry = 0x101,\n} APPHELPCACHESERVICECLASS, *PAPPHELPCACHESERVICECLASS;"
},
{
"identifiers": ["TOKEN_SECURITY_ATTRIBUTE_FQBN_VALUE", "PTOKEN_SECURITY_ATTRIBUTE_FQBN_VALUE"],
"dependencies": ["UNICODE_STRING"],
"definition": "typedef struct _TOKEN_SECURITY_ATTRIBUTE_FQBN_VALUE\n{\n\tULONG64 Version;\n\tUNICODE_STRING Name;\n} TOKEN_SECURITY_ATTRIBUTE_FQBN_VALUE, *PTOKEN_SECURITY_ATTRIBUTE_FQBN_VALUE;"
},
{
"identifiers": ["TOKEN_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE", "PTOKEN_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE"],
"dependencies": [],
"definition": "typedef struct _TOKEN_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE\n{\n\tPVOID pValue;\n\tULONG ValueLength;\n} TOKEN_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE, *PTOKEN_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE;"
},
{
"identifiers": ["TOKEN_SECURITY_ATTRIBUTE_V1", "PTOKEN_SECURITY_ATTRIBUTE_V1"],
"dependencies": ["PUNICODE_STRING", "PTOKEN_SECURITY_ATTRIBUTE_FQBN_VALUE", "PTOKEN_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE"],
"definition": "typedef struct _TOKEN_SECURITY_ATTRIBUTE_V1\n{\n\tUNICODE_STRING Name;\n\tUSHORT ValueType;\n\tUSHORT Reserved;\n\tULONG Flags;\n\tULONG ValueCount;\n\tunion\n\t{\n\t\tPLONG64 pInt64;\n\t\tPULONG64 pUint64;\n\t\tPUNICODE_STRING pString;\n\t\tPTOKEN_SECURITY_ATTRIBUTE_FQBN_VALUE pFqbn;\n\t\tPTOKEN_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE pOctetString;\n\t} Values;\n} TOKEN_SECURITY_ATTRIBUTE_V1, *PTOKEN_SECURITY_ATTRIBUTE_V1;"
},
{
"identifiers": ["TOKEN_SECURITY_ATTRIBUTES_INFORMATION", "PTOKEN_SECURITY_ATTRIBUTES_INFORMATION"],
"dependencies": ["PTOKEN_SECURITY_ATTRIBUTE_V1"],
"definition": "typedef struct _TOKEN_SECURITY_ATTRIBUTES_INFORMATION\n{\n\tUSHORT Version;\n\tUSHORT Reserved;\n\tULONG AttributeCount;\n\tunion\n\t{\n\t\tPTOKEN_SECURITY_ATTRIBUTE_V1 pAttributeV1;\n\t} Attribute;\n} TOKEN_SECURITY_ATTRIBUTES_INFORMATION, *PTOKEN_SECURITY_ATTRIBUTES_INFORMATION;"
},
{
"identifiers": ["FILE_IO_COMPLETION_INFORMATION", "PFILE_IO_COMPLETION_INFORMATION"],
"dependencies": [],
"definition": "typedef struct _FILE_IO_COMPLETION_INFORMATION\n{\n\tPVOID KeyContext;\n\tPVOID ApcContext;\n\tIO_STATUS_BLOCK IoStatusBlock;\n} FILE_IO_COMPLETION_INFORMATION, *PFILE_IO_COMPLETION_INFORMATION;"
},
{
"identifiers": ["PT2_CANCEL_PARAMETERS"],
"dependencies": [],
"definition": "typedef PVOID PT2_CANCEL_PARAMETERS;"
},
{
"identifiers": ["THREADINFOCLASS", "PTHREADINFOCLASS"],
"dependencies": [],
"definition": "typedef enum _THREADINFOCLASS\n{\n\tThreadBasicInformation,\n\tThreadTimes,\n\tThreadPriority,\n\tThreadBasePriority,\n\tThreadAffinityMask,\n\tThreadImpersonationToken,\n\tThreadDescriptorTableEntry,\n\tThreadEnableAlignmentFaultFixup,\n\tThreadEventPair_Reusable,\n\tThreadQuerySetWin32StartAddress,\n\tThreadZeroTlsCell,\n\tThreadPerformanceCount,\n\tThreadAmILastThread,\n\tThreadIdealProcessor,\n\tThreadPriorityBoost,\n\tThreadSetTlsArrayAddress,\n\tThreadIsIoPending,\n\tThreadHideFromDebugger,\n\tThreadBreakOnTermination,\n\tMaxThreadInfoClass\n} THREADINFOCLASS, *PTHREADINFOCLASS;"
},
{
"identifiers": ["OBJECT_INFORMATION_CLASS", "POBJECT_INFORMATION_CLASS"],
"dependencies": [],
"definition": "typedef enum _OBJECT_INFORMATION_CLASS\n{\n\tObjectBasicInformation,\n\tObjectNameInformation,\n\tObjectTypeInformation,\n\tObjectAllTypesInformation,\n\tObjectHandleInformation\n} OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS;"
},
{
"identifiers": ["FILE_INFORMATION_CLASS", "PFILE_INFORMATION_CLASS"],
"dependencies": [],
"definition": "typedef enum _FILE_INFORMATION_CLASS\n{\n\tFileDirectoryInformation = 1,\n\tFileFullDirectoryInformation = 2,\n\tFileBothDirectoryInformation = 3,\n\tFileBasicInformation = 4,\n\tFileStandardInformation = 5,\n\tFileInternalInformation = 6,\n\tFileEaInformation = 7,\n\tFileAccessInformation = 8,\n\tFileNameInformation = 9,\n\tFileRenameInformation = 10,\n\tFileLinkInformation = 11,\n\tFileNamesInformation = 12,\n\tFileDispositionInformation = 13,\n\tFilePositionInformation = 14,\n\tFileFullEaInformation = 15,\n\tFileModeInformation = 16,\n\tFileAlignmentInformation = 17,\n\tFileAllInformation = 18,\n\tFileAllocationInformation = 19,\n\tFileEndOfFileInformation = 20,\n\tFileAlternateNameInformation = 21,\n\tFileStreamInformation = 22,\n\tFilePipeInformation = 23,\n\tFilePipeLocalInformation = 24,\n\tFilePipeRemoteInformation = 25,\n\tFileMailslotQueryInformation = 26,\n\tFileMailslotSetInformation = 27,\n\tFileCompressionInformation = 28,\n\tFileObjectIdInformation = 29,\n\tFileCompletionInformation = 30,\n\tFileMoveClusterInformation = 31,\n\tFileQuotaInformation = 32,\n\tFileReparsePointInformation = 33,\n\tFileNetworkOpenInformation = 34,\n\tFileAttributeTagInformation = 35,\n\tFileTrackingInformation = 36,\n\tFileIdBothDirectoryInformation = 37,\n\tFileIdFullDirectoryInformation = 38,\n\tFileValidDataLengthInformation = 39,\n\tFileShortNameInformation = 40,\n\tFileIoCompletionNotificationInformation = 41,\n\tFileIoStatusBlockRangeInformation = 42,\n\tFileIoPriorityHintInformation = 43,\n\tFileSfioReserveInformation = 44,\n\tFileSfioVolumeInformation = 45,\n\tFileHardLinkInformation = 46,\n\tFileProcessIdsUsingFileInformation = 47,\n\tFileNormalizedNameInformation = 48,\n\tFileNetworkPhysicalNameInformation = 49,\n\tFileIdGlobalTxDirectoryInformation = 50,\n\tFileIsRemoteDeviceInformation = 51,\n\tFileUnusedInformation = 52,\n\tFileNumaNodeInformation = 53,\n\tFileStandardLinkInformation = 54,\n\tFileRemoteProtocolInformation = 55,\n\tFileRenameInformationBypassAccessCheck = 56,\n\tFileLinkInformationBypassAccessCheck = 57,\n\tFileVolumeNameInformation = 58,\n\tFileIdInformation = 59,\n\tFileIdExtdDirectoryInformation = 60,\n\tFileReplaceCompletionInformation = 61,\n\tFileHardLinkFullIdInformation = 62,\n\tFileIdExtdBothDirectoryInformation = 63,\n\tFileDispositionInformationEx = 64,\n\tFileRenameInformationEx = 65,\n\tFileRenameInformationExBypassAccessCheck = 66,\n\tFileMaximumInformation = 67,\n} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;"
},
{
"identifiers": ["KEY_INFORMATION_CLASS", "PKEY_INFORMATION_CLASS"],
"dependencies": [],
"definition": "typedef enum _KEY_INFORMATION_CLASS\n{\n\tKeyBasicInformation = 0,\n\tKeyNodeInformation = 1,\n\tKeyFullInformation = 2,\n\tKeyNameInformation = 3,\n\tKeyCachedInformation = 4,\n\tKeyFlagsInformation = 5,\n\tKeyVirtualizationInformation = 6,\n\tKeyHandleTagsInformation = 7,\n\tMaxKeyInfoClass = 8\n} KEY_INFORMATION_CLASS, *PKEY_INFORMATION_CLASS;"
},
{
"identifiers": ["UNICODE_STRING", "PUNICODE_STRING"],
"dependencies": [],
"definition": "typedef struct _UNICODE_STRING\n{\n\tUSHORT Length;\n\tUSHORT MaximumLength;\n\tPWSTR Buffer;\n} UNICODE_STRING, *PUNICODE_STRING;"
},
{
"identifiers": ["InitializeObjectAttributes"],
"dependencies": [],
"definition": "#ifndef InitializeObjectAttributes\n#define InitializeObjectAttributes( p, n, a, r, s ) { \\\n\t(p)->Length = sizeof( OBJECT_ATTRIBUTES ); \\\n\t(p)->RootDirectory = r; \\\n\t(p)->Attributes = a; \\\n\t(p)->ObjectName = n; \\\n\t(p)->SecurityDescriptor = s; \\\n\t(p)->SecurityQualityOfService = NULL; \\\n}\n#endif"
},
{
"identifiers": ["OBJECT_ATTRIBUTES", "POBJECT_ATTRIBUTES"],
"dependencies": ["PUNICODE_STRING", "InitializeObjectAttributes"],
"definition": "typedef struct _OBJECT_ATTRIBUTES\n{\n\tULONG Length;\n\tHANDLE RootDirectory;\n\tPUNICODE_STRING ObjectName;\n\tULONG Attributes;\n\tPVOID SecurityDescriptor;\n\tPVOID SecurityQualityOfService;\n} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;"
},
{
"identifiers": ["TIMER_INFORMATION_CLASS", "PTIMER_INFORMATION_CLASS"],
"dependencies": [],
"definition": "typedef enum _TIMER_INFORMATION_CLASS\n{\n\tTimerBasicInformation\n} TIMER_INFORMATION_CLASS, *PTIMER_INFORMATION_CLASS;"
},
{
"identifiers": ["KCONTINUE_TYPE"],
"dependencies": [],
"definition": "typedef enum _KCONTINUE_TYPE\n{\n\tKCONTINUE_UNWIND,\n\tKCONTINUE_RESUME,\n\tKCONTINUE_LONGJUMP,\n\tKCONTINUE_SET,\n\tKCONTINUE_LAST\n} KCONTINUE_TYPE;"
},
{
"identifiers": ["KCONTINUE_ARGUMENT", "PKCONTINUE_ARGUMENT"],
"dependencies": ["KCONTINUE_TYPE"],
"definition": "typedef struct _KCONTINUE_ARGUMENT\n{\n\tKCONTINUE_TYPE ContinueType;\n\tULONG ContinueFlags;\n\tULONGLONG Reserved[2];\n} KCONTINUE_ARGUMENT, *PKCONTINUE_ARGUMENT;"
}
]

902
SysWhispers3/syswhispers.py Normal file
View File

@ -0,0 +1,902 @@
#!/usr/bin/python3
import argparse
import json
import os
import random
import re
import string
import struct
from enum import Enum
from pathlib import Path
def fetch_all_type_definitions(code) -> list:
"""Fetch all type definitions from a given code
Args:
code (str): The code to parse
Returns:
list: The list of all type definitions (tuple of 4 elements) found in the code
"""
return re.findall(r"typedef\s+(\w+)\s+(\w+)\s+([\w|*]*)\s*([\w|*]*)", code, re.DOTALL)
def fetch_inner_enum_definitions(code) -> list:
"""Fetch all type definitions from a given code
Args:
code (str): The code to parse
Returns:
list: The list of all enum definitions (tuple of 2 elements) found in the code
"""
enum_list = []
code = code.replace("\r", "")
code = re.sub(r"/\*.*?\*/", "", code, re.DOTALL | re.MULTILINE)
for x, y in re.findall(r"typedef\s+enum\s+(\w+)\s*{([^}]+)\s*}", code, re.DOTALL | re.MULTILINE):
for line in y.splitlines():
if line.startswith("//"):
continue
line = re.sub("//.*$", "", line)
if line.strip() == "":
continue
line = line.split("=")[0].replace(",", "").strip()
enum_list.append((x, line))
return enum_list
def fetch_includes(code) -> list:
"""
Fetch all includes from a given code
Args:
code (str): The code to parse
Returns:
list: The list of all includes found in the code
"""
_includes = []
code = code.replace("\r", "")
code = re.sub(r"/\*.*?\*/", "", code, re.DOTALL | re.MULTILINE)
for x in re.findall(r'#include\s+\"\s*([^"]+)\s*\"', code, re.DOTALL | re.MULTILINE):
_includes.append(x.strip())
for x in re.findall(r'#include\s+<\s*([^>]+)\s*>', code, re.DOTALL | re.MULTILINE):
_includes.append(x.strip())
return _includes
try:
from enums.Architectures import Arch
from enums.Compilers import Compiler
from enums.SyscallRecoveryType import SyscallRecoveryType
from utils.utils import get_project_root
base_directory = os.path.join(get_project_root(), 'syscalls', 'syswhispersv3')
define_search_and_replace = False
except ModuleNotFoundError:
def get_project_root() -> Path:
return Path(__file__).parent
base_directory = get_project_root()
define_search_and_replace = True
class Arch(Enum):
Any = ""
x86 = "x86"
x64 = "x64"
@staticmethod
def from_string(label):
if label.lower() in ["any", "all"]:
return Arch.Any
elif label.lower() in ["32", "86", "x86", "i386"]:
return Arch.x86
elif label.lower() in ["64", "x64", "amd64", "x86_64"]:
return Arch.x64
class Compiler(Enum):
All = ""
MSVC = "MSVC"
MINGW = "MinGW"
@staticmethod
def from_string(label):
if label.lower() in ["all"]:
return Compiler.All
elif label.lower() in ["msvc"]:
return Compiler.MSVC
elif label.lower() in ["mingw"]:
return Compiler.MINGW
# Define SyscallRecoveryType
class SyscallRecoveryType(Enum):
EMBEDDED = 0
EGG_HUNTER = 1
JUMPER = 2
JUMPER_RANDOMIZED = 3
@classmethod
def from_name_or_default(cls, name):
_types = dict(map(lambda c: (c.name.lower(), c.value), cls))
return SyscallRecoveryType(_types[name]) if name in _types.keys() else SyscallRecoveryType.EMBEDDED
@classmethod
def get_name(cls, value):
if isinstance(value, str):
value = int(value)
_types = dict(map(lambda c: (c.value, c.name.lower()), cls))
return _types[value] if value in _types.keys() else None
@classmethod
def from_name(cls, name):
_types = dict(map(lambda c: (c.name.lower(), c.value), cls))
return _types[name] if name in _types.keys() else None
@classmethod
def value_list(cls):
return list(map(lambda c: c.value, cls))
@classmethod
def key_list(cls):
return list(map(lambda c: c.name.lower(), cls))
class SysWhispers(object):
def __init__(
self,
arch: Arch = Arch.x64,
compiler: Compiler = Compiler.MSVC,
recovery: SyscallRecoveryType = SyscallRecoveryType.EMBEDDED,
syscall_instruction: str = "syscall",
wow64: bool = False,
verbose: bool = False,
debug: bool = False,
prefix: str = 'SW3',
alternative_headers: list = None,
no_windows_headers: bool = False):
self.no_windows_headers = no_windows_headers
self.prefix = prefix
self.arch = arch
self.compiler = compiler
self.recovery = recovery
self.wow64 = wow64
self.syscall_instruction = syscall_instruction
self.egg = [hex(ord(random.choices(string.ascii_lowercase, k=1)[0])), "0x0", "0x0",
hex(ord(random.choices(string.ascii_lowercase, k=1)[0]))]
self.seed = random.randint(2 ** 28, 2 ** 32 - 1)
self.typedefs: list = json.load(
open(os.path.join(base_directory, 'data', 'typedefs.json')))
self.prototypes: dict = json.load(
open(os.path.join(base_directory, 'data', 'prototypes.json')))
self.verbose = verbose
self.debug = debug
self.structured_types = []
self.replaced_types = []
self.alternative_headers = alternative_headers if alternative_headers else []
self.includes = []
self.already_defined_types = []
self.already_defined_enums = []
self.populate_defined_types()
self.validate()
def __find_header_files(self):
print("[*] Searching for alternative header files...", end="")
for i in range(len(self.alternative_headers)):
if self.alternative_headers[i].startswith("+"):
self.includes.append(self.alternative_headers[i][1:])
self.alternative_headers[i] = self.alternative_headers[i][1:]
print("done")
print("[*] Resolving header files...", end="")
for _p in self.alternative_headers.copy():
p = Path(_p).absolute().resolve()
if not p.exists():
self.alternative_headers.remove(_p)
elif p.is_file():
self.alternative_headers.remove(_p)
self.alternative_headers.append(p)
continue
elif p.is_dir():
self.alternative_headers.remove(_p)
for f in p.glob("**/*.h"):
self.alternative_headers.append(f)
print("done")
print("[*] Recursively resolving header files from #include directives...", end="")
alternative_headers = []
found = True
while found:
alternative_headers = self.alternative_headers.copy()
for f in alternative_headers:
p = Path(f).absolute().resolve().parent
with open(f, 'r') as fh:
code = fh.read()
for i in fetch_includes(code):
try:
_p_i = Path(i).relative_to(p).absolute().resolve()
if _p_i not in self.alternative_headers:
self.alternative_headers.append(_p_i)
except ValueError:
pass
found = len(alternative_headers) != len(self.alternative_headers)
print("done")
print("[*] Removing duplicates...", end="")
self.alternative_headers = list(set(self.alternative_headers))
print("done")
def populate_defined_types(self):
self.__find_header_files()
typedefs = []
for f in self.alternative_headers:
with open(f, 'r') as fh:
code = fh.read()
typedefs += fetch_all_type_definitions(code)
self.already_defined_enums += fetch_inner_enum_definitions(code)
for x1, x2 in self.already_defined_enums:
for y in self.typedefs:
code = y.get("definition")
_c_t = fetch_all_type_definitions(code)
if len(_c_t) == 0 or len(_c_t[0]) == 0 or _c_t[0][0] != "enum":
continue
_c_e = fetch_inner_enum_definitions(code)
if len(_c_e) == 0:
continue
for _z1, _z2 in _c_e:
if x2 == _z2:
if x1[1:] not in y.get("identifiers"):
new_type_alias = x1[1:]
y["definition"] = y["definition"].replace(_z1[1:], new_type_alias)
# print("corresponding enum found: ", _z1, x1, y.get("identifiers"))
for function, details in self.prototypes.items():
for param in details["params"]:
if param["type"] in y.get("identifiers"):
param["type"] = param["type"].replace(_z1[1:], new_type_alias)
# print("function using type found: ", function, param["type"], param["name"])
break
for k1, k2, k3, k4 in typedefs:
if k1 not in ["struct", "enum", "union", "const"]:
self.already_defined_types.append(k1)
else:
self.already_defined_types.append(k2)
self.already_defined_types = list(set(self.already_defined_types))
def validate(self):
if self.recovery == SyscallRecoveryType.EGG_HUNTER:
if self.compiler in [Compiler.All, Compiler.MINGW]:
# TODO: try to make the 'db' instruction work in MinGW
exit("[-] Egg-Hunter not compatible with MinGW")
print(r"[*] With the egg-hunter, you need to use a search-replace functionality:")
print(f" unsigned char egg[] = {{ {', '.join([hex(int(x, 16)) for x in self.egg] * 2)} }}; // egg")
replace_x86 = ' unsigned char replace[] = { 0x0f, 0x34, 0x90, 0x90, 0xC3, 0x90, 0xCC, 0xCC }; // sysenter; nop; nop; ret; nop; int3; int3'
replace_x64 = ' unsigned char replace[] = { 0x0f, 0x05, 0x90, 0x90, 0xC3, 0x90, 0xCC, 0xCC }; // syscall; nop; nop; ret; nop; int3; int3'
if self.arch == Arch.Any:
print(f"#ifdef _WIN64\n{replace_x64}\n#else\n{replace_x86}\n#endif")
elif self.arch == Arch.x86:
print(replace_x86)
else:
print(replace_x64)
print()
def generate(self, function_names: list = (), basename: str = 'syscalls'):
if not function_names:
function_names = list(self.prototypes.keys())
elif any([f not in self.prototypes.keys() for f in function_names]):
raise ValueError('Prototypes are not available for one or more of the requested functions.')
# Write C file.
with open(os.path.join(base_directory, 'data', 'base.c'), 'rb') as base_source:
with open(f'{basename}.c', 'wb') as output_source:
base_source_contents = base_source.read().decode()
if self.verbose:
base_source_contents = base_source_contents.replace('//#define DEBUG', '#define DEBUG')
base_source_contents = base_source_contents.replace('<BASENAME>', os.path.basename(basename), 1)
if self.recovery in [SyscallRecoveryType.JUMPER, SyscallRecoveryType.JUMPER_RANDOMIZED]:
base_source_contents = base_source_contents.replace("// JUMPER", "#define JUMPER")
if self.wow64:
base_source_contents = base_source_contents.replace('// JUMP_TO_WOW32Reserved',
' // if we are a WoW64 process, jump to WOW32Reserved\n SyscallAddress = (PVOID)__readfsdword(0xc0);\n return SyscallAddress;')
else:
base_source_contents = base_source_contents.replace('// JUMP_TO_WOW32Reserved',
' return NULL;')
msvc_wow64 = '__declspec(naked) BOOL local_is_wow64(void)\n{\n __asm {\n mov eax, fs:[0xc0]\n test eax, eax\n jne wow64\n mov eax, 0\n ret\n wow64:\n mov eax, 1\n ret\n }\n}\n'
mingw_wow64 = '__declspec(naked) BOOL local_is_wow64(void)\n{\n asm(\n "mov eax, fs:[0xc0] \\n"\n "test eax, eax \\n"\n "jne wow64 \\n"\n "mov eax, 0 \\n"\n "ret \\n"\n "wow64: \\n"\n "mov eax, 1 \\n"\n "ret \\n"\n );\n}'
wow64_function = ''
if self.compiler == Compiler.All:
wow64_function += '#if defined(_MSC_VER)\n\n'
wow64_function += msvc_wow64
wow64_function += '\n\n#elif defined(__GNUC__)\n\n'
wow64_function += mingw_wow64
wow64_function += '\n\n#endif'
elif self.compiler == Compiler.MSVC:
wow64_function += msvc_wow64
elif self.compiler == Compiler.MINGW:
wow64_function += mingw_wow64
base_source_contents = base_source_contents.replace('// LOCAL_IS_WOW64', wow64_function)
output_source.write(base_source_contents.encode())
if self.compiler in [Compiler.All, Compiler.MINGW]:
output_source.write('#if defined(__GNUC__)\n\n'.encode())
for function_name in function_names:
output_source.write((self._get_function_asm_code_mingw(function_name) + '\n').encode())
output_source.write('#endif\n'.encode())
basename_suffix = ''
basename_suffix = basename_suffix.capitalize() if os.path.basename(basename).istitle() else basename_suffix
if self.compiler in [Compiler.All, Compiler.MSVC]:
if self.arch in [Arch.Any, Arch.x64]:
# Write x64 ASM file
basename_suffix = f'_{basename_suffix}' if '_' in basename else basename_suffix
with open(f'{basename}{basename_suffix}-asm.x64.asm', 'wb') as output_asm:
output_asm.write(b'.code\n\nEXTERN SW3_GetSyscallNumber: PROC\n\n')
if self.recovery == SyscallRecoveryType.JUMPER:
# We perform a direct jump to the syscall instruction inside ntdll.dll
output_asm.write(b'EXTERN SW3_GetSyscallAddress: PROC\n\n')
elif self.recovery == SyscallRecoveryType.JUMPER_RANDOMIZED:
# We perform a direct jump to a syscall instruction of another API
output_asm.write(b'EXTERN SW3_GetRandomSyscallAddress: PROC\n\n')
for function_name in function_names:
output_asm.write((self._get_function_asm_code_msvc(function_name, Arch.x64) + '\n').encode())
output_asm.write(b'end')
if self.arch in [Arch.Any, Arch.x86]:
# Write x86 ASM file
with open(f'{basename}{basename_suffix}-asm.x86.asm', 'wb') as output_asm:
output_asm.write(b".686\n.XMM\n.MODEL flat, c\nASSUME fs:_DATA\n.code\n\n")
output_asm.write(
b'EXTERN SW3_GetSyscallNumber: PROC\nEXTERN local_is_wow64: PROC\nEXTERN internal_cleancall_wow64_gate: PROC')
if self.recovery == SyscallRecoveryType.JUMPER:
# We perform a direct jump to the syscall instruction inside ntdll.dll
output_asm.write(b'\nEXTERN SW3_GetSyscallAddress: PROC')
elif self.recovery == SyscallRecoveryType.JUMPER_RANDOMIZED:
# We perform a direct jump to a syscall instruction of another API
output_asm.write(b'\nEXTERN SW3_GetRandomSyscallAddress: PROC')
output_asm.write(b'\n\n')
for function_name in function_names:
output_asm.write((self._get_function_asm_code_msvc(function_name, Arch.x86) + '\n').encode())
output_asm.write(b'end')
# Write header file.
with open(os.path.join(base_directory, 'data', 'base.h'), 'rb') as base_header:
with open(f'{basename}.h', 'wb') as output_header:
# Replace <SEED_VALUE> with a random seed.
base_header_contents = base_header.read().decode()
base_header_contents = base_header_contents.replace('<SEED_VALUE>', f'0x{self.seed:08X}', 1)
if self.alternative_headers:
for f in self.includes:
f = Path(f).absolute().resolve()
base_header_contents = base_header_contents.replace('#include <windows.h>', f'#include "{f}"\n#include <windows.h>')
if self.no_windows_headers:
base_header_contents = base_header_contents.replace('#include <windows.h>', '')
# Write the base header.
output_header.write(base_header_contents.encode())
# Write the typedefs.
for typedef in self._get_typedefs(function_names):
output_header.write(typedef.encode() + b'\n\n')
# Write the function prototypes.
for function_name in function_names:
output_header.write((self._get_function_prototype(function_name) + '\n\n').encode())
# Write the endif line.
output_header.write('#endif\n'.encode())
if self.verbose:
print('[+] Complete! Files written to:')
print(f'\t{basename}.h')
print(f'\t{basename}.c')
if self.arch in [Arch.x64, Arch.Any]:
print(f'\t{basename}{basename_suffix}-asm.x64.asm')
if self.arch in [Arch.x86, Arch.Any]:
print(f'\t{basename}{basename_suffix}-asm.x86.asm')
input("[/] Press a key to continue...")
def _get_typedefs(self, function_names: list) -> list:
def _names_to_ids(names: list) -> list:
return [next(i for i, t in enumerate(self.typedefs) if n in t['identifiers']) for n in names]
# Determine typedefs to use.
used_typedefs = []
for function_name in function_names:
for param in self.prototypes[function_name]['params']:
if list(filter(lambda t: param['type'] in t['identifiers'], self.typedefs)):
if param['type'] not in used_typedefs:
used_typedefs.append(param['type'])
# Resolve typedef dependencies.
i = 0
typedef_layers = {i: _names_to_ids(used_typedefs)}
while True:
# Identify dependencies of current layer.
more_dependencies = []
for typedef_id in typedef_layers[i]:
more_dependencies += self.typedefs[typedef_id].get('dependencies')
more_dependencies = list(set(more_dependencies)) # Remove duplicates.
if more_dependencies:
# Create new layer.
i += 1
typedef_layers[i] = _names_to_ids(more_dependencies)
else:
# Remove duplicates between layers.
for k in range(len(typedef_layers) - 1):
typedef_layers[k] = set(typedef_layers[k]) - set(typedef_layers[k + 1])
break
# Get code for each typedef.
typedef_code = []
prefix = self.prefix + "_" if self.prefix else ""
for i in range(max(typedef_layers.keys()), -1, -1):
for j in typedef_layers[i]:
code = self.typedefs[j].get('definition')
if code.startswith('typedef') and code.split(" ")[1] in ["const", "struct", "enum"]:
pname = code.split(" ")[2].split("\n")[0].strip()
name = pname[1:]
if pname in self.already_defined_types:
continue
# self.structured_types.append(name)
# code = code.replace(name, prefix + name)
# # Probably handle deps here
# for dep in self.structured_types:
# if dep != name and dep in code:
# code = code.replace(dep + " ", prefix + dep + " ")
# elif code.startswith('typedef'):
# for dep in self.structured_types:
# if dep in code:
# code = code.replace(dep + " ", prefix + dep + " ")
typedef_code.append(code)
return typedef_code
def _fix_type(self, _type: str) -> str:
return _type
# if self.prefix in [None, ""]:
# return _type
# if _type in self.structured_types:
# return self.prefix + "_" + _type
#
# elif _type.startswith("P") and _type[1:] in self.structured_types:
# return "P" + self.prefix + "_" + _type[1:]
#
# return _type
def _get_function_prototype(self, function_name: str) -> str:
# Check if given function is in syscall map.
if function_name not in self.prototypes:
raise ValueError('Invalid function name provided.')
num_params = len(self.prototypes[function_name]['params'])
signature = f'EXTERN_C NTSTATUS {self.prefix.capitalize()}{function_name}('
if num_params:
for i in range(num_params):
param = self.prototypes[function_name]['params'][i]
_type = self._fix_type(param['type'])
signature += '\n\t'
signature += 'IN ' if param['in'] else ''
signature += 'OUT ' if param['out'] else ''
signature += f'{_type} {param["name"]}'
signature += ' OPTIONAL' if param['optional'] else ''
signature += ',' if i < num_params - 1 else ');'
else:
signature += ');'
return signature
def _get_function_hash(self, function_name: str):
hash = self.seed
name = function_name.replace('Nt', 'Zw', 1) + '\0'
ror8 = lambda v: ((v >> 8) & (2 ** 32 - 1)) | ((v << 24) & (2 ** 32 - 1))
for segment in [s for s in [name[i:i + 2] for i in range(len(name))] if len(s) == 2]:
partial_name_short = struct.unpack('<H', segment.encode())[0]
hash ^= partial_name_short + ror8(hash)
return hash
def _get_function_asm_code_mingw(self, function_name: str) -> str:
function_hash = self._get_function_hash(function_name)
num_params = len(self.prototypes[function_name]['params'])
prototype = self._get_function_prototype(function_name)
prototype = prototype.replace('EXTERN_C', '__declspec(naked)')
prototype = prototype.replace(');', ')')
code = prototype
code += '\n{'
code += '\n\tasm('
if self.arch == Arch.Any:
code += '\n#if defined(_WIN64)'
if self.arch in [Arch.Any, Arch.x64]:
# Generate 64-bit ASM code.
code += '\n\t\t"mov [rsp +8], rcx \\n"'
code += '\n\t\t"mov [rsp+16], rdx \\n"'
code += '\n\t\t"mov [rsp+24], r8 \\n"'
code += '\n\t\t"mov [rsp+32], r9 \\n"'
code += '\n\t\t"sub rsp, 0x28 \\n"'
code += f'\n\t\t"mov ecx, 0x{function_hash:08X} \\n"'
if self.recovery in [SyscallRecoveryType.JUMPER, SyscallRecoveryType.JUMPER_RANDOMIZED]:
if self.recovery == SyscallRecoveryType.JUMPER_RANDOMIZED:
code += '\n\t\t"call SW3_GetRandomSyscallAddress \\n"'
else:
code += '\n\t\t"call SW3_GetSyscallAddress \\n"'
code += '\n\t\t"mov r11, rax \\n"'
code += f'\n\t\t"mov ecx, 0x{function_hash:08X} \\n"'
code += '\n\t\t"call SW3_GetSyscallNumber \\n"'
code += '\n\t\t"add rsp, 0x28 \\n"'
code += '\n\t\t"mov rcx, [rsp+8] \\n"'
code += '\n\t\t"mov rdx, [rsp+16] \\n"'
code += '\n\t\t"mov r8, [rsp+24] \\n"'
code += '\n\t\t"mov r9, [rsp+32] \\n"'
code += '\n\t\t"mov r10, rcx \\n"'
if self.debug:
code += '\n\t\t"int 3 \\n"'
if self.recovery in [SyscallRecoveryType.JUMPER, SyscallRecoveryType.JUMPER_RANDOMIZED]:
code += '\n\t\t"jmp r11 \\n"'
elif self.recovery == SyscallRecoveryType.EGG_HUNTER:
for x in self.egg + self.egg:
code += f'\n\t\t"DB {x} \\n"'
code += '\n\t\t"ret \\n"'
elif self.recovery == SyscallRecoveryType.EMBEDDED:
code += f'\n\t\t"{self.syscall_instruction} \\n"'
code += '\n\t\t"ret \\n"'
if self.arch == Arch.Any:
code += '\n#else'
if self.arch in [Arch.Any, Arch.x86]:
code += '\n\t\t"push ebp \\n"'
code += '\n\t\t"mov ebp, esp \\n"'
code += f'\n\t\t"push 0x{function_hash:08X} \\n"'
if self.recovery in [SyscallRecoveryType.JUMPER, SyscallRecoveryType.JUMPER_RANDOMIZED]:
if self.recovery == SyscallRecoveryType.JUMPER_RANDOMIZED:
code += '\n\t\t"call _SW3_GetRandomSyscallAddress \\n"'
else:
code += '\n\t\t"call _SW3_GetSyscallAddress \\n"'
code += '\n\t\t"mov edi, eax \\n"'
code += f'\n\t\t"push 0x{function_hash:08X} \\n"'
code += '\n\t\t"call _SW3_GetSyscallNumber \\n"'
code += '\n\t\t"lea esp, [esp+4] \\n"'
code += f'\n\t\t"mov ecx, {hex(num_params)} \\n"'
code += f'\n\t"push_argument_{function_hash:08X}: \\n"'
code += '\n\t\t"dec ecx \\n"'
code += '\n\t\t"push [ebp + 8 + ecx * 4] \\n"'
code += f'\n\t\t"jnz push_argument_{function_hash:08X} \\n"'
if self.debug:
# 2nd SW breakpoint, to study the syscall instruction in detail
code += '\n\t\t"int 3 \\n"'
code += '\n\t\t"mov ecx, eax \\n"'
if self.recovery not in [SyscallRecoveryType.JUMPER,
SyscallRecoveryType.JUMPER_RANDOMIZED] \
and self.wow64:
# check if the process is WoW64 or native
code += '\n\t\t"call _local_is_wow64 \\n"'
code += '\n\t\t"test eax, eax \\n"'
code += '\n\t\t"je is_native \\n"'
# if is wow64
code += '\n\t\t"call _internal_cleancall_wow64_gate \\n"'
code += f'\n\t\t"lea ebx, [ret_address_epilog_{function_hash:08X}] \\n"'
code += '\n\t\t"push ebx \\n"'
# Note: Workaround for Wow64 call
# ntdll!NtWriteFile+0xc:
# 77ca2a1c c22400 ret 24h
# In a standard call, we have two addresses before the arguments passed to the Nt function
# In this case, as we need to return to the program, we can insert the return address twice
code += '\n\t\t"push ebx \\n"'
code += '\n\t\t"xchg eax, ecx \\n"'
code += '\n\t\t"jmp ecx \\n"'
code += '\n\t\t"jmp finish \\n"'
# if is native
code += '\n\t"is_native: \\n"'
code += '\n\t\t"mov eax, ecx \\n"'
code += f'\n\t\t"lea ebx, [ret_address_epilog_{function_hash:08X}] \\n"'
code += '\n\t\t"push ebx \\n"'
code += f'\n\t\t"call do_sysenter_interrupt_{function_hash:08X} \\n"'
if self.recovery not in [SyscallRecoveryType.JUMPER,
SyscallRecoveryType.JUMPER_RANDOMIZED] \
and self.wow64:
code += '\n\t"finish: \\n"'
code += '\n\t\t"lea esp, [esp+4] \\n"'
code += f'\n\t"ret_address_epilog_{function_hash:08X}: \\n"'
code += '\n\t\t"mov esp, ebp \\n"'
code += '\n\t\t"pop ebp \\n"'
code += '\n\t\t"ret \\n"'
code += f'\n\t"do_sysenter_interrupt_{function_hash:08X}: \\n"'
code += '\n\t\t"mov edx, esp \\n"'
if self.debug:
code += '\n\t\t"int 3 \\n"'
if self.recovery == SyscallRecoveryType.EGG_HUNTER:
for x in self.egg + self.egg:
code += f'\n\t\t"DB {x} \\n"'
elif self.recovery in [SyscallRecoveryType.JUMPER, SyscallRecoveryType.JUMPER_RANDOMIZED]:
code += '\n\t\t"jmp edi \\n"'
else:
code += '\n\t\t"sysenter \\n"'
code += '\n\t\t"ret \\n"'
if self.arch == Arch.Any:
code += '\n#endif'
code += '\n\t);'
code += '\n}'
code += '\n'
return code
def _get_function_asm_code_msvc(self, function_name: str, arch: Arch) -> str:
function_hash = self._get_function_hash(function_name)
num_params = len(self.prototypes[function_name]['params'])
code = ''
code += f'{self.prefix.capitalize()}{function_name} PROC\n'
if arch == Arch.x64:
# Generate 64-bit ASM code.
if self.debug:
code += '\tint 3\n'
code += '\tmov [rsp +8], rcx ; Save registers.\n'
code += '\tmov [rsp+16], rdx\n'
code += '\tmov [rsp+24], r8\n'
code += '\tmov [rsp+32], r9\n'
code += '\tsub rsp, 28h\n'
code += f'\tmov ecx, 0{function_hash:08X}h ; Load function hash into ECX.\n'
if self.recovery in [SyscallRecoveryType.JUMPER, SyscallRecoveryType.JUMPER_RANDOMIZED]:
if self.recovery == SyscallRecoveryType.JUMPER_RANDOMIZED:
code += '\tcall SW3_GetRandomSyscallAddress ; Get a syscall offset from a different api.\n'
else:
code += '\tcall SW3_GetSyscallAddress ; Resolve function hash into syscall offset.\n'
code += '\tmov r11, rax ; Save the address of the syscall\n'
code += f'\tmov ecx, 0{function_hash:08X}h ; Re-Load function hash into ECX (optional).\n'
code += '\tcall SW3_GetSyscallNumber ; Resolve function hash into syscall number.\n'
code += '\tadd rsp, 28h\n'
code += '\tmov rcx, [rsp+8] ; Restore registers.\n'
code += '\tmov rdx, [rsp+16]\n'
code += '\tmov r8, [rsp+24]\n'
code += '\tmov r9, [rsp+32]\n'
code += '\tmov r10, rcx\n'
if self.debug:
code += '\tint 3\n'
if self.recovery in [SyscallRecoveryType.JUMPER, SyscallRecoveryType.JUMPER_RANDOMIZED]:
code += '\tjmp r11 ; Jump to -> Invoke system call.\n'
elif self.recovery == SyscallRecoveryType.EGG_HUNTER:
for x in self.egg + self.egg:
code += f'\tDB {x[2:]}h ; "{chr(int(x, 16)) if int(x, 16) != 0 else str(0)}"\n'
code += '\tret\n'
elif self.recovery == SyscallRecoveryType.EMBEDDED:
code += f'\t{self.syscall_instruction} ; Invoke system call.\n'
code += '\tret\n'
else:
# x32 Prolog
code += '\t\tpush ebp\n'
code += '\t\tmov ebp, esp\n'
code += f'\t\tpush 0{function_hash:08X}h ; Load function hash into ECX.\n'
if self.recovery in [SyscallRecoveryType.JUMPER, SyscallRecoveryType.JUMPER_RANDOMIZED]:
if self.recovery == SyscallRecoveryType.JUMPER_RANDOMIZED:
code += '\t\tcall SW3_GetRandomSyscallAddress ; Get a syscall offset from a different api.\n'
else:
code += '\t\tcall SW3_GetSyscallAddress ; Resolve function hash into syscall offset.\n'
code += '\t\tmov edi, eax ; Save the address of the syscall\n'
code += f'\t\tpush 0{function_hash:08X}h ; Re-Load function hash into ECX (optional).\n'
code += '\t\tcall SW3_GetSyscallNumber\n'
code += '\t\tlea esp, [esp+4]\n'
code += f'\t\tmov ecx, 0{hex(num_params)[2:]}h\n'
code += f'\tpush_argument_{function_hash:08X}:\n'
code += '\t\tdec ecx\n'
code += '\t\tpush [ebp + 8 + ecx * 4]\n'
code += f'\t\tjnz push_argument_{function_hash:08X}\n'
if self.debug:
# 2nd SW breakpoint, to study the syscall instruction in detail
code += '\t\tint 3\n'
code += '\t\tmov ecx, eax\n'
if self.recovery not in [SyscallRecoveryType.JUMPER,
SyscallRecoveryType.JUMPER_RANDOMIZED] \
and self.wow64:
# check if the process is WoW64 or native
code += '\t\tcall local_is_wow64\n'
code += '\t\ttest eax, eax\n'
code += '\t\tje is_native\n'
# if is wow64
code += '\t\tcall internal_cleancall_wow64_gate\n'
# Note: Workaround for Wow64 call
# ntdll!NtWriteFile+0xc:
# 77ca2a1c c22400 ret 24h
# In a standard call, we have two addresses before the arguments passed to the Nt function
# In this case, as we need to return to the program, we can insert the return address twice
code += f'\t\tpush ret_address_epilog_{function_hash:08X}\n'
code += f'\t\tpush ret_address_epilog_{function_hash:08X}\n'
code += '\t\txchg eax, ecx\n'
code += '\t\tjmp ecx\n'
code += '\t\tjmp finish\n'
# if is native
code += '\tis_native:\n'
code += '\t\tmov eax, ecx\n'
code += f'\t\tpush ret_address_epilog_{function_hash:08X}\n'
code += f'\t\tcall do_sysenter_interrupt_{function_hash:08X}\n'
if self.recovery not in [SyscallRecoveryType.JUMPER,
SyscallRecoveryType.JUMPER_RANDOMIZED] \
and self.wow64:
code += '\tfinish:\n'
code += '\t\tlea esp, [esp+4]\n'
code += f'\tret_address_epilog_{function_hash:08X}:\n'
code += '\t\tmov esp, ebp\n'
code += '\t\tpop ebp\n'
code += '\t\tret\n'
code += f'\tdo_sysenter_interrupt_{function_hash:08X}:\n'
code += '\t\tmov edx, esp\n'
if self.recovery == SyscallRecoveryType.EGG_HUNTER:
for x in self.egg + self.egg:
code += f'\t\tDB {x[2:]}h ; "{chr(int(x, 16)) if int(x, 16) != 0 else str(0)}"\n'
elif self.recovery in [SyscallRecoveryType.JUMPER, SyscallRecoveryType.JUMPER_RANDOMIZED]:
code += '\t\tjmp edi\n'
else:
code += '\t\tsysenter\n'
code += '\t\tret\n'
code += f'{self.prefix.capitalize()}{function_name} ENDP\n'
return code
if __name__ == '__main__':
print(
" \n"
" . ,--. \n"
",-. . . ,-. . , , |-. o ,-. ,-. ,-. ,-. ,-. __/ \n"
"`-. | | `-. |/|/ | | | `-. | | |-' | `-. . \\ \n"
"`-' `-| `-' ' ' ' ' ' `-' |-' `-' ' `-' ''' \n"
" /| | @Jackson_T \n"
" `-' ' @modexpblog, 2021 \n\n"
" Edits by @klezVirus, 2022 \n"
"SysWhispers3: Why call the kernel when you can whisper?\n\n"
)
parser = argparse.ArgumentParser(description="SysWhispers3 - SysWhispers on steroids")
parser.add_argument('-p', '--preset', help='Preset ("all", "common")', required=False)
parser.add_argument('-a', '--arch', default="x64", choices=["x86", "x64", "all"], help='Architecture',
required=False)
parser.add_argument('-c', '--compiler', default="msvc", choices=["msvc", "mingw", "all"], help='Compiler',
required=False)
parser.add_argument('-m', '--method', default="embedded",
choices=["embedded", "egg_hunter", "jumper", "jumper_randomized"],
help='Syscall recovery method', required=False)
parser.add_argument('-f', '--functions', help='Comma-separated functions', required=False)
parser.add_argument('-o', '--out-file', help='Output basename (w/o extension)', required=True)
parser.add_argument('--int2eh', default=False, action='store_true',
help='Use the old `int 2eh` instruction in place of `syscall`', required=False)
parser.add_argument('--wow64', default=False, action='store_true',
help='Add support for WoW64, to run x86 on x64', required=False)
parser.add_argument('-v', '--verbose', default=False, action='store_true',
help='Enable debug output', required=False)
parser.add_argument('-d', '--debug', default=False, action='store_true',
help='Enable syscall debug (insert software breakpoint)', required=False)
parser.add_argument('-P', '--prefix', default="SW3", type=str,
help='Add prefix to function names to avoid pollution', required=False)
parser.add_argument('-H', '--alternative-headers', default=[], action="append",
help='Alternative headers files (e.g., phnt.h)', required=False)
parser.add_argument('-nWH', '--no-win-headers', default=False, action="store_true",
help='Do not add <windows.h> in syscalls.h', required=False)
args = parser.parse_args()
recovery = SyscallRecoveryType.from_name_or_default(args.method)
arch = Arch.from_string(args.arch)
compiler = Compiler.from_string(args.compiler)
sw = SysWhispers(
arch=arch,
compiler=compiler,
syscall_instruction="syscall" if not args.int2eh else "int 2eh",
recovery=recovery,
wow64=args.wow64,
verbose=args.verbose,
debug=args.debug,
prefix=args.prefix,
alternative_headers=args.alternative_headers,
no_windows_headers=args.no_win_headers
)
print()
if args.preset == 'all':
print('[I] All functions selected.\n')
sw.generate(basename=args.out_file)
elif args.preset == 'common':
print('[I] Common functions selected.\n')
sw.generate(
['NtCreateProcess',
'NtCreateThreadEx',
'NtOpenProcess',
'NtOpenProcessToken',
'NtTestAlert',
'NtOpenThread',
'NtSuspendProcess',
'NtSuspendThread',
'NtResumeProcess',
'NtResumeThread',
'NtGetContextThread',
'NtSetContextThread',
'NtClose',
'NtReadVirtualMemory',
'NtWriteVirtualMemory',
'NtAllocateVirtualMemory',
'NtProtectVirtualMemory',
'NtFreeVirtualMemory',
'NtQuerySystemInformation',
'NtQueryDirectoryFile',
'NtQueryInformationFile',
'NtQueryInformationProcess',
'NtQueryInformationThread',
'NtCreateSection',
'NtOpenSection',
'NtMapViewOfSection',
'NtUnmapViewOfSection',
'NtAdjustPrivilegesToken',
'NtDeviceIoControlFile',
'NtQueueApcThread',
'NtWaitForMultipleObjects'],
basename=args.out_file)
elif args.preset:
print('[-] Invalid preset provided. Must be "all" or "common".')
elif not args.functions:
print('[-] --preset XOR --functions switch must be specified.\n')
print('[H] ./syswhispers.py --preset common --out-file syscalls_common')
print('[H] ./syswhispers.py --functions NtTestAlert,NtGetCurrentProcessorNumber --out-file syscalls_test')
else:
functions = args.functions.split(',') if args.functions else []
sw.generate(functions, args.out_file)