Skip to content

Instantly share code, notes, and snippets.

@knightsc
Created February 12, 2019 17:30
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save knightsc/25c337925e2de2b075119fc8ee2e6718 to your computer and use it in GitHub Desktop.
Save knightsc/25c337925e2de2b075119fc8ee2e6718 to your computer and use it in GitHub Desktop.
Scans all kexts in /System/Library/Extensions and generates a graphml graph representation of the dependencies.
import plistlib
import subprocess
import os
def main():
output = subprocess.check_output(['find', '/System/Library/Extensions', '-name', '*.kext', '-print'])
print('<?xml version="1.0" encoding="UTF-8"?>')
print('<graphml xmlns="http://graphml.graphdrawing.org/xmlns">')
print(' <graph id="G" edgedefault="undirected">')
print(' <node id="Kernel"/>')
names = {}
# First pass to build id to kext name mapping
for line in output.split('\n'):
line = line.strip()
if line:
kext = os.path.splitext(os.path.basename(line))[0]
plist = os.path.join(os.path.join(line, 'info.plist'))
if not os.path.isfile(plist):
plist = os.path.join(os.path.join(line, 'Contents/info.plist'))
p = plistlib.readPlist(plist)
deps = {}
if 'OSBundleLibraries' in p:
deps = p['OSBundleLibraries']
if 'OSBundleLibraries_x86_64' in p:
deps = p['OSBundleLibraries_x86_64']
if deps:
names[p['CFBundleIdentifier']] = kext
print(' <node id="' + kext + '"/>')
# Second pass to build nodes and edges
for line in output.split('\n'):
line = line.strip()
if line:
kext = os.path.basename(line)
plist = os.path.join(os.path.join(line, 'info.plist'))
if not os.path.isfile(plist):
plist = os.path.join(os.path.join(line, 'Contents/info.plist'))
p = plistlib.readPlist(plist)
deps = {}
if 'OSBundleLibraries' in p:
deps = p['OSBundleLibraries']
if 'OSBundleLibraries_x86_64' in p:
deps = p['OSBundleLibraries_x86_64']
if deps:
source = p['CFBundleIdentifier']
if source in names:
source = names[p['CFBundleIdentifier']]
count = 0
for key in deps:
if not 'kpi' in key:
count = count + 1
target = key
if key in names:
target = names[key]
print(' <edge source="' + source + '" target="' + target + '"/>')
if count == 0:
print(' <edge source="' + source + '" target="Kernel" />')
print(' </graph>')
print('</graphml>')
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment