def _unpack(t): with TemporaryDirectory() as unpack_dir: file, unpacked_file = t unpacked = f"{unpack_dir}/unpacked.exe" sample = Sample(file) event = threading.Event() client = SimpleClient(event) heartbeat = RepeatedTimer(120, print, "- still running -", file=sys.stderr) engine = UnpackerEngine(sample, unpacked) engine.register_client(client) heartbeat.start() threading.Thread(target=engine.emu).start() event.wait() heartbeat.stop() engine.stop() assert os.path.exists(unpacked) assert not os.path.exists( sample.unpacker.dumper.brokenimport_dump_file) if os.path.exists(unpacked): return file, calc_md5(unpacked).hexdigest(), calc_md5( unpacked_file).hexdigest() else: return file, '', calc_md5(unpacked_file)
def prepare_test(self, sample_path): sample = Sample(sample_path) unpacker, _ = get_unpacker(sample) event = threading.Event() client = SimpleClient(event) heartbeat = RepeatedTimer(120, print, "- still running -", file=sys.stderr) engine = UnpackerEngine(sample) engine.register_client(client) heartbeat.start() threading.Thread(target=engine.emu).start() event.wait() heartbeat.stop() engine.stop() print(f"\n--- Emulation of {os.path.basename(sample_path)} finished ---")
def unpack_if_applicable( self, sample: JVSample, inplace=True): dest = sample.file + '_unipacker_' uni_sample = None if not sample.file_type.lower().startswith('pe'): return [sample] try: with redirect_std() as unipacker_logs: logs = None uni_sample = Sample( sample.file, True) unpacker = uni_sample.unpacker.__class__.__name__.lower().replace( 'unpacker', '') dest = dest + unpacker if not 'default' in unpacker and not unpacker in sample.packers: engine = UnpackerEngine(uni_sample, dest) event = threading.Event() client = SimpleClient(event) engine.register_client(client) threading.Thread(target=engine.emu).start() event.wait() engine.stop() if os.path.exists(dest): os.remove(sample.file) sample.file_type = get_file_type(dest) os.rename(dest, sample.file) sample._sha256 = None sample.add_packer(unpacker) return [sample] # dest = str(Path(file).with_suffix('')) + '_upx.bin' except Exception as e: traceback.print_exc() print(str(e)) if os.path.exists(dest): os.remove(dest) finally: # if uni_sample: # tmp_file = uni_sample.unpacker.dumper.brokenimport_dump_file # if os.path.exists(tmp_file): # os.remove(tmp_file) pass return [sample]
def sample_loop(self, samples=None): known_samples = self.init_banner_and_history() if not samples: sample_path = self.get_path_from_user(known_samples) samples = Sample.get_samples(sample_path) for self.sample in samples: print(f"\nNext up: {self.sample}") with open(".unpacker_history", "w") as f: f.writelines("\n".join( sorted( set([ f"{self.sample.unpacker.name};{self.sample.path}" ] + known_samples[:-1])))) self.init_engine() with open(f"{os.path.dirname(unipacker.__file__)}/fortunes") as f: fortunes = f.read().splitlines() print(f"\n\x1b[31m{choice(fortunes)}\x1b[0m\n") self.cmdloop() if self.clear_queue: break
def __init__(self): try: Cmd.__init__(self) self.allow_cli_args = False builtins.print = self.shell_print self.histfile = ".unpacker_history" self.clear_queue = False self.sample = None parser = argparse.ArgumentParser( prog='unipacker', description= 'Automatic and platform-independent unpacker for Windows binaries based on emulation' ) parser.add_argument( 'samples', metavar='sample', type=file_or_dir, nargs='*', help= 'The path to a sample (or directory containing samples) you want unpacked' ) parser.add_argument( '-d', '--dest', nargs='?', default='.', help='The destination directory for unpacked binaries') parser.add_argument('-p', '--partition-by-packer', action='store_true', help='Group the unpacked files by packer') parser.add_argument( '-i', '--interactive', action='store_true', help='Open the chosen sample(s) in the un{i}packer shell') parser.add_argument('--version', action='store_true', help='Show version information and exit') args = parser.parse_args() if args.version: print_version_and_exit() if args.samples: samples = [] for s in args.samples: if os.path.exists(s): samples.extend( Sample.get_samples(s, interactive=args.interactive)) else: print(f"Path does not exist: {s}") if args.interactive: while True: self.sample_loop(samples) self.shell_event.wait() samples = None else: IOHandler(samples, args.dest, args.partition_by_packer) else: while True: self.sample_loop() self.shell_event.wait() except EOFError: with open(f"{os.path.dirname(unipacker.__file__)}/fortunes") as f: fortunes = f.read().splitlines() print(f"\n\x1b[31m{choice(fortunes)}\x1b[0m\n") sys.exit(0)