2024-02-14 18:17:04 +00:00
|
|
|
#include <windows.h>
|
|
|
|
#include <wincrypt.h>
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include "hook/table.h"
|
|
|
|
|
|
|
|
#include "platform/cert.h"
|
|
|
|
#include "hook/procaddr.h"
|
|
|
|
|
|
|
|
#include "util/dprintf.h"
|
|
|
|
#include "util/str.h"
|
|
|
|
|
|
|
|
static CRITICAL_SECTION cert_lock;
|
|
|
|
static wchar_t path[MAX_PATH];
|
|
|
|
|
|
|
|
PCCERT_CONTEXT WINAPI hook_CertFindCertificateInStore(
|
|
|
|
HCERTSTORE hCertStore,
|
|
|
|
DWORD dwCertEncodingType,
|
|
|
|
DWORD dwFindFlags,
|
|
|
|
DWORD dwFindType,
|
|
|
|
const void *pvFindPara,
|
|
|
|
PCCERT_CONTEXT pPrevCertContext
|
|
|
|
);
|
|
|
|
|
2024-02-18 01:15:31 +00:00
|
|
|
HCERTSTORE WINAPI hook_CertOpenStore(
|
|
|
|
LPCSTR lpszStoreProvider,
|
|
|
|
DWORD dwEncodingType,
|
|
|
|
HCRYPTPROV_LEGACY hCryptProv,
|
|
|
|
DWORD dwFlags,
|
|
|
|
const void *pvPara
|
|
|
|
);
|
|
|
|
|
2024-02-14 18:17:04 +00:00
|
|
|
PCCERT_CONTEXT (WINAPI *next_CertFindCertificateInStore)(
|
|
|
|
HCERTSTORE hCertStore,
|
|
|
|
DWORD dwCertEncodingType,
|
|
|
|
DWORD dwFindFlags,
|
|
|
|
DWORD dwFindType,
|
|
|
|
const void *pvFindPara,
|
|
|
|
PCCERT_CONTEXT pPrevCertContext
|
|
|
|
);
|
|
|
|
|
2024-02-18 01:15:31 +00:00
|
|
|
HCERTSTORE (WINAPI *next_CertOpenStore)(
|
|
|
|
LPCSTR lpszStoreProvider,
|
|
|
|
DWORD dwEncodingType,
|
|
|
|
HCRYPTPROV_LEGACY hCryptProv,
|
|
|
|
DWORD dwFlags,
|
|
|
|
const void *pvPara
|
|
|
|
);
|
|
|
|
|
2024-02-14 18:17:04 +00:00
|
|
|
static const struct hook_symbol cert_syms[] = {
|
|
|
|
{
|
|
|
|
.name = "CertFindCertificateInStore",
|
|
|
|
.patch = hook_CertFindCertificateInStore,
|
|
|
|
.link = (void **) &next_CertFindCertificateInStore,
|
|
|
|
},
|
2024-02-18 01:15:31 +00:00
|
|
|
{
|
|
|
|
.name = "CertOpenStore",
|
|
|
|
.patch = hook_CertOpenStore,
|
|
|
|
.link = (void **) &next_CertOpenStore,
|
|
|
|
},
|
2024-02-14 18:17:04 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
HRESULT cert_hook_init(const struct cert_config *cfg)
|
|
|
|
{
|
|
|
|
assert(cfg != NULL);
|
|
|
|
|
|
|
|
if (!cfg->enable) {
|
|
|
|
return S_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
dprintf("Cert hook init\n");
|
|
|
|
wcscpy_s(path, MAX_PATH, cfg->path);
|
|
|
|
InitializeCriticalSection(&cert_lock);
|
|
|
|
cert_hook_insert_hooks(NULL);
|
|
|
|
|
|
|
|
proc_addr_table_push(
|
|
|
|
NULL,
|
|
|
|
"crypt32.dll",
|
|
|
|
(struct hook_symbol *) cert_syms,
|
|
|
|
_countof(cert_syms));
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void cert_hook_insert_hooks(HMODULE target)
|
|
|
|
{
|
|
|
|
hook_table_apply(
|
|
|
|
target,
|
|
|
|
"crypt32.dll",
|
|
|
|
cert_syms,
|
|
|
|
_countof(cert_syms));
|
|
|
|
}
|
|
|
|
|
|
|
|
PCCERT_CONTEXT WINAPI hook_CertFindCertificateInStore(
|
|
|
|
HCERTSTORE hCertStore,
|
|
|
|
DWORD dwCertEncodingType,
|
|
|
|
DWORD dwFindFlags,
|
|
|
|
DWORD dwFindType,
|
|
|
|
const void *pvFindPara,
|
|
|
|
PCCERT_CONTEXT pPrevCertContext
|
|
|
|
)
|
|
|
|
{
|
2024-02-17 09:24:36 +00:00
|
|
|
char bfr[4096] = {0};
|
|
|
|
uint8_t bfr_decode[4096] = {0};
|
|
|
|
DWORD pcbBinary = 4096;
|
2024-02-14 19:26:11 +00:00
|
|
|
wchar_t cert_path[MAX_PATH] = {0};
|
|
|
|
DWORD num_read = 0;
|
2024-02-17 09:24:36 +00:00
|
|
|
PCCERT_CONTEXT cert_ctx = NULL;
|
2024-02-14 18:17:04 +00:00
|
|
|
|
2024-02-14 19:26:11 +00:00
|
|
|
if (dwFindType == CERT_FIND_ISSUER_STR || dwFindType == CERT_FIND_SUBJECT_STR) {
|
|
|
|
wcscat_s(cert_path, _countof(cert_path), path);
|
|
|
|
wcscat_s(cert_path, _countof(cert_path), L"/");
|
|
|
|
wcscat_s(cert_path, _countof(cert_path), (wchar_t *)pvFindPara); // use the search string as a name
|
2024-02-17 09:24:36 +00:00
|
|
|
wcscat_s(cert_path, _countof(cert_path), L".cer");
|
2024-02-14 18:17:04 +00:00
|
|
|
|
2024-02-18 01:15:31 +00:00
|
|
|
//dprintf("Cert: Look for override cert at %S\n", cert_path);
|
2024-02-14 19:26:11 +00:00
|
|
|
|
2024-02-17 09:24:36 +00:00
|
|
|
HANDLE f = CreateFileW((LPCWSTR)cert_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
2024-02-14 19:26:11 +00:00
|
|
|
|
|
|
|
if (f != INVALID_HANDLE_VALUE) {
|
2024-02-18 01:15:31 +00:00
|
|
|
//dprintf("Cert: Read file %S\n", cert_path);
|
2024-02-14 19:26:11 +00:00
|
|
|
ReadFile(f, bfr, sizeof(bfr), &num_read, NULL);
|
|
|
|
CloseHandle(f);
|
2024-02-14 18:17:04 +00:00
|
|
|
|
2024-02-14 19:26:11 +00:00
|
|
|
if (bfr[0]) {
|
2024-02-17 09:24:36 +00:00
|
|
|
dprintf("Cert: Override %S\n", cert_path);
|
|
|
|
if (CryptStringToBinary(bfr, 0, CRYPT_STRING_BASE64X509CRLHEADER, bfr_decode, &pcbBinary, NULL, NULL)) {
|
|
|
|
cert_ctx = CertCreateCertificateContext(X509_ASN_ENCODING, bfr_decode, num_read);
|
|
|
|
if (cert_ctx != NULL) {
|
|
|
|
return cert_ctx;
|
|
|
|
}
|
|
|
|
dprintf("Cert: Override FAIL %08X\n", (int)GetLastError());
|
|
|
|
}
|
|
|
|
dprintf("Cert: CryptStringToBinary FAIL %08X\n", (int)GetLastError());
|
2024-02-14 19:26:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return next_CertFindCertificateInStore(
|
|
|
|
hCertStore,
|
|
|
|
dwCertEncodingType,
|
|
|
|
dwFindFlags,
|
|
|
|
dwFindType,
|
|
|
|
pvFindPara,
|
|
|
|
pPrevCertContext
|
|
|
|
);
|
2024-02-14 18:17:04 +00:00
|
|
|
}
|
2024-02-18 01:15:31 +00:00
|
|
|
|
|
|
|
HCERTSTORE WINAPI hook_CertOpenStore(
|
|
|
|
LPCSTR lpszStoreProvider,
|
|
|
|
DWORD dwEncodingType,
|
|
|
|
HCRYPTPROV_LEGACY hCryptProv,
|
|
|
|
DWORD dwFlags,
|
|
|
|
const void *pvPara)
|
|
|
|
{
|
2024-02-21 08:43:44 +00:00
|
|
|
BYTE bfr[4096] = {0};
|
|
|
|
DWORD num_read = 0;
|
|
|
|
/*if (lpszStoreProvider <= CERT_STORE_PROV_PKCS12) {
|
2024-02-18 01:15:31 +00:00
|
|
|
dprintf("Cert: Open store for %p -> %S (%04X)\n", lpszStoreProvider, (wchar_t *)pvPara, (int)dwFlags);
|
|
|
|
} else {
|
|
|
|
dprintf("Cert: Open store for %s\n", lpszStoreProvider);
|
|
|
|
}
|
|
|
|
|
|
|
|
HCERTSTORE ret = next_CertOpenStore(lpszStoreProvider, dwEncodingType, hCryptProv, dwFlags, pvPara);
|
|
|
|
if (ret == NULL) {
|
|
|
|
int err = GetLastError();
|
|
|
|
if (err == 0x00000005) {
|
|
|
|
ret = next_CertOpenStore(lpszStoreProvider, dwEncodingType, hCryptProv, 0x28000, pvPara); // This works without admin perms
|
|
|
|
if (ret != NULL) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dprintf("Cert: Failed to open store %08X\n", (int)err);
|
|
|
|
}
|
2024-02-21 08:43:44 +00:00
|
|
|
return ret;*/
|
|
|
|
HANDLE f = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
|
|
|
|
if (f != INVALID_HANDLE_VALUE) {
|
|
|
|
dprintf("Cert: Read file %S\n", path);
|
|
|
|
ReadFile(f, bfr, sizeof(bfr), &num_read, NULL);
|
|
|
|
CloseHandle(f);
|
|
|
|
|
|
|
|
if (bfr[0]) {
|
|
|
|
CRYPT_INTEGER_BLOB blob = {
|
|
|
|
.pbData = bfr,
|
|
|
|
.cbData = num_read
|
|
|
|
};
|
|
|
|
dprintf("Cert: detour open of %S to %S\n", (wchar_t *)pvPara, path);
|
|
|
|
HCERTSTORE ret = next_CertOpenStore(CERT_STORE_PROV_PKCS12, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, hCryptProv, dwFlags, &blob);
|
|
|
|
dprintf("Cert: Open %p\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return next_CertOpenStore(lpszStoreProvider, dwEncodingType, hCryptProv, dwFlags, pvPara);
|
|
|
|
|
2024-02-18 01:15:31 +00:00
|
|
|
}
|