[
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2016, @aim4r\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n"
  },
  {
    "path": "README.md",
    "content": "\nVolDiff: Malware Memory Footprint Analysis\n==========================================\n\nVolDiff is a Python script that leverages the [Volatility](https://github.com/volatilityfoundation/volatility) framework to identify malware threats on Windows 7 memory images.\n\nVolDiff can be used to run a collection of Volatility plugins against memory images captured before and after malware execution. It creates a report that highlights system changes based on memory (RAM) analysis.\n\nVolDiff can also be used against a single Windows memory image to automate Volatility plugin execution, and hunt for malicious patterns.\n\nInstallation and use directions\n--------------------------------\nPlease refer to the VolDiff [home wiki](https://github.com/aim4r/VolDiff/wiki) for details. VolDiff has also been included in the [REMnux](https://remnux.org/) Linux malware analysis toolkit.\n\nSample report\n--------------\nSee [this wiki page](https://github.com/aim4r/VolDiff/wiki/Memory-Analysis-of-DarkComet-using-VolDiff) for a sample VolDiff analysis of a system infected with the [DarkComet](https://en.wikipedia.org/wiki/DarkComet) RAT, or [this blog post](http://malwology.com/2015/06/25/remnux-v6-for-malware-analysis-part-1-voldiff/?utm_content=buffere3751&utm_medium=social&utm_source=twitter.com&utm_campaign=buffer) for example VolDiff use againt a malware Trojan. \n\n\nInspiration\n------------\nThis work was initially inspired by Andrew Case ([@attrc](https://twitter.com/attrc)) talk on [analyzing the sophisticated Careto malware sample with memory forensics](http://2014.video.sector.ca/video/110388398 \"analyzing the sophisticated Careto malware sample with memory forensics\"). Kudos to [@attrc](https://twitter.com/attrc) and all the [Volatility development team](https://github.com/aim4r/VolDiff/wiki#credits) for creating and maintaining the greatest memory forensic framework out there!\n"
  },
  {
    "path": "VolDiff.py",
    "content": "#!/usr/bin/env python\n# VolDiff malware analysis script by @aim4r\n__author__ = 'aim4r'\n\n# IMPORTS ================================================================\nimport os\nimport sys\nimport time\nimport datetime\nimport difflib\nimport shutil\nimport re\nimport string\nimport simplejson\nimport urllib\nimport urllib2\nimport hashlib\nfrom subprocess import Popen\n\n# VARIABLES ================================================================\nversion = \"2.1.5\"\npath_to_volatility = \"vol.py\"\nmax_concurrent_subprocesses = 3\ndiff_output_threshold = 100\nma_output_threshold = 60\nvt_api_key = \"473db868008cddb184e609ace3ca05de8e51f806e57eba74005aba2efa4a1e6e\"  # the rate limit os 4 requests per IP per minute\ndevnull = open(os.devnull, 'w')\n\n# volatility plugins to run:\nplugins_to_run = [\"handles\", \"psxview\", \"netscan\", \"iehistory\", \"getsids\", \"pslist\", \"psscan\", \"cmdline\", \"consoles\",\n                  \"dlllist\", \"filescan\", \"shimcache\", \"shellbags\", \"sessions\", \"messagehooks\", \"eventhooks\", \"svcscan\",\n                  \"envars\", \"mutantscan\", \"symlinkscan\", \"atoms\", \"atomscan\", \"drivermodule\", \"mftparser\", \"driverscan\",\n                  \"devicetree\", \"modules\", \"modscan\", \"unloadedmodules\", \"callbacks\", \"ldrmodules\", \"privs\", \"hashdump\",\n                  \"threads\", \"malfind\", \"procdump\", \"idt\", \"gdt\", \"driverirp\", \"deskscan\", \"timers\", \"gditimers\",\n                  \"ssdt\"]\n\n# volatility plugins to report / only used when a baseline memory image is provided:\nplugins_to_report = [\"pslist\", \"psscan\", \"psxview\", \"netscan\", \"iehistory\", \"malfind\", \"sessions\", \"privs\",\n                     \"messagehooks\", \"eventhooks\", \"envars\", \"shimcache\", \"shellbags\", \"cmdline\", \"consoles\",\n                     \"hashdump\", \"drivermodule\", \"driverscan\", \"driverirp\", \"modules\", \"modscan\", \"unloadedmodules\",\n                     \"devicetree\", \"callbacks\", \"threads\", \"mutantscan\", \"symlinkscan\", \"ssdt\"]\n\n# REGEX EXPRESSIONS ================================================================\n# regex expressions used to analyse imports\nransomware_imports = \"CreateDesktop\"\nkeylogger_imports = \"GetKeyboardState|GetKeyState\"\npassword_extract_imports = \"SamLookupDomainInSamServer|NlpGetPrimaryCredential|LsaEnumerateLogonSessions|SamOpenDomain|SamOpenUser|SamGetPrivateData|SamConnect|SamRidToSid|PowerCreateRequest|SeDebugPrivilege|SystemFunction006|SystemFunction040\"\nclipboard_imports = \"OpenClipboard\"\nprocess_injection_imports = \"VirtualAllocEx|AllocateVirtualMemory|VirtualProtectEx|ProtectVirtualMemory|CreateProcess|LoadLibrary|LdrLoadDll|CreateToolhelp32Snapshot|QuerySystemInformation|EnumProcesses|WriteProcessMemory|WriteVirtualMemory|CreateRemoteThread|ResumeThread|SetThreadContext|SetContextThread|QueueUserAPC|QueueApcThread|WinExec|FindResource\"\nuac_bypass_imports = \"AllocateAndInitializeSid|EqualSid|RtlQueryElevationFlags|GetTokenInformation|GetSidSubAuthority|GetSidSubAuthorityCount\"\nanti_debug_imports = \"SetUnhandledExceptionFilter|CheckRemoteDebugger|DebugActiveProcess|FindWindow|GetLastError|GetWindowThreadProcessId|IsDebugged|IsDebuggerPresent|NtCreateThreadEx|NtGlobalFlags|NtSetInformationThread|OutputDebugString|pbIsPresent|Process32First|Process32Next|TerminateProcess|ThreadHideFromDebugger|UnhandledExceptionFilter|ZwQueryInformation|Sleep|GetProcessHeap\"\nweb_imports = \"InternetReadFile|recvfrom|WSARecv|DeleteUrlCacheEntry|CreateUrlCacheEntry|URLDownloadToFile|WSASocket|WSASend|WSARecv|WS2_32|InternetOpen|HTTPOpen|HTTPSend|InternetWrite|InternetConnect\"\nlisten_imports = \"RasPortListen|RpcServerListen|RpcMgmtWaitServerListen|RpcMgmtIsServerListening\"\nservice_imports = \"OpenService|CreateService|StartService|NdrClientCall2|NtLoadDriver\"\nshutdown_imports = \"ExitWindows\"\nregistry_imports = \"RegOpenKey|RegQueryValue|ZwSetValueKey\"\nfile_imports = \"CreateFile|WriteFile\"\natoms_imports = \"GlobalAddAtom\"\nlocaltime_imports = \"GetLocalTime|GetSystemTime\"\ndriver_imports = \"DeviceIoControl\"\nusername_imports = \"GetUserName|LookupAccountNameLocal\"\nmachine_version_imports = \"GetVersion\"\nstartup_imports = \"GetStartupInfo\"\ndiskspace_imports = \"GetDiskFreeSpace\"\nsysinfo_imports = \"CreateToolhelp32Snapshot|NtSetSystemInformation|NtQuerySystemInformation|GetCurrentProcess|GetModuleFileName\"\n\n# regex expressions used to analyse strings (from process executables)\nweb_regex_str = \"cookie|download|proxy|responsetext|socket|useragent|user-agent|urlmon|user_agent|WebClient|winhttp|http\"\nantivirus_regex_str = \"antivir|anvir|avast|avcons|avgctrl|avginternet|avira|bitdefender|checkpoint|comodo|F-Secure|firewall|kaspersky|mcafee|norton|norman|safeweb|sophos|symantec|windefend\"\nvirtualisation_regex_str = \"000569|001C14|080027|citrix|parallels|proxmox|qemu|SbieDll|Vbox|VMXh|virm|virtualbox|virtualpc|vmsrvc|vpc|winice|vmware|xen\"\nsandbox_regex_str = \"anubis|capturebat|cuckoo|deepfreeze|debug|fiddler|fireeye|inctrl5|installwatch|installspy|netmon|noriben|nwinvestigatorpe|perl|processhacker|python|regshot|sandb|schmidti|sleep|snort|systracer|uninstalltool|tcpdump|trackwinstall|whatchanged|wireshark\"\nsysinternals_regex_str = \"filemon|sysinternal|procdump|procexp|procmon|psexec|regmon|sysmon\"\nshell_regex_str = \"shellexecute|shell32\"\nkeylogger_regex_str = \"backspace|klog|keylog|shift\"\nfilepath_regex_str = 'C:\\\\\\(?:[^\\\\\\/:*?\"<>|\\r\\n]+\\\\\\)*[^\\\\\\/:*?\"<>|\\r\\n]*'\npassword_regex_str = \"brute|credential|creds|mimikatz|passwd|password|pwd|sniff|stdapi|WCEServicePipe|wce_krbtkts\"\npowershell_regex_str = \"powerview|powershell\"\nsql_regex_str = \"SELECT|INSERT|sqlite|MySQL\"\ninfogathering_regex_str = \"driverquery|gethost|wmic|GetVolumeInformation|systeminfo|tasklist|reg.exe\"\ntool_regex_str = \"cain|clearev|ipscan|netsh|rundll32|timestomp|torrent\"\nbanking_regex_str = \"banc|banco|bank|Barclays|hsbc|jpmorgan|lloyds|natwest|nwolb|paypal|rbc.com|santander\"\nsocialsites_regex_str = \"facebook|instagram|linkedin|pastebin|twitter|yahoo|youtube\"\nexec_regex_str = \".*\\.bat|.*\\.cmd|.*\\.class|.*\\.exe|.*\\.jar|.*\\.js|.*\\.jse|.*\\.SCR|.*\\.VBE|.*\\.vbs\"\ncrypto_regex_str = \"bitlocker|bitcoin|CIPHER|crypt|locker|logkey|publickey|ransom|truecrypt|veracrypt\"\nrat_regex_str = \"backdoor|botnet|login|malware|rootkit|screenshot|Trojan|Vnc|VncStart\"\nbrowser_regex_str = \"chrome|firefox|mozilla|opera\"\nother_regex_str = \"admin|currentversion|hosts|registry|smtp|UserInit|.*\\.pdb\"\n\n# regex expressions used to extract ips, domains and email addresses\nips_regex = r\"(?!\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.0\\b)\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b\"\ndomains_regex_http = 'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+'\ndomains_regex_ftp = 'ftp[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+'\ndomains_regex_file = 'file[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+'\nemails_regex = r\"\\b[a-zA-Z0-9.-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z0-9.-]+\\b\"\n\n# regex expressions used to analyse registry handles\nregistry_infogathering_regex = \"SOFTWARE\\\\\\MICROSOFT|Parameters|SOFTWARE\\\\\\POLICIES\"\nregistry_proxy_settings_regex = \"INTERNET SETTINGS\"\nregistry_locale_regex = \"NLS\\\\\\LOCALE\"\nregistry_hostname_regex = \"COMPUTERNAME\"\nregistry_installed_programs_regex = \"CurrentVersion\\\\\\App Paths|CurrentVersion\\\\\\Uninstall|Installed Components\"\nregistry_remote_control_regex = \"Terminal Server|Realvnc\"\nregistry_firewall_regex = \"firewall\"\nregistry_services_regex = \"CurrentControlSet\\\\\\services\"\nregistry_network_regex = \"NetworkList|Tcpip\"\nregistry_autorun_regex = \"CurrentVersion\\\\\\Explorer|CurrentVersion\\\\\\Run|CurrentVersion\\\\\\Windows|Current Version\\\\\\Policies\\\\\\Explorer|CurrentVersion\\\\\\Winlogon|Shell Extensions\"\nregistry_command_processor_regex = \"Command Processor\"\nregistry_crypto_regex = \"CRYPTOGRAPHY\"\nregistry_tracing_regex = \"TRACING\"\nregistry_file_associations_regex = \"SYSTEMFILEASSOCIATIONS\"\nregistry_ie_security_regex = \"INTERNET EXPLORER\\\\\\SECURITY\"\nregistry_security_center_regex = \"Security Center\"\n\n# suspicious processes and dlls\nhacker_process_regex = \"at.exe|chtask.exe|clearev|ftp.exe|net.exe|nbtstat.exe|net1.exe|ping.exe|powershell|procdump.exe|psexec|quser.exe|reg.exe|regsvr32.exe|schtasks|systeminfo.exe|taskkill.exe|timestomp|winrm|wmic|xcopy.exe\"\nhacker_dll_regex = \"mimilib.dll|sekurlsa.dll|wceaux.dll|iamdll.dll|VMCheck.dll\"\n# suspicious process names\nl33t_process_name = \"snss|crss|cssrs|csrsss|lass|isass|lssass|lsasss|scvh|svch0st|svhos|svchst|svchosts|lsn|g0n|l0g|nvcpl|rundii|wauclt|spscv|spppsvc|sppscv|sppcsv|taskchost|tskhost|msorsv|corsw|arch1ndex|wmipvr|wmiprse|runddl|crss.exe\"\n# \"usual\" process names\nusual_processes = \"sppsvc.exe|audiodg.exe|mscorsvw.exe|SearchIndexer|TPAutoConnSvc|TPAutoConnect|taskhost.exe|smss.exe|wininit.exe|services.exe|lsass.exe|svchost.exe|lsm.exe|explorer.exe|winlogon|conhost.exe|dllhost.exe|spoolsv.exe|vmtoolsd.exe|WmiPrvSE.exe|msdtc.exe|TrustedInstall|SearchFilterHo|csrss.exe|System|ipconfig.exe|cmd.exe|dwm.exe|mobsync.exe|DumpIt.exe|VMwareTray.exe|wuauclt.exe|LogonUI.exe|SearchProtocol|vssvc.exe|WMIADAP.exe\"\n# suspicious filepaths\nsusp_filepath = \"\\\\\\ProgramData|\\\\\\Recycle|\\\\\\Windows\\\\\\Temp|\\\\\\Users\\\\\\All|\\\\\\Users\\\\\\Default|\\\\\\Users\\\\\\Public|\\\\\\ProgramData|AppData\"\ntemp_filepath = \"\\\\\\TMP|\\\\\\TEMP|\\\\\\AppData\"\n# usual timers\nusual_timers = \"ataport.SYS|ntoskrnl.exe|NETIO.SYS|storport.sys|afd.sys|cng.sys|dfsc.sys|discache.sys|HTTP.sys|luafv.sys|ndis.sys|Ntfs.sys|rdbss.sys|rdyboost.sys|spsys.sys|srvnet.sys|srv.sys|tcpip.sys|usbccgp.sys|netbt.sys|volsnap.sys|dxgkrnl.sys|bowser.sys|fltmgr.sys\"\n# usual gditimers\nusual_gditimers = \"dllhost.exe|explorer.exe|csrss.exe\"\n# usual ssdt\nusual_ssdt = \"(ntos|win32k)\"\n# usual atoms and atomscan dlls\nusual_atoms_dlls = \"system32\\\\\\wls0wndh.dll|System32\\\\\\pnidui.dll|system32\\\\\\stobject.dll|vmusr\\\\\\\\vmtray.dll|system32\\\\\\EXPLORERFRAME.dll|system32\\\\\\uxtheme.dll|system32\\\\\\MsftEdit.dll|system32\\\\\\SndVolSSO.DLL|system32\\\\\\\\fxsst.dll|system32\\\\\\WINMM.dll\"\n# extensions of interest\nsusp_extensions_regex = \"\\.job$|\\.pdb$|\\.xls$|\\.doc$|\\.pdf$|\\.tmp$|\\.temp$|\\.rar$|\\.zip$|\\.bat|\\.cmd$|\\.class$|\\.jar$|\\.jse$|\\.SCR$|\\.VBE$|\\.vbs$\"\n\n# DICTIONARIES/LISTS USED FOR PROCESS CHECKS ================================================================\n# list of \"unique\" processes\nuniq_processes = [\"services.exe\", \"System\", \"wininit.exe\", \"smss.exe\", \"lsass.exe\", \"lsm.exe\", \"explorer.exe\"]\n# expected execution path for some processes\nprocess_execpath = {'smss.exe': \"\\systemroot\\system32\\smss.exe\",\n                    \"crss.exe\": \"\\windows\\system32\\csrss.exe\",\n                    \"wininit.exe\": \"wininit.exe\",\n                    \"services.exe\": \"\\windows\\system32\\services.exe\",\n                    \"lsass.exe\": \"\\windows\\system32\\lsass.exe\",\n                    \"svchost.exe\": \"\\windows\\system32\\svchost.exe\",\n                    \"lsm.exe\": \"\\windows\\system32\\lsm.exe\",\n                    \"explorer.exe\": \"\\windows\\explorer.exe\",\n                    \"winlogon.exe\": \"winlogon.exe\",\n                    \"sppsvc.exe\": \"\\windows\\system32\\sppsvc.exe\"}\n\n# expected process parent/child relationship\nparent_child = {'services.exe': [\"sppsvc.exe\", \"taskhost.exe\", \"mscorsvw.exe\", \"TPAutoConnSvc\", \"SearchIndexer\", \"svchost.exe\", \"taskhost.exe\", \"spoolsv.exe\"],\n                'System': [\"smss.exe\"], 'csrss.exe': [\"conhost.exe\"],\n                'svchost.exe': [\"WmiPrvSE.exe\", \"audiodg.exe\"],\n                'wininit.exe': [\"services.exe\", \"lsass.exe\", \"lsm.exe\"]\n                }\n\n# expected process sessions\nsession0_processes = [\"wininit.exe\", \"services.exe\", \"svchost.exe\", \"lsm.exe\", \"lsass.exe\"]\nsession1_processes = [\"winlogon.exe\"]\n\n# VOLATILITY PROFILES ================================================================\nprofiles = [\"VistaSP0x86\", \"VistaSP0x64\", \"VistaSP1x86\", \"VistaSP1x64\", \"VistaSP2x86\", \"VistaSP2x64\",\n            \"Win2003SP0x86\", \"Win2003SP1x86\", \"Win2003SP1x64\", \"Win2003SP2x86\", \"Win2003SP2x64\",\n            \"Win2008SP1x86\", \"Win2008SP1x64\", \"Win2008SP2x86\", \"Win2008SP2x64\", \"Win2008R2SP0x64\", \"Win2008R2SP1x64\",\n            \"Win2012R2x64\", \"Win2012x64\",\n            \"Win7SP0x86\", \"Win7SP0x64\", \"Win7SP1x86\", \"Win7SP1x64\",\n            \"Win8SP0x86\", \"Win8SP0x64\", \"Win8SP1x86\", \"Win8SP1x64\",\n            \"WinXPSP2x86\", \"WinXPSP1x64\", \"WinXPSP2x64\", \"WinXPSP3x86\"]\n\npreferred_profiles = [\"Win7SP0x86\", \"Win7SP0x64\", \"Win7SP1x86\", \"Win7SP1x64\"]\n\n\n# PRINT VOLDIFF BANNER ================================================================\ndef print_voldiff_banner():\n    print (\"             _    ___ _  __  __ \")\n    print (\" /\\   /\\___ | |  /   (_)/ _|/ _|\")\n    print (\" \\ \\ / / _ \\| | / /\\ / | |_| |_ \")\n    print (\"  \\ V / (_) | |/ /_//| |  _|  _|\")\n    print (\"   \\_/ \\___/|_/___,' |_|_| |_|  \")\n    print (\"\\nVolDiff: Malware Memory Footprint Analysis (v%s)\\n\" % version)\n\n\n# PRINT HELP SECTION ================================================================\ndef print_help():\n    print (\"Usage: ./VolDiff.py [BASELINE_IMAGE] INFECTED_IMAGE PROFILE [OPTIONS]\")\n    print (\"\\nOptions:\")\n    print (\"--help                display this help and exit\")\n    print (\"--version             display version information and exit\")\n    print (\"--dependencies        display information about script dependencies and exit\")\n    print (\"--malware-checks      hunt and report suspicious anomalies (slow, recommended)\")\n    print (\"--output-dir [dir]    custom directory to store analysis results\")\n    print (\"--no-report           do not create a report\")\n    print (\"\\nTested using Volatility 2.5 (vol.py) on Windows 7 images.\")\n    sys.exit()\n\n\n# PRINT VERSION INFORMATION ================================================================\ndef print_version():\n    print (\"This is a free software: you are free to change and redistribute it.\")\n    print (\"There is no warranty, to the extent permitted by law.\")\n    print (\"Written by @aim4r. Report bugs to voldiff[@]gmail.com.\")\n    sys.exit()\n\n\n# PRINT DEPENDENCIES ================================================================\ndef print_dependencies():\n    print (\"Requires volatility 2.5 (vol.py) to be installed.\")\n    sys.exit()\n\n\n# VERIFY PATH TO VOLATILITY EXISTS ================================================================\ndef check_volatility_path(path):\n    if os.path.isfile(path):\n        return True\n    for p in os.environ[\"PATH\"].split(os.pathsep):\n        full_path = os.path.join(p, path)\n        if os.path.exists(full_path):\n            return True\n    return False\n\n\n# VERIFY ENOUGH ARGUMENTS ARE SUPPLIED ================================================================\ndef check_enough_arguments_supplied(n=4):\n    if len(sys.argv) < n:\n        print(\"Not enough arguments supplied. Please use the --help option for help.\")\n        sys.exit()\n\n\n# SET PROFILE AND FIND PATH TO MEMORY IMAGE(S) ================================================================\ndef check_profile(pr):\n    if pr not in profiles:\n        print (\"Please specify a valid Volatility Windows profile for use (such as Win7SP1x64).\")\n        sys.exit()\n    if pr not in preferred_profiles:\n        print(\n            \"WARNING: This script was only tested using Windows 7 profiles. The specified profile (%s) seems different!\" % pr)\n    else:\n        print (\"Profile: %s\" % pr)\n    return\n\n\n# COMPLETION AND CLEANUP FUNCTION ================================================================\ndef script_completion(start_time):\n    if 'report' in globals():\n        report.write(\"\\n\\nEnd of report.\")\n        report.close()\n        open_report(output_dir + \"/VolDiff_Report.txt\")\n    notify_completion(\"VolDiff execution completed.\")\n    shutil.rmtree(output_dir + '/tmpfolder')\n    completion_time = time.time() - start_time\n    a = int(completion_time / 60)\n    b = int(completion_time % 60)\n    if 'devnull' in globals():\n        devnull.close()\n    print(\"\\nVolDiff execution completed in %s minutes and %s seconds.\" % (a, b))\n    sys.exit()\n\n\n# DIFFING RESULTS ================================================================\ndef diff_files(path1, path2, diffpath):\n    with open(path1, \"r\") as file1:\n        with open(path2, \"r\") as file2:\n            diff = difflib.unified_diff(file1.readlines(), file2.readlines())\n            with open(diffpath, 'w+') as file3:\n                print >> file3, ''.join(list(diff))\n                file3.seek(0)\n                lines = file3.readlines()\n                file3.seek(0)\n                for line in lines:\n                    if line.startswith(\"+\") and not line.startswith(\"+++\"):\n                        file3.write(line[1:])\n                file3.truncate()\n    return\n\n\n# REPORT CREATION ================================================================\ndef report_plugin(plugin, header_lines=0, threshold=diff_output_threshold):\n    report.write(\"\\n\\nNew %s entries.\" % plugin)\n    report.write(\"\\n==========================================================================================================================\\n\")\n    if header_lines != 0:\n        with open(output_dir + \"/\" + plugin + \"/infected_\" + plugin + \".txt\") as f:\n            for i in range(header_lines):\n                line = next(f, '').strip()\n                report.write(line + \"\\n\")\n    line_counter = 0\n    with open(output_dir + \"/\" + plugin + \"/diff_\" + plugin + \".txt\") as diff:\n        for line in diff:\n            line_counter += 1\n            if line_counter < threshold:\n                report.write(line)\n            else:\n                report.write(\"\\nWarning: too many new entries to report, output truncated!\\n\")\n                break\n    return\n\n\n# OPENING REPORT ================================================================\ndef open_report(report_path):\n    if os.name == 'posix':\n        p = Popen(['xdg-open', report_path], stdout=devnull, stderr=devnull)\n        p.wait()\n    elif os.name == 'mac':\n        p = Popen(['open', report_path], stdout=devnull, stderr=devnull)\n        p.wait()\n    elif os.name == 'nt':\n        p = Popen(['cmd', '/c', 'start', report_path], stdout=devnull, stderr=devnull)  # cmd /c start [filename]\n        p.wait()\n\n\n# NOTIFYING ABOUT SCRIPT COMPLETION ================================================================\ndef notify_completion(message):\n    if os.name == 'posix':\n        p = Popen(['notify-send', message], stdout=devnull, stderr=devnull)\n        p.wait()\n\n\n# MALWARE ANALYSIS FUNCTIONS ================================================================\ndef open_full_plugin(plugin=\"psscan\", lines_to_ignore=2, state=\"infected\"):\n    if os.path.isfile(output_dir + \"/\" + plugin + \"/\" + state + \"_\" + plugin + \".txt\"):\n        f = open(output_dir + \"/\" + plugin + \"/\" + state + \"_\" + plugin + \".txt\")\n    else:\n        f = open(output_dir + \"/\" + plugin + \"/\" + plugin + \".txt\")\n    for i in xrange(lines_to_ignore):\n        next(f, '')\n    return f\n\n\ndef open_diff_plugin(plugin=\"psscan\", lines_to_ignore=2):\n    if os.path.isfile(output_dir + \"/\" + plugin + \"/diff_\" + plugin + \".txt\"):\n        f = open(output_dir + \"/\" + plugin + \"/diff_\" + plugin + \".txt\")\n    else:\n        f = open(output_dir + \"/\" + plugin + \"/\" + plugin + \".txt\")\n        for i in xrange(lines_to_ignore):\n            next(f, '')\n    return f\n\n\ndef anomaly_search(plugin, regex_to_include, ignorecase='yes', regex_to_exclude='', diff=\"diff\"):\n    match_list = []\n    if diff == \"diff\":\n        f = open_diff_plugin(plugin)\n    else:\n        f = open_full_plugin(plugin)\n    for line in f:\n        if ignorecase == 'yes':\n            if re.search(regex_to_include, line, re.IGNORECASE):\n                if regex_to_exclude == '':\n                    match_list.append(line)\n                elif not re.search(regex_to_exclude, line, re.IGNORECASE):\n                    match_list.append(line)\n        else:\n            if re.search(regex_to_include, line):\n                if regex_to_exclude == '':\n                    match_list.append(line)\n                elif not re.search(regex_to_exclude, line):\n                    match_list.append(line)\n    f.close()\n    return match_list\n\n\ndef anomaly_search_inverted(plugin, regex_to_exclude, ignorecase='yes', regex_to_include=''):\n    match_list = []\n    f = open_diff_plugin(plugin)\n    for line in f:\n        if ignorecase == 'yes':\n            if not re.search(regex_to_exclude, line, re.IGNORECASE):\n                if regex_to_include == '':\n                    match_list.append(line)\n                elif re.search(regex_to_include, line, re.IGNORECASE):\n                    match_list.append(line)\n        else:\n            if not re.search(regex_to_exclude, line):\n                if regex_to_include == '':\n                    match_list.append(line)\n                elif re.search(regex_to_include, line):\n                    match_list.append(line)\n    f.close()\n    return match_list\n\n\ndef report_anomalies(headline, anomaly_list, delim=\"=\", plugin=\"\", header_lines=0, threshold=ma_output_threshold):\n    if len(anomaly_list) != 0:\n        report.write(\"\\n\\n%s\" % headline)\n        if delim == \"=\":\n            report.write(\n                \"\\n==========================================================================================================================\\n\")\n        elif delim == '-':\n            report.write(\n                \"\\n--------------------------------------------------------------------------------------------------------------------------\\n\")\n        if header_lines != 0 and plugin != \"\":\n            if os.path.isfile(output_dir + \"/\" + plugin + \"/infected_\" + plugin + \".txt\"):\n                with open(output_dir + \"/\" + plugin + \"/infected_\" + plugin + \".txt\") as f:\n                    for i in range(header_lines):\n                        line = next(f, '').strip()\n                        report.write(line + \"\\n\")\n            else:\n                with open(output_dir + \"/\" + plugin + \"/\" + plugin + \".txt\") as f:\n                    for i in range(header_lines):\n                        line = next(f, '').strip()\n                        report.write(line + \"\\n\")\n        if len(anomaly_list) > threshold:\n            anomaly_list_to_report = anomaly_list[0:threshold]\n            anomaly_list_to_report.append(\"\\nWarning: too many entries to report, output truncated!\\n\")\n        else:\n            anomaly_list_to_report = anomaly_list\n        for line in anomaly_list_to_report:\n            report.write(line)\n    return\n\n\ndef extract_substrings(input_list, regex):\n    extracted_list = []\n    for entry in input_list:\n        subentries = entry.split(' ')\n        for subentry in subentries:\n            if re.search(regex, subentry, re.IGNORECASE):\n                extracted_list.append(subentry)\n    return extracted_list\n\n\ndef tidy_list(input_list):\n    updatedlist = []\n    for entry in input_list:\n        if not re.search(\"\\\\n\", entry):\n            entry += '\\n'\n        updatedlist.append(entry)\n    updatedlist = sorted(set(updatedlist))\n    return updatedlist\n\n\ndef find_ips_domains_emails(plugin):\n    f = open_diff_plugin(plugin, 0)\n    ips = []\n    ips_to_report = []\n    ips_regex_exclude = r\"127\\.0\\.0\\.1|0\\.0\\.0\\.0\"\n    for line in f:\n        if re.search(ips_regex, line, re.IGNORECASE):\n            ips += re.findall(ips_regex, line, re.IGNORECASE)\n    for ip in ips:\n        if not re.search(ips_regex_exclude, ip, re.IGNORECASE):\n            ips_to_report.append(ip)\n    domains = []\n    f.seek(0)\n    for line in f:\n        if re.search(domains_regex_http, line, re.IGNORECASE):\n            domains += re.findall(domains_regex_http, line, re.IGNORECASE)\n        if re.search(domains_regex_ftp, line, re.IGNORECASE):\n            domains += re.findall(domains_regex_ftp, line, re.IGNORECASE)\n        if re.search(domains_regex_file, line, re.IGNORECASE):\n            domains += re.findall(domains_regex_file, line, re.IGNORECASE)\n    emails = []\n    f.seek(0)\n    for line in f:\n        if re.search(emails_regex, line, re.IGNORECASE):\n            emails += re.findall(emails_regex, line, re.IGNORECASE)\n    ips_domains_emails = ips_to_report + domains + emails\n    ips_domains_emails = tidy_list(ips_domains_emails)\n    f.close()\n    return ips_domains_emails\n\n\ndef get_pids(procname, plugin=\"psscan\"):\n    pids = []\n    if procname == \"\":\n        return pids\n    f = open_full_plugin(plugin, 2)\n    for line in f:\n        if re.search(' ' + procname + ' ', line, re.IGNORECASE):\n            pids.append(re.sub(' +', ' ', line).split(' ')[2])\n    pids = sorted(set(pids))\n    f.close()\n    return pids\n\n\ndef get_associated_process_lines_pids(pids, plugin=\"psscan\"):\n    f = open_full_plugin(plugin, 2)\n    associated_psscan_lines = []\n    for line in f:\n        for pid in pids:\n            if re.sub(' +', ' ', line).split(' ')[2] == str(pid):\n                associated_psscan_lines.append(line)\n    f.close()\n    return associated_psscan_lines\n\n\ndef get_associated_process_lines_ppids(ppids, plugin=\"psscan\"):\n    f = open_full_plugin(plugin, 2)\n    associated_psscan_lines = []\n    for line in f:\n        for ppid in ppids:\n            if re.sub(' +', ' ', line).split(' ')[3] == str(ppid):\n                associated_psscan_lines.append(line)\n    f.close()\n    return associated_psscan_lines\n\n\ndef get_childs_of(pids):\n    f = open_full_plugin(\"psscan\", 2)\n    childs = []\n    for line in f:\n        for pid in pids:\n            ppid = re.sub(' +', ' ', line).split(' ')[3]\n            if ppid == str(pid):\n                childs.append(re.sub(' +', ' ', line).split(' ')[2])\n    childs = sorted(set(childs))\n    f.close()\n    return childs\n\n\ndef get_parent_pids_of(childs):\n    f = open_full_plugin(\"psscan\", 2)\n    parents = []\n    for line in f:\n        for child in childs:\n            if re.sub(' +', ' ', line).split(' ')[2] == child:\n                parents.append(re.sub(' +', ' ', line).split(' ')[3])\n    parents = sorted(set(parents))\n    f.close()\n    return parents\n\n\ndef get_procnames(pids):\n    f = open_full_plugin(\"psscan\", 2)\n    procnames = []\n    for line in f:\n        for pid in pids:\n            if re.sub(' +', ' ', line).split(' ')[2] == pid:\n                procnames.append(re.sub(' +', ' ', line).split(' ')[1])\n    f.close()\n    return procnames\n\n\ndef get_all_pids(exception_regex=''):\n    f = open_full_plugin(\"psscan\", 2)\n    pids = []\n    for line in f:\n        if exception_regex != '' and re.search(exception_regex, line, re.IGNORECASE):\n            continue\n        else:\n            pid = re.sub(' +', ' ', line).split(' ')[2]\n            if pid != \"0\":\n                pids.append(pid)\n    pids = sorted(set(pids))\n    f.close()\n    return pids\n\n\ndef get_diff_pids(exception_regex=''):\n    f = open_diff_plugin(\"psscan\", 2)\n    pids = []\n    for line in f:\n        if exception_regex != '' and re.search(exception_regex, line, re.IGNORECASE):\n            continue\n        else:\n            pid = re.sub(' +', ' ', line).split(' ')[2]\n            if pid != \"0\":\n                pids.append(pid)\n    pids = sorted(set(pids))\n    f.close()\n    return pids\n\n\ndef get_procname(pid, plugin='psscan'):\n    f = open_full_plugin(plugin, 2)\n    procnamee = \"\"\n    for line in f:\n        if re.search(r\"[a-zA-Z\\.]\\s+%s \" % pid, line, re.IGNORECASE):\n            procnamee = (re.sub(' +', ' ', line).split(' ')[1])\n            break\n    procnamee = str(procnamee)\n    f.close()\n    return procnamee\n\n\ndef get_all_procnames(plugin='psscan', exception_regex=''):\n    f = open_full_plugin(plugin, 2)\n    procnames = []\n    for line in f:\n        if exception_regex != '' and re.search(exception_regex, line, re.IGNORECASE):\n            continue\n        else:\n            procnames.append(re.sub(' +', ' ', line).split(' ')[1])\n    procnames = sorted(set(procnames))\n    f.close()\n    return procnames\n\n\ndef get_all_ppids(exception_regex=''):\n    f = open_full_plugin(\"psscan\", 2)\n    ppids = []\n    for line in f:\n        if exception_regex != '' and re.search(exception_regex, line, re.IGNORECASE):\n            continue\n        elif re.sub(' +', ' ', line).split(' ')[2] != \"0\":\n            ppids.append(re.sub(' +', ' ', line).split(' ')[3])\n    ppids = sorted(set(ppids))\n    f.close()\n    return ppids\n\n\ndef get_session(pid):\n    session = \"\"\n    f = open_full_plugin(\"pslist\", 2)\n    for line in f:\n        if re.search(' ' + str(pid) + ' ', line, re.IGNORECASE):\n            session = re.sub(' +', ' ', line).split(' ')[6]\n            break\n    f.close()\n    return session\n\n\ndef get_execpath(pid):\n    execpath = ''\n    procnamep = get_procname(pid)\n    f = open_full_plugin(\"dlllist\", 0)\n    for line in f:\n        if re.search(procnamep + ' pid.*' + str(pid), line, re.IGNORECASE):\n            command_line = next(f, '')\n            execpath = re.sub(\"Command line : \", \"\", command_line)\n            execpath = re.sub(\".:\", \"\", execpath)\n            execpath = re.sub(\" .*\", \"\", execpath)\n            execpath = re.sub(\"\\n\", \"\", execpath)\n    f.close()\n    return execpath\n\n\ndef get_cmdline(pid):\n    cmdline = []\n    procnamec = get_procname(pid)\n    f = open_full_plugin(\"cmdline\", 0)\n    for line in f:\n        if re.search(procnamec + ' pid.* ' + pid, line, re.IGNORECASE):\n            cmdline.append(line)\n            line = next(f, '')\n            cmdline.append(line)\n            break\n    if cmdline:\n        if not re.search(\"Command\", cmdline[1], re.IGNORECASE):\n            cmdline = []\n    f.close()\n    return cmdline\n\n\ndef deadproc_activethreads():\n    f = open_full_plugin(\"psxview\", 2)\n    dead_proc_active_threads = []\n    for line in f:\n        if 'UTC' in str(re.sub(' +', ' ', line).split(' ')[9:]) and re.sub(' +', ' ', line).split(' ')[5] == \"True\":\n            dead_proc_active_threads.append(line)\n    f.close()\n    return dead_proc_active_threads\n\n\ndef get_hosts_contents(memory_image_file):\n    hostscontent = []\n    f = open_full_plugin(\"filescan\", 2)\n    qaddressb = \"\"\n    for line in f:\n        if re.search(\"etc\\\\\\hosts$\", line, re.IGNORECASE):\n            qaddressb = re.sub(' +', ' ', line).split(' ')[0]\n            break\n    if qaddressb != \"\":\n        hostsfolder = tmpfolder + \"hosts/\"\n        if not os.path.isdir(hostsfolder):\n            os.makedirs(hostsfolder)\n        process_var = Popen([path_to_volatility, \"--profile\", profile, \"-f\", memory_image_file, \"dumpfiles\", \"-Q\", qaddressb, \"-D\", hostsfolder], stdout=devnull, stderr=devnull)\n        process_var.wait()\n        dumped_hosts_filename = os.listdir(hostsfolder)\n        if len(dumped_hosts_filename) == 1:\n            with open(hostsfolder + str(dumped_hosts_filename[0]), mode='rb') as hosts:\n                for line in hosts:\n                    if not re.search(\"^#\", line) and re.search(\" \", line):\n                        hostscontent.append(line)\n    hostscontent = sorted(set(hostscontent))\n    f.close()\n    return hostscontent\n\n\ndef filter_new_services():\n    filtered_services = []\n    diff_svcscan = open_diff_plugin(\"svcscan\", 0)\n    baseline_svcscan = open_full_plugin(\"svcscan\", 0, \"baseline\")\n    for line in diff_svcscan:\n        if line not in baseline_svcscan and not re.search(\"Offset:\", line, re.IGNORECASE):\n            filtered_services.append(line)\n        baseline_svcscan.seek(0)\n    filtered_services = set(filtered_services)\n    baseline_svcscan.close()\n    diff_svcscan.close()\n    return filtered_services\n\n\ndef get_associated_services(pid):\n    services = []\n    full_svcscan = open_full_plugin(\"svcscan\", 0)\n    for line in full_svcscan:\n        if re.search(\"Process ID: \" + str(pid) + \"\\n\", line, re.IGNORECASE):\n            services.append(\"\\n\")\n            services.append(line)\n            for i in xrange(5):\n                line = next(full_svcscan, '')\n                services.append(line)\n    full_svcscan.close()\n    return services\n\n\ndef get_malfind_pids():\n    malfind_pids = []\n    f = open_diff_plugin(\"malfind\", 0)\n    for line in f:\n        if re.search(\"Address:\", line):\n            malfind_pids.append(re.sub(' +', ' ', line).split(' ')[3])\n    malfind_pids = sorted(set(malfind_pids))\n    f.close()\n    return malfind_pids\n\n\ndef get_malfind_injections(pid, m=\"dual\"):\n    malfind_injections = []\n    f = open_diff_plugin(\"malfind\", 0)\n    if m == \"dual\":\n        n = 6\n    else:\n        n = 7\n    for line in f:\n        if re.search(\"Pid: \" + str(pid) + \" \", line):\n            malfind_injections.append(\"\\n\")\n            malfind_injections.append(line)\n            for i in xrange(n):\n                line = next(f, '')\n                malfind_injections.append(line)\n    f.close()\n    return malfind_injections\n\n\ndef analyse_registry(pid):\n    rhit = False\n    registry_analysis_matrix = {\"\\nCollects information about system\": registry_infogathering_regex,\n                                \"\\nQueries / modifies proxy settings\": registry_proxy_settings_regex,\n                                \"\\nReads information about supported languages\": registry_locale_regex,\n                                \"\\nIdentifies machine name\": registry_hostname_regex,\n                                \"\\nIdentifies installed programs\": registry_installed_programs_regex,\n                                \"\\nQueries / modifies remote control settings\": registry_remote_control_regex,\n                                \"\\nQueries / modifies firewall settings\": registry_firewall_regex,\n                                \"\\nQueries / modifies service settings\": registry_services_regex,\n                                \"\\nQueries / modifies network settings\": registry_network_regex,\n                                \"\\nHas access to autorun registry keys\": registry_autorun_regex,\n                                \"\\nQueries / modifies the Windows command processor\": registry_command_processor_regex,\n                                \"\\nQueries / modifies encryption seettings\": registry_crypto_regex,\n                                \"\\nQueries / modifies file association settings\": registry_file_associations_regex,\n                                \"\\nQueries / modifies security seettings\": registry_ie_security_regex,\n                                }\n    for reg_key in registry_analysis_matrix:\n        registry = anomaly_search(\"handles\", registry_analysis_matrix[reg_key], \"yes\", \"\", \"diff\")\n        registry_to_report = []\n        for key in registry:\n            if re.search(\" \" + str(pid) + \" \", key, re.IGNORECASE) and re.search(\"Key\", key, re.IGNORECASE):\n                a = re.sub(' +', ' ', key).split(' ')[5:]\n                b = re.sub('\\n', '', ' '.join(a))\n                registry_to_report.append(b)\n        if len(registry_to_report) > 0:\n            if not rhit:\n                report.write(\"\\n\\nInteresting registry handles:\")\n                report.write(\n                    \"\\n--------------------------------------------------------------------------------------------------------------------------\\n\")\n                rhit = True\n            report_string = \"\"\n            registry_to_report = sorted(set(registry_to_report))\n            for regkey in registry_to_report:\n                report_string += \"  \" + regkey + \"\\n\"\n            report.write(reg_key + \":\\n\" + report_string)\n\n\ndef analyse_imports(pid):\n    import_analysis_matrix = {\"Can create new desktops \": ransomware_imports,\n                              \"Can track keyboard strokes \": keylogger_imports,\n                              \"Can extract passwords \": password_extract_imports,\n                              \"Can access the clipboard \": clipboard_imports,\n                              \"Can inject code to other processes \": process_injection_imports,\n                              \"Can bypass UAC \": uac_bypass_imports,\n                              \"Can use antidebug techniques \": anti_debug_imports,\n                              \"Can receive or send files from or to internet \": web_imports,\n                              \"Can listen for inbound connections \": listen_imports,\n                              \"Can create or start services \": service_imports,\n                              \"Can restart or shutdown the system \": shutdown_imports,\n                              \"Can interact with the registry \": registry_imports,\n                              \"Can create or write to files \": file_imports,\n                              \"Can create atoms \": atoms_imports,\n                              \"Can identify machine time \": localtime_imports,\n                              \"Can interact with or query device drivers \": driver_imports,\n                              \"Can enumerate username \": username_imports,\n                              \"Can identify machine version information \": machine_version_imports,\n                              \"Can query startup information \": startup_imports,\n                              \"Can enumerate free disk space \": diskspace_imports,\n                              \"Can enumerate system information \": sysinfo_imports\n                              }\n    impscanfolder = tmpfolder + \"impscan/\"\n    hit = False\n    if os.path.isfile(impscanfolder + str(pid) + \".txt\"):\n        for susp_imports_codename in import_analysis_matrix:\n            regex = import_analysis_matrix[susp_imports_codename]\n            susp_functions = []\n            with open(impscanfolder + str(pid) + \".txt\", \"r\") as imports:\n                for function in imports:\n                    if re.search(regex, function, re.IGNORECASE):\n                        susp_functions.append(re.sub(' +', ' ', function).split(' ')[3])\n            if len(susp_functions) > 0:\n                if not hit:\n                    report.write(\"\\n\\nInteresting imports:\")\n                    report.write(\n                        \"\\n--------------------------------------------------------------------------------------------------------------------------\\n\")\n                    hit = True\n                report_string = \"\"\n                susp_functions = sorted(set(susp_functions))\n                for function in susp_functions:\n                    if function == susp_functions[-1]:\n                        report_string += re.sub(\"\\n\", \"\", function)\n                    else:\n                        report_string += (re.sub(\"\\n\", \"\", function) + \", \")\n                report.write(susp_imports_codename + \"(\" + report_string + \").\\n\")\n\n\ndef strings(filepath, minimum=4):\n    with open(filepath, \"rb\") as f:\n        result = \"\"\n        for c in f.read():\n            if c in string.printable:\n                result += c\n                continue\n            if len(result) >= minimum:\n                yield result\n            result = \"\"\n\n\ndef analyse_strings(pid):\n    strings_analysis_matrix = {\"IP address(es)\": ips_regex,\n                               \"Email(s)\": emails_regex,\n                               \"HTTP URL(s)\": domains_regex_http,\n                               \"FTP URL(s)\": domains_regex_ftp,\n                               \"File URL(s)\": domains_regex_file,\n                               \"Web related keyword(s)\": web_regex_str,\n                               \"Keylogger keyword(s)\": keylogger_regex_str,\n                               \"Password keyword(s)\": password_regex_str,\n                               \"RAT keyword(s)\": rat_regex_str,\n                               \"Tool(s)\": tool_regex_str,\n                               \"Banking keyword(s)\": banking_regex_str,\n                               \"Social website(s)\": socialsites_regex_str,\n                               \"Antivirus keyword(s)\": antivirus_regex_str,\n                               \"Anti-sandbox keyword(s)\": sandbox_regex_str,\n                               \"Virtualisation keyword(s)\": virtualisation_regex_str,\n                               \"Sysinternal tool(s)\": sysinternals_regex_str,\n                               \"Powershell keyword(s)\": powershell_regex_str,\n                               \"SQL keyword(s)\": sql_regex_str,\n                               \"Shell keyword(s)\": shell_regex_str,\n                               \"Information gathering keyword(s)\": infogathering_regex_str,\n                               \"Executable file(s)\": exec_regex_str,\n                               \"Encryption keyword(s)\": crypto_regex_str,\n                               \"Filepath(s)\": filepath_regex_str,\n                               \"Browser keyword(s)\": browser_regex_str,\n                               \"Misc keyword(s)\": other_regex_str\n                               }\n    dumpfolder = tmpfolder + str(pid) + \"/\"\n    filelist = os.listdir(dumpfolder)\n    hit = False\n    for susp_strings_codename in strings_analysis_matrix:\n        regex = strings_analysis_matrix[susp_strings_codename]\n        susp_strings = []\n        for f in filelist:\n            for stringa in strings(dumpfolder + f):\n                if re.search(regex, stringa, re.IGNORECASE):\n                    for i in re.findall(regex, stringa, re.IGNORECASE):\n                        susp_strings.append(i)\n        if len(susp_strings) > 0:\n            if not hit:\n                report.write(\"\\n\\nSuspicious strings from process memory:\")\n                report.write(\"\\n--------------------------------------------------------------------------------------------------------------------------\\n\")\n                hit = True\n            report_string = \"\"\n            susp_strings = sorted(set(susp_strings))\n            for susp_string in susp_strings:\n                if susp_string == susp_strings[-1]:\n                    report_string += re.sub(\"\\n\", \"\", susp_string)\n                else:\n                    report_string += (re.sub(\"\\n\", \"\", susp_string) + \", \")\n            report.write(susp_strings_codename + \": \" + report_string + \"\\n\")\n\n\ndef check_expected_parent(pid):\n    fl = False\n    expected_parent = \"\"\n    childname = get_procname(pid, 'psscan')\n    parent = \"\"\n    for parent in parent_child:\n        if childname in parent_child[parent]:\n            fl = True\n            expected_parent = parent\n            break\n    if fl:\n        actual_parent = get_procname(get_parent_pids_of([pid, ])[0], \"psscan\")\n        if actual_parent.lower() != parent.lower():\n            j = get_associated_process_lines_pids(get_pids(actual_parent))\n            l = get_associated_process_lines_pids(get_pids(expected_parent))\n            k = get_associated_process_lines_pids([pid, ])\n            report_anomalies(\"Unexpected parent process (\" + actual_parent + \" instead of \" + expected_parent + \"):\", k + j + l, '-', \"psscan\", 2)\n\n\ndef get_remote_share_handles(pid):\n    share_handles_to_report = []\n    remote_share = anomaly_search(\"handles\", \"Device\\\\\\(LanmanRedirector|Mup)\", 'yes', '', \"diff\")\n    for share_handle in remote_share:\n        if re.sub(' +', ' ', share_handle).split(' ')[1] == pid:\n            share_handles_to_report.append(share_handle)\n    return share_handles_to_report\n\n\ndef get_raw_sockets(pid):\n    raw_sockets_to_report = []\n    raw_sockets = anomaly_search(\"handles\", \"\\\\\\Device\\\\\\RawIp\", 'yes', '', \"diff\")\n    for raw_socket in raw_sockets:\n        if re.sub(' +', ' ', raw_socket).split(' ')[1] == pid:\n            raw_sockets_to_report.append(raw_socket)\n    return raw_sockets_to_report\n\n\ndef get_md5(pid):\n    md5 = \"\"\n    dump_folder = tmpfolder + str(pid) + \"/\"\n    filelist = os.listdir(dump_folder)\n    for f in filelist:\n        if f == \"executable.\" + str(pid) + \".exe\":\n            md5 = hashlib.md5(open(dump_folder + f).read()).hexdigest()\n            break\n    return md5\n\n\ndef report_virustotal_md5_results(md5, api):\n    url = \"https://www.virustotal.com/vtapi/v2/file/report\"\n    parameters = {\"resource\": md5, \"apikey\": api}\n    data = urllib.urlencode(parameters)\n    req = urllib2.Request(url, data)\n    response_dict = {}\n    network_error = False\n    try:\n        response = urllib2.urlopen(req)\n        json = response.read()\n        if json != \"\":\n            response_dict = simplejson.loads(json)\n    except urllib2.URLError:\n        network_error = True\n    if not network_error:\n        report.write(\"\\n\\nVirusTotal scan results:\")\n        report.write(\"\\n--------------------------------------------------------------------------------------------------------------------------\\n\")\n        report.write(\"MD5 value: \" + md5 + \"\\n\")\n        if \"response_code\" in response_dict:\n            if response_dict[\"response_code\"] == 1:\n                report.write(\"VirusTotal scan date: \" + str(response_dict[\"scan_date\"]) + \"\\n\")\n                report.write(\"VirusTotal engine detections: \" + str(response_dict[\"positives\"]) + \"/\" + str(response_dict[\"total\"]) + \"\\n\")\n                report.write(\"Link to VirusTotal report: \" + str(response_dict[\"permalink\"]) + \"\\n\")\n            else:\n                report.write(\"Could not find VirusTotal scan results for the MD5 value above.\\n\")\n        else:\n            report.write(\"VirusTotal request rate limit reached, could not retrieve results.\\n\")\n\n\ndef main():\n    # PRINT VOLDIFF BANNER ================================================================\n    print_voldiff_banner()\n    global output_dir\n    global report\n    global tmpfolder\n    global profile\n    global baseline_memory_image\n    global infected_memory_image\n    global memory_image\n\n    # CHECK THAT VOL.PY IS INSTALLED ================================================================\n    if not check_volatility_path(path_to_volatility):\n        print(\"vol.py does not seem to be installed. Please ensure that volatility is installed/functional before using VolDiff.\")\n        sys.exit()\n\n    # READ SYS.ARGV VARIABLES ================================================================\n    if not len(sys.argv) > 1:\n        print_help()\n    elif \"--help\" in sys.argv:\n        print_help()\n    elif \"--version\" in sys.argv:\n        print_version()\n    elif \"--dependencies\" in sys.argv:\n        print_dependencies()\n    if \"--output-dir\" in sys.argv:\n        check_enough_arguments_supplied(5)\n    else:\n        check_enough_arguments_supplied(3)\n    if os.path.isfile(sys.argv[2]):\n        mode = \"dual\"\n        if os.path.isfile(sys.argv[1]):\n            baseline_memory_image = sys.argv[1]\n            print (\"Path to baseline memory image: %s\" % baseline_memory_image)\n        else:\n            print (\"Please specify a valid path to a baseline memory image.\")\n            sys.exit()\n        infected_memory_image = sys.argv[2]\n        print (\"Path to infected memory image: %s\" % infected_memory_image)\n\n        if len(sys.argv) == 3:\n            print (\"Profile is not specified. Please specify a profile to use (such as Win7SP1x64).\")\n            sys.exit()\n        else:\n            check_profile(sys.argv[3])\n            profile = sys.argv[3]\n    else:\n        mode = \"standalone\"\n        if os.path.isfile(sys.argv[1]):\n            memory_image = sys.argv[1]\n            print (\"Only one memory image specified: standalone mode\")\n            print (\"Path to memory image: %s\" % memory_image)\n        else:\n            print (\"Please specify a valid path to a baseline memory image.\")\n            sys.exit()\n        if len(sys.argv) == 2:\n            print (\"Profile is not specified. Please specify a profile to use (such as Win7SP1x64)!\")\n            sys.exit()\n        else:\n            check_profile(sys.argv[2])\n            profile = sys.argv[2]\n\n    # CREATE FOLDER TO STORE OUTPUT ================================================================\n    starttime = time.time()\n    output_dir = 'VolDiff_' + datetime.datetime.now().strftime(\"%d-%m-%Y_%H:%M\")\n    if os.name == 'nt':\n        output_dir = 'VolDiff_' + datetime.datetime.now().strftime(\"%d-%m-%Y_%H%M\")  # can't name file/dir with :\n    tmpval = False\n    for arg in sys.argv:\n        if tmpval:\n            output_dir = arg\n            tmpval = False\n        if arg == \"--output-dir\":\n            tmpval = True\n    tmpfolder = output_dir + '/tmpfolder/'\n    os.makedirs(tmpfolder)\n\n    # RUN VOLATILITY PLUGINS ================================================================\n    print (\"\\nRunning a selection of volatility plugins (time consuming):\")\n    sub_procs = {}\n    file_dict = {}\n    proc_counter = 0\n    for plugin in plugins_to_run:\n        print(\"Volatility plugin %s execution in progress...\" % plugin)\n        plugin_path = output_dir + '/' + plugin + '/'\n        os.makedirs(plugin_path)\n        if plugin == \"mutantscan\" or plugin == \"handles\" or plugin == \"privs\" or plugin == \"envars\":\n            option = \"--silent\"\n        elif plugin == \"threads\":\n            option = \"-F OrphanThread\"\n        elif plugin == \"psxview\":\n            option = \"-R\"\n        elif plugin == \"malfind\":\n            if mode == \"dual\":\n                dump_dir_baseline = output_dir + '/malfind/dump_dir_baseline/'\n                os.makedirs(dump_dir_baseline)\n                option = \"--dump-dir=\" + output_dir + \"/malfind/dump_dir_baseline/\"\n                file_dict[plugin + \"baseline\"] = open(output_dir + '/' + plugin + '/' + \"baseline_\" + plugin + \".txt\", \"w\")\n                sub_procs[plugin + \"baseline\"] = Popen([path_to_volatility, \"--profile\", profile, \"-f\", baseline_memory_image, plugin, option], stdout=file_dict[plugin + \"baseline\"], stderr=devnull)\n                proc_counter += 1\n                if proc_counter >= max_concurrent_subprocesses:\n                    for pr in sub_procs:\n                        sub_procs[pr].wait()\n                    proc_counter = 0\n                    sub_procs = {}\n                dump_dir_infected = output_dir + '/malfind/dump_dir_infected/'\n                os.makedirs(dump_dir_infected)\n                option = \"--dump-dir=\" + output_dir + \"/malfind/dump_dir_infected/\"\n                file_dict[plugin + \"infected\"] = open(output_dir + '/' + plugin + '/' + \"infected_\" + plugin + \".txt\", \"w\")\n                sub_procs[plugin + \"infected\"] = Popen([path_to_volatility, \"--profile\", profile, \"-f\", infected_memory_image, plugin, option], stdout=file_dict[plugin + \"infected\"], stderr=devnull)\n                proc_counter += 1\n                if proc_counter >= max_concurrent_subprocesses:\n                    for pr in sub_procs:\n                        sub_procs[pr].wait()\n                    proc_counter = 0\n                    sub_procs = {}\n            else:\n                dump_dir = output_dir + '/malfind/dump_dir/'\n                os.makedirs(dump_dir)\n                option = \"--dump-dir=\" + output_dir + \"/malfind/dump_dir/\"\n                file_dict[plugin] = open(output_dir + '/' + plugin + '/' + plugin + \".txt\", \"w\")\n                sub_procs[plugin] = Popen([path_to_volatility, \"--profile\", profile, \"-f\", memory_image, plugin, option], stdout=file_dict[plugin], stderr=devnull)\n                proc_counter += 1\n                if proc_counter >= max_concurrent_subprocesses:\n                    for pr in sub_procs:\n                        sub_procs[pr].wait()\n                    proc_counter = 0\n                    sub_procs = {}\n            continue\n        elif plugin == \"procdump\":\n            option = \"--dump-dir=\" + output_dir + \"/procdump/\"\n            if mode == \"dual\":\n                sub_procs[plugin] = Popen([path_to_volatility, \"--profile\", profile, \"-f\", infected_memory_image, plugin, \"-u\", option], stdout=devnull, stderr=devnull)\n                proc_counter += 1\n                if proc_counter >= max_concurrent_subprocesses:\n                    for pr in sub_procs:\n                        sub_procs[pr].wait()\n                    proc_counter = 0\n                    sub_procs = {}\n            else:\n                sub_procs[plugin] = Popen([path_to_volatility, \"--profile\", profile, \"-f\", memory_image, plugin, \"-u\", option], stdout=devnull, stderr=devnull)\n                proc_counter += 1\n                if proc_counter >= max_concurrent_subprocesses:\n                    for pr in sub_procs:\n                        sub_procs[pr].wait()\n                    proc_counter = 0\n                    sub_procs = {}\n            continue\n        else:\n            option = ''\n        # option set, running vol.py processes in //:\n        if mode == \"dual\":\n            file_dict[plugin + \"baseline\"] = open(output_dir + '/' + plugin + '/' + \"baseline_\" + plugin + \".txt\", \"w\")\n            sub_procs[plugin + \"baseline\"] = Popen([path_to_volatility, \"--profile\", profile, \"-f\", baseline_memory_image, plugin, option], stdout=file_dict[plugin + \"baseline\"], stderr=devnull)\n            proc_counter += 1\n            if proc_counter >= max_concurrent_subprocesses:\n                for pr in sub_procs:\n                    sub_procs[pr].wait()\n                proc_counter = 0\n                sub_procs = {}\n            file_dict[plugin + \"infected\"] = open(output_dir + '/' + plugin + '/' + \"infected_\" + plugin + \".txt\", \"w\")\n            sub_procs[plugin + \"infected\"] = Popen([path_to_volatility, \"--profile\", profile, \"-f\", infected_memory_image, plugin, option], stdout=file_dict[plugin + \"infected\"], stderr=devnull)\n            proc_counter += 1\n            if proc_counter >= max_concurrent_subprocesses:\n                for pr in sub_procs:\n                    sub_procs[pr].wait()\n                proc_counter = 0\n                sub_procs = {}\n        else:\n            file_dict[plugin] = open(output_dir + '/' + plugin + '/' + plugin + \".txt\", \"w\")\n            sub_procs[plugin] = Popen([path_to_volatility, \"--profile\", profile, \"-f\", memory_image, plugin, option], stdout=file_dict[plugin], stderr=devnull)\n            proc_counter += 1\n            if proc_counter >= max_concurrent_subprocesses:\n                for pr in sub_procs:\n                    sub_procs[pr].wait()\n                proc_counter = 0\n                sub_procs = {}\n    # ensuring that all subprocesses are completed before proceeding:\n    for pr in sub_procs:\n        sub_procs[pr].wait()\n    for f in file_dict:\n        file_dict[f].close()\n\n    # DEV MODE SWITCH ================================================================\n    if \"--devmode\" in sys.argv:\n        raw_input('\\nChange files and hit enter once ready.')\n\n    # DIFF OUTPUT RESULTS ================================================================\n    if mode == \"dual\":\n        print (\"Diffing output results...\")\n        for plugin in plugins_to_run:\n            if plugin != \"procdump\":\n                diff_files(output_dir + '/' + plugin + '/baseline_' + plugin + \".txt\",\n                           output_dir + '/' + plugin + '/infected_' + plugin + \".txt\",\n                           output_dir + '/' + plugin + '/diff_' + plugin + \".txt\")\n\n    if \"--no-report\" in sys.argv:\n        script_completion(starttime)\n\n    # CREATE REPORT ================================================================\n    report = open(output_dir + \"/VolDiff_Report.txt\", 'w')\n\n    if mode == \"dual\":\n        report.write(\"             _    ___ _  __  __ \\n\")\n        report.write(\" /\\   /\\___ | |  /   (_)/ _|/ _|\\n\")\n        report.write(\" \\ \\ / / _ \\| | / /\\ / | |_| |_ \\n\")\n        report.write(\"  \\ V / (_) | |/ /_//| |  _|  _|\\n\")\n        report.write(\"   \\_/ \\___/|_/___,' |_|_| |_|  \\n\")\n\n        report.write(\"\\nVolatility analysis report generated by VolDiff v%s\" % version)\n        report.write(\"\\nDownload the latest VolDiff version from https://github.com/aim4r/VolDiff/\")\n        report.write(\"\\n\\nBaseline memory image: %s\" % baseline_memory_image)\n        report.write(\"\\nInfected memory image: %s\" % infected_memory_image)\n        report.write(\"\\nProfile: %s\" % profile)\n        report.write(\"\\nDate and time: \" + datetime.datetime.now().strftime(\"%d/%m/%Y %H:%M\"))\n\n        no_new_entries = []\n\n        for plugin in plugins_to_report:\n            if os.stat(output_dir + \"/\" + plugin + \"/diff_\" + plugin + \".txt\").st_size == 0:\n                no_new_entries.append(plugin)\n\n            # processing pslist and psscan output:\n            elif plugin == \"pslist\" or plugin == \"psscan\":\n                # store baseline pids in a list\n                with open(output_dir + \"/\" + plugin + \"/baseline_\" + plugin + \".txt\") as baseline:\n                    baseline_pids = []\n                    for line in baseline:\n                        pid = re.sub(' +', ' ', line).split(' ')[2]\n                        baseline_pids.append(pid)\n                    sorted(set(baseline_pids))\n                # store infected pids in a list\n                with open(output_dir + \"/\" + plugin + \"/infected_\" + plugin + \".txt\") as infected:\n                    infected_pids = []\n                    for line in infected:\n                        pid = re.sub(' +', ' ', line).split(' ')[2]\n                        infected_pids.append(pid)\n                    sorted(set(infected_pids))\n                # get the diff between both\n                diff_pids = []\n                for pid in infected_pids:\n                    if pid not in baseline_pids:\n                        diff_pids.append(pid)\n                # print diff lines\n                if len(diff_pids) > 0:\n                    report.write(\"\\n\\nNew %s entries.\" % plugin)\n                    report.write(\n                        \"\\n==========================================================================================================================\\n\")\n                    with open(output_dir + \"/\" + plugin + \"/infected_\" + plugin + \".txt\") as f:\n                        for i in range(2):\n                            line = next(f, '').strip()\n                            report.write(line + \"\\n\")\n                    for pid in diff_pids:\n                        with open(output_dir + \"/\" + plugin + \"/infected_\" + plugin + \".txt\") as f:\n                            for line in f:\n                                if re.search(r\"[a-zA-Z\\.]\\s+%s \" % pid, line, re.IGNORECASE):\n                                    report.write(line)\n\n            # processing netscan output\n            elif plugin == \"netscan\":\n                report_plugin(plugin, 1)\n\n            # filtering mutantscan output\n            elif plugin == \"mutantscan\":\n\n                with open(output_dir + \"/\" + plugin + \"/diff_\" + plugin + \".txt\") as diff_mutants:\n                    mutants = []\n                    for line in diff_mutants:\n                        mutant = ' '.join((re.sub(' +', ' ', line).split(' ')[5:]))\n                        if mutant != '\\n':\n                            mutants.append(mutant)\n                    mutants = sorted(set(mutants))\n                    if len(mutants) > 0:\n                        report.write(\"\\n\\nNew %s entries.\" % plugin)\n                        report.write(\n                            \"\\n==========================================================================================================================\\n\")\n                        for mutant in mutants:\n                            report.write(mutant)\n\n            # ensuring malfind output is completely reported\n            elif plugin == \"malfind\":\n                report_plugin(plugin, 0, 500)\n\n            # processing plugins that don't need output formatting:\n            elif plugin == \"devicetree\" or plugin == \"orphanthreads\" or plugin == \"cmdline\" or plugin == \"consoles\" or plugin == \"svcscan\" or plugin == \"driverirp\" or plugin == \"shellbags\" or plugin == \"iehistory\" or plugin == \"sessions\" or plugin == \"eventhooks\":\n                report_plugin(plugin)\n\n            # processing other plugins:\n            else:\n                report_plugin(plugin, 2)\n\n        # display list of plugins with no notable changes:\n        if len(no_new_entries) != 0:\n            report.write(\"\\n\\nNo notable changes to highlight from the following plugins.\")\n            report.write(\n                \"\\n==========================================================================================================================\\n\")\n            for plugin in no_new_entries:\n                report.write(plugin + \"\\n\")\n\n        # display list of plugins hidden from report (verbose):\n        report.write(\"\\n\\nPlugins that were executed but are not included in the report above.\")\n        report.write(\n            \"\\n==========================================================================================================================\\n\")\n        report.write(\n            \"filescan\\nhandles\\ngetsids\\ndeskscan\\ndlllist\\nldrmodules\\natoms\\nsvcscan\\natomscan\\nidt\\ngdt\\ntimers\\ngditimers\")\n\n    # MALWARE CHECKS ================================================================\n    if \"--malware-checks\" not in sys.argv:\n        if mode == \"standalone\":\n            try:\n                os.remove(output_dir + \"/VolDiff_Report.txt\")\n            except:\n                pass\n        script_completion(starttime)\n\n    # PRINT BANNERS ================================================================\n    print(\"\\nHunting for malicious artifacts in memory...\")\n    if mode == \"dual\":\n        report.write(\"\\n\\n\")\n        report.write(\"   _               _           _         __                 _ _       \\n\")\n        report.write(\"  /_\\  _ __   __ _| |_   _ ___(_)___    /__\\ ___  ___ _   _| | |_ ___ \\n\")\n        report.write(\" //_\\\\\\\\| '_ \\\\ / _\\`| | | | / __| / __|  / \\\\/// _ \\\\/ __| | | | | __/ __|\\n\")\n        report.write(\"/  _  \\\\ | | | (_| | | |_| \\\\__ \\\\ \\\\__ \\\\ / _  \\\\  __/\\\\__ \\\\ |_| | | |_\\\\__ \\\\\\n\")\n        report.write(\"\\_/ \\_/_| |_|\\__,_|_|\\__, |___/_|___/ \\/ \\_/\\___||___/\\__,_|_|\\__|___/\\n\")\n        report.write(\"                     |___/                                            \\n\")\n    elif mode == \"standalone\":\n        report.write(\"\\n\")\n        report.write(\"             _    ___ _  __  __     _               _           _         __                 _ _       \\n\")\n        report.write(\" /\\   /\\___ | |  /   (_)/ _|/ _|   /_\\  _ __   __ _| |_   _ ___(_)___    /__\\ ___  ___ _   _| | |_ ___ \\n\")\n        report.write(\" \\\\ \\\\ / / _ \\\\| | / /\\\\ / | |_| |_   //_ \\\\| '_ \\\\ / _\\`| | | | / __| / __|  / \\\\/// _ \\\\/ __| | | | | __/ __|\\n\")\n        report.write(\"  \\\\ V / (_) | |/ /_//| |  _|  _| /  _  \\\\ | | | (_| | | |_| \\\\__ \\\\ \\\\__ \\\\ / _  \\\\  __/\\\\__ \\\\ |_| | | |_\\\\__ \\\\\\n\")\n        report.write(\"   \\_/ \\___/|_/___,' |_|_| |_|   \\_/ \\_/_| |_|\\__,_|_|\\__, |___/_|___/ \\/ \\_/\\___||___/\\__,_|_|\\__|___/\\n\")\n        report.write(\"                                                      |___/                                            \\n\")\n        report.write(\"\\nVolatility analysis report of %s (%s)\" % (memory_image, profile))\n        report.write(\"\\nReport created by VolDiff v\" + version + \" on the \" + datetime.datetime.now().strftime(\"%d/%m/%Y %H:%M\"))\n        report.write(\"\\nDownload the latest VolDiff version from https://github.com/aim4r/VolDiff/\")\n\n    # PIDS FOR ANALYSIS ================================================================\n    pids_to_analyse = {}\n    if mode == \"standalone\":\n        unusual_pids = get_all_pids(usual_processes)\n        for pid in unusual_pids:\n            if pid in pids_to_analyse:\n                pids_to_analyse[pid] += \", non-default process\"\n            else:\n                pids_to_analyse[pid] = \"non-default process\"\n        malfind_pids = get_malfind_pids()\n        for pid in malfind_pids:\n            if pid in pids_to_analyse:\n                pids_to_analyse[pid] += \", potential code injection\"\n            else:\n                pids_to_analyse[pid] = \"potential code injection\"\n    else:\n        unusual_pids = get_diff_pids(\"conhost.exe|ipconfig.exe|cmd.exe\")\n        for pid in unusual_pids:\n            if pid in pids_to_analyse:\n                pids_to_analyse[pid] += \", new process\"\n            else:\n                pids_to_analyse[pid] = \"New process\"\n        malfind_pids = get_malfind_pids()\n        for pid in malfind_pids:\n            if pid in pids_to_analyse:\n                pids_to_analyse[pid] += \", potential code injection\"\n            else:\n                pids_to_analyse[pid] = \"potential code injection\"\n\n    # MALWARE CHECKS - NETWORK ================================================================\n    # compute unique IPs from netscan output:\n    report_anomalies(\"IP addresses found in netscan output.\", find_ips_domains_emails(\"netscan\"))\n    # compute unique IPs and domains from iehistory output:\n    report_anomalies(\"IP addresses, domains and emails found in iehistory output.\", find_ips_domains_emails(\"iehistory\"))\n\n    # MALWARE CHECKS - PROCESS ANOMALIES ================================================================\n    # verify PID of System process = 4\n    system_pids = get_pids(\"system\")\n    system_process_check = False\n    for pid in system_pids:\n        if pid != '4':\n            system_process_check = True\n            if pid in pids_to_analyse:\n                pids_to_analyse[pid] += \", unusual pid (not 4)\"\n            else:\n                pids_to_analyse[pid] = \"unusual pid (not 4)\"\n    if system_process_check:\n        l = get_associated_process_lines_pids(system_pids)\n        report_anomalies(\"Unusual system process PID (different to 4).\", l, \"=\", \"psscan\", 2)\n    # verify that only one instance of certain processes is running:\n    for process in uniq_processes:\n        pids = get_pids(process)\n        if len(pids) > 1:\n            l = get_associated_process_lines_pids(get_pids(process))\n            report_anomalies(\"Unexpected multiple instances of \" + process + \".\", l, \"=\", \"psscan\", 2)\n    # verify that some processes do not have a child:\n    nochild_processes = [\"lsass.exe\", \"lsm.exe\"]\n    for process in nochild_processes:\n        pids = get_pids(process)\n        childs = get_childs_of(pids)\n        if len(childs) > 0:\n            parent_lines = get_associated_process_lines_pids(get_pids(process))\n            child_lines = get_associated_process_lines_pids(childs)\n            report_anomalies(\"Process \" + process + \" has unexpected childs.\", parent_lines + child_lines, \"=\", \"psscan\", 2)\n            for pid in pids:\n                pidchilds = get_childs_of([pid, ])\n                if len(pidchilds) > 0:\n                    if pid in pids_to_analyse:\n                        pids_to_analyse[pid] += \", has unexpected child process\"\n                    else:\n                        pids_to_analyse[pid] = \"has unexpected child process\"\n    # verify child/parent process relationships:\n    for parent in parent_child:\n        for child in parent_child[parent]:\n            child_pids = get_pids(child)\n            for pid in child_pids:\n                parent_pids = get_parent_pids_of([pid, ])\n                parent_procnames = get_procnames(parent_pids)\n                for parent_procname in parent_procnames:\n                    if parent_procname.lower() != parent.lower():\n                        j = get_associated_process_lines_pids([pid, ])\n                        l = get_associated_process_lines_pids(parent_pids)\n                        report_anomalies(\"Unexpected parent process of \" + child + \" PID \" + pid + \" (\" + parent_procname + \" instead of \" + parent + \").\", j + l, \"=\", \"psscan\", 2)\n                        if pid in pids_to_analyse:\n                            pids_to_analyse[pid] += \", has an unexpected parent process\"\n                        else:\n                            pids_to_analyse[pid] = \"has an unexpected parent process\"\n    # verify that every process has a parent (except for explorer.exe, csrss.exe, wininit.exe and winlogon.exe)\n    pids = get_all_pids()\n    ppids = get_all_ppids(\"explorer.exe|csrss.exe|wininit.exe|winlogon.exe|system\")\n    for ppid in ppids:\n        if ppid not in pids:\n            l = get_associated_process_lines_ppids([ppid, ])\n            report_anomalies(\"Parent process with PPID \" + ppid + \" is not listed in psscan output.\", l, \"=\", \"psscan\", 2)\n    # verify processes are running in expected sessions:\n    for process in session0_processes:\n        process_pids = get_pids(process)\n        for pid in process_pids:\n            session = get_session(pid)\n            if session != '0':\n                l = get_associated_process_lines_pids([pid, ], \"pslist\")\n                report_anomalies(\"Process \" + process + \" (\" + str(pid) + \") is running in unexpected session (\" + session + \" instead of 0).\", l, \"=\", \"pslist\", 2)\n                if pid in pids_to_analyse:\n                    pids_to_analyse[pid] += \", running in an unusual session\"\n                else:\n                    pids_to_analyse[pid] = \"running in an unusual session\"\n    for process in session1_processes:\n        process_pids = get_pids(process)\n        for pid in process_pids:\n            session = get_session(pid)\n            if session != '1':\n                l = get_associated_process_lines_pids([pid, ], \"pslist\")\n                report_anomalies(\"Process \" + process + \" (\" + str(pid) + \") is running in unexpected session (\" + session + \" instead of 1).\", l, \"=\", \"pslist\", 2)\n                if pid in pids_to_analyse:\n                    pids_to_analyse[pid] += \", running in an unusual session\"\n                else:\n                    pids_to_analyse[pid] = \"running in an unusual session\"\n    # check process executable path:\n    for process in process_execpath:\n        process_pids = get_pids(process)\n        for pid in process_pids:\n            path = get_execpath(pid)\n            correct_path = process_execpath[process]\n            if path != \"\" and path.lower() != correct_path.lower():\n                l = get_associated_process_lines_pids([pid, ], \"psscan\")\n                report_anomalies(\"Process \" + process + \" (\" + pid + \") is running from an unexpected path (\" + path.lower() + \" instead of \" + correct_path.lower() + \").\", l, \"=\", \"psscan\", 2)\n                if pid in pids_to_analyse:\n                    pids_to_analyse[pid] += \", running from an unexpected execution path\"\n                else:\n                    pids_to_analyse[pid] = \"running from an unexpected execution path\"\n    # verify if any processes have suspicious l33t names:\n    leet_processes = anomaly_search(\"psscan\", l33t_process_name, 'yes', '', \"diff\")\n    report_anomalies(\"Suspicious process name found.\", leet_processes, \"=\", \"psscan\", 2)\n    for l in leet_processes:\n        pid = re.sub(' +', ' ', l).split(' ')[2]\n        if pid in pids_to_analyse:\n            pids_to_analyse[pid] += \", has a suspicious process name\"\n        else:\n            pids_to_analyse[pid] = \"has a suspicious process name\"\n    # check if any process is running from a TEMP directory:\n    pid_list = get_all_pids()\n    for pid in pid_list:\n        path = get_execpath(pid)\n        process = get_procname(pid)\n        if re.search(temp_filepath, path, re.IGNORECASE):\n            l = get_associated_process_lines_pids([pid, ], \"psscan\")\n            report_anomalies(\"Process \" + process + \" PID \" + pid + \" is running from a temporary folder (\" + path.lower() + \").\", l, \"=\", \"psscan\", 2)\n            if pid in pids_to_analyse:\n                pids_to_analyse[pid] += \", running from a temporary folder\"\n            else:\n                pids_to_analyse[pid] = \"running from a temporary folder\"\n    # verify if any hacker tools were used in process list:\n    hacker_processes = anomaly_search(\"psscan\", hacker_process_regex, 'yes', '', \"diff\")\n    report_anomalies(\"Process(es) that may have been used for lateral movement, exfiltration etc.\", hacker_processes, \"=\", \"psscan\", 2)\n    # detect process hollowing:\n    path = output_dir + \"/procdump/\"\n    dumped_process_filenames = os.listdir(path)\n    procnames = get_all_procnames()\n    for procnameh in procnames:\n        procpids = get_pids(procnameh)\n        report_string = \"\"\n        if len(procpids) > 1:\n            procname_sizes = []\n            unique_procname_sizes = []\n            for pid in procpids:\n                for dumped_process_filename in dumped_process_filenames:\n                    if re.search(\"executable.\" + pid + \".exe\", dumped_process_filename, re.IGNORECASE):\n                        procname_sizes.append(os.stat(path + dumped_process_filename).st_size)\n                        unique_procname_sizes = sorted(set(procname_sizes))\n                        report_string += procnameh + \"   \" + pid + \"   \" + str(\n                            os.stat(path + dumped_process_filename).st_size) + \"\\n\"\n            if len(unique_procname_sizes) > 1:\n                report.write(\"\\n\\nPotential process hollowing detected in \" + procnameh + \" (based on size).\")\n                report.write(\n                    \"\\n==========================================================================================================================\\n\")\n                report.write(\"\\nProcess       PID    Size\")\n                report.write(\"\\n----------------------------\\n\")\n                report.write(report_string)\n    # detect processes with exit time but active threads:\n    report_anomalies(\"Process(es) with exit time and active threads.\", deadproc_activethreads(), \"=\", \"psxview\", 2)\n    for d in deadproc_activethreads():\n        pid = re.sub(' +', ' ', d).split(' ')[2]\n        if pid in pids_to_analyse:\n            pids_to_analyse[pid] += \", has an exit time and active threads\"\n        else:\n            pids_to_analyse[pid] = \"has an exit time and active threads\"\n    # check if any process has domain or enterprise admin privileges:\n    high_privileges_regex = \"Domain Admin|Enterprise Admin|Schema Admin\"\n    high_privileges = anomaly_search(\"getsids\", high_privileges_regex, 'yes', '', \"diff\")\n    report_anomalies(\"Process(es) with domain or enterprise admin privileges.\", high_privileges)\n    # check if any process has debug privileges:\n    debug_privileges = anomaly_search(\"getsids\", \"debug\", 'yes', '', \"diff\")\n    report_anomalies(\"Process(es) with debug privileges.\", debug_privileges)\n\n    # MALWARE CHECKS - SUSPICIOUS DLLs/EXEs ================================================================\n    # Prefetch artifacts (mftparser): [DUAL ONLY]\n    if mode == \"dual\":\n        prefetch_files = anomaly_search(\"mftparser\", \".pf$\", 'yes')\n        prefetch_files_to_report = []\n        for entry in prefetch_files:\n            pf = ' '.join((re.sub(' +', ' ', entry).split(' ')[12:]))\n            if pf != \"\":\n                prefetch_files_to_report.append(pf)\n        report_anomalies(\"Prefetch artifacts (mftparser).\", prefetch_files_to_report)\n    # Suspicious dlls/executables (dlllist) - loaded from temp folders, unusual new (DUAL ONLY), etc:\n    temp_dlls = anomaly_search(\"dlllist\", temp_filepath, 'yes')\n    temp_dlls = extract_substrings(temp_dlls, temp_filepath)\n    new_exe_excluded_regex = \"system32|explorer.exe|iexplore.exe|VMware|wininit.exe|winlogon.exe|TrustedInstaller.exe|taskhost.exe|mscorsvw.exe|TPAutoConnect.exe|comctl32.dll\"\n    new_exes = anomaly_search(\"dlllist\", \"Command line\", 'yes', new_exe_excluded_regex)\n    if mode == \"dual\":\n        new_dlls = anomaly_search(\"dlllist\", \"C:.*.dll\", 'yes', \"System32\")\n        new_dlls = extract_substrings(new_dlls, \"C:.*.dll\")\n        dlls = temp_dlls + new_exes + new_dlls\n    else:\n        dlls = temp_dlls + new_exes\n    dlls_to_report = []\n    for dll in dlls:\n        b = re.sub('\"', '', dll)\n        c = re.sub(\"Command line : \", \"\", b)\n        dlls_to_report.append(c)\n    dlls_to_report = tidy_list(dlls_to_report)\n    report_anomalies(\"Suspicious DLLs/EXEs (dlllist).\", dlls_to_report)\n    # Hidden/suspicious DLLs/EXEs (ldrmodules):\n    ldrmodules_excluded_regex_1 = \"System32\\\\\\msxml6r.dll|System32\\\\\\oleaccrc.dll|System32\\\\\\imageres.dll|System32\\\\\\\\ntdll.dll|System32\\\\\\winlogon.exe|System32\\\\\\services.exe|System32\\\\\\tquery.dll|System32\\\\\\wevtapi.dll\"\n    hiddendlls1_ldrmodules = anomaly_search(\"ldrmodules\", \"False  False  False.*dll$|False  False  False.*exe$\", 'yes', ldrmodules_excluded_regex_1)\n    ldrmodules_excluded_regex_2 = \"system32|explorer.exe|iexplore.exe|.fon$|TrustedInstaller.exe|VMware\\\\\\VMware Tools|mscorsvw.exe\"\n    hiddendlls2_ldrmodules = anomaly_search(\"ldrmodules\", \"False\", 'yes', ldrmodules_excluded_regex_2)\n    hiddendlls3_ldrmodules = anomaly_search(\"ldrmodules\", \"no name\", 'yes')\n    hiddendlls_ldrmodules = hiddendlls1_ldrmodules + hiddendlls2_ldrmodules + hiddendlls3_ldrmodules\n    hiddendlls_ldrmodules = sorted(set(hiddendlls_ldrmodules))\n    report_anomalies(\"Hidden/suspicious DLLs/EXEs (ldrmodules).\", hiddendlls_ldrmodules, \"=\", \"ldrmodules\", 2)\n    # Suspicious DLLs (atoms):\n    dll_atoms = anomaly_search(\"atoms\", \".dll$\", 'yes', usual_atoms_dlls)\n    report_anomalies(\"Suspicious DLLs (atoms).\", dll_atoms, \"=\", \"atoms\", 2)\n    # Suspicious DLLs (atomscan):\n    dll_atomscan = anomaly_search(\"atomscan\", \".dll$\", 'yes', usual_atoms_dlls)\n    report_anomalies(\"Suspicious DLLs (atomscan).\", dll_atomscan, \"=\", \"atomscan\", 2)\n    # DLLs used for password theft or VM evasion (ldrmodules):\n    suspdll_ldrmodules = anomaly_search(\"ldrmodules\", hacker_dll_regex, 'yes')\n    report_anomalies(\"DLLs used for password theft or VM evasion (ldrmodules).\", suspdll_ldrmodules, \"=\", \"ldrmodules\", 2)\n\n    # MALWARE CHECKS - SUSPICIOUS FILES ================================================================\n    # Interesting files on disk (filescan)\n    if mode == \"dual\":\n        suspicious_files1 = anomaly_search(\"filescan\", susp_filepath, 'yes', \"\\.db$|\\.lnk$|\\.ini$|\\.log$\", \"diff\")\n        suspicious_files2 = anomaly_search(\"filescan\", susp_extensions_regex, 'yes', \"suspend-vm-default\\.bat\")\n        suspicious_files = suspicious_files1 + suspicious_files2\n    else:\n        suspicious_files = anomaly_search(\"filescan\", susp_extensions_regex, 'yes')\n    suspicious_files_to_report = []\n    for entry in suspicious_files:\n        en = ' '.join((re.sub(' +', ' ', entry).split(' ')[4:]))\n        if en != \"\":\n            suspicious_files_to_report.append(en)\n    suspicious_files_to_report = sorted(set(suspicious_files_to_report))\n    report_anomalies(\"Interesting files on disk (filescan).\", suspicious_files_to_report, \"=\", \"filescan\", 0, 100)\n    # Alternate Data Stream (ADS) files (mftparser):\n    ads_files = anomaly_search(\"mftparser\", \"DATA ADS\", 'yes', \"Bad$|Max$\")\n    report_anomalies(\"Alternate Data Stream (ADS) files (mftparser).\", ads_files)\n\n    # MALWARE CHECKS - MISC ================================================================\n    # find suspicious desktop instances: [DUAL ONLY]\n    if mode == \"dual\":\n        new_desktops = anomaly_search(\"deskscan\", \"Desktop:\", 'yes', '', 'diff')\n        report_anomalies(\"New desktop instances (deskscan).\", new_desktops)\n    # find interesting entries in hosts file\n    if mode == \"dual\":\n        hostsb = get_hosts_contents(baseline_memory_image)\n        hostsi = get_hosts_contents(infected_memory_image)\n        hosts = []\n        for line in hostsi:\n            if line not in hostsb:\n                hosts.append(line)\n    else:\n        hosts = get_hosts_contents(memory_image)\n    report_anomalies(\"Interesting 'hosts' file entries.\", hosts)\n\n    # MALWARE CHECKS - PERSISTENCE ================================================================\n    # find new services: [Dual Only]\n    if mode == \"dual\":\n        services_to_report = filter_new_services()\n        report_anomalies(\"Notable new entries from svcscan.\", services_to_report)\n    # highlight temp folders appearing in services: [Standalone Only]\n    if mode == \"standalone\":\n        temp_services = anomaly_search(\"svcscan\", temp_filepath, 'yes')\n        report_anomalies(\"Temp folders appearing in svcscan output.\", temp_services)\n\n    # MALWARE CHECKS - KERNEL ================================================================\n    # Keylogger traces (messagehooks):\n    keylogger_messagehooks = anomaly_search(\"messagehooks\", \"KEYBOARD\", 'yes')\n    report_anomalies(\"Keylogger traces (messagehooks).\", keylogger_messagehooks, \"=\", \"messagehooks\", 2)\n    # Unusual timers:\n    unusual_timers = anomaly_search_inverted(\"timers\", usual_timers, 'yes')\n    if mode == \"standalone\":\n        report_anomalies(\"Unusual timers.\", unusual_timers[2:], \"=\", \"timers\", 2)\n    else:\n        report_anomalies(\"Unusual timers.\", unusual_timers, \"=\", \"timers\", 2)\n    # Suspicious 'unknown' timers:\n    unknown_timers = anomaly_search(\"timers\", \"UNKNOWN\", 'yes')\n    report_anomalies(\"Suspicious 'unknown' timers.\", unknown_timers, \"=\", \"timers\", 2)\n    # find unusual gditimers:\n    unusual_gditimers = anomaly_search_inverted(\"gditimers\", usual_gditimers, 'yes')\n    if mode == \"standalone\":\n        report_anomalies(\"Unusual gditimers.\", unusual_gditimers[2:], \"=\", \"gditimers\", 2, 20)\n    else:\n        report_anomalies(\"Unusual gditimers.\", unusual_gditimers, \"=\", \"gditimers\", 2, 20)\n    # Suspicious 'unknown' callbacks:\n    unknown_callbacks = anomaly_search(\"callbacks\", \"UNKNOWN\", 'yes')\n    report_anomalies(\"Suspicious 'unknown' callbacks.\", unknown_callbacks, \"=\", \"callbacks\", 2)\n    # Suspicious 'unknown' drivermodules:\n    unknown_drivermodules = anomaly_search(\"drivermodule\", \"UNKNOWN\", 'yes')\n    report_anomalies(\"Suspicious 'unknown' drivermodules.\", unknown_drivermodules, \"=\", \"drivermodule\", 2, 20)\n    # Suspicious 'unknown' driverirp entries:\n    unknown_driverirp = anomaly_search(\"driverirp\", \"UNKNOWN\", 'yes')\n    report_anomalies(\"Suspicious 'unknown' driverirp entries.\", unknown_driverirp, \"=\", \"\", 0, 20)\n    # Unusual ssdt entries:\n    unusual_ssdt = anomaly_search_inverted(\"ssdt\", usual_ssdt, 'yes', \"Entry\")\n    report_anomalies(\"Unusual ssdt entries.\", unusual_ssdt, \"=\", \"\", 0, 20)\n    # Suspicious idt entries:\n    susp_idt = anomaly_search(\"idt\", \"rsrc\", 'yes')\n    report_anomalies(\"Suspicious idt entries.\", susp_idt, \"=\", \"idt\", 2)\n    # Suspicious orphan threads:\n    orphan_threads = anomaly_search(\"threads\", \".*\", 'yes')\n    if mode == \"standalone\":\n        report_anomalies(\"Suspicious orphan threads.\", orphan_threads[2:])\n    else:\n        report_anomalies(\"Suspicious orphan threads.\", orphan_threads)\n\n    # IMPSCAN AND PROCDUMP EXECUTION (IN PREPERATION FOR PROCESS PROFILER) ================================================================\n    # run impscan plugin in //\n    impscanfolder = tmpfolder + \"impscan/\"\n    if not os.path.isdir(impscanfolder):\n        os.makedirs(impscanfolder)\n    else:\n        shutil.rmtree(impscanfolder)\n        os.makedirs(impscanfolder)\n    plugin = \"impscan\"\n    i = 0\n    subprocesses = {}\n    for pid in pids_to_analyse:\n        if mode == \"dual\":\n            with open(impscanfolder + str(pid) + \".txt\", \"w\") as f:\n                subprocesses[str(pid)] = Popen([path_to_volatility, \"--profile\", profile, \"-f\", infected_memory_image, plugin, \"--pid=\" + str(pid)], stdout=f, stderr=devnull)\n        else:\n            with open(impscanfolder + str(pid) + \".txt\", \"w\") as f:\n                subprocesses[str(pid)] = Popen([path_to_volatility, \"--profile\", profile, \"-f\", memory_image, plugin, \"--pid=\" + str(pid)], stdout=f, stderr=devnull)\n        i += 1\n        if i >= max_concurrent_subprocesses:\n            for subproc in subprocesses:\n                subprocesses[subproc].wait()\n            i = 0\n            subprocesses = {}\n    for subproc in subprocesses:\n        subprocesses[subproc].wait()\n\n    # dump suspicious processes to disk in //\n    subprocesses = {}\n    i = 0\n    for pid in pids_to_analyse:\n        procname = get_procname(pid)\n        dumpfolder = tmpfolder + str(pid) + \"/\"\n        if not os.path.isdir(dumpfolder):\n            os.makedirs(dumpfolder)\n        else:\n            shutil.rmtree(dumpfolder)\n            os.makedirs(dumpfolder)\n        offsets = []\n        if procname != \"\":\n            f = open_full_plugin(\"psscan\", 2)\n            for line in f:\n                if re.search(procname + \" +\" + str(pid) + \" \", line, re.IGNORECASE):\n                    offsets.append(re.sub(' +', ' ', line).split(' ')[0])\n            f.close()\n        for offset in offsets:\n            if mode == \"dual\":\n                subprocesses[offset] = Popen([path_to_volatility, \"--profile\", profile, \"-f\", infected_memory_image, \"procdump\", \"--offset=\" + offset, \"--dump-dir=\" + dumpfolder], stdout=devnull, stderr=devnull)\n            else:\n                subprocesses[offset] = Popen([path_to_volatility, \"--profile\", profile, \"-f\", memory_image, \"procdump\", \"--offset=\" + offset, \"--dump-dir=\" + dumpfolder], stdout=devnull, stderr=devnull)\n            i += 1\n            if i >= max_concurrent_subprocesses:\n                for subproc in subprocesses:\n                    subprocesses[subproc].wait()\n                i = 0\n                subprocesses = {}\n        if mode == \"dual\":\n            subprocesses[str(pid)] = Popen([path_to_volatility, \"--profile\", profile, \"-f\", infected_memory_image, \"malfind\", \"--pid=\" + str(pid), \"--dump-dir=\" + dumpfolder], stdout=devnull, stderr=devnull)\n        else:\n            subprocesses[str(pid)] = Popen([path_to_volatility, \"--profile\", profile, \"-f\", memory_image, \"malfind\", \"--pid=\" + str(pid), \"--dump-dir=\" + dumpfolder], stdout=devnull, stderr=devnull)\n        i += 1\n        if i >= max_concurrent_subprocesses:\n            for subproc in subprocesses:\n                subprocesses[subproc].wait()\n            i = 0\n            subprocesses = {}\n    for subproc in subprocesses:\n        subprocesses[subproc].wait()\n\n    # DEV MODE SWITCH ================================================================\n    if \"--devmode\" in sys.argv:\n        raw_input('\\nCheckpoint before executing process profiler.')\n\n    # MALWARE CHECKS - PROCESS PROFILER ================================================================\n    # dispay list of processes that will be analysed\n    if len(pids_to_analyse) > 0:\n        report.write(\"\\n\\nProcesses that will be analysed in the next section:\")\n        report.write(\n            \"\\n==========================================================================================================================\\n\")\n        for pid in pids_to_analyse:\n            report.write(get_procname(pid) + \" (\" + str(pid) + \"): \" + pids_to_analyse[pid] + \".\\n\")\n        l = get_associated_process_lines_pids(pids_to_analyse, \"psscan\")\n        report_anomalies(\"Psscan output for suspicious processes.\", l, \"-\", \"psscan\", 2)\n\n    for pid in pids_to_analyse:\n        procname = get_procname(pid)\n        report.write(\"\\n\\nAnalysis results for \" + procname + \" PID \" + pid + \" (\" + pids_to_analyse[pid] + \"):\")\n        report.write(\n            \"\\n==========================================================================================================================\")\n        # print VirusTotal scan results of exec MD5 hash\n        if vt_api_key != \"\":\n            susp_md5 = get_md5(pid)\n            if susp_md5 != \"\":\n                report_virustotal_md5_results(susp_md5, vt_api_key)\n        # print psxview output for the process (psxview)\n        l = get_associated_process_lines_pids([pid, ], \"psxview\")\n        report_anomalies(\"Psxview results:\", l, '-', \"psxview\", 2)\n        # print comand line (cmdline)\n        cmdline = get_cmdline(pid)\n        report_anomalies(\"Command line (cmdline):\", cmdline, '-')\n        # analyse network connections (netscan)\n        susp_connections = anomaly_search(\"netscan\", \" \" + str(pid), \"yes\", \"\", \"diff\")\n        report_anomalies(\"Network connections (netscan):\", susp_connections, '-', \"netscan\", 1)\n        # print parent process information\n        if len(get_parent_pids_of([pid, ])) > 0:\n            ppid = get_parent_pids_of([pid, ])[0]\n            pids = get_all_pids()\n            if ppid not in pids:\n                l = get_associated_process_lines_ppids([ppid, ])\n                report_anomalies(\"Parent process (PPID \" + ppid + \") is not listed in psscan output:\", l, '-', \"psscan\",\n                                 2)\n            else:\n                l = get_associated_process_lines_pids([ppid, ])\n                j = get_associated_process_lines_pids([pid, ])\n                report_anomalies(\"Parent process (PPID \" + ppid + \") information:\", j + l, '-', \"psscan\", 2)\n        # check if process has an \"expected\" parent\n        check_expected_parent(pid)\n        # print child process information\n        childs = get_childs_of([pid, ])\n        l = get_associated_process_lines_pids(childs)\n        report_anomalies(\"Child process(es):\", l, '-', \"psscan\", 2)\n        # print malfind injections (malfind)\n        malfind_injections = get_malfind_injections(pid, mode)\n        report_anomalies(\"Code injection (malfind):\", malfind_injections, '-')\n        # print associated services (svcscan)\n        susp_services = get_associated_services(pid)\n        report_anomalies(\"Associated service(s) (svcscan):\", susp_services, '-')\n        # print envars (envars)\n        associated_envars = anomaly_search(\"envars\", \" \" + str(pid) + \" \", \"yes\", \"\", \"diff\")\n        report_anomalies(\"Environment variables (envars):\", associated_envars, '-', \"envars\", 2)\n        # print interesting DLLs (ldrmodules)\n        dlls1 = anomaly_search(\"ldrmodules\", hacker_dll_regex, 'yes', \"\", \"diff\")\n        dlls2 = anomaly_search(\"ldrmodules\", \"no name\", 'yes', \"\", \"diff\")\n        dlls3 = anomaly_search(\"ldrmodules\", \"False  False  False.*dll$|False  False  False.*exe$\", 'yes', ldrmodules_excluded_regex_1, \"diff\")\n        dlls4 = anomaly_search(\"ldrmodules\", \"False\", 'yes', ldrmodules_excluded_regex_2, \"diff\")\n        dlls = sorted(set(dlls1 + dlls2 + dlls3 + dlls4))\n        dlls_to_report = []\n        for dll in dlls:\n            if re.search(\" \" + str(pid) + \" \", dll, re.IGNORECASE):\n                dlls_to_report.append(dll)\n        report_anomalies(\"Interesting DLLs (ldrmodules):\", dlls_to_report, '-', \"ldrmodules\", 2)\n        # print mutants (handles) DUAL ONLY\n        if mode == \"dual\":\n            mutants = anomaly_search(\"handles\", \" \" + str(pid) + \" .*Mutant\", \"yes\", \"\", \"diff\")\n            report_anomalies(\"Mutants accessed (handles):\", mutants, '-', \"handles\", 2)\n        # print interesting files accessed (handles)\n        files1 = anomaly_search(\"handles\", \" \" + str(pid) + \" .*\\\\\\Device\\\\\\RawIp\", 'yes', '', \"diff\")\n        files2 = anomaly_search(\"handles\", \" \" + str(pid) + \" .*Device\\\\\\(LanmanRedirector|Mup)\", 'yes', '', \"diff\")\n        files3 = anomaly_search(\"handles\", \" \" + str(pid) + \" .*\\..{2,3}$\", 'yes', \"\\.mui$\", \"diff\")\n        files_to_report = []\n        filelist = sorted(set(files1 + files2 + files3))\n        for i in filelist:\n            if re.search(\"File\", i, re.IGNORECASE):\n                files_to_report.append(i)\n        report_anomalies(\"Interesting files accessed (handles):\", files_to_report, '-', \"handles\", 2)\n        # print privileges (privs)\n        privs = anomaly_search(\"privs\", \" \" + str(pid) + \" \", \"yes\", \"\", \"diff\")\n        report_anomalies(\"Enabled privileges (privs):\", privs, '-', \"privs\", 2)\n        # print high privileges (getsids)\n        sids = anomaly_search(\"getsids\", \"\\(\" + str(pid) + \"\\).*(Domain Admin|Enterprise Admin|Schema Admin)\", \"yes\", \"\", \"diff\")\n        report_anomalies(\"Process privileges (getsids):\", sids, '-')\n        # check if process has a raw socket handle:\n        raw_sockets = get_raw_sockets(pid)\n        report_anomalies(\"Raw socket handles:\", raw_sockets, \"-\", \"handles\", 2)\n        # check if process has a handle to a remote mapped share:\n        share_handles = get_remote_share_handles(pid)\n        report_anomalies(\"Remote share handles:\", share_handles, \"-\", \"handles\", 2)\n        # print handles to interesting registry entries (handles)\n        if get_procname(pid) != 'explorer.exe':\n            analyse_registry(pid)\n        # print interesting imports (impscan)\n        if get_procname(pid) != 'explorer.exe':\n            analyse_imports(pid)\n        # find suspicious strings in process strings (procdump + malfind + strings)\n        analyse_strings(pid)\n\n    # CLEANUP AND CLOSURE ================================================================\n    script_completion(starttime)\n\n\nif __name__ == '__main__':\n    main()\n"
  }
]