mirror of
https://github.com/wavestone-cdt/EDRSandblast.git
synced 2026-06-10 17:31:23 +00:00
D3FC0N 30 release: Obj callbacks, firewalling, symbols w/ internet, and more
Co-authored-by: Maxime Meignan <maxime.meignan@wavestone.com>
This commit is contained in:
@@ -0,0 +1,204 @@
|
||||
#include "SignatureOps.h"
|
||||
#include "../EDRSandblast.h"
|
||||
|
||||
// Concat in pSigners output the list of Signer(s) signing the specified file on disk.
|
||||
SignatureOpsError GetFileSigners(TCHAR* pFilePath, TCHAR* outSigners, size_t* szOutSigners) {
|
||||
HCERTSTORE hCertStore = NULL;
|
||||
HCRYPTMSG hCryptMsg = NULL;
|
||||
DWORD dwCountSigners = 0;
|
||||
DWORD dwcbSz = sizeof(DWORD), dwcbSzPrevious = sizeof(DWORD);
|
||||
PCMSG_SIGNER_INFO pSignerInfo = NULL;
|
||||
CERT_INFO certificateInfo = { 0 };
|
||||
PCCERT_CONTEXT pCertContext = NULL;
|
||||
TCHAR* tmpSignerName = NULL;
|
||||
TCHAR* pSigners = NULL;
|
||||
TCHAR* tmpSignerHolder = NULL;
|
||||
size_t sztmpSignerHolder = 0;
|
||||
TCHAR signerSeperator[] = TEXT(" | ");
|
||||
DWORD dwError = 0;
|
||||
BOOL returnStatus = 0;
|
||||
|
||||
returnStatus = CryptQueryObject(CERT_QUERY_OBJECT_FILE,
|
||||
pFilePath,
|
||||
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
|
||||
CERT_QUERY_FORMAT_FLAG_BINARY,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&hCertStore,
|
||||
&hCryptMsg,
|
||||
NULL);
|
||||
|
||||
if (!returnStatus) {
|
||||
dwError = GetLastError();
|
||||
// File is not signed.
|
||||
if (dwError == CRYPT_E_NO_MATCH) {
|
||||
return E_NOT_SIGNED;
|
||||
}
|
||||
else {
|
||||
_tprintf_or_not(TEXT("[!] Couldn't retrieve certificate objects of file \"%s\" (CryptQueryObject(CERT_QUERY_OBJECT_FILE) failed: 0x%08lx)\n"), pFilePath, GetLastError());
|
||||
return E_KO;
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the file has at least one Signer.
|
||||
returnStatus = CryptMsgGetParam(hCryptMsg, CMSG_SIGNER_COUNT_PARAM, 0, &dwCountSigners, &dwcbSz);
|
||||
if (!returnStatus) {
|
||||
_tprintf_or_not(TEXT("[!] Couldn't get number of signers of file \"%s\" (CryptMsgGetParam(CMSG_SIGNER_COUNT_PARAM) failed: 0x%08lx)\n"), pFilePath, GetLastError());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (dwCountSigners == 0) {
|
||||
_tprintf_or_not(TEXT("[-] \"%s\" file is not digitally signed by at least one signer\n"), pFilePath);
|
||||
CryptMsgClose(hCryptMsg);
|
||||
hCryptMsg = NULL;
|
||||
CertCloseStore(hCertStore, 0);
|
||||
hCertStore = NULL;
|
||||
return E_NOT_SIGNED;
|
||||
}
|
||||
|
||||
// Get Signer name of each certificates and concat to Signers string.
|
||||
for (DWORD index = 0; index < dwCountSigners; index++) {
|
||||
// index = 0;
|
||||
dwcbSz = 0;
|
||||
if (pSignerInfo) {
|
||||
free(pSignerInfo);
|
||||
pSignerInfo = NULL;
|
||||
}
|
||||
if (tmpSignerName) {
|
||||
free(tmpSignerName);
|
||||
tmpSignerName = NULL;
|
||||
}
|
||||
if (pCertContext) {
|
||||
CertFreeCertificateContext(pCertContext);
|
||||
pCertContext = NULL;
|
||||
}
|
||||
|
||||
// Retrieve the CMSG_SIGNER_INFO_PARAM that contains the information to build CERT_INFO (Issuer and SerialNumber).
|
||||
// First call CryptMsgGetParam to retrieve the size neeeded for the buffer.
|
||||
returnStatus = CryptMsgGetParam(hCryptMsg, CMSG_SIGNER_INFO_PARAM, index, NULL, &dwcbSz);
|
||||
if (!returnStatus || !dwcbSz) {
|
||||
_tprintf_or_not(TEXT("[!] Couldn't get signer information of certificate of file \"%s\" (CryptMsgGetParam(CMSG_SIGNER_INFO_PARAM) for size failed: 0x%08lx)\n"), pFilePath, GetLastError());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Allocate the size needed by CryptMsgGetParam to retrieve CMSG_SIGNER_INFO_PARAM.
|
||||
pSignerInfo = (PCMSG_SIGNER_INFO)calloc(dwcbSz, sizeof(BYTE));
|
||||
if (!pSignerInfo) {
|
||||
_putts_or_not(TEXT("[!] Couldn't allocate memory for PCMSG_SIGNER_INFO"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Retrieve the CMSG_SIGNER_INFO_PARAM of the certificate and validate the return.
|
||||
dwcbSzPrevious = dwcbSz;
|
||||
returnStatus = CryptMsgGetParam(hCryptMsg, CMSG_SIGNER_INFO_PARAM, index, pSignerInfo, &dwcbSz);
|
||||
if (!returnStatus || (dwcbSzPrevious != dwcbSz)) {
|
||||
_tprintf_or_not(TEXT("[!] Couldn't get signer information of certificate of file \"%s\" (CryptMsgGetParam(CMSG_SIGNER_INFO_PARAM) failed: 0x%08lx)\n"), pFilePath, GetLastError());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Build CERT_INFO for certificate lookup using CertFindCertificateInStore.
|
||||
memset(&certificateInfo, 0, sizeof(CERT_INFO));
|
||||
certificateInfo.Issuer = pSignerInfo->Issuer;
|
||||
certificateInfo.SerialNumber = pSignerInfo->SerialNumber;
|
||||
|
||||
// Certificate lookup matching the Issuer and SerialNumber in hCertStore.
|
||||
pCertContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_CERT, &certificateInfo, NULL);
|
||||
if (!pCertContext) {
|
||||
_tprintf_or_not(TEXT("[!] Couldn't find certificate of file \"%s\" in store (CertFindCertificateInStore failed: 0x%08lx)\n"), pFilePath, GetLastError());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Retrieves the subject name. First call is done to determine the subject name size.
|
||||
dwcbSz = CertNameToStr(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &pCertContext->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, NULL, 0);
|
||||
tmpSignerName = calloc(dwcbSz, sizeof(TCHAR));
|
||||
if (!tmpSignerName) {
|
||||
_putts_or_not(TEXT("[!] Couldn't allocate memory for decoded certificate Subject name."));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
CertNameToStr(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &pCertContext->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, tmpSignerName, dwcbSz);
|
||||
if (!tmpSignerName) {
|
||||
_tprintf_or_not(TEXT("[!] Couldn't retrieve decoded Subject name of certificate of file \"%s\" (CertNameToStr failed: 0x%08lx)\n"), pFilePath, GetLastError());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Concat the subject to the already found ones, if any.
|
||||
if (pSigners) {
|
||||
sztmpSignerHolder = _tcsclen(pSigners) + _tcsclen(signerSeperator) + _tcsclen(tmpSignerName) + 1;
|
||||
tmpSignerHolder = (TCHAR*)calloc(sztmpSignerHolder, sizeof(TCHAR));
|
||||
if (!tmpSignerHolder) {
|
||||
_putts_or_not(TEXT("[!] Couldn't allocate memory for concatenated signers"));
|
||||
goto cleanup;
|
||||
}
|
||||
_tcscat_s(tmpSignerHolder, sztmpSignerHolder, pSigners);
|
||||
_tcscat_s(tmpSignerHolder, sztmpSignerHolder, signerSeperator);
|
||||
_tcscat_s(tmpSignerHolder, sztmpSignerHolder, tmpSignerName);
|
||||
free(pSigners);
|
||||
pSigners = tmpSignerHolder;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
sztmpSignerHolder = _tcsclen(tmpSignerName) + 1;
|
||||
pSigners = (TCHAR*)calloc(sztmpSignerHolder, sizeof(TCHAR));
|
||||
if (!pSigners) {
|
||||
_putts_or_not(TEXT("[!] Couldn't allocate memory for first signer"));
|
||||
goto cleanup;
|
||||
}
|
||||
_tcscpy_s(pSigners, sztmpSignerHolder, tmpSignerName);
|
||||
}
|
||||
}
|
||||
|
||||
CertFreeCertificateContext(pCertContext);
|
||||
pCertContext = NULL;
|
||||
CryptMsgClose(hCryptMsg);
|
||||
hCryptMsg = NULL;
|
||||
CertCloseStore(hCertStore, 0);
|
||||
hCertStore = NULL;
|
||||
free(pSignerInfo);
|
||||
pSignerInfo = NULL;
|
||||
free(tmpSignerName);
|
||||
tmpSignerName = NULL;
|
||||
|
||||
if (!outSigners || (*szOutSigners < sztmpSignerHolder)) {
|
||||
*szOutSigners = sztmpSignerHolder;
|
||||
free(pSigners);
|
||||
return E_INSUFFICIENT_BUFFER;
|
||||
}
|
||||
else {
|
||||
*szOutSigners = sztmpSignerHolder;
|
||||
_tcscat_s(outSigners, sztmpSignerHolder, pSigners);
|
||||
free(pSigners);
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
if (pCertContext) {
|
||||
CertFreeCertificateContext(pCertContext);
|
||||
pCertContext = NULL;
|
||||
}
|
||||
|
||||
if (hCryptMsg) {
|
||||
CryptMsgClose(hCryptMsg);
|
||||
hCryptMsg = NULL;
|
||||
}
|
||||
|
||||
if (hCertStore) {
|
||||
CertCloseStore(hCertStore, 0);
|
||||
hCertStore = NULL;
|
||||
}
|
||||
|
||||
if (pSignerInfo) {
|
||||
free(pSignerInfo);
|
||||
pSignerInfo = NULL;
|
||||
}
|
||||
|
||||
if (tmpSignerName) {
|
||||
free(tmpSignerName);
|
||||
tmpSignerName = NULL;
|
||||
}
|
||||
|
||||
return E_KO;
|
||||
}
|
||||
Reference in New Issue
Block a user