From c1067b02586138cc758da75da9407dda7c2cf49c Mon Sep 17 00:00:00 2001 From: Eric Conrad Date: Wed, 20 Sep 2017 08:42:56 -0400 Subject: [PATCH] First release of DeepBlue.py --- DeepBlue.py | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 DeepBlue.py diff --git a/DeepBlue.py b/DeepBlue.py new file mode 100644 index 0000000..f69ad34 --- /dev/null +++ b/DeepBlue.py @@ -0,0 +1,129 @@ +#!/usr/bin/python + +# DeepBlue.py Alpha 0.1 (pre-DerbyCon release) +# Eric Conrad +# Twitter: @eric_conrad +# http://ericconrad.com +# deepblue at backshore dot net + +# Currently alpha level functionality, supports CLI parsing only +# More features to come + +# Requires libevtx: https://github.com/libyal/libevtx + +import sys +import re +import csv +import base64 +import os.path +import string +from subprocess import Popen, PIPE + +def filter(str): + # Used to convert base64 decoded data (unicode) to ASCII + return ''.join([c for c in str if ord(c) > 31 or ord(c) == 9]) + +def CheckRegex(regexes,command): + string="" + for regex in regexes: + if re.search(regex[1],command,re.IGNORECASE): + string+=" - "+regex[2]+"\n" + return(string) + +def CheckObfu(cli,minpercent): + string="" + noalphastring =re.sub("[A-Za-z0-9]","",cli) + length1=float(len(cli)) + length2=float(len(noalphastring)) + if ((length1/100) < minpercent): + minpercent=length1/100 # Shorter strings get lower minpercent, based on the string length + percent =((length1-length2)/length1) + if (percent < minpercent): + percent=(round(percent,2)) + string += " - Potential command obfuscation: "+str(percent)+"% alpha characters" + return(string) + +def CheckCommand(time, log, eventid, cli): + minpercent=.65 + string="" + decoded="" + noalphastring="" + string=CheckRegex(regexes,cli) + if re.search("\-enc.*[A-Za-z0-9/+=]{100}",cli,re.IGNORECASE): + b64=re.sub("^.* \-Enc(odedCommand)? ","",cli,re.IGNORECASE) + decoded=base64.b64decode(b64) + decoded=str(filter(decoded)) # Convert base64 to ASCII + string+=CheckRegex(regexes,decoded) + string += CheckObfu(cli,minpercent) + if(string): + print "Date: %s\nLog: %s\nEventID: %s" % (time,log,eventid) + print "Results:\n%s\n" % (string.rstrip()) + print "Command: %s\n" % (cli) + if(decoded): + print "Decoded: %s" % (decoded) + if(string): + print "\n" + +filename="" +regexfile="regexes.txt" +regexes=[] +if len(sys.argv)==2: + if os.path.isfile(sys.argv[1]): + filename=sys.argv[1] + if os.path.isfile(regexfile): + with open(regexfile) as csvfile: + reader = csv.reader(csvfile, delimiter=',') + for row in reader: + if not row[0].startswith('#'): + regexes.append(row) + else: + print "Error: cannot open "+regexfile+"\n" + else: + print "Error: no such file: %s\n" % (sys.argv) +else: + print "Error: filename required as an argument\n" + +if (filename and regexes): + process="" + try: + process = Popen(['evtxexport', filename], stdout=PIPE, stderr=PIPE) + except: + print 'Can\'t find libevtx. Check the path and verify it is installed. See: https://github.com/libyal/libevtx' + + if (process): + time="" + log="" + eventid="" + cli="" + path="" + for line in iter(process.stdout.readline,''): + if re.search("^Written time",line): + #Written time : Aug 30, 2017 19:16:26.133985000 UTC + time = re.sub("^.*: ","",line) + time = time[:21] + elif re.search("^Source name",line): + log = re.sub("^.*: ","",line).rstrip() + elif re.search("^Event identifier",line): + # Looks like this, grab the number between the parentheses: + #Event identifier : 0x00001008 (4104) + #Event identifier : 0x00000001 (1) + eventid = re.sub("^.*\(","",line.rstrip()) + eventid = re.sub("\).*$","",eventid) + elif re.search("^String: 3",line): + #Source name : Microsoft-Windows-PowerShell + if log=="Microsoft-Windows-PowerShell": + cli = line[14:].rstrip() + elif re.search("^String: 5",line): + if log=="Microsoft-Windows-PowerShell": + path = line[14:].rstrip() + elif log=="Microsoft-Windows-Sysmon": + cli = line[14:].rstrip() + elif re.search("^String: 9",line): + if log=="Microsoft-Windows-Security-Auditing": + cli = line[14:].rstrip() + elif re.search("^$",line): + # 4688: CLI via System log + # 4104: PowerShell CLI if path is blank (non-blank path == PowerShell script) + # 1: Sysmon CLI + if ((eventid=="4688")or(eventid=="1")or((eventid=="4104")and(path==""))): + CheckCommand(time,log,eventid,cli)