def load_code(self): rand = self.r_long() length = self.r_long() seed = rng(rand, length) mt = MT19937(seed) key = [] for i in range(0, 4): key.append(mt.extract_number()) # take care of padding for size calculation sz = (length + 15) & ~0xf words = sz / 4 # convert data to list of dwords buf = self._read(sz) data = list(struct.unpack("<%dL" % words, buf)) # decrypt and convert back to stream of bytes data = tea.tea_decipher(data, key) data = struct.pack("<%dL" % words, *data) iodata = io.BytesIO(data) um = unmarshaller.Unmarshaller(iodata.read) # make sure that the rest is being marshalled with the same TYPE_CODE # dispatch method as is being used for the current code object such that we # end up with a consistent ummarshalled object structure (instead of for # example having parent code level objects being opcode-remapped and child # objects still having the obfuscated opcode-mapping. um.opcode_mapping = self.opcode_mapping um.dispatch[unmarshaller.TYPE_CODE] = self.dispatch[unmarshaller.TYPE_CODE] um.flags.append(0) um.depth = self.depth retval = um.load_code() return retval
def generate_opcode_mapping_from_zipfile(opc_map, zf, pydir): total = 0 mapped = 0 for fn in zf.namelist(): if fn[-3:] != "pyc": continue with zf.open(fn, "r") as f: data = f.read(16) ulc = unpacker.load_code_without_patching um = unmarshaller.Unmarshaller(f.read) um.dispatch[unmarshaller.TYPE_CODE] = (ulc, "TYPE_CODE") remapped_co = um.load() total += 1 # bytecompile the .py file to a .pyc file pyfn = os.path.join(pydir, fn[:-1]) optimize = 2 # level is -OO try: py_compile.compile(pyfn, cfile=None, dfile=None, doraise=True, optimize=optimize) logger.debug("succesfully compiled %s" % pyfn) except Exception: continue # load the resulting .pyc file and compare it to the dropbox one try: libfile = os.path.join(pydir, "%s.cpython-37.opt-2.pyc" % (fn[:-4])) libfile = os.path.join(os.path.dirname(libfile), "__pycache__", os.path.basename(libfile)) with open(libfile, "rb") as f: f.read(16) data = f.read() orig_co = marshal.loads(data) logger.info("mapping %s to %s" % (remapped_co.co_filename, libfile)) opc_map.map_co_objects(remapped_co, orig_co) mapped += 1 except FileNotFoundError: continue logger.info("Total .pyc files processed: %d" % total) logger.info("Total .pyc files mapped to Python standard library: %d" % mapped)
def decompile_pycfiles_from_zipfile(opc_map, zf, outdir): failed = 0 processed = 0 for fn in zf.namelist(): if fn[-3:] != "pyc": continue with zf.open(fn, "r") as f: processed += 1 logger.info("Decrypting, patching and decompiling %s" % fn) try: f.read(16) um = unmarshaller.Unmarshaller(f.read) um.opcode_mapping = opc_map um.dispatch[unmarshaller.TYPE_CODE] = (load_code_with_patching, "TYPE_CODE") co = um.load() outfn = os.path.join(outdir, fn[:-1]) ok, res = decompile_co_object(co) if not ok: logger.warning("Failed to decompile %s to %s" % (fn, outfn)) failed += 1 else: logger.info("Successfully decompiled %s to %s" % (fn, outfn)) partial_dirname = os.path.dirname(fn) full_dirname = os.path.join(outdir, partial_dirname) os.makedirs(full_dirname, exist_ok=True) with open(outfn, "wb") as outfd: outfd.write(res.encode("utf-8")) except Exception as e: failed += 1 logger.error("Exception %s occured" % str(e)) break logger.info("Processed %d files (%d succesfully decompiled, %d failed)" % (processed, processed - failed, failed))
"e27eae61e774b19f4053361e523c771a92e838026da42c60e6b097d9cb2bc825", "dropbox/webdebugger/server.pyc": "5df50a9c69f00ac71f873d02ff14f3b86e39600312c0b603cbb76b8b8a433d3f" } results = {} replace_str = hashlib.sha256(b"ANVILVENTURES").hexdigest() with zipfile.PyZipFile(ns.dropbox_zip, "r", zipfile.ZIP_DEFLATED) as zf: for fn in [x for x in zf.namelist() if x in hashes]: with zf.open(fn, "r") as f: data = f.read(12) ulc = unpacker.load_code_without_patching um = unmarshaller.Unmarshaller(f.read) um._read = read_wrapper(um, f.read) # XXX dirty um.dispatch[unmarshaller.TYPE_CODE] = (replace_hash( hashes[fn], replace_str), "TYPE_CODE") co = um.load() with io.BytesIO() as out: out.write(data) m = unmarshaller.Marshaller(out.write, out) m.dispatch[unmarshaller.TYPE_CODE] = (dump_code_wrapper, "TYPE_CODE") m.dump(co) out.flush() results[fn] = bytes(out.getbuffer())