summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeroen Vermeulen2018-07-16 10:02:01 +0200
committerjvoisin2018-07-16 08:02:01 +0000
commit882a1aba2385e1d817ff139e677ad60dec579698 (patch)
tree01ee3fcce4890d4ade6b5aa27961c03652e04a53
parent80d3f7fbf75ff48f906b198313db851896ff8f8f (diff)
Updated mass_whitelist to output progress to STDERR (#75)
Only the generated rules are printed to STDOUT Now you can do: ``` ./mass_whitelist.py [NAME] [URL_PATTERN] [MAJOR] [MINOR] [PATCH] > ../whitelists/name.yar ```
-rwxr-xr-xphp-malware-finder/utils/mass_whitelist.py28
1 files changed, 16 insertions, 12 deletions
diff --git a/php-malware-finder/utils/mass_whitelist.py b/php-malware-finder/utils/mass_whitelist.py
index c2cf131..868f7b5 100755
--- a/php-malware-finder/utils/mass_whitelist.py
+++ b/php-malware-finder/utils/mass_whitelist.py
@@ -50,6 +50,10 @@ class Opts:
50 return '<Opts(%s)>' % ' '.join(values) 50 return '<Opts(%s)>' % ' '.join(values)
51 51
52 52
53def eprint(*args, **kwargs):
54 print(*args, file=sys.stderr, **kwargs)
55
56
53def extract_version_arg(index): 57def extract_version_arg(index):
54 min_ver, max_ver = (Opts.DEFAULT_MIN, Opts.DEFAULT_MAX) 58 min_ver, max_ver = (Opts.DEFAULT_MIN, Opts.DEFAULT_MAX)
55 if len(sys.argv) >= (index + 1): 59 if len(sys.argv) >= (index + 1):
@@ -67,7 +71,7 @@ def generate_whitelist(version):
67 dl_failed = False 71 dl_failed = False
68 download_url = Opts.URL_PATTERN.replace('__version__', version) 72 download_url = Opts.URL_PATTERN.replace('__version__', version)
69 download_url_str = Opts.URL_PATTERN.replace('__version__', '\x1b[1;33m%s\x1b[0m' % version) 73 download_url_str = Opts.URL_PATTERN.replace('__version__', '\x1b[1;33m%s\x1b[0m' % version)
70 print("[+] Downloading %s... " % download_url_str, end='') 74 eprint("[+] Downloading %s... " % download_url_str, end='')
71 sys.stdout.flush() 75 sys.stdout.flush()
72 try: 76 try:
73 resp = urlopen(download_url) 77 resp = urlopen(download_url)
@@ -76,14 +80,14 @@ def generate_whitelist(version):
76 dl_failed = True 80 dl_failed = True
77 resp_code = err.code 81 resp_code = err.code
78 if dl_failed or (resp_code != 200): 82 if dl_failed or (resp_code != 200):
79 print("\x1b[1;31mFAILED (%d)\x1b[0m" % resp_code) 83 eprint("\x1b[1;31mFAILED (%d)\x1b[0m" % resp_code)
80 return None 84 return None
81 data = StringIO(resp.read()) 85 data = StringIO(resp.read())
82 data.seek(0) 86 data.seek(0)
83 print("\x1b[1;32mOK\x1b[0m") 87 eprint("\x1b[1;32mOK\x1b[0m")
84 88
85 # extract archive and check against YARA signatures (in-memory) 89 # extract archive and check against YARA signatures (in-memory)
86 print("[-] Generating whitelist... ", end='') 90 eprint("[-] Generating whitelist... ", end='')
87 sys.stdout.flush() 91 sys.stdout.flush()
88 tar = tarfile.open(mode='r:gz', fileobj=data) 92 tar = tarfile.open(mode='r:gz', fileobj=data)
89 for entry in tar.getnames(): 93 for entry in tar.getnames():
@@ -94,7 +98,7 @@ def generate_whitelist(version):
94 matches = Opts.YARA_RULES.match(data=entry_data, fast=True) 98 matches = Opts.YARA_RULES.match(data=entry_data, fast=True)
95 if matches: 99 if matches:
96 rules['/'.join(entry.split('/')[1:])] = sha1(entry_data).hexdigest() 100 rules['/'.join(entry.split('/')[1:])] = sha1(entry_data).hexdigest()
97 print("\x1b[1;32mDONE\x1b[0m") 101 eprint("\x1b[1;32mDONE\x1b[0m")
98 102
99 return rules 103 return rules
100 104
@@ -104,7 +108,7 @@ whitelists = OrderedDict()
104 108
105# check args 109# check args
106if (len(sys.argv) < 3) or (len(sys.argv) > 6): 110if (len(sys.argv) < 3) or (len(sys.argv) > 6):
107 print(USAGE) 111 eprint(USAGE)
108 sys.exit(1) 112 sys.exit(1)
109 113
110# parse args 114# parse args
@@ -132,8 +136,8 @@ for vmajor in range(Opts.MIN_MAJOR, Opts.MAX_MAJOR + 1):
132 has_mversion = True 136 has_mversion = True
133 if rules: 137 if rules:
134 whitelists[version] = rules 138 whitelists[version] = rules
135 if (rules is None) and (has_mversion or not first_mloop): 139 #if (rules is None) and (has_mversion or not first_mloop):
136 break 140 # break
137 first_mloop = False 141 first_mloop = False
138 142
139 has_pversion = False 143 has_pversion = False
@@ -154,7 +158,7 @@ for vmajor in range(Opts.MIN_MAJOR, Opts.MAX_MAJOR + 1):
154 first_ploop = False 158 first_ploop = False
155 159
156# remove duplicate entries: 160# remove duplicate entries:
157print("[+] Deduplicating detections... ", end='') 161eprint("[+] Deduplicating detections... ", end='')
158known_files = [] 162known_files = []
159for version, rules in copy(whitelists.items()): 163for version, rules in copy(whitelists.items()):
160 used_rules = 0 164 used_rules = 0
@@ -167,9 +171,9 @@ for version, rules in copy(whitelists.items()):
167 used_rules += 1 171 used_rules += 1
168 if used_rules == 0: 172 if used_rules == 0:
169 del whitelists[version] 173 del whitelists[version]
170print("\x1b[1;32mDONE\x1b[0m") 174eprint("\x1b[1;32mDONE\x1b[0m")
171 175
172print("[+] Generating final whitelist... ", end='') 176eprint("[+] Generating final whitelist... ", end='')
173# build final rule 177# build final rule
174prefix = 8 * ' ' 178prefix = 8 * ' '
175conditions = [] 179conditions = []
@@ -183,7 +187,7 @@ for index, (version, rules) in enumerate(whitelists.items()):
183 else: 187 else:
184 cond_str += '%shash.sha1(0, filesize) == "%s" or // %s\n' % (prefix, digest, filename) 188 cond_str += '%shash.sha1(0, filesize) == "%s" or // %s\n' % (prefix, digest, filename)
185 conditions.append(cond_str) 189 conditions.append(cond_str)
186print("\x1b[1;32mDONE\x1b[0m") 190eprint("\x1b[1;32mDONE\x1b[0m")
187 191
188final_rule = """ 192final_rule = """
189import "hash" 193import "hash"