133 lines
4.7 KiB
Python
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)
|