Files
DeepBlueCLI/DeepBlue.py
2017-11-07 12:28:21 -05:00

133 lines
4.7 KiB
Python

#!/usr/bin/python
# DeepBlue.py Alpha 0.12 (post-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 (regex[0] == "0"):
if re.search(regex[1],command,re.IGNORECASE):
string+=" - "+regex[2]+"\n"
return(string)
def CheckObfu(cli,minpercent,minlength):
string=""
noalphastring=re.sub("[A-Za-z0-9]","",cli)
length1=float(len(cli))
if (length1 > minlength):
length2=float(len(noalphastring))
if ((length1/150) < minpercent):
minpercent=length1/150 # Shorter strings get lower minpercent, based on the string length
percent =((length1-length2)/length1)
if (percent < minpercent):
percent=(round(percent,2))*100
string += " - Potential command obfuscation: "+str(int(percent))+"% alpha characters"
return(string)
def CheckCommand(time, log, eventid, cli):
minpercent=.65
minlength=25 # Minimum CLI length to check for obfuscation
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,minlength)
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)