diff options
| author | Jeroen Vermeulen | 2018-07-16 10:02:01 +0200 |
|---|---|---|
| committer | jvoisin | 2018-07-16 08:02:01 +0000 |
| commit | 882a1aba2385e1d817ff139e677ad60dec579698 (patch) | |
| tree | 01ee3fcce4890d4ade6b5aa27961c03652e04a53 | |
| parent | 80d3f7fbf75ff48f906b198313db851896ff8f8f (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-x | php-malware-finder/utils/mass_whitelist.py | 28 |
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 | ||
| 53 | def eprint(*args, **kwargs): | ||
| 54 | print(*args, file=sys.stderr, **kwargs) | ||
| 55 | |||
| 56 | |||
| 53 | def extract_version_arg(index): | 57 | def 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 |
| 106 | if (len(sys.argv) < 3) or (len(sys.argv) > 6): | 110 | if (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: |
| 157 | print("[+] Deduplicating detections... ", end='') | 161 | eprint("[+] Deduplicating detections... ", end='') |
| 158 | known_files = [] | 162 | known_files = [] |
| 159 | for version, rules in copy(whitelists.items()): | 163 | for 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] |
| 170 | print("\x1b[1;32mDONE\x1b[0m") | 174 | eprint("\x1b[1;32mDONE\x1b[0m") |
| 171 | 175 | ||
| 172 | print("[+] Generating final whitelist... ", end='') | 176 | eprint("[+] Generating final whitelist... ", end='') |
| 173 | # build final rule | 177 | # build final rule |
| 174 | prefix = 8 * ' ' | 178 | prefix = 8 * ' ' |
| 175 | conditions = [] | 179 | conditions = [] |
| @@ -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) |
| 186 | print("\x1b[1;32mDONE\x1b[0m") | 190 | eprint("\x1b[1;32mDONE\x1b[0m") |
| 187 | 191 | ||
| 188 | final_rule = """ | 192 | final_rule = """ |
| 189 | import "hash" | 193 | import "hash" |
