-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathobf.py
91 lines (76 loc) · 3.19 KB
/
obf.py
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
import random, string, base64, codecs, argparse, os, sys, hashlib
from textwrap import wrap
from lzma import compress
from marshal import dumps
def printerr(data):
print(data, file=sys.stderr)
class obf:
def __init__(self, code, outputpath):
self.code = code.encode()
self.outpath = outputpath
self.varlen = 5
self.vars = {}
self.marshal()
self.encrypt1()
self.encrypt2()
self.finalize()
def generate(self, name):
res = self.vars.get(name)
if res is None:
res = "".join(random.choice(string.ascii_letters) for _ in range(self.varlen))
self.varlen = random.randint(3, 10)
self.vars[name] = res
return res
def encryptstring(self, string):
# Using SHA256 hash to generate random-looking variable names
hash_val = hashlib.sha256(string.encode()).hexdigest()
cut = random.randint(5, 10)
return hash_val[:cut]
def marshal(self):
self.code = dumps(compile(self.code, "<string>", "exec"))
def encrypt1(self):
# Base64 encoding then breaking into parts and encoding each with a different method
encoded = base64.b64encode(self.code).decode()
parts = wrap(encoded, 10)
shuffled_parts = [codecs.encode(part, 'rot13') for part in parts]
random.shuffle(shuffled_parts)
var_names = [self.generate("var") for _ in range(len(shuffled_parts))]
init = "; ".join(f'{var}="{part}"' for var, part in zip(var_names, shuffled_parts))
self.code = f'''
# obf Advanced Obfuscation
{init}
exec("".join([codecs.decode(name, "rot13") for name in [{','.join(var_names)}]]))
'''.encode()
def encrypt2(self):
# Additional compression step
self.code = compress(self.code)
enc_code = base64.b64encode(self.code).decode()
variable = self.generate("compressed")
self.code = f'''
# obf Compressed and encoded
{variable} = "{enc_code}"
import base64, lzma; exec(lzma.decompress(base64.b64decode({variable})).decode())
'''.encode()
def finalize(self):
if os.path.dirname(self.outpath).strip() != "":
os.makedirs(os.path.dirname(self.outpath), exist_ok=True)
with open(self.outpath, "w") as e:
e.write(self.code.decode())
print("Saved as --> " + os.path.realpath(self.outpath))
if __name__ == "__main__":
parser = argparse.ArgumentParser(prog="xszOBF", description="Obfuscates python program to make it harder to read")
parser.add_argument("FILE", help="Path to the file containing the python code")
parser.add_argument("-o", "--output", type=str, default=None, help='Output file path', dest="path")
args = parser.parse_args()
if not os.path.isfile(sourcefile := args.FILE):
printerr(f'No such file: "{args.FILE}"')
sys.exit(1)
elif not sourcefile.endswith((".py", ".pyw")):
printerr('The file does not have a valid python script extension!')
sys.exit(1)
if args.path is None:
args.path = "Obfuscated_" + os.path.basename(sourcefile)
# Specify the encoding as 'utf-8'
with open(sourcefile, encoding='utf-8') as file:
code = file.read()
obf(code, args.path)