-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added support for ImplMap entries and relationships for .NET binaries #54
Conversation
for more information, see https://pre-commit.ci
surfactant/infoextractors/pe_file.py
Outdated
@@ -233,6 +238,17 @@ def get_assemblyref_info(asmref_info): | |||
return asmref | |||
|
|||
|
|||
def get_implmap_info(im_info, imp_modules): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
def get_implmap_info(im_info, imp_modules): | |
def get_implmap_info(im_info, imp_modules): |
This is doing a bit more than just getting the implmap -- maybe call it add_implmap_info
or insert_implmap_info
instead to capture that it is also modifying part of the SBOM.
if "dotnetImplMap" in metadata: | ||
combinedRefs.append(metadata["dotnetImplMap"]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What were the URLs/doc links that you referenced for info on how .NET determines where to look for the DLLs listed in ImplMap?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was mistaken about unmanaged code loading being the same as loading assemblies. I got my sources mixed up, but I found the one that relates to ImplMap (PInvoked) libraries and included it. From what it looks like, if it's not the assembly/application directory, it's the system32 folder (default unless someone overrides the loading function).
for more information, see https://pre-commit.ci
for more information, see https://pre-commit.ci
…actant into CYT-579-dotNet-ImplMap-Support
for more information, see https://pre-commit.ci
refName = None | ||
refCulture = None | ||
if "Name" in asmRef: | ||
refName = asmRef["Name"] | ||
|
||
# Aside from .deps.json, the assembly's install directory is searched | ||
probedirs = get_dotnet_probedirs(software, refCulture, refName, dnProbingPaths) | ||
for e in find_installed_software(sbom, probedirs, refName + ".dll"): | ||
dependency_uuid = e.UUID | ||
relationships.append(Relationship(dependent_uuid, dependency_uuid, "Uses")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In addition to probing directories similar to .NET (or instead of depending on if we can determine whether or not this applies to loading unmanaged libraries), it looks like we need to have code that looks for relationships according to https://learn.microsoft.com/en-us/dotnet/core/dependency-loading/default-probing#unmanaged-native-library-probing and searches for names/paths according to https://learn.microsoft.com/en-us/dotnet/standard/native-interop/native-library-loading when a relative path is given.
…directories, mostly for WSL
for more information, see https://pre-commit.ci
for more information, see https://pre-commit.ci
…elper function stub to check for absolute paths
for more information, see https://pre-commit.ci
for more information, see https://pre-commit.ci
for more information, see https://pre-commit.ci
for more information, see https://pre-commit.ci
continue | ||
refName = asmRef["Name"] | ||
if is_absolute_path(refName): | ||
relationships.extend(get_windows_pe_dependencies(sbom, software, [refName])) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the get_windows_pe_dependencies
function does what we want when a dependency is specified using absolute paths -- the function itself constructs a list of probe directories relative to the software, which when the given path is absolute we don't care about searching, and then it calls the find_installed_software
function internally to find a match, which appends the file name for an import (which in this case would be an absolute path) to each probe directory given in turn.
For an example of a program in C:/PrgFiles/Program.exe
an absolute import of C:/SomeFolder/Dep.dll
looks like it would result in the function trying to search for something like C:/PrgFiles/C:/Somefolder/Dep.dll
.
For matching an import listed as an absolute dependency, I think we can have a loop that just looks for a Software entry with an install path that just matches the absolute import name, without any of the probe directory things in it.
ref_abspath = pathlib.PureWindowsPath(refName)
# iterate through all sbom entries
for e in sbom.software:
# Skip if no install path (e.g. installer/temporary file)
if e.installPath is None:
continue
if isinstance(e.installPath, Iterable):
for ifile in e.installPath:
# PureWindowsPath is case-insensitive for file/directory names
if ref_abspath == pathlib.PureWindowsPath(ifile):
# matching probe directory and filename, add relationship to list
relationships.extend(Relationship(dependent_uuid, e.uuid, "Uses"))
…actant into CYT-579-dotNet-ImplMap-Support Retrieve changes from main
for more information, see https://pre-commit.ci
…line already checks for relationships in the software entries
for ifile in e.installPath: | ||
if ref_abspath == pathlib.PureWindowsPath(ifile): | ||
relationships.extend(Relationship(dependent_uuid, e.uuid, "Uses")) | ||
relationships.extend(get_windows_pe_dependencies(sbom, software, [refName])) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the line calling get_windows_pe_dependencies
should be present - haven't confirmed, but in that function it is appending refName (which in this case is an absolute path such as C:/Somefolder/Dep.dll
) with the path software is located in, so it will just be searching for garbage paths like C:/Program Files/softwareinstalldir/C:/Somefolder/Dep.dll
that are actually invalid path names on Windows (: is not allowed in folder names) so the files it is looking for should never exist.
for more information, see https://pre-commit.ci
for more information, see https://pre-commit.ci
Output for the "dotnetImplMap" key in the metadata shows the name of the DLL paired with a list of functions used from the DLL. Determining relationships works the same way as "dotnetAssemblyRef" entries.