Skip to content

Instantly share code, notes, and snippets.

@Auscitte
Created February 10, 2023 10:21
Show Gist options
  • Save Auscitte/65337dd77c4a9375e5d1711e08165056 to your computer and use it in GitHub Desktop.
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
""" 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)
@Auscitte
Copy link
Author

After reading this post the script will appear less mysterious.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment