From 7c7a006b46909fbd79ce2b6933eef55124677869 Mon Sep 17 00:00:00 2001 From: Andre Herbst Date: Sun, 1 Oct 2023 11:39:52 +0200 Subject: [PATCH] fix: xdis (>=6.0) and decompyle6 (>=3.9.0) now expect version tuples in parameters --- pydecipher/artifact_types/pyinstaller.py | 3 ++- pydecipher/bytecode.py | 10 +++++---- pydecipher/remap.py | 27 ++++++++++++++++-------- setup.py | 4 ++-- 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/pydecipher/artifact_types/pyinstaller.py b/pydecipher/artifact_types/pyinstaller.py index 3ff6f03..a6a2db5 100644 --- a/pydecipher/artifact_types/pyinstaller.py +++ b/pydecipher/artifact_types/pyinstaller.py @@ -422,13 +422,14 @@ def check_for_password_file(self): ( crypto_key_filename, crypto_key_co, - crypto_key_python_version, + version_tuple, crypto_key_compilation_timestamp, crypto_key_magic_int, crypto_key_is_pypy, crypto_key_source_size, crypto_key_sip_hash, ) = disassemble_file(str(key_file), outstream=open(os.devnull, "w")) + crypto_key_python_version = xdis.magics.version_tuple_to_str(version_tuple) except Exception as e: logger.warning(f"[!] Could not disassemble file {key_file}. Received error: {e}") else: diff --git a/pydecipher/bytecode.py b/pydecipher/bytecode.py index 236747b..4dd5086 100644 --- a/pydecipher/bytecode.py +++ b/pydecipher/bytecode.py @@ -296,7 +296,7 @@ def decompile_pyc(arg_tuple: Tuple[pathlib.Path, Dict[str, int], Dict[str, Union ( filename, co, - version, + version_tuple, timestamp, magic_int, is_pypy, @@ -308,8 +308,8 @@ def decompile_pyc(arg_tuple: Tuple[pathlib.Path, Dict[str, int], Dict[str, Union output_file: TextIO with new_file_name.open(mode="w") as output_file: uncompyle6.main.decompile( - version, co, + version_tuple, timestamp=timestamp, source_size=source_size, magic_int=magic_int, @@ -394,7 +394,8 @@ def _build_opcode_index(co_code_objects, HAVE_ARGUMENT=90, version: str = None) HAVE_ARGUMENT: int = 90 if version: try: - xdis_opcode: ModuleType = xdis.disasm.get_opcode(version, is_pypy=("pypy" in version)) + version_tuple = xdis.magics.py_str2tuple(version) + xdis_opcode: ModuleType = xdis.disasm.get_opcode(version_tuple, is_pypy=("pypy" in version)) except TypeError: logger.warning("[!] Couldn't retrieve version {version}'s opcodes from xdis.") else: @@ -509,7 +510,8 @@ def validate_opmap(version: str, opmap: Dict[str, int]) -> bool: """ is_pypy: bool = True if "pypy" in version else False try: - opcode_obj: ModuleType = xdis.disasm.get_opcode(version, is_pypy) + version_tuple = xdis.magics.py_str2tuple(version) + opcode_obj: ModuleType = xdis.disasm.get_opcode(version_tuple, is_pypy) except KeyError: raise KeyError(f"[!] The version specified, {version}, is not supported by xdis.") xdis_opcode_map: Dict[str, int] = opcode_obj.opmap diff --git a/pydecipher/remap.py b/pydecipher/remap.py index 4c43678..781ad12 100644 --- a/pydecipher/remap.py +++ b/pydecipher/remap.py @@ -149,7 +149,8 @@ def write_remapping_file( xdis_opcode: ModuleType = None try: - xdis_opcode = xdis.disasm.get_opcode(version, is_pypy=False) + version_tuple = xdis.magics.py_str2tuple(version) + xdis_opcode = xdis.disasm.get_opcode(version_tuple, is_pypy=False) except Exception: logger.debug(f"[!] Couldn't retrieve version {version} from xdis! Continuing anyway...") @@ -285,7 +286,8 @@ def fill_opmap_gaps(remappings: Dict[int, int], version: str) -> Dict[int, Tuple filled_remappings: Dict[int, Tuple[int, bool]] = {k: (v, False) for k, v in remappings.items()} is_pypy: bool = True if "pypy" in version else False try: - opcode_obj: ModuleType = xdis.disasm.get_opcode(version, is_pypy) + version_tuple = xdis.magics.py_str2tuple(version) + opcode_obj: ModuleType = xdis.disasm.get_opcode(version_tuple, is_pypy) except KeyError: raise KeyError(f"[!] The version specified, {version}, is not supported by xdis.") xdis_opcode_map: Dict[str, int] = opcode_obj.opmap @@ -348,13 +350,14 @@ def megafile_remap( ( reference_filename, reference_co, - reference_version, + version_tuple, reference_timestamp, reference_magic_int, reference_is_pypy, reference_source_size, reference_sip_hash, ) = xdis.disasm.disassemble_file(str(reference_megafile), outstream=open(os.devnull, "w")) + reference_version = xdis.magics.version_tuple_to_str(version_tuple) fixed_megafile_file: pathlib.Path if fixed_megafile_file := artifact_types.pyc.Pyc.check_and_fix_pyc( @@ -378,13 +381,14 @@ def megafile_remap( ( remapped_filename, remapped_co, - remapped_version, + version_tuple, remapped_timestamp, remapped_magic_int, remapped_is_pypy, remapped_source_size, remapped_sip_hash, ) = xdis.disasm.disassemble_file(str(remapped_bytecode_path), outstream=open(os.devnull, "w")) + remapped_version = xdis.magics.version_tuple_to_str(version_tuple) except Exception as e: e: Exception logger.debug(f"Error disassembling remap megafile: {e}") @@ -427,7 +431,8 @@ def opcode_constants_remap( def get_nearest_opcode(opname: str, unused_opcodes: List[int], version: str) -> int: xdis_opcode: ModuleType try: - xdis_opcode = xdis.disasm.get_opcode(version, is_pypy=False) + version_tuple = xdis.magics.py_str2tuple(version) + xdis_opcode = xdis.disasm.get_opcode(version_tuple, is_pypy=False) actual_opcode = getattr(xdis_opcode, opname) except Exception: return unused_opcodes[0] @@ -458,9 +463,10 @@ def get_nearest_opcode(opname: str, unused_opcodes: List[int], version: str) -> source_size: int sip_hash: str try: - (filename, co, version, timestamp, magic_int, is_pypy, source_size, sip_hash) = xdis.disasm.disassemble_file( + (filename, co, version_tuple, timestamp, magic_int, is_pypy, source_size, sip_hash) = xdis.disasm.disassemble_file( str(opcode_file), header=True, outstream=open(os.devnull, "w") ) + version = xdis.magics.version_tuple_to_str(version_tuple) except Exception as e: e: Exception logger.error(f"[!] Couldn't disassemble opcode file {opcode_file} with error: {e}") @@ -522,7 +528,8 @@ def get_nearest_opcode(opname: str, unused_opcodes: List[int], version: str) -> break is_pypy: bool = "pypy" in xdis.magics.magicint2version[magic_int] - opc: ModuleType = xdis.disasm.get_opcode(version, is_pypy) + version_tuple = xdis.magics.py_str2tuple(version) + opc: ModuleType = xdis.disasm.get_opcode(version_tuple, is_pypy) remappings: Dict[int, Dict[int, int]] = {} # We need to match the format of the other remappings method's return values @@ -656,13 +663,14 @@ def standard_pyc_remap( ( remapped_filename, remapped_co, - remapped_version, + version_tuple, remapped_timestamp, remapped_magic_int, remapped_is_pypy, remapped_source_size, remapped_sip_hash, ) = xdis.disasm.disassemble_file(str(pyc_filepath), header=True, outstream=open(os.devnull, "w")) + remapped_version = xdis.magics.version_tuple_to_str(version_tuple) reference_filename: str reference_co: CodeType # can also be xdis codetypes @@ -675,13 +683,14 @@ def standard_pyc_remap( ( reference_filename, reference_co, - reference_version, + version_tuple, reference_timestamp, reference_magic_int, reference_is_pypy, reference_source_size, reference_sip_hash, ) = xdis.disasm.disassemble_file(str(reference_file), outstream=open(os.devnull, "w")) + reference_version = xdis.magics.version_tuple_to_str(version_tuple) except Exception: continue diff --git a/setup.py b/setup.py index 2b83b39..250a44f 100644 --- a/setup.py +++ b/setup.py @@ -47,12 +47,12 @@ "Topic :: Software Development :: Disassemblers", ], install_requires=[ - "xdis>=5.0.8", + "xdis>=6.0.0", "python-magic", "argparse", "six", "pefile", - "uncompyle6", + "uncompyle6>=3.9.0", "signify>=0.3.0", "asn1crypto", "pycryptodome",