From 00dcf762f2e5a53b6a03f524ae77addd1689ea07 Mon Sep 17 00:00:00 2001 From: Imanol-Mikel Barba Sabariego Date: Mon, 28 Aug 2017 10:33:45 +0200 Subject: [PATCH] fixed windows path storing (per volume). Added globeimposter2 module. Added functionality for registry and file lookup. --- findfile.py | 38 ++++++++++++++++++++++++++++++++++++++ modules/edb.py | 2 +- modules/globeimposter2.py | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ regquery.py | 34 ++++++++++++++++++++++++++++++++++ winver.py | 22 ++++++++++++++-------- 5 files changed, 143 insertions(+), 9 deletions(-) create mode 100644 findfile.py create mode 100644 modules/globeimposter2.py create mode 100644 regquery.py diff --git a/findfile.py b/findfile.py new file mode 100644 index 0000000..391b1f3 --- /dev/null +++ b/findfile.py @@ -0,0 +1,38 @@ +import os +import fnmatch + +def find_pattern_all(pattern, path, casesensitive): + result = [] + for root, dirs, files in os.walk(path): + for name in files: + if sensitive: + if fnmatch.fnmatchcase(name,pattern): + result.append(os.path.join(root, name)) + else: + if fnmatch.fnmatch(name.lower(), pattern.lower()): + result.append(os.path.join(root, name)) + return result + +def find_pattern(pattern, path, casesensitive): + for root, dirs, files in os.walk(path): + for name in files: + if sensitive: + if fnmatch.fnmatchcase(name,pattern): + return os.path.join(root, name) + else: + if fnmatch.fnmatch(name.lower(), pattern.lower()): + return os.path.join(root, name) + return None + +def find_all(name, path): + result = [] + for root, dirs, files in os.walk(path): + if name in files: + result.append(os.path.join(root, name)) + return result + +def find(name, path): + for root, dirs, files in os.walk(path): + if name in files: + return os.path.join(root, name) + return None diff --git a/modules/edb.py b/modules/edb.py index 2db5d0a..4aeac9b 100644 --- a/modules/edb.py +++ b/modules/edb.py @@ -43,7 +43,7 @@ class RegistryModule(Module): else: files += [mntpoint + "/ProgramData/Microsoft/Search/Data/Applications/Windows/Windows.edb"] - runProcess(["tar","-czvf",path + "evt_" + vol + "_" + str(int(time.time())) + ".tar.gz"] + files) + runProcess(["tar","-czvf",path + "edb_" + vol + "_" + str(int(time.time())) + ".tar.gz"] + files) try: umount(mntid) except: diff --git a/modules/globeimposter2.py b/modules/globeimposter2.py new file mode 100644 index 0000000..06d2314 --- /dev/null +++ b/modules/globeimposter2.py @@ -0,0 +1,56 @@ +import os + +import regquery +import logger +import tomb +import winver +from modules.module import Module +from mount import mount,umount +from runcmd import runProcess +import time +import findfile + +def getInstance(): + return RegistryModule() + +class RegistryModule(Module): + + def __init__(self): + self.name = "globeimposter2" + self.description = "Detects a Globeimposter 2.0 infection" + self.requiredVars = ["ntfsvol","winvol"] + self.vars = {} + + def execute(self): + path = tomb.getPath() + self.name + "/" + if(not os.path.exists(path)): + os.mkdir(path) + logger.msgLog("Scanning volumes " + repr(self.vars['winvol'].value) + " " + repr(self.vars['ntfsvol'].value) + " for Globeimposter 2.0 infection","globeimposter2", logger.TYPE_INFO) + for vol in self.vars['winvol'].value: + mntpoint = "/mnt/" + try: + mntid = mount("/dev/" + vol) + except: + raise + mntpoint += mntid + profiles = winver.getUserProfiles(mntpoint) + for profile in profiles: + hkcu = profile + "/NTUSER.DAT" + value = regquery.queryValue(hkcu,"""Software\Microsoft\Windows\CurrentVersion\RunOnce""","CertificatesCheck") + if(value != None): + logger.msgLog("FOUND Globeimposter 2.0 value in RunOnce: " + value,"globeimposter2",logger.TYPE_WARNING) + #VSS + + for vol in self.vars['ntfsvol'].value: + mntpoint = "/mnt/" + try: + mntid = mount("/dev/" + vol) + except: + raise + mntpoint += mntid + result = find_pattern("*.725",mntpoint,False) + if(result != None): + logger.msgLog("FOUND at least one file with 725 extension: " + result,"globeimposter2",logger.TYPE_WARNING) + result = find("RECOVER-FILES.html",mntpoint) + if(result != None): + logger.msgLog("FOUND ransom letter: " + result,"globeimposter2",logger.TYPE_WARNING) diff --git a/regquery.py b/regquery.py new file mode 100644 index 0000000..eb00126 --- /dev/null +++ b/regquery.py @@ -0,0 +1,34 @@ +from Registry import Registry + +def queryValue(hive,keyPath,valueName): + reg = Registry.Registry(hive) + key = reg.open(keyPath) + try: + value = str(key.value(valueName).value) + except Registry.RegistryValueNotFoundException: + value = None + return value + +def getValues(hive,key): + valueList = [] + reg = Registry.Registry(hive) + key = reg.open(keyPath) + for value in key.values(): + valueList.append(value.value_name) + return valueList + +def getSubkeys(hive,key): + subkeyList = [] + reg = Registry.Registry(hive) + key = reg.open(keyPath) + for subkey in key.subkeys(): + subkeyList.append(subkey.name) + return subkeyList + +def keyExists(hive,key): + reg = Registry.Registry(hive) + try: + key = reg.open(key) + return True + except Registry.RegistryKeyNotFoundException: + return False diff --git a/winver.py b/winver.py index 8a132ce..0f3879a 100644 --- a/winver.py +++ b/winver.py @@ -2,6 +2,7 @@ import os from runcmd import runProcess import re import pefile +import findfile _WIN_9x = 0 _WIN_ME = 1 @@ -19,7 +20,7 @@ _WIN_81 = 9 _WIN_2k12R2 = 9 _WIN_10 = 10 - +DETECTED_WINDOWS_PATH = {} def getWindowsVersion(path): if(os.path.isfile(getWindowsDirectory(path) + "/System32/ntdll.dll")): @@ -51,13 +52,18 @@ def getWindowsVersion(path): return _WIN_9x def getWindowsDirectory(path): - result,code = runProcess(["find",path,"-xdev","-iname","explorer.exe","-print","-quit"]) - if(result.decode("utf-8") == ""): - return None - matches = result.decode("utf-8").splitlines() - #WARNING: ONLY CONSIDERING FIRST MATCH - #TODO: Improve - return os.path.dirname(os.path.realpath(matches[0])) + if DETECTED_WINDOWS_PATH[path] is None: + result = find_pattern("explorer.exe",path,False) + #result,code = runProcess(["find",path,"-xdev","-iname","explorer.exe","-print","-quit"]) + #if(result.decode("utf-8") == ""): + if(len(result) == 0): + return None + #matches = result.decode("utf-8").splitlines() + #WARNING: ONLY CONSIDERING FIRST MATCH + #TODO: Improve + #return os.path.dirname(os.path.realpath(matches[0])) + DETECTED_WINDOWS_PATH[path] = os.path.dirname(os.path.realpath(result)) + return DETECTED_WINDOWS_PATH[path] def getUserProfiles(path): version = getWindowsVersion(path) -- libgit2 0.22.2