Created
February 10, 2023 10:21
-
-
Save Auscitte/65337dd77c4a9375e5d1711e08165056 to your computer and use it in GitHub Desktop.
Prints set-theoretic (loosly speaking) relations for a sequence of consecutive dbxupdate.bin files
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
""" Prints set-theoretic relations for a sequence of consecutive dbxupdate.bin files | |
Prepend file names with the release date in the yyyy-mm-dd format (you can name the files | |
in some other way, but make sure that sorting the files in a lexicographical order | |
correspendeds to sorting them by a release date) | |
dbxupdate_parser lives at https://github.com/Auscitte/sys-utils/blob/main/dbxupdate_parser.py | |
:Copyright: | |
Ry Auscitte 2023. This script is distributed under MIT License. | |
:Authors: | |
Ry Auscitte | |
""" | |
from dbxupdate_parser import DbxUpdate | |
import glob, os, sys | |
def extract_field(sig, field): | |
"""Recursively extracts either attributes or instance variables (whichever is available) with names from the ``field`` list""" | |
val = sig | |
for p in field: | |
try: | |
val = getattr(val, p) | |
except Exception as e: | |
val = val.__dict__[p] | |
return val | |
def get_dbxupdate_entries(files, guid, field): | |
"""Creates a set of signatures for each file in ``files`` | |
Signature lists with SignatureType != ``guid`` are skipped. | |
``field`` is a list of instance attributes leading to a value uniquely identifying the signature; | |
for a X.509 certificate, for example, it might be a serial number: | |
[EFI_SIGNATURE::SignatureData, X509Cert::_crt, asn1crypto.X509.Certificate::serial_number] | |
""" | |
sets = [] | |
for f in files: | |
upd = DbxUpdate(f , None) | |
st = set() | |
for sl in upd.upd.SignatureLists: | |
if sl.SignatureType != guid: | |
continue | |
st = st.union({ extract_field(s, field) for s in sl.Signatures }) | |
sets.append(st) | |
return sets | |
def print_set_relations(files, sets): | |
for i in range(len(sets) - 1): | |
print(f"intersection: {len(sets[i].intersection(sets[i+1]))}; "\ | |
f"{files[i]}: {len(sets[i])}; "\ | |
f"{files[i + 1]}: {len(sets[i+1])}") | |
def dbxupdate_matroska(files, guid, field): | |
"""Prints cardinalities of intersection of signatures found in consecutive files | |
Accepts sorted list of paths as the parameter ``files``. | |
If the update files were intended to rewrite existing dbx, each subsequent | |
set of signatures would be a superset of the previous one, thus forming a | |
Russian doll of signatures. | |
""" | |
sets = get_dbxupdate_entries(files, guid, field) | |
print_set_relations(files, sets) | |
def print_usage(args): | |
print(args[0], "<path to a folder containing dbxupdate.bin files>") | |
def main(args): | |
if len(args) < 2: | |
print_usage(args) | |
return | |
files = [ itm for itm in glob.glob(os.path.join(args[1], "*")) if os.path.isfile(itm) ] | |
files.sort() | |
dbxupdate_matroska(files, "{c1c41626-504c-4092-a9ac-41f936934328}", ["SignatureData"]) | |
dbxupdate_matroska(files, "{a5c059a1-94e4-4aa7-b587-ab155c2bf072}", ["SignatureData", "_crt", "serial_number"]) | |
if __name__ == "__main__": | |
main(sys.argv) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
After reading this post the script will appear less mysterious.