Last active
January 8, 2018 16:37
-
-
Save q3hardcore/35fa3fab5d8baf5fff79b6dba5d61ac6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
'''convert payload to zip''' | |
import struct | |
import sys | |
import zipfile | |
import datetime | |
import io | |
import lzma | |
def get_chunk(payload, chunknum): | |
'''reads a chunk, decompressing if necessary''' | |
chunkheader = payload.read(16) | |
if len(chunkheader) < 16: | |
return | |
uncompsize, compsize = struct.unpack('>QQ', chunkheader) | |
print('chunk #%03d, uncompressed size %d, compressed size %d' % ( | |
chunknum, uncompsize, compsize)) | |
chunkdata = payload.read(compsize) | |
if uncompsize != compsize: | |
chunkdata = lzma.decompress(chunkdata, lzma.FORMAT_XZ) | |
return io.BytesIO(chunkdata) | |
def main(): | |
'''entry point''' | |
if len(sys.argv) < 3: | |
print('Usage: %s In Out (PayloadPath)' % sys.argv[0]) | |
sys.exit(1) | |
instr = sys.argv[1] | |
outstr = sys.argv[2] | |
if instr[-4:] == '.zip': | |
infile = zipfile.ZipFile(instr, 'r') | |
payload = infile.open(sys.argv[3] if len(sys.argv) > 3 else 'AssetData/payloadv2/payload') | |
else: | |
infile = payload = open(instr, 'rb') | |
if payload.read(12)[:4] != b'pbzx': | |
print('not pbzx') | |
infile.close() | |
return | |
main.chunknum = 1 | |
main.curchunk = get_chunk(payload, main.chunknum) | |
def safe_read(reqlen): | |
'''read data from chunks contiguously''' | |
if not main.curchunk: | |
return b'' | |
totalread = b'' | |
while True: | |
thisread = main.curchunk.read(reqlen) | |
reqlen -= len(thisread) | |
totalread += thisread | |
if reqlen <= 0: | |
return totalread | |
main.chunknum += 1 | |
main.curchunk = get_chunk(payload, main.chunknum) | |
if not main.curchunk: | |
return b'' | |
header = safe_read(30) | |
outzip = zipfile.ZipFile(outstr, 'w', allowZip64=True) | |
while header: | |
kind, _a, filesize, _b, timestamp, _c, namelen, uid, gid, perms = ( | |
struct.unpack('>IHIIIIHHHH', header)) | |
filename = safe_read(namelen).decode('utf-8') | |
if not filename: | |
print('truncated') | |
break | |
extra1 = struct.pack('<HHBI', 0x5455, 5, 1, timestamp) | |
extra2 = struct.pack('<HHHH', 0x7855, 4, uid, gid) | |
zinfo = zipfile.ZipInfo(filename, datetime.datetime.utcfromtimestamp(timestamp).timetuple()) | |
zinfo.extra = extra1 + extra2 | |
zinfo.create_system = 3 | |
zinfo.external_attr = perms << 16 | |
if kind == 0x10020000: | |
zinfo.filename += '/' | |
zinfo.external_attr |= 0x10 | |
outzip.writestr(zinfo, safe_read(filesize)) | |
zinfo.extra = extra1 + struct.pack('<HH', 0x7855, 0) | |
header = safe_read(30) | |
outzip.close() | |
infile.close() | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment