Last active
November 25, 2025 20:08
-
-
Save PierceLBrooks/dc12b8748b61ac3cc10bb069feeb6fbc to your computer and use it in GitHub Desktop.
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 characters
| # Author: Pierce Brooks | |
| import os | |
| import sys | |
| import copy | |
| import json | |
| import platform | |
| import subprocess | |
| def run(binaries): | |
| if (sys.flags.debug): | |
| print("RUN") | |
| past = [] | |
| sboms = [] | |
| components = {} | |
| dependencies = {} | |
| references = {} | |
| mapping = {} | |
| environment = None | |
| if (platform.system().strip().lower() == "linux"): | |
| environment = {} | |
| try: | |
| command = [] | |
| command.append("ldconfig") | |
| command.append("-p") | |
| output = subprocess.check_output(command).decode() | |
| lines = output.split("\n") | |
| for line in lines: | |
| line = line.strip() | |
| if not (" => " in line): | |
| continue | |
| line = line.split(" => ") | |
| left = line[0].strip() | |
| if (left in environment): | |
| continue | |
| right = line[len(line)-1].strip() | |
| if not (os.path.exists(right)): | |
| continue | |
| environment[left] = right | |
| except: | |
| pass | |
| elif (platform.system().strip().lower() == "windows"): | |
| environment = os.environ.copy() | |
| rpath = "" | |
| if (platform.system().strip().lower() == "linux"): | |
| rpath += "$ORIGIN" | |
| else: | |
| rpath += "@rpath" | |
| origin = os.path.join(os.getcwd(), os.path.basename(binaries[0])+".sbom.cdx.json") | |
| while ((len(binaries) > 0) or (len(sboms) > 0)): | |
| if (sys.flags.debug): | |
| print("WHILE") | |
| if (len(binaries) > 0): | |
| if (sys.flags.debug): | |
| print(json.dumps(binaries)) | |
| binary = binaries[0] | |
| if not (binary in past): | |
| past.append(binary) | |
| if (len(binaries) == 1): | |
| binaries = [] | |
| else: | |
| binaries = binaries[1:] | |
| if (sys.flags.debug): | |
| print(binary) | |
| if not (os.path.exists(binary)): | |
| continue | |
| sbom = os.path.join(os.getcwd(), os.path.basename(binary)+".sbom.cdx.json") | |
| mapping[sbom] = binary | |
| dependencies[binary] = [] | |
| if (os.path.exists(sbom)): | |
| sboms.append(sbom) | |
| continue | |
| command = [] | |
| command.append("blint") | |
| command.append("sbom") | |
| command.append("-i") | |
| command.append(binary) | |
| command.append("-o") | |
| command.append(sbom) | |
| if (sys.flags.debug): | |
| print(str(command)) | |
| subprocess.check_output(command) | |
| if not (os.path.exists(sbom)): | |
| continue | |
| sboms.append(sbom) | |
| continue | |
| sbom = sboms[0] | |
| if (len(sboms) == 1): | |
| sboms = [] | |
| else: | |
| sboms = sboms[1:] | |
| if (sys.flags.debug): | |
| print(sbom) | |
| if not (os.path.exists(sbom)): | |
| continue | |
| descriptor = open(sbom, "r") | |
| content = descriptor.read() | |
| descriptor.close() | |
| data = json.loads(content) | |
| if (sys.flags.debug): | |
| for key in data: | |
| print(key) | |
| dep = [] | |
| if ("components" in data): | |
| for i in range(len(data["components"])): | |
| comp = copy.deepcopy(data["components"][i]) | |
| ref = None | |
| name = None | |
| source = None | |
| if ("properties" in comp): | |
| for prop in comp["properties"]: | |
| if (("name" in prop) and ("value" in prop)): | |
| if (prop["name"] == "internal:libPath"): | |
| name = prop["value"] | |
| elif (prop["name"] == "internal:srcFile"): | |
| source = prop["value"] | |
| if ((name == None) and ("name" in comp) and not (environment == None)): | |
| if (platform.system().strip().lower() == "linux"): | |
| for key in environment: | |
| if (comp["name"] in key): | |
| name = environment[key] | |
| break | |
| if ((name == None) and not (source == None)): | |
| if ((os.path.exists(source)) and (os.path.isdir(os.path.dirname(source))) and not (os.path.isdir(source))): | |
| source = os.path.dirname(source) | |
| try: | |
| command = [] | |
| command.append("objdump") | |
| command.append("-x") | |
| command.append(mapping[sbom]) | |
| output = subprocess.check_output(command).decode() | |
| lines = output.split("\n") | |
| for line in lines: | |
| line = line.strip().replace("\t", " ") | |
| if not (" " in line): | |
| continue | |
| line = line.split(" ") | |
| if not (("RPATH" in line[0].upper()) or ("RUNPATH" in line[0].upper())): | |
| continue | |
| line = line[len(line)-1].strip() | |
| if (rpath in line): | |
| for root, folders, files in os.walk(source): | |
| for library in files: | |
| if (library == comp["name"]): | |
| name = os.path.join(root, library) | |
| break | |
| break | |
| if not (name == None): | |
| break | |
| except: | |
| pass | |
| else: | |
| for key in environment: | |
| if (key.strip().lower() == "path"): | |
| paths = environment[key].split(";") | |
| if not (source == None): | |
| if ((os.path.exists(source)) and (os.path.isdir(os.path.dirname(source)))): | |
| paths.append(os.path.dirname(source)) | |
| for path in paths: | |
| if not (os.path.isdir(path)): | |
| continue | |
| for root, folders, files in os.walk(path): | |
| for library in files: | |
| if (os.path.exists(os.path.join(root, library))): | |
| if (library == comp["name"]): | |
| name = os.path.join(root, library) | |
| break | |
| break | |
| if not (name == None): | |
| break | |
| break | |
| if ("bom-ref" in comp): | |
| ref = comp["bom-ref"] | |
| if not ((name == None) or (ref == None)): | |
| if not (ref in dep): | |
| dep.append(ref) | |
| if ((rpath in name) and not (source == None)): | |
| if (sys.flags.debug): | |
| print(source) | |
| if ((os.path.exists(source)) and (os.path.isdir(os.path.dirname(source))) and not (os.path.isdir(source))): | |
| source = os.path.dirname(source) | |
| name = name.replace(rpath, source) | |
| if not (ref in references): | |
| if not (name in past): | |
| binaries.append(name) | |
| references[ref] = name | |
| if ("properties" in comp): | |
| for prop in comp["properties"]: | |
| if (("name" in prop) and ("value" in prop)): | |
| if (prop["name"] == "internal:libPath"): | |
| prop["value"] = name | |
| name = None | |
| break | |
| if not (name == None): | |
| comp["properties"].append({"name": "internal:libPath", "value": name}) | |
| if not (ref == None): | |
| if not (ref in components): | |
| component = json.dumps(comp) | |
| components[ref] = component | |
| for dependency in dep: | |
| if (dependency in dependencies[mapping[sbom]]): | |
| continue | |
| dependencies[mapping[sbom]].append(dependency) | |
| if not (os.path.exists(origin)): | |
| return -1 | |
| descriptor = open(origin, "r") | |
| content = descriptor.read() | |
| descriptor.close() | |
| data = json.loads(content) | |
| data["components"] = [] | |
| for component in components: | |
| data["components"].append(json.loads(components[component])) | |
| if ("dependencies" in data): | |
| for i in range(len(data["dependencies"])): | |
| dependency = data["dependencies"][i] | |
| if (("ref" in dependency) and ("dependsOn" in dependency)): | |
| ref = dependency["ref"] | |
| if (ref in references): | |
| ref = references[ref] | |
| if (ref in dependencies): | |
| for dep in dependencies[ref]: | |
| if not (dep in dependency["dependsOn"]): | |
| data["dependencies"][i]["dependsOn"].append(dep) | |
| descriptor = open(origin, "w") | |
| descriptor.write(json.dumps(data)) | |
| descriptor.close() | |
| return 0 | |
| def launch(arguments): | |
| if (sys.flags.debug): | |
| print("LAUNCH") | |
| if (len(arguments) < 2): | |
| return False | |
| result = run(arguments[1:]) | |
| print(str(result)) | |
| if not (result == 0): | |
| return False | |
| return True | |
| if (__name__ == "__main__"): | |
| print(str(launch(sys.argv))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment