diff --git a/src/vipyr_deobf/deobf_base.py b/src/vipyr_deobf/deobf_base.py index b6b36af..68382c2 100644 --- a/src/vipyr_deobf/deobf_base.py +++ b/src/vipyr_deobf/deobf_base.py @@ -34,7 +34,6 @@ def __post_init__(self): raise DeobfLoadingError('Deobfuscator was not initialized in a deobf module: see repo README') obf_name = normalize_deobf_name(module_name) res = parse_deobf_file_name(filename) - print(res, obf_name) if not res: raise DeobfLoadingError('Filename does not match module name: see repo README') name, version = res diff --git a/src/vipyr_deobf/deobfuscators/Vare/vare.py b/src/vipyr_deobf/deobfuscators/Vare/vare.py index 1800374..5082ab4 100644 --- a/src/vipyr_deobf/deobfuscators/Vare/vare.py +++ b/src/vipyr_deobf/deobfuscators/Vare/vare.py @@ -6,30 +6,61 @@ import ast import base64 -import marshal +import logging import re import zlib from cryptography.fernet import Fernet +from build.lib.vipyr_deobf.exceptions import DeobfuscationFailError from vipyr_deobf.deobf_base import Deobfuscator, register from vipyr_deobf.deobf_utils import WEBHOOK_REGEX +logger = logging.getLogger('deobf') -def deobf(code: str) -> str: + +def deobf_layer(code: str) -> str: """ - Extracts the entire source code from code + Extracts the entire source code from code layer """ key = ast.literal_eval(re.search(r'__mikey__\s*=\s*(([\'"]).+\2);mydata', code).group(1)) data = ast.literal_eval(re.search(r'mydata\s*=\s*(([\'"]).+\2)', code).group(1)) fernet = Fernet(base64.b64decode(key)) - return marshal.loads( - zlib.decompress(base64.b32decode(base64.b64decode( - base64.b64decode(base64.b64decode(base64.b32decode( - base64.b64decode(fernet.decrypt(bytes.fromhex(data))) - )))[::-1] - ))) - ).decode() + marshalled = zlib.decompress(base64.b32decode(base64.b64decode( + base64.b64decode(base64.b64decode(base64.b32decode( + base64.b64decode(fernet.decrypt(bytes.fromhex(data))) + )))[::-1] + ))) + try: + return str_unmarshal(marshalled) + except DeobfuscationFailError: + return f'{marshalled}' + + +def deobf(code: str) -> str: + i = 0 + while scan(code): + logger.info(f'Deobfuscating layer {i}') + code = deobf_layer(code) + i += 1 + logger.info(f'Finished deobfuscating at layer {i}') + return code + + +def str_unmarshal(marshalled: bytes) -> str: + """ + Unmarshals a marshalled string, which is what vare is + """ + total_length = len(marshalled) + payload_length = total_length - 5 + if not marshalled.startswith(b's'): + logger.error('Marshalled object was not a string') + raise DeobfuscationFailError() + expected_length = int.from_bytes(marshalled[1:5], 'little') + if expected_length != payload_length: + logger.error('Marshalled object length does not match expected length') + raise DeobfuscationFailError() + return marshalled[5:].decode('utf-8') def format_results(result: str) -> str: @@ -51,5 +82,6 @@ def scan(code: str): ) ) + vare_deobf = Deobfuscator(deobf, format_results, scan) register(vare_deobf)