├── dist ├── process_protection_enum.x64.o └── process_protection_enum.cna ├── src ├── Makefile ├── beacon.h ├── main.c └── syscalls.h └── README.md /dist/process_protection_enum.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspressoCake/Process_Protection_Level_BOF/HEAD/dist/process_protection_enum.x64.o -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | BOFNAME := process_protection_enum 2 | CC_x64 := x86_64-w64-mingw32-gcc 3 | 4 | all: 5 | $(CC_x64) -o ../dist/$(BOFNAME).x64.o -c main.c -masm=intel 6 | 7 | clean: 8 | rm -f ../dist/$(BOFNAME).x64.o -------------------------------------------------------------------------------- /dist/process_protection_enum.cna: -------------------------------------------------------------------------------- 1 | beacon_command_register( 2 | "process_protection_enum", 3 | "Use syscalls to extract the process protection constants associated with a process identifier.", 4 | "Synopsis: process_protection_enum PID"); 5 | 6 | 7 | sub packAndExecuteBOF { 8 | local('$handle'); 9 | local('$file_data'); 10 | local('$args'); 11 | 12 | $handle = openf(script_resource("process_protection_enum.x64.o")); 13 | $data = readb($handle, -1); 14 | closef($handle); 15 | 16 | # Argument packer 17 | $args = bof_pack($1, "i", $2); 18 | 19 | # Task the Beacon 20 | btask($1, "Process Protection Enumerator (@the_bit_diddler)"); 21 | btask($1, "Attempting to gather handle to provided process: $+ $2"); 22 | 23 | # Execution with packed arguments 24 | beacon_inline_execute($1, $data, "go", $args); 25 | } 26 | 27 | alias process_protection_enum { 28 | # Ensure that we're in an x64 Session 29 | if ( !-is64 $1 ) { 30 | show_error("This must be a 64-bit process to work effectively. Exiting."); 31 | } else { 32 | if ( !-isadmin $1 ) { 33 | prompt_confirm("Unprivileged beacon, continue?", "Here Be Dragons", { 34 | packAndExecuteBOF($1, $2); 35 | }); 36 | } else { 37 | packAndExecuteBOF($1, $2); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Process Protection Level Enumerator BOF 2 | ## 3 | #### What is this? 4 | - A Syscall-only BOF file intended to grab process protection attributes, limited to a handful that _Red Team_ operators and _pentesters_ would commonly be interested in. 5 | ## 6 | #### What problem are you trying to solve? 7 | - There are great tools that exist in order to stealthily obtain access to and dump `LSASS` memory, thanks to some wonderful authors. 8 | - These (to my knowledge) do not currently preempt an operator from unintentionally using the aforementioned to grab a valid `handle` to the `LSASS` process 9 | - Existing tooling (outside of references in blog posts from the always-helpful [@itm4n](https://twitter.com/itm4n)) does not currently enumerate the protection levels of a given process. 10 | - Obtaining a handle to a [PPL](https://docs.microsoft.com/en-us/windows/win32/services/protecting-anti-malware-services-)-enabled process can lead to a _very_ dead `Beacon` in very short order 11 | - This aims to fill that void, allowing an operator to know exactly what a protection level of a desired process is (if any) before unintentionally shooting themselves in the foot and/or determine what their next step(s) would/should be, given the output 12 | ## 13 | #### How do I build this? 14 | ```sh 15 | git clone https://github.com/EspressoCake/Process_Protection_Level_BOF 16 | cd Process_Protection_Level_BOF/src 17 | make 18 | ``` 19 | 20 | #### How do I use this? 21 | - Load the `Aggressor` `.cna` file from the `dist` directory, after building 22 | - Determine whatever `PID` you wish to interrogate 23 | - From a given `Beacon`: 24 | ```sh 25 | process_protection_enum PROCESS_ID_NUMBER 26 | ``` 27 | ## 28 | #### I tend to touch the stove carelessly, how are you taking care of the injury-prone? 29 | - Currently, the `Aggressor` script has safeguards 30 | - The current `Beacon` is checked to ensure that it is administrative, and an `x64` process 31 | ## 32 | #### What does the output look like? 33 | ##### Protected Process Output 34 | ![](https://i.ibb.co/7nF0G7v/image.png) 35 | ##### Unprotected Process Output 36 | ![](https://i.ibb.co/SRLVtMn/image.png) 37 | -------------------------------------------------------------------------------- /src/beacon.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Beacon Object Files (BOF) 3 | * ------------------------- 4 | * A Beacon Object File is a light-weight post exploitation tool that runs 5 | * with Beacon's inline-execute command. 6 | * 7 | * Cobalt Strike 4.1. 8 | */ 9 | 10 | /* data API */ 11 | typedef struct { 12 | char * original; /* the original buffer [so we can free it] */ 13 | char * buffer; /* current pointer into our buffer */ 14 | int length; /* remaining length of data */ 15 | int size; /* total size of this buffer */ 16 | } datap; 17 | 18 | DECLSPEC_IMPORT void BeaconDataParse(datap * parser, char * buffer, int size); 19 | DECLSPEC_IMPORT int BeaconDataInt(datap * parser); 20 | DECLSPEC_IMPORT short BeaconDataShort(datap * parser); 21 | DECLSPEC_IMPORT int BeaconDataLength(datap * parser); 22 | DECLSPEC_IMPORT char * BeaconDataExtract(datap * parser, int * size); 23 | 24 | /* format API */ 25 | typedef struct { 26 | char * original; /* the original buffer [so we can free it] */ 27 | char * buffer; /* current pointer into our buffer */ 28 | int length; /* remaining length of data */ 29 | int size; /* total size of this buffer */ 30 | } formatp; 31 | 32 | DECLSPEC_IMPORT void BeaconFormatAlloc(formatp * format, int maxsz); 33 | DECLSPEC_IMPORT void BeaconFormatReset(formatp * format); 34 | DECLSPEC_IMPORT void BeaconFormatFree(formatp * format); 35 | DECLSPEC_IMPORT void BeaconFormatAppend(formatp * format, char * text, int len); 36 | DECLSPEC_IMPORT void BeaconFormatPrintf(formatp * format, char * fmt, ...); 37 | DECLSPEC_IMPORT char * BeaconFormatToString(formatp * format, int * size); 38 | DECLSPEC_IMPORT void BeaconFormatInt(formatp * format, int value); 39 | 40 | /* Output Functions */ 41 | #define CALLBACK_OUTPUT 0x0 42 | #define CALLBACK_OUTPUT_OEM 0x1e 43 | #define CALLBACK_ERROR 0x0d 44 | #define CALLBACK_OUTPUT_UTF8 0x20 45 | 46 | DECLSPEC_IMPORT void BeaconPrintf(int type, char * fmt, ...); 47 | DECLSPEC_IMPORT void BeaconOutput(int type, char * data, int len); 48 | 49 | /* Token Functions */ 50 | DECLSPEC_IMPORT BOOL BeaconUseToken(HANDLE token); 51 | DECLSPEC_IMPORT void BeaconRevertToken(); 52 | DECLSPEC_IMPORT BOOL BeaconIsAdmin(); 53 | 54 | /* Spawn+Inject Functions */ 55 | DECLSPEC_IMPORT void BeaconGetSpawnTo(BOOL x86, char * buffer, int length); 56 | DECLSPEC_IMPORT void BeaconInjectProcess(HANDLE hProc, int pid, char * payload, int p_len, int p_offset, char * arg, int a_len); 57 | DECLSPEC_IMPORT void BeaconInjectTemporaryProcess(PROCESS_INFORMATION * pInfo, char * payload, int p_len, int p_offset, char * arg, int a_len); 58 | DECLSPEC_IMPORT void BeaconCleanupProcess(PROCESS_INFORMATION * pInfo); 59 | 60 | /* Utility Functions */ 61 | DECLSPEC_IMPORT BOOL toWideChar(char * src, wchar_t * dst, int max); 62 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright © 2019-2020 Odzhan. All Rights Reserved. 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 1. Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | 2. Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | 3. The name of the author may not be used to endorse or promote products 12 | derived from this software without specific prior written permission. 13 | THIS SOFTWARE IS PROVIDED BY AUTHORS "AS IS" AND ANY EXPRESS OR 14 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 17 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 21 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 22 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 23 | POSSIBILITY OF SUCH DAMAGE. */ 24 | 25 | #ifndef _WIN64 26 | #error You must use a 64-bit version of MSVC 27 | #endif 28 | 29 | #pragma warning(disable : 4047) 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include "beacon.h" 37 | #include "syscalls.h" 38 | 39 | 40 | void go(char* args, int length) { 41 | char* sc_ptr; 42 | DWORD processID; 43 | datap parser; 44 | 45 | BeaconDataParse(&parser, args, length); 46 | processID = BeaconDataInt(&parser); 47 | 48 | HANDLE assumedProcessHandle = NULL; 49 | 50 | OBJECT_ATTRIBUTES oa = {sizeof(oa)}; 51 | CLIENT_ID cid = { 0 }; 52 | cid.UniqueProcess = processID; 53 | 54 | NTSTATUS handleResult = ZwOpenProcess(&assumedProcessHandle, 0x1000, &oa, &cid); 55 | 56 | if (!handleResult) { 57 | PS_PROTECTION protectionStruct = { 0 }; 58 | NTSTATUS protectionResult = ZwQueryInformationProcess(assumedProcessHandle, (PROCESSINFOCLASS)61, &protectionStruct, sizeof(protectionStruct), NULL); 59 | 60 | if (protectionResult == 0) { 61 | unsigned int protectionType = (unsigned int)protectionStruct.Type; 62 | unsigned int protectionSigner = (unsigned int)protectionStruct.Signer; 63 | 64 | switch (protectionType) { 65 | case 0: 66 | BeaconPrintf(CALLBACK_OUTPUT, "Type: PsProtectedTypeNone\n"); 67 | break; 68 | case 1: 69 | BeaconPrintf(CALLBACK_OUTPUT, "Type: PsProtectedTypeProtectedLight\n"); 70 | break; 71 | case 2: 72 | BeaconPrintf(CALLBACK_OUTPUT, "Type: PsProtectedTypeProtected\n"); 73 | break; 74 | default: 75 | break; 76 | } 77 | 78 | switch(protectionSigner) { 79 | case 0: 80 | BeaconPrintf(CALLBACK_OUTPUT, "Signer: PsProtectedSignerNone\n"); 81 | break; 82 | case 4: 83 | BeaconPrintf(CALLBACK_OUTPUT, "Signer: PsProtectedSignerLsa\n"); 84 | break; 85 | } 86 | 87 | ZwClose(assumedProcessHandle); 88 | 89 | return; 90 | 91 | } else { 92 | BeaconPrintf(CALLBACK_ERROR, "ZwQueryInformation process failed with supplied handle."); 93 | ZwClose(assumedProcessHandle); 94 | 95 | return; 96 | } 97 | } else { 98 | BeaconPrintf(CALLBACK_ERROR, "Unable to derive handle to specified process."); 99 | return; 100 | } 101 | 102 | } -------------------------------------------------------------------------------- /src/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 SW2_HEADER_H_ 7 | #define SW2_HEADER_H_ 8 | 9 | #include 10 | 11 | #define SW2_SEED 0xD00A90C2 12 | #define SW2_ROL8(v) (v << 8 | v >> 24) 13 | #define SW2_ROR8(v) (v >> 8 | v << 24) 14 | #define SW2_ROX8(v) ((SW2_SEED % 2) ? SW2_ROL8(v) : SW2_ROR8(v)) 15 | #define SW2_MAX_ENTRIES 500 16 | #define SW2_RVA2VA(Type, DllBase, Rva) (Type)((ULONG_PTR) DllBase + Rva) 17 | 18 | // Typedefs are prefixed to avoid pollution. 19 | 20 | typedef struct _SW2_SYSCALL_ENTRY 21 | { 22 | DWORD Hash; 23 | DWORD Address; 24 | } SW2_SYSCALL_ENTRY, *PSW2_SYSCALL_ENTRY; 25 | 26 | typedef struct _SW2_SYSCALL_LIST 27 | { 28 | DWORD Count; 29 | SW2_SYSCALL_ENTRY Entries[SW2_MAX_ENTRIES]; 30 | } SW2_SYSCALL_LIST, *PSW2_SYSCALL_LIST; 31 | 32 | typedef struct _SW2_PEB_LDR_DATA { 33 | BYTE Reserved1[8]; 34 | PVOID Reserved2[3]; 35 | LIST_ENTRY InMemoryOrderModuleList; 36 | } SW2_PEB_LDR_DATA, *PSW2_PEB_LDR_DATA; 37 | 38 | typedef struct _SW2_LDR_DATA_TABLE_ENTRY { 39 | PVOID Reserved1[2]; 40 | LIST_ENTRY InMemoryOrderLinks; 41 | PVOID Reserved2[2]; 42 | PVOID DllBase; 43 | } SW2_LDR_DATA_TABLE_ENTRY, *PSW2_LDR_DATA_TABLE_ENTRY; 44 | 45 | typedef struct _SW2_PEB { 46 | BYTE Reserved1[2]; 47 | BYTE BeingDebugged; 48 | BYTE Reserved2[1]; 49 | PVOID Reserved3[2]; 50 | PSW2_PEB_LDR_DATA Ldr; 51 | } SW2_PEB, *PSW2_PEB; 52 | 53 | typedef struct _PS_PROTECTION { 54 | union { 55 | UCHAR Level; 56 | struct { 57 | UCHAR Type : 3; 58 | UCHAR Audit : 1; 59 | UCHAR Signer : 4; 60 | }; 61 | }; 62 | } PS_PROTECTION, *PPS_PROTECTION; 63 | 64 | DWORD SW2_HashSyscall(PCSTR FunctionName); 65 | BOOL SW2_PopulateSyscallList(); 66 | EXTERN_C DWORD SW2_GetSyscallNumber(DWORD FunctionHash); 67 | 68 | #ifndef InitializeObjectAttributes 69 | #define InitializeObjectAttributes( p, n, a, r, s ) { \ 70 | (p)->Length = sizeof( OBJECT_ATTRIBUTES ); \ 71 | (p)->RootDirectory = r; \ 72 | (p)->Attributes = a; \ 73 | (p)->ObjectName = n; \ 74 | (p)->SecurityDescriptor = s; \ 75 | (p)->SecurityQualityOfService = NULL; \ 76 | } 77 | #endif 78 | 79 | typedef struct _UNICODE_STRING { 80 | USHORT Length; 81 | USHORT MaximumLength; 82 | PWSTR Buffer; 83 | } UNICODE_STRING, *PUNICODE_STRING; 84 | 85 | typedef struct _OBJECT_ATTRIBUTES { 86 | ULONG Length; 87 | HANDLE RootDirectory; 88 | PUNICODE_STRING ObjectName; 89 | ULONG Attributes; 90 | PVOID SecurityDescriptor; 91 | PVOID SecurityQualityOfService; 92 | } OBJECT_ATTRIBUTES; 93 | typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES; 94 | 95 | typedef struct _CLIENT_ID { 96 | PVOID UniqueProcess; 97 | PVOID UniqueThread; 98 | } CLIENT_ID, *PCLIENT_ID; 99 | 100 | typedef enum _PROCESSINFOCLASS 101 | { 102 | ProcessBasicInformation = 0, 103 | ProcessDebugPort = 7, 104 | ProcessWow64Information = 26, 105 | ProcessImageFileName = 27, 106 | ProcessBreakOnTermination = 29 107 | } PROCESSINFOCLASS, *PPROCESSINFOCLASS; 108 | 109 | EXTERN_C NTSTATUS NtOpenProcess( 110 | OUT PHANDLE ProcessHandle, 111 | IN ACCESS_MASK DesiredAccess, 112 | IN POBJECT_ATTRIBUTES ObjectAttributes, 113 | IN PCLIENT_ID ClientId OPTIONAL); 114 | 115 | EXTERN_C NTSTATUS NtQueryInformationProcess( 116 | IN HANDLE ProcessHandle, 117 | IN PROCESSINFOCLASS ProcessInformationClass, 118 | OUT PVOID ProcessInformation, 119 | IN ULONG ProcessInformationLength, 120 | OUT PULONG ReturnLength OPTIONAL); 121 | 122 | EXTERN_C NTSTATUS NtClose( 123 | IN HANDLE Handle); 124 | 125 | EXTERN_C NTSTATUS NtAdjustPrivilegesToken( 126 | IN HANDLE TokenHandle, 127 | IN BOOLEAN DisableAllPrivileges, 128 | IN PTOKEN_PRIVILEGES NewState OPTIONAL, 129 | IN ULONG BufferLength, 130 | OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL, 131 | OUT PULONG ReturnLength OPTIONAL); 132 | 133 | #endif 134 | 135 | 136 | // Code below is adapted from @modexpblog. Read linked article for more details. 137 | // https://www.mdsec.co.uk/2020/12/bypassing-user-mode-hooks-and-direct-invocation-of-system-calls-for-red-teams 138 | 139 | SW2_SYSCALL_LIST SW2_SyscallList = {0,1}; 140 | 141 | DWORD SW2_HashSyscall(PCSTR FunctionName) 142 | { 143 | DWORD i = 0; 144 | DWORD Hash = SW2_SEED; 145 | 146 | while (FunctionName[i]) 147 | { 148 | WORD PartialName = *(WORD*)((ULONG64)FunctionName + i++); 149 | Hash ^= PartialName + SW2_ROR8(Hash); 150 | } 151 | 152 | return Hash; 153 | } 154 | 155 | BOOL SW2_PopulateSyscallList() 156 | { 157 | // Return early if the list is already populated. 158 | if (SW2_SyscallList.Count) return TRUE; 159 | 160 | PSW2_PEB Peb = (PSW2_PEB)__readgsqword(0x60); 161 | PSW2_PEB_LDR_DATA Ldr = Peb->Ldr; 162 | PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL; 163 | PVOID DllBase = NULL; 164 | 165 | // Get the DllBase address of NTDLL.dll. NTDLL is not guaranteed to be the second 166 | // in the list, so it's safer to loop through the full list and find it. 167 | PSW2_LDR_DATA_TABLE_ENTRY LdrEntry; 168 | for (LdrEntry = (PSW2_LDR_DATA_TABLE_ENTRY)Ldr->Reserved2[1]; LdrEntry->DllBase != NULL; LdrEntry = (PSW2_LDR_DATA_TABLE_ENTRY)LdrEntry->Reserved1[0]) 169 | { 170 | DllBase = LdrEntry->DllBase; 171 | PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)DllBase; 172 | PIMAGE_NT_HEADERS NtHeaders = SW2_RVA2VA(PIMAGE_NT_HEADERS, DllBase, DosHeader->e_lfanew); 173 | PIMAGE_DATA_DIRECTORY DataDirectory = (PIMAGE_DATA_DIRECTORY)NtHeaders->OptionalHeader.DataDirectory; 174 | DWORD VirtualAddress = DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; 175 | if (VirtualAddress == 0) continue; 176 | 177 | ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)SW2_RVA2VA(ULONG_PTR, DllBase, VirtualAddress); 178 | 179 | // If this is NTDLL.dll, exit loop. 180 | PCHAR DllName = SW2_RVA2VA(PCHAR, DllBase, ExportDirectory->Name); 181 | 182 | if ((*(ULONG*)DllName | 0x20202020) != 'ldtn') continue; 183 | if ((*(ULONG*)(DllName + 4) | 0x20202020) == 'ld.l') break; 184 | } 185 | 186 | if (!ExportDirectory) return FALSE; 187 | 188 | DWORD NumberOfNames = ExportDirectory->NumberOfNames; 189 | PDWORD Functions = SW2_RVA2VA(PDWORD, DllBase, ExportDirectory->AddressOfFunctions); 190 | PDWORD Names = SW2_RVA2VA(PDWORD, DllBase, ExportDirectory->AddressOfNames); 191 | PWORD Ordinals = SW2_RVA2VA(PWORD, DllBase, ExportDirectory->AddressOfNameOrdinals); 192 | 193 | // Populate SW2_SyscallList with unsorted Zw* entries. 194 | DWORD i = 0; 195 | PSW2_SYSCALL_ENTRY Entries = SW2_SyscallList.Entries; 196 | do 197 | { 198 | PCHAR FunctionName = SW2_RVA2VA(PCHAR, DllBase, Names[NumberOfNames - 1]); 199 | 200 | // Is this a system call? 201 | if (*(USHORT*)FunctionName == 'wZ') 202 | { 203 | Entries[i].Hash = SW2_HashSyscall(FunctionName); 204 | Entries[i].Address = Functions[Ordinals[NumberOfNames - 1]]; 205 | 206 | i++; 207 | if (i == SW2_MAX_ENTRIES) break; 208 | } 209 | } while (--NumberOfNames); 210 | 211 | // Save total number of system calls found. 212 | SW2_SyscallList.Count = i; 213 | 214 | // Sort the list by address in ascending order. 215 | for (DWORD i = 0; i < SW2_SyscallList.Count - 1; i++) 216 | { 217 | for (DWORD j = 0; j < SW2_SyscallList.Count - i - 1; j++) 218 | { 219 | if (Entries[j].Address > Entries[j + 1].Address) 220 | { 221 | // Swap entries. 222 | SW2_SYSCALL_ENTRY TempEntry; 223 | 224 | TempEntry.Hash = Entries[j].Hash; 225 | TempEntry.Address = Entries[j].Address; 226 | 227 | Entries[j].Hash = Entries[j + 1].Hash; 228 | Entries[j].Address = Entries[j + 1].Address; 229 | 230 | Entries[j + 1].Hash = TempEntry.Hash; 231 | Entries[j + 1].Address = TempEntry.Address; 232 | } 233 | } 234 | } 235 | 236 | return TRUE; 237 | } 238 | 239 | EXTERN_C DWORD SW2_GetSyscallNumber(DWORD FunctionHash) 240 | { 241 | // Ensure SW2_SyscallList is populated. 242 | if (!SW2_PopulateSyscallList()) return -1; 243 | 244 | for (DWORD i = 0; i < SW2_SyscallList.Count; i++) 245 | { 246 | if (FunctionHash == SW2_SyscallList.Entries[i].Hash) 247 | { 248 | return i; 249 | } 250 | } 251 | 252 | return -1; 253 | } 254 | #define ZwOpenProcess NtOpenProcess 255 | __asm__("NtOpenProcess: \n\ 256 | mov [rsp +8], rcx\n\ 257 | mov [rsp+16], rdx\n\ 258 | mov [rsp+24], r8\n\ 259 | mov [rsp+32], r9\n\ 260 | sub rsp, 0x28\n\ 261 | mov ecx, 0x0592346A8\n\ 262 | call SW2_GetSyscallNumber\n\ 263 | add rsp, 0x28\n\ 264 | mov rcx, [rsp +8]\n\ 265 | mov rdx, [rsp+16]\n\ 266 | mov r8, [rsp+24]\n\ 267 | mov r9, [rsp+32]\n\ 268 | mov r10, rcx\n\ 269 | syscall\n\ 270 | ret\n\ 271 | "); 272 | #define ZwQueryInformationProcess NtQueryInformationProcess 273 | __asm__("NtQueryInformationProcess: \n\ 274 | mov [rsp +8], rcx\n\ 275 | mov [rsp+16], rdx\n\ 276 | mov [rsp+24], r8\n\ 277 | mov [rsp+32], r9\n\ 278 | sub rsp, 0x28\n\ 279 | mov ecx, 0x001AB0E30\n\ 280 | call SW2_GetSyscallNumber\n\ 281 | add rsp, 0x28\n\ 282 | mov rcx, [rsp +8]\n\ 283 | mov rdx, [rsp+16]\n\ 284 | mov r8, [rsp+24]\n\ 285 | mov r9, [rsp+32]\n\ 286 | mov r10, rcx\n\ 287 | syscall\n\ 288 | ret\n\ 289 | "); 290 | #define ZwClose NtClose 291 | __asm__("NtClose: \n\ 292 | mov [rsp +8], rcx\n\ 293 | mov [rsp+16], rdx\n\ 294 | mov [rsp+24], r8\n\ 295 | mov [rsp+32], r9\n\ 296 | sub rsp, 0x28\n\ 297 | mov ecx, 0x0C8912610\n\ 298 | call SW2_GetSyscallNumber\n\ 299 | add rsp, 0x28\n\ 300 | mov rcx, [rsp +8]\n\ 301 | mov rdx, [rsp+16]\n\ 302 | mov r8, [rsp+24]\n\ 303 | mov r9, [rsp+32]\n\ 304 | mov r10, rcx\n\ 305 | syscall\n\ 306 | ret\n\ 307 | "); 308 | #define ZwAdjustPrivilegesToken NtAdjustPrivilegesToken 309 | __asm__("NtAdjustPrivilegesToken: \n\ 310 | mov [rsp +8], rcx\n\ 311 | mov [rsp+16], rdx\n\ 312 | mov [rsp+24], r8\n\ 313 | mov [rsp+32], r9\n\ 314 | sub rsp, 0x28\n\ 315 | mov ecx, 0x06BC96354\n\ 316 | call SW2_GetSyscallNumber\n\ 317 | add rsp, 0x28\n\ 318 | mov rcx, [rsp +8]\n\ 319 | mov rdx, [rsp+16]\n\ 320 | mov r8, [rsp+24]\n\ 321 | mov r9, [rsp+32]\n\ 322 | mov r10, rcx\n\ 323 | syscall\n\ 324 | ret\n\ 325 | "); 326 | --------------------------------------------------------------------------------