├── .gitignore ├── LICENSE ├── README.md ├── __init__.py ├── data ├── base.c ├── base.h ├── prototypes.json └── typedefs.json ├── example-output ├── Syscalls-asm.x64.asm ├── Syscalls.c └── Syscalls.h └── syswhispers.py /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | !data/* 3 | !example-output/* 4 | __pycache__ 5 | *.asm 6 | *.c 7 | *.h -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2019 Jackson T. 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SysWhispers3 2 | 3 | SysWhispers helps with evasion by generating header/ASM files implants can use to make direct system calls. 4 | 5 | ## Official Discord Channel 6 | 7 | Come hang out on Discord! 8 | 9 | [![Inceptor Server](https://discordapp.com/api/guilds/1155753953108164628/widget.png?style=banner3)](https://discord.gg/f6w6dwZq) 10 | 11 | ### Why on earth didn't I create a PR to SysWhispers2? 12 | 13 | The reason for SysWhispers3 to be a standalone version are many, but the most important are: 14 | 15 | * SysWhispers3 is the de-facto "fork" used by [Inceptor][1], and implements some utils class which are not relevant to the 16 | original version of the tool. 17 | * SysWhispers2 is moving towards supporting NASM compilation (for gcc/mingw), while this version is specifically designed and 18 | tested to support MSVC (because [Inceptor][1] will stay a Windows-only framework for the near future). 19 | * SysWhispers3 contains partially implemented features (such as egg-hunting) which would not be sensible to include 20 | in the original version of the tool. 21 | 22 | ## Differences with SysWhispers2 23 | 24 | The usage is pretty similar to [SysWhispers2](https://github.com/jthuraisamy/SysWhispers2), with the following exceptions: 25 | 26 | * It also supports x86/WoW64 27 | * It supports syscalls instruction replacement with an EGG (to be dynamically replaced) 28 | * It supports direct jumps to syscalls in x86/x64 mode (in WOW64 it's almost standard) 29 | * It supports direct jumps to random syscalls (borrowing [@ElephantSeal's idea](https://twitter.com/ElephantSe4l/status/1488464546746540042)) 30 | 31 | A better explanation of these features are better outlined i the blog post [SysWhispers is dead, long live SysWhispers!][2] 32 | 33 | ## Introduction 34 | 35 | Security products, such as AVs and EDRs, usually place hooks in user-mode API functions to analyse a program execution 36 | flow, in order to detect potentially malicious activities. 37 | 38 | SysWhispers2 is a tool designed to generate header/ASM pairs for any system call in the core kernel image 39 | (`ntoskrnl.exe`), which can then be integrated and called directly from C/C++ code, evading user-lands hooks. 40 | 41 | The tool, however, generates some patters which can be included in signatures, or behaviour which can be detected 42 | at runtime. 43 | 44 | SysWhispers3 is built on top of SysWhispers2, and integrates some helpful features to bypass these forms of detection. 45 | 46 | ## Installation 47 | 48 | ``` 49 | C:\> git clone https://github.com/klezVirus/SysWhispers3.git 50 | C:\> cd SysWhispers3 51 | C:\> python .\syswhispers.py --help 52 | ``` 53 | 54 | ## Usage and Examples 55 | 56 | The help shows all the available commands and features of the tool: 57 | 58 | ``` 59 | C:\>python syswhispers.py -h 60 | 61 | 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] 62 | 63 | SysWhispers3 - SysWhispers on steroids 64 | 65 | optional arguments: 66 | -h, --help show this help message and exit 67 | -p PRESET, --preset PRESET 68 | Preset ("all", "common") 69 | -a {x86,x64}, --arch {x86,x64} 70 | Architecture 71 | -c {msvc,mingw,all}, --compiler {msvc,mingw,all} 72 | Compiler 73 | -m {embedded,egg_hunter,jumper,jumper_randomized}, --method {embedded,egg_hunter,jumper,jumper_randomized} 74 | Syscall recovery method 75 | -f FUNCTIONS, --functions FUNCTIONS 76 | Comma-separated functions 77 | -o OUT_FILE, --out-file OUT_FILE 78 | Output basename (w/o extension) 79 | --int2eh Use the old `int 2eh` instruction in place of `syscall` 80 | --wow64 Use Wow64 to run x86 on x64 (only usable with x86 architecture) 81 | -v, --verbose Enable debug output 82 | -d, --debug Enable syscall debug (insert software breakpoint) 83 | ``` 84 | 85 | ### Command Lines 86 | 87 | #### Standard SysWhispers, embedded system calls (x64) 88 | 89 | ```powershell 90 | # Export all functions with compatibility for all supported Windows versions (see example-output/). 91 | py .\syswhispers.py --preset all -o syscalls_all 92 | 93 | # Export just the common functions (see below for list). 94 | py .\syswhispers.py --preset common -o syscalls_common 95 | 96 | # Export NtProtectVirtualMemory and NtWriteVirtualMemory with compatibility for all versions. 97 | py .\syswhispers.py --functions NtProtectVirtualMemory,NtWriteVirtualMemory -o syscalls_mem 98 | ``` 99 | 100 | #### SysWhispers3-only samples 101 | 102 | ```powershell 103 | # Normal SysWhispers, 32-bits mode 104 | py .\syswhispers.py --preset all -o syscalls_all -m jumper --arch x86 105 | 106 | # Normal SysWhispers, using WOW64 in 32-bits mode (only specific functions) 107 | py .\syswhispers.py --functions NtProtectVirtualMemory,NtWriteVirtualMemory -o syscalls_mem --arch x86 --wow64 108 | 109 | # Egg-Hunting SysWhispers, to bypass the "mark of the sycall" (common function) 110 | py .\syswhispers.py --preset common -o syscalls_common -m egg_hunter 111 | 112 | # Jumping/Jumping Randomized SysWhispers, to bypass dynamic RIP validation (all functions) using MinGW as the compiler 113 | py .\syswhispers.py --preset all -o syscalls_all -m jumper -c mingw 114 | 115 | 116 | ``` 117 | 118 | ### Script Output 119 | 120 | ``` 121 | PS C:\Projects\SysWhispers2> py .\syswhispers.py --preset common --out-file temp\syscalls_common -v 122 | 123 | . ,--. 124 | ,-. . . ,-. . , , |-. o ,-. ,-. ,-. ,-. ,-. __/ 125 | `-. | | `-. |/|/ | | | `-. | | |-' | `-. . \ 126 | `-' `-| `-' ' ' ' ' ' `-' |-' `-' ' `-' ''' 127 | /| | @Jackson_T 128 | `-' ' @modexpblog, 2021 129 | 130 | Edits by @klezVirus, 2022 131 | SysWhispers3: Why call the kernel when you can whisper? 132 | 133 | 134 | Common functions selected. 135 | 136 | Complete! Files written to: 137 | temp\syscalls_common.h 138 | temp\syscalls_common.c 139 | temp\syscalls_common_.asm 140 | Press a key to continue... 141 | 142 | ``` 143 | 144 | ## Importing into Visual Studio 145 | 146 | 1. Copy the generated H/C/ASM files into the project folder. 147 | 2. In Visual Studio, go to *Project* → *Build Customizations...* and enable MASM. 148 | 3. In the *Solution Explorer*, add the .h and .c/.asm files to the project as header and source files, respectively. 149 | 4. Go to the properties of the ASM file, and set the *Item Type* to *Microsoft Macro Assembler*. 150 | 151 | ## Compiling outside of Visual Studio 152 | 153 | ### Windows 154 | 155 | Makefile for 64 bits: 156 | 157 | `Makefile.msvc` 158 | ``` 159 | OPTIONS = -Zp8 -c -nologo -Gy -Os -O1 -GR- -EHa -Oi -GS- 160 | LIBS = libvcruntime.lib libcmt.lib ucrt.lib kernel32.lib 161 | 162 | program: 163 | ML64 /c syscalls-asm.x64.asm /link /NODEFAULTLIB /RELEASE /MACHINE:X64 164 | cl.exe $(OPTIONS) syscalls.c program.c 165 | link.exe /OUT:program.x64.exe -nologo $(LIBS) /MACHINE:X64 -subsystem:console -nodefaultlib syscalls-asm.x64.obj syscalls.obj program.obj 166 | ``` 167 | 168 | Makefile for 32 bits: 169 | 170 | `Makefile.msvc` 171 | ``` 172 | OPTIONS = -Zp8 -c -nologo -Gy -Os -O1 -GR- -EHa -Oi -GS- 173 | LIBS = libvcruntime.lib libcmt.lib ucrt.lib kernel32.lib 174 | 175 | program: 176 | ML /c syscalls-asm.x86.asm /link /NODEFAULTLIB /RELEASE /MACHINE:X86 177 | cl.exe $(OPTIONS) syscalls.c program.c 178 | link.exe /OUT:program.x86.exe -nologo $(LIBS) /MACHINE:X86 -subsystem:console -nodefaultlib syscalls-asm.x86.obj syscalls.obj program.obj 179 | ``` 180 | 181 | Compile with nmake: 182 | ``` 183 | nmake -f Makefile.msvc 184 | ``` 185 | 186 | ### Linux 187 | 188 | Makefile for both 64 and 32 bits: 189 | 190 | `Makefile.mingw` 191 | ``` 192 | CC_x64 := x86_64-w64-mingw32-gcc 193 | CC_x86 := i686-w64-mingw32-gcc 194 | OPTIONS := -masm=intel -Wall 195 | 196 | program: 197 | $(CC_x64) syscalls.c program.c -o program.x64.exe $(OPTIONS) 198 | $(CC_x86) syscalls.c program.c -o program.x86.exe $(OPTIONS) 199 | ``` 200 | 201 | Compile with make: 202 | ``` 203 | make -f Makefile.mingw 204 | ``` 205 | 206 | ## Caveats and Limitations 207 | 208 | - The Egg-Hunter functionality is not implemented within this tool, it is in [Inceptor][1]. 209 | - System calls from the graphical subsystem (`win32k.sys`) are not supported. 210 | - Tested on Visual Studio 2019/2022 with Windows 10 SDK. 211 | - Support for NASM is not guaranteed. 212 | - Support for GCC and MinGW is not guaranteed. 213 | 214 | ## Troubleshooting 215 | 216 | #### From SysWhispers2 217 | - Type redefinitions errors: a project may not compile if typedefs in `syscalls.h` have already been defined. 218 | - Ensure that only required functions are included (i.e. `--preset all` is rarely necessary). 219 | - If a typedef is already defined in another used header, then it could be removed from `syscalls.h`. 220 | 221 | #### New 222 | - With `--verbose`, it is possible to enable troubleshooting output during code generation. 223 | - With `--debug`, the tool will insert a software breakpoint in the syscall stub, to ease the debugging in WinDbg. 224 | - If you get a `error A2084:constant value too large` during compilation, regenerates the stubs. 225 | 226 | ## Credits 227 | 228 | #### SysWhispers2 229 | 230 | Developed by [@Jackson_T](https://twitter.com/Jackson_T) and [@modexpblog](https://twitter.com/modexpblog), 231 | but builds upon the work of many others: 232 | 233 | - [@FoxHex0ne](https://twitter.com/FoxHex0ne) for cataloguing many function prototypes and typedefs in a machine-readable format. 234 | - [@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. 235 | - [@Cn33liz](https://twitter.com/Cneelis) for the initial [Dumpert](https://github.com/outflanknl/Dumpert) POC implementation. 236 | 237 | #### SysWhispers2 (x86/WOW64) 238 | 239 | - [@rooster](https://github.com/mai1zhi2) for creating a sample x86/WOW64 compatible fork. 240 | 241 | #### Others 242 | 243 | - [@ElephantSe4l](https://mobile.twitter.com/elephantse4l) for the idea about randomizing the jumps to the syscalls. 244 | - [@S4ntiagoP](https://twitter.com/s4ntiago_p) for the incredible work on [nanodump](https://github.com/helpsystems/nanodump), which gave me tons of ideas. 245 | 246 | ## Licence 247 | 248 | As the original, this project is also licensed under the Apache License 2.0. 249 | 250 | 251 | [1]: https://github.com/klezVirus/inceptor 252 | [2]: https://klezvirus.github.io/RedTeaming/AV_Evasion/NoSysWhisper/ 253 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klezVirus/SysWhispers3/31cfc93c9466b52ae79d60925b0b5e0a1f653b88/__init__.py -------------------------------------------------------------------------------- /data/base.c: -------------------------------------------------------------------------------- 1 | #include ".h" 2 | #include 3 | 4 | //#define DEBUG 5 | 6 | // JUMPER 7 | 8 | #ifdef _M_IX86 9 | 10 | EXTERN_C PVOID internal_cleancall_wow64_gate(VOID) { 11 | return (PVOID)__readfsdword(0xC0); 12 | } 13 | 14 | // LOCAL_IS_WOW64 15 | 16 | #endif 17 | 18 | // Code below is adapted from @modexpblog. Read linked article for more details. 19 | // https://www.mdsec.co.uk/2020/12/bypassing-user-mode-hooks-and-direct-invocation-of-system-calls-for-red-teams 20 | 21 | SW3_SYSCALL_LIST SW3_SyscallList; 22 | 23 | // SEARCH_AND_REPLACE 24 | #ifdef SEARCH_AND_REPLACE 25 | // THIS IS NOT DEFINED HERE; don't know if I'll add it in a future release 26 | EXTERN void SearchAndReplace(unsigned char[], unsigned char[]); 27 | #endif 28 | 29 | DWORD SW3_HashSyscall(PCSTR FunctionName) 30 | { 31 | DWORD i = 0; 32 | DWORD Hash = SW3_SEED; 33 | 34 | while (FunctionName[i]) 35 | { 36 | WORD PartialName = *(WORD*)((ULONG_PTR)FunctionName + i++); 37 | Hash ^= PartialName + SW3_ROR8(Hash); 38 | } 39 | 40 | return Hash; 41 | } 42 | 43 | #ifndef JUMPER 44 | PVOID SC_Address(PVOID NtApiAddress) 45 | { 46 | return NULL; 47 | } 48 | #else 49 | PVOID SC_Address(PVOID NtApiAddress) 50 | { 51 | DWORD searchLimit = 512; 52 | PVOID SyscallAddress; 53 | 54 | #ifdef _WIN64 55 | // If the process is 64-bit on a 64-bit OS, we need to search for syscall 56 | BYTE syscall_code[] = { 0x0f, 0x05, 0xc3 }; 57 | ULONG distance_to_syscall = 0x12; 58 | #else 59 | // If the process is 32-bit on a 32-bit OS, we need to search for sysenter 60 | BYTE syscall_code[] = { 0x0f, 0x34, 0xc3 }; 61 | ULONG distance_to_syscall = 0x0f; 62 | #endif 63 | 64 | #ifdef _M_IX86 65 | // If the process is 32-bit on a 64-bit OS, we need to jump to WOW32Reserved 66 | if (local_is_wow64()) 67 | { 68 | #ifdef DEBUG 69 | printf("[+] Running 32-bit app on x64 (WOW64)\n"); 70 | #endif 71 | // JUMP_TO_WOW32Reserved 72 | } 73 | #endif 74 | 75 | // we don't really care if there is a 'jmp' between 76 | // NtApiAddress and the 'syscall; ret' instructions 77 | SyscallAddress = SW3_RVA2VA(PVOID, NtApiAddress, distance_to_syscall); 78 | 79 | if (!memcmp((PVOID)syscall_code, SyscallAddress, sizeof(syscall_code))) 80 | { 81 | // we can use the original code for this system call :) 82 | #if defined(DEBUG) 83 | printf("Found Syscall Opcodes at address 0x%p\n", SyscallAddress); 84 | #endif 85 | return SyscallAddress; 86 | } 87 | 88 | // the 'syscall; ret' intructions have not been found, 89 | // we will try to use one near it, similarly to HalosGate 90 | 91 | for (ULONG32 num_jumps = 1; num_jumps < searchLimit; num_jumps++) 92 | { 93 | // let's try with an Nt* API below our syscall 94 | SyscallAddress = SW3_RVA2VA( 95 | PVOID, 96 | NtApiAddress, 97 | distance_to_syscall + num_jumps * 0x20); 98 | if (!memcmp((PVOID)syscall_code, SyscallAddress, sizeof(syscall_code))) 99 | { 100 | #if defined(DEBUG) 101 | printf("Found Syscall Opcodes at address 0x%p\n", SyscallAddress); 102 | #endif 103 | return SyscallAddress; 104 | } 105 | 106 | // let's try with an Nt* API above our syscall 107 | SyscallAddress = SW3_RVA2VA( 108 | PVOID, 109 | NtApiAddress, 110 | distance_to_syscall - num_jumps * 0x20); 111 | if (!memcmp((PVOID)syscall_code, SyscallAddress, sizeof(syscall_code))) 112 | { 113 | #if defined(DEBUG) 114 | printf("Found Syscall Opcodes at address 0x%p\n", SyscallAddress); 115 | #endif 116 | return SyscallAddress; 117 | } 118 | } 119 | 120 | #ifdef DEBUG 121 | printf("Syscall Opcodes not found!\n"); 122 | #endif 123 | 124 | return NULL; 125 | } 126 | #endif 127 | 128 | 129 | BOOL SW3_PopulateSyscallList() 130 | { 131 | // Return early if the list is already populated. 132 | if (SW3_SyscallList.Count) return TRUE; 133 | 134 | #ifdef _WIN64 135 | PSW3_PEB Peb = (PSW3_PEB)__readgsqword(0x60); 136 | #else 137 | PSW3_PEB Peb = (PSW3_PEB)__readfsdword(0x30); 138 | #endif 139 | PSW3_PEB_LDR_DATA Ldr = Peb->Ldr; 140 | PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL; 141 | PVOID DllBase = NULL; 142 | 143 | // Get the DllBase address of NTDLL.dll. NTDLL is not guaranteed to be the second 144 | // in the list, so it's safer to loop through the full list and find it. 145 | PSW3_LDR_DATA_TABLE_ENTRY LdrEntry; 146 | for (LdrEntry = (PSW3_LDR_DATA_TABLE_ENTRY)Ldr->Reserved2[1]; LdrEntry->DllBase != NULL; LdrEntry = (PSW3_LDR_DATA_TABLE_ENTRY)LdrEntry->Reserved1[0]) 147 | { 148 | DllBase = LdrEntry->DllBase; 149 | PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)DllBase; 150 | PIMAGE_NT_HEADERS NtHeaders = SW3_RVA2VA(PIMAGE_NT_HEADERS, DllBase, DosHeader->e_lfanew); 151 | PIMAGE_DATA_DIRECTORY DataDirectory = (PIMAGE_DATA_DIRECTORY)NtHeaders->OptionalHeader.DataDirectory; 152 | DWORD VirtualAddress = DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; 153 | if (VirtualAddress == 0) continue; 154 | 155 | ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)SW3_RVA2VA(ULONG_PTR, DllBase, VirtualAddress); 156 | 157 | // If this is NTDLL.dll, exit loop. 158 | PCHAR DllName = SW3_RVA2VA(PCHAR, DllBase, ExportDirectory->Name); 159 | 160 | if ((*(ULONG*)DllName | 0x20202020) != 0x6c64746e) continue; 161 | if ((*(ULONG*)(DllName + 4) | 0x20202020) == 0x6c642e6c) break; 162 | } 163 | 164 | if (!ExportDirectory) return FALSE; 165 | 166 | DWORD NumberOfNames = ExportDirectory->NumberOfNames; 167 | PDWORD Functions = SW3_RVA2VA(PDWORD, DllBase, ExportDirectory->AddressOfFunctions); 168 | PDWORD Names = SW3_RVA2VA(PDWORD, DllBase, ExportDirectory->AddressOfNames); 169 | PWORD Ordinals = SW3_RVA2VA(PWORD, DllBase, ExportDirectory->AddressOfNameOrdinals); 170 | 171 | // Populate SW3_SyscallList with unsorted Zw* entries. 172 | DWORD i = 0; 173 | PSW3_SYSCALL_ENTRY Entries = SW3_SyscallList.Entries; 174 | do 175 | { 176 | PCHAR FunctionName = SW3_RVA2VA(PCHAR, DllBase, Names[NumberOfNames - 1]); 177 | 178 | // Is this a system call? 179 | if (*(USHORT*)FunctionName == 0x775a) 180 | { 181 | Entries[i].Hash = SW3_HashSyscall(FunctionName); 182 | Entries[i].Address = Functions[Ordinals[NumberOfNames - 1]]; 183 | Entries[i].SyscallAddress = SC_Address(SW3_RVA2VA(PVOID, DllBase, Entries[i].Address)); 184 | 185 | i++; 186 | if (i == SW3_MAX_ENTRIES) break; 187 | } 188 | } while (--NumberOfNames); 189 | 190 | // Save total number of system calls found. 191 | SW3_SyscallList.Count = i; 192 | 193 | // Sort the list by address in ascending order. 194 | for (DWORD i = 0; i < SW3_SyscallList.Count - 1; i++) 195 | { 196 | for (DWORD j = 0; j < SW3_SyscallList.Count - i - 1; j++) 197 | { 198 | if (Entries[j].Address > Entries[j + 1].Address) 199 | { 200 | // Swap entries. 201 | SW3_SYSCALL_ENTRY TempEntry; 202 | 203 | TempEntry.Hash = Entries[j].Hash; 204 | TempEntry.Address = Entries[j].Address; 205 | TempEntry.SyscallAddress = Entries[j].SyscallAddress; 206 | 207 | Entries[j].Hash = Entries[j + 1].Hash; 208 | Entries[j].Address = Entries[j + 1].Address; 209 | Entries[j].SyscallAddress = Entries[j + 1].SyscallAddress; 210 | 211 | Entries[j + 1].Hash = TempEntry.Hash; 212 | Entries[j + 1].Address = TempEntry.Address; 213 | Entries[j + 1].SyscallAddress = TempEntry.SyscallAddress; 214 | } 215 | } 216 | } 217 | 218 | return TRUE; 219 | } 220 | 221 | EXTERN_C DWORD SW3_GetSyscallNumber(DWORD FunctionHash) 222 | { 223 | // Ensure SW3_SyscallList is populated. 224 | if (!SW3_PopulateSyscallList()) return -1; 225 | 226 | for (DWORD i = 0; i < SW3_SyscallList.Count; i++) 227 | { 228 | if (FunctionHash == SW3_SyscallList.Entries[i].Hash) 229 | { 230 | return i; 231 | } 232 | } 233 | 234 | return -1; 235 | } 236 | 237 | EXTERN_C PVOID SW3_GetSyscallAddress(DWORD FunctionHash) 238 | { 239 | // Ensure SW3_SyscallList is populated. 240 | if (!SW3_PopulateSyscallList()) return NULL; 241 | 242 | for (DWORD i = 0; i < SW3_SyscallList.Count; i++) 243 | { 244 | if (FunctionHash == SW3_SyscallList.Entries[i].Hash) 245 | { 246 | return SW3_SyscallList.Entries[i].SyscallAddress; 247 | } 248 | } 249 | 250 | return NULL; 251 | } 252 | 253 | EXTERN_C PVOID SW3_GetRandomSyscallAddress(DWORD FunctionHash) 254 | { 255 | // Ensure SW3_SyscallList is populated. 256 | if (!SW3_PopulateSyscallList()) return NULL; 257 | 258 | DWORD index = ((DWORD) rand()) % SW3_SyscallList.Count; 259 | 260 | while (FunctionHash == SW3_SyscallList.Entries[index].Hash){ 261 | // Spoofing the syscall return address 262 | index = ((DWORD) rand()) % SW3_SyscallList.Count; 263 | } 264 | return SW3_SyscallList.Entries[index].SyscallAddress; 265 | } 266 | -------------------------------------------------------------------------------- /data/base.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Code below is adapted from @modexpblog. Read linked article for more details. 4 | // https://www.mdsec.co.uk/2020/12/bypassing-user-mode-hooks-and-direct-invocation-of-system-calls-for-red-teams 5 | 6 | #ifndef SW3_HEADER_H_ 7 | #define SW3_HEADER_H_ 8 | 9 | #include 10 | 11 | #ifndef _NTDEF_ 12 | typedef _Return_type_success_(return >= 0) LONG NTSTATUS; 13 | typedef NTSTATUS* PNTSTATUS; 14 | #endif 15 | 16 | #define SW3_SEED 17 | #define SW3_ROL8(v) (v << 8 | v >> 24) 18 | #define SW3_ROR8(v) (v >> 8 | v << 24) 19 | #define SW3_ROX8(v) ((SW3_SEED % 2) ? SW3_ROL8(v) : SW3_ROR8(v)) 20 | #define SW3_MAX_ENTRIES 600 21 | #define SW3_RVA2VA(Type, DllBase, Rva) (Type)((ULONG_PTR) DllBase + Rva) 22 | 23 | // Typedefs are prefixed to avoid pollution. 24 | 25 | typedef struct _SW3_SYSCALL_ENTRY 26 | { 27 | DWORD Hash; 28 | DWORD Address; 29 | PVOID SyscallAddress; 30 | } SW3_SYSCALL_ENTRY, *PSW3_SYSCALL_ENTRY; 31 | 32 | typedef struct _SW3_SYSCALL_LIST 33 | { 34 | DWORD Count; 35 | SW3_SYSCALL_ENTRY Entries[SW3_MAX_ENTRIES]; 36 | } SW3_SYSCALL_LIST, *PSW3_SYSCALL_LIST; 37 | 38 | typedef struct _SW3_PEB_LDR_DATA { 39 | BYTE Reserved1[8]; 40 | PVOID Reserved2[3]; 41 | LIST_ENTRY InMemoryOrderModuleList; 42 | } SW3_PEB_LDR_DATA, *PSW3_PEB_LDR_DATA; 43 | 44 | typedef struct _SW3_LDR_DATA_TABLE_ENTRY { 45 | PVOID Reserved1[2]; 46 | LIST_ENTRY InMemoryOrderLinks; 47 | PVOID Reserved2[2]; 48 | PVOID DllBase; 49 | } SW3_LDR_DATA_TABLE_ENTRY, *PSW3_LDR_DATA_TABLE_ENTRY; 50 | 51 | typedef struct _SW3_PEB { 52 | BYTE Reserved1[2]; 53 | BYTE BeingDebugged; 54 | BYTE Reserved2[1]; 55 | PVOID Reserved3[2]; 56 | PSW3_PEB_LDR_DATA Ldr; 57 | } SW3_PEB, *PSW3_PEB; 58 | 59 | DWORD SW3_HashSyscall(PCSTR FunctionName); 60 | BOOL SW3_PopulateSyscallList(); 61 | EXTERN_C DWORD SW3_GetSyscallNumber(DWORD FunctionHash); 62 | EXTERN_C PVOID SW3_GetSyscallAddress(DWORD FunctionHash); 63 | EXTERN_C PVOID internal_cleancall_wow64_gate(VOID); 64 | -------------------------------------------------------------------------------- /data/typedefs.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "identifiers": ["MEM_EXTENDED_PARAMETER_TYPE", "PMEM_EXTENDED_PARAMETER_TYPE"], 4 | "dependencies": [], 5 | "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;" 6 | }, 7 | { 8 | "identifiers": ["IO_STATUS_BLOCK", "PIO_STATUS_BLOCK"], 9 | "dependencies": [], 10 | "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;" 11 | }, 12 | { 13 | "identifiers": ["KEY_VALUE_ENTRY", "PKEY_VALUE_ENTRY"], 14 | "dependencies": ["PUNICODE_STRING"], 15 | "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;" 16 | }, 17 | { 18 | "identifiers": ["KEY_SET_INFORMATION_CLASS", "PKEY_SET_INFORMATION_CLASS"], 19 | "dependencies": [], 20 | "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;" 21 | }, 22 | { 23 | "identifiers": ["SYSTEM_HANDLE", "PSYSTEM_HANDLE"], 24 | "dependencies": [], 25 | "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;" 26 | }, 27 | { 28 | "identifiers": ["SYSTEM_HANDLE_INFORMATION", "PSYSTEM_HANDLE_INFORMATION"], 29 | "dependencies": ["SYSTEM_HANDLE"], 30 | "definition": "typedef struct _SYSTEM_HANDLE_INFORMATION\n{\n\tULONG HandleCount;\n\tSYSTEM_HANDLE Handles[1];\n} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;" 31 | }, 32 | { 33 | "identifiers": ["SYSTEM_INFORMATION_CLASS", "PSYSTEM_INFORMATION_CLASS"], 34 | "dependencies": ["SYSTEM_HANDLE_INFORMATION"], 35 | "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;" 36 | }, 37 | { 38 | "identifiers": ["PROCESSINFOCLASS", "PPROCESSINFOCLASS"], 39 | "dependencies": [], 40 | "definition": "typedef enum _PROCESSINFOCLASS\n{\n\tProcessBasicInformation = 0,\n\tProcessDebugPort = 7,\n\tProcessWow64Information = 26,\n\tProcessImageFileName = 27,\n\tProcessBreakOnTermination = 29\n} PROCESSINFOCLASS, *PPROCESSINFOCLASS;" 41 | }, 42 | { 43 | "identifiers": ["MEMORY_RANGE_ENTRY", "PMEMORY_RANGE_ENTRY"], 44 | "dependencies": [], 45 | "definition": "typedef struct _MEMORY_RANGE_ENTRY\n{\n\tPVOID VirtualAddress;\n\tSIZE_T NumberOfBytes;\n} MEMORY_RANGE_ENTRY, *PMEMORY_RANGE_ENTRY;" 46 | }, 47 | { 48 | "identifiers": ["T2_SET_PARAMETERS", "PT2_SET_PARAMETERS"], 49 | "dependencies": [], 50 | "definition": "typedef struct _T2_SET_PARAMETERS_V0\n{\n\tULONG Version;\n\tULONG Reserved;\n\tLONGLONG NoWakeTolerance;\n} T2_SET_PARAMETERS, *PT2_SET_PARAMETERS;" 51 | }, 52 | { 53 | "identifiers": ["FILE_PATH", "PFILE_PATH"], 54 | "dependencies": [], 55 | "definition": "typedef struct _FILE_PATH\n{\n\tULONG Version;\n\tULONG Length;\n\tULONG Type;\n\tCHAR FilePath[1];\n} FILE_PATH, *PFILE_PATH;" 56 | }, 57 | { 58 | "identifiers": ["FILE_USER_QUOTA_INFORMATION", "PFILE_USER_QUOTA_INFORMATION"], 59 | "dependencies": [], 60 | "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;" 61 | }, 62 | { 63 | "identifiers": ["FILE_QUOTA_LIST_INFORMATION", "PFILE_QUOTA_LIST_INFORMATION"], 64 | "dependencies": [], 65 | "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;" 66 | }, 67 | { 68 | "identifiers": ["FILE_NETWORK_OPEN_INFORMATION", "PFILE_NETWORK_OPEN_INFORMATION"], 69 | "dependencies": [], 70 | "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;" 71 | }, 72 | { 73 | "identifiers": ["FILTER_BOOT_OPTION_OPERATION", "PFILTER_BOOT_OPTION_OPERATION"], 74 | "dependencies": [], 75 | "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;" 76 | }, 77 | { 78 | "identifiers": ["EVENT_TYPE", "PEVENT_TYPE"], 79 | "dependencies": [], 80 | "definition": "typedef enum _EVENT_TYPE\n{\n\tNotificationEvent = 0,\n\tSynchronizationEvent = 1,\n} EVENT_TYPE, *PEVENT_TYPE;" 81 | }, 82 | { 83 | "identifiers": ["FILE_FULL_EA_INFORMATION", "PFILE_FULL_EA_INFORMATION"], 84 | "dependencies": [], 85 | "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;" 86 | }, 87 | { 88 | "identifiers": ["FILE_GET_EA_INFORMATION", "PFILE_GET_EA_INFORMATION"], 89 | "dependencies": [], 90 | "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;" 91 | }, 92 | { 93 | "identifiers": ["BOOT_OPTIONS", "PBOOT_OPTIONS"], 94 | "dependencies": [], 95 | "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;" 96 | }, 97 | { 98 | "identifiers": ["WNF_CHANGE_STAMP", "PWNF_CHANGE_STAMP"], 99 | "dependencies": [], 100 | "definition": "typedef ULONG WNF_CHANGE_STAMP, *PWNF_CHANGE_STAMP;" 101 | }, 102 | { 103 | "identifiers": ["WNF_DATA_SCOPE", "PWNF_DATA_SCOPE"], 104 | "dependencies": [], 105 | "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;" 106 | }, 107 | { 108 | "identifiers": ["WNF_STATE_NAME_LIFETIME", "PWNF_STATE_NAME_LIFETIME"], 109 | "dependencies": [], 110 | "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;" 111 | }, 112 | { 113 | "identifiers": ["VIRTUAL_MEMORY_INFORMATION_CLASS", "PVIRTUAL_MEMORY_INFORMATION_CLASS"], 114 | "dependencies": [], 115 | "definition": "typedef enum _VIRTUAL_MEMORY_INFORMATION_CLASS\n{\n\tVmPrefetchInformation,\n\tVmPagePriorityInformation,\n\tVmCfgCallTargetInformation\n} VIRTUAL_MEMORY_INFORMATION_CLASS, *PVIRTUAL_MEMORY_INFORMATION_CLASS;" 116 | }, 117 | { 118 | "identifiers": ["IO_SESSION_EVENT", "PIO_SESSION_EVENT"], 119 | "dependencies": [], 120 | "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;" 121 | }, 122 | { 123 | "identifiers": ["PORT_INFORMATION_CLASS", "PPORT_INFORMATION_CLASS"], 124 | "dependencies": [], 125 | "definition": "typedef enum _PORT_INFORMATION_CLASS\n{\n\tPortBasicInformation,\n#if DEVL\n\tPortDumpInformation\n#endif\n} PORT_INFORMATION_CLASS, *PPORT_INFORMATION_CLASS;" 126 | }, 127 | { 128 | "identifiers": ["PLUGPLAY_CONTROL_CLASS", "PPLUGPLAY_CONTROL_CLASS"], 129 | "dependencies": [], 130 | "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;" 131 | }, 132 | { 133 | "identifiers": ["IO_COMPLETION_INFORMATION_CLASS", "PIO_COMPLETION_INFORMATION_CLASS"], 134 | "dependencies": [], 135 | "definition": "typedef enum _IO_COMPLETION_INFORMATION_CLASS\n{\n\tIoCompletionBasicInformation\n} IO_COMPLETION_INFORMATION_CLASS, *PIO_COMPLETION_INFORMATION_CLASS;" 136 | }, 137 | { 138 | "identifiers": ["SECTION_INHERIT", "PSECTION_INHERIT"], 139 | "dependencies": [], 140 | "definition": "typedef enum _SECTION_INHERIT\n{\n\tViewShare = 1,\n\tViewUnmap = 2\n} SECTION_INHERIT, *PSECTION_INHERIT;" 141 | }, 142 | { 143 | "identifiers": ["PS_ATTRIBUTE", "PPS_ATTRIBUTE"], 144 | "dependencies": [], 145 | "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;" 146 | }, 147 | { 148 | "identifiers": ["DEBUGOBJECTINFOCLASS", "PDEBUGOBJECTINFOCLASS"], 149 | "dependencies": [], 150 | "definition": "typedef enum _DEBUGOBJECTINFOCLASS\n{\n\tDebugObjectFlags = 1,\n\tMaxDebugObjectInfoClass\n} DEBUGOBJECTINFOCLASS, *PDEBUGOBJECTINFOCLASS;" 151 | }, 152 | { 153 | "identifiers": ["SEMAPHORE_INFORMATION_CLASS", "PSEMAPHORE_INFORMATION_CLASS"], 154 | "dependencies": [], 155 | "definition": "typedef enum _SEMAPHORE_INFORMATION_CLASS\n{\n\tSemaphoreBasicInformation\n} SEMAPHORE_INFORMATION_CLASS, *PSEMAPHORE_INFORMATION_CLASS;" 156 | }, 157 | { 158 | "identifiers": ["PS_ATTRIBUTE_LIST", "PPS_ATTRIBUTE_LIST"], 159 | "dependencies": ["PS_ATTRIBUTE"], 160 | "definition": "typedef struct _PS_ATTRIBUTE_LIST\n{\n\tSIZE_T TotalLength;\n\tPS_ATTRIBUTE Attributes[1];\n} PS_ATTRIBUTE_LIST, *PPS_ATTRIBUTE_LIST;" 161 | }, 162 | { 163 | "identifiers": ["VDMSERVICECLASS"], 164 | "dependencies": [], 165 | "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;" 166 | }, 167 | { 168 | "identifiers": ["PS_CREATE_STATE", "PPS_CREATE_STATE"], 169 | "dependencies": [], 170 | "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;" 171 | }, 172 | { 173 | "identifiers": ["PS_CREATE_INFO", "PPS_CREATE_INFO"], 174 | "dependencies": ["PS_CREATE_STATE"], 175 | "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;" 176 | }, 177 | { 178 | "identifiers": ["MEMORY_INFORMATION_CLASS", "PMEMORY_INFORMATION_CLASS"], 179 | "dependencies": [], 180 | "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;" 181 | }, 182 | { 183 | "identifiers": ["MEMORY_RESERVE_TYPE", "PMEMORY_RESERVE_TYPE"], 184 | "dependencies": [], 185 | "definition": "typedef enum _MEMORY_RESERVE_TYPE\n{\n\tMemoryReserveUserApc,\n\tMemoryReserveIoCompletion,\n\tMemoryReserveTypeMax\n} MEMORY_RESERVE_TYPE, *PMEMORY_RESERVE_TYPE;" 186 | }, 187 | { 188 | "identifiers": ["ALPC_PORT_INFORMATION_CLASS", "PALPC_PORT_INFORMATION_CLASS"], 189 | "dependencies": [], 190 | "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;" 191 | }, 192 | { 193 | "identifiers": ["ALPC_CONTEXT_ATTR", "PALPC_CONTEXT_ATTR"], 194 | "dependencies": [], 195 | "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;" 196 | }, 197 | { 198 | "identifiers": ["ALPC_DATA_VIEW_ATTR", "PALPC_DATA_VIEW_ATTR"], 199 | "dependencies": [], 200 | "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;" 201 | }, 202 | { 203 | "identifiers": ["ALPC_SECURITY_ATTR", "PALPC_SECURITY_ATTR"], 204 | "dependencies": [], 205 | "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;" 206 | }, 207 | { 208 | "identifiers": ["PPVOID"], 209 | "dependencies": [], 210 | "definition": "typedef PVOID* PPVOID;" 211 | }, 212 | { 213 | "identifiers": ["KPROFILE_SOURCE", "PKPROFILE_SOURCE"], 214 | "dependencies": [], 215 | "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;" 216 | }, 217 | { 218 | "identifiers": ["ALPC_MESSAGE_INFORMATION_CLASS", "PALPC_MESSAGE_INFORMATION_CLASS"], 219 | "dependencies": [], 220 | "definition": "typedef enum _ALPC_MESSAGE_INFORMATION_CLASS\n{\n\tAlpcMessageSidInformation,\n\tAlpcMessageTokenModifiedIdInformation\n} ALPC_MESSAGE_INFORMATION_CLASS, *PALPC_MESSAGE_INFORMATION_CLASS;" 221 | }, 222 | { 223 | "identifiers": ["WORKERFACTORYINFOCLASS", "PWORKERFACTORYINFOCLASS"], 224 | "dependencies": [], 225 | "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;" 226 | }, 227 | { 228 | "identifiers": ["MEMORY_PARTITION_INFORMATION_CLASS", "PMEMORY_PARTITION_INFORMATION_CLASS"], 229 | "dependencies": [], 230 | "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;" 231 | }, 232 | { 233 | "identifiers": ["MUTANT_INFORMATION_CLASS", "PMUTANT_INFORMATION_CLASS"], 234 | "dependencies": [], 235 | "definition": "typedef enum _MUTANT_INFORMATION_CLASS\n{\n\tMutantBasicInformation,\n\tMutantOwnerInformation\n} MUTANT_INFORMATION_CLASS, *PMUTANT_INFORMATION_CLASS;" 236 | }, 237 | { 238 | "identifiers": ["ATOM_INFORMATION_CLASS", "PATOM_INFORMATION_CLASS"], 239 | "dependencies": [], 240 | "definition": "typedef enum _ATOM_INFORMATION_CLASS\n{\n\tAtomBasicInformation,\n\tAtomTableInformation\n} ATOM_INFORMATION_CLASS, *PATOM_INFORMATION_CLASS;" 241 | }, 242 | { 243 | "identifiers": ["SHUTDOWN_ACTION"], 244 | "dependencies": [], 245 | "definition": "typedef enum _SHUTDOWN_ACTION {\n\tShutdownNoReboot,\n\tShutdownReboot,\n\tShutdownPowerOff\n} SHUTDOWN_ACTION;" 246 | }, 247 | { 248 | "identifiers": ["PTIMER_APC_ROUTINE"], 249 | "dependencies": [], 250 | "definition": "typedef VOID(CALLBACK* PTIMER_APC_ROUTINE)(\n\tIN PVOID TimerContext,\n\tIN ULONG TimerLowValue,\n\tIN LONG TimerHighValue);" 251 | }, 252 | { 253 | "identifiers": ["KEY_VALUE_INFORMATION_CLASS"], 254 | "dependencies": [], 255 | "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;" 256 | }, 257 | { 258 | "identifiers": ["PLANGID"], 259 | "dependencies": [], 260 | "definition": "typedef LANGID* PLANGID;" 261 | }, 262 | { 263 | "identifiers": ["PLUGPLAY_EVENT_CATEGORY", "PPLUGPLAY_EVENT_CATEGORY"], 264 | "dependencies": [], 265 | "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;" 266 | }, 267 | { 268 | "identifiers": ["PNP_VETO_TYPE", "PPNP_VETO_TYPE"], 269 | "dependencies": [], 270 | "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;" 271 | }, 272 | { 273 | "identifiers": ["PLUGPLAY_EVENT_BLOCK", "PPLUGPLAY_EVENT_BLOCK"], 274 | "dependencies": ["PLUGPLAY_EVENT_CATEGORY", "PNP_VETO_TYPE"], 275 | "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]; // DeviceIdVetoName\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;" 276 | }, 277 | { 278 | "identifiers": ["PIO_APC_ROUTINE"], 279 | "dependencies": ["PIO_STATUS_BLOCK"], 280 | "definition": "typedef VOID(NTAPI* PIO_APC_ROUTINE) (\n\tIN PVOID ApcContext,\n\tIN PIO_STATUS_BLOCK IoStatusBlock,\n\tIN ULONG Reserved);" 281 | }, 282 | { 283 | "identifiers": ["KNORMAL_ROUTINE"], 284 | "dependencies": [], 285 | "definition": "typedef VOID(KNORMAL_ROUTINE) (\n\tIN PVOID NormalContext,\n\tIN PVOID SystemArgument1,\n\tIN PVOID SystemArgument2);" 286 | }, 287 | { 288 | "identifiers": ["PKNORMAL_ROUTINE"], 289 | "dependencies": ["KNORMAL_ROUTINE"], 290 | "definition": "typedef KNORMAL_ROUTINE* PKNORMAL_ROUTINE;" 291 | }, 292 | { 293 | "identifiers": ["DIRECTORY_NOTIFY_INFORMATION_CLASS", "PDIRECTORY_NOTIFY_INFORMATION_CLASS"], 294 | "dependencies": [], 295 | "definition": "typedef enum _DIRECTORY_NOTIFY_INFORMATION_CLASS\n{\n\tDirectoryNotifyInformation = 1,\n\tDirectoryNotifyExtendedInformation = 2,\n} DIRECTORY_NOTIFY_INFORMATION_CLASS, *PDIRECTORY_NOTIFY_INFORMATION_CLASS;" 296 | }, 297 | { 298 | "identifiers": ["EVENT_INFORMATION_CLASS", "PEVENT_INFORMATION_CLASS"], 299 | "dependencies": [], 300 | "definition": "typedef enum _EVENT_INFORMATION_CLASS\n{\n\tEventBasicInformation\n} EVENT_INFORMATION_CLASS, *PEVENT_INFORMATION_CLASS;" 301 | }, 302 | { 303 | "identifiers": ["ALPC_MESSAGE_ATTRIBUTES", "PALPC_MESSAGE_ATTRIBUTES"], 304 | "dependencies": [], 305 | "definition": "typedef struct _ALPC_MESSAGE_ATTRIBUTES\n{\n\tunsigned long AllocatedAttributes;\n\tunsigned long ValidAttributes;\n} ALPC_MESSAGE_ATTRIBUTES, *PALPC_MESSAGE_ATTRIBUTES;" 306 | }, 307 | { 308 | "identifiers": ["ALPC_PORT_ATTRIBUTES", "PALPC_PORT_ATTRIBUTES"], 309 | "dependencies": [], 310 | "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;" 311 | }, 312 | { 313 | "identifiers": ["IO_SESSION_STATE", "PIO_SESSION_STATE"], 314 | "dependencies": [], 315 | "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;" 316 | }, 317 | { 318 | "identifiers": ["WNF_STATE_NAME", "PWNF_STATE_NAME"], 319 | "dependencies": [], 320 | "definition": "typedef struct _WNF_STATE_NAME\n{\n\tULONG Data[2];\n} WNF_STATE_NAME, *PWNF_STATE_NAME;" 321 | }, 322 | { 323 | "identifiers": ["PCWNF_STATE_NAME"], 324 | "dependencies": ["WNF_STATE_NAME"], 325 | "definition": "typedef const WNF_STATE_NAME *PCWNF_STATE_NAME;" 326 | }, 327 | { 328 | "identifiers": ["WNF_TYPE_ID", "PWNF_TYPE_ID"], 329 | "dependencies": [], 330 | "definition": "typedef struct _WNF_TYPE_ID\n{\n\tGUID TypeId;\n} WNF_TYPE_ID, *PWNF_TYPE_ID;" 331 | }, 332 | { 333 | "identifiers": ["PCWNF_TYPE_ID"], 334 | "dependencies": ["WNF_TYPE_ID"], 335 | "definition": "typedef const WNF_TYPE_ID *PCWNF_TYPE_ID;" 336 | }, 337 | { 338 | "identifiers": ["WNF_DELIVERY_DESCRIPTOR", "PWNF_DELIVERY_DESCRIPTOR"], 339 | "dependencies": ["WNF_STATE_NAME", "WNF_TYPE_ID"], 340 | "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;" 341 | }, 342 | { 343 | "identifiers": ["DEBUG_CONTROL_CODE", "PPDEBUG_CONTROL_CODE"], 344 | "dependencies": [], 345 | "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;" 346 | }, 347 | { 348 | "identifiers": ["CLIENT_ID", "PCLIENT_ID"], 349 | "dependencies": [], 350 | "definition": "typedef struct _CLIENT_ID\n{\n\tHANDLE UniqueProcess;\n\tHANDLE UniqueThread;\n} CLIENT_ID, *PCLIENT_ID;" 351 | }, 352 | { 353 | "identifiers": ["PORT_MESSAGE", "PPORT_MESSAGE"], 354 | "dependencies": ["CLIENT_ID"], 355 | "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;" 356 | }, 357 | { 358 | "identifiers": ["FILE_BASIC_INFORMATION", "PFILE_BASIC_INFORMATION"], 359 | "dependencies": [], 360 | "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;" 361 | }, 362 | { 363 | "identifiers": ["PORT_SECTION_READ", "PPORT_SECTION_READ"], 364 | "dependencies": [], 365 | "definition": "typedef struct _PORT_SECTION_READ\n{\n\tULONG Length;\n\tULONG ViewSize;\n\tULONG ViewBase;\n} PORT_SECTION_READ, *PPORT_SECTION_READ;" 366 | }, 367 | { 368 | "identifiers": ["PORT_SECTION_WRITE", "PPORT_SECTION_WRITE"], 369 | "dependencies": [], 370 | "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;" 371 | }, 372 | { 373 | "identifiers": ["TIMER_TYPE", "PTIMER_TYPE"], 374 | "dependencies": [], 375 | "definition": "typedef enum _TIMER_TYPE\n{\n\tNotificationTimer,\n\tSynchronizationTimer\n} TIMER_TYPE, *PTIMER_TYPE;" 376 | }, 377 | { 378 | "identifiers": ["BOOT_ENTRY", "PBOOT_ENTRY"], 379 | "dependencies": [], 380 | "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;" 381 | }, 382 | { 383 | "identifiers": ["EFI_DRIVER_ENTRY", "PEFI_DRIVER_ENTRY"], 384 | "dependencies": [], 385 | "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;" 386 | }, 387 | { 388 | "identifiers": ["RTL_ATOM", "PRTL_ATOM"], 389 | "dependencies": [], 390 | "definition": "typedef USHORT RTL_ATOM, *PRTL_ATOM;" 391 | }, 392 | { 393 | "identifiers": ["TIMER_SET_INFORMATION_CLASS", "PTIMER_SET_INFORMATION_CLASS"], 394 | "dependencies": [], 395 | "definition": "typedef enum _TIMER_SET_INFORMATION_CLASS\n{\n\tTimerSetCoalescableTimer,\n\tMaxTimerInfoClass\n} TIMER_SET_INFORMATION_CLASS, *PTIMER_SET_INFORMATION_CLASS;" 396 | }, 397 | { 398 | "identifiers": ["FSINFOCLASS", "PFSINFOCLASS"], 399 | "dependencies": [], 400 | "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;" 401 | }, 402 | { 403 | "identifiers": ["WAIT_TYPE", "PWAIT_TYPE"], 404 | "dependencies": [], 405 | "definition": "typedef enum _WAIT_TYPE\n{\n\tWaitAll = 0,\n\tWaitAny = 1\n} WAIT_TYPE, *PWAIT_TYPE;" 406 | }, 407 | { 408 | "identifiers": ["USER_STACK", "PUSER_STACK"], 409 | "dependencies": [], 410 | "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;" 411 | }, 412 | { 413 | "identifiers": ["SECTION_INFORMATION_CLASS", "PSECTION_INFORMATION_CLASS"], 414 | "dependencies": [], 415 | "definition": "typedef enum _SECTION_INFORMATION_CLASS\n{\n\tSectionBasicInformation,\n\tSectionImageInformation,\n} SECTION_INFORMATION_CLASS, *PSECTION_INFORMATION_CLASS;" 416 | }, 417 | { 418 | "identifiers": ["APPHELPCACHESERVICECLASS", "PAPPHELPCACHESERVICECLASS"], 419 | "dependencies": [], 420 | "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;" 421 | }, 422 | { 423 | "identifiers": ["TOKEN_SECURITY_ATTRIBUTE_FQBN_VALUE", "PTOKEN_SECURITY_ATTRIBUTE_FQBN_VALUE"], 424 | "dependencies": ["UNICODE_STRING"], 425 | "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;" 426 | }, 427 | { 428 | "identifiers": ["TOKEN_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE", "PTOKEN_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE"], 429 | "dependencies": [], 430 | "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;" 431 | }, 432 | { 433 | "identifiers": ["TOKEN_SECURITY_ATTRIBUTE_V1", "PTOKEN_SECURITY_ATTRIBUTE_V1"], 434 | "dependencies": ["PUNICODE_STRING", "PTOKEN_SECURITY_ATTRIBUTE_FQBN_VALUE", "PTOKEN_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE"], 435 | "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;" 436 | }, 437 | { 438 | "identifiers": ["TOKEN_SECURITY_ATTRIBUTES_INFORMATION", "PTOKEN_SECURITY_ATTRIBUTES_INFORMATION"], 439 | "dependencies": ["PTOKEN_SECURITY_ATTRIBUTE_V1"], 440 | "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;" 441 | }, 442 | { 443 | "identifiers": ["FILE_IO_COMPLETION_INFORMATION", "PFILE_IO_COMPLETION_INFORMATION"], 444 | "dependencies": [], 445 | "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;" 446 | }, 447 | { 448 | "identifiers": ["PT2_CANCEL_PARAMETERS"], 449 | "dependencies": [], 450 | "definition": "typedef PVOID PT2_CANCEL_PARAMETERS;" 451 | }, 452 | { 453 | "identifiers": ["THREADINFOCLASS", "PTHREADINFOCLASS"], 454 | "dependencies": [], 455 | "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;" 456 | }, 457 | { 458 | "identifiers": ["OBJECT_INFORMATION_CLASS", "POBJECT_INFORMATION_CLASS"], 459 | "dependencies": [], 460 | "definition": "typedef enum _OBJECT_INFORMATION_CLASS\n{\n\tObjectBasicInformation,\n\tObjectNameInformation,\n\tObjectTypeInformation,\n\tObjectAllTypesInformation,\n\tObjectHandleInformation\n} OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS;" 461 | }, 462 | { 463 | "identifiers": ["FILE_INFORMATION_CLASS", "PFILE_INFORMATION_CLASS"], 464 | "dependencies": [], 465 | "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;" 466 | }, 467 | { 468 | "identifiers": ["KEY_INFORMATION_CLASS", "PKEY_INFORMATION_CLASS"], 469 | "dependencies": [], 470 | "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;" 471 | }, 472 | { 473 | "identifiers": ["UNICODE_STRING", "PUNICODE_STRING"], 474 | "dependencies": [], 475 | "definition": "typedef struct _UNICODE_STRING\n{\n\tUSHORT Length;\n\tUSHORT MaximumLength;\n\tPWSTR Buffer;\n} UNICODE_STRING, *PUNICODE_STRING;" 476 | }, 477 | { 478 | "identifiers": ["InitializeObjectAttributes"], 479 | "dependencies": [], 480 | "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" 481 | }, 482 | { 483 | "identifiers": ["OBJECT_ATTRIBUTES", "POBJECT_ATTRIBUTES"], 484 | "dependencies": ["PUNICODE_STRING", "InitializeObjectAttributes"], 485 | "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;" 486 | }, 487 | { 488 | "identifiers": ["TIMER_INFORMATION_CLASS", "PTIMER_INFORMATION_CLASS"], 489 | "dependencies": [], 490 | "definition": "typedef enum _TIMER_INFORMATION_CLASS\n{\n\tTimerBasicInformation\n} TIMER_INFORMATION_CLASS, *PTIMER_INFORMATION_CLASS;" 491 | }, 492 | { 493 | "identifiers": ["KCONTINUE_TYPE"], 494 | "dependencies": [], 495 | "definition": "typedef enum _KCONTINUE_TYPE\n{\n\tKCONTINUE_UNWIND,\n\tKCONTINUE_RESUME,\n\tKCONTINUE_LONGJUMP,\n\tKCONTINUE_SET,\n\tKCONTINUE_LAST\n} KCONTINUE_TYPE;" 496 | 497 | }, 498 | { 499 | "identifiers": ["KCONTINUE_ARGUMENT", "PKCONTINUE_ARGUMENT"], 500 | "dependencies": ["KCONTINUE_TYPE"], 501 | "definition": "typedef struct _KCONTINUE_ARGUMENT\n{\n\tKCONTINUE_TYPE ContinueType;\n\tULONG ContinueFlags;\n\tULONGLONG Reserved[2];\n} KCONTINUE_ARGUMENT, *PKCONTINUE_ARGUMENT;" 502 | } 503 | ] -------------------------------------------------------------------------------- /example-output/Syscalls-asm.x64.asm: -------------------------------------------------------------------------------- 1 | .code 2 | 3 | EXTERN SW3_GetSyscallNumber: PROC 4 | 5 | NtCreateProcess PROC 6 | mov [rsp +8], rcx ; Save registers. 7 | mov [rsp+16], rdx 8 | mov [rsp+24], r8 9 | mov [rsp+32], r9 10 | sub rsp, 28h 11 | mov ecx, 029943818h ; Load function hash into ECX. 12 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 13 | add rsp, 28h 14 | mov rcx, [rsp+8] ; Restore registers. 15 | mov rdx, [rsp+16] 16 | mov r8, [rsp+24] 17 | mov r9, [rsp+32] 18 | mov r10, rcx 19 | syscall ; Invoke system call. 20 | ret 21 | NtCreateProcess ENDP 22 | 23 | NtCreateThreadEx PROC 24 | mov [rsp +8], rcx ; Save registers. 25 | mov [rsp+16], rdx 26 | mov [rsp+24], r8 27 | mov [rsp+32], r9 28 | sub rsp, 28h 29 | mov ecx, 052B6124Eh ; Load function hash into ECX. 30 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 31 | add rsp, 28h 32 | mov rcx, [rsp+8] ; Restore registers. 33 | mov rdx, [rsp+16] 34 | mov r8, [rsp+24] 35 | mov r9, [rsp+32] 36 | mov r10, rcx 37 | syscall ; Invoke system call. 38 | ret 39 | NtCreateThreadEx ENDP 40 | 41 | NtOpenProcess PROC 42 | mov [rsp +8], rcx ; Save registers. 43 | mov [rsp+16], rdx 44 | mov [rsp+24], r8 45 | mov [rsp+32], r9 46 | sub rsp, 28h 47 | mov ecx, 00DD60C24h ; Load function hash into ECX. 48 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 49 | add rsp, 28h 50 | mov rcx, [rsp+8] ; Restore registers. 51 | mov rdx, [rsp+16] 52 | mov r8, [rsp+24] 53 | mov r9, [rsp+32] 54 | mov r10, rcx 55 | syscall ; Invoke system call. 56 | ret 57 | NtOpenProcess ENDP 58 | 59 | NtOpenProcessToken PROC 60 | mov [rsp +8], rcx ; Save registers. 61 | mov [rsp+16], rdx 62 | mov [rsp+24], r8 63 | mov [rsp+32], r9 64 | sub rsp, 28h 65 | mov ecx, 0C3914A8Dh ; Load function hash into ECX. 66 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 67 | add rsp, 28h 68 | mov rcx, [rsp+8] ; Restore registers. 69 | mov rdx, [rsp+16] 70 | mov r8, [rsp+24] 71 | mov r9, [rsp+32] 72 | mov r10, rcx 73 | syscall ; Invoke system call. 74 | ret 75 | NtOpenProcessToken ENDP 76 | 77 | NtTestAlert PROC 78 | mov [rsp +8], rcx ; Save registers. 79 | mov [rsp+16], rdx 80 | mov [rsp+24], r8 81 | mov [rsp+32], r9 82 | sub rsp, 28h 83 | mov ecx, 02EB45D3Ah ; Load function hash into ECX. 84 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 85 | add rsp, 28h 86 | mov rcx, [rsp+8] ; Restore registers. 87 | mov rdx, [rsp+16] 88 | mov r8, [rsp+24] 89 | mov r9, [rsp+32] 90 | mov r10, rcx 91 | syscall ; Invoke system call. 92 | ret 93 | NtTestAlert ENDP 94 | 95 | NtOpenThread PROC 96 | mov [rsp +8], rcx ; Save registers. 97 | mov [rsp+16], rdx 98 | mov [rsp+24], r8 99 | mov [rsp+32], r9 100 | sub rsp, 28h 101 | mov ecx, 075426DE5h ; Load function hash into ECX. 102 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 103 | add rsp, 28h 104 | mov rcx, [rsp+8] ; Restore registers. 105 | mov rdx, [rsp+16] 106 | mov r8, [rsp+24] 107 | mov r9, [rsp+32] 108 | mov r10, rcx 109 | syscall ; Invoke system call. 110 | ret 111 | NtOpenThread ENDP 112 | 113 | NtSuspendProcess PROC 114 | mov [rsp +8], rcx ; Save registers. 115 | mov [rsp+16], rdx 116 | mov [rsp+24], r8 117 | mov [rsp+32], r9 118 | sub rsp, 28h 119 | mov ecx, 0F022DFBFh ; Load function hash into ECX. 120 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 121 | add rsp, 28h 122 | mov rcx, [rsp+8] ; Restore registers. 123 | mov rdx, [rsp+16] 124 | mov r8, [rsp+24] 125 | mov r9, [rsp+32] 126 | mov r10, rcx 127 | syscall ; Invoke system call. 128 | ret 129 | NtSuspendProcess ENDP 130 | 131 | NtSuspendThread PROC 132 | mov [rsp +8], rcx ; Save registers. 133 | mov [rsp+16], rdx 134 | mov [rsp+24], r8 135 | mov [rsp+32], r9 136 | sub rsp, 28h 137 | mov ecx, 00F3F9E0Dh ; Load function hash into ECX. 138 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 139 | add rsp, 28h 140 | mov rcx, [rsp+8] ; Restore registers. 141 | mov rdx, [rsp+16] 142 | mov r8, [rsp+24] 143 | mov r9, [rsp+32] 144 | mov r10, rcx 145 | syscall ; Invoke system call. 146 | ret 147 | NtSuspendThread ENDP 148 | 149 | NtResumeProcess PROC 150 | mov [rsp +8], rcx ; Save registers. 151 | mov [rsp+16], rdx 152 | mov [rsp+24], r8 153 | mov [rsp+32], r9 154 | sub rsp, 28h 155 | mov ecx, 041D54040h ; Load function hash into ECX. 156 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 157 | add rsp, 28h 158 | mov rcx, [rsp+8] ; Restore registers. 159 | mov rdx, [rsp+16] 160 | mov r8, [rsp+24] 161 | mov r9, [rsp+32] 162 | mov r10, rcx 163 | syscall ; Invoke system call. 164 | ret 165 | NtResumeProcess ENDP 166 | 167 | NtResumeThread PROC 168 | mov [rsp +8], rcx ; Save registers. 169 | mov [rsp+16], rdx 170 | mov [rsp+24], r8 171 | mov [rsp+32], r9 172 | sub rsp, 28h 173 | mov ecx, 0B28FAC35h ; Load function hash into ECX. 174 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 175 | add rsp, 28h 176 | mov rcx, [rsp+8] ; Restore registers. 177 | mov rdx, [rsp+16] 178 | mov r8, [rsp+24] 179 | mov r9, [rsp+32] 180 | mov r10, rcx 181 | syscall ; Invoke system call. 182 | ret 183 | NtResumeThread ENDP 184 | 185 | NtGetContextThread PROC 186 | mov [rsp +8], rcx ; Save registers. 187 | mov [rsp+16], rdx 188 | mov [rsp+24], r8 189 | mov [rsp+32], r9 190 | sub rsp, 28h 191 | mov ecx, 0BB97FF4Fh ; Load function hash into ECX. 192 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 193 | add rsp, 28h 194 | mov rcx, [rsp+8] ; Restore registers. 195 | mov rdx, [rsp+16] 196 | mov r8, [rsp+24] 197 | mov r9, [rsp+32] 198 | mov r10, rcx 199 | syscall ; Invoke system call. 200 | ret 201 | NtGetContextThread ENDP 202 | 203 | NtSetContextThread PROC 204 | mov [rsp +8], rcx ; Save registers. 205 | mov [rsp+16], rdx 206 | mov [rsp+24], r8 207 | mov [rsp+32], r9 208 | sub rsp, 28h 209 | mov ecx, 093B3CF03h ; Load function hash into ECX. 210 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 211 | add rsp, 28h 212 | mov rcx, [rsp+8] ; Restore registers. 213 | mov rdx, [rsp+16] 214 | mov r8, [rsp+24] 215 | mov r9, [rsp+32] 216 | mov r10, rcx 217 | syscall ; Invoke system call. 218 | ret 219 | NtSetContextThread ENDP 220 | 221 | NtClose PROC 222 | mov [rsp +8], rcx ; Save registers. 223 | mov [rsp+16], rdx 224 | mov [rsp+24], r8 225 | mov [rsp+32], r9 226 | sub rsp, 28h 227 | mov ecx, 04B1B40BBh ; Load function hash into ECX. 228 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 229 | add rsp, 28h 230 | mov rcx, [rsp+8] ; Restore registers. 231 | mov rdx, [rsp+16] 232 | mov r8, [rsp+24] 233 | mov r9, [rsp+32] 234 | mov r10, rcx 235 | syscall ; Invoke system call. 236 | ret 237 | NtClose ENDP 238 | 239 | NtReadVirtualMemory PROC 240 | mov [rsp +8], rcx ; Save registers. 241 | mov [rsp+16], rdx 242 | mov [rsp+24], r8 243 | mov [rsp+32], r9 244 | sub rsp, 28h 245 | mov ecx, 009824143h ; Load function hash into ECX. 246 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 247 | add rsp, 28h 248 | mov rcx, [rsp+8] ; Restore registers. 249 | mov rdx, [rsp+16] 250 | mov r8, [rsp+24] 251 | mov r9, [rsp+32] 252 | mov r10, rcx 253 | syscall ; Invoke system call. 254 | ret 255 | NtReadVirtualMemory ENDP 256 | 257 | NtWriteVirtualMemory PROC 258 | mov [rsp +8], rcx ; Save registers. 259 | mov [rsp+16], rdx 260 | mov [rsp+24], r8 261 | mov [rsp+32], r9 262 | sub rsp, 28h 263 | mov ecx, 08E108490h ; Load function hash into ECX. 264 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 265 | add rsp, 28h 266 | mov rcx, [rsp+8] ; Restore registers. 267 | mov rdx, [rsp+16] 268 | mov r8, [rsp+24] 269 | mov r9, [rsp+32] 270 | mov r10, rcx 271 | syscall ; Invoke system call. 272 | ret 273 | NtWriteVirtualMemory ENDP 274 | 275 | NtAllocateVirtualMemory PROC 276 | mov [rsp +8], rcx ; Save registers. 277 | mov [rsp+16], rdx 278 | mov [rsp+24], r8 279 | mov [rsp+32], r9 280 | sub rsp, 28h 281 | mov ecx, 0C253FAF2h ; Load function hash into ECX. 282 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 283 | add rsp, 28h 284 | mov rcx, [rsp+8] ; Restore registers. 285 | mov rdx, [rsp+16] 286 | mov r8, [rsp+24] 287 | mov r9, [rsp+32] 288 | mov r10, rcx 289 | syscall ; Invoke system call. 290 | ret 291 | NtAllocateVirtualMemory ENDP 292 | 293 | NtProtectVirtualMemory PROC 294 | mov [rsp +8], rcx ; Save registers. 295 | mov [rsp+16], rdx 296 | mov [rsp+24], r8 297 | mov [rsp+32], r9 298 | sub rsp, 28h 299 | mov ecx, 0C0603A1Dh ; Load function hash into ECX. 300 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 301 | add rsp, 28h 302 | mov rcx, [rsp+8] ; Restore registers. 303 | mov rdx, [rsp+16] 304 | mov r8, [rsp+24] 305 | mov r9, [rsp+32] 306 | mov r10, rcx 307 | syscall ; Invoke system call. 308 | ret 309 | NtProtectVirtualMemory ENDP 310 | 311 | NtFreeVirtualMemory PROC 312 | mov [rsp +8], rcx ; Save registers. 313 | mov [rsp+16], rdx 314 | mov [rsp+24], r8 315 | mov [rsp+32], r9 316 | sub rsp, 28h 317 | mov ecx, 087118D83h ; Load function hash into ECX. 318 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 319 | add rsp, 28h 320 | mov rcx, [rsp+8] ; Restore registers. 321 | mov rdx, [rsp+16] 322 | mov r8, [rsp+24] 323 | mov r9, [rsp+32] 324 | mov r10, rcx 325 | syscall ; Invoke system call. 326 | ret 327 | NtFreeVirtualMemory ENDP 328 | 329 | NtQuerySystemInformation PROC 330 | mov [rsp +8], rcx ; Save registers. 331 | mov [rsp+16], rdx 332 | mov [rsp+24], r8 333 | mov [rsp+32], r9 334 | sub rsp, 28h 335 | mov ecx, 0A4069EABh ; Load function hash into ECX. 336 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 337 | add rsp, 28h 338 | mov rcx, [rsp+8] ; Restore registers. 339 | mov rdx, [rsp+16] 340 | mov r8, [rsp+24] 341 | mov r9, [rsp+32] 342 | mov r10, rcx 343 | syscall ; Invoke system call. 344 | ret 345 | NtQuerySystemInformation ENDP 346 | 347 | NtQueryDirectoryFile PROC 348 | mov [rsp +8], rcx ; Save registers. 349 | mov [rsp+16], rdx 350 | mov [rsp+24], r8 351 | mov [rsp+32], r9 352 | sub rsp, 28h 353 | mov ecx, 09533C586h ; Load function hash into ECX. 354 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 355 | add rsp, 28h 356 | mov rcx, [rsp+8] ; Restore registers. 357 | mov rdx, [rsp+16] 358 | mov r8, [rsp+24] 359 | mov r9, [rsp+32] 360 | mov r10, rcx 361 | syscall ; Invoke system call. 362 | ret 363 | NtQueryDirectoryFile ENDP 364 | 365 | NtQueryInformationFile PROC 366 | mov [rsp +8], rcx ; Save registers. 367 | mov [rsp+16], rdx 368 | mov [rsp+24], r8 369 | mov [rsp+32], r9 370 | sub rsp, 28h 371 | mov ecx, 0AC3E2418h ; Load function hash into ECX. 372 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 373 | add rsp, 28h 374 | mov rcx, [rsp+8] ; Restore registers. 375 | mov rdx, [rsp+16] 376 | mov r8, [rsp+24] 377 | mov r9, [rsp+32] 378 | mov r10, rcx 379 | syscall ; Invoke system call. 380 | ret 381 | NtQueryInformationFile ENDP 382 | 383 | NtQueryInformationProcess PROC 384 | mov [rsp +8], rcx ; Save registers. 385 | mov [rsp+16], rdx 386 | mov [rsp+24], r8 387 | mov [rsp+32], r9 388 | sub rsp, 28h 389 | mov ecx, 002AC0B33h ; Load function hash into ECX. 390 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 391 | add rsp, 28h 392 | mov rcx, [rsp+8] ; Restore registers. 393 | mov rdx, [rsp+16] 394 | mov r8, [rsp+24] 395 | mov r9, [rsp+32] 396 | mov r10, rcx 397 | syscall ; Invoke system call. 398 | ret 399 | NtQueryInformationProcess ENDP 400 | 401 | NtQueryInformationThread PROC 402 | mov [rsp +8], rcx ; Save registers. 403 | mov [rsp+16], rdx 404 | mov [rsp+24], r8 405 | mov [rsp+32], r9 406 | sub rsp, 28h 407 | mov ecx, 0745A2EE3h ; Load function hash into ECX. 408 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 409 | add rsp, 28h 410 | mov rcx, [rsp+8] ; Restore registers. 411 | mov rdx, [rsp+16] 412 | mov r8, [rsp+24] 413 | mov r9, [rsp+32] 414 | mov r10, rcx 415 | syscall ; Invoke system call. 416 | ret 417 | NtQueryInformationThread ENDP 418 | 419 | NtCreateSection PROC 420 | mov [rsp +8], rcx ; Save registers. 421 | mov [rsp+16], rdx 422 | mov [rsp+24], r8 423 | mov [rsp+32], r9 424 | sub rsp, 28h 425 | mov ecx, 0F42FD4F1h ; Load function hash into ECX. 426 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 427 | add rsp, 28h 428 | mov rcx, [rsp+8] ; Restore registers. 429 | mov rdx, [rsp+16] 430 | mov r8, [rsp+24] 431 | mov r9, [rsp+32] 432 | mov r10, rcx 433 | syscall ; Invoke system call. 434 | ret 435 | NtCreateSection ENDP 436 | 437 | NtOpenSection PROC 438 | mov [rsp +8], rcx ; Save registers. 439 | mov [rsp+16], rdx 440 | mov [rsp+24], r8 441 | mov [rsp+32], r9 442 | sub rsp, 28h 443 | mov ecx, 064CE6A2Fh ; Load function hash into ECX. 444 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 445 | add rsp, 28h 446 | mov rcx, [rsp+8] ; Restore registers. 447 | mov rdx, [rsp+16] 448 | mov r8, [rsp+24] 449 | mov r9, [rsp+32] 450 | mov r10, rcx 451 | syscall ; Invoke system call. 452 | ret 453 | NtOpenSection ENDP 454 | 455 | NtMapViewOfSection PROC 456 | mov [rsp +8], rcx ; Save registers. 457 | mov [rsp+16], rdx 458 | mov [rsp+24], r8 459 | mov [rsp+32], r9 460 | sub rsp, 28h 461 | mov ecx, 0508A5019h ; Load function hash into ECX. 462 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 463 | add rsp, 28h 464 | mov rcx, [rsp+8] ; Restore registers. 465 | mov rdx, [rsp+16] 466 | mov r8, [rsp+24] 467 | mov r9, [rsp+32] 468 | mov r10, rcx 469 | syscall ; Invoke system call. 470 | ret 471 | NtMapViewOfSection ENDP 472 | 473 | NtUnmapViewOfSection PROC 474 | mov [rsp +8], rcx ; Save registers. 475 | mov [rsp+16], rdx 476 | mov [rsp+24], r8 477 | mov [rsp+32], r9 478 | sub rsp, 28h 479 | mov ecx, 0DF54DBCEh ; Load function hash into ECX. 480 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 481 | add rsp, 28h 482 | mov rcx, [rsp+8] ; Restore registers. 483 | mov rdx, [rsp+16] 484 | mov r8, [rsp+24] 485 | mov r9, [rsp+32] 486 | mov r10, rcx 487 | syscall ; Invoke system call. 488 | ret 489 | NtUnmapViewOfSection ENDP 490 | 491 | NtAdjustPrivilegesToken PROC 492 | mov [rsp +8], rcx ; Save registers. 493 | mov [rsp+16], rdx 494 | mov [rsp+24], r8 495 | mov [rsp+32], r9 496 | sub rsp, 28h 497 | mov ecx, 05DC34340h ; Load function hash into ECX. 498 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 499 | add rsp, 28h 500 | mov rcx, [rsp+8] ; Restore registers. 501 | mov rdx, [rsp+16] 502 | mov r8, [rsp+24] 503 | mov r9, [rsp+32] 504 | mov r10, rcx 505 | syscall ; Invoke system call. 506 | ret 507 | NtAdjustPrivilegesToken ENDP 508 | 509 | NtDeviceIoControlFile PROC 510 | mov [rsp +8], rcx ; Save registers. 511 | mov [rsp+16], rdx 512 | mov [rsp+24], r8 513 | mov [rsp+32], r9 514 | sub rsp, 28h 515 | mov ecx, 0D1DAE373h ; Load function hash into ECX. 516 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 517 | add rsp, 28h 518 | mov rcx, [rsp+8] ; Restore registers. 519 | mov rdx, [rsp+16] 520 | mov r8, [rsp+24] 521 | mov r9, [rsp+32] 522 | mov r10, rcx 523 | syscall ; Invoke system call. 524 | ret 525 | NtDeviceIoControlFile ENDP 526 | 527 | NtQueueApcThread PROC 528 | mov [rsp +8], rcx ; Save registers. 529 | mov [rsp+16], rdx 530 | mov [rsp+24], r8 531 | mov [rsp+32], r9 532 | sub rsp, 28h 533 | mov ecx, 0E851AAFFh ; Load function hash into ECX. 534 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 535 | add rsp, 28h 536 | mov rcx, [rsp+8] ; Restore registers. 537 | mov rdx, [rsp+16] 538 | mov r8, [rsp+24] 539 | mov r9, [rsp+32] 540 | mov r10, rcx 541 | syscall ; Invoke system call. 542 | ret 543 | NtQueueApcThread ENDP 544 | 545 | NtWaitForMultipleObjects PROC 546 | mov [rsp +8], rcx ; Save registers. 547 | mov [rsp+16], rdx 548 | mov [rsp+24], r8 549 | mov [rsp+32], r9 550 | sub rsp, 28h 551 | mov ecx, 003837B11h ; Load function hash into ECX. 552 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 553 | add rsp, 28h 554 | mov rcx, [rsp+8] ; Restore registers. 555 | mov rdx, [rsp+16] 556 | mov r8, [rsp+24] 557 | mov r9, [rsp+32] 558 | mov r10, rcx 559 | syscall ; Invoke system call. 560 | ret 561 | NtWaitForMultipleObjects ENDP 562 | 563 | end -------------------------------------------------------------------------------- /example-output/Syscalls.c: -------------------------------------------------------------------------------- 1 | #include "Syscalls.h" 2 | #include 3 | 4 | //#define DEBUG 5 | 6 | // JUMPER 7 | 8 | #ifdef _M_IX86 9 | 10 | EXTERN_C PVOID internal_cleancall_wow64_gate(VOID) { 11 | return (PVOID)__readfsdword(0xC0); 12 | } 13 | 14 | __declspec(naked) BOOL local_is_wow64(void) 15 | { 16 | __asm { 17 | mov eax, fs:[0xc0] 18 | test eax, eax 19 | jne wow64 20 | mov eax, 0 21 | ret 22 | wow64: 23 | mov eax, 1 24 | ret 25 | } 26 | } 27 | 28 | 29 | #endif 30 | 31 | // Code below is adapted from @modexpblog. Read linked article for more details. 32 | // https://www.mdsec.co.uk/2020/12/bypassing-user-mode-hooks-and-direct-invocation-of-system-calls-for-red-teams 33 | 34 | SW3_SYSCALL_LIST SW3_SyscallList; 35 | 36 | // SEARCH_AND_REPLACE 37 | #ifdef SEARCH_AND_REPLACE 38 | // THIS IS NOT DEFINED HERE; don't know if I'll add it in a future release 39 | EXTERN void SearchAndReplace(unsigned char[], unsigned char[]); 40 | #endif 41 | 42 | DWORD SW3_HashSyscall(PCSTR FunctionName) 43 | { 44 | DWORD i = 0; 45 | DWORD Hash = SW3_SEED; 46 | 47 | while (FunctionName[i]) 48 | { 49 | WORD PartialName = *(WORD*)((ULONG_PTR)FunctionName + i++); 50 | Hash ^= PartialName + SW3_ROR8(Hash); 51 | } 52 | 53 | return Hash; 54 | } 55 | 56 | #ifndef JUMPER 57 | PVOID SC_Address(PVOID NtApiAddress) 58 | { 59 | return NULL; 60 | } 61 | #else 62 | PVOID SC_Address(PVOID NtApiAddress) 63 | { 64 | DWORD searchLimit = 512; 65 | PVOID SyscallAddress; 66 | 67 | #ifdef _WIN64 68 | // If the process is 64-bit on a 64-bit OS, we need to search for syscall 69 | BYTE syscall_code[] = { 0x0f, 0x05, 0xc3 }; 70 | ULONG distance_to_syscall = 0x12; 71 | #else 72 | // If the process is 32-bit on a 32-bit OS, we need to search for sysenter 73 | BYTE syscall_code[] = { 0x0f, 0x34, 0xc3 }; 74 | ULONG distance_to_syscall = 0x0f; 75 | #endif 76 | 77 | #ifdef _M_IX86 78 | // If the process is 32-bit on a 64-bit OS, we need to jump to WOW32Reserved 79 | if (local_is_wow64()) 80 | { 81 | #ifdef DEBUG 82 | printf("[+] Running 32-bit app on x64 (WOW64)\n"); 83 | #endif 84 | return NULL; 85 | } 86 | #endif 87 | 88 | // we don't really care if there is a 'jmp' between 89 | // NtApiAddress and the 'syscall; ret' instructions 90 | SyscallAddress = SW3_RVA2VA(PVOID, NtApiAddress, distance_to_syscall); 91 | 92 | if (!memcmp((PVOID)syscall_code, SyscallAddress, sizeof(syscall_code))) 93 | { 94 | // we can use the original code for this system call :) 95 | #if defined(DEBUG) 96 | printf("Found Syscall Opcodes at address 0x%p\n", SyscallAddress); 97 | #endif 98 | return SyscallAddress; 99 | } 100 | 101 | // the 'syscall; ret' intructions have not been found, 102 | // we will try to use one near it, similarly to HalosGate 103 | 104 | for (ULONG32 num_jumps = 1; num_jumps < searchLimit; num_jumps++) 105 | { 106 | // let's try with an Nt* API below our syscall 107 | SyscallAddress = SW3_RVA2VA( 108 | PVOID, 109 | NtApiAddress, 110 | distance_to_syscall + num_jumps * 0x20); 111 | if (!memcmp((PVOID)syscall_code, SyscallAddress, sizeof(syscall_code))) 112 | { 113 | #if defined(DEBUG) 114 | printf("Found Syscall Opcodes at address 0x%p\n", SyscallAddress); 115 | #endif 116 | return SyscallAddress; 117 | } 118 | 119 | // let's try with an Nt* API above our syscall 120 | SyscallAddress = SW3_RVA2VA( 121 | PVOID, 122 | NtApiAddress, 123 | distance_to_syscall - num_jumps * 0x20); 124 | if (!memcmp((PVOID)syscall_code, SyscallAddress, sizeof(syscall_code))) 125 | { 126 | #if defined(DEBUG) 127 | printf("Found Syscall Opcodes at address 0x%p\n", SyscallAddress); 128 | #endif 129 | return SyscallAddress; 130 | } 131 | } 132 | 133 | #ifdef DEBUG 134 | printf("Syscall Opcodes not found!\n"); 135 | #endif 136 | 137 | return NULL; 138 | } 139 | #endif 140 | 141 | 142 | BOOL SW3_PopulateSyscallList() 143 | { 144 | // Return early if the list is already populated. 145 | if (SW3_SyscallList.Count) return TRUE; 146 | 147 | #ifdef _WIN64 148 | PSW3_PEB Peb = (PSW3_PEB)__readgsqword(0x60); 149 | #else 150 | PSW3_PEB Peb = (PSW3_PEB)__readfsdword(0x30); 151 | #endif 152 | PSW3_PEB_LDR_DATA Ldr = Peb->Ldr; 153 | PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL; 154 | PVOID DllBase = NULL; 155 | 156 | // Get the DllBase address of NTDLL.dll. NTDLL is not guaranteed to be the second 157 | // in the list, so it's safer to loop through the full list and find it. 158 | PSW3_LDR_DATA_TABLE_ENTRY LdrEntry; 159 | for (LdrEntry = (PSW3_LDR_DATA_TABLE_ENTRY)Ldr->Reserved2[1]; LdrEntry->DllBase != NULL; LdrEntry = (PSW3_LDR_DATA_TABLE_ENTRY)LdrEntry->Reserved1[0]) 160 | { 161 | DllBase = LdrEntry->DllBase; 162 | PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)DllBase; 163 | PIMAGE_NT_HEADERS NtHeaders = SW3_RVA2VA(PIMAGE_NT_HEADERS, DllBase, DosHeader->e_lfanew); 164 | PIMAGE_DATA_DIRECTORY DataDirectory = (PIMAGE_DATA_DIRECTORY)NtHeaders->OptionalHeader.DataDirectory; 165 | DWORD VirtualAddress = DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; 166 | if (VirtualAddress == 0) continue; 167 | 168 | ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)SW3_RVA2VA(ULONG_PTR, DllBase, VirtualAddress); 169 | 170 | // If this is NTDLL.dll, exit loop. 171 | PCHAR DllName = SW3_RVA2VA(PCHAR, DllBase, ExportDirectory->Name); 172 | 173 | if ((*(ULONG*)DllName | 0x20202020) != 0x6c64746e) continue; 174 | if ((*(ULONG*)(DllName + 4) | 0x20202020) == 0x6c642e6c) break; 175 | } 176 | 177 | if (!ExportDirectory) return FALSE; 178 | 179 | DWORD NumberOfNames = ExportDirectory->NumberOfNames; 180 | PDWORD Functions = SW3_RVA2VA(PDWORD, DllBase, ExportDirectory->AddressOfFunctions); 181 | PDWORD Names = SW3_RVA2VA(PDWORD, DllBase, ExportDirectory->AddressOfNames); 182 | PWORD Ordinals = SW3_RVA2VA(PWORD, DllBase, ExportDirectory->AddressOfNameOrdinals); 183 | 184 | // Populate SW3_SyscallList with unsorted Zw* entries. 185 | DWORD i = 0; 186 | PSW3_SYSCALL_ENTRY Entries = SW3_SyscallList.Entries; 187 | do 188 | { 189 | PCHAR FunctionName = SW3_RVA2VA(PCHAR, DllBase, Names[NumberOfNames - 1]); 190 | 191 | // Is this a system call? 192 | if (*(USHORT*)FunctionName == 0x775a) 193 | { 194 | Entries[i].Hash = SW3_HashSyscall(FunctionName); 195 | Entries[i].Address = Functions[Ordinals[NumberOfNames - 1]]; 196 | Entries[i].SyscallAddress = SC_Address(SW3_RVA2VA(PVOID, DllBase, Entries[i].Address)); 197 | 198 | i++; 199 | if (i == SW3_MAX_ENTRIES) break; 200 | } 201 | } while (--NumberOfNames); 202 | 203 | // Save total number of system calls found. 204 | SW3_SyscallList.Count = i; 205 | 206 | // Sort the list by address in ascending order. 207 | for (DWORD i = 0; i < SW3_SyscallList.Count - 1; i++) 208 | { 209 | for (DWORD j = 0; j < SW3_SyscallList.Count - i - 1; j++) 210 | { 211 | if (Entries[j].Address > Entries[j + 1].Address) 212 | { 213 | // Swap entries. 214 | SW3_SYSCALL_ENTRY TempEntry; 215 | 216 | TempEntry.Hash = Entries[j].Hash; 217 | TempEntry.Address = Entries[j].Address; 218 | TempEntry.SyscallAddress = Entries[j].SyscallAddress; 219 | 220 | Entries[j].Hash = Entries[j + 1].Hash; 221 | Entries[j].Address = Entries[j + 1].Address; 222 | Entries[j].SyscallAddress = Entries[j + 1].SyscallAddress; 223 | 224 | Entries[j + 1].Hash = TempEntry.Hash; 225 | Entries[j + 1].Address = TempEntry.Address; 226 | Entries[j + 1].SyscallAddress = TempEntry.SyscallAddress; 227 | } 228 | } 229 | } 230 | 231 | return TRUE; 232 | } 233 | 234 | EXTERN_C DWORD SW3_GetSyscallNumber(DWORD FunctionHash) 235 | { 236 | // Ensure SW3_SyscallList is populated. 237 | if (!SW3_PopulateSyscallList()) return -1; 238 | 239 | for (DWORD i = 0; i < SW3_SyscallList.Count; i++) 240 | { 241 | if (FunctionHash == SW3_SyscallList.Entries[i].Hash) 242 | { 243 | return i; 244 | } 245 | } 246 | 247 | return -1; 248 | } 249 | 250 | EXTERN_C PVOID SW3_GetSyscallAddress(DWORD FunctionHash) 251 | { 252 | // Ensure SW3_SyscallList is populated. 253 | if (!SW3_PopulateSyscallList()) return NULL; 254 | 255 | for (DWORD i = 0; i < SW3_SyscallList.Count; i++) 256 | { 257 | if (FunctionHash == SW3_SyscallList.Entries[i].Hash) 258 | { 259 | return SW3_SyscallList.Entries[i].SyscallAddress; 260 | } 261 | } 262 | 263 | return NULL; 264 | } 265 | 266 | EXTERN_C PVOID SW3_GetRandomSyscallAddress(DWORD FunctionHash) 267 | { 268 | // Ensure SW3_SyscallList is populated. 269 | if (!SW3_PopulateSyscallList()) return NULL; 270 | 271 | DWORD index = ((DWORD) rand()) % SW3_SyscallList.Count; 272 | 273 | while (FunctionHash == SW3_SyscallList.Entries[index].Hash){ 274 | // Spoofing the syscall return address 275 | index = ((DWORD) rand()) % SW3_SyscallList.Count; 276 | } 277 | return SW3_SyscallList.Entries[index].SyscallAddress; 278 | } 279 | -------------------------------------------------------------------------------- /example-output/Syscalls.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Code below is adapted from @modexpblog. Read linked article for more details. 4 | // https://www.mdsec.co.uk/2020/12/bypassing-user-mode-hooks-and-direct-invocation-of-system-calls-for-red-teams 5 | 6 | #ifndef SW3_HEADER_H_ 7 | #define SW3_HEADER_H_ 8 | 9 | #include 10 | 11 | #define SW3_SEED 0x769430A3 12 | #define SW3_ROL8(v) (v << 8 | v >> 24) 13 | #define SW3_ROR8(v) (v >> 8 | v << 24) 14 | #define SW3_ROX8(v) ((SW3_SEED % 2) ? SW3_ROL8(v) : SW3_ROR8(v)) 15 | #define SW3_MAX_ENTRIES 500 16 | #define SW3_RVA2VA(Type, DllBase, Rva) (Type)((ULONG_PTR) DllBase + Rva) 17 | 18 | // Typedefs are prefixed to avoid pollution. 19 | 20 | typedef struct _SW3_SYSCALL_ENTRY 21 | { 22 | DWORD Hash; 23 | DWORD Address; 24 | PVOID SyscallAddress; 25 | } SW3_SYSCALL_ENTRY, *PSW3_SYSCALL_ENTRY; 26 | 27 | typedef struct _SW3_SYSCALL_LIST 28 | { 29 | DWORD Count; 30 | SW3_SYSCALL_ENTRY Entries[SW3_MAX_ENTRIES]; 31 | } SW3_SYSCALL_LIST, *PSW3_SYSCALL_LIST; 32 | 33 | typedef struct _SW3_PEB_LDR_DATA { 34 | BYTE Reserved1[8]; 35 | PVOID Reserved2[3]; 36 | LIST_ENTRY InMemoryOrderModuleList; 37 | } SW3_PEB_LDR_DATA, *PSW3_PEB_LDR_DATA; 38 | 39 | typedef struct _SW3_LDR_DATA_TABLE_ENTRY { 40 | PVOID Reserved1[2]; 41 | LIST_ENTRY InMemoryOrderLinks; 42 | PVOID Reserved2[2]; 43 | PVOID DllBase; 44 | } SW3_LDR_DATA_TABLE_ENTRY, *PSW3_LDR_DATA_TABLE_ENTRY; 45 | 46 | typedef struct _SW3_PEB { 47 | BYTE Reserved1[2]; 48 | BYTE BeingDebugged; 49 | BYTE Reserved2[1]; 50 | PVOID Reserved3[2]; 51 | PSW3_PEB_LDR_DATA Ldr; 52 | } SW3_PEB, *PSW3_PEB; 53 | 54 | DWORD SW3_HashSyscall(PCSTR FunctionName); 55 | BOOL SW3_PopulateSyscallList(); 56 | EXTERN_C DWORD SW3_GetSyscallNumber(DWORD FunctionHash); 57 | EXTERN_C PVOID SW3_GetSyscallAddress(DWORD FunctionHash); 58 | EXTERN_C PVOID internal_cleancall_wow64_gate(VOID); 59 | typedef struct _SYSTEM_HANDLE 60 | { 61 | ULONG ProcessId; 62 | BYTE ObjectTypeNumber; 63 | BYTE Flags; 64 | USHORT Handle; 65 | PVOID Object; 66 | ACCESS_MASK GrantedAccess; 67 | } SYSTEM_HANDLE, *PSYSTEM_HANDLE; 68 | 69 | typedef struct _IO_STATUS_BLOCK 70 | { 71 | union 72 | { 73 | NTSTATUS Status; 74 | VOID* Pointer; 75 | }; 76 | ULONG_PTR Information; 77 | } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; 78 | 79 | typedef struct _SYSTEM_HANDLE_INFORMATION 80 | { 81 | ULONG HandleCount; 82 | SYSTEM_HANDLE Handles[1]; 83 | } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; 84 | 85 | typedef VOID(KNORMAL_ROUTINE) ( 86 | IN PVOID NormalContext, 87 | IN PVOID SystemArgument1, 88 | IN PVOID SystemArgument2); 89 | 90 | typedef struct _PS_ATTRIBUTE 91 | { 92 | ULONG Attribute; 93 | SIZE_T Size; 94 | union 95 | { 96 | ULONG Value; 97 | PVOID ValuePtr; 98 | } u1; 99 | PSIZE_T ReturnLength; 100 | } PS_ATTRIBUTE, *PPS_ATTRIBUTE; 101 | 102 | typedef struct _UNICODE_STRING 103 | { 104 | USHORT Length; 105 | USHORT MaximumLength; 106 | PWSTR Buffer; 107 | } UNICODE_STRING, *PUNICODE_STRING; 108 | 109 | #ifndef InitializeObjectAttributes 110 | #define InitializeObjectAttributes( p, n, a, r, s ) { \ 111 | (p)->Length = sizeof( OBJECT_ATTRIBUTES ); \ 112 | (p)->RootDirectory = r; \ 113 | (p)->Attributes = a; \ 114 | (p)->ObjectName = n; \ 115 | (p)->SecurityDescriptor = s; \ 116 | (p)->SecurityQualityOfService = NULL; \ 117 | } 118 | #endif 119 | 120 | typedef struct _OBJECT_ATTRIBUTES 121 | { 122 | ULONG Length; 123 | HANDLE RootDirectory; 124 | PUNICODE_STRING ObjectName; 125 | ULONG Attributes; 126 | PVOID SecurityDescriptor; 127 | PVOID SecurityQualityOfService; 128 | } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; 129 | 130 | typedef struct _CLIENT_ID 131 | { 132 | HANDLE UniqueProcess; 133 | HANDLE UniqueThread; 134 | } CLIENT_ID, *PCLIENT_ID; 135 | 136 | typedef enum _SYSTEM_INFORMATION_CLASS 137 | { 138 | SystemBasicInformation = 0, 139 | SystemPerformanceInformation = 2, 140 | SystemTimeOfDayInformation = 3, 141 | SystemProcessInformation = 5, 142 | SystemProcessorPerformanceInformation = 8, 143 | SystemHandleInformation = 16, 144 | SystemInterruptInformation = 23, 145 | SystemExceptionInformation = 33, 146 | SystemRegistryQuotaInformation = 37, 147 | SystemLookasideInformation = 45, 148 | SystemCodeIntegrityInformation = 103, 149 | SystemPolicyInformation = 134, 150 | } SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS; 151 | 152 | typedef enum _PROCESSINFOCLASS 153 | { 154 | ProcessBasicInformation = 0, 155 | ProcessDebugPort = 7, 156 | ProcessWow64Information = 26, 157 | ProcessImageFileName = 27, 158 | ProcessBreakOnTermination = 29 159 | } PROCESSINFOCLASS, *PPROCESSINFOCLASS; 160 | 161 | typedef enum _WAIT_TYPE 162 | { 163 | WaitAll = 0, 164 | WaitAny = 1 165 | } WAIT_TYPE, *PWAIT_TYPE; 166 | 167 | typedef VOID(NTAPI* PIO_APC_ROUTINE) ( 168 | IN PVOID ApcContext, 169 | IN PIO_STATUS_BLOCK IoStatusBlock, 170 | IN ULONG Reserved); 171 | 172 | typedef KNORMAL_ROUTINE* PKNORMAL_ROUTINE; 173 | 174 | typedef enum _THREADINFOCLASS 175 | { 176 | ThreadBasicInformation, 177 | ThreadTimes, 178 | ThreadPriority, 179 | ThreadBasePriority, 180 | ThreadAffinityMask, 181 | ThreadImpersonationToken, 182 | ThreadDescriptorTableEntry, 183 | ThreadEnableAlignmentFaultFixup, 184 | ThreadEventPair_Reusable, 185 | ThreadQuerySetWin32StartAddress, 186 | ThreadZeroTlsCell, 187 | ThreadPerformanceCount, 188 | ThreadAmILastThread, 189 | ThreadIdealProcessor, 190 | ThreadPriorityBoost, 191 | ThreadSetTlsArrayAddress, 192 | ThreadIsIoPending, 193 | ThreadHideFromDebugger, 194 | ThreadBreakOnTermination, 195 | MaxThreadInfoClass 196 | } THREADINFOCLASS, *PTHREADINFOCLASS; 197 | 198 | typedef enum _SECTION_INHERIT 199 | { 200 | ViewShare = 1, 201 | ViewUnmap = 2 202 | } SECTION_INHERIT, *PSECTION_INHERIT; 203 | 204 | typedef enum _FILE_INFORMATION_CLASS 205 | { 206 | FileDirectoryInformation = 1, 207 | FileFullDirectoryInformation = 2, 208 | FileBothDirectoryInformation = 3, 209 | FileBasicInformation = 4, 210 | FileStandardInformation = 5, 211 | FileInternalInformation = 6, 212 | FileEaInformation = 7, 213 | FileAccessInformation = 8, 214 | FileNameInformation = 9, 215 | FileRenameInformation = 10, 216 | FileLinkInformation = 11, 217 | FileNamesInformation = 12, 218 | FileDispositionInformation = 13, 219 | FilePositionInformation = 14, 220 | FileFullEaInformation = 15, 221 | FileModeInformation = 16, 222 | FileAlignmentInformation = 17, 223 | FileAllInformation = 18, 224 | FileAllocationInformation = 19, 225 | FileEndOfFileInformation = 20, 226 | FileAlternateNameInformation = 21, 227 | FileStreamInformation = 22, 228 | FilePipeInformation = 23, 229 | FilePipeLocalInformation = 24, 230 | FilePipeRemoteInformation = 25, 231 | FileMailslotQueryInformation = 26, 232 | FileMailslotSetInformation = 27, 233 | FileCompressionInformation = 28, 234 | FileObjectIdInformation = 29, 235 | FileCompletionInformation = 30, 236 | FileMoveClusterInformation = 31, 237 | FileQuotaInformation = 32, 238 | FileReparsePointInformation = 33, 239 | FileNetworkOpenInformation = 34, 240 | FileAttributeTagInformation = 35, 241 | FileTrackingInformation = 36, 242 | FileIdBothDirectoryInformation = 37, 243 | FileIdFullDirectoryInformation = 38, 244 | FileValidDataLengthInformation = 39, 245 | FileShortNameInformation = 40, 246 | FileIoCompletionNotificationInformation = 41, 247 | FileIoStatusBlockRangeInformation = 42, 248 | FileIoPriorityHintInformation = 43, 249 | FileSfioReserveInformation = 44, 250 | FileSfioVolumeInformation = 45, 251 | FileHardLinkInformation = 46, 252 | FileProcessIdsUsingFileInformation = 47, 253 | FileNormalizedNameInformation = 48, 254 | FileNetworkPhysicalNameInformation = 49, 255 | FileIdGlobalTxDirectoryInformation = 50, 256 | FileIsRemoteDeviceInformation = 51, 257 | FileUnusedInformation = 52, 258 | FileNumaNodeInformation = 53, 259 | FileStandardLinkInformation = 54, 260 | FileRemoteProtocolInformation = 55, 261 | FileRenameInformationBypassAccessCheck = 56, 262 | FileLinkInformationBypassAccessCheck = 57, 263 | FileVolumeNameInformation = 58, 264 | FileIdInformation = 59, 265 | FileIdExtdDirectoryInformation = 60, 266 | FileReplaceCompletionInformation = 61, 267 | FileHardLinkFullIdInformation = 62, 268 | FileIdExtdBothDirectoryInformation = 63, 269 | FileDispositionInformationEx = 64, 270 | FileRenameInformationEx = 65, 271 | FileRenameInformationExBypassAccessCheck = 66, 272 | FileMaximumInformation = 67, 273 | } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; 274 | 275 | typedef struct _PS_ATTRIBUTE_LIST 276 | { 277 | SIZE_T TotalLength; 278 | PS_ATTRIBUTE Attributes[1]; 279 | } PS_ATTRIBUTE_LIST, *PPS_ATTRIBUTE_LIST; 280 | 281 | EXTERN_C NTSTATUS NtCreateProcess( 282 | OUT PHANDLE ProcessHandle, 283 | IN ACCESS_MASK DesiredAccess, 284 | IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, 285 | IN HANDLE ParentProcess, 286 | IN BOOLEAN InheritObjectTable, 287 | IN HANDLE SectionHandle OPTIONAL, 288 | IN HANDLE DebugPort OPTIONAL, 289 | IN HANDLE ExceptionPort OPTIONAL); 290 | 291 | EXTERN_C NTSTATUS NtCreateThreadEx( 292 | OUT PHANDLE ThreadHandle, 293 | IN ACCESS_MASK DesiredAccess, 294 | IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, 295 | IN HANDLE ProcessHandle, 296 | IN PVOID StartRoutine, 297 | IN PVOID Argument OPTIONAL, 298 | IN ULONG CreateFlags, 299 | IN SIZE_T ZeroBits, 300 | IN SIZE_T StackSize, 301 | IN SIZE_T MaximumStackSize, 302 | IN PPS_ATTRIBUTE_LIST AttributeList OPTIONAL); 303 | 304 | EXTERN_C NTSTATUS NtOpenProcess( 305 | OUT PHANDLE ProcessHandle, 306 | IN ACCESS_MASK DesiredAccess, 307 | IN POBJECT_ATTRIBUTES ObjectAttributes, 308 | IN PCLIENT_ID ClientId OPTIONAL); 309 | 310 | EXTERN_C NTSTATUS NtOpenProcessToken( 311 | IN HANDLE ProcessHandle, 312 | IN ACCESS_MASK DesiredAccess, 313 | OUT PHANDLE TokenHandle); 314 | 315 | EXTERN_C NTSTATUS NtTestAlert(); 316 | 317 | EXTERN_C NTSTATUS NtOpenThread( 318 | OUT PHANDLE ThreadHandle, 319 | IN ACCESS_MASK DesiredAccess, 320 | IN POBJECT_ATTRIBUTES ObjectAttributes, 321 | IN PCLIENT_ID ClientId OPTIONAL); 322 | 323 | EXTERN_C NTSTATUS NtSuspendProcess( 324 | IN HANDLE ProcessHandle); 325 | 326 | EXTERN_C NTSTATUS NtSuspendThread( 327 | IN HANDLE ThreadHandle, 328 | OUT PULONG PreviousSuspendCount); 329 | 330 | EXTERN_C NTSTATUS NtResumeProcess( 331 | IN HANDLE ProcessHandle); 332 | 333 | EXTERN_C NTSTATUS NtResumeThread( 334 | IN HANDLE ThreadHandle, 335 | IN OUT PULONG PreviousSuspendCount OPTIONAL); 336 | 337 | EXTERN_C NTSTATUS NtGetContextThread( 338 | IN HANDLE ThreadHandle, 339 | IN OUT PCONTEXT ThreadContext); 340 | 341 | EXTERN_C NTSTATUS NtSetContextThread( 342 | IN HANDLE ThreadHandle, 343 | IN PCONTEXT Context); 344 | 345 | EXTERN_C NTSTATUS NtClose( 346 | IN HANDLE Handle); 347 | 348 | EXTERN_C NTSTATUS NtReadVirtualMemory( 349 | IN HANDLE ProcessHandle, 350 | IN PVOID BaseAddress OPTIONAL, 351 | OUT PVOID Buffer, 352 | IN SIZE_T BufferSize, 353 | OUT PSIZE_T NumberOfBytesRead OPTIONAL); 354 | 355 | EXTERN_C NTSTATUS NtWriteVirtualMemory( 356 | IN HANDLE ProcessHandle, 357 | IN PVOID BaseAddress, 358 | IN PVOID Buffer, 359 | IN SIZE_T NumberOfBytesToWrite, 360 | OUT PSIZE_T NumberOfBytesWritten OPTIONAL); 361 | 362 | EXTERN_C NTSTATUS NtAllocateVirtualMemory( 363 | IN HANDLE ProcessHandle, 364 | IN OUT PVOID * BaseAddress, 365 | IN ULONG ZeroBits, 366 | IN OUT PSIZE_T RegionSize, 367 | IN ULONG AllocationType, 368 | IN ULONG Protect); 369 | 370 | EXTERN_C NTSTATUS NtProtectVirtualMemory( 371 | IN HANDLE ProcessHandle, 372 | IN OUT PVOID * BaseAddress, 373 | IN OUT PSIZE_T RegionSize, 374 | IN ULONG NewProtect, 375 | OUT PULONG OldProtect); 376 | 377 | EXTERN_C NTSTATUS NtFreeVirtualMemory( 378 | IN HANDLE ProcessHandle, 379 | IN OUT PVOID * BaseAddress, 380 | IN OUT PSIZE_T RegionSize, 381 | IN ULONG FreeType); 382 | 383 | EXTERN_C NTSTATUS NtQuerySystemInformation( 384 | IN SYSTEM_INFORMATION_CLASS SystemInformationClass, 385 | IN OUT PVOID SystemInformation, 386 | IN ULONG SystemInformationLength, 387 | OUT PULONG ReturnLength OPTIONAL); 388 | 389 | EXTERN_C NTSTATUS NtQueryDirectoryFile( 390 | IN HANDLE FileHandle, 391 | IN HANDLE Event OPTIONAL, 392 | IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, 393 | IN PVOID ApcContext OPTIONAL, 394 | OUT PIO_STATUS_BLOCK IoStatusBlock, 395 | OUT PVOID FileInformation, 396 | IN ULONG Length, 397 | IN FILE_INFORMATION_CLASS FileInformationClass, 398 | IN BOOLEAN ReturnSingleEntry, 399 | IN PUNICODE_STRING FileName OPTIONAL, 400 | IN BOOLEAN RestartScan); 401 | 402 | EXTERN_C NTSTATUS NtQueryInformationFile( 403 | IN HANDLE FileHandle, 404 | OUT PIO_STATUS_BLOCK IoStatusBlock, 405 | OUT PVOID FileInformation, 406 | IN ULONG Length, 407 | IN FILE_INFORMATION_CLASS FileInformationClass); 408 | 409 | EXTERN_C NTSTATUS NtQueryInformationProcess( 410 | IN HANDLE ProcessHandle, 411 | IN PROCESSINFOCLASS ProcessInformationClass, 412 | OUT PVOID ProcessInformation, 413 | IN ULONG ProcessInformationLength, 414 | OUT PULONG ReturnLength OPTIONAL); 415 | 416 | EXTERN_C NTSTATUS NtQueryInformationThread( 417 | IN HANDLE ThreadHandle, 418 | IN THREADINFOCLASS ThreadInformationClass, 419 | OUT PVOID ThreadInformation, 420 | IN ULONG ThreadInformationLength, 421 | OUT PULONG ReturnLength OPTIONAL); 422 | 423 | EXTERN_C NTSTATUS NtCreateSection( 424 | OUT PHANDLE SectionHandle, 425 | IN ACCESS_MASK DesiredAccess, 426 | IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, 427 | IN PLARGE_INTEGER MaximumSize OPTIONAL, 428 | IN ULONG SectionPageProtection, 429 | IN ULONG AllocationAttributes, 430 | IN HANDLE FileHandle OPTIONAL); 431 | 432 | EXTERN_C NTSTATUS NtOpenSection( 433 | OUT PHANDLE SectionHandle, 434 | IN ACCESS_MASK DesiredAccess, 435 | IN POBJECT_ATTRIBUTES ObjectAttributes); 436 | 437 | EXTERN_C NTSTATUS NtMapViewOfSection( 438 | IN HANDLE SectionHandle, 439 | IN HANDLE ProcessHandle, 440 | IN OUT PVOID BaseAddress, 441 | IN ULONG ZeroBits, 442 | IN SIZE_T CommitSize, 443 | IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, 444 | IN OUT PSIZE_T ViewSize, 445 | IN SECTION_INHERIT InheritDisposition, 446 | IN ULONG AllocationType, 447 | IN ULONG Win32Protect); 448 | 449 | EXTERN_C NTSTATUS NtUnmapViewOfSection( 450 | IN HANDLE ProcessHandle, 451 | IN PVOID BaseAddress); 452 | 453 | EXTERN_C NTSTATUS NtAdjustPrivilegesToken( 454 | IN HANDLE TokenHandle, 455 | IN BOOLEAN DisableAllPrivileges, 456 | IN PTOKEN_PRIVILEGES NewState OPTIONAL, 457 | IN ULONG BufferLength, 458 | OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL, 459 | OUT PULONG ReturnLength OPTIONAL); 460 | 461 | EXTERN_C NTSTATUS NtDeviceIoControlFile( 462 | IN HANDLE FileHandle, 463 | IN HANDLE Event OPTIONAL, 464 | IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, 465 | IN PVOID ApcContext OPTIONAL, 466 | OUT PIO_STATUS_BLOCK IoStatusBlock, 467 | IN ULONG IoControlCode, 468 | IN PVOID InputBuffer OPTIONAL, 469 | IN ULONG InputBufferLength, 470 | OUT PVOID OutputBuffer OPTIONAL, 471 | IN ULONG OutputBufferLength); 472 | 473 | EXTERN_C NTSTATUS NtQueueApcThread( 474 | IN HANDLE ThreadHandle, 475 | IN PKNORMAL_ROUTINE ApcRoutine, 476 | IN PVOID ApcArgument1 OPTIONAL, 477 | IN PVOID ApcArgument2 OPTIONAL, 478 | IN PVOID ApcArgument3 OPTIONAL); 479 | 480 | EXTERN_C NTSTATUS NtWaitForMultipleObjects( 481 | IN ULONG Count, 482 | IN PHANDLE Handles, 483 | IN WAIT_TYPE WaitType, 484 | IN BOOLEAN Alertable, 485 | IN PLARGE_INTEGER Timeout OPTIONAL); 486 | 487 | #endif 488 | -------------------------------------------------------------------------------- /syswhispers.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import argparse 4 | import json 5 | import os 6 | import random 7 | import re 8 | import string 9 | import struct 10 | from enum import Enum 11 | from pathlib import Path 12 | 13 | 14 | def fetch_all_type_definitions(code) -> list: 15 | """Fetch all type definitions from a given code 16 | 17 | Args: 18 | code (str): The code to parse 19 | 20 | Returns: 21 | list: The list of all type definitions (tuple of 4 elements) found in the code 22 | """ 23 | return re.findall(r"typedef\s+(\w+)\s+(\w+)\s+([\w|*]*)\s*([\w|*]*)", code, re.DOTALL) 24 | 25 | 26 | def fetch_inner_enum_definitions(code) -> list: 27 | """Fetch all type definitions from a given code 28 | 29 | Args: 30 | code (str): The code to parse 31 | 32 | Returns: 33 | list: The list of all enum definitions (tuple of 2 elements) found in the code 34 | """ 35 | enum_list = [] 36 | code = code.replace("\r", "") 37 | code = re.sub(r"/\*.*?\*/", "", code, re.DOTALL | re.MULTILINE) 38 | for x, y in re.findall(r"typedef\s+enum\s+(\w+)\s*{([^}]+)\s*}", code, re.DOTALL | re.MULTILINE): 39 | for line in y.splitlines(): 40 | if line.startswith("//"): 41 | continue 42 | line = re.sub("//.*$", "", line) 43 | if line.strip() == "": 44 | continue 45 | line = line.split("=")[0].replace(",", "").strip() 46 | enum_list.append((x, line)) 47 | 48 | return enum_list 49 | 50 | 51 | def fetch_includes(code) -> list: 52 | """ 53 | Fetch all includes from a given code 54 | 55 | Args: 56 | code (str): The code to parse 57 | 58 | Returns: 59 | list: The list of all includes found in the code 60 | """ 61 | 62 | _includes = [] 63 | code = code.replace("\r", "") 64 | code = re.sub(r"/\*.*?\*/", "", code, re.DOTALL | re.MULTILINE) 65 | for x in re.findall(r'#include\s+\"\s*([^"]+)\s*\"', code, re.DOTALL | re.MULTILINE): 66 | _includes.append(x.strip()) 67 | for x in re.findall(r'#include\s+<\s*([^>]+)\s*>', code, re.DOTALL | re.MULTILINE): 68 | _includes.append(x.strip()) 69 | 70 | return _includes 71 | 72 | 73 | try: 74 | from enums.Architectures import Arch 75 | from enums.Compilers import Compiler 76 | from enums.SyscallRecoveryType import SyscallRecoveryType 77 | from utils.utils import get_project_root 78 | 79 | base_directory = os.path.join(get_project_root(), 'syscalls', 'syswhispersv3') 80 | define_search_and_replace = False 81 | 82 | except ModuleNotFoundError: 83 | def get_project_root() -> Path: 84 | return Path(__file__).parent 85 | 86 | 87 | base_directory = get_project_root() 88 | define_search_and_replace = True 89 | 90 | 91 | class Arch(Enum): 92 | Any = "" 93 | x86 = "x86" 94 | x64 = "x64" 95 | 96 | @staticmethod 97 | def from_string(label): 98 | if label.lower() in ["any", "all"]: 99 | return Arch.Any 100 | elif label.lower() in ["32", "86", "x86", "i386"]: 101 | return Arch.x86 102 | elif label.lower() in ["64", "x64", "amd64", "x86_64"]: 103 | return Arch.x64 104 | 105 | 106 | class Compiler(Enum): 107 | All = "" 108 | MSVC = "MSVC" 109 | MINGW = "MinGW" 110 | 111 | @staticmethod 112 | def from_string(label): 113 | if label.lower() in ["all"]: 114 | return Compiler.All 115 | elif label.lower() in ["msvc"]: 116 | return Compiler.MSVC 117 | elif label.lower() in ["mingw"]: 118 | return Compiler.MINGW 119 | 120 | 121 | # Define SyscallRecoveryType 122 | class SyscallRecoveryType(Enum): 123 | EMBEDDED = 0 124 | EGG_HUNTER = 1 125 | JUMPER = 2 126 | JUMPER_RANDOMIZED = 3 127 | 128 | @classmethod 129 | def from_name_or_default(cls, name): 130 | _types = dict(map(lambda c: (c.name.lower(), c.value), cls)) 131 | return SyscallRecoveryType(_types[name]) if name in _types.keys() else SyscallRecoveryType.EMBEDDED 132 | 133 | @classmethod 134 | def get_name(cls, value): 135 | if isinstance(value, str): 136 | value = int(value) 137 | _types = dict(map(lambda c: (c.value, c.name.lower()), cls)) 138 | return _types[value] if value in _types.keys() else None 139 | 140 | @classmethod 141 | def from_name(cls, name): 142 | _types = dict(map(lambda c: (c.name.lower(), c.value), cls)) 143 | return _types[name] if name in _types.keys() else None 144 | 145 | @classmethod 146 | def value_list(cls): 147 | return list(map(lambda c: c.value, cls)) 148 | 149 | @classmethod 150 | def key_list(cls): 151 | return list(map(lambda c: c.name.lower(), cls)) 152 | 153 | 154 | class SysWhispers(object): 155 | def __init__( 156 | self, 157 | arch: Arch = Arch.x64, 158 | compiler: Compiler = Compiler.MSVC, 159 | recovery: SyscallRecoveryType = SyscallRecoveryType.EMBEDDED, 160 | syscall_instruction: str = "syscall", 161 | wow64: bool = False, 162 | verbose: bool = False, 163 | debug: bool = False, 164 | prefix: str = 'SW3', 165 | alternative_headers: list = None, 166 | no_windows_headers: bool = False): 167 | self.no_windows_headers = no_windows_headers 168 | self.prefix = prefix 169 | self.arch = arch 170 | self.compiler = compiler 171 | self.recovery = recovery 172 | self.wow64 = wow64 173 | self.syscall_instruction = syscall_instruction 174 | self.egg = [hex(ord(random.choices(string.ascii_lowercase, k=1)[0])), "0x0", "0x0", 175 | hex(ord(random.choices(string.ascii_lowercase, k=1)[0]))] 176 | self.seed = random.randint(2 ** 28, 2 ** 32 - 1) 177 | self.typedefs: list = json.load( 178 | open(os.path.join(base_directory, 'data', 'typedefs.json'))) 179 | self.prototypes: dict = json.load( 180 | open(os.path.join(base_directory, 'data', 'prototypes.json'))) 181 | self.verbose = verbose 182 | self.debug = debug 183 | self.structured_types = [] 184 | self.replaced_types = [] 185 | 186 | self.alternative_headers = alternative_headers if alternative_headers else [] 187 | self.includes = [] 188 | self.already_defined_types = [] 189 | self.already_defined_enums = [] 190 | self.populate_defined_types() 191 | 192 | self.validate() 193 | 194 | def __find_header_files(self): 195 | print("[*] Searching for alternative header files...", end="") 196 | for i in range(len(self.alternative_headers)): 197 | if self.alternative_headers[i].startswith("+"): 198 | self.includes.append(self.alternative_headers[i][1:]) 199 | self.alternative_headers[i] = self.alternative_headers[i][1:] 200 | print("done") 201 | print("[*] Resolving header files...", end="") 202 | for _p in self.alternative_headers.copy(): 203 | p = Path(_p).absolute().resolve() 204 | if not p.exists(): 205 | self.alternative_headers.remove(_p) 206 | elif p.is_file(): 207 | self.alternative_headers.remove(_p) 208 | self.alternative_headers.append(p) 209 | continue 210 | elif p.is_dir(): 211 | self.alternative_headers.remove(_p) 212 | for f in p.glob("**/*.h"): 213 | self.alternative_headers.append(f) 214 | print("done") 215 | 216 | print("[*] Recursively resolving header files from #include directives...", end="") 217 | alternative_headers = [] 218 | found = True 219 | while found: 220 | alternative_headers = self.alternative_headers.copy() 221 | for f in alternative_headers: 222 | p = Path(f).absolute().resolve().parent 223 | with open(f, 'r') as fh: 224 | code = fh.read() 225 | for i in fetch_includes(code): 226 | try: 227 | _p_i = Path(i).relative_to(p).absolute().resolve() 228 | if _p_i not in self.alternative_headers: 229 | self.alternative_headers.append(_p_i) 230 | except ValueError: 231 | pass 232 | found = len(alternative_headers) != len(self.alternative_headers) 233 | 234 | print("done") 235 | 236 | print("[*] Removing duplicates...", end="") 237 | self.alternative_headers = list(set(self.alternative_headers)) 238 | print("done") 239 | 240 | def populate_defined_types(self): 241 | self.__find_header_files() 242 | 243 | typedefs = [] 244 | 245 | for f in self.alternative_headers: 246 | with open(f, 'r') as fh: 247 | code = fh.read() 248 | typedefs += fetch_all_type_definitions(code) 249 | self.already_defined_enums += fetch_inner_enum_definitions(code) 250 | 251 | for x1, x2 in self.already_defined_enums: 252 | for y in self.typedefs: 253 | code = y.get("definition") 254 | _c_t = fetch_all_type_definitions(code) 255 | if len(_c_t) == 0 or len(_c_t[0]) == 0 or _c_t[0][0] != "enum": 256 | continue 257 | _c_e = fetch_inner_enum_definitions(code) 258 | if len(_c_e) == 0: 259 | continue 260 | 261 | for _z1, _z2 in _c_e: 262 | if x2 == _z2: 263 | if x1[1:] not in y.get("identifiers"): 264 | new_type_alias = x1[1:] 265 | y["definition"] = y["definition"].replace(_z1[1:], new_type_alias) 266 | # print("corresponding enum found: ", _z1, x1, y.get("identifiers")) 267 | for function, details in self.prototypes.items(): 268 | for param in details["params"]: 269 | if param["type"] in y.get("identifiers"): 270 | param["type"] = param["type"].replace(_z1[1:], new_type_alias) 271 | # print("function using type found: ", function, param["type"], param["name"]) 272 | break 273 | 274 | for k1, k2, k3, k4 in typedefs: 275 | if k1 not in ["struct", "enum", "union", "const"]: 276 | self.already_defined_types.append(k1) 277 | else: 278 | self.already_defined_types.append(k2) 279 | 280 | self.already_defined_types = list(set(self.already_defined_types)) 281 | 282 | 283 | def validate(self): 284 | if self.recovery == SyscallRecoveryType.EGG_HUNTER: 285 | if self.compiler in [Compiler.All, Compiler.MINGW]: 286 | # TODO: try to make the 'db' instruction work in MinGW 287 | exit("[-] Egg-Hunter not compatible with MinGW") 288 | 289 | print(r"[*] With the egg-hunter, you need to use a search-replace functionality:") 290 | print(f" unsigned char egg[] = {{ {', '.join([hex(int(x, 16)) for x in self.egg] * 2)} }}; // egg") 291 | replace_x86 = ' unsigned char replace[] = { 0x0f, 0x34, 0x90, 0x90, 0xC3, 0x90, 0xCC, 0xCC }; // sysenter; nop; nop; ret; nop; int3; int3' 292 | replace_x64 = ' unsigned char replace[] = { 0x0f, 0x05, 0x90, 0x90, 0xC3, 0x90, 0xCC, 0xCC }; // syscall; nop; nop; ret; nop; int3; int3' 293 | if self.arch == Arch.Any: 294 | print(f"#ifdef _WIN64\n{replace_x64}\n#else\n{replace_x86}\n#endif") 295 | elif self.arch == Arch.x86: 296 | print(replace_x86) 297 | else: 298 | print(replace_x64) 299 | print() 300 | 301 | def generate(self, function_names: list = (), basename: str = 'syscalls'): 302 | if not function_names: 303 | function_names = list(self.prototypes.keys()) 304 | elif any([f not in self.prototypes.keys() for f in function_names]): 305 | raise ValueError('Prototypes are not available for one or more of the requested functions.') 306 | 307 | # Write C file. 308 | with open(os.path.join(base_directory, 'data', 'base.c'), 'rb') as base_source: 309 | with open(f'{basename}.c', 'wb') as output_source: 310 | base_source_contents = base_source.read().decode() 311 | 312 | if self.verbose: 313 | base_source_contents = base_source_contents.replace('//#define DEBUG', '#define DEBUG') 314 | 315 | base_source_contents = base_source_contents.replace('', os.path.basename(basename), 1) 316 | if self.recovery in [SyscallRecoveryType.JUMPER, SyscallRecoveryType.JUMPER_RANDOMIZED]: 317 | base_source_contents = base_source_contents.replace("// JUMPER", "#define JUMPER") 318 | 319 | if self.wow64: 320 | base_source_contents = base_source_contents.replace('// JUMP_TO_WOW32Reserved', 321 | ' // if we are a WoW64 process, jump to WOW32Reserved\n SyscallAddress = (PVOID)__readfsdword(0xc0);\n return SyscallAddress;') 322 | else: 323 | base_source_contents = base_source_contents.replace('// JUMP_TO_WOW32Reserved', 324 | ' return NULL;') 325 | 326 | 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' 327 | 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}' 328 | wow64_function = '' 329 | if self.compiler == Compiler.All: 330 | wow64_function += '#if defined(_MSC_VER)\n\n' 331 | wow64_function += msvc_wow64 332 | wow64_function += '\n\n#elif defined(__GNUC__)\n\n' 333 | wow64_function += mingw_wow64 334 | wow64_function += '\n\n#endif' 335 | elif self.compiler == Compiler.MSVC: 336 | wow64_function += msvc_wow64 337 | elif self.compiler == Compiler.MINGW: 338 | wow64_function += mingw_wow64 339 | base_source_contents = base_source_contents.replace('// LOCAL_IS_WOW64', wow64_function) 340 | 341 | output_source.write(base_source_contents.encode()) 342 | 343 | if self.compiler in [Compiler.All, Compiler.MINGW]: 344 | output_source.write('#if defined(__GNUC__)\n\n'.encode()) 345 | for function_name in function_names: 346 | output_source.write((self._get_function_asm_code_mingw(function_name) + '\n').encode()) 347 | output_source.write('#endif\n'.encode()) 348 | 349 | basename_suffix = '' 350 | basename_suffix = basename_suffix.capitalize() if os.path.basename(basename).istitle() else basename_suffix 351 | if self.compiler in [Compiler.All, Compiler.MSVC]: 352 | if self.arch in [Arch.Any, Arch.x64]: 353 | # Write x64 ASM file 354 | basename_suffix = f'_{basename_suffix}' if '_' in basename else basename_suffix 355 | with open(f'{basename}{basename_suffix}-asm.x64.asm', 'wb') as output_asm: 356 | output_asm.write(b'.code\n\nEXTERN SW3_GetSyscallNumber: PROC\n\n') 357 | if self.recovery == SyscallRecoveryType.JUMPER: 358 | # We perform a direct jump to the syscall instruction inside ntdll.dll 359 | output_asm.write(b'EXTERN SW3_GetSyscallAddress: PROC\n\n') 360 | 361 | elif self.recovery == SyscallRecoveryType.JUMPER_RANDOMIZED: 362 | # We perform a direct jump to a syscall instruction of another API 363 | output_asm.write(b'EXTERN SW3_GetRandomSyscallAddress: PROC\n\n') 364 | 365 | for function_name in function_names: 366 | output_asm.write((self._get_function_asm_code_msvc(function_name, Arch.x64) + '\n').encode()) 367 | 368 | output_asm.write(b'end') 369 | 370 | if self.arch in [Arch.Any, Arch.x86]: 371 | # Write x86 ASM file 372 | with open(f'{basename}{basename_suffix}-asm.x86.asm', 'wb') as output_asm: 373 | 374 | output_asm.write(b".686\n.XMM\n.MODEL flat, c\nASSUME fs:_DATA\n.code\n\n") 375 | 376 | output_asm.write( 377 | b'EXTERN SW3_GetSyscallNumber: PROC\nEXTERN local_is_wow64: PROC\nEXTERN internal_cleancall_wow64_gate: PROC') 378 | if self.recovery == SyscallRecoveryType.JUMPER: 379 | # We perform a direct jump to the syscall instruction inside ntdll.dll 380 | output_asm.write(b'\nEXTERN SW3_GetSyscallAddress: PROC') 381 | 382 | elif self.recovery == SyscallRecoveryType.JUMPER_RANDOMIZED: 383 | # We perform a direct jump to a syscall instruction of another API 384 | output_asm.write(b'\nEXTERN SW3_GetRandomSyscallAddress: PROC') 385 | 386 | output_asm.write(b'\n\n') 387 | 388 | for function_name in function_names: 389 | output_asm.write((self._get_function_asm_code_msvc(function_name, Arch.x86) + '\n').encode()) 390 | 391 | output_asm.write(b'end') 392 | 393 | # Write header file. 394 | with open(os.path.join(base_directory, 'data', 'base.h'), 'rb') as base_header: 395 | with open(f'{basename}.h', 'wb') as output_header: 396 | # Replace with a random seed. 397 | base_header_contents = base_header.read().decode() 398 | base_header_contents = base_header_contents.replace('', f'0x{self.seed:08X}', 1) 399 | 400 | if self.alternative_headers: 401 | for f in self.includes: 402 | f = Path(f).absolute().resolve() 403 | base_header_contents = base_header_contents.replace('#include ', f'#include "{f}"\n#include ') 404 | if self.no_windows_headers: 405 | base_header_contents = base_header_contents.replace('#include ', '') 406 | 407 | # Write the base header. 408 | output_header.write(base_header_contents.encode()) 409 | 410 | # Write the typedefs. 411 | for typedef in self._get_typedefs(function_names): 412 | output_header.write(typedef.encode() + b'\n\n') 413 | 414 | # Write the function prototypes. 415 | for function_name in function_names: 416 | output_header.write((self._get_function_prototype(function_name) + '\n\n').encode()) 417 | 418 | # Write the endif line. 419 | output_header.write('#endif\n'.encode()) 420 | 421 | if self.verbose: 422 | print('[+] Complete! Files written to:') 423 | print(f'\t{basename}.h') 424 | print(f'\t{basename}.c') 425 | if self.arch in [Arch.x64, Arch.Any]: 426 | print(f'\t{basename}{basename_suffix}-asm.x64.asm') 427 | if self.arch in [Arch.x86, Arch.Any]: 428 | print(f'\t{basename}{basename_suffix}-asm.x86.asm') 429 | input("[/] Press a key to continue...") 430 | 431 | def _get_typedefs(self, function_names: list) -> list: 432 | def _names_to_ids(names: list) -> list: 433 | return [next(i for i, t in enumerate(self.typedefs) if n in t['identifiers']) for n in names] 434 | 435 | # Determine typedefs to use. 436 | used_typedefs = [] 437 | for function_name in function_names: 438 | for param in self.prototypes[function_name]['params']: 439 | if list(filter(lambda t: param['type'] in t['identifiers'], self.typedefs)): 440 | if param['type'] not in used_typedefs: 441 | used_typedefs.append(param['type']) 442 | 443 | # Resolve typedef dependencies. 444 | i = 0 445 | typedef_layers = {i: _names_to_ids(used_typedefs)} 446 | while True: 447 | # Identify dependencies of current layer. 448 | more_dependencies = [] 449 | for typedef_id in typedef_layers[i]: 450 | more_dependencies += self.typedefs[typedef_id].get('dependencies') 451 | more_dependencies = list(set(more_dependencies)) # Remove duplicates. 452 | 453 | if more_dependencies: 454 | # Create new layer. 455 | i += 1 456 | typedef_layers[i] = _names_to_ids(more_dependencies) 457 | else: 458 | # Remove duplicates between layers. 459 | for k in range(len(typedef_layers) - 1): 460 | typedef_layers[k] = set(typedef_layers[k]) - set(typedef_layers[k + 1]) 461 | break 462 | 463 | # Get code for each typedef. 464 | typedef_code = [] 465 | prefix = self.prefix + "_" if self.prefix else "" 466 | for i in range(max(typedef_layers.keys()), -1, -1): 467 | for j in typedef_layers[i]: 468 | code = self.typedefs[j].get('definition') 469 | if code.startswith('typedef') and code.split(" ")[1] in ["const", "struct", "enum"]: 470 | pname = code.split(" ")[2].split("\n")[0].strip() 471 | name = pname[1:] 472 | if pname in self.already_defined_types: 473 | continue 474 | 475 | 476 | # self.structured_types.append(name) 477 | # code = code.replace(name, prefix + name) 478 | # # Probably handle deps here 479 | # for dep in self.structured_types: 480 | # if dep != name and dep in code: 481 | # code = code.replace(dep + " ", prefix + dep + " ") 482 | # elif code.startswith('typedef'): 483 | # for dep in self.structured_types: 484 | # if dep in code: 485 | # code = code.replace(dep + " ", prefix + dep + " ") 486 | typedef_code.append(code) 487 | 488 | return typedef_code 489 | 490 | def _fix_type(self, _type: str) -> str: 491 | return _type 492 | # if self.prefix in [None, ""]: 493 | # return _type 494 | # if _type in self.structured_types: 495 | # return self.prefix + "_" + _type 496 | # 497 | # elif _type.startswith("P") and _type[1:] in self.structured_types: 498 | # return "P" + self.prefix + "_" + _type[1:] 499 | # 500 | # return _type 501 | 502 | def _get_function_prototype(self, function_name: str) -> str: 503 | # Check if given function is in syscall map. 504 | if function_name not in self.prototypes: 505 | raise ValueError('Invalid function name provided.') 506 | 507 | num_params = len(self.prototypes[function_name]['params']) 508 | signature = f'EXTERN_C NTSTATUS {self.prefix.capitalize()}{function_name}(' 509 | if num_params: 510 | for i in range(num_params): 511 | param = self.prototypes[function_name]['params'][i] 512 | 513 | _type = self._fix_type(param['type']) 514 | 515 | signature += '\n\t' 516 | signature += 'IN ' if param['in'] else '' 517 | signature += 'OUT ' if param['out'] else '' 518 | signature += f'{_type} {param["name"]}' 519 | signature += ' OPTIONAL' if param['optional'] else '' 520 | signature += ',' if i < num_params - 1 else ');' 521 | else: 522 | signature += ');' 523 | 524 | return signature 525 | 526 | def _get_function_hash(self, function_name: str): 527 | hash = self.seed 528 | name = function_name.replace('Nt', 'Zw', 1) + '\0' 529 | ror8 = lambda v: ((v >> 8) & (2 ** 32 - 1)) | ((v << 24) & (2 ** 32 - 1)) 530 | 531 | for segment in [s for s in [name[i:i + 2] for i in range(len(name))] if len(s) == 2]: 532 | partial_name_short = struct.unpack(' str: 538 | function_hash = self._get_function_hash(function_name) 539 | num_params = len(self.prototypes[function_name]['params']) 540 | prototype = self._get_function_prototype(function_name) 541 | prototype = prototype.replace('EXTERN_C', '__declspec(naked)') 542 | prototype = prototype.replace(');', ')') 543 | 544 | code = prototype 545 | code += '\n{' 546 | code += '\n\tasm(' 547 | if self.arch == Arch.Any: 548 | code += '\n#if defined(_WIN64)' 549 | if self.arch in [Arch.Any, Arch.x64]: 550 | # Generate 64-bit ASM code. 551 | code += '\n\t\t"mov [rsp +8], rcx \\n"' 552 | code += '\n\t\t"mov [rsp+16], rdx \\n"' 553 | code += '\n\t\t"mov [rsp+24], r8 \\n"' 554 | code += '\n\t\t"mov [rsp+32], r9 \\n"' 555 | code += '\n\t\t"sub rsp, 0x28 \\n"' 556 | code += f'\n\t\t"mov ecx, 0x{function_hash:08X} \\n"' 557 | if self.recovery in [SyscallRecoveryType.JUMPER, SyscallRecoveryType.JUMPER_RANDOMIZED]: 558 | if self.recovery == SyscallRecoveryType.JUMPER_RANDOMIZED: 559 | code += '\n\t\t"call SW3_GetRandomSyscallAddress \\n"' 560 | else: 561 | code += '\n\t\t"call SW3_GetSyscallAddress \\n"' 562 | code += '\n\t\t"mov r11, rax \\n"' 563 | code += f'\n\t\t"mov ecx, 0x{function_hash:08X} \\n"' 564 | code += '\n\t\t"call SW3_GetSyscallNumber \\n"' 565 | code += '\n\t\t"add rsp, 0x28 \\n"' 566 | code += '\n\t\t"mov rcx, [rsp+8] \\n"' 567 | code += '\n\t\t"mov rdx, [rsp+16] \\n"' 568 | code += '\n\t\t"mov r8, [rsp+24] \\n"' 569 | code += '\n\t\t"mov r9, [rsp+32] \\n"' 570 | code += '\n\t\t"mov r10, rcx \\n"' 571 | if self.debug: 572 | code += '\n\t\t"int 3 \\n"' 573 | 574 | if self.recovery in [SyscallRecoveryType.JUMPER, SyscallRecoveryType.JUMPER_RANDOMIZED]: 575 | code += '\n\t\t"jmp r11 \\n"' 576 | elif self.recovery == SyscallRecoveryType.EGG_HUNTER: 577 | for x in self.egg + self.egg: 578 | code += f'\n\t\t"DB {x} \\n"' 579 | code += '\n\t\t"ret \\n"' 580 | elif self.recovery == SyscallRecoveryType.EMBEDDED: 581 | code += f'\n\t\t"{self.syscall_instruction} \\n"' 582 | code += '\n\t\t"ret \\n"' 583 | 584 | if self.arch == Arch.Any: 585 | code += '\n#else' 586 | 587 | if self.arch in [Arch.Any, Arch.x86]: 588 | code += '\n\t\t"push ebp \\n"' 589 | code += '\n\t\t"mov ebp, esp \\n"' 590 | code += f'\n\t\t"push 0x{function_hash:08X} \\n"' 591 | 592 | if self.recovery in [SyscallRecoveryType.JUMPER, SyscallRecoveryType.JUMPER_RANDOMIZED]: 593 | if self.recovery == SyscallRecoveryType.JUMPER_RANDOMIZED: 594 | code += '\n\t\t"call _SW3_GetRandomSyscallAddress \\n"' 595 | else: 596 | code += '\n\t\t"call _SW3_GetSyscallAddress \\n"' 597 | code += '\n\t\t"mov edi, eax \\n"' 598 | code += f'\n\t\t"push 0x{function_hash:08X} \\n"' 599 | code += '\n\t\t"call _SW3_GetSyscallNumber \\n"' 600 | code += '\n\t\t"lea esp, [esp+4] \\n"' 601 | code += f'\n\t\t"mov ecx, {hex(num_params)} \\n"' 602 | code += f'\n\t"push_argument_{function_hash:08X}: \\n"' 603 | code += '\n\t\t"dec ecx \\n"' 604 | code += '\n\t\t"push [ebp + 8 + ecx * 4] \\n"' 605 | code += f'\n\t\t"jnz push_argument_{function_hash:08X} \\n"' 606 | if self.debug: 607 | # 2nd SW breakpoint, to study the syscall instruction in detail 608 | code += '\n\t\t"int 3 \\n"' 609 | code += '\n\t\t"mov ecx, eax \\n"' 610 | 611 | if self.recovery not in [SyscallRecoveryType.JUMPER, 612 | SyscallRecoveryType.JUMPER_RANDOMIZED] \ 613 | and self.wow64: 614 | # check if the process is WoW64 or native 615 | code += '\n\t\t"call _local_is_wow64 \\n"' 616 | code += '\n\t\t"test eax, eax \\n"' 617 | code += '\n\t\t"je is_native \\n"' 618 | 619 | # if is wow64 620 | code += '\n\t\t"call _internal_cleancall_wow64_gate \\n"' 621 | code += f'\n\t\t"lea ebx, [ret_address_epilog_{function_hash:08X}] \\n"' 622 | code += '\n\t\t"push ebx \\n"' 623 | # Note: Workaround for Wow64 call 624 | # ntdll!NtWriteFile+0xc: 625 | # 77ca2a1c c22400 ret 24h 626 | # In a standard call, we have two addresses before the arguments passed to the Nt function 627 | # In this case, as we need to return to the program, we can insert the return address twice 628 | code += '\n\t\t"push ebx \\n"' 629 | code += '\n\t\t"xchg eax, ecx \\n"' 630 | code += '\n\t\t"jmp ecx \\n"' 631 | code += '\n\t\t"jmp finish \\n"' 632 | 633 | # if is native 634 | code += '\n\t"is_native: \\n"' 635 | 636 | code += '\n\t\t"mov eax, ecx \\n"' 637 | code += f'\n\t\t"lea ebx, [ret_address_epilog_{function_hash:08X}] \\n"' 638 | code += '\n\t\t"push ebx \\n"' 639 | code += f'\n\t\t"call do_sysenter_interrupt_{function_hash:08X} \\n"' 640 | 641 | if self.recovery not in [SyscallRecoveryType.JUMPER, 642 | SyscallRecoveryType.JUMPER_RANDOMIZED] \ 643 | and self.wow64: 644 | code += '\n\t"finish: \\n"' 645 | code += '\n\t\t"lea esp, [esp+4] \\n"' 646 | code += f'\n\t"ret_address_epilog_{function_hash:08X}: \\n"' 647 | code += '\n\t\t"mov esp, ebp \\n"' 648 | code += '\n\t\t"pop ebp \\n"' 649 | code += '\n\t\t"ret \\n"' 650 | 651 | code += f'\n\t"do_sysenter_interrupt_{function_hash:08X}: \\n"' 652 | code += '\n\t\t"mov edx, esp \\n"' 653 | 654 | if self.debug: 655 | code += '\n\t\t"int 3 \\n"' 656 | 657 | if self.recovery == SyscallRecoveryType.EGG_HUNTER: 658 | for x in self.egg + self.egg: 659 | code += f'\n\t\t"DB {x} \\n"' 660 | elif self.recovery in [SyscallRecoveryType.JUMPER, SyscallRecoveryType.JUMPER_RANDOMIZED]: 661 | code += '\n\t\t"jmp edi \\n"' 662 | else: 663 | code += '\n\t\t"sysenter \\n"' 664 | code += '\n\t\t"ret \\n"' 665 | 666 | if self.arch == Arch.Any: 667 | code += '\n#endif' 668 | code += '\n\t);' 669 | code += '\n}' 670 | code += '\n' 671 | 672 | return code 673 | 674 | def _get_function_asm_code_msvc(self, function_name: str, arch: Arch) -> str: 675 | function_hash = self._get_function_hash(function_name) 676 | num_params = len(self.prototypes[function_name]['params']) 677 | code = '' 678 | 679 | code += f'{self.prefix.capitalize()}{function_name} PROC\n' 680 | if arch == Arch.x64: 681 | # Generate 64-bit ASM code. 682 | if self.debug: 683 | code += '\tint 3\n' 684 | code += '\tmov [rsp +8], rcx ; Save registers.\n' 685 | code += '\tmov [rsp+16], rdx\n' 686 | code += '\tmov [rsp+24], r8\n' 687 | code += '\tmov [rsp+32], r9\n' 688 | code += '\tsub rsp, 28h\n' 689 | code += f'\tmov ecx, 0{function_hash:08X}h ; Load function hash into ECX.\n' 690 | if self.recovery in [SyscallRecoveryType.JUMPER, SyscallRecoveryType.JUMPER_RANDOMIZED]: 691 | if self.recovery == SyscallRecoveryType.JUMPER_RANDOMIZED: 692 | code += '\tcall SW3_GetRandomSyscallAddress ; Get a syscall offset from a different api.\n' 693 | else: 694 | code += '\tcall SW3_GetSyscallAddress ; Resolve function hash into syscall offset.\n' 695 | code += '\tmov r11, rax ; Save the address of the syscall\n' 696 | code += f'\tmov ecx, 0{function_hash:08X}h ; Re-Load function hash into ECX (optional).\n' 697 | code += '\tcall SW3_GetSyscallNumber ; Resolve function hash into syscall number.\n' 698 | code += '\tadd rsp, 28h\n' 699 | code += '\tmov rcx, [rsp+8] ; Restore registers.\n' 700 | code += '\tmov rdx, [rsp+16]\n' 701 | code += '\tmov r8, [rsp+24]\n' 702 | code += '\tmov r9, [rsp+32]\n' 703 | code += '\tmov r10, rcx\n' 704 | 705 | if self.debug: 706 | code += '\tint 3\n' 707 | 708 | if self.recovery in [SyscallRecoveryType.JUMPER, SyscallRecoveryType.JUMPER_RANDOMIZED]: 709 | code += '\tjmp r11 ; Jump to -> Invoke system call.\n' 710 | elif self.recovery == SyscallRecoveryType.EGG_HUNTER: 711 | for x in self.egg + self.egg: 712 | code += f'\tDB {x[2:]}h ; "{chr(int(x, 16)) if int(x, 16) != 0 else str(0)}"\n' 713 | code += '\tret\n' 714 | elif self.recovery == SyscallRecoveryType.EMBEDDED: 715 | code += f'\t{self.syscall_instruction} ; Invoke system call.\n' 716 | code += '\tret\n' 717 | else: 718 | # x32 Prolog 719 | code += '\t\tpush ebp\n' 720 | code += '\t\tmov ebp, esp\n' 721 | code += f'\t\tpush 0{function_hash:08X}h ; Load function hash into ECX.\n' 722 | 723 | if self.recovery in [SyscallRecoveryType.JUMPER, SyscallRecoveryType.JUMPER_RANDOMIZED]: 724 | if self.recovery == SyscallRecoveryType.JUMPER_RANDOMIZED: 725 | code += '\t\tcall SW3_GetRandomSyscallAddress ; Get a syscall offset from a different api.\n' 726 | else: 727 | code += '\t\tcall SW3_GetSyscallAddress ; Resolve function hash into syscall offset.\n' 728 | code += '\t\tmov edi, eax ; Save the address of the syscall\n' 729 | code += f'\t\tpush 0{function_hash:08X}h ; Re-Load function hash into ECX (optional).\n' 730 | code += '\t\tcall SW3_GetSyscallNumber\n' 731 | code += '\t\tlea esp, [esp+4]\n' 732 | code += f'\t\tmov ecx, 0{hex(num_params)[2:]}h\n' 733 | code += f'\tpush_argument_{function_hash:08X}:\n' 734 | code += '\t\tdec ecx\n' 735 | code += '\t\tpush [ebp + 8 + ecx * 4]\n' 736 | code += f'\t\tjnz push_argument_{function_hash:08X}\n' 737 | if self.debug: 738 | # 2nd SW breakpoint, to study the syscall instruction in detail 739 | code += '\t\tint 3\n' 740 | code += '\t\tmov ecx, eax\n' 741 | 742 | if self.recovery not in [SyscallRecoveryType.JUMPER, 743 | SyscallRecoveryType.JUMPER_RANDOMIZED] \ 744 | and self.wow64: 745 | # check if the process is WoW64 or native 746 | code += '\t\tcall local_is_wow64\n' 747 | code += '\t\ttest eax, eax\n' 748 | code += '\t\tje is_native\n' 749 | 750 | # if is wow64 751 | code += '\t\tcall internal_cleancall_wow64_gate\n' 752 | # Note: Workaround for Wow64 call 753 | # ntdll!NtWriteFile+0xc: 754 | # 77ca2a1c c22400 ret 24h 755 | # In a standard call, we have two addresses before the arguments passed to the Nt function 756 | # In this case, as we need to return to the program, we can insert the return address twice 757 | code += f'\t\tpush ret_address_epilog_{function_hash:08X}\n' 758 | code += f'\t\tpush ret_address_epilog_{function_hash:08X}\n' 759 | code += '\t\txchg eax, ecx\n' 760 | code += '\t\tjmp ecx\n' 761 | code += '\t\tjmp finish\n' 762 | 763 | # if is native 764 | code += '\tis_native:\n' 765 | 766 | code += '\t\tmov eax, ecx\n' 767 | code += f'\t\tpush ret_address_epilog_{function_hash:08X}\n' 768 | code += f'\t\tcall do_sysenter_interrupt_{function_hash:08X}\n' 769 | 770 | if self.recovery not in [SyscallRecoveryType.JUMPER, 771 | SyscallRecoveryType.JUMPER_RANDOMIZED] \ 772 | and self.wow64: 773 | code += '\tfinish:\n' 774 | code += '\t\tlea esp, [esp+4]\n' 775 | code += f'\tret_address_epilog_{function_hash:08X}:\n' 776 | code += '\t\tmov esp, ebp\n' 777 | code += '\t\tpop ebp\n' 778 | code += '\t\tret\n' 779 | 780 | code += f'\tdo_sysenter_interrupt_{function_hash:08X}:\n' 781 | code += '\t\tmov edx, esp\n' 782 | if self.recovery == SyscallRecoveryType.EGG_HUNTER: 783 | for x in self.egg + self.egg: 784 | code += f'\t\tDB {x[2:]}h ; "{chr(int(x, 16)) if int(x, 16) != 0 else str(0)}"\n' 785 | elif self.recovery in [SyscallRecoveryType.JUMPER, SyscallRecoveryType.JUMPER_RANDOMIZED]: 786 | code += '\t\tjmp edi\n' 787 | else: 788 | code += '\t\tsysenter\n' 789 | code += '\t\tret\n' 790 | code += f'{self.prefix.capitalize()}{function_name} ENDP\n' 791 | return code 792 | 793 | 794 | if __name__ == '__main__': 795 | print( 796 | " \n" 797 | " . ,--. \n" 798 | ",-. . . ,-. . , , |-. o ,-. ,-. ,-. ,-. ,-. __/ \n" 799 | "`-. | | `-. |/|/ | | | `-. | | |-' | `-. . \\ \n" 800 | "`-' `-| `-' ' ' ' ' ' `-' |-' `-' ' `-' ''' \n" 801 | " /| | @Jackson_T \n" 802 | " `-' ' @modexpblog, 2021 \n\n" 803 | " Edits by @klezVirus, 2022 \n" 804 | "SysWhispers3: Why call the kernel when you can whisper?\n\n" 805 | ) 806 | 807 | parser = argparse.ArgumentParser(description="SysWhispers3 - SysWhispers on steroids") 808 | parser.add_argument('-p', '--preset', help='Preset ("all", "common")', required=False) 809 | parser.add_argument('-a', '--arch', default="x64", choices=["x86", "x64", "all"], help='Architecture', 810 | required=False) 811 | parser.add_argument('-c', '--compiler', default="msvc", choices=["msvc", "mingw", "all"], help='Compiler', 812 | required=False) 813 | parser.add_argument('-m', '--method', default="embedded", 814 | choices=["embedded", "egg_hunter", "jumper", "jumper_randomized"], 815 | help='Syscall recovery method', required=False) 816 | parser.add_argument('-f', '--functions', help='Comma-separated functions', required=False) 817 | parser.add_argument('-o', '--out-file', help='Output basename (w/o extension)', required=True) 818 | parser.add_argument('--int2eh', default=False, action='store_true', 819 | help='Use the old `int 2eh` instruction in place of `syscall`', required=False) 820 | parser.add_argument('--wow64', default=False, action='store_true', 821 | help='Add support for WoW64, to run x86 on x64', required=False) 822 | parser.add_argument('-v', '--verbose', default=False, action='store_true', 823 | help='Enable debug output', required=False) 824 | parser.add_argument('-d', '--debug', default=False, action='store_true', 825 | help='Enable syscall debug (insert software breakpoint)', required=False) 826 | parser.add_argument('-P', '--prefix', default="SW3", type=str, 827 | help='Add prefix to function names to avoid pollution', required=False) 828 | parser.add_argument('-H', '--alternative-headers', default=[], action="append", 829 | help='Alternative headers files (e.g., phnt.h)', required=False) 830 | parser.add_argument('-nWH', '--no-win-headers', default=False, action="store_true", 831 | help='Do not add in syscalls.h', required=False) 832 | args = parser.parse_args() 833 | 834 | recovery = SyscallRecoveryType.from_name_or_default(args.method) 835 | arch = Arch.from_string(args.arch) 836 | compiler = Compiler.from_string(args.compiler) 837 | 838 | sw = SysWhispers( 839 | arch=arch, 840 | compiler=compiler, 841 | syscall_instruction="syscall" if not args.int2eh else "int 2eh", 842 | recovery=recovery, 843 | wow64=args.wow64, 844 | verbose=args.verbose, 845 | debug=args.debug, 846 | prefix=args.prefix, 847 | alternative_headers=args.alternative_headers, 848 | no_windows_headers=args.no_win_headers 849 | ) 850 | print() 851 | 852 | if args.preset == 'all': 853 | print('[I] All functions selected.\n') 854 | sw.generate(basename=args.out_file) 855 | 856 | elif args.preset == 'common': 857 | print('[I] Common functions selected.\n') 858 | sw.generate( 859 | ['NtCreateProcess', 860 | 'NtCreateThreadEx', 861 | 'NtOpenProcess', 862 | 'NtOpenProcessToken', 863 | 'NtTestAlert', 864 | 'NtOpenThread', 865 | 'NtSuspendProcess', 866 | 'NtSuspendThread', 867 | 'NtResumeProcess', 868 | 'NtResumeThread', 869 | 'NtGetContextThread', 870 | 'NtSetContextThread', 871 | 'NtClose', 872 | 'NtReadVirtualMemory', 873 | 'NtWriteVirtualMemory', 874 | 'NtAllocateVirtualMemory', 875 | 'NtProtectVirtualMemory', 876 | 'NtFreeVirtualMemory', 877 | 'NtQuerySystemInformation', 878 | 'NtQueryDirectoryFile', 879 | 'NtQueryInformationFile', 880 | 'NtQueryInformationProcess', 881 | 'NtQueryInformationThread', 882 | 'NtCreateSection', 883 | 'NtOpenSection', 884 | 'NtMapViewOfSection', 885 | 'NtUnmapViewOfSection', 886 | 'NtAdjustPrivilegesToken', 887 | 'NtDeviceIoControlFile', 888 | 'NtQueueApcThread', 889 | 'NtWaitForMultipleObjects'], 890 | basename=args.out_file) 891 | 892 | elif args.preset: 893 | print('[-] Invalid preset provided. Must be "all" or "common".') 894 | 895 | elif not args.functions: 896 | print('[-] --preset XOR --functions switch must be specified.\n') 897 | print('[H] ./syswhispers.py --preset common --out-file syscalls_common') 898 | print('[H] ./syswhispers.py --functions NtTestAlert,NtGetCurrentProcessorNumber --out-file syscalls_test') 899 | 900 | else: 901 | functions = args.functions.split(',') if args.functions else [] 902 | sw.generate(functions, args.out_file) 903 | --------------------------------------------------------------------------------