Prepare documented WhatsApp injector with portable Python bundle
This commit is contained in:
commit
d2b621bce7
49 files changed
+5737
No files matched your search
@@ -0,0 +1,100 @@
|
||||
"""Build a deterministic single Python file; run this only for development."""
|
||||
import base64
|
||||
import hashlib
|
||||
import io
|
||||
import json
|
||||
import lzma
|
||||
from pathlib import Path
|
||||
import textwrap
|
||||
import zipfile
|
||||
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
|
||||
BOOTSTRAP = '''#!/usr/bin/env python3
|
||||
"""Portable WhatsApp suite: python whatsapp.py --help
|
||||
|
||||
All Python modules, native helpers and regression fixtures are embedded.
|
||||
Only native DLLs are cached beside this file when a live command needs them.
|
||||
Core commands use the standard library. Legacy CDP/Frida/QR commands retain
|
||||
their optional dependencies. Live WebView probes require the supported
|
||||
WhatsApp Desktop build, Windows x64 and 64-bit Python 3.11+.
|
||||
Generated by build_whatsapp_bundle.py; edit the development sources to rebuild.
|
||||
"""
|
||||
import base64
|
||||
import hashlib
|
||||
import importlib.abc
|
||||
import importlib.util
|
||||
import io
|
||||
import lzma
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import zipfile
|
||||
|
||||
PAYLOAD_SHA256 = __DIGEST__
|
||||
PAYLOAD = (
|
||||
__PAYLOAD__
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
compressed = base64.b85decode(PAYLOAD)
|
||||
if hashlib.sha256(compressed).hexdigest() != PAYLOAD_SHA256:
|
||||
raise RuntimeError('Bundle integrity check failed')
|
||||
archive = zipfile.ZipFile(io.BytesIO(lzma.decompress(compressed)))
|
||||
members = frozenset(archive.namelist())
|
||||
launcher = Path(__file__).resolve()
|
||||
|
||||
class EmbeddedModules(importlib.abc.MetaPathFinder, importlib.abc.Loader):
|
||||
def find_spec(self, fullname, path=None, target=None):
|
||||
relative = fullname.replace('.', '/')
|
||||
for name, package in ((relative + '/__init__.py', True), (relative + '.py', False)):
|
||||
if name in members:
|
||||
return importlib.util.spec_from_loader(fullname, self, is_package=package)
|
||||
return None
|
||||
|
||||
def create_module(self, spec):
|
||||
return None
|
||||
|
||||
def exec_module(self, module):
|
||||
relative = module.__name__.replace('.', '/')
|
||||
name = relative + ('/__init__.py' if module.__spec__.submodule_search_locations is not None else '.py')
|
||||
module.__file__ = str(launcher) + '!' + name
|
||||
exec(compile(archive.read(name), module.__file__, 'exec'), module.__dict__)
|
||||
|
||||
sys._whatsapp_bundle = {'base': launcher.parent, 'launcher': launcher, 'read': archive.read}
|
||||
sys.meta_path.insert(0, EmbeddedModules())
|
||||
from whatsapp_suite.cli import main as cli
|
||||
return cli()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
raise SystemExit(main())
|
||||
'''
|
||||
|
||||
|
||||
def main():
|
||||
files={p.relative_to(ROOT).as_posix():p.read_bytes() for p in sorted((ROOT/'whatsapp_suite').glob('*.py'))}
|
||||
for name in ('math_probe.dll','search_probe.dll','sqlite_inject.js'):
|
||||
files['whatsapp_suite/assets/'+name]=(ROOT/'whatsapp_suite/assets'/name).read_bytes()
|
||||
files['whatsapp_suite/_regression.py']=(ROOT/'tests/test_whatsapp_suite.py').read_bytes()
|
||||
for p in sorted((ROOT/'tests').glob('*.cjs')):
|
||||
files['tests/'+p.name]=p.read_bytes()
|
||||
# Whole-archive compression shares repeated source and native-helper bytes.
|
||||
memory=io.BytesIO()
|
||||
with zipfile.ZipFile(memory,'w',compression=zipfile.ZIP_STORED) as archive:
|
||||
for name,data in sorted(files.items()):
|
||||
entry=zipfile.ZipInfo(name,date_time=(1980,1,1,0,0,0))
|
||||
archive.writestr(entry,data)
|
||||
payload=lzma.compress(memory.getvalue(),preset=9)
|
||||
encoded=base64.b85encode(payload).decode('ascii')
|
||||
lines='\n'.join(' '+repr(line) for line in textwrap.wrap(encoded,100,break_on_hyphens=False))
|
||||
source=BOOTSTRAP.replace('__DIGEST__',repr(hashlib.sha256(payload).hexdigest())).replace('__PAYLOAD__',lines)
|
||||
destination=ROOT/'whatsapp.py'
|
||||
destination.write_text(source,encoding='utf-8',newline='\n')
|
||||
report={'bundle':destination.name,'bundle_bytes':destination.stat().st_size,'embedded_source_and_asset_bytes':sum(map(len,files.values())),'files_embedded':len(files),'sha256':hashlib.sha256(destination.read_bytes()).hexdigest()}
|
||||
(ROOT/'analysis/whatsapp-suite').mkdir(parents=True, exist_ok=True)
|
||||
(ROOT/'analysis/whatsapp-suite/bundle-build.json').write_text(json.dumps(report,indent=2),encoding='utf-8')
|
||||
print(json.dumps(report))
|
||||
|
||||
|
||||
if __name__=='__main__':main()
|
||||
Reference in new issue
Block a user