Skip to content

Instantly share code, notes, and snippets.

@juhovh
Created April 20, 2020 14:53
Show Gist options
  • Save juhovh/91b500f2350555e849049fa24b130309 to your computer and use it in GitHub Desktop.
Save juhovh/91b500f2350555e849049fa24b130309 to your computer and use it in GitHub Desktop.
Decompress WeChat weapp binary file bundles (after zstd decompression)
# Decompress WeChat weapp binary file bundles (after zstd decompression)
import os
import sys
import struct
import errno
HEADER_LEN = 14
if (len(sys.argv) != 3):
print(f"Usage: {sys.argv[0]} <file.bin> <outputdir>")
sys.exit(1)
print(f"Opening file of size {os.path.getsize(sys.argv[1])}")
fin = open(sys.argv[1], "rb")
header = fin.read(HEADER_LEN)
start, pad, metalen, datalen, end = struct.unpack(">BLLLB", header)
if (start != 0xbe or pad != 0 or end != 0xed):
print("Invalid header")
sys.exit(1)
print(f"Metadata length {metalen}, data length {datalen} total {HEADER_LEN+metalen+datalen}")
item_count = struct.unpack(">L", fin.read(4))[0]
print(f"Metadata contains {item_count} items")
processed_bytes = 0
for i in range(item_count):
(namelen,) = struct.unpack(">L", fin.read(4))
filename = fin.read(namelen).decode()
filepos, filelen = struct.unpack(">LL", fin.read(8))
# Read the file data and return to same offset
offset = fin.tell()
fin.seek(filepos)
filedata = fin.read(filelen)
fin.seek(offset)
processed_bytes += filelen
# Write the file data to corresponding file
filepath = f"{sys.argv[2]}{filename}"
try:
os.makedirs(os.path.dirname(filepath))
except OSError as exc:
if exc.errno != errno.EEXIST:
raise
with open(filepath, "wb") as fout:
fout.write(filedata)
print(f"Processed file: {filename}")
print(f"Processed metadata of {fin.tell()-HEADER_LEN} bytes, reading {processed_bytes} bytes of file data")
fin.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment