Files
bikini-patchwork/patchwork/cli.py
T
2026-04-29 00:17:18 -05:00

45 lines
2.3 KiB
Python

from __future__ import annotations
import argparse
import sys
from pathlib import Path
from .core import Obfuscator
def _parser() -> argparse.ArgumentParser:
p = argparse.ArgumentParser(prog='patchwork')
p.add_argument('input')
p.add_argument('-o', '--output')
p.add_argument('--seed', type=int, default=None)
p.add_argument('--layers', type=int, default=3)
p.add_argument('--stage2-layers', type=int, default=3, dest='stage2_layers')
p.add_argument('--keep', action='append', default=[], metavar='NAME')
p.add_argument('--no-rename', action='store_true')
p.add_argument('--no-encrypt-strings', action='store_true')
p.add_argument('--no-obfuscate-numbers', action='store_true')
p.add_argument('--no-opaque', action='store_true')
p.add_argument('--no-mba', action='store_true')
p.add_argument('--no-junk', action='store_true')
p.add_argument('--no-lazy', action='store_true')
p.add_argument('--no-anti-debug', action='store_true')
p.add_argument('--quiet', '-q', action='store_true')
return p
def main(argv: list[str] | None=None) -> int:
args = _parser().parse_args(argv)
inp = Path(args.input)
if not inp.is_file():
print(f'patchwork: input file not found: {inp}', file=sys.stderr)
return 2
src = inp.read_text(encoding='utf-8')
obf = Obfuscator(seed=args.seed, rename=not args.no_rename, encrypt_strings=not args.no_encrypt_strings, obfuscate_numbers=not args.no_obfuscate_numbers, opaque_predicates=not args.no_opaque, mba=not args.no_mba, junk_branches=not args.no_junk, lazy_funcs=not args.no_lazy, anti_debug=not args.no_anti_debug, layers=args.layers, stage2_layers=args.stage2_layers, keep=set(args.keep))
out_src = obf.obfuscate(src)
out_path = Path(args.output) if args.output else inp.with_name(inp.stem + '_obf.py')
out_path.write_text(out_src, encoding='utf-8')
if not args.quiet:
in_size = len(src)
out_size = len(out_src)
ratio = out_size / max(in_size, 1)
print(f'patchwork: {inp} -> {out_path}\n input: {in_size:,} bytes\n output: {out_size:,} bytes ({ratio:.1f}x)\n seed: {obf.seed}\n layers: {obf.layers}', file=sys.stderr)
return 0
if __name__ == '__main__':
raise SystemExit(main())