Sometimes we can't get around a C dependency, and I don't think it'll be possible to load those from memory any time soon... So in those cases we may want to drop them to a temporary directory on disk, and insert them into our search path for modules.
I've previously done that using this piece of code as run.py, but ideally it gets integrated into pystandalone itself:
import os
import sys
import runpy
import argparse
import tempfile
import zipimport
import subprocess
from pathlib import Path
def unpack_dist(tmpdir):
tmppath = Path(tmpdir)
# Find decrypted payload zip
payload_zip = None
for loader in sys.meta_path:
if hasattr(loader, 'archive') and loader.archive == '<payload>':
payload_zip = loader
break
if not payload_zip:
sys.exit("No payload zip")
for f, toc_entry in payload_zip._files.items():
if f.endswith('/'):
continue
if f.startswith('dist'):
out_path = tmppath.joinpath(os.path.normpath(f))
if not out_path.parent.exists():
out_path.parent.mkdir(parents=True)
data = zipimport._get_data(payload_zip.archive, toc_entry, payload_zip._buf)
out_path.write_bytes(data)
return str(tmppath.joinpath('dist'))
def run_loader(key):
with tempfile.TemporaryDirectory(prefix='thunderx-decrypt-') as tmpdir:
dist_dir = unpack_dist(tmpdir)
print('Unpacked dist to {}'.format(dist_dir))
sys.argv.insert(1, key)
subprocess.run(sys.argv + ['--lib', dist_dir])
if __name__ == '__main__':
key = sys.argv.pop(1)
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('--lib', help=argparse.SUPPRESS)
args, remaining = parser.parse_known_args()
if not args.lib:
run_loader(key)
else:
sys.path.insert(0, args.lib)
sys.argv = [sys.argv[0]] + remaining
runpy._run_module_as_main('decrypt', alter_argv=False)
Sometimes we can't get around a C dependency, and I don't think it'll be possible to load those from memory any time soon... So in those cases we may want to drop them to a temporary directory on disk, and insert them into our search path for modules.
I've previously done that using this piece of code as run.py, but ideally it gets integrated into pystandalone itself: