Skip to content

Instantly share code, notes, and snippets.

@uyjulian
Last active May 31, 2023 00:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save uyjulian/1ca6d4980798beae305a68ffc79bc420 to your computer and use it in GitHub Desktop.
Save uyjulian/1ca6d4980798beae305a68ffc79bc420 to your computer and use it in GitHub Desktop.
# References:
# https://github.com/ashang/unar/blob/473488cc612c3f47e1c76f9baf92d268db259dc1/XADMaster/XADRPMParser.m
# https://refspecs.linuxbase.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/pkgformat.html
import os
import sys
import hashlib
with open(sys.argv[1], "r+b") as f:
lead_header_bytes = f.read(4)
if lead_header_bytes == b"\xED\xAB\xEE\xDB":
f.seek(92, os.SEEK_CUR) # skip rest of lead
signature_header_bytes = f.read(4)
if signature_header_bytes == b"\x8E\xAD\xE8\x01":
f.seek(4, os.SEEK_CUR)
signature_entries = int.from_bytes(f.read(4), byteorder="big")
signature_bytes = int.from_bytes(f.read(4), byteorder="big")
signature_entries_bytes = f.read(signature_entries * 16)
signature_bytes_start = f.tell()
signature_bytes_bytes = f.read((signature_bytes + 7) & (7 ^ 0xffffffff))
signature_entries_list = []
for i in range(signature_entries):
base = (i * 16)
signature_entries_list.append(
{
"tag" : int.from_bytes(signature_entries_bytes[base + 0:base + 4], byteorder="big"),
"type" : int.from_bytes(signature_entries_bytes[base + 4:base + 8], byteorder="big"),
"offset" : int.from_bytes(signature_entries_bytes[base + 8:base + 12], byteorder="big"),
"count" : int.from_bytes(signature_entries_bytes[base + 12:base + 16], byteorder="big"),
}
)
for x in signature_entries_list:
if x["type"] == 4:
x["data"] = int.from_bytes(signature_bytes_bytes[x["offset"]:x["offset"] + (x["count"] * 4)], byteorder="big")
if x["type"] == 7:
x["data"] = signature_bytes_bytes[x["offset"]:x["offset"] + (x["count"] * 4)]
data = f.read()
data_len = len(data)
data_md5 = hashlib.md5(data).digest()
for x in signature_entries_list:
if x["tag"] == 1000 and x["count"] == 1:
f.seek(signature_bytes_start + x["offset"])
f.write(data_len.to_bytes(byteorder="big", length=4))
if x["tag"] == 1004 and x["count"] == 16:
f.seek(signature_bytes_start + x["offset"])
f.write(data_md5)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment