#-----------------------------------------------------------
# malware.pl
#
# This plugin is essentially a 'container' for a lot of other individual
#  plugins, running the queries against any hive.
#
# References:
#  <included inline>
#
# Change history:
#  20161210 - added WebRoot check
#  20160615 - added new Sofacy persistence
#  20160412 - added Ramdo checks
#  20160217 - added check for Locky ransomware
#  20160127 - added Helminth entry
#  20151203 - added DCOM port config detection
#  20151013 - added Warood.B
#  20151012 - 9002 ref/checks added
#  20151008 - added keys
#  20150828 - created
#
# copyright 2015 Quantum Analytics Research, LLC
# Author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package malware;
use strict;

my %config = (hive          => "All",
              hasShortDescr => 1,
              hasDescr      => 0,
              hasRefs       => 0,
              osmask        => 22,
              category      => "malware",
              version       => 20161210);

sub getConfig{return %config}
sub getShortDescr {
	return "Checks for malware-related keys/values";	
}
sub getDescr{}
sub getRefs {}
sub getHive {return $config{hive};}
sub getVersion {return $config{version};}

my $VERSION = getVersion();

sub pluginmain {
	my $class = shift;
	my $hive = shift;
	::logMsg("Launching malware v.".$VERSION);
	::rptMsg("malware v.".$VERSION); # banner
  ::rptMsg("(".getHive().") ".getShortDescr()."\n"); # banner
	my $reg = Parse::Win32Registry->new($hive);
	my $root_key = $reg->get_root_key;
	my $key_path;
	my $key;

# Security Hive
# This is the same code as the secrets.pl plugin - provides an indication
# regarding the use of GSecDump on systems; see "The Art of Memory Forensics",
# 

	eval {
		$key_path = "Policy\\Secrets";
		$key;
		if ($key = $root_key->get_subkey($key_path)) {
			::rptMsg($key_path);
			::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
			::rptMsg("");
		}
	};


# System Hive
# First, need to get the value for the CurrentControlSet
	my $ccs;
	my $current;
	eval {
		if ($key = $root_key->get_subkey("Select")) {
			$current = $key->get_value("Current")->get_data();
			$ccs = "ControlSet00".$current;
		}
	};
	
# If we've got a populated $ccs value, other checks will now likely work	
# Look for known/observed PlugX services
	my @services = ("RasTLS","Macfee MC","usta","emproxy","mproxysvr3","gzQkNtWeabrwf","brwTRsulGqj","sock5proxy");
	eval {
		foreach my $svc (@services) {
			if ($key = $root_key->get_subkey($ccs."\\services\\".$svc)) {
				::rptMsg("Possible PlugX variant found in ".$svc." service");
				
				eval {
					::rptMsg("  ImagePath  : ".$key->get_value("ImagePath")->get_data());
				};
				
				eval {
					::rptMsg("  Description: ".$key->get_value("Description")->get_data());
				};
				
			}
		}
	}; 
	

# Software Hive

# Check for several PlugX variants
# http://www.symantec.com/security_response/earthlink_writeup.jsp?docid=2013-112101-0135-99
# http://www.trendmicro.com/vinfo/us/threat-encyclopedia/malware/PLUGX
	eval {
		$key_path = "Classes\\FAST";
		if ($key = $root_key->get_subkey($key_path)) {
			::rptMsg("Possible PlugX variant (".$key_path.") found.");
			::rptMsg("  LastWrite time: ".gmtime($key->get_timestamp()));
		}
	};
	
	eval {
		$key_path = "Classes\\XXXX";
		if ($key = $root_key->get_subkey($key_path)) {
			::rptMsg("Possible PlugX variant (".$key_path.") found.");
			::rptMsg("  LastWrite time: ".gmtime($key->get_timestamp()));
		}
	};
	
	eval {
		$key_path = "BINARY";
		if ($key = $root_key->get_subkey($key_path)) {
			::rptMsg("Possible PlugX variant (".$key_path.") found.");
			::rptMsg("  LastWrite time: ".gmtime($key->get_timestamp()));
			if ($key->get_value("SXLOC\.ZAP")) {
				::rptMsg("Value SXLOC\.ZAP found.");
			}
		}
	};

# https://www.sophos.com/en-us/threat-center/threat-analyses/viruses-and-spyware/Troj~DwnLdr-GWF/detailed-analysis.aspx
  eval {
		$key_path = "Begin";
		if ($key = $root_key->get_subkey($key_path)) {
			::rptMsg("Possible Downloader variant (".$key_path.") found.");
			::rptMsg("  LastWrite time: ".gmtime($key->get_timestamp()));
		}
	};


# check Classes\Network\SharingHandler default value for modification
# in most cases, it's "ntshrui.dll"
# http://www.trendmicro.com/vinfo/us/threat-encyclopedia/malware/worm_cosmu.elg
	eval { 
		$key_path = "Classes\\Network\\SharingHandler";
		if ($key = $root_key->get_subkey($key_path)) {
			::rptMsg($key_path);
			::rptMsg("  LastWrite Time : ".gmtime($key->get_timestamp())." (UTC)");
			::rptMsg("  (Default) value: ".$key->get_value("")->get_data());
			::rptMsg("If the (Default) value is not ntshrui\.dll, there may be an infection.");
		}
		::rptMsg("");
	};
	
# Poison Ivy variant
# http://blog.jpcert.or.jp/2015/07/poisonivy-adapts-to-communicate-through-authentication-proxies.html
	eval {
		$key_path = "Classes\\BJ\\Static";
		if ($key = $root_key->get_subkey($key_path)) {
			::rptMsg($key_path);
			::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
			if ($key->get_value("MessageFile")) {
				::rptMsg("MessageFile value found.");
			}
			::rptMsg("");
		}
	};

# Warood.A
# https://www.microsoft.com/security/portal/threat/encyclopedia/entry.aspx?Name=Backdoor:Win32/Warood.A#tab=2
  eval {
		$key_path = "Clients\\Netrau";
		if ($key = $root_key->get_subkey($key_path)) {
			::rptMsg($key_path);
			::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
			if ($key->get_value("HostGUID") || $key->get_value("InstallTime")) {
				::rptMsg("Warood.A value(s) found.");
			}
			::rptMsg("");
		}
	};

# Warood.B	
# https://www.microsoft.com/security/portal/threat/encyclopedia/entry.aspx?Name=Backdoor:Win32/Warood.B#tab=2
  eval {
		$key_path = "Clients\\sdata";
		if ($key = $root_key->get_subkey($key_path)) {
			::rptMsg($key_path);
			::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
			if ($key->get_value("sdata")) {
				::rptMsg("sdata value found.");
			}
			::rptMsg("");
		}
	};

# From FireEye APT30 report, ShipShape malware
  eval {
		$key_path = "Microsoft\\ShipUp";
		if ($key = $root_key->get_subkey($key_path)) {
			::rptMsg("Possible ShipShape malware found: ".$key_path);
			::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
			if ($key->get_value("lnk")) {
				::rptMsg("lnk value found.");
			}
			::rptMsg("");
		}
	};

# From FireEye APT30 report, SpaceShip malware
  eval {
		$key_path = "Microsoft\\ShipTr";
		if ($key = $root_key->get_subkey($key_path)) {
			::rptMsg("Possible SpaceShip malware found: ".$key_path);
			::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
			if ($key->get_value("lnk")) {
				::rptMsg("lnk value found.");
			}
			::rptMsg("");
		}
	};
	
# From MIRCon 2014 presentation on WMI
# HKLM/Software/Microsoft/WBEM/ESS///./root/CIMV2/Win32ClockProvider 
# $$$PROTO.HIV\Microsoft\WBEM\ESS\//./root/CIMV2\Win32ClockProvider
  eval {
		$key_path = "Microsoft\\WBEM\\ESS\\//./root/CIMV2\\Win32ClockProvider";
		if ($key = $root_key->get_subkey($key_path)) {
			::rptMsg($key_path);
			::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
			::rptMsg("Possible use of WMI time trigger found.");
			::rptMsg("");
		}
	};	
	
	
# Bledoor/RbDoor - added 20151117
# https://www.microsoft.com/security/portal/threat/encyclopedia/entry.aspx?Name=Trojan:Win64/Bledoor.A#tab=2	
	eval {
		$key_path = "Microsoft\\HTMLHelp";
		if ($key = $root_key->get_subkey($key_path)) {	
			if ($key->get_value("data")) {
				::rptMsg("Possible BleDoor/Rbdoor malware found: ".$key_path);
				::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
				::rptMsg("data value found: ".$key->get_value("data")->get_value());
			}
			::rptMsg("");
		}
	};

# Detect DCOM port change
# https://www.blackhat.com/docs/us-15/materials/us-15-Graeber-Abusing-Windows-Management
#    -Instrumentation-WMI-To-Build-A-Persistent%20Asynchronous-And-Fileless-Backdoor-wp.pdf	
# http://blog.backslasher.net/setting-dynamic-rpc-port-ranges.html
	eval {
		$key_path = "Microsoft\\Rpc\\Internet";
		if ($key = $root_key->get_subkey($key_path)) {	
			if ($key->get_value("Ports")) {
				::rptMsg("Possible DCOM port config change found: ".$key_path);
				::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
				::rptMsg("Ports value: ".$key->get_value("Ports")->get_value());
			}
			::rptMsg("");
		}
	};
	
# WebRoot Threat checks
	eval {
		$key_path = "WRData\\Threats\\History";
		if ($key = $root_key->get_subkey($key_path)) {	
			my @vals = $key->get_list_of_values();
			if (scalar @vals > 0) {
				::rptMsg($key_path);
				::rptMsg("LastWrite Time : ".gmtime($key->get_timestamp())." UTC");
				foreach my $v (@vals) {
					::rptMsg($v->get_name()." - ".$v->get_data());
				}
			}
			else {
				::rptMsg($key_path." has no values.");
			}
			::rptMsg("");
		}
	};	
	eval {
		$key_path = "Wow6432Node\\WRData\\Threats\\History";
		if ($key = $root_key->get_subkey($key_path)) {	
			my @vals = $key->get_list_of_values();
			if (scalar @vals > 0) {
				::rptMsg($key_path);
				::rptMsg("LastWrite Time : ".gmtime($key->get_timestamp())." UTC");
				foreach my $v (@vals) {
					::rptMsg($v->get_name()." - ".$v->get_data());
				}
			}
			else {
				::rptMsg($key_path." has no values.");
			}
			::rptMsg("");
		}
	};
	
# NTUSER.DAT/USRCLASS.DAT		

# Possible PlugX
# http://www.symantec.com/security_response/earthlink_writeup.jsp?docid=2013-112101-0135-99
	eval {
		$key_path = "Software\\BINARY";
		if ($key = $root_key->get_subkey($key_path)) {
			::rptMsg("Possible PlugX variant (".$key_path.") found.");
			::rptMsg("  LastWrite time: ".gmtime($key->get_timestamp()));
			if ($key->get_value("SXLOC\.ZAP")) {
				::rptMsg("Value SXLOC\.ZAP found.");
			}
		}
	};
	
# Nflog, et al.
# http://www.microsoft.com/security/portal/threat/encyclopedia/entry.aspx?name=TROJAN:WIN32/NFLOG.A#tab=2
# https://www.sophos.com/en-us/threat-center/threat-analyses/viruses-and-spyware/Troj~DwnLdr-GWF/detailed-analysis.aspx	
	eval {
		$key_path = "Software\\Microsoft\\Clock";
		if ($key = $root_key->get_subkey($key_path)) {
			::rptMsg("Possible Nflog variant (".$key_path.") found.");
			::rptMsg("  LastWrite time: ".gmtime($key->get_timestamp()));
			if ($key->get_value("HID")) {
				::rptMsg("Value HID found: ".$key->get_value("HID")->get_data());
			}
		}
	};

# 9002 RAT
# http://researchcenter.paloaltonetworks.com/2015/09/chinese-actors-use-3102-malware-in-attacks-on-us-government-and-eu-media/
# http://blog.cylance.com/another-9002-trojan-variant
	eval {
		$key_path = "Software\\TransPan";
		if ($key = $root_key->get_subkey($key_path)) {
			::rptMsg("Possible 9002 RAT variant (".$key_path.") found.");
			::rptMsg("  LastWrite time: ".gmtime($key->get_timestamp()));
			if ($key->get_value("RunPath") || $key->get_value("mshtm")) {
				::rptMsg("  Possible 9002 config value(s) found.");
			}
		}
	};
	
# From FireEye report on APT30/BackSpace RAT
	eval {
		$key_path = "Software\\Microsoft\\CurrentHalInf";
		if ($key = $root_key->get_subkey($key_path)) {
			::rptMsg("Possible BACKSPACE RAT variant (".$key_path.") found.");
			::rptMsg("  LastWrite time: ".gmtime($key->get_timestamp()));
			if ($key->get_value("hFlag")) {
				::rptMsg("  Possible hFlag value found: ".$key->get_value("hFlag")->get_data());
			}
		}
	};	
	
	eval {
		$key_path = "Software\\Microsoft\\CurrentPnpSetup";
		if ($key = $root_key->get_subkey($key_path)) {
			::rptMsg("Possible BACKSPACE RAT variant (".$key_path.") found.");
			::rptMsg("  LastWrite time: ".gmtime($key->get_timestamp()));
			if ($key->get_value("lnk") || $key->get_value("hostid")) {
				::rptMsg("  Possible BACKSPACE value(s) found.");
			}
		}
	};	

# TEST - this addition was derived from malware write-ups, which may not be correct
# Helminth	
# http://www.threatexpert.com/report.aspx?md5=3448c57a2dfc824098fca500478ab405
# http://www.trendmicro.no/vinfo/no/threat-encyclopedia/malware/troj_battoexe.dv
	eval {
		$key_path = "Software\\Microsoft\\Wbem\\WMIC";
		if ($key = $root_key->get_subkey($key_path)) {
			::rptMsg("  LastWrite time: ".gmtime($key->get_timestamp()));
			if ($key->get_value("WMICLC")) {
				::rptMsg(sprintf "  WMICLC: 0x%x",$key->get_value("WMICLC")->get_data());
			}
			
			if ($key->get_value("mofcompMUIStatus")) {
				::rptMsg(sprintf "  mofcompMUIStatus: 0x%x",$key->get_value("mofcompMUIStatus")->get_data());
			}
		}
	};	

# https://www.carbonblack.com/2016/01/31/tackling-latentbot-look-big-picture-not-just-individual-functions/
  eval {
		$key_path = "Software\\Google\\Update\\network\\secure";
		if ($key = $root_key->get_subkey($key_path)) {
			if ($key->get_value("0")) {
				::rptMsg("  LastWrite time: ".gmtime($key->get_timestamp()));
				::rptMsg("  Possible LatentBot malware located.");
				::rptMsg(sprintf "  0: 0x%x",$key->get_value("0")->get_data());
			}
			
			if ($key->get_value("1")) {
				::rptMsg(sprintf "  1: 0x%x",$key->get_value("1")->get_data());
			}
		}
	};
# Locky check
# http://www.bleepingcomputer.com/news/security/the-locky-ransomware-encrypts-local-files-and-unmapped-network-shares/
  eval {
		$key_path = "Software\\Locky";
		if ($key = $root_key->get_subkey($key_path)) {
			::rptMsg("  LastWrite time: ".gmtime($key->get_timestamp()));
			if ($key->get_value("id")) {
				::rptMsg("  Possible Locky ransomware located.");
				::rptMsg("  Value 'id': ".$key->get_value("id")->get_data());
			}
		}
	};
	
# Ramdo checks, added 20160412
# https://blogs.technet.microsoft.com/mmpc/2014/04/02/msrt-april-2014-ramdo/
# https://www.symantec.com/security_response/writeup.jsp?docid=2014-021912-3653-99&tabid=2
  eval {
		my @val_names = ("tLast_ReadedSpec", "tLastCollab_doc");
		$key_path = "Software\\Adobe\\Adobe ARM\\1.0\\ARM";
		if ($key = $root_key->get_subkey($key_path)) {
			foreach my $val (@val_names) {
				if (my $v = $key->get_value($val)) {
					::rptMsg("Possible Ramdo value found.");
					::rptMsg("  ".$val." = ".$v->get_data());
				}
			}
		}
	};	
	
	eval {
		my @versions = ("9.0", "10.0","11.0","12.0","13.0");
		my @val_names = ("iTestPropulsion", "iTestShears");
		foreach my $version (@versions) { 
			$key_path = "Software\\Adobe\\Adobe Reader\\".$version."\\IPM";
			if ($key = $root_key->get_subkey($key_path)) {
				foreach my $val (@val_names) {
					if (my $v = $key->get_value($val)) {
						::rptMsg("Possible Ramdo value found: ".$val." = ".$v->get_data());
					}
				}
			}
		}
	};
	
	eval {
		$key_path = "Software\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION";
		if ($key = $root_key->get_subkey($key_path)) {
			if ($key->get_value("twunk_32.exe")->get_data() == 9000) {
				::rptMsg("Possible Ramdo value found: twunk_32.exe = 9000");
			}
			
			if ($key->get_value("winhlp32.exe")->get_data() == 9000) {
				::rptMsg("Possible Ramdo value found: winhlp32.exe = 9000");
			}
			
		}
	};
	
# Sofacy
# http://researchcenter.paloaltonetworks.com/2016/06/unit42-new-sofacy-attacks-against-us-government-agency/
# http://www.trendmicro.com/vinfo/us/threat-encyclopedia/malware/troj_cve20151641.bzd
# http://www.hexacorn.com/blog/2014/04/16/beyond-good-ol-run-key-part-10/
	eval {
		$key_path = "Software\\Microsoft\\Office test\\Special\\Perf";
		if ($key = $root_key->get_subkey($key_path)) {
			my $bte;
			if ($bte = $key->get_value("")->get_data()) {
				::rptMsg("Possible Sofacy value found: ".$bte);
				::rptMsg("**Be sure to examine the ".$bte." file\.");
			}
		}
	};	
	
}
1;