├── ModuleSpoof.sln ├── ModuleSpoof ├── ModuleSpoof.vcxproj ├── ModuleSpoof.vcxproj.filters ├── ModuleSpoof.vcxproj.user ├── honeypot.cpp ├── honeypot.hpp ├── main.cpp ├── manual_map.cpp ├── manual_map.hpp ├── spoof_module.cpp ├── spoof_module.hpp ├── util.hpp ├── z_hook.cpp └── z_hook.hpp ├── Protected ├── Protected.vcxproj ├── Protected.vcxproj.filters ├── Protected.vcxproj.user └── main.cpp └── README.md /ModuleSpoof.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.4.33213.308 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ModuleSpoof", "ModuleSpoof\ModuleSpoof.vcxproj", "{9989F746-9EEA-4A45-B099-2767ADCA4E44}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Protected", "Protected\Protected.vcxproj", "{067D72D3-EE55-4EBF-BD6E-19C2B7955DE1}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {9989F746-9EEA-4A45-B099-2767ADCA4E44}.Debug|x64.ActiveCfg = Debug|x64 19 | {9989F746-9EEA-4A45-B099-2767ADCA4E44}.Debug|x64.Build.0 = Debug|x64 20 | {9989F746-9EEA-4A45-B099-2767ADCA4E44}.Debug|x86.ActiveCfg = Debug|Win32 21 | {9989F746-9EEA-4A45-B099-2767ADCA4E44}.Debug|x86.Build.0 = Debug|Win32 22 | {9989F746-9EEA-4A45-B099-2767ADCA4E44}.Release|x64.ActiveCfg = Release|x64 23 | {9989F746-9EEA-4A45-B099-2767ADCA4E44}.Release|x64.Build.0 = Release|x64 24 | {9989F746-9EEA-4A45-B099-2767ADCA4E44}.Release|x86.ActiveCfg = Release|Win32 25 | {9989F746-9EEA-4A45-B099-2767ADCA4E44}.Release|x86.Build.0 = Release|Win32 26 | {067D72D3-EE55-4EBF-BD6E-19C2B7955DE1}.Debug|x64.ActiveCfg = Debug|x64 27 | {067D72D3-EE55-4EBF-BD6E-19C2B7955DE1}.Debug|x64.Build.0 = Debug|x64 28 | {067D72D3-EE55-4EBF-BD6E-19C2B7955DE1}.Debug|x86.ActiveCfg = Debug|Win32 29 | {067D72D3-EE55-4EBF-BD6E-19C2B7955DE1}.Debug|x86.Build.0 = Debug|Win32 30 | {067D72D3-EE55-4EBF-BD6E-19C2B7955DE1}.Release|x64.ActiveCfg = Release|x64 31 | {067D72D3-EE55-4EBF-BD6E-19C2B7955DE1}.Release|x64.Build.0 = Release|x64 32 | {067D72D3-EE55-4EBF-BD6E-19C2B7955DE1}.Release|x86.ActiveCfg = Release|Win32 33 | {067D72D3-EE55-4EBF-BD6E-19C2B7955DE1}.Release|x86.Build.0 = Release|Win32 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | GlobalSection(ExtensibilityGlobals) = postSolution 39 | SolutionGuid = {C3494850-1496-44F7-ABA2-0F5E539A94FE} 40 | EndGlobalSection 41 | EndGlobal 42 | -------------------------------------------------------------------------------- /ModuleSpoof/ModuleSpoof.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 | 16.0 23 | Win32Proj 24 | {9989f746-9eea-4a45-b099-2767adca4e44} 25 | ModuleSpoof 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 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Level3 76 | true 77 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS 78 | true 79 | 80 | 81 | Console 82 | true 83 | 84 | 85 | 86 | 87 | Level3 88 | true 89 | true 90 | true 91 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS 92 | true 93 | 94 | 95 | Console 96 | true 97 | true 98 | true 99 | 100 | 101 | 102 | 103 | Level3 104 | true 105 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS 106 | true 107 | 108 | 109 | Console 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | true 117 | true 118 | true 119 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS 120 | true 121 | 122 | 123 | Console 124 | true 125 | true 126 | true 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /ModuleSpoof/ModuleSpoof.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | Source Files 40 | 41 | 42 | Source Files 43 | 44 | 45 | Source Files 46 | 47 | 48 | -------------------------------------------------------------------------------- /ModuleSpoof/ModuleSpoof.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /ModuleSpoof/honeypot.cpp: -------------------------------------------------------------------------------- 1 | #include "honeypot.hpp" 2 | uint64_t module_base; 3 | bool is_va_loaded(PVOID virtualAddress) { 4 | PSAPI_WORKING_SET_EX_INFORMATION w = { 0 }; 5 | w.VirtualAddress = virtualAddress; 6 | K32QueryWorkingSetEx(GetCurrentProcess(), &w, sizeof(w)); 7 | 8 | return w.VirtualAttributes.Valid; 9 | } 10 | 11 | void honeypot(){ 12 | 13 | PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)module_base; 14 | if (dos->e_magic != IMAGE_DOS_SIGNATURE) return; 15 | PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((BYTE*)module_base + dos->e_lfanew); 16 | if (nt->Signature != IMAGE_NT_SIGNATURE) return; 17 | uint32_t pages = SIZE_TO_PAGES(nt->OptionalHeader.SizeOfImage); 18 | K32EmptyWorkingSet(GetCurrentProcess()); 19 | 20 | while (1) { 21 | for (uint32_t i = 0; i < pages; i++) { 22 | if (is_va_loaded((PVOID)(module_base + i * PAGE_SIZE))) { 23 | printf("Someone accessed the non spoofed module!\n"); 24 | K32EmptyWorkingSet(GetCurrentProcess()); 25 | } 26 | } 27 | } 28 | } 29 | 30 | void run_honeypot(uint64_t base) { 31 | module_base = base; 32 | std::thread s(honeypot); 33 | s.detach(); 34 | } -------------------------------------------------------------------------------- /ModuleSpoof/honeypot.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define PAGE_SIZE 0x1000 11 | #define PAGE_MASK 0xFFF 12 | #define PAGE_SHIFT 12 13 | #define SIZE_TO_PAGES(Size) (((Size) >> PAGE_SHIFT) + (((Size) & PAGE_MASK) ? 1 : 0)) 14 | #define PAGES_TO_SIZE(Pages) ((Pages) << PAGE_SIZE) 15 | 16 | bool is_va_loaded(PVOID virtualAddress); 17 | void honeypot(); 18 | void run_honeypot(uint64_t base); -------------------------------------------------------------------------------- /ModuleSpoof/main.cpp: -------------------------------------------------------------------------------- 1 | #include "spoof_module.hpp" 2 | #include "honeypot.hpp" 3 | 4 | void main() { 5 | uint64_t org = spoof("Protected.dll"); 6 | run_honeypot(org); 7 | while (1) { 8 | Sleep(100); 9 | } 10 | } 11 | 12 | BOOL start = FALSE; 13 | BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID Reserved){ 14 | if (dwReason == DLL_PROCESS_ATTACH){ 15 | if(start == FALSE){ 16 | start = TRUE; 17 | AllocConsole(); 18 | freopen("CONOUT$", "w", stdout); 19 | main(); 20 | } 21 | } 22 | return 1; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /ModuleSpoof/manual_map.cpp: -------------------------------------------------------------------------------- 1 | #include "manual_map.hpp" 2 | 3 | bool manual_map_reloc(uint64_t base) { 4 | PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)base; 5 | if (dos->e_magic != IMAGE_DOS_SIGNATURE) return false; 6 | PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((uint64_t)base + dos->e_lfanew); 7 | if (nt->Signature != IMAGE_NT_SIGNATURE) return false; 8 | 9 | PIMAGE_BASE_RELOCATION reloc = (PIMAGE_BASE_RELOCATION)(nt->OptionalHeader.DataDirectory[0x5].VirtualAddress + base); 10 | while (reloc->SizeOfBlock && reloc->VirtualAddress) { 11 | if (reloc->SizeOfBlock >= sizeof(IMAGE_BASE_RELOCATION)) { 12 | uint16_t* info = (uint16_t*)((uint64_t)reloc + sizeof(IMAGE_BASE_RELOCATION)); 13 | if (info == NULL) return false; 14 | 15 | for (uint32_t i = 0; i < (reloc->SizeOfBlock - 0x4); i++) { 16 | if (info[i]) { 17 | *(uint64_t*)((uint64_t)base + (reloc->VirtualAddress + (info[i] & 0xFFF))) += (base - nt->OptionalHeader.ImageBase); 18 | } 19 | } 20 | } 21 | reloc = (PIMAGE_BASE_RELOCATION)((uint64_t)reloc + reloc->SizeOfBlock); 22 | } 23 | 24 | return true; 25 | } 26 | 27 | bool manual_map_import(uint64_t base) { 28 | PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)base; 29 | if (dos->e_magic != IMAGE_DOS_SIGNATURE) return false; 30 | PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((uint64_t)base + dos->e_lfanew); 31 | if (nt->Signature != IMAGE_NT_SIGNATURE) return false; 32 | 33 | PIMAGE_IMPORT_DESCRIPTOR import = (PIMAGE_IMPORT_DESCRIPTOR)(nt->OptionalHeader.DataDirectory[1].VirtualAddress + base); 34 | while (import->Name) { 35 | PIMAGE_THUNK_DATA thunk = (PIMAGE_THUNK_DATA)(base + import->OriginalFirstThunk); 36 | PIMAGE_THUNK_DATA fthunk = (PIMAGE_THUNK_DATA)(base + import->FirstThunk); 37 | 38 | HMODULE hmodule = LoadLibraryA((LPCSTR)(base + import->Name)); 39 | if (hmodule == NULL) return false; 40 | 41 | while (thunk->u1.AddressOfData) { 42 | LPCSTR name = (thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) ? (LPCSTR)(thunk->u1.Ordinal & 0xFFFF) : ((PIMAGE_IMPORT_BY_NAME)(base + thunk->u1.AddressOfData))->Name; 43 | *(PVOID*)fthunk = GetProcAddress(hmodule, name); 44 | thunk++, fthunk++; 45 | } 46 | import++; 47 | } 48 | 49 | return true; 50 | } 51 | 52 | uint64_t manual_map_populate(uint64_t file_buffer) { 53 | PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)file_buffer; 54 | if (dos->e_magic != IMAGE_DOS_SIGNATURE) return 0; 55 | PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((uint64_t)file_buffer + dos->e_lfanew); 56 | if (nt->Signature != IMAGE_NT_SIGNATURE) return 0; 57 | PVOID mapped_base = VirtualAlloc(NULL, nt->OptionalHeader.SizeOfImage, MEM_COMMIT, PAGE_EXECUTE_READWRITE); // TODO set page protection 58 | 59 | memcpy(mapped_base, (PVOID)file_buffer, nt->OptionalHeader.SizeOfHeaders); 60 | PIMAGE_SECTION_HEADER section_ptr = IMAGE_FIRST_SECTION(nt); 61 | for (uint16_t i = 0; i < nt->FileHeader.NumberOfSections; i++) { 62 | IMAGE_SECTION_HEADER section = (IMAGE_SECTION_HEADER)*section_ptr++; 63 | memcpy((PVOID)((uint64_t)mapped_base + section.VirtualAddress), (PVOID)((uint64_t)file_buffer + section.PointerToRawData), section.SizeOfRawData); 64 | } 65 | 66 | return (uint64_t)mapped_base; 67 | } 68 | 69 | PVOID manual_map(PVOID file) { 70 | PVOID file_buffer = file; 71 | 72 | uint64_t mapped_base = manual_map_populate((uint64_t)file_buffer); 73 | manual_map_reloc(mapped_base); 74 | manual_map_import(mapped_base); 75 | 76 | return (PVOID)mapped_base; 77 | } -------------------------------------------------------------------------------- /ModuleSpoof/manual_map.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | bool manual_map_reloc(uint64_t base); 8 | bool manual_map_import(uint64_t base); 9 | uint64_t manual_map_populate(uint64_t file_buffer); 10 | PVOID manual_map(PVOID file); -------------------------------------------------------------------------------- /ModuleSpoof/spoof_module.cpp: -------------------------------------------------------------------------------- 1 | #include "spoof_module.hpp" 2 | 3 | HMODULE remapped_location = 0; 4 | HMODULE original_location = 0; 5 | 6 | BOOL is_spoofed = FALSE; 7 | 8 | z_hook* load_lib = nullptr; 9 | z_hook* get_modulew = nullptr; 10 | z_hook* get_module_exw = nullptr; 11 | z_hook* get_proc_address_for_caller = nullptr; 12 | z_hook* get_proc_address = nullptr; 13 | z_hook* free_lib = nullptr; 14 | z_hook* main_info = nullptr; 15 | 16 | std::wstring wspoofed_name; 17 | std::string spoofed_name; 18 | 19 | EntryPoint_t spoofed_main; 20 | 21 | BOOL free_library_hook(HMODULE module) { 22 | log("free_library_hook called!\n"); 23 | if (module == remapped_location) { 24 | log("free_library_hook remapped called!\n"); 25 | return TRUE; 26 | } 27 | FreeLibrary_t lib = (FreeLibrary_t)(free_lib->gateway_bytes); 28 | BOOL ret = lib(module); 29 | 30 | return ret; 31 | } 32 | 33 | FARPROC __stdcall get_proc_address_hook(HMODULE module, LPCSTR name) { 34 | log("get_proc_address_hook called!\n"); 35 | 36 | GetProcAddress_t orginal = (GetProcAddress_t)(get_proc_address->gateway_bytes); 37 | 38 | if (module == original_location) { 39 | log("get_proc_address_hook original location called!\n"); 40 | } 41 | 42 | if (module == remapped_location) { 43 | //Sleep(5000); 44 | log("get_proc_address_hook remapped called!\n"); 45 | 46 | return (FARPROC)z_get_proc_address((uint64_t)remapped_location, name); 47 | } 48 | 49 | return orginal(module, name); 50 | } 51 | 52 | __int64 __fastcall get_proc_address_for_caller_hook(void* a1, const char* a2, __int64 a3) { 53 | log("get_proc_address_for_caller_hook called!\n"); 54 | 55 | GetProcAddressForCaller_t orginal = (GetProcAddressForCaller_t)(get_proc_address_for_caller->gateway_bytes); 56 | if (a1 == original_location) { 57 | log("get_proc_address_for_caller_hook original location called!\n"); 58 | 59 | } 60 | if (a1 == remapped_location) { 61 | //Sleep(5000); 62 | log("get_proc_address_for_caller_hook remapped called!\n"); 63 | return (__int64)z_get_proc_address((uint64_t)remapped_location, a2); 64 | } 65 | 66 | return orginal(a1, a2, a3); 67 | } 68 | 69 | HMODULE __stdcall get_module_handleW_hook(LPCWSTR name) { 70 | logw(L"get_module_handleW_hook called: %s\n", name); 71 | 72 | GetModuleHandleW_t original = (GetModuleHandleW_t)(get_modulew->gateway_bytes); 73 | 74 | if (name == NULL) { 75 | return (HMODULE)NtCurrentPeb()->ImageBaseAddress; 76 | } 77 | 78 | if (wcscmp(name, wspoofed_name.c_str())) { 79 | auto ret = original(name); 80 | return ret; 81 | } 82 | 83 | log("get_module_handleW_hook remapped called!\n"); 84 | 85 | return remapped_location; 86 | 87 | } 88 | 89 | BOOL __stdcall get_module_handle_exW_hook(DWORD flags, LPCWSTR name, HMODULE* module) { 90 | log("get_module_handle_exW_hook called: %s\n", name); 91 | 92 | GetModuleHandleExW_t original = (GetModuleHandleExW_t)(get_module_exw->gateway_bytes); 93 | 94 | if (name == NULL) { 95 | *module = (HMODULE)NtCurrentPeb()->ImageBaseAddress; 96 | return TRUE; 97 | } 98 | 99 | if (wcscmp(name, wspoofed_name.c_str())) { 100 | return original(flags, name, module); 101 | } 102 | 103 | log("get_module_handle_exW_hook remapped called!\n"); 104 | 105 | *module = remapped_location; 106 | return TRUE; 107 | } 108 | 109 | HMODULE load_lib_hook(LPCWSTR name, HANDLE file, DWORD flags) { 110 | LoadLibraryExW_t original = (LoadLibraryExW_t)load_lib->gateway_bytes; 111 | log("load_lib_hook called!\n"); 112 | 113 | if (!wcsstr(name, wspoofed_name.c_str())) { 114 | HMODULE modT = original(name, file, flags); 115 | return modT; 116 | } 117 | 118 | if (is_spoofed == TRUE) { 119 | return remapped_location; 120 | } 121 | 122 | HMODULE ret = original(name, file, flags); 123 | if (ret == 0) { 124 | log("load_lib_hook error: %x\n", GetLastError()); 125 | return 0; 126 | } 127 | 128 | original_location = ret; 129 | is_spoofed = TRUE; 130 | 131 | log("load_lib_hook original location: 0x%x\n", ret); 132 | log("load_lib_hook spoofed location: 0x%x\n", remapped_location); 133 | 134 | return remapped_location; 135 | } 136 | 137 | BOOL WINAPI main_hook(HINSTANCE dll, DWORD reason, LPVOID reserved) { 138 | log("Spoofed entry hook was called! Base 0x%x Reason %d\n", dll, reason); 139 | 140 | auto ret = spoofed_main(remapped_location, reason, reserved); 141 | log("Spoofed entry was executed! return value %d\n", (int)ret); 142 | 143 | //Sleep(5000); 144 | return TRUE; 145 | } 146 | 147 | PVOID load_file(LPCWSTR path) { 148 | HANDLE file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL); 149 | DWORD file_size = GetFileSize(file, NULL); 150 | PVOID file_base = VirtualAlloc(NULL, file_size, MEM_COMMIT, PAGE_READWRITE); 151 | ReadFile(file, file_base, file_size, 0, 0); 152 | 153 | return file_base; 154 | } 155 | 156 | void WINAPI dll_callback(ULONG reason, PCLDR_DLL_NOTIFICATION_DATA data, PVOID context) { 157 | UNREFERENCED_PARAMETER(context); 158 | if (reason == LDR_DLL_NOTIFICATION_REASON_LOADED) { 159 | if (data == NULL || data->Loaded.FullDllName == NULL) return; 160 | if (wcscmp(data->Loaded.BaseDllName->Buffer, wspoofed_name.c_str()) || is_spoofed == TRUE) return; 161 | 162 | PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)data->Loaded.DllBase; 163 | if (dos->e_magic != IMAGE_DOS_SIGNATURE) return; 164 | PIMAGE_NT_HEADERS nt = PIMAGE_NT_HEADERS((uint64_t)dos + dos->e_lfanew); 165 | if (nt->Signature != IMAGE_NT_SIGNATURE) return; 166 | 167 | logw(L"Module load callback was called: %s\n", data->Loaded.FullDllName->Buffer); 168 | 169 | //Hook real entry. 170 | (main_info = new z_hook((void*)((uint64_t)dos + nt->OptionalHeader.AddressOfEntryPoint), main_hook))->activate(); 171 | 172 | //Now when entry is looked we manual map in spoofed module 173 | PVOID file = load_file(data->Loaded.FullDllName->Buffer); 174 | 175 | if (file == NULL) { 176 | log("Module load callback! Could not find file!\n"); 177 | while (1) {} 178 | } 179 | 180 | remapped_location = (HMODULE)manual_map(file); 181 | 182 | if (remapped_location == NULL) { 183 | log("Module load callback! Could not map module\n"); 184 | while (1) {} 185 | } 186 | 187 | dos = (PIMAGE_DOS_HEADER)remapped_location; 188 | if (dos->e_magic != IMAGE_DOS_SIGNATURE) return; 189 | nt = (PIMAGE_NT_HEADERS)((uint64_t)remapped_location + dos->e_lfanew); 190 | if (nt->Signature != IMAGE_NT_SIGNATURE) return; 191 | spoofed_main = (EntryPoint_t)(nt->OptionalHeader.AddressOfEntryPoint + (ULONGLONG)remapped_location); 192 | 193 | //Sleep(5000); 194 | } 195 | } 196 | 197 | NTSTATUS(NTAPI* LdrRegisterDllNotification)( 198 | ULONG flags, 199 | PLDR_DLL_NOTIFICATION_FUNCTION function, 200 | PVOID context, 201 | PVOID* cookie 202 | ); 203 | 204 | uint64_t spoof(std::string name) { 205 | spoofed_name = name; 206 | wspoofed_name = std::wstring(name.begin(), name.end()); 207 | 208 | log("spoofing %s!\n", name); 209 | 210 | VOID* dll_callback_handle = 0; 211 | *(void**)&LdrRegisterDllNotification = (void*)GetProcAddress(LoadLibraryA("ntdll.dll"), "LdrRegisterDllNotification"); 212 | LdrRegisterDllNotification(0, dll_callback, 0, &dll_callback_handle); 213 | log("Module load callback set!\n"); 214 | 215 | (load_lib = new z_hook((void*)GetProcAddress(LoadLibraryA("kernelbase.dll"), "LoadLibraryExW"), &load_lib_hook))->activate(); 216 | (get_modulew = new z_hook((void*)GetProcAddress(LoadLibraryA("kernelbase.dll"), "GetModuleHandleW"), &get_module_handleW_hook))->activate(); 217 | (get_module_exw = new z_hook((void*)GetProcAddress(LoadLibraryA("kernelbase.dll"), "GetModuleHandleExW"), &get_module_handle_exW_hook))->activate(); 218 | (free_lib = new z_hook((void*)GetProcAddress(LoadLibraryA("kernelbase.dll"), "FreeLibrary"), &free_library_hook))->activate(); 219 | (get_proc_address = new z_hook((void*)GetProcAddress(LoadLibraryA("kernelbase.dll"), "GetProcAddress"), &get_proc_address_hook))->activate(); 220 | (get_proc_address_for_caller = new z_hook((void*)GetProcAddress(LoadLibraryA("kernelbase.dll"), "GetProcAddressForCaller"), &get_proc_address_for_caller_hook))->activate(); 221 | log("Hooks activated!\n"); 222 | 223 | //----------Test----------\\ 224 | 225 | log("Loading protected dll!\n"); 226 | 227 | 228 | HMODULE dll = LoadLibraryA(name.c_str()); 229 | 230 | FARPROC address = GetProcAddress(dll, "export_test"); 231 | typedef int(__stdcall* export_test_t)(long bar); 232 | export_test_t export_test = (export_test_t)address; 233 | 234 | log("export_test: %d\n", export_test(5)); 235 | log("Test LoadLibraryA 0x%x\n ", LoadLibraryA(name.c_str())); 236 | log("Test GetModuleHandleA 0x%x\n ", GetModuleHandleA(name.c_str())); 237 | 238 | return (uint64_t)original_location; 239 | } 240 | -------------------------------------------------------------------------------- /ModuleSpoof/spoof_module.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "z_hook.hpp" 3 | #include "manual_map.hpp" 4 | #include "util.hpp" 5 | 6 | #define log(msg, ...) printf("[Zepta-ModuleSpoof] "); printf(msg, __VA_ARGS__);fflush(stdout); 7 | #define logw(msg, ...) wprintf(L"[Zepta-ModuleSpoof] "); wprintf(msg, __VA_ARGS__);fflush(stdout); 8 | 9 | typedef BOOL(WINAPI* EntryPoint_t)(HINSTANCE dll, DWORD reason, LPVOID reserved); 10 | typedef HMODULE(WINAPI* LoadLibraryExW_t)(LPCWSTR name, HANDLE file, DWORD flags); 11 | typedef BOOL(WINAPI* FreeLibrary_t)(HMODULE module); 12 | typedef BOOL(WINAPI* GetModuleHandleExW_t)(DWORD flags, LPCWSTR name, HMODULE* module); 13 | typedef HMODULE(WINAPI* GetModuleHandleW_t)(LPCWSTR name); 14 | typedef __int64 (WINAPI* LdrGetProcedureAddressForCaller_t)(unsigned __int64 a1, const void** a2, int a3, ULONGLONG* a4, char a5, unsigned __int64 a6); 15 | typedef __int64(WINAPI* GetProcAddressForCaller_t)(void* a1, const char* a2, __int64 a3); 16 | typedef FARPROC(WINAPI* GetProcAddress_t)(HMODULE module, LPCSTR name); 17 | 18 | BOOL free_library_hook(HMODULE module); 19 | FARPROC __stdcall get_proc_address_hook(HMODULE module, LPCSTR name); 20 | __int64 __fastcall get_proc_address_for_caller_hook(void* a1, const char* a2, __int64 a3); 21 | HMODULE __stdcall get_module_handleW_hook(LPCWSTR name); 22 | BOOL __stdcall get_module_handle_exW_hook(DWORD flags, LPCWSTR name, HMODULE* module); 23 | HMODULE load_lib_hook(LPCWSTR name, HANDLE file, DWORD flags); 24 | void WINAPI dll_callback(ULONG reason, PCLDR_DLL_NOTIFICATION_DATA data, PVOID context); 25 | uint64_t spoof(std::string name); 26 | -------------------------------------------------------------------------------- /ModuleSpoof/util.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #pragma pack(push) 8 | #pragma pack(1) 9 | template 10 | struct LIST_ENTRY_T 11 | { 12 | T Flink; 13 | T Blink; 14 | }; 15 | 16 | template 17 | struct UNICODE_STRING_T 18 | { 19 | union 20 | { 21 | struct 22 | { 23 | WORD Length; 24 | WORD MaximumLength; 25 | }; 26 | T dummy; 27 | }; 28 | T _Buffer; 29 | }; 30 | 31 | template 32 | struct _PEB_T 33 | { 34 | union 35 | { 36 | struct 37 | { 38 | BYTE InheritedAddressSpace; 39 | BYTE ReadImageFileExecOptions; 40 | BYTE BeingDebugged; 41 | BYTE BitField; 42 | }; 43 | T dummy01; 44 | }; 45 | T Mutant; 46 | T ImageBaseAddress; 47 | T Ldr; 48 | T ProcessParameters; 49 | T SubSystemData; 50 | T ProcessHeap; 51 | T FastPebLock; 52 | T AtlThunkSListPtr; 53 | T IFEOKey; 54 | T CrossProcessFlags; 55 | T UserSharedInfoPtr; 56 | DWORD SystemReserved; 57 | DWORD AtlThunkSListPtr32; 58 | T ApiSetMap; 59 | T TlsExpansionCounter; 60 | T TlsBitmap; 61 | DWORD TlsBitmapBits[2]; 62 | T ReadOnlySharedMemoryBase; 63 | T HotpatchInformation; 64 | T ReadOnlyStaticServerData; 65 | T AnsiCodePageData; 66 | T OemCodePageData; 67 | T UnicodeCaseTableData; 68 | DWORD NumberOfProcessors; 69 | union 70 | { 71 | DWORD NtGlobalFlag; 72 | NGF dummy02; 73 | }; 74 | LARGE_INTEGER CriticalSectionTimeout; 75 | T HeapSegmentReserve; 76 | T HeapSegmentCommit; 77 | T HeapDeCommitTotalFreeThreshold; 78 | T HeapDeCommitFreeBlockThreshold; 79 | DWORD NumberOfHeaps; 80 | DWORD MaximumNumberOfHeaps; 81 | T ProcessHeaps; 82 | T GdiSharedHandleTable; 83 | T ProcessStarterHelper; 84 | T GdiDCAttributeList; 85 | T LoaderLock; 86 | DWORD OSMajorVersion; 87 | DWORD OSMinorVersion; 88 | WORD OSBuildNumber; 89 | WORD OSCSDVersion; 90 | DWORD OSPlatformId; 91 | DWORD ImageSubsystem; 92 | DWORD ImageSubsystemMajorVersion; 93 | T ImageSubsystemMinorVersion; 94 | T ActiveProcessAffinityMask; 95 | T GdiHandleBuffer[A]; 96 | T PostProcessInitRoutine; 97 | T TlsExpansionBitmap; 98 | DWORD TlsExpansionBitmapBits[32]; 99 | T SessionId; 100 | ULARGE_INTEGER AppCompatFlags; 101 | ULARGE_INTEGER AppCompatFlagsUser; 102 | T pShimData; 103 | T AppCompatInfo; 104 | UNICODE_STRING_T CSDVersion; 105 | T ActivationContextData; 106 | T ProcessAssemblyStorageMap; 107 | T SystemDefaultActivationContextData; 108 | T SystemAssemblyStorageMap; 109 | T MinimumStackCommit; 110 | T FlsCallback; 111 | LIST_ENTRY_T FlsListHead; 112 | T FlsBitmap; 113 | DWORD FlsBitmapBits[4]; 114 | T FlsHighIndex; 115 | T WerRegistrationData; 116 | T WerShipAssertPtr; 117 | T pContextData; 118 | T pImageHeaderHash; 119 | T TracingFlags; 120 | }; 121 | 122 | typedef _PEB_T PEB32; 123 | typedef _PEB_T PEB64; 124 | #pragma pack(pop) 125 | 126 | inline PEB64* NtCurrentPeb() { 127 | #ifdef _M_X64 128 | return (PEB64*)(__readgsqword(0x60)); 129 | #elif _M_IX86 130 | return (PEB*)(__readfsdword(0x30)); 131 | #else 132 | #endif 133 | } 134 | 135 | typedef struct _ANSI_STRING { 136 | USHORT Length; 137 | USHORT MaximumLength; 138 | PSTR Buffer; 139 | } ANSI_STRING, * PANSI_STRING; 140 | typedef const UNICODE_STRING* PCUNICODE_STRING; 141 | typedef struct _LDR_DLL_LOADED_NOTIFICATION_DATA { 142 | ULONG Flags; //Reserved. 143 | PCUNICODE_STRING FullDllName; //The full path name of the DLL module. 144 | PCUNICODE_STRING BaseDllName; //The base file name of the DLL module. 145 | PVOID DllBase; //A pointer to the base address for the DLL in memory. 146 | ULONG SizeOfImage; //The size of the DLL image, in bytes. 147 | } LDR_DLL_LOADED_NOTIFICATION_DATA, * PLDR_DLL_LOADED_NOTIFICATION_DATA; 148 | 149 | typedef union _LDR_DLL_NOTIFICATION_DATA { 150 | LDR_DLL_LOADED_NOTIFICATION_DATA Loaded; 151 | LDR_DLL_LOADED_NOTIFICATION_DATA Unloaded; 152 | } LDR_DLL_NOTIFICATION_DATA, * PLDR_DLL_NOTIFICATION_DATA; 153 | 154 | typedef const _LDR_DLL_NOTIFICATION_DATA* PCLDR_DLL_NOTIFICATION_DATA; 155 | 156 | static uint64_t z_get_proc_address(uint64_t base, PCSTR export_name) { 157 | PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)base; 158 | if (dos->e_magic != IMAGE_DOS_SIGNATURE) return 0; 159 | PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((uint64_t)base + dos->e_lfanew); 160 | if (nt->Signature != IMAGE_NT_SIGNATURE) return 0; 161 | 162 | IMAGE_DATA_DIRECTORY exp = nt->OptionalHeader.DataDirectory[0]; 163 | IMAGE_EXPORT_DIRECTORY* dir = (IMAGE_EXPORT_DIRECTORY*)(base + exp.VirtualAddress); 164 | 165 | PDWORD addresses = (PDWORD)(base + dir->AddressOfFunctions); 166 | PDWORD names = (PDWORD)(base + dir->AddressOfNames); 167 | uint16_t* ordinals = (uint16_t*)(base + dir->AddressOfNameOrdinals); 168 | 169 | for (int i = 0; i < dir->NumberOfNames; i++) { 170 | PCSTR name = (PCSTR)(base + names[i]); 171 | if (!_strcmpi(name, export_name)) { 172 | return base + addresses[ordinals[i]]; 173 | } 174 | } 175 | 176 | return 0; 177 | } 178 | 179 | typedef VOID(CALLBACK* PLDR_DLL_NOTIFICATION_FUNCTION)( 180 | _In_ ULONG NotificationReason, 181 | _In_ PCLDR_DLL_NOTIFICATION_DATA NotificationData, 182 | _In_opt_ PVOID Context 183 | ); 184 | 185 | 186 | #define LDR_DLL_NOTIFICATION_REASON_LOADED 1 187 | #define LDR_DLL_NOTIFICATION_REASON_UNLOADED 2 188 | -------------------------------------------------------------------------------- /ModuleSpoof/z_hook.cpp: -------------------------------------------------------------------------------- 1 | #include "z_hook.hpp" 2 | //JMP X 3 | static const unsigned char shellcode[] = { 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 4 | 5 | z_hook::z_hook(void* original_function, void* target_function) { 6 | this->original_function = original_function; 7 | this->target_function = target_function; 8 | this->active = false; 9 | this->size = 0; 10 | this->gateway_bytes = 0; 11 | while (this->size < sizeof(shellcode)) 12 | this->size += get_instruction_size((uint8_t*)this->original_function + this->size); 13 | 14 | memcpy(this->original_bytes, this->original_function, this->size); 15 | } 16 | 17 | bool z_hook::activate(){ 18 | if (active == true) { 19 | return true; 20 | } 21 | 22 | uint8_t* buffer = (uint8_t*)VirtualAlloc(NULL, size + sizeof(shellcode), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); 23 | if (buffer == NULL) { 24 | return false; 25 | } 26 | 27 | memcpy(buffer, original_bytes, size); 28 | 29 | unsigned char temp[sizeof(shellcode)] = {0}; 30 | memcpy(temp, shellcode, sizeof(shellcode)); 31 | *(uint64_t*)((uint64_t)temp + 0x6) = (uint64_t)((uint64_t)original_function + size); 32 | 33 | memcpy(buffer + size, temp, sizeof(shellcode)); 34 | 35 | memset(temp, 0, sizeof(shellcode)); 36 | memcpy(temp, shellcode, sizeof(shellcode)); 37 | *(uint64_t*)((uint64_t)temp + 0x6) = (uint64_t)((uint64_t)target_function); 38 | 39 | DWORD old = 0; 40 | VirtualProtect(original_function, size, PAGE_EXECUTE_READWRITE, &old); 41 | 42 | memcpy(original_function, temp, sizeof(shellcode)); 43 | VirtualProtect(original_function, size, old, &old); 44 | 45 | active = true; 46 | gateway_bytes = buffer; 47 | 48 | return true; 49 | } 50 | 51 | bool z_hook::deactivate(){ 52 | if (active == false) 53 | return true; 54 | 55 | DWORD old = 0; 56 | VirtualProtect(original_function, size, PAGE_EXECUTE_READWRITE, &old); 57 | memcpy(original_function, original_bytes, size); 58 | VirtualProtect(original_function, size, old, &old); 59 | VirtualFree(gateway_bytes, sizeof(shellcode) + size, MEM_RELEASE); 60 | 61 | return false; 62 | } 63 | 64 | 65 | 66 | //https://github.com/Nomade040/length-disassembler 67 | //https://github.com/SamuelTulach/LightHook 68 | #define HOOK_R (*b >> 4) 69 | #define HOOK_C2 (*b & 0xF) 70 | 71 | static const unsigned char PREFIXES[] = { 0xF0, 0xF2, 0xF3, 0x2E, 0x36, 0x3E, 0x26, 0x64, 0x65, 0x66, 0x67 }; 72 | static const unsigned char OP1_MODRM[] = { 0x62, 0x63, 0x69, 0x6B, 0xC0, 0xC1, 0xC4, 0xC5, 0xC6, 0xC7, 0xD0, 0xD1, 0xD2, 0xD3, 0xF6, 0xF7, 0xFE, 0xFF }; 73 | static const unsigned char OP1_IMM8[] = { 0x6A, 0x6B, 0x80, 0x82, 0x83, 0xA8, 0xC0, 0xC1, 0xC6, 0xCD, 0xD4, 0xD5, 0xEB }; 74 | static const unsigned char OP1_IMM32[] = { 0x68, 0x69, 0x81, 0xA9, 0xC7, 0xE8, 0xE9 }; 75 | static const unsigned char OP2_MODRM[] = { 0x0D, 0xA3, 0xA4, 0xA5, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF }; 76 | 77 | static int find_byte(const unsigned char* buffer, const unsigned long long maxLength, const unsigned char value) 78 | { 79 | for (unsigned long long i = 0; i < maxLength; i++) 80 | { 81 | if (buffer[i] == value) 82 | return 1; 83 | } 84 | 85 | return 0; 86 | } 87 | 88 | void parse_mod_rm(unsigned char** buffer, const int addressPrefix){ 89 | const unsigned char modRm = *++ * buffer; 90 | 91 | if (!addressPrefix || (addressPrefix && **buffer >= 0x40)){ 92 | int hasSib = 0; 93 | if (**buffer < 0xC0 && (**buffer & 0b111) == 0b100 && !addressPrefix) 94 | hasSib = 1, (*buffer)++; 95 | 96 | if (modRm >= 0x40 && modRm <= 0x7F) 97 | (*buffer)++; 98 | else if ((modRm <= 0x3F && (modRm & 0b111) == 0b101) || (modRm >= 0x80 && modRm <= 0xBF)) 99 | *buffer += (addressPrefix) ? 2 : 4; 100 | else if (hasSib && (**buffer & 0b111) == 0b101) 101 | *buffer += (modRm & 0b01000000) ? 1 : 4; 102 | } 103 | else if (addressPrefix && modRm == 0x26) 104 | *buffer += 2; 105 | } 106 | 107 | int z_hook::get_instruction_size(const void* address){ 108 | unsigned long long offset = 0; 109 | int operandPrefix = 0, addressPrefix = 0, rexW = 0; 110 | unsigned char* b = (unsigned char*)address; 111 | 112 | for (int i = 0; i < 14 && find_byte(PREFIXES, sizeof(PREFIXES), *b) || HOOK_R == 4; i++, b++){ 113 | if (*b == 0x66) 114 | operandPrefix = 1; 115 | else if (*b == 0x67) 116 | addressPrefix = 1; 117 | else if (HOOK_R == 4 && HOOK_C2 >= 8) 118 | rexW = 1; 119 | } 120 | 121 | if (*b == 0x0F){ 122 | b++; 123 | if (*b == 0x38 || *b == 0x3A){ 124 | if (*b++ == 0x3A) 125 | offset++; 126 | 127 | parse_mod_rm(&b, addressPrefix); 128 | } 129 | else{ 130 | if (HOOK_R == 8) 131 | offset += 4; 132 | else if ((HOOK_R == 7 && HOOK_C2 < 4) || *b == 0xA4 || *b == 0xC2 || (*b > 0xC3 && *b <= 0xC6) || *b == 0xBA || *b == 0xAC) 133 | offset++; 134 | 135 | if (find_byte(OP2_MODRM, sizeof(OP2_MODRM), *b) || (HOOK_R != 3 && HOOK_R > 0 && HOOK_R < 7) || *b >= 0xD0 || (HOOK_R == 7 && HOOK_C2 != 7) || HOOK_R == 9 || HOOK_R == 0xB || (HOOK_R == 0xC && HOOK_C2 < 8) || (HOOK_R == 0 && HOOK_C2 < 4)) 136 | parse_mod_rm(&b, addressPrefix); 137 | } 138 | } 139 | else{ 140 | if ((HOOK_R == 0xE && HOOK_C2 < 8) || (HOOK_R == 0xB && HOOK_C2 < 8) || HOOK_R == 7 || (HOOK_R < 4 && (HOOK_C2 == 4 || HOOK_C2 == 0xC)) || (*b == 0xF6 && !(*(b + 1) & 48)) || find_byte(OP1_IMM8, sizeof(OP1_IMM8), *b)) 141 | offset++; 142 | else if (*b == 0xC2 || *b == 0xCA) 143 | offset += 2; 144 | else if (*b == 0xC8) 145 | offset += 3; 146 | else if ((HOOK_R < 4 && (HOOK_C2 == 5 || HOOK_C2 == 0xD)) || (HOOK_R == 0xB && HOOK_C2 >= 8) || (*b == 0xF7 && !(*(b + 1) & 48)) || find_byte(OP1_IMM32, sizeof(OP1_IMM32), *b)) 147 | offset += (rexW) ? 8 : (operandPrefix ? 2 : 4); 148 | else if (HOOK_R == 0xA && HOOK_C2 < 4) 149 | offset += (rexW) ? 8 : (addressPrefix ? 2 : 4); 150 | else if (*b == 0xEA || *b == 0x9A) 151 | offset += operandPrefix ? 4 : 6; 152 | 153 | if (find_byte(OP1_MODRM, sizeof(OP1_MODRM), *b) || (HOOK_R < 4 && (HOOK_C2 < 4 || (HOOK_C2 >= 8 && HOOK_C2 < 0xC))) || HOOK_R == 8 || (HOOK_R == 0xD && HOOK_C2 >= 8)) 154 | parse_mod_rm(&b, addressPrefix); 155 | } 156 | 157 | return (int)(++b + offset - (unsigned char*)address); 158 | } -------------------------------------------------------------------------------- /ModuleSpoof/z_hook.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | class z_hook{ 9 | public: 10 | z_hook(void* original_function, void* target_function); 11 | bool activate(); 12 | bool deactivate(); 13 | uint8_t* gateway_bytes; 14 | 15 | private: 16 | bool active; 17 | uint16_t size; 18 | 19 | unsigned char original_bytes[32]; 20 | 21 | void* original_function; 22 | void* target_function; 23 | 24 | int get_instruction_size(const void* address); 25 | }; 26 | 27 | -------------------------------------------------------------------------------- /Protected/Protected.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 | 16.0 23 | Win32Proj 24 | {067d72d3-ee55-4ebf-bd6e-19c2b7955de1} 25 | Protected 26 | 10.0 27 | 28 | 29 | 30 | DynamicLibrary 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | DynamicLibrary 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | DynamicLibrary 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | DynamicLibrary 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Level3 76 | true 77 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 78 | true 79 | 80 | 81 | Console 82 | true 83 | 84 | 85 | 86 | 87 | Level3 88 | true 89 | true 90 | true 91 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | true 93 | 94 | 95 | Console 96 | true 97 | true 98 | true 99 | 100 | 101 | 102 | 103 | Level3 104 | true 105 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 106 | true 107 | 108 | 109 | Console 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | true 117 | true 118 | true 119 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 120 | true 121 | 122 | 123 | Console 124 | true 125 | true 126 | true 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /Protected/Protected.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /Protected/Protected.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Protected/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define log(msg, ...) printf("[Zepta-Protected.dll] "); printf(msg, __VA_ARGS__);fflush(stdout); 7 | #define logw(msg, ...) wprintf(L"[Zepta-Protected.dll] "); wprintf(msg, __VA_ARGS__);fflush(stdout); 8 | int* bb = nullptr; 9 | void main(); 10 | extern "C" __declspec(dllexport) 11 | int __stdcall export_test(long bar) { 12 | log("export_test called\n"); 13 | 14 | int* nn = new int; 15 | *nn = 55; 16 | return *bb + 1 + *nn; 17 | } 18 | int m = 0; 19 | int func(void) { 20 | return 3; 21 | } 22 | 23 | class test_classes { 24 | public: 25 | 26 | test_classes() { 27 | log("test_classes called\n"); 28 | } 29 | 30 | void test() { 31 | log("test_classes test called\n"); 32 | } 33 | 34 | ~test_classes() { 35 | log("test_classes deloc called \n"); 36 | } 37 | }; 38 | 39 | void normal_test() { 40 | log("Normal test...\n"); 41 | log("Main fuction address: 0x%x\n", &main); 42 | log("export fuction address: 0x%x\n", &export_test); 43 | } 44 | 45 | //crt 46 | test_classes test; 47 | int gi = func(); 48 | void crt_test() { 49 | test_classes test2; 50 | test2.test(); 51 | 52 | test_classes* test3 = new test_classes; 53 | test3->test(); 54 | 55 | log("crt test gi %x\n", gi); 56 | _onexit(func); 57 | 58 | } 59 | 60 | void import_test() { 61 | log("ntdll: 0x%x\n", GetModuleHandleA("ntdll.dll")); 62 | log("kernelbase: 0x%x\n", GetModuleHandleA("kernelbase.dll")); 63 | log("Protected: 0x%x\n", GetModuleHandleA("Protected.dll")); 64 | 65 | } 66 | 67 | void main() { 68 | normal_test(); 69 | crt_test(); 70 | import_test(); 71 | 72 | bb = new int; 73 | *bb = 5; 74 | 75 | int u = 6; 76 | memcpy(bb, &u, sizeof(int)); 77 | 78 | log("... %d\n", *bb); 79 | } 80 | 81 | BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) { 82 | if (fdwReason == DLL_PROCESS_ATTACH) { 83 | main(); 84 | } 85 | return 1; 86 | } 87 | 88 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Module Spoof 2 | 3 | ## 1.1 Introduction: 4 | So recently I thought of a way to spoof the location of a DLL. By doing this you could hide important information from an attacker. 5 | And the only way they could find this DLL is by brute-forcing pages or by reversing the application. 6 | This project spoofs the DLL location by trapping/ redirecting internal API calls to the spoofed location. 7 | To explain this I made a picture: 8 | 9 | ![overview: ](https://i.imgur.com/zyPJnpy.png "overview: ") 10 | 11 | So this shows that internal calls to functions like 12 | GetModuleHandleW, GetModuleHandleExW, GetProcAddress and GetProcAddressForCaller will return the location of the spoofed location. 13 | The outside will still have the illusion that the DLL is at the location that PEB->LDR->protected.dll reports. 14 | 15 | ## 1.2 Technical details: 16 | To achieve this I found two alternatives. One way is to hook LoadLibrary and when LoadLibrary is called with the right name we manually map our DLL to another location. 17 | This has its drawbacks since we need to make sure the internal application never has access to the non-spoofed DLL because it will crash the application. 18 | Making sure the internal application does not have that access is difficult since there might be a lot of win32-API functions reporting the non-spoofed location. 19 | 20 | The other way I found is by a public repository[1]. To get more info on how this works I suggest reading the project's code. 21 | From what I've heard there are anti-cheats using this solution to break attacker's programs. 22 | 23 | ## 1.3 Honeypot: 24 | The non-spoofed DLL is also honeypotted to detect if anyone is trying to access the memory. 25 | This is also displayed in the picture. 26 | To demonstrate this functionality I recorded a video on accessing this DLL. 27 | 28 | [!["video"](https://img.youtube.com/vi/PL9dBUEDFas/0.jpg)](https://www.youtube.com/watch?v=PL9dBUEDFas) 29 | 30 | The honeypot catches most attackers but can be easily avoided by checking if the pages are loaded in memory before reading. 31 | 32 | ## 1.4 Proof of concept: 33 | I made a simple proof of concept for this idea which can be found here: https://github.com/Oliver-1-1/ModuleSpoof. 34 | This is a C++ project that spoofs the location of protected.dll. 35 | Protected.dll includes basic tests to showcase that it's working. 36 | I also tested this on game DLLs but without success. The most likely reason why it fails is because the manual mapping is faulty or that I forgot to hook a function. 37 | I might fix this in the future if I get motivated. 38 | 39 | ## 1.5 References: 40 | [1] = https://github.com/changeofpace/Self-Remapping-Code 41 | 42 | [2] = https://github.com/Oliver-1-1/ModuleSpoof 43 | 44 | Other sources are found in the code. 45 | --------------------------------------------------------------------------------