Snippets
Revised by
Alexander Hanel
5f061fd
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | __author__ = "Alexander Hanel"
__version__ = "1.0"
__contact__ = "alexander<dot>hanel<at>gmail<dot>com"
__date__ = "2015/06"
"""
Command line example
python obf_str_replace.py -r "[)|1|I|l|9|\+|]{10,}" -g "*as"
-r is the regex pattern.
Please place the regex in quotes . The regex pattern "[)|1|I|l|9|\+|]{10,}" would match the random looking
strings as seen below.
public var Illl1III111I11:String;
public var lIll1III111I11:String;
public var llll1III111I11:String;
public var ))ll1III111I11:String;
-t use this option to test the regex pattern and print the found strings. Output
Match on "s 1I111IIIlllIl1 e" at 98:116 in 1I111IIIlllIl1.as
Match on "r Il111IIIlllIl1:O" at 157:175 in 1I111IIIlllIl1.as
Match on " _lllIII111I11:C" at 201:217 in 1I111IIIlllIl1.as
Match on "r 1Ill1III111I11:I" at 241:259 in 1I111IIIlllIl1.as
Match on "1:IIll1III111I11;" at 256:274 in 1I111IIIlllIl1.as
Match on "r lI111IIIlllIl19:u" at 292:311 in 1I111IIIlllIl1.as
Match on "r ll111IIIlllIl1:u" at 338:356 in 1I111IIIlllIl1.as
-g is the glob file pattern. It is optional. If In the example above it will oly match files that end with "as"
"""
import sys
import re
import glob
import os
import argparse
class ObfStrReplacer():
"""
A module that can be used to de-obfuscate code by searching
for strings that match a regular express pattern and replace
them with more readable characters.
"""
def __init__(self):
self.regex_pattern = None
self.compiled_regex = None
self.file_glob_pattern = None
self.test_regex = False
self.script_name = None
self.globbed_files = None
self.word_list = [
"abacus", "iota", "nu", "baryon", "ceres", "dean", "zipf",
"mu", "epsilon", "lune", "fermat", "gamma", "carat", "gaudi",
"ides", "alpha", "iris", "julia", "tare", "omicron", "pascal",
"kappa", "aeon", "umbra", "secant", "lambda", "beta", "lemma",
"eta", "mars", "nocebo", "occam", "chaos", "arc", "omega",
"xenon", "pareto", "locus", "psi", "rho", "delta", "sigma",
"pi", "simson", "tau", "gnomen", "theta", "atlas", "upsilon",
"phi", "venus", "ogive", "surd", "xi", "zeta", "sabot", "chi",
"kite"]
self.match_set = set([])
self.names = []
self.name_mapping = {}
def get_args(self):
"""
gets the command line arguments.
"""
parser = argparse.ArgumentParser(
description='Replaces strings matched by a regular expression with more \
distinguishable text/strings.')
parser.add_argument('-r', '--regex', type=str, required=True, help="regex pattern for search and replace")
parser.add_argument('-g', '--glob', type=str, help="glob file pattern to search in")
parser.add_argument('-t', '--test', action='store_true', help="only print found strings that match regex")
args = parser.parse_args()
# assign arguments
self.regex_pattern = args.regex
# default is all files in the current working directory
if args.glob is None:
self.file_glob_pattern = "*"
else:
self.file_glob_pattern = args.glob
self.test_regex = args.test
self.script_name = parser.prog
def get_files(self):
"""
uses glob to get paths & names of files. Removes script from the list
"""
try:
self.globbed_files = glob.glob(self.file_glob_pattern)
except:
print " * ERROR: Glob failed, aborting."
# remove script from list
if self.script_name in self.globbed_files:
self.globbed_files.remove(self.script_name)
# verify glob results
if not self.globbed_files:
print " * ERROR: No matches for glob file pattern, aborting."
os._exit(1)
def compile_regex(self):
"""
verifies the regex pattern can be compiled
"""
try:
self.compiled_regex = re.compile(self.regex_pattern)
except:
print " * ERROR: regex pattern compiling failed, aborting."
os._exit(1)
def get_matches(self):
"""
get all matches
"""
file_data = None
for file_name in self.globbed_files:
with open(file_name, 'r') as f:
file_data = f.read()
for match in re.finditer(self.compiled_regex, file_data):
self.match_set.add(file_data[match.start():match.end()].rstrip())
def print_regex_matches(self):
"""
prints all matches
"""
file_data = None
for file_name in self.globbed_files:
with open(file_name, 'r') as f:
file_data = f.read()
for match in re.finditer(self.compiled_regex, file_data):
try:
s = match.start() - 2
except:
s = match.start()
try:
e = match.end() + 2
except:
e = match.end()
print 'Match on "%s" at %d:%d in %s' % (file_data[s:e].rstrip(), s, e, file_name)
def create_str(self):
"""
constructs unique strings
"""
len_set = len(self.word_list)
temp_name_list = []
temp_str = ""
for count,name in enumerate(self.match_set):
temp_str = "_" + self.word_list[count % len_set]
if temp_str in temp_name_list:
while True:
temp_str = "_" + self.word_list[count % len_set] + "_" + str(count)
count += 1
if temp_str not in temp_name_list:
break
temp_name_list.append(temp_str)
# should never happen
self.names = temp_name_list
if not self.names:
print " * ERROR: no names created, aborting."
os._exit(1)
def string_to_name(self):
"""
map string to regex match
"""
if len(self.names) == len(self.match_set):
for count, name in enumerate(self.match_set):
self.name_mapping[name] = self.names[count]
else:
print " * ERROR: logic bug. length of name and matches incorrect, aborting."
os._exit(1)
def replace_str(self):
"""
replace regex match with generated string
"""
# names sorted the largest match is done first. If not sub-strings
names_sorted = sorted(list(self.match_set), key=len)[::-1]
for file_name in self.globbed_files:
with open(file_name, 'r') as f:
file_data = f.read()
for key in names_sorted:
file_data = file_data.replace(key, self.name_mapping[key])
with open(file_name + ".d", 'w') as ff:
ff.write(file_data)
def run(self):
self.get_args()
self.get_files()
self.compile_regex()
if self.test_regex:
self.print_regex_matches()
return
self.get_matches()
self.create_str()
self.string_to_name()
self.replace_str()
if __name__ == "__main__":
xx = ObfStrReplacer()
xx.run()
|
You can clone a snippet to your computer for local editing. Learn more.