mirror of https://gitlab.com/PoroCYon/vondehi
add zstd support, add autovndh to repo
This commit is contained in:
parent
243908254c
commit
036268783e
|
@ -0,0 +1,220 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
import itertools
|
||||
import os, os.path
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
import multiprocessing
|
||||
import multiprocessing.dummy as multi
|
||||
|
||||
verbose = 0
|
||||
|
||||
def is_exec(p):
|
||||
return (p is not None) and os.path.isfile(p) and os.access(p, os.X_OK)
|
||||
|
||||
def eprint(*args, **kwargs): print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
def run_proc_get_stdout(cmdlin):
|
||||
try:
|
||||
if verbose > 1: eprint(cmdlin)
|
||||
proc = subprocess.Popen(cmdlin, stdout=subprocess.PIPE)
|
||||
output = proc.stdout.read()
|
||||
proc.wait()
|
||||
if proc.returncode != 0:
|
||||
if verbose > 1: eprint("-> " + str(proc.returncode))
|
||||
elif verobse > 0:
|
||||
eprint(str(cmdlin)+" -> " + str(proc.returncode))
|
||||
return None if proc.returncode != 0 else output
|
||||
except KeyboardInterrupt:
|
||||
exit(1)
|
||||
except Exception as e:
|
||||
return None
|
||||
|
||||
|
||||
def run_one(binf, opt, input_file):
|
||||
return run_proc_get_stdout([binf]+opt+[input_file])
|
||||
|
||||
def run_compr(compr, mpool,inp):
|
||||
binf, opt, isgz = compr
|
||||
|
||||
return list(filter(lambda x: x[0] is not None,
|
||||
mpool.map(lambda o: (run_one(binf,o,inp), isgz), opt)))
|
||||
|
||||
def do_vndh(bin_nasm,vndh_dir,brute_result,vtag,vfork,vunibin,vcheat,vnoargv):
|
||||
blob, isgz = brute_result
|
||||
vndh_src = os.path.join(vndh_dir, "vondehi.asm")
|
||||
if not os.path.isfile(vndh_src):
|
||||
eprint("vondehi src file doesn't exist.")
|
||||
return None
|
||||
|
||||
cmdlin = [bin_nasm,"-fbin","-o/dev/stdout"]
|
||||
if isgz == 2: cmdlin.append('-DUSE_ZSTD')
|
||||
elif isgz: cmdlin.append("-DUSE_GZIP")
|
||||
if vtag is not None: cmdlin.append('-DTAG='+vtag)
|
||||
if vfork: cmdlin.append('-DUSE_VFORK')
|
||||
if vunibin: cmdlin.append('-DNO_UBUNTU_COMPAT')
|
||||
if not vcheat: cmdlin.append('-DNO_CHEATING')
|
||||
if not vnoargv: cmdlin.append('-DWANT_ARGV')
|
||||
cmdlin.append(vndh_src)
|
||||
|
||||
vbl = run_proc_get_stdout(cmdlin)
|
||||
return None if vbl is None else (vbl + blob)
|
||||
|
||||
|
||||
opt_xz_lzma = [
|
||||
[ 'dict=8M' ],
|
||||
[ 'lc=0,lp=0', 'lc=0,lp=1', 'lc=0,lp=2', 'lc=0,lp=3', 'lc=0,lp=4',
|
||||
'lc=1,lp=0', 'lc=1,lp=1', 'lc=1,lp=2', 'lc=1,lp=3',
|
||||
'lc=2,lp=0', 'lc=2,lp=1', 'lc=2,lp=2',
|
||||
'lc=3,lp=0', 'lc=3,lp=1',
|
||||
'lc=4,lp=0' ],
|
||||
[ 'pb=0', 'pb=1', 'pb=2', 'pb=3', 'pb=4' ],
|
||||
[ 'mf=bt4', 'mf=hc4' ],
|
||||
[ 'mode=normal' ],
|
||||
[ 'nice=273' ],
|
||||
[ 'depth=1000' ]
|
||||
]
|
||||
|
||||
|
||||
opt_gzip = [["-cnk9"]]
|
||||
opt_xz = list(map(lambda x: ['--stdout','--keep']+sum(x,[]),itertools.product(\
|
||||
[[],['--x86'],['--delta'],['--x86','--delta'],['--delta','--x86']],\
|
||||
map(lambda opts: ['--lzma2='+','.join(opts)], itertools.product(*opt_xz_lzma))
|
||||
)))
|
||||
opt_lzma = list(map(lambda opts: ['--stdout','--keep','--lzma1='+','.join(opts)], \
|
||||
itertools.product(*opt_xz_lzma)))
|
||||
opt_zopfli = [['--gzip','--i1024','-c']]
|
||||
opt_zstd = [['-z','--ultra','-22','--no-check','--no-dictID','-c','-k','--format=zstd']]
|
||||
|
||||
def main(opts):
|
||||
global verbose
|
||||
if opts.verbose is not None:
|
||||
verbose = opts.verbose
|
||||
|
||||
if verbose>1:opt_zopfli[0].append('-v')
|
||||
|
||||
if not is_exec(opts.nasm):
|
||||
eprint("nasm binary not found, doesn't exist or is not executable.")
|
||||
return
|
||||
|
||||
if not is_exec(opts.gzip ): opts.gzip = None
|
||||
if not is_exec(opts.xz ): opts.xz = None
|
||||
if not is_exec(opts.lzma ): opts.lzma = None
|
||||
if not is_exec(opts.zopfli): opts.zopfli = None
|
||||
|
||||
comprs = sum([ \
|
||||
[(opts.gzip , opt_gzip , True )] if opts.gzip is not None else [],
|
||||
[(opts.xz , opt_xz , False)] if opts.xz is not None else [],
|
||||
[(opts.lzma , opt_lzma , False)] if opts.lzma is not None else [],
|
||||
[(opts.zopfli, opt_zopfli, True )] if opts.zopfli is not None else [],
|
||||
[(opts.zstd , opt_zstd , 2 )] if opts.zstd is not None else [] \
|
||||
], [])
|
||||
|
||||
if len(comprs) == 0:
|
||||
eprint("No compression methods specified.")
|
||||
return
|
||||
|
||||
mpool = multi.Pool(processes=opts.jobs)
|
||||
|
||||
allofthem = list(sum(map(lambda x: run_compr(x, mpool, opts.input_file),
|
||||
comprs),[]))
|
||||
|
||||
if len(allofthem) == 0:
|
||||
eprint("No useable results available. See error log.")
|
||||
return
|
||||
|
||||
allofthem_s = sorted(allofthem, key=lambda x:len(x[0]))
|
||||
|
||||
best = allofthem_s[0]
|
||||
|
||||
if verbose > 0:
|
||||
lbl = "xz"
|
||||
if best[1] == 2:
|
||||
lbl = "zstd"
|
||||
elif best[1]:
|
||||
lbl = "gzip"
|
||||
eprint(len(best[0]), lbl)
|
||||
|
||||
res, stubbed = best[0], None
|
||||
if not opts.nostub:
|
||||
stubbed = do_vndh(opts.nasm, opts.vndh, best,
|
||||
opts.vndh_tag, opts.vndh_vfork, opts.vndh_unibin,
|
||||
opts.vndh_cheat,opts.vndh_no_argv)
|
||||
|
||||
if verbose > 0: eprint("final: "+str(len(res)))
|
||||
|
||||
opts.output_file.write(stubbed or res)
|
||||
if stubbed is not None and opts.rawout is not None:
|
||||
opts.rawout.write(res)
|
||||
|
||||
if __name__=='__main__':
|
||||
p = argparse.ArgumentParser(description="""\
|
||||
Computes the smallest possible compressed size of a binary through
|
||||
brute-forcing, and then automatically vondehi-packs the result using the
|
||||
correct flags.
|
||||
""")
|
||||
|
||||
p.add_argument('input_file', type=str, metavar='input',
|
||||
help='The executable file to compress')
|
||||
p.add_argument('output_file', type=argparse.FileType('wb'), metavar='output',
|
||||
default=sys.stdout.buffer, nargs='?',
|
||||
help='Output file (defaults to stdout)')
|
||||
|
||||
p.add_argument('--nostub', '-n', action='store_true',
|
||||
help="Don't prepend a vondehi stub, only compress the input data.")
|
||||
|
||||
p.add_argument('--verbose', '-v', action='count',
|
||||
help='Increase verbosity level (0..2)')
|
||||
p.add_argument('--gzip', '-g', nargs='?', const=shutil.which('gzip'),
|
||||
default=None, type=str, help='Enable gzip compression, and'+
|
||||
' optionally specify which gzip binary to use.')
|
||||
p.add_argument('--xz', '-x', nargs='?', const=shutil.which('xz'), type=str,
|
||||
default=None, help='Enable xz (LZMA2) compression, and ' +
|
||||
'optionally specify which xz binary to use.')
|
||||
p.add_argument('--lzma', '-l', const=shutil.which('lzma'), type=str,
|
||||
nargs='?', default=None, help='Enable LZMA1 compression '+
|
||||
'(using xz), and optionally specify which lzma binary to '+
|
||||
'use.')
|
||||
p.add_argument('--zopfli', '-z', const=shutil.which('zopfli'), nargs='?',
|
||||
type=str, default=None, help='Enable Zopfli-based gzip '+
|
||||
'compression, and optionally specify which zopfli binary to'+
|
||||
' use.')
|
||||
p.add_argument('--zstd', '-Z', const=shutil.which('zstd'), nargs='?',
|
||||
type=str, default=None, help='Enable Zstd-based '+
|
||||
'compression, and optionally specify which Zstd binary to'+
|
||||
' use.')
|
||||
|
||||
p.add_argument('--nasm', type=str, default=shutil.which('nasm'),
|
||||
help='nasm binary to use')
|
||||
p.add_argument('--vndh', type=str, default='ext/vondehi',
|
||||
help='Directory of the vondehi source code')
|
||||
|
||||
p.add_argument('--jobs', '-j', type=int, default=multiprocessing.cpu_count(),
|
||||
help="Number of jobs that run in parallel for the bruteforcing")
|
||||
|
||||
p.add_argument('--vndh_tag', type=str, help="Vanity tag to pass to vondehi")
|
||||
p.add_argument('--vndh_vfork', action='store_true',
|
||||
help="Tell vondehi to use vfork(2)")
|
||||
p.add_argument('--vndh_unibin', action='store_true', help="Disable "+
|
||||
"compatibility with distributions that keep /bin and "+
|
||||
"/usr/bin separate.")
|
||||
p.add_argument('--vndh_cheat', action='store_true', help="Assume file "+
|
||||
"descriptor numbers and hope arguments and environment "+
|
||||
"variables are passed correctly by chance to the payload."+
|
||||
" You cannot use this if you're running on Wayland.")
|
||||
p.add_argument('--vndh_no_argv', action='store_true', help="Don't properly"+
|
||||
" keep track of the stack location, makes argv passing bork"+
|
||||
" but saves a few bytes. Only in effect if --vndh_cheat is "+
|
||||
"not enabled.")
|
||||
|
||||
p.add_argument('--rawout', type=argparse.FileType('wb'),
|
||||
help='File to write the raw compressed data to (if --vndh is enabled).')
|
||||
|
||||
main(p.parse_args(sys.argv[1:]))
|
||||
|
11
vondehi.asm
11
vondehi.asm
|
@ -171,14 +171,25 @@ __self:
|
|||
__strempty:
|
||||
db 0
|
||||
__zip:
|
||||
%ifdef USE_ZSTD
|
||||
%ifndef NO_UBUNTU_COMPAT
|
||||
db '/usr'
|
||||
%endif
|
||||
db '/bin/zstdcat',0
|
||||
%else
|
||||
; !USE_ZSTD
|
||||
%ifdef USE_GZIP
|
||||
db '/bin/zcat',0
|
||||
%else
|
||||
; !USE_ZSTD && !USE_GZIP
|
||||
%ifndef NO_UBUNTU_COMPAT
|
||||
db '/usr'
|
||||
%endif
|
||||
db '/bin/xzcat',0
|
||||
%endif
|
||||
; ^ end USE_GZIP
|
||||
%endif
|
||||
; ^ end USE_ZSTD
|
||||
|
||||
; if you insist
|
||||
%ifdef TAG
|
||||
|
|
Loading…
Reference in New Issue