#!/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)
