mirror of
https://github.com/tdeerenberg/InlineWhispers3.git
synced 2025-07-17 00:44:17 +00:00
Add SysWhispers3 to repo as non-submodule
This commit is contained in:
7
SysWhispers3/.gitignore
vendored
Normal file
7
SysWhispers3/.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
.idea
|
||||
!data/*
|
||||
!example-output/*
|
||||
__pycache__
|
||||
*.asm
|
||||
*.c
|
||||
*.h
|
201
SysWhispers3/LICENSE
Normal file
201
SysWhispers3/LICENSE
Normal 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
252
SysWhispers3/README.md
Normal 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!
|
||||
|
||||
[](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
0
SysWhispers3/__init__.py
Normal file
16291
SysWhispers3/data/prototypes.json
Normal file
16291
SysWhispers3/data/prototypes.json
Normal file
File diff suppressed because it is too large
Load Diff
503
SysWhispers3/data/typedefs.json
Normal file
503
SysWhispers3/data/typedefs.json
Normal 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
902
SysWhispers3/syswhispers.py
Normal 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)
|
Reference in New Issue
Block a user