Example #1
0
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)
Example #2
0
    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 ---")
Example #3
0
    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]
Example #4
0
    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
Example #5
0
    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)