From cf2de849a35617c97b5861c2afec90026b24c585 Mon Sep 17 00:00:00 2001 From: Imanol-Mikel Barba Sabariego Date: Thu, 27 Oct 2016 10:56:16 +0200 Subject: [PATCH] Added logging. Added better error handling and displaying. Implemented evt module --- digger.py | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------------- logger/consolelogger.py | 25 +++++++++++++++++++++++++ logger/filelogger.py | 34 ++++++++++++++++++++++++++++++++++ logger/logger.py | 8 ++++++++ logger/logsystem.py | 12 ++++++++++++ module.py | 19 ------------------- modules/evt.py | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ modules/info.py | 8 +++++--- modules/mft.py | 10 +++++++--- modules/module.py | 22 ++++++++++++++++++++++ modules/winreg.py | 20 +++++++++++++++----- modulevar.py | 16 ---------------- vars/__init__.py | 0 vars/modulevar.py | 19 +++++++++++++++++++ vars/ntfsvol.py | 6 ++++-- vars/winvol.py | 8 ++++++-- 16 files changed, 281 insertions(+), 88 deletions(-) create mode 100644 logger/consolelogger.py create mode 100644 logger/filelogger.py create mode 100644 logger/logger.py create mode 100644 logger/logsystem.py delete mode 100644 module.py create mode 100644 modules/evt.py create mode 100644 modules/module.py delete mode 100644 modulevar.py create mode 100644 vars/__init__.py create mode 100644 vars/modulevar.py diff --git a/digger.py b/digger.py index 43175d8..1f65f0d 100644 --- a/digger.py +++ b/digger.py @@ -1,16 +1,21 @@ #! /usr/bin/env python3 +import sys + +sys.path.append('modules') +sys.path.append('vars') +sys.path.append('logger') + import locale from dialog import Dialog import glob import os -import sys import subprocess as sp import tomb import traceback - -sys.path.append('modules') -sys.path.append('vars') +import logger +from consolelogger import ConsoleLogger +from filelogger import FileLogger def getModules(): choiceList = [] @@ -37,52 +42,80 @@ def prepareModule(moduleName): module.getVars() return module except Exception as e: - raise Exception("[" + moduleName + "] " + str(e)) - -locale.setlocale(locale.LC_ALL, '') -d = Dialog(dialog="dialog",autowidgetsize=True) -d.set_background_title("Gravedigger") - -moduleList = getModules() -code,value = d.inputbox("Input computer's name") -if code == d.OK: - tomb._MACHINE_NAME= value - d.set_background_title("Gravedigger - " + value) - code, tags = d.checklist("Select modules to execute", - choices=moduleList + [("all","Execute all modules",False)], - title="Module selection") + raise + +def showFinishDialog(allSuccessful): + msg = "" + if(allSuccessful): + msg = "All modules finished execution" + else: + msg = "Some or all modules failed execution. Please check the logs." + + code, tag = d.menu(msg, choices=[("Poweroff", "Shutdown the computer"), + ("Reboot", "Reboot the computer"), + ("Restart", "Run Gravedigger again")]) + if (code == d.OK): + if tag == "Poweroff": + sp.call("poweroff", shell=True) + elif tag == "Reboot": + sp.call("reboot", shell=True) + + exit(0) + +def showContinueDialog(d,msg): + ans = d.yesno(msg + "\n\nDo you want to continue execution without the module?") + return ans == d.OK + +if __name__ == "__main__": + locale.setlocale(locale.LC_ALL, '') + d = Dialog(dialog="dialog",autowidgetsize=True) + d.set_background_title("Gravedigger") + + moduleList = getModules() + code,value = d.inputbox("Input computer's name") if code == d.OK: - runlist = [] - try: + tomb._MACHINE_NAME= value + logger.logSystems.append(ConsoleLogger()) + logger.logSystems.append(FileLogger(tomb.getPath() + "log.txt")) + d.set_background_title("Gravedigger - " + value) + code, tags = d.checklist("Select modules to execute", + choices=moduleList + [("all","Execute all modules",False)], + title="Module selection") + if code == d.OK: + runlist = [] if "all" in tags: for module in moduleList: - runlist.append(prepareModule(module[0])) + try: + mod = prepareModule(module[0]) + runlist.append(mod) + except Exception as e: + msg = "Exception raised while preparing module \"" + module[0] + "\": " + str(e) + logger.msgLog(msg, module[0], logger.TYPE_ERROR) + #logger.msgLog(traceback.format_exc(), module[0], logger.TYPE_ERROR) + if(not showContinueDialog(d,msg)): + showFinishDialog(False) else: for tag in tags: - runlist.append(prepareModule(tag)) + try: + mod = prepareModule(tag) + runlist.append(mod) + except Exception as e: + msg = "Exception raised while preparing module \"" + tag + "\": " + str(e) + logger.msgLog(msg,tag,logger.TYPE_ERROR) + #logger.msgLog(traceback.format_exc(), tag logger.TYPE_ERROR) + if(not showContinueDialog(d,msg)): + showFinishDialog(False) sp.call('clear', shell=True) - for module in runlist: - print("Running " + module.name + "...") + logger.msgLog("Running " + module.name + "...", "digger", logger.TYPE_INFO) try: module.run() except Exception as e: - print("Exception raised while running " + module.name + ": " + str(e)) - traceback.print_exc() + logger.msgLog("Exception raised while running \"" + module.name + "\": " + str(e), module.name, logger.TYPE_ERROR) + #logger.msgLog(traceback.format_exc(), module.name, logger.TYPE_ERROR) - code, tag = d.menu("All modules finished execution",choices=[("Poweroff","Shutdown the computer"), - ("Reboot","Reboot the computer"), - ("Restart","Run Gravedigger again")]) - if(code == d.OK): - if tag == "Poweroff": - sp.call("poweroff",shell=True) - elif tag == "Reboot": - sp.call("reboot", shell=True) - - except Exception as e: - print("Exception raised while preparing module: " + str(e)) - traceback.print_exc() + showFinishDialog(True) diff --git a/logger/consolelogger.py b/logger/consolelogger.py new file mode 100644 index 0000000..aacdef2 --- /dev/null +++ b/logger/consolelogger.py @@ -0,0 +1,25 @@ +import datetime +from logsystem import LogSystem + +BASH_YLW_TEXT = '\033[33m' +BASH_RED_TEXT = '\033[31m' +BASH_RESET_TEXT = '\033[0m' + +class ConsoleLogger(LogSystem): + + def writeLog(self,message,module,type = None): + if(type == None): + type = self.TYPE_INFO + time = str(datetime.datetime.now()) + + if(type == self.TYPE_ERROR): + print(time + " [" + module + "] " + BASH_RED_TEXT + "ERROR: " + message + BASH_RESET_TEXT) + + elif(type == self.TYPE_WARNING): + print(time + " [" + module + "] " + BASH_YLW_TEXT + "WARNING: " + message + BASH_RESET_TEXT) + + elif(type == self.TYPE_INFO): + print(time + " [" + module + "] " + "INFO: " + message) + + else: + print(message) \ No newline at end of file diff --git a/logger/filelogger.py b/logger/filelogger.py new file mode 100644 index 0000000..ac10dfb --- /dev/null +++ b/logger/filelogger.py @@ -0,0 +1,34 @@ +import datetime +from logsystem import LogSystem + +class FileLogger(LogSystem): + + def __init__(self,filename): + self.file = filename + f = open(filename,"w+") + f.close() + + def writeLog(self,message,module,type = None): + if(type == None): + type = self.TYPE_INFO + time = str(datetime.datetime.now()) + + if(type == self.TYPE_ERROR): + f = open(self.file,"a+") + f.write(time + " [" + module + "] " + "ERROR: " + message + "\n") + f.close() + + elif(type == self.TYPE_WARNING): + f = open(self.file,"a+") + f.write(time + " [" + module + "] " + "WARNING: " + message + "\n") + f.close() + + elif(type == self.TYPE_INFO): + f = open(self.file,"a+") + f.write(time + " [" + module + "] " + "INFO: " + message + "\n") + f.close() + + else: + f = open(self.file,"a+") + f.write(message + "\n") + f.close() \ No newline at end of file diff --git a/logger/logger.py b/logger/logger.py new file mode 100644 index 0000000..e392b4c --- /dev/null +++ b/logger/logger.py @@ -0,0 +1,8 @@ +logSystems = [] +TYPE_INFO = 0 +TYPE_WARNING = 1 +TYPE_ERROR = 2 + +def msgLog(message,module,type=None): + for system in logSystems: + system.writeLog(message,module,type) \ No newline at end of file diff --git a/logger/logsystem.py b/logger/logsystem.py new file mode 100644 index 0000000..47ae3c0 --- /dev/null +++ b/logger/logsystem.py @@ -0,0 +1,12 @@ +from abc import ABCMeta, abstractmethod + +class LogSystem(object): + __metaclass__ = ABCMeta + + TYPE_INFO = 0 + TYPE_WARNING = 1 + TYPE_ERROR = 2 + + @abstractmethod + def writeLog(self,message,module,type): + pass \ No newline at end of file diff --git a/module.py b/module.py deleted file mode 100644 index de3d073..0000000 --- a/module.py +++ /dev/null @@ -1,19 +0,0 @@ -from abc import ABCMeta, abstractmethod - -class Module(object): - __metaclass__ = ABCMeta - - name = "" - description = "" - vars = {} - requiredVars = [] - - @abstractmethod - def run(self): - pass - - def getVars(self): - for var in self.requiredVars: - modvar = __import__(var).getInstance(self.name) - modvar.query() - self.vars[modvar.name] = modvar \ No newline at end of file diff --git a/modules/evt.py b/modules/evt.py new file mode 100644 index 0000000..809b71e --- /dev/null +++ b/modules/evt.py @@ -0,0 +1,53 @@ +import os + +import logger +import tomb +import winver +from modules.module import Module +from mount import mount,umount +from runcmd import runProcess + + +def getInstance(): + return RegistryModule() + +class RegistryModule(Module): + + def __init__(self): + self.name = "evt" + self.description = "Extracts Windows Event Viewer files" + self.requiredVars = ["winvol"] + self.vars = {} + + def run(self): + path = tomb.getPath() + self.name + "/" + if(not os.path.exists(path)): + os.mkdir(path) + logger.msgLog("Extracting Windows Event Logs from volumes: " + repr(self.vars['winvol'].value), "winreg", logger.TYPE_INFO) + for vol in self.vars['winvol'].value: + mntpoint = "/mnt/" + try: + mntid = mount("/dev/" + vol) + except: + raise + mntpoint += mntid + files = [] + windir = winver.getWindowsDirectory(mntpoint) + if windir == None: + raise Exception("No Windows installation present") + version = winver.getWindowsVersion(mntpoint) + + if version < winver._WIN_2k: + raise Exception("No EVT files in Windows versions prior to Windows 2000") + elif version < winver._WIN_VISTA: + files += [windir + "/System32/config/*.evt"] + files += [windir + "/System32/config/*.Evt"] + files += [windir + "/System32/config/*.EVT"] + else: + files += [windir + "/System32/winevt/Logs" ] + + runProcess(["tar","-czvf",path + "evt_" + vol + ".tar.gz"] + files) + try: + umount(mntid) + except: + raise diff --git a/modules/info.py b/modules/info.py index 3f006a0..f0a8ed5 100644 --- a/modules/info.py +++ b/modules/info.py @@ -1,8 +1,10 @@ -from module import Module -from runcmd import runProcess -import tomb import os +import tomb +from modules.module import Module +from runcmd import runProcess + + def getInstance(): return INFOModule() diff --git a/modules/mft.py b/modules/mft.py index 8a00cd3..be12614 100644 --- a/modules/mft.py +++ b/modules/mft.py @@ -1,8 +1,11 @@ -from module import Module -from runcmd import runProcess -import tomb import os +import logger +import tomb +from modules.module import Module +from runcmd import runProcess + + def getInstance(): return MFTModule() @@ -18,6 +21,7 @@ class MFTModule(Module): path = tomb.getPath() + self.name + "/" if(not os.path.exists(path)): os.mkdir(path) + logger.msgLog("Extracting MFT from volumes: " + repr(self.vars['ntfsvol'].value), "mft", logger.TYPE_INFO) for vol in self.vars['ntfsvol'].value: result,code = runProcess(["icat","/dev/" + vol,"0"]) mftbin = open(path + vol + ".bin",'wb') diff --git a/modules/module.py b/modules/module.py new file mode 100644 index 0000000..00f451c --- /dev/null +++ b/modules/module.py @@ -0,0 +1,22 @@ +from abc import ABCMeta, abstractmethod + +class Module(object): + __metaclass__ = ABCMeta + + name = "" + description = "" + vars = {} + requiredVars = [] + + @abstractmethod + def run(self): + pass + + def getVars(self): + for var in self.requiredVars: + modvar = __import__(var).getInstance(self.name) + modvar.query() + self.vars[modvar.name] = modvar + + def __str__(self): + return self.name \ No newline at end of file diff --git a/modules/winreg.py b/modules/winreg.py index a3c4019..07ce27c 100644 --- a/modules/winreg.py +++ b/modules/winreg.py @@ -1,9 +1,12 @@ -from module import Module -import tomb import os + +import logger +import tomb import winver -from runcmd import runProcess +from modules.module import Module from mount import mount,umount +from runcmd import runProcess + def getInstance(): return RegistryModule() @@ -20,9 +23,13 @@ class RegistryModule(Module): path = tomb.getPath() + self.name + "/" if(not os.path.exists(path)): os.mkdir(path) + logger.msgLog("Extracting Windows registry from volumes: " + repr(self.vars['winvol'].value), "winreg", logger.TYPE_INFO) for vol in self.vars['winvol'].value: mntpoint = "/mnt/" - mntid = mount("/dev/" + vol) + try: + mntid = mount("/dev/" + vol) + except: + raise mntpoint += mntid files = [] windir = winver.getWindowsDirectory(mntpoint) @@ -58,4 +65,7 @@ class RegistryModule(Module): files += [profile + "/AppData/Local/Microsoft/Windows/UsrClass.dat"] runProcess(["tar","-czvf",path + "winreg_" + vol + ".tar.gz"] + files) - umount(mntid) + try: + umount(mntid) + except: + raise diff --git a/modulevar.py b/modulevar.py deleted file mode 100644 index d63f5d7..0000000 --- a/modulevar.py +++ /dev/null @@ -1,16 +0,0 @@ -from abc import ABCMeta,abstractmethod - -class Modulevar(object): - __metaclass__ = ABCMeta - - name = "" - parentModule = "" - description = "" - value = None - - def setValue(self,value): - self.value = value - - @abstractmethod - def query(self): - pass \ No newline at end of file diff --git a/vars/__init__.py b/vars/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/vars/__init__.py diff --git a/vars/modulevar.py b/vars/modulevar.py new file mode 100644 index 0000000..793522f --- /dev/null +++ b/vars/modulevar.py @@ -0,0 +1,19 @@ +from abc import ABCMeta,abstractmethod + +class Modulevar(object): + __metaclass__ = ABCMeta + + name = "" + parentModule = "" + description = "" + value = None + + def setValue(self,value): + self.value = value + + @abstractmethod + def query(self): + pass + + def __str__(self): + return self.name \ No newline at end of file diff --git a/vars/ntfsvol.py b/vars/ntfsvol.py index 2cbb478..306e84f 100644 --- a/vars/ntfsvol.py +++ b/vars/ntfsvol.py @@ -1,6 +1,8 @@ -from modulevar import Modulevar from dialog import Dialog + from runcmd import runProcess +from vars.modulevar import Modulevar + def getInstance(modname): return NTFSVol(modname) @@ -27,7 +29,7 @@ class NTFSVol(Modulevar): d.set_background_title("[" + self.parentModule + "] Setting variable: ntfsvol") volumes = self.getNTFSVolumes() if(len(volumes) == 0): - raise Exception("[" + self.name + "] No Windows Volumes found") + raise Exception("[" + self.name + "] No NTFS Volumes found") volumeList = [] for vol in volumes: volumeList.append((vol[0],vol[1], False)) diff --git a/vars/winvol.py b/vars/winvol.py index 722b7c0..fae170d 100644 --- a/vars/winvol.py +++ b/vars/winvol.py @@ -1,8 +1,11 @@ -from modulevar import Modulevar from dialog import Dialog -from runcmd import runProcess + +import logger import winver from mount import mount,umount +from runcmd import runProcess +from vars.modulevar import Modulevar + def getInstance(modname): return WinVol(modname) @@ -49,6 +52,7 @@ class WinVol(Modulevar): d = Dialog(dialog="dialog", autowidgetsize=True) d.set_background_title("[" + self.parentModule + "] Setting variable: winvol") volumes = self.getWindowsVolumes() + logger.msgLog("Detected Windows volumes in " + repr(volumes),"winvol",logger.TYPE_INFO) if(len(volumes) == 0): raise Exception("[" + self.name + "] No Windows Volumes found") volumeList = [] -- libgit2 0.22.2