├── .gitattributes ├── .shared └── shared.hpp ├── .gitignore ├── client ├── entry.cpp ├── include.hpp ├── utils │ └── utils.hpp ├── comm │ ├── comm.hpp │ └── comm.cpp └── client.vcxproj ├── driver ├── hide │ ├── pfn.hpp │ ├── stub.asm │ ├── offsets.hpp │ ├── ret.hpp │ ├── strings.hpp │ └── thread.hpp ├── driver.cpp ├── include.hpp ├── defs.hpp ├── kernel │ ├── modules.hpp │ ├── scanner.hpp │ ├── physical │ │ ├── cr3.hpp │ │ └── physical.hpp │ ├── crt.hpp │ └── nt.hpp ├── driver.vcxproj └── comm │ └── comm.hpp ├── LICENSE └── core.sln /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.shared/shared.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum class comm_type : unsigned long 4 | { 5 | none = 0, 6 | init = 1, 7 | destory = 2, 8 | read_physical = 3, 9 | write_physical = 4, 10 | base = 5, 11 | cr3 = 6, 12 | }; 13 | 14 | struct shared_data 15 | { 16 | comm_type type; 17 | 18 | unsigned long process_id; 19 | 20 | unsigned long long address; 21 | unsigned long long buffer; 22 | unsigned long long size; 23 | }; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | .vs 35 | bin 36 | -------------------------------------------------------------------------------- /client/entry.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | if (!Comm::Open()) 6 | { 7 | std::cerr << "Failed to open comm" << std::endl; 8 | return 1; 9 | } 10 | 11 | int pid = Utils::FindProcessId("explorer.exe"); 12 | if (!pid) 13 | { 14 | std::cerr << "Failed to find explorer" << std::endl; 15 | return 1; 16 | } 17 | 18 | Comm::SetTargetPid(pid); 19 | 20 | std::uint64_t Base = Comm::GetBase(); 21 | std::cout << "Base: " << std::hex << Base << std::endl; 22 | 23 | std::uint64_t Cr3 = Comm::GetCr3(); 24 | std::cout << "Cr3: " << std::hex << Cr3 << std::endl; 25 | 26 | Comm::Close(); 27 | 28 | getchar(); 29 | } -------------------------------------------------------------------------------- /driver/hide/pfn.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace hide::pfn 5 | { 6 | __forceinline bool Clear(PMDL Mdl) 7 | { 8 | PPFN_NUMBER Array = MmGetMdlPfnArray(Mdl); 9 | if (!Array) 10 | return false; 11 | 12 | ULONG Count = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Mdl), MmGetMdlByteCount(Mdl)); 13 | 14 | for (ULONG i = 0; i < Count; i++) 15 | { 16 | size_t bytes = 0; 17 | crt::memset(&Array[i], 0, sizeof(ULONG)); 18 | 19 | printf("Clearing PFN: %p\n", &Array[i]); 20 | } 21 | 22 | return true; 23 | } 24 | } -------------------------------------------------------------------------------- /driver/driver.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | __forceinline EXTERN_C NTSTATUS Entry(PMDL MdlPtr, void* param2) 4 | { 5 | if (!MdlPtr) 6 | return STATUS_INVALID_PARAMETER; 7 | 8 | hide::pfn::Clear(MdlPtr); 9 | hide::offsets::Load(); 10 | 11 | const auto ntoskrnl = modules::get_kernel_module(skCrypt("ntoskrnl.exe")); 12 | if (!ntoskrnl) 13 | { 14 | printf("Failed to get ntoskrnl.exe\n"); 15 | return STATUS_NOT_FOUND; 16 | } 17 | 18 | ret::trampoline_gadget = reinterpret_cast(scanner::find_pattern( 19 | ntoskrnl.base, 20 | "\xFF\x26", 21 | "xx" 22 | )); 23 | if (!ret::trampoline_gadget) 24 | { 25 | printf("Failed to find ret trampoline gadget\n"); 26 | return STATUS_NOT_FOUND; 27 | } 28 | 29 | return comm::Open(); 30 | } -------------------------------------------------------------------------------- /driver/include.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Windows 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | // C++ 12 | #include 13 | #include 14 | 15 | // Project 16 | #include 17 | #include 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | #include 33 | 34 | #include -------------------------------------------------------------------------------- /client/include.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // C++ Standard Library 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | // Windows API 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | // Project 33 | #include <../.shared/shared.hpp> 34 | 35 | #include 36 | 37 | #include -------------------------------------------------------------------------------- /driver/defs.hpp: -------------------------------------------------------------------------------- 1 | #define PRINT_DEBUG 0 2 | 3 | #if PRINT_DEBUG 4 | #define printf(text, ...) DbgPrintEx(DPFLTR_IHVBUS_ID, 0, text, ##__VA_ARGS__) 5 | #else 6 | #define printf(text, ...) 7 | #endif 8 | 9 | #define dereference(ptr)(uint64)(ptr + *(int*)((unsigned int*)ptr + 3 ) + 7) 10 | #define in_range(x,a,b)(x >= a && x <= b) 11 | #define get_bits(x)(in_range((x&(~0x20)),'A','F') ? ((x&(~0x20)) - 'A' + 0xA) : (in_range(x,'0','9') ? x - '0' : 0)) 12 | #define get_byte(x)(get_bits(x[0]) << 4 | get_bits(x[1])) 13 | #define to_lower_i(Char)((Char >= 'A' && Char <= 'Z') ? (Char + 32) : Char) 14 | #define to_lower_c(Char)((Char >= (char*)'A' && Char <= (char*)'Z') ? (Char + 32) : Char) 15 | 16 | #define print_bytes(address, size) \ 17 | { \ 18 | for (int i = 0; i < size; i++) \ 19 | { \ 20 | printf("%02X ", *(unsigned char*)(address + i)); \ 21 | } \ 22 | } 23 | 24 | -------------------------------------------------------------------------------- /client/utils/utils.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class Utils 5 | { 6 | public: 7 | static int FindProcessId(std::string ProcessName) 8 | { 9 | HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 10 | if (snapshot == INVALID_HANDLE_VALUE) 11 | { 12 | std::cout << "Failed to create snapshot: " << GetLastError() << std::endl; 13 | return 0; 14 | } 15 | 16 | PROCESSENTRY32 entry; 17 | entry.dwSize = sizeof(entry); 18 | 19 | if (!Process32First(snapshot, &entry)) 20 | { 21 | std::cout << "Failed to get first process: " << GetLastError() << std::endl; 22 | CloseHandle(snapshot); 23 | return 0; 24 | } 25 | 26 | do 27 | { 28 | if (ProcessName.compare(entry.szExeFile) == 0) 29 | { 30 | CloseHandle(snapshot); 31 | return entry.th32ProcessID; 32 | } 33 | } while (Process32Next(snapshot, &entry)); 34 | 35 | CloseHandle(snapshot); 36 | return 0; 37 | } 38 | }; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Vasie1337 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /driver/hide/stub.asm: -------------------------------------------------------------------------------- 1 | .code 2 | 3 | spoofer_stub proc 4 | pop r11 ; poping without setting up stack frame, r11 is the return address (the one in our code) 5 | add rsp, 8 ; skipping callee reserved space 6 | mov rax, [rsp + 24] ; dereference shell_param 7 | 8 | mov r10, [rax] ; load shell_param.trampoline 9 | mov [rsp], r10 ; store address of trampoline as return address 10 | 11 | mov r10, [rax + 8] ; load shell_param.function 12 | mov [rax + 8], r11 ; store the original return address in shell_param.function 13 | 14 | mov [rax + 16], rsi ; preserve rsi in shell_param.rsi 15 | lea rsi, fixup 16 | mov [rax], rsi ; store address of fixup label in shell_param.trampoline 17 | mov rsi, rax ; preserve address of shell_param in rsi 18 | 19 | jmp r10 ; call shell_param.function 20 | 21 | fixup: 22 | sub rsp, 16 23 | mov rcx, rsi ; restore address of shell_param 24 | mov rsi, [rcx + 16] ; restore rsi from shell_param.rsi 25 | 26 | jmp QWORD PTR [rcx + 8] ; jmp to the original return address 27 | spoofer_stub endp 28 | 29 | end -------------------------------------------------------------------------------- /driver/hide/offsets.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace hide::offsets 5 | { 6 | inline uint64 ThreadListHead = 0x5e0; 7 | 8 | inline uint64 MiscFlags = 0x74; 9 | inline uint64 StartAddress = 0x450; 10 | inline uint64 Win32StartAddress = 0x4D0; 11 | inline uint64 ThreadListEntry = 0x4E8; 12 | 13 | inline uint64 AlertAble = 4; 14 | inline uint64 SystemThread = 10; 15 | inline uint64 ApcQueuable = 14; 16 | 17 | __forceinline void Load() 18 | { 19 | RTL_OSVERSIONINFOW Version{}; 20 | RtlGetVersion(&Version); 21 | 22 | if (22000 <= Version.dwBuildNumber) 23 | { 24 | StartAddress = 0x4A0; 25 | Win32StartAddress = 0x520; 26 | ThreadListEntry = 0x538; 27 | } 28 | } 29 | } 30 | 31 | namespace hide::patterns 32 | { 33 | inline const char* PspCidTableSig = skCrypt("\x48\x8B\x0D\x00\x00\x00\x00\x48\x89\x7C\x24\x00\x45\x33\xC9"); 34 | inline const char* PspCidTableMask = skCrypt("xxx????xxxx?xxx"); 35 | 36 | inline const char* LookUpHandleSig = skCrypt("\x8B\x01\x48\x83\xE2"); 37 | inline const char* LookUpHandleMask = skCrypt("xxxxx"); 38 | 39 | inline const char* DestroyHandleSig = skCrypt("\x48\x89\x5C\x24\x00\x48\x89\x6C\x24\x00\x48\x89\x74\x24\x00\x57\x48\x83\xEC\x00\x48\x83\x79\x00\x00\x49\x8B\xE8"); 40 | inline const char* DestroyHandleMask = skCrypt("xxxx?xxxx?xxxx?xxxx?xxx??xxx"); 41 | } -------------------------------------------------------------------------------- /client/comm/comm.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class Comm 5 | { 6 | public: 7 | static void SetTargetPid(long pid) { target_pid = pid; } 8 | 9 | static bool Open(); 10 | static void Close(); 11 | 12 | static std::uint64_t GetCr3(); 13 | static std::uint64_t GetBase(); 14 | 15 | static bool ReadPhysicalMemory(std::uint64_t Address, void* Buffer, std::size_t Size); 16 | static bool WritePhysicalMemory(std::uint64_t Address, void* Buffer, std::size_t Size); 17 | 18 | template 19 | static T Read(std::uint64_t Address, std::size_t Size = sizeof(T)); 20 | 21 | template 22 | static bool Write(std::uint64_t Address, T Value); 23 | 24 | 25 | private: 26 | static void Initialize(); 27 | static bool OpenEvents(); 28 | 29 | inline static long target_pid{}; 30 | 31 | inline static shared_data* shared_section{}; 32 | inline static HANDLE section_handle{}; 33 | 34 | inline static HANDLE event_handle{}; 35 | inline static HANDLE event_handle_response{}; 36 | }; 37 | 38 | template 39 | inline T Comm::Read(std::uint64_t Address, std::size_t Size) 40 | { 41 | T Buffer{}; 42 | ReadPhysicalMemory(Address, &Buffer, Size); 43 | return Buffer; 44 | } 45 | 46 | template 47 | inline bool Comm::Write(std::uint64_t Address, T Value) 48 | { 49 | return WritePhysicalMemory(Address, &Value, sizeof(T)); 50 | } 51 | -------------------------------------------------------------------------------- /driver/kernel/modules.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace modules 5 | { 6 | typedef class DATA_ENTRY 7 | { 8 | public: 9 | bool operator!() const 10 | { 11 | return !base || !size; 12 | } 13 | 14 | uint64 base; 15 | uint64 size; 16 | }; 17 | 18 | __forceinline PRTL_PROCESS_MODULES get_modules() 19 | { 20 | NTSTATUS Status = STATUS_SUCCESS; 21 | ULONG Bytes = 0; 22 | PRTL_PROCESS_MODULES Modules = 0; 23 | 24 | Status = ZwQuerySystemInformation(SystemModuleInformation, 0, Bytes, &Bytes); 25 | if (Status != STATUS_INFO_LENGTH_MISMATCH) 26 | return 0; 27 | 28 | Modules = (PRTL_PROCESS_MODULES)ExAllocatePool(NonPagedPool, Bytes); 29 | if (!Modules) 30 | return 0; 31 | 32 | Status = ZwQuerySystemInformation(SystemModuleInformation, Modules, Bytes, &Bytes); 33 | if (!NT_SUCCESS(Status)) 34 | { 35 | ExFreePool(Modules); 36 | return 0; 37 | } 38 | 39 | return Modules; 40 | } 41 | 42 | __forceinline DATA_ENTRY get_kernel_module(const char* module_name) 43 | { 44 | DATA_ENTRY entry = { 0 }; 45 | 46 | PRTL_PROCESS_MODULES Modules = get_modules(); 47 | 48 | for (ULONG i = 0; i < Modules->NumberOfModules; i++) 49 | { 50 | if (crt::strstr(to_lower_c((const char*)Modules->Modules[i].FullPathName), module_name)) 51 | { 52 | entry.base = (uint64)Modules->Modules[i].ImageBase; 53 | entry.size = (uint64)Modules->Modules[i].ImageSize; 54 | break; 55 | } 56 | } 57 | 58 | ExFreePool(Modules); 59 | return entry; 60 | } 61 | 62 | __forceinline DATA_ENTRY get_section(DATA_ENTRY module, const char* section_name) 63 | { 64 | PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)module.base; 65 | PIMAGE_NT_HEADERS nt_headers = (PIMAGE_NT_HEADERS)(module.base + dos_header->e_lfanew); 66 | PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(nt_headers); 67 | 68 | for (unsigned i = 0; i < nt_headers->FileHeader.NumberOfSections; i++) 69 | { 70 | if (crt::strstr((const char*)section->Name, section_name)) 71 | { 72 | DATA_ENTRY entry = { 0 }; 73 | entry.base = module.base + section->VirtualAddress; 74 | entry.size = section->Misc.VirtualSize; 75 | return entry; 76 | } 77 | 78 | section++; 79 | } 80 | 81 | return { 0 }; 82 | } 83 | } -------------------------------------------------------------------------------- /driver/hide/ret.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace ret 5 | { 6 | extern "C" void* spoofer_stub(); 7 | 8 | namespace detail 9 | { 10 | template 11 | static __forceinline auto shellcode_stub_helper( 12 | const void* shell, 13 | Args... args 14 | ) -> Ret 15 | { 16 | auto fn = (Ret(*)(Args...))(shell); 17 | return fn(args...); 18 | } 19 | 20 | template 21 | struct argument_remapper 22 | { 23 | // At least 5 params 24 | template< 25 | typename Ret, 26 | typename First, 27 | typename Second, 28 | typename Third, 29 | typename Fourth, 30 | typename... Pack 31 | > 32 | static auto do_call( 33 | const void* shell, 34 | void* shell_param, 35 | First first, 36 | Second second, 37 | Third third, 38 | Fourth fourth, 39 | Pack... pack 40 | ) -> Ret 41 | { 42 | return shellcode_stub_helper< 43 | Ret, 44 | First, 45 | Second, 46 | Third, 47 | Fourth, 48 | void*, 49 | void*, 50 | Pack... 51 | >( 52 | shell, 53 | first, 54 | second, 55 | third, 56 | fourth, 57 | shell_param, 58 | nullptr, 59 | pack... 60 | ); 61 | } 62 | }; 63 | 64 | template 65 | struct argument_remapper> 66 | { 67 | // 4 or less params 68 | template< 69 | typename Ret, 70 | typename First = void*, 71 | typename Second = void*, 72 | typename Third = void*, 73 | typename Fourth = void* 74 | > 75 | static auto do_call( 76 | const void* shell, 77 | void* shell_param, 78 | First first = First{}, 79 | Second second = Second{}, 80 | Third third = Third{}, 81 | Fourth fourth = Fourth{} 82 | ) -> Ret 83 | { 84 | return shellcode_stub_helper< 85 | Ret, 86 | First, 87 | Second, 88 | Third, 89 | Fourth, 90 | void*, 91 | void* 92 | >( 93 | shell, 94 | first, 95 | second, 96 | third, 97 | fourth, 98 | shell_param, 99 | nullptr 100 | ); 101 | } 102 | }; 103 | } 104 | 105 | void* trampoline_gadget = nullptr; 106 | 107 | template 108 | static __forceinline auto spoof_call( 109 | Ret(*fn)(Args...), 110 | Args... args 111 | ) -> Ret 112 | { 113 | struct shell_params 114 | { 115 | const void* trampoline; 116 | void* function; 117 | void* rsi; 118 | }; 119 | 120 | shell_params p{ trampoline_gadget, reinterpret_cast(fn) }; 121 | using mapper = detail::argument_remapper; 122 | return mapper::template do_call((const void*)&spoofer_stub, &p, args...); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /driver/kernel/scanner.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace scanner 5 | { 6 | __forceinline uint64 find_pattern(uint64 base, size_t range, const char* pattern, const char* mask) 7 | { 8 | const auto check_mask = [](const char* base, const char* pattern, const char* mask) -> bool 9 | { 10 | for (; *mask; ++base, ++pattern, ++mask) 11 | { 12 | if (*mask == 'x' && *base != *pattern) 13 | { 14 | return false; 15 | } 16 | } 17 | 18 | return true; 19 | }; 20 | 21 | range = range - crt::strlen(mask); 22 | 23 | for (size_t i = 0; i < range; ++i) 24 | { 25 | if (check_mask((const char*)base + i, pattern, mask)) 26 | { 27 | return base + i; 28 | } 29 | } 30 | 31 | return 0; 32 | } 33 | 34 | __forceinline uint64 find_pattern(uint64 base, const char* pattern, const char* mask) 35 | { 36 | const PIMAGE_NT_HEADERS headers = (PIMAGE_NT_HEADERS)(base + ((PIMAGE_DOS_HEADER)base)->e_lfanew); 37 | const PIMAGE_SECTION_HEADER sections = IMAGE_FIRST_SECTION(headers); 38 | 39 | for (size_t i = 0; i < headers->FileHeader.NumberOfSections; i++) 40 | { 41 | const PIMAGE_SECTION_HEADER section = §ions[i]; 42 | 43 | if (section->Characteristics & IMAGE_SCN_MEM_EXECUTE) 44 | { 45 | const auto match = find_pattern(base + section->VirtualAddress, section->Misc.VirtualSize, pattern, mask); 46 | 47 | if (match) 48 | { 49 | return match; 50 | } 51 | } 52 | } 53 | 54 | return 0; 55 | } 56 | 57 | __forceinline uint64 find_pattern(uint64 module_base, const char* pattern) 58 | { 59 | auto pattern_ = pattern; 60 | uint64 first_match = 0; 61 | 62 | if (!module_base) 63 | { 64 | return 0; 65 | } 66 | 67 | const auto nt = reinterpret_cast(module_base + reinterpret_cast(module_base)->e_lfanew); 68 | 69 | for (uint64 current = module_base; current < module_base + nt->OptionalHeader.SizeOfImage; current++) 70 | { 71 | if (!*pattern_) 72 | { 73 | return first_match; 74 | } 75 | 76 | if (*(unsigned int*)pattern_ == '\?' || *(unsigned int*)current == get_byte(pattern_)) 77 | { 78 | if (!first_match) 79 | first_match = current; 80 | 81 | if (!pattern_[2]) 82 | return first_match; 83 | 84 | if (*(unsigned short*)pattern_ == '\?\?' || *(unsigned int*)pattern_ != '\?') 85 | pattern_ += 3; 86 | 87 | else 88 | pattern_ += 2; 89 | } 90 | else 91 | { 92 | pattern_ = pattern; 93 | first_match = 0; 94 | } 95 | } 96 | 97 | return 0; 98 | } 99 | } -------------------------------------------------------------------------------- /client/comm/comm.cpp: -------------------------------------------------------------------------------- 1 | #include "comm.hpp" 2 | 3 | bool Comm::Open() 4 | { 5 | section_handle = CreateFileMappingA(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, sizeof(shared_data), "Global\\SharedData"); 6 | if (!section_handle) 7 | { 8 | std::cout << "Failed to create section: " << GetLastError() << std::endl; 9 | return 1; 10 | } 11 | 12 | shared_section = reinterpret_cast(MapViewOfFile(section_handle, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(shared_data))); 13 | if (!shared_section) 14 | { 15 | std::cout << "Failed to map view of section: " << GetLastError() << std::endl; 16 | CloseHandle(section_handle); 17 | return false; 18 | } 19 | 20 | if (!OpenEvents()) 21 | { 22 | return false; 23 | } 24 | 25 | Initialize(); 26 | 27 | return true; 28 | } 29 | 30 | void Comm::Close() 31 | { 32 | shared_section->type = comm_type::destory; 33 | 34 | SetEvent(event_handle); 35 | WaitForSingleObject(event_handle_response, INFINITE); 36 | ResetEvent(event_handle_response); 37 | 38 | UnmapViewOfFile(shared_section); 39 | CloseHandle(section_handle); 40 | CloseHandle(event_handle); 41 | } 42 | 43 | std::uint64_t Comm::GetCr3() 44 | { 45 | shared_section->type = comm_type::cr3; 46 | shared_section->process_id = target_pid; 47 | 48 | SetEvent(event_handle); 49 | WaitForSingleObject(event_handle_response, INFINITE); 50 | ResetEvent(event_handle_response); 51 | 52 | return shared_section->buffer; 53 | } 54 | 55 | std::uint64_t Comm::GetBase() 56 | { 57 | shared_section->type = comm_type::base; 58 | shared_section->process_id = target_pid; 59 | 60 | SetEvent(event_handle); 61 | WaitForSingleObject(event_handle_response, INFINITE); 62 | ResetEvent(event_handle_response); 63 | 64 | return shared_section->buffer; 65 | } 66 | 67 | bool Comm::ReadPhysicalMemory(std::uint64_t Address, void* Buffer, std::size_t Size) 68 | { 69 | shared_section->type = comm_type::read_physical; 70 | shared_section->process_id = target_pid; 71 | shared_section->address = Address; 72 | shared_section->buffer = reinterpret_cast(Buffer); 73 | shared_section->size = Size; 74 | 75 | SetEvent(event_handle); 76 | WaitForSingleObject(event_handle_response, INFINITE); 77 | ResetEvent(event_handle_response); 78 | 79 | return true; 80 | } 81 | 82 | bool Comm::WritePhysicalMemory(std::uint64_t Address, void* Buffer, std::size_t Size) 83 | { 84 | shared_section->type = comm_type::write_physical; 85 | shared_section->process_id = target_pid; 86 | shared_section->address = Address; 87 | shared_section->buffer = reinterpret_cast(Buffer); 88 | shared_section->size = Size; 89 | 90 | SetEvent(event_handle); 91 | WaitForSingleObject(event_handle_response, INFINITE); 92 | ResetEvent(event_handle_response); 93 | 94 | return true; 95 | } 96 | 97 | void Comm::Initialize() 98 | { 99 | shared_section->type = comm_type::init; 100 | shared_section->process_id = GetCurrentProcessId(); 101 | 102 | SetEvent(event_handle); 103 | WaitForSingleObject(event_handle_response, INFINITE); 104 | ResetEvent(event_handle_response); 105 | } 106 | 107 | bool Comm::OpenEvents() 108 | { 109 | event_handle = CreateEventA(NULL, FALSE, FALSE, "Global\\SharedMemEvent"); 110 | if (!event_handle) 111 | { 112 | std::cout << "Failed to open event: " << GetLastError() << std::endl; 113 | return false; 114 | } 115 | 116 | event_handle_response = CreateEventA(NULL, FALSE, FALSE, "Global\\SharedMemEventResponse"); 117 | if (!event_handle_response) 118 | { 119 | std::cout << "Failed to open response event: " << GetLastError() << std::endl; 120 | return false; 121 | } 122 | return true; 123 | } 124 | -------------------------------------------------------------------------------- /driver/hide/strings.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*____________________________________________________________________________________________________________ 4 | 5 | Original Author: skadro 6 | Github: https://github.com/skadro-official 7 | License: See end of file 8 | 9 | skCrypter 10 | Compile-time, Usermode + Kernelmode, safe and lightweight string crypter library for C++11+ 11 | 12 | *Not removing this part is appreciated* 13 | ____________________________________________________________________________________________________________*/ 14 | 15 | namespace skc 16 | { 17 | template 18 | using clean_type = typename std::remove_const_t>; 19 | 20 | template 21 | class skCrypter 22 | { 23 | public: 24 | __forceinline constexpr skCrypter(T* data) 25 | { 26 | crypt(data); 27 | } 28 | 29 | __forceinline T* get() 30 | { 31 | return _storage; 32 | } 33 | 34 | __forceinline int size() // (w)char count 35 | { 36 | return _size; 37 | } 38 | 39 | __forceinline char key() 40 | { 41 | return _key1; 42 | } 43 | 44 | __forceinline T* encrypt() 45 | { 46 | if (!isEncrypted()) 47 | crypt(_storage); 48 | 49 | return _storage; 50 | } 51 | 52 | __forceinline T* decrypt() 53 | { 54 | if (isEncrypted()) 55 | crypt(_storage); 56 | 57 | return _storage; 58 | } 59 | 60 | __forceinline bool isEncrypted() 61 | { 62 | return _storage[_size - 1] != 0; 63 | } 64 | 65 | __forceinline void clear() // set full storage to 0 66 | { 67 | for (int i = 0; i < _size; i++) 68 | { 69 | _storage[i] = 0; 70 | } 71 | } 72 | 73 | __forceinline operator T* () 74 | { 75 | decrypt(); 76 | 77 | return _storage; 78 | } 79 | 80 | private: 81 | __forceinline constexpr void crypt(T* data) 82 | { 83 | for (int i = 0; i < _size; i++) 84 | { 85 | _storage[i] = data[i] ^ (_key1 + i % (1 + _key2)); 86 | } 87 | } 88 | 89 | T _storage[_size]{}; 90 | }; 91 | } 92 | 93 | #define skCrypt(str) skCrypt_key(str, __TIME__[4], __TIME__[7]) 94 | #define skCrypt_key(str, key1, key2) []() { \ 95 | constexpr static auto crypted = skc::skCrypter \ 96 | >((skc::clean_type*)str); \ 97 | return crypted; }() 98 | 99 | /*________________________________________________________________________________ 100 | 101 | MIT License 102 | 103 | Copyright (c) 2020 skadro 104 | 105 | Permission is hereby granted, free of charge, to any person obtaining a copy 106 | of this software and associated documentation files (the "Software"), to deal 107 | in the Software without restriction, including without limitation the rights 108 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 109 | copies of the Software, and to permit persons to whom the Software is 110 | furnished to do so, subject to the following conditions: 111 | 112 | The above copyright notice and this permission notice shall be included in all 113 | copies or substantial portions of the Software. 114 | 115 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 116 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 117 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 118 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 119 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 120 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 121 | SOFTWARE. 122 | 123 | ________________________________________________________________________________*/ -------------------------------------------------------------------------------- /driver/kernel/physical/cr3.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace physical::cr3 5 | { 6 | inline uint64 StoredCr3 = 0; 7 | 8 | __forceinline uint64 GetFromBase(uint64 Base) 9 | { 10 | if (!Base) 11 | { 12 | printf("Invalid base address\n"); 13 | return 0; 14 | } 15 | 16 | VirtualAddress VirtualAddress = { 0 }; 17 | VirtualAddress.Value = Base; 18 | 19 | PPHYSICAL_MEMORY_RANGE Ranges = ret::spoof_call(&MmGetPhysicalMemoryRanges); 20 | if (!Ranges) 21 | { 22 | printf("Failed to get physical memory ranges\n"); 23 | return 0; 24 | } 25 | 26 | void* Buffer = ret::spoof_call(&ExAllocatePool, (POOL_TYPE)NonPagedPoolNx, (SIZE_T)PAGE_SIZE); 27 | if (!Buffer) 28 | { 29 | printf("Failed to allocate buffer\n"); 30 | return 0; 31 | } 32 | 33 | for (int i = 0;; i++) 34 | { 35 | auto Range = &Ranges[i]; 36 | 37 | if (!Range->BaseAddress.QuadPart || !Range->NumberOfBytes.QuadPart) 38 | { 39 | printf("Failed to find CR3\n"); 40 | break; 41 | } 42 | 43 | uint64 PhysicalAddr = Range->BaseAddress.QuadPart; 44 | 45 | for (int j = 0; j < (Range->NumberOfBytes.QuadPart / PAGE_SIZE); j++, PhysicalAddr += PAGE_SIZE) 46 | { 47 | _MMPTE Entries[4] = {}; 48 | 49 | size_t Bytes = 0; 50 | if (!NT_SUCCESS(physical::ReadPhysical(PhysicalAddr + 8 * VirtualAddress.pml4_index, reinterpret_cast(&Entries[0]), sizeof(_MMPTE), &Bytes))) 51 | continue; 52 | if (!Entries[0].u.Hard.Valid) 53 | continue; 54 | 55 | if (!NT_SUCCESS(physical::ReadPhysical((Entries[0].u.Hard.PageFrameNumber << 12) + 8 * VirtualAddress.pdpt_index, reinterpret_cast(&Entries[1]), sizeof(_MMPTE), &Bytes))) 56 | continue; 57 | if (!Entries[1].u.Hard.Valid) 58 | continue; 59 | 60 | if (!NT_SUCCESS(physical::ReadPhysical((Entries[1].u.Hard.PageFrameNumber << 12) + 8 * VirtualAddress.pd_index, reinterpret_cast(&Entries[2]), sizeof(_MMPTE), &Bytes))) 61 | continue; 62 | if (!Entries[2].u.Hard.Valid) 63 | continue; 64 | 65 | if (!NT_SUCCESS(physical::ReadPhysical((Entries[2].u.Hard.PageFrameNumber << 12) + 8 * VirtualAddress.pt_index, reinterpret_cast(&Entries[3]), sizeof(_MMPTE), &Bytes))) 66 | continue; 67 | if (!Entries[3].u.Hard.Valid) 68 | continue; 69 | 70 | if (!NT_SUCCESS(physical::ReadMemory(PhysicalAddr, reinterpret_cast(Base), Buffer, PAGE_SIZE, &Bytes))) 71 | continue; 72 | 73 | IMAGE_DOS_HEADER* dosHeader = reinterpret_cast(Buffer); 74 | if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) 75 | { 76 | IMAGE_NT_HEADERS* ntHeaders = reinterpret_cast(reinterpret_cast(Buffer) + dosHeader->e_lfanew); 77 | if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) 78 | continue; 79 | 80 | if (ntHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) 81 | { 82 | IMAGE_NT_HEADERS64* ntHeaders64 = reinterpret_cast(ntHeaders); 83 | if (ntHeaders64->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC || ntHeaders64->OptionalHeader.ImageBase != Base) 84 | continue; 85 | } 86 | else if (ntHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) 87 | { 88 | IMAGE_NT_HEADERS32* ntHeaders32 = reinterpret_cast(ntHeaders); 89 | if (ntHeaders32->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC || ntHeaders32->OptionalHeader.ImageBase != Base) 90 | continue; 91 | } 92 | else { 93 | continue; 94 | } 95 | 96 | ret::spoof_call(&ExFreePoolWithTag, Buffer, (ULONG)0); 97 | return PhysicalAddr; 98 | } 99 | } 100 | } 101 | 102 | printf("Failed to find CR3\n"); 103 | ret::spoof_call(&ExFreePoolWithTag, Buffer, (ULONG)0); 104 | return 0; 105 | } 106 | } -------------------------------------------------------------------------------- /driver/kernel/crt.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | namespace crt 3 | { 4 | __forceinline void* __cdecl memmove(void* Address, const void* Src, unsigned __int64 Size) 5 | { 6 | unsigned char* dest = static_cast(Address); 7 | const unsigned char* src = static_cast(Src); 8 | 9 | if (dest == src) { 10 | return Address; 11 | } 12 | 13 | if (dest < src) { 14 | for (unsigned __int64 i = 0; i < Size; ++i) { 15 | dest[i] = src[i]; 16 | } 17 | } 18 | else { 19 | for (unsigned __int64 i = Size; i > 0; --i) { 20 | dest[i - 1] = src[i - 1]; 21 | } 22 | } 23 | 24 | return Address; 25 | } 26 | 27 | __forceinline void* __cdecl memset(void* Address, int Value, unsigned __int64 Size) 28 | { 29 | unsigned char* dest = static_cast(Address); 30 | unsigned char val = static_cast(Value); 31 | 32 | for (unsigned __int64 i = 0; i < Size; ++i) { 33 | dest[i] = val; 34 | } 35 | 36 | return Address; 37 | } 38 | 39 | __forceinline void* __cdecl memcpy(void* Address, const void* Src, unsigned __int64 Size) 40 | { 41 | unsigned char* dest = static_cast(Address); 42 | const unsigned char* src = static_cast(Src); 43 | 44 | for (unsigned __int64 i = 0; i < Size; ++i) { 45 | dest[i] = src[i]; 46 | } 47 | 48 | return Address; 49 | } 50 | 51 | __forceinline int __cdecl memcmp(const void* First, const void* Second, unsigned __int64 Size) 52 | { 53 | const unsigned char* ptr1 = static_cast(First); 54 | const unsigned char* ptr2 = static_cast(Second); 55 | 56 | for (unsigned __int64 i = 0; i < Size; ++i) { 57 | if (ptr1[i] != ptr2[i]) { 58 | return (ptr1[i] < ptr2[i]) ? -1 : 1; 59 | } 60 | } 61 | 62 | return 0; 63 | } 64 | 65 | __forceinline unsigned __int64 __cdecl strlen(const char* Str) 66 | { 67 | unsigned __int64 len = 0; 68 | 69 | while (Str[len]) { 70 | ++len; 71 | } 72 | 73 | return len; 74 | } 75 | 76 | __forceinline char* __cdecl strcpy(char* Dest, const char* Src) 77 | { 78 | char* dest = Dest; 79 | 80 | while ((*dest++ = *Src++) != '\0') { 81 | ; 82 | } 83 | 84 | return Dest; 85 | } 86 | 87 | __forceinline int __cdecl strcmp(const char* Str1, const char* Str2) 88 | { 89 | while (*Str1 && *Str1 == *Str2) { 90 | ++Str1; 91 | ++Str2; 92 | } 93 | 94 | return *(unsigned char*)Str1 - *(unsigned char*)Str2; 95 | } 96 | 97 | __forceinline char* __cdecl strcat(char* Dest, const char* Src) 98 | { 99 | char* dest = Dest; 100 | 101 | while (*dest) { 102 | ++dest; 103 | } 104 | 105 | while ((*dest++ = *Src++) != '\0') { 106 | ; 107 | } 108 | 109 | return Dest; 110 | } 111 | 112 | __forceinline char* __cdecl strncpy(char* Dest, const char* Src, unsigned __int64 Count) 113 | { 114 | char* dest = Dest; 115 | 116 | while (Count && (*dest++ = *Src++)) { 117 | --Count; 118 | } 119 | 120 | if (Count) { 121 | while (--Count) { 122 | *dest++ = '\0'; 123 | } 124 | } 125 | 126 | return Dest; 127 | } 128 | 129 | __forceinline int __cdecl strncmp(const char* Str1, const char* Str2, unsigned __int64 Count) 130 | { 131 | while (Count && *Str1 && *Str1 == *Str2) { 132 | ++Str1; 133 | ++Str2; 134 | --Count; 135 | } 136 | 137 | return Count ? *(unsigned char*)Str1 - *(unsigned char*)Str2 : 0; 138 | } 139 | 140 | __forceinline char* __cdecl strstr(const char* Str, const char* SubStr) 141 | { 142 | unsigned __int64 len = strlen(SubStr); 143 | 144 | while (*Str) { 145 | if (!strncmp(Str, SubStr, len)) { 146 | return const_cast(Str); 147 | } 148 | 149 | ++Str; 150 | } 151 | 152 | return 0; 153 | } 154 | } -------------------------------------------------------------------------------- /driver/kernel/nt.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | typedef unsigned long long uint64; 5 | typedef unsigned long uint32; 6 | typedef unsigned short uint16; 7 | typedef unsigned char uint8; 8 | 9 | typedef struct _RTL_PROCESS_MODULE_INFORMATION 10 | { 11 | HANDLE Section; 12 | void* MappedBase; 13 | void* ImageBase; 14 | ULONG ImageSize; 15 | ULONG Flags; 16 | USHORT LoadOrderIndex; 17 | USHORT InitOrderIndex; 18 | USHORT LoadCount; 19 | USHORT OffsetToFileName; 20 | UCHAR FullPathName[256]; 21 | } RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION; 22 | 23 | typedef struct _RTL_PROCESS_MODULES 24 | { 25 | ULONG NumberOfModules; 26 | RTL_PROCESS_MODULE_INFORMATION Modules[1]; 27 | } RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES; 28 | 29 | typedef enum _SYSTEM_INFORMATION_CLASS 30 | { 31 | SystemBasicInformation, 32 | SystemProcessorInformation, 33 | SystemPerformanceInformation, 34 | SystemTimeOfDayInformation, 35 | SystemPathInformation, 36 | SystemProcessInformation, 37 | SystemCallCountInformation, 38 | SystemDeviceInformation, 39 | SystemProcessorPerformanceInformation, 40 | SystemFlagsInformation, 41 | SystemCallTimeInformation, 42 | SystemModuleInformation, 43 | SystemLocksInformation, 44 | SystemStackTraceInformation, 45 | SystemPagedPoolInformation, 46 | SystemNonPagedPoolInformation, 47 | SystemHandleInformation, 48 | SystemObjectInformation, 49 | SystemPageFileInformation, 50 | SystemVdmInstemulInformation, 51 | SystemVdmBopInformation, 52 | SystemFileCacheInformation, 53 | SystemPoolTagInformation, 54 | SystemInterruptInformation, 55 | SystemDpcBehaviorInformation, 56 | SystemFullMemoryInformation, 57 | SystemLoadGdiDriverInformation, 58 | SystemUnloadGdiDriverInformation, 59 | SystemTimeAdjustmentInformation, 60 | SystemSummaryMemoryInformation, 61 | SystemNextEventIdInformation, 62 | SystemEventIdsInformation, 63 | SystemCrashDumpInformation, 64 | SystemExceptionInformation, 65 | SystemCrashDumpStateInformation, 66 | SystemKernelDebuggerInformation, 67 | SystemContextSwitchInformation, 68 | SystemRegistryQuotaInformation, 69 | SystemExtendServiceTableInformation, 70 | SystemPrioritySeperation, 71 | SystemPlugPlayBusInformation, 72 | SystemDockInformation, 73 | SystemProcessorSpeedInformation, 74 | SystemCurrentTimeZoneInformation, 75 | SystemLookasideInformation, 76 | SystemBigPoolInformation = 0x42 77 | } SYSTEM_INFORMATION_CLASS, * PSYSTEM_INFORMATION_CLASS; 78 | 79 | struct VirtualAddress { 80 | union { 81 | uint64 Value; 82 | struct { 83 | uint64 offset : 12; 84 | uint64 pt_index : 9; 85 | uint64 pd_index : 9; 86 | uint64 pdpt_index : 9; 87 | uint64 pml4_index : 9; 88 | uint64 reserved : 16; 89 | }; 90 | }; 91 | }; 92 | 93 | struct _MMPTE_HARDWARE 94 | { 95 | ULONGLONG Valid : 1; 96 | ULONGLONG Dirty1 : 1; 97 | ULONGLONG Owner : 1; 98 | ULONGLONG WriteThrough : 1; 99 | ULONGLONG CacheDisable : 1; 100 | ULONGLONG Accessed : 1; 101 | ULONGLONG Dirty : 1; 102 | ULONGLONG LargePage : 1; 103 | ULONGLONG Global : 1; 104 | ULONGLONG CopyOnWrite : 1; 105 | ULONGLONG Unused : 1; 106 | ULONGLONG Write : 1; 107 | ULONGLONG PageFrameNumber : 40; 108 | ULONGLONG ReservedForSoftware : 4; 109 | ULONGLONG WsleAge : 4; 110 | ULONGLONG WsleProtection : 3; 111 | ULONGLONG NoExecute : 1; 112 | }; 113 | 114 | struct _MMPTE 115 | { 116 | union 117 | { 118 | struct _MMPTE_HARDWARE Hard; 119 | } u; 120 | }; 121 | 122 | 123 | EXTERN_C_START 124 | 125 | NTSTATUS NTAPI ZwQuerySystemInformation(ULONG SystemInformationClass, void* SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength); 126 | 127 | NTSTATUS NTAPI MmCopyVirtualMemory(PEPROCESS SourceProcess, void* SourceAddress, PEPROCESS TargetProcess, void* TargetAddress, SIZE_T BufferSize, KPROCESSOR_MODE PreviousMode, PSIZE_T ReturnSize); 128 | 129 | void* NTAPI PsGetProcessSectionBaseAddress(PEPROCESS Process); 130 | 131 | inline POBJECT_TYPE MmSectionObjectType = 0; 132 | 133 | NTSTATUS __fastcall ZwIsProcessInJob(void* a1, void* a2); 134 | 135 | EXTERN_C_END -------------------------------------------------------------------------------- /driver/kernel/physical/physical.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace physical 5 | { 6 | __forceinline NTSTATUS ReadPhysical(uint64 Address, void* Buffer, size_t Size, size_t* Bytes) 7 | { 8 | MM_COPY_ADDRESS Target = { 0 }; 9 | Target.PhysicalAddress.QuadPart = Address; 10 | return ret::spoof_call(&MmCopyMemory, (PVOID)Buffer, Target, (SIZE_T)Size, (ULONG)MM_COPY_MEMORY_PHYSICAL, Bytes); 11 | } 12 | 13 | __forceinline NTSTATUS WritePhysical(uint64 Address, void* Buffer, size_t Size, size_t* Bytes) 14 | { 15 | if (!Address) 16 | return STATUS_UNSUCCESSFUL; 17 | 18 | PHYSICAL_ADDRESS Target = { 0 }; 19 | Target.QuadPart = Address; 20 | 21 | void* Mapped = ret::spoof_call(&MmMapIoSpace, Target, Size, MmNonCached); 22 | if (!Mapped) 23 | return STATUS_UNSUCCESSFUL; 24 | 25 | crt::memcpy(Mapped, Buffer, Size); 26 | ret::spoof_call(&MmUnmapIoSpace, Mapped, Size); 27 | *Bytes = Size; 28 | 29 | return STATUS_SUCCESS; 30 | } 31 | 32 | __forceinline uint64 TranslateLinear(uint64 Cr3, uint64 Address) 33 | { 34 | Cr3 &= ~0xf; 35 | 36 | uint64 virt_addr = Address & ~(~0ul << 12); 37 | uint64 pte = ((Address >> 12) & (0x1ffll)); 38 | uint64 pt = ((Address >> 21) & (0x1ffll)); 39 | uint64 pd = ((Address >> 30) & (0x1ffll)); 40 | uint64 pdp = ((Address >> 39) & (0x1ffll)); 41 | uint64 p_mask = ((~0xfull << 8) & 0xfffffffffull); 42 | 43 | size_t readsize = 0; 44 | uint64 pdpe = 0; 45 | ReadPhysical(Cr3 + 8 * pdp, &pdpe, sizeof(pdpe), &readsize); 46 | if (~pdpe & 1) { 47 | return 0; 48 | } 49 | 50 | uint64 pde = 0; 51 | ReadPhysical((pdpe & p_mask) + 8 * pd, &pde, sizeof(pde), &readsize); 52 | if (~pde & 1) { 53 | return 0; 54 | } 55 | 56 | /* 1GB large page, use pde's 12-34 bits */ 57 | if (pde & 0x80) 58 | return (pde & (~0ull << 42 >> 12)) + (Address & ~(~0ull << 30)); 59 | 60 | uint64 pteAddr = 0; 61 | ReadPhysical((pde & p_mask) + 8 * pt, &pteAddr, sizeof(pteAddr), &readsize); 62 | if (~pteAddr & 1) { 63 | return 0; 64 | } 65 | 66 | /* 2MB large page */ 67 | if (pteAddr & 0x80) { 68 | return (pteAddr & p_mask) + (Address & ~(~0ull << 21)); 69 | } 70 | 71 | Address = 0; 72 | ReadPhysical((pteAddr & p_mask) + 8 * pte, &Address, sizeof(Address), &readsize); 73 | Address &= p_mask; 74 | 75 | if (!Address) { 76 | return 0; 77 | } 78 | 79 | return Address + virt_addr; 80 | } 81 | 82 | __forceinline NTSTATUS ReadMemory(uint64 Cr3, void* Address, void* AllocatedBuffer, size_t Size, size_t* Read) 83 | { 84 | if (Cr3 == 0 || !Address || !AllocatedBuffer || Size == 0 || !Read) 85 | { 86 | return STATUS_INVALID_PARAMETER; 87 | } 88 | 89 | size_t CurOffset = 0; 90 | size_t TotalSize = Size; 91 | NTSTATUS Status = STATUS_SUCCESS; 92 | 93 | while (TotalSize) 94 | { 95 | uint64 CurPhysAddr = physical::TranslateLinear(Cr3, reinterpret_cast(Address) + CurOffset); 96 | if (!CurPhysAddr) 97 | { 98 | return STATUS_UNSUCCESSFUL; 99 | } 100 | 101 | uint64 ReadSize = min(PAGE_SIZE - (CurPhysAddr & 0xFFF), TotalSize); 102 | size_t BytesRead = 0; 103 | 104 | Status = physical::ReadPhysical(CurPhysAddr, reinterpret_cast(reinterpret_cast(AllocatedBuffer) + CurOffset), ReadSize, &BytesRead); 105 | 106 | TotalSize -= BytesRead; 107 | CurOffset += BytesRead; 108 | 109 | if (Status != STATUS_SUCCESS || BytesRead == 0) 110 | { 111 | break; 112 | } 113 | } 114 | 115 | *Read = CurOffset; 116 | return Status; 117 | } 118 | 119 | __forceinline NTSTATUS WriteMemory(uint64 Cr3, void* Address, void* Buffer, size_t Size, size_t* Written) 120 | { 121 | if (Cr3 == 0 || !Address || !Buffer || Size == 0 || !Written) 122 | { 123 | return STATUS_INVALID_PARAMETER; 124 | } 125 | 126 | size_t CurOffset = 0; 127 | size_t TotalSize = Size; 128 | NTSTATUS Status = STATUS_SUCCESS; 129 | 130 | while (TotalSize) 131 | { 132 | uint64 CurPhysAddr = physical::TranslateLinear(Cr3, reinterpret_cast(Address) + CurOffset); 133 | if (!CurPhysAddr) 134 | { 135 | return STATUS_UNSUCCESSFUL; 136 | } 137 | 138 | uint64 WriteSize = min(PAGE_SIZE - (CurPhysAddr & 0xFFF), TotalSize); 139 | size_t BytesWritten = 0; 140 | 141 | Status = physical::WritePhysical(CurPhysAddr, reinterpret_cast(reinterpret_cast(Buffer) + CurOffset), WriteSize, &BytesWritten); 142 | 143 | TotalSize -= BytesWritten; 144 | CurOffset += BytesWritten; 145 | 146 | if (Status != STATUS_SUCCESS || BytesWritten == 0) 147 | { 148 | break; 149 | } 150 | } 151 | 152 | *Written = CurOffset; 153 | return Status; 154 | } 155 | } -------------------------------------------------------------------------------- /driver/hide/thread.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace hide::thread 5 | { 6 | typedef void* (__fastcall* tLookUpHandle)(void*, HANDLE); 7 | typedef long long(__fastcall* tDestoyHandle)(void*, void*, void*); 8 | 9 | __forceinline bool ClearPspCidTable(PETHREAD _Thread) 10 | { 11 | const auto mod = modules::get_kernel_module(skCrypt("ntoskrnl.exe")); 12 | if (!mod) 13 | { 14 | printf("Failed to get ntoskrnl.exe\n"); 15 | return false; 16 | } 17 | 18 | const auto PspCidTableAddress = scanner::find_pattern( 19 | mod.base, 20 | hide::patterns::PspCidTableSig, 21 | hide::patterns::PspCidTableMask 22 | ); 23 | if (!PspCidTableAddress) 24 | { 25 | printf("Failed to find PspCidTable\n"); 26 | return false; 27 | } 28 | 29 | void* PspCidTable = *(void**)(*(unsigned int*)(PspCidTableAddress + 3ULL) + (uint64)PspCidTableAddress + 7ULL); 30 | 31 | const auto LookUpHandle = reinterpret_cast(scanner::find_pattern( 32 | mod.base, 33 | hide::patterns::LookUpHandleSig, 34 | hide::patterns::LookUpHandleMask 35 | )); 36 | 37 | const auto DestroyHandle = reinterpret_cast(scanner::find_pattern( 38 | mod.base, 39 | hide::patterns::DestroyHandleSig, 40 | hide::patterns::DestroyHandleMask 41 | )); 42 | 43 | if (!LookUpHandle || !DestroyHandle) 44 | { 45 | printf("Failed to find LookUpHandle or DestroyHandle\n"); 46 | return false; 47 | } 48 | 49 | const auto ThreadId = PsGetThreadId(_Thread); 50 | if (!ThreadId) 51 | { 52 | printf("Failed to get thread id\n"); 53 | return false; 54 | } 55 | 56 | void* Entry = LookUpHandle(PspCidTable, ThreadId); 57 | if (!Entry) 58 | { 59 | printf("Failed to lookup entry\n"); 60 | return false; 61 | } 62 | 63 | DestroyHandle(PspCidTable, ThreadId, Entry); 64 | return true; 65 | } 66 | 67 | __forceinline void SwapThreadValues(PETHREAD _Current, PETHREAD _Target) 68 | { 69 | const auto Current = reinterpret_cast(_Current); 70 | const auto Target = reinterpret_cast(_Target); 71 | 72 | *(void**)(Current + hide::offsets::StartAddress) = *(void**)(Target + hide::offsets::StartAddress); 73 | *(void**)(Current + hide::offsets::Win32StartAddress) = *(void**)(Target + hide::offsets::Win32StartAddress); 74 | } 75 | 76 | __forceinline bool IsAdressOutsideModulelist(uint64 Address) 77 | { 78 | if (!Address) 79 | return true; 80 | 81 | PRTL_PROCESS_MODULES Modules = modules::get_modules(); 82 | 83 | for (ULONG i = 0; i < Modules->NumberOfModules; i++) 84 | { 85 | const auto Module = Modules->Modules[i]; 86 | 87 | if (Address >= (ULONG64)Module.ImageBase && 88 | Address <= (ULONG64)Module.ImageBase + Module.ImageSize) 89 | { 90 | return false; 91 | } 92 | } 93 | 94 | return true; 95 | } 96 | 97 | __forceinline PETHREAD GetValidThread() 98 | { 99 | for (ULONG ThreadID = 4; ThreadID < 0xFFFF; ThreadID += 4) 100 | { 101 | PETHREAD Thread = 0; 102 | if (!NT_SUCCESS(PsLookupThreadByThreadId((HANDLE)ThreadID, &Thread)) || !Thread) 103 | continue; 104 | 105 | if (!PsIsSystemThread(Thread)) 106 | { 107 | ObDereferenceObject(Thread); 108 | continue; 109 | } 110 | 111 | if (Thread == PsGetCurrentThread()) 112 | { 113 | ObDereferenceObject(Thread); 114 | continue; 115 | } 116 | 117 | const auto StartAddress = *(void**)(reinterpret_cast(Thread) + hide::offsets::StartAddress); 118 | if (!StartAddress) 119 | { 120 | ObDereferenceObject(Thread); 121 | continue; 122 | } 123 | 124 | if (IsAdressOutsideModulelist(reinterpret_cast(StartAddress))) 125 | { 126 | ObDereferenceObject(Thread); 127 | continue; 128 | } 129 | 130 | printf("Found valid thread with startaddress: %p\n", StartAddress); 131 | 132 | return Thread; 133 | } 134 | 135 | return 0; 136 | } 137 | 138 | __forceinline bool Hide() 139 | { 140 | const auto Thread = reinterpret_cast(PsGetCurrentThread()); 141 | if (!Thread) 142 | { 143 | printf("Invalid param\n"); 144 | return false; 145 | } 146 | 147 | *reinterpret_cast(Thread + hide::offsets::MiscFlags) &= ~(1ul << hide::offsets::SystemThread); 148 | *reinterpret_cast(Thread + hide::offsets::MiscFlags) &= ~(1ul << hide::offsets::AlertAble); 149 | *reinterpret_cast(Thread + hide::offsets::MiscFlags) &= ~(1ul << hide::offsets::ApcQueuable); 150 | 151 | printf("Spoofed thread values\n"); 152 | 153 | //if (!ClearPspCidTable(PsGetCurrentThread())) 154 | //{ 155 | // printf("Failed to clear PspCidTable\n"); 156 | // return false; 157 | //} 158 | // 159 | //printf("Cleared PspCidTable\n"); 160 | 161 | const auto ValidThread = GetValidThread(); 162 | if (!ValidThread) 163 | { 164 | printf("Failed to get a valid thread\n"); 165 | return false; 166 | } 167 | 168 | SwapThreadValues(PsGetCurrentThread(), ValidThread); 169 | 170 | printf("Swapped thread values\n"); 171 | 172 | return true; 173 | } 174 | } -------------------------------------------------------------------------------- /core.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.10.35004.147 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "driver", "driver\driver.vcxproj", "{AACC46B5-9AD8-465C-BA0D-03109F9C43F6}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "client", "client\client.vcxproj", "{A431507A-9D01-4D7C-A034-5C6551B1B745}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|ARM64 = Debug|ARM64 13 | Debug|x64 = Debug|x64 14 | Debug|x86 = Debug|x86 15 | lib-Debug|ARM64 = lib-Debug|ARM64 16 | lib-Debug|x64 = lib-Debug|x64 17 | lib-Debug|x86 = lib-Debug|x86 18 | lib-Release|ARM64 = lib-Release|ARM64 19 | lib-Release|x64 = lib-Release|x64 20 | lib-Release|x86 = lib-Release|x86 21 | Release|ARM64 = Release|ARM64 22 | Release|x64 = Release|x64 23 | Release|x86 = Release|x86 24 | EndGlobalSection 25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 26 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.Debug|ARM64.ActiveCfg = Debug|ARM64 27 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.Debug|ARM64.Build.0 = Debug|ARM64 28 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.Debug|ARM64.Deploy.0 = Debug|ARM64 29 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.Debug|x64.ActiveCfg = Debug|x64 30 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.Debug|x64.Build.0 = Debug|x64 31 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.Debug|x64.Deploy.0 = Debug|x64 32 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.Debug|x86.ActiveCfg = Debug|x64 33 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.Debug|x86.Build.0 = Debug|x64 34 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.Debug|x86.Deploy.0 = Debug|x64 35 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.lib-Debug|ARM64.ActiveCfg = Debug|ARM64 36 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.lib-Debug|ARM64.Build.0 = Debug|ARM64 37 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.lib-Debug|ARM64.Deploy.0 = Debug|ARM64 38 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.lib-Debug|x64.ActiveCfg = Debug|x64 39 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.lib-Debug|x64.Build.0 = Debug|x64 40 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.lib-Debug|x64.Deploy.0 = Debug|x64 41 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.lib-Debug|x86.ActiveCfg = Debug|x64 42 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.lib-Debug|x86.Build.0 = Debug|x64 43 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.lib-Debug|x86.Deploy.0 = Debug|x64 44 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.lib-Release|ARM64.ActiveCfg = Release|ARM64 45 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.lib-Release|ARM64.Build.0 = Release|ARM64 46 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.lib-Release|ARM64.Deploy.0 = Release|ARM64 47 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.lib-Release|x64.ActiveCfg = Release|x64 48 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.lib-Release|x64.Build.0 = Release|x64 49 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.lib-Release|x64.Deploy.0 = Release|x64 50 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.lib-Release|x86.ActiveCfg = Release|x64 51 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.lib-Release|x86.Build.0 = Release|x64 52 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.lib-Release|x86.Deploy.0 = Release|x64 53 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.Release|ARM64.ActiveCfg = Release|ARM64 54 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.Release|ARM64.Build.0 = Release|ARM64 55 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.Release|ARM64.Deploy.0 = Release|ARM64 56 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.Release|x64.ActiveCfg = Release|x64 57 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.Release|x64.Build.0 = Release|x64 58 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.Release|x64.Deploy.0 = Release|x64 59 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.Release|x86.ActiveCfg = Release|x64 60 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.Release|x86.Build.0 = Release|x64 61 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6}.Release|x86.Deploy.0 = Release|x64 62 | {A431507A-9D01-4D7C-A034-5C6551B1B745}.Debug|ARM64.ActiveCfg = Debug|x64 63 | {A431507A-9D01-4D7C-A034-5C6551B1B745}.Debug|ARM64.Build.0 = Debug|x64 64 | {A431507A-9D01-4D7C-A034-5C6551B1B745}.Debug|x64.ActiveCfg = Debug|x64 65 | {A431507A-9D01-4D7C-A034-5C6551B1B745}.Debug|x64.Build.0 = Debug|x64 66 | {A431507A-9D01-4D7C-A034-5C6551B1B745}.Debug|x86.ActiveCfg = Debug|Win32 67 | {A431507A-9D01-4D7C-A034-5C6551B1B745}.Debug|x86.Build.0 = Debug|Win32 68 | {A431507A-9D01-4D7C-A034-5C6551B1B745}.lib-Debug|ARM64.ActiveCfg = Debug|x64 69 | {A431507A-9D01-4D7C-A034-5C6551B1B745}.lib-Debug|ARM64.Build.0 = Debug|x64 70 | {A431507A-9D01-4D7C-A034-5C6551B1B745}.lib-Debug|x64.ActiveCfg = Debug|x64 71 | {A431507A-9D01-4D7C-A034-5C6551B1B745}.lib-Debug|x64.Build.0 = Debug|x64 72 | {A431507A-9D01-4D7C-A034-5C6551B1B745}.lib-Debug|x86.ActiveCfg = Debug|Win32 73 | {A431507A-9D01-4D7C-A034-5C6551B1B745}.lib-Debug|x86.Build.0 = Debug|Win32 74 | {A431507A-9D01-4D7C-A034-5C6551B1B745}.lib-Release|ARM64.ActiveCfg = Release|x64 75 | {A431507A-9D01-4D7C-A034-5C6551B1B745}.lib-Release|ARM64.Build.0 = Release|x64 76 | {A431507A-9D01-4D7C-A034-5C6551B1B745}.lib-Release|x64.ActiveCfg = Release|x64 77 | {A431507A-9D01-4D7C-A034-5C6551B1B745}.lib-Release|x64.Build.0 = Release|x64 78 | {A431507A-9D01-4D7C-A034-5C6551B1B745}.lib-Release|x86.ActiveCfg = Release|Win32 79 | {A431507A-9D01-4D7C-A034-5C6551B1B745}.lib-Release|x86.Build.0 = Release|Win32 80 | {A431507A-9D01-4D7C-A034-5C6551B1B745}.Release|ARM64.ActiveCfg = Release|x64 81 | {A431507A-9D01-4D7C-A034-5C6551B1B745}.Release|ARM64.Build.0 = Release|x64 82 | {A431507A-9D01-4D7C-A034-5C6551B1B745}.Release|x64.ActiveCfg = Release|x64 83 | {A431507A-9D01-4D7C-A034-5C6551B1B745}.Release|x64.Build.0 = Release|x64 84 | {A431507A-9D01-4D7C-A034-5C6551B1B745}.Release|x86.ActiveCfg = Release|Win32 85 | {A431507A-9D01-4D7C-A034-5C6551B1B745}.Release|x86.Build.0 = Release|Win32 86 | EndGlobalSection 87 | GlobalSection(SolutionProperties) = preSolution 88 | HideSolutionNode = FALSE 89 | EndGlobalSection 90 | GlobalSection(ExtensibilityGlobals) = postSolution 91 | SolutionGuid = {C35CA1C4-0ECA-4BF5-A9CE-242ACEA19A4B} 92 | EndGlobalSection 93 | EndGlobal 94 | -------------------------------------------------------------------------------- /driver/driver.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | Debug 14 | ARM64 15 | 16 | 17 | Release 18 | ARM64 19 | 20 | 21 | 22 | {AACC46B5-9AD8-465C-BA0D-03109F9C43F6} 23 | {dd38f7fc-d7bd-488b-9242-7d8754cde80d} 24 | v4.5 25 | 12.0 26 | Debug 27 | x64 28 | driver 29 | $(LatestTargetPlatformVersion) 30 | 31 | 32 | 33 | Windows10 34 | true 35 | WindowsKernelModeDriver10.0 36 | Driver 37 | WDM 38 | false 39 | 1 40 | 41 | 42 | Windows10 43 | false 44 | WindowsKernelModeDriver10.0 45 | Driver 46 | WDM 47 | false 48 | 1 49 | 50 | 51 | Windows10 52 | true 53 | WindowsKernelModeDriver10.0 54 | Driver 55 | WDM 56 | 57 | 58 | Windows10 59 | false 60 | WindowsKernelModeDriver10.0 61 | Driver 62 | WDM 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | DbgengKernelDebugger 73 | $(SolutionDir)bin\ 74 | $(SolutionDir)bin\$(ProjectName)\ 75 | $(ProjectName) 76 | $(ProjectDir);$(SolutionDir).shared\;$(IncludePath) 77 | false 78 | 79 | 80 | DbgengKernelDebugger 81 | $(SolutionDir)bin\ 82 | $(SolutionDir)bin\$(ProjectName)\ 83 | $(ProjectName) 84 | $(ProjectDir);$(SolutionDir).shared\;$(IncludePath) 85 | false 86 | true 87 | --checks=modernize-use-cast 88 | 89 | 90 | DbgengKernelDebugger 91 | 92 | 93 | DbgengKernelDebugger 94 | 95 | 96 | 97 | sha256 98 | 99 | 100 | stdcpp20 101 | false 102 | TurnOffAllWarnings 103 | false 104 | false 105 | 106 | 107 | Entry 108 | false 109 | 110 | 111 | 112 | 113 | sha256 114 | 115 | 116 | stdcpp20 117 | false 118 | TurnOffAllWarnings 119 | false 120 | false 121 | Full 122 | true 123 | None 124 | false 125 | false 126 | false 127 | AnySuitable 128 | true 129 | 130 | 131 | Entry 132 | false 133 | UseLinkTimeCodeGeneration 134 | false 135 | false 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /client/client.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 17.0 23 | Win32Proj 24 | {a431507a-9d01-4d7c-a034-5c6551b1b745} 25 | client 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v143 52 | true 53 | MultiByte 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | $(SolutionDir)bin\ 75 | $(SolutionDir)bin\$(ProjectName)\ 76 | $(ProjectDir)\;$(IncludePath) 77 | 78 | 79 | $(SolutionDir)bin\ 80 | $(SolutionDir)bin\$(ProjectName)\ 81 | $(ProjectDir)\;$(IncludePath) 82 | 83 | 84 | 85 | Level3 86 | true 87 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 88 | true 89 | 90 | 91 | Console 92 | true 93 | 94 | 95 | 96 | 97 | Level3 98 | true 99 | true 100 | true 101 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 102 | true 103 | 104 | 105 | Console 106 | true 107 | true 108 | true 109 | 110 | 111 | 112 | 113 | true 114 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 115 | true 116 | stdcpp20 117 | stdc17 118 | Full 119 | AnySuitable 120 | true 121 | true 122 | true 123 | Default 124 | 125 | 126 | Console 127 | true 128 | false 129 | RequireAdministrator 130 | NoErrorReport 131 | 132 | 133 | 134 | 135 | true 136 | true 137 | true 138 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 139 | true 140 | stdcpp20 141 | stdc17 142 | Full 143 | AnySuitable 144 | true 145 | 146 | 147 | Console 148 | true 149 | true 150 | true 151 | false 152 | RequireAdministrator 153 | NoErrorReport 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | -------------------------------------------------------------------------------- /driver/comm/comm.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class comm 5 | { 6 | public: 7 | 8 | // Open shared section 9 | __forceinline static NTSTATUS Open() 10 | { 11 | InitStrings(); 12 | 13 | OBJECT_ATTRIBUTES ObjectAttributes{}; 14 | InitializeObjectAttributes(&ObjectAttributes, 15 | &SectionName, 16 | OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 17 | NULL, 18 | NULL 19 | ); 20 | 21 | LARGE_INTEGER MaximumSize{}; 22 | MaximumSize.QuadPart = 1024 * 1024; 23 | 24 | Status = ZwCreateSection( 25 | &SectionHandle, 26 | SECTION_ALL_ACCESS, 27 | &ObjectAttributes, 28 | &MaximumSize, 29 | PAGE_READWRITE, 30 | SEC_COMMIT, 31 | NULL 32 | ); 33 | if (!NT_SUCCESS(Status)) { 34 | printf("Failed to create section: 0x%X\n", Status); 35 | Cleanup(); 36 | return Status; 37 | } 38 | 39 | PVOID SectionObject{}; 40 | Status = ObReferenceObjectByHandle( 41 | SectionHandle, 42 | SECTION_MAP_READ | SECTION_QUERY, 43 | MmSectionObjectType, 44 | KernelMode, 45 | &SectionObject, 46 | nullptr 47 | ); 48 | if (!NT_SUCCESS(Status)) 49 | { 50 | printf("Failed to reference object by handle: 0x%X\n", Status); 51 | Cleanup(); 52 | return Status; 53 | } 54 | 55 | Status = MmMapViewInSystemSpace( 56 | SectionObject, 57 | &MappedBase, 58 | &MappedSize 59 | ); 60 | if (!NT_SUCCESS(Status)) 61 | { 62 | printf("Failed to map view in system space: 0x%X\n", Status); 63 | Cleanup(); 64 | return Status; 65 | } 66 | 67 | Status = OpenEvents(); 68 | if (!NT_SUCCESS(Status)) 69 | { 70 | printf("Failed to open event: 0x%X\n", Status); 71 | Cleanup(); 72 | return Status; 73 | } 74 | printf("Event handle: 0x%p\n", EventHandle); 75 | 76 | HANDLE ThreadHandle{}; 77 | Status = PsCreateSystemThread( 78 | &ThreadHandle, 79 | 0, 80 | 0, 81 | 0, 82 | 0, 83 | Handler, 84 | 0 85 | ); 86 | if (!NT_SUCCESS(Status)) 87 | { 88 | printf("Failed to create system thread: 0x%X\n", Status); 89 | Cleanup(); 90 | return Status; 91 | } 92 | 93 | ZwClose(ThreadHandle); 94 | return STATUS_SUCCESS; 95 | } 96 | 97 | private: 98 | 99 | // Events 100 | __forceinline static NTSTATUS OpenEvents() 101 | { 102 | Event = IoCreateNotificationEvent(&EventName, &EventHandle); 103 | if (!Event) 104 | { 105 | printf("Failed to create event\n"); 106 | return STATUS_UNSUCCESSFUL; 107 | } 108 | KeClearEvent(Event); 109 | 110 | EventResponse = IoCreateNotificationEvent(&EventResponseName, &EventResponseHandle); 111 | if (!EventResponse) 112 | { 113 | printf("Failed to create event response\n"); 114 | return STATUS_UNSUCCESSFUL; 115 | } 116 | KeClearEvent(EventResponse); 117 | 118 | return STATUS_SUCCESS; 119 | } 120 | 121 | // Packet handler thread 122 | __forceinline static void Handler(void* Context) 123 | { 124 | PEPROCESS TargetProcess{}; 125 | shared_data* Data = reinterpret_cast(MappedBase); 126 | 127 | if (!hide::thread::Hide()) 128 | { 129 | printf("Failed to hide thread\n"); 130 | goto DESTROY_AND_CLEANUP; 131 | } 132 | 133 | while (true) 134 | { 135 | ret::spoof_call(&KeWaitForSingleObject, (PVOID)Event, (KWAIT_REASON)Executive, (KPROCESSOR_MODE)KernelMode, (BOOLEAN)FALSE, (PLARGE_INTEGER)nullptr); 136 | ret::spoof_call(&KeClearEvent, (PRKEVENT)Event); 137 | 138 | if (Data->type == comm_type::none) 139 | { 140 | continue; 141 | } 142 | 143 | if (Data->type == comm_type::init) 144 | { 145 | printf("Received init\n"); 146 | if (!Init(Data)) 147 | { 148 | printf("Failed to initialize\n"); 149 | goto DESTROY_AND_CLEANUP; 150 | } 151 | ret::spoof_call(&KeSetEvent, (PRKEVENT)EventResponse, (KPRIORITY)IO_NO_INCREMENT, (BOOLEAN)FALSE); 152 | continue; 153 | } 154 | 155 | if (Data->size > CachePoolSize) 156 | { 157 | if (CachePool) 158 | { 159 | ExFreePool(CachePool); 160 | } 161 | 162 | CachePool = ret::spoof_call(&ExAllocatePool, (POOL_TYPE)NonPagedPoolNx, (SIZE_T)Data->size); 163 | if (!CachePool) 164 | { 165 | printf("Failed to allocate pool\n"); 166 | ret::spoof_call(&KeSetEvent, (PRKEVENT)EventResponse, (KPRIORITY)IO_NO_INCREMENT, (BOOLEAN)FALSE); 167 | continue; 168 | } 169 | 170 | CachePoolSize = Data->size; 171 | printf("Allocated new cache pool: 0x%p\n", CachePool); 172 | } 173 | 174 | NTSTATUS Status = ret::spoof_call(&PsLookupProcessByProcessId, reinterpret_cast(Data->process_id), &TargetProcess); 175 | if (!NT_SUCCESS(Status)) 176 | { 177 | printf("Failed to lookup process by process id: 0x%X\n", Status); 178 | ret::spoof_call(&KeSetEvent, (PRKEVENT)EventResponse, (KPRIORITY)IO_NO_INCREMENT, (BOOLEAN)FALSE); 179 | continue; 180 | } 181 | 182 | switch (Data->type) 183 | { 184 | case comm_type::cr3: 185 | { 186 | printf("Received cr3\n"); 187 | const auto BaseAddress = reinterpret_cast(ret::spoof_call(&PsGetProcessSectionBaseAddress, TargetProcess)); 188 | if (!BaseAddress) 189 | { 190 | printf("Failed to get base address\n"); 191 | break; 192 | } 193 | const auto DirBase = physical::cr3::GetFromBase(BaseAddress); 194 | if (!DirBase) 195 | { 196 | printf("Failed to get DirBase\n"); 197 | break; 198 | } 199 | 200 | physical::cr3::StoredCr3 = DirBase; 201 | Data->buffer = DirBase; 202 | break; 203 | } 204 | case comm_type::base: 205 | { 206 | printf("Received base\n"); 207 | const auto BaseAddress = reinterpret_cast(ret::spoof_call(&PsGetProcessSectionBaseAddress, TargetProcess)); 208 | if (!BaseAddress) 209 | { 210 | printf("Failed to get base address\n"); 211 | break; 212 | } 213 | 214 | Data->buffer = BaseAddress; 215 | break; 216 | } 217 | case comm_type::read_physical: 218 | { 219 | printf("Received read physical\n"); 220 | physical::ReadMemory(physical::cr3::StoredCr3, reinterpret_cast(Data->address), CachePool, Data->size, &Data->size); 221 | if (!Data->size) 222 | { 223 | printf("Failed to read memory\n"); 224 | break; 225 | } 226 | physical::WriteMemory(ClientCr3, reinterpret_cast(Data->buffer), CachePool, Data->size, &Data->size); 227 | if (!Data->size) 228 | { 229 | printf("Failed to write memory\n"); 230 | break; 231 | } 232 | break; 233 | } 234 | case comm_type::write_physical: 235 | { 236 | printf("Received write physical\n"); 237 | physical::ReadMemory(ClientCr3, reinterpret_cast(Data->buffer), CachePool, Data->size, &Data->size); 238 | if (!Data->size) 239 | { 240 | printf("Failed to read memory\n"); 241 | break; 242 | } 243 | physical::WriteMemory(physical::cr3::StoredCr3, reinterpret_cast(Data->address), CachePool, Data->size, &Data->size); 244 | if (!Data->size) 245 | { 246 | printf("Failed to write memory\n"); 247 | break; 248 | } 249 | break; 250 | } 251 | case comm_type::destory: 252 | { 253 | printf("Received destory\n"); 254 | goto DESTROY_AND_CLEANUP; 255 | } 256 | default: 257 | { 258 | printf("Received unknown type\n"); 259 | break; 260 | } 261 | } 262 | 263 | ret::spoof_call(&KeSetEvent, (PRKEVENT)EventResponse, (KPRIORITY)IO_NO_INCREMENT, (BOOLEAN)FALSE); 264 | } 265 | 266 | DESTROY_AND_CLEANUP: 267 | printf("Exiting thread\n"); 268 | ret::spoof_call(&KeSetEvent, (PRKEVENT)EventResponse, (KPRIORITY)IO_NO_INCREMENT, (BOOLEAN)FALSE); 269 | Cleanup(); 270 | ret::spoof_call(&PsTerminateSystemThread, STATUS_SUCCESS); 271 | } 272 | 273 | // Init for client 274 | __forceinline static bool Init(shared_data* Data) 275 | { 276 | ClientPID = reinterpret_cast(Data->process_id); 277 | printf("Client PID: 0x%X\n", ClientPID); 278 | if (!ClientPID) 279 | { 280 | printf("Invalid client pid\n"); 281 | return false; 282 | } 283 | 284 | Status = ret::spoof_call(&PsLookupProcessByProcessId, ClientPID, &ClientProcess); 285 | if (!NT_SUCCESS(Status)) 286 | { 287 | printf("Failed to lookup client by process id: 0x%X\n", Status); 288 | return false; 289 | } 290 | 291 | printf("Client process: 0x%p\n", ClientProcess); 292 | 293 | ClientBaseAddress = reinterpret_cast(ret::spoof_call(&PsGetProcessSectionBaseAddress, ClientProcess)); 294 | printf("Client base address: 0x%p\n", ClientBaseAddress); 295 | if (!ClientBaseAddress) 296 | { 297 | printf("Failed to get client base address\n"); 298 | return false; 299 | } 300 | 301 | ClientCr3 = physical::cr3::GetFromBase(ClientBaseAddress); 302 | printf("Client cr3: 0x%p\n", ClientCr3); 303 | if (!ClientCr3) 304 | { 305 | printf("Failed to get client cr3\n"); 306 | return false; 307 | } 308 | return true; 309 | } 310 | 311 | // Cleanup 312 | __forceinline static void Cleanup() 313 | { 314 | if (SectionHandle) 315 | { 316 | ret::spoof_call(&ZwClose, SectionHandle); 317 | } 318 | 319 | if (MappedBase) 320 | { 321 | ret::spoof_call(&MmUnmapViewInSystemSpace, MappedBase); 322 | } 323 | 324 | if (EventHandle) 325 | { 326 | ret::spoof_call(&ZwClose, EventHandle); 327 | } 328 | 329 | if (EventResponseHandle) 330 | { 331 | ret::spoof_call(&ZwClose, EventResponseHandle); 332 | } 333 | 334 | if (CachePool) 335 | { 336 | ret::spoof_call(&ExFreePool, CachePool); 337 | } 338 | 339 | if (ClientProcess) 340 | { 341 | ret::spoof_call(&ObfDereferenceObject, (PVOID)ClientProcess); 342 | } 343 | } 344 | 345 | // Strings 346 | static void InitStrings() 347 | { 348 | RtlInitUnicodeString(&SectionName, L"\\BaseNamedObjects\\Global\\SharedData"); 349 | RtlInitUnicodeString(&EventName, L"\\BaseNamedObjects\\SharedMemEvent"); 350 | RtlInitUnicodeString(&EventResponseName, L"\\BaseNamedObjects\\SharedMemEventResponse"); 351 | } 352 | 353 | private: 354 | 355 | // Strings 356 | inline static UNICODE_STRING SectionName{}; 357 | inline static UNICODE_STRING EventName{}; 358 | inline static UNICODE_STRING EventResponseName{}; 359 | 360 | // Global 361 | inline static NTSTATUS Status{}; 362 | 363 | // Section 364 | inline static HANDLE SectionHandle{}; 365 | inline static PVOID MappedBase{}; 366 | inline static SIZE_T MappedSize{}; 367 | 368 | // Client 369 | inline static PEPROCESS ClientProcess{}; 370 | inline static HANDLE ClientPID{}; 371 | inline static uint64 ClientBaseAddress{}; 372 | inline static uint64 ClientCr3{}; 373 | 374 | // Events 375 | inline static HANDLE EventHandle{}; 376 | inline static PKEVENT Event{}; 377 | inline static HANDLE EventResponseHandle{}; 378 | inline static PKEVENT EventResponse{}; 379 | 380 | // Cache 381 | inline static void* CachePool{}; 382 | inline static size_t CachePoolSize{}; 383 | }; --------------------------------------------------------------------------------