Last active
June 12, 2021 12:22
-
-
Save koseki/9737a4490128bcb8b426c22a0b7c3885 to your computer and use it in GitHub Desktop.
Revisions
-
koseki revised this gist
Jun 12, 2021 . 1 changed file with 27 additions and 26 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -139,30 +139,30 @@ class HeaderTagValue(Enum): RPMTAG_PLATFORM = 1132 # https://github.com/rpm-software-management/rpm/blob/847c6f062c267c4be643be9c202141bd330a7891/lib/rpmtag.h RPMTAG_PATCHESNAME = 1133 RPMTAG_PATCHESFLAGS = 1134 RPMTAG_PATCHESVERSION = 1135 RPMTAG_CACHECTIME = 1136 RPMTAG_CACHEPKGPATH = 1137 RPMTAG_CACHEPKGSIZE = 1138 RPMTAG_CACHEPKGMTIME = 1139 RPMTAG_FILECOLORS = 1140 RPMTAG_FILECLASS = 1141 RPMTAG_CLASSDICT = 1142 RPMTAG_FILEDEPENDSX = 1143 RPMTAG_FILEDEPENDSN = 1144 RPMTAG_DEPENDSDICT = 1145 RPMTAG_SOURCEPKGID = 1146 RPMTAG_FILECONTEXTS = 1147 RPMTAG_FSCONTEXTS = 1148 RPMTAG_RECONTEXTS = 1149 RPMTAG_POLICIES = 1150 RPMTAG_PRETRANS = 1151 RPMTAG_POSTTRANS = 1152 RPMTAG_PRETRANSPROG = 1153 RPMTAG_POSTTRANSPROG = 1154 RPMTAG_DISTTAG = 1155 RPMTAG_OLDSUGGESTSNAME = 1156 RPMTAG_FILEDIGESTALGO = 5011 RPMTAG_BUGURL = 5012 @@ -183,7 +183,8 @@ class RPMLead(BigEndianStructure): class RPMHeader(BigEndianStructure): _fields_ = ( ('magic', c_char * 3), ('version', c_char), ('reserved', c_char * 4), ('nindex', c_int), ('hsize', c_int), @@ -291,4 +292,4 @@ def dump_header_structure(source, label, tag_value): print(f"[{index.position:>3}] {index.tag_name}\n{v}") print("") main(argv[1]) -
koseki created this gist
May 4, 2021 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,294 @@ #! /usr/bin/env python import struct from ctypes import * import io import re from enum import Enum from sys import argv """ Linux Standard Base Core Specification, Generic Part - 25.2. Package File Format https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/pkgformat.html """ class IndexTypeValue(Enum): NULL = 0 CHAR = 1 INT8 = 2 INT16 = 3 INT32 = 4 INT64 = 5 STRING = 6 BIN = 7 STRING_ARRAY = 8 I18NSTRING = 9 def ctype_size(self): return { self.NULL: 1, self.CHAR: 1, self.INT8: 1, self.INT16: 2, self.INT32: 4, self.INT64: 8, self.STRING: 1, self.BIN: 1, self.STRING_ARRAY: 1, self.I18NSTRING: 1, }[self] def format_char(self): format_chars = { self.INT8: 'C', self.INT16: 'H', self.INT32: 'I', self.INT64: 'L', } if self in format_chars: return format_chars[self] return None class SignatureTagValue(Enum): RPMTAG_HEADERSIGNATURES = 62 RPMTAG_HEADERIMMUTABLE = 63 RPMTAG_HEADERI18NTABLE = 100 RPMSIGTAG_SIZE = 1000 RPMSIGTAG_PAYLOADSIZE = 1007 RPMSIGTAG_SHA1 = 269 RPMSIGTAG_MD5 = 1004 RPMSIGTAG_DSA = 267 RPMSIGTAG_RSA = 268 RPMSIGTAG_PGP = 1002 RPMSIGTAG_GPG = 1005 class HeaderTagValue(Enum): RPMTAG_HEADERSIGNATURES = 62 RPMTAG_HEADERIMMUTABLE = 63 RPMTAG_HEADERI18NTABLE = 100 RPMTAG_NAME = 1000 RPMTAG_VERSION = 1001 RPMTAG_RELEASE = 1002 RPMTAG_SUMMARY = 1004 RPMTAG_DESCRIPTION = 1005 RPMTAG_SIZE = 1009 RPMTAG_DISTRIBUTION = 1010 RPMTAG_VENDOR = 1011 RPMTAG_LICENSE = 1014 RPMTAG_PACKAGER = 1015 RPMTAG_GROUP = 1016 RPMTAG_URL = 1020 RPMTAG_OS = 1021 RPMTAG_ARCH = 1022 RPMTAG_SOURCERPM = 1044 RPMTAG_ARCHIVESIZE = 1046 RPMTAG_RPMVERSION = 1064 RPMTAG_COOKIE = 1094 RPMTAG_DISTURL = 1123 RPMTAG_PAYLOADFORMAT = 1124 RPMTAG_PAYLOADCOMPRESSOR = 1125 RPMTAG_PAYLOADFLAGS = 1126 RPMTAG_PREIN = 1023 RPMTAG_POSTIN = 1024 RPMTAG_PREUN = 1025 RPMTAG_POSTUN = 1026 RPMTAG_PREINPROG = 1085 RPMTAG_POSTINPROG = 1086 RPMTAG_PREUNPROG = 1087 RPMTAG_POSTUNPROG = 1088 RPMTAG_OLDFILENAMES = 1027 RPMTAG_FILESIZES = 1028 RPMTAG_FILEMODES = 1030 RPMTAG_FILERDEVS = 1033 RPMTAG_FILEMTIMES = 1034 RPMTAG_FILEMD5S = 1035 RPMTAG_FILELINKTOS = 1036 RPMTAG_FILEFLAGS = 1037 RPMTAG_FILEUSERNAME = 1039 RPMTAG_FILEGROUPNAME = 1040 RPMTAG_FILEDEVICES = 1095 RPMTAG_FILEINODES = 1096 RPMTAG_FILELANGS = 1097 RPMTAG_DIRINDEXES = 1116 RPMTAG_BASENAMES = 1117 RPMTAG_DIRNAMES = 1118 RPMTAG_PROVIDENAME = 1047 RPMTAG_REQUIREFLAGS = 1048 RPMTAG_REQUIRENAME = 1049 RPMTAG_REQUIREVERSION = 1050 RPMTAG_CONFLICTFLAGS = 1053 RPMTAG_CONFLICTNAME = 1054 RPMTAG_CONFLICTVERSION = 1055 RPMTAG_OBSOLETENAME = 1090 RPMTAG_PROVIDEFLAGS = 1112 RPMTAG_PROVIDEVERSION = 1113 RPMTAG_OBSOLETEFLAGS = 1114 RPMTAG_OBSOLETEVERSION = 1115 RPMTAG_BUILDTIME = 1006 RPMTAG_BUILDHOST = 1007 RPMTAG_FILEVERIFYFLAGS = 1045 RPMTAG_CHANGELOGTIME = 1080 RPMTAG_CHANGELOGNAME = 1081 RPMTAG_CHANGELOGTEXT = 1082 RPMTAG_OPTFLAGS = 1122 RPMTAG_RHNPLATFORM = 1131 RPMTAG_PLATFORM = 1132 # https://github.com/rpm-software-management/rpm/blob/847c6f062c267c4be643be9c202141bd330a7891/lib/rpmtag.h RPMTAG_PATCHESNAME = 1133 RPMTAG_PATCHESFLAGS = 1134 RPMTAG_PATCHESVERSION = 1135 RPMTAG_CACHECTIME = 1136 RPMTAG_CACHEPKGPATH = 1137 RPMTAG_CACHEPKGSIZE = 1138 RPMTAG_CACHEPKGMTIME = 1139 RPMTAG_FILECOLORS = 1140 RPMTAG_FILECLASS = 1141 RPMTAG_CLASSDICT = 1142 RPMTAG_FILEDEPENDSX = 1143 RPMTAG_FILEDEPENDSN = 1144 RPMTAG_DEPENDSDICT = 1145 RPMTAG_SOURCEPKGID = 1146 RPMTAG_FILECONTEXTS = 1147 RPMTAG_FSCONTEXTS = 1148 RPMTAG_RECONTEXTS = 1149 RPMTAG_POLICIES = 1150 RPMTAG_PRETRANS = 1151 RPMTAG_POSTTRANS = 1152 RPMTAG_PRETRANSPROG = 1153 RPMTAG_POSTTRANSPROG = 1154 RPMTAG_DISTTAG = 1155 RPMTAG_OLDSUGGESTSNAME = 1156 RPMTAG_FILEDIGESTALGO = 5011 RPMTAG_BUGURL = 5012 class RPMLead(BigEndianStructure): _fields_ = ( ('magic', c_char * 4), ('major', c_char), ('minor', c_char), ('type', c_short), ('archnum', c_short), ('name', c_char * 66), ('osnum', c_short), ('signature_type', c_short), ('reserved', c_char * 16), ) class RPMHeader(BigEndianStructure): _fields_ = ( ('magic', c_char * 4), ('reserved', c_char * 4), ('nindex', c_int), ('hsize', c_int), ) class RPMHeaderIndex(BigEndianStructure): position = -1 tag_name = "Unknown" _fields_ = ( ('tag', c_int), ('type', c_int), ('offset', c_int), ('count', c_int), ) def read_string(source:io.IOBase): result = [] while True: chunk = source.read(128) i = chunk.find(b'\0') if i == -1: result.append(chunk) else: result.append(chunk[:i]) source.seek(i - 128 + 1, io.SEEK_CUR) break if len(chunk) < 128: break return b''.join(result) def read_string_array(source:io.IOBase, length:int): result = [] for i in range(length): result.append(read_string(source)) return result def main(rpmfile): source = open(rpmfile, 'rb') print("==== Lead Section ====") lead = RPMLead() source.readinto(lead) for field in lead._fields_: v = getattr(lead, field[0]) print(f"{field[0]:>10}: {v}") dump_header_structure(source, "Signature Section", SignatureTagValue) dump_header_structure(source, "Header Section", HeaderTagValue) source.close() def dump_header_structure(source, label, tag_value): print(f"==== {label} - Header ====") header = RPMHeader() source.readinto(header) for field in header._fields_: v = getattr(header, field[0]) print(f"{field[0]:>10}: {v}") print(f"==== {label} - Index Entries ====") index_entries = [] for i in range(header.nindex): e = RPMHeaderIndex() source.readinto(e) e.position = i index_entries.append(e) try: e.tag_name = tag_value(e.tag).name except: pass t = IndexTypeValue(e.type).name print(f"[{i:>3}] tag:{e.tag:>5} type: {t:<12} offset:{e.offset:>4} count:{e.count:>4} # {e.tag_name}") print(f"==== {label} - Data ====") index_entries = sorted(index_entries, key=lambda e: e.offset) start = source.tell() for index in index_entries: index_type = IndexTypeValue(index.type) size = index_type.ctype_size() source.seek(start + index.offset) if index_type == IndexTypeValue.STRING: v = read_string(source) elif index_type == IndexTypeValue.STRING_ARRAY: v = read_string_array(source, index.count) v = ' ' + '\n '.join(map(str, v)) else: v = source.read(size * index.count) format_char = index_type.format_char() if format_char: v = ' ' + '\n '.join(map(str, struct.unpack('>' + format_char * index.count, v))) else: v = re.sub('([0-9a-f]{4})', '\\1 ', re.sub('(.{32})', '\\1\n', v.hex())) v = v.strip() print(f"[{index.position:>3}] {index.tag_name}\n{v}") print("") main(argv[1])