Commit 00dcf762f2e5a53b6a03f524ae77addd1689ea07
1 parent
956444dd
fixed windows path storing (per volume). Added globeimposter2 module. Added func…
…tionality for registry and file lookup.
Showing
5 changed files
with
143 additions
and
9 deletions
findfile.py
0 → 100644
1 | +import os | ||
2 | +import fnmatch | ||
3 | + | ||
4 | +def find_pattern_all(pattern, path, casesensitive): | ||
5 | + result = [] | ||
6 | + for root, dirs, files in os.walk(path): | ||
7 | + for name in files: | ||
8 | + if sensitive: | ||
9 | + if fnmatch.fnmatchcase(name,pattern): | ||
10 | + result.append(os.path.join(root, name)) | ||
11 | + else: | ||
12 | + if fnmatch.fnmatch(name.lower(), pattern.lower()): | ||
13 | + result.append(os.path.join(root, name)) | ||
14 | + return result | ||
15 | + | ||
16 | +def find_pattern(pattern, path, casesensitive): | ||
17 | + for root, dirs, files in os.walk(path): | ||
18 | + for name in files: | ||
19 | + if sensitive: | ||
20 | + if fnmatch.fnmatchcase(name,pattern): | ||
21 | + return os.path.join(root, name) | ||
22 | + else: | ||
23 | + if fnmatch.fnmatch(name.lower(), pattern.lower()): | ||
24 | + return os.path.join(root, name) | ||
25 | + return None | ||
26 | + | ||
27 | +def find_all(name, path): | ||
28 | + result = [] | ||
29 | + for root, dirs, files in os.walk(path): | ||
30 | + if name in files: | ||
31 | + result.append(os.path.join(root, name)) | ||
32 | + return result | ||
33 | + | ||
34 | +def find(name, path): | ||
35 | + for root, dirs, files in os.walk(path): | ||
36 | + if name in files: | ||
37 | + return os.path.join(root, name) | ||
38 | + return None |
modules/edb.py
@@ -43,7 +43,7 @@ class RegistryModule(Module): | @@ -43,7 +43,7 @@ class RegistryModule(Module): | ||
43 | else: | 43 | else: |
44 | files += [mntpoint + "/ProgramData/Microsoft/Search/Data/Applications/Windows/Windows.edb"] | 44 | files += [mntpoint + "/ProgramData/Microsoft/Search/Data/Applications/Windows/Windows.edb"] |
45 | 45 | ||
46 | - runProcess(["tar","-czvf",path + "evt_" + vol + "_" + str(int(time.time())) + ".tar.gz"] + files) | 46 | + runProcess(["tar","-czvf",path + "edb_" + vol + "_" + str(int(time.time())) + ".tar.gz"] + files) |
47 | try: | 47 | try: |
48 | umount(mntid) | 48 | umount(mntid) |
49 | except: | 49 | except: |
modules/globeimposter2.py
0 → 100644
1 | +import os | ||
2 | + | ||
3 | +import regquery | ||
4 | +import logger | ||
5 | +import tomb | ||
6 | +import winver | ||
7 | +from modules.module import Module | ||
8 | +from mount import mount,umount | ||
9 | +from runcmd import runProcess | ||
10 | +import time | ||
11 | +import findfile | ||
12 | + | ||
13 | +def getInstance(): | ||
14 | + return RegistryModule() | ||
15 | + | ||
16 | +class RegistryModule(Module): | ||
17 | + | ||
18 | + def __init__(self): | ||
19 | + self.name = "globeimposter2" | ||
20 | + self.description = "Detects a Globeimposter 2.0 infection" | ||
21 | + self.requiredVars = ["ntfsvol","winvol"] | ||
22 | + self.vars = {} | ||
23 | + | ||
24 | + def execute(self): | ||
25 | + path = tomb.getPath() + self.name + "/" | ||
26 | + if(not os.path.exists(path)): | ||
27 | + os.mkdir(path) | ||
28 | + logger.msgLog("Scanning volumes " + repr(self.vars['winvol'].value) + " " + repr(self.vars['ntfsvol'].value) + " for Globeimposter 2.0 infection","globeimposter2", logger.TYPE_INFO) | ||
29 | + for vol in self.vars['winvol'].value: | ||
30 | + mntpoint = "/mnt/" | ||
31 | + try: | ||
32 | + mntid = mount("/dev/" + vol) | ||
33 | + except: | ||
34 | + raise | ||
35 | + mntpoint += mntid | ||
36 | + profiles = winver.getUserProfiles(mntpoint) | ||
37 | + for profile in profiles: | ||
38 | + hkcu = profile + "/NTUSER.DAT" | ||
39 | + value = regquery.queryValue(hkcu,"""Software\Microsoft\Windows\CurrentVersion\RunOnce""","CertificatesCheck") | ||
40 | + if(value != None): | ||
41 | + logger.msgLog("FOUND Globeimposter 2.0 value in RunOnce: " + value,"globeimposter2",logger.TYPE_WARNING) | ||
42 | + #VSS | ||
43 | + | ||
44 | + for vol in self.vars['ntfsvol'].value: | ||
45 | + mntpoint = "/mnt/" | ||
46 | + try: | ||
47 | + mntid = mount("/dev/" + vol) | ||
48 | + except: | ||
49 | + raise | ||
50 | + mntpoint += mntid | ||
51 | + result = find_pattern("*.725",mntpoint,False) | ||
52 | + if(result != None): | ||
53 | + logger.msgLog("FOUND at least one file with 725 extension: " + result,"globeimposter2",logger.TYPE_WARNING) | ||
54 | + result = find("RECOVER-FILES.html",mntpoint) | ||
55 | + if(result != None): | ||
56 | + logger.msgLog("FOUND ransom letter: " + result,"globeimposter2",logger.TYPE_WARNING) |
regquery.py
0 → 100644
1 | +from Registry import Registry | ||
2 | + | ||
3 | +def queryValue(hive,keyPath,valueName): | ||
4 | + reg = Registry.Registry(hive) | ||
5 | + key = reg.open(keyPath) | ||
6 | + try: | ||
7 | + value = str(key.value(valueName).value) | ||
8 | + except Registry.RegistryValueNotFoundException: | ||
9 | + value = None | ||
10 | + return value | ||
11 | + | ||
12 | +def getValues(hive,key): | ||
13 | + valueList = [] | ||
14 | + reg = Registry.Registry(hive) | ||
15 | + key = reg.open(keyPath) | ||
16 | + for value in key.values(): | ||
17 | + valueList.append(value.value_name) | ||
18 | + return valueList | ||
19 | + | ||
20 | +def getSubkeys(hive,key): | ||
21 | + subkeyList = [] | ||
22 | + reg = Registry.Registry(hive) | ||
23 | + key = reg.open(keyPath) | ||
24 | + for subkey in key.subkeys(): | ||
25 | + subkeyList.append(subkey.name) | ||
26 | + return subkeyList | ||
27 | + | ||
28 | +def keyExists(hive,key): | ||
29 | + reg = Registry.Registry(hive) | ||
30 | + try: | ||
31 | + key = reg.open(key) | ||
32 | + return True | ||
33 | + except Registry.RegistryKeyNotFoundException: | ||
34 | + return False |
winver.py
@@ -2,6 +2,7 @@ import os | @@ -2,6 +2,7 @@ import os | ||
2 | from runcmd import runProcess | 2 | from runcmd import runProcess |
3 | import re | 3 | import re |
4 | import pefile | 4 | import pefile |
5 | +import findfile | ||
5 | 6 | ||
6 | _WIN_9x = 0 | 7 | _WIN_9x = 0 |
7 | _WIN_ME = 1 | 8 | _WIN_ME = 1 |
@@ -19,7 +20,7 @@ _WIN_81 = 9 | @@ -19,7 +20,7 @@ _WIN_81 = 9 | ||
19 | _WIN_2k12R2 = 9 | 20 | _WIN_2k12R2 = 9 |
20 | _WIN_10 = 10 | 21 | _WIN_10 = 10 |
21 | 22 | ||
22 | - | 23 | +DETECTED_WINDOWS_PATH = {} |
23 | 24 | ||
24 | def getWindowsVersion(path): | 25 | def getWindowsVersion(path): |
25 | if(os.path.isfile(getWindowsDirectory(path) + "/System32/ntdll.dll")): | 26 | if(os.path.isfile(getWindowsDirectory(path) + "/System32/ntdll.dll")): |
@@ -51,13 +52,18 @@ def getWindowsVersion(path): | @@ -51,13 +52,18 @@ def getWindowsVersion(path): | ||
51 | return _WIN_9x | 52 | return _WIN_9x |
52 | 53 | ||
53 | def getWindowsDirectory(path): | 54 | def getWindowsDirectory(path): |
54 | - result,code = runProcess(["find",path,"-xdev","-iname","explorer.exe","-print","-quit"]) | ||
55 | - if(result.decode("utf-8") == ""): | ||
56 | - return None | ||
57 | - matches = result.decode("utf-8").splitlines() | ||
58 | - #WARNING: ONLY CONSIDERING FIRST MATCH | ||
59 | - #TODO: Improve | ||
60 | - return os.path.dirname(os.path.realpath(matches[0])) | 55 | + if DETECTED_WINDOWS_PATH[path] is None: |
56 | + result = find_pattern("explorer.exe",path,False) | ||
57 | + #result,code = runProcess(["find",path,"-xdev","-iname","explorer.exe","-print","-quit"]) | ||
58 | + #if(result.decode("utf-8") == ""): | ||
59 | + if(len(result) == 0): | ||
60 | + return None | ||
61 | + #matches = result.decode("utf-8").splitlines() | ||
62 | + #WARNING: ONLY CONSIDERING FIRST MATCH | ||
63 | + #TODO: Improve | ||
64 | + #return os.path.dirname(os.path.realpath(matches[0])) | ||
65 | + DETECTED_WINDOWS_PATH[path] = os.path.dirname(os.path.realpath(result)) | ||
66 | + return DETECTED_WINDOWS_PATH[path] | ||
61 | 67 | ||
62 | def getUserProfiles(path): | 68 | def getUserProfiles(path): |
63 | version = getWindowsVersion(path) | 69 | version = getWindowsVersion(path) |