Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
e818133
Update: added exported function scanning in Plugin
May 29, 2025
0865396
Merge branch 'LLNL:main' into main
T0pAc3 Jun 5, 2025
3164728
export to import function reachability plugin
Jun 6, 2025
694d1dc
Fixed an issue within angrimportfinder
Jun 6, 2025
694e100
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 6, 2025
7e8a80e
Update README.md
T0pAc3 Jun 6, 2025
b268551
Fixed an issue within angrimportfinder
Jun 6, 2025
2d5730c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 9, 2025
42ce123
Update plugins/angrimportfinder/README.md
T0pAc3 Jun 9, 2025
a6a3a2f
surfactant reachability plugin
Jun 12, 2025
9dab6b4
Update README.md
T0pAc3 Jun 12, 2025
4fd81fa
Merge pull request #1 from T0pAc3/angrimportfixes
T0pAc3 Jun 12, 2025
f0a7593
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 12, 2025
4baf14f
Merge branch 'main' into main
T0pAc3 Jun 12, 2025
26f478a
turned JSON form into python dictionary
Jun 12, 2025
604429a
Merge branch 'main' of github.com:T0pAc3/Surfactant
Jun 12, 2025
e96a8cb
Final fix for reachability 1.0
Jun 13, 2025
70e68af
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 13, 2025
d634754
added to the metadata section in the json output
Jun 23, 2025
8102e10
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 23, 2025
9dc83fc
added error checking to reachability plugin
Jul 7, 2025
ee5aa1d
Merge branch 'main' of github.com:T0pAc3/Surfactant
Jul 7, 2025
622a38d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 7, 2025
1dcb0d3
Merge branch 'main' into main
WorkingRobot Jul 17, 2025
24a73e2
Merge branch 'main' into main
nightlark Jul 21, 2025
6d5c585
Merge branch 'main' into main
WorkingRobot Jul 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion plugins/angrimportfinder/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Imported and Exported function name extractor Plugin for SBOM Surfactant

A plugin for Surfactant that uses the [angr](https://github.com/angr/angr)
Python library to extract the imported function names from ELF and PE files.
Python library to extract the imported and exported function names from ELF and PE files.

## Quickstart

Expand Down
42 changes: 42 additions & 0 deletions plugins/reachability/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Import Reachability Plugin for SBOM Surfactant

A plugin for Surfactant that checks the reachability of imported functions within exported functions to narrow down reachable code and reduse the amount of deadcode analysts are having to view.

## Quickstart

To install this plugin within the same virtual environment as Surfactant, use the command `pip install .`.

For developers modifying the plugin, the editable installation can be achieved with `pip install -e .`.

After installing the plugin, run Surfactant to generate an SBOM as usual and entries for ELF
and PE files will contain a metadata object with the information that checksec.py was able
to get about security related features.

After the plugin installation, run Surfactant as you normally would to create an SBOM. For binary files analyzed by this plugin, additional JSON files will be generated containing vulnerability data extracted from the binaries. If there are duplicate hashed files, the extractor will check if they have the exported functions entries and skip remaking the output file if so.
Comment on lines +11 to +15
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These lines don't describe the reachability plugin.


Example:
Output Filename: `reachability.json`

```json
{
"filename": {
"exp_func": {
"library": [
"imp_func1",
"imp_func2"
]
}
}
}
```
Comment on lines +17 to +31
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this description is accurate either -- the json blob looks slightly different if I'm remembering correctly, and is added to the metadata list for software entries rather than being in a separate file.


The plugin's functionality can be toggled via Surfactant's plugin management features, using the plugin name `surfactantplugin_reachability.py` as defined in the `pyproject.toml` under the `project.entry-points."surfactant"` section.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The plugin name to enable/disable it is surfactantplugin_reachability, without the .py suffix.


## Uninstalling

Remove the plugin from your environment with `pip uninstall surfactantplugin_reachability`.

## Important Licensing Information
Main Project License (Surfactant): MIT License.

Plugin License: MIT License, but it includes and uses cve-bin-tool, which is GPL-3.0 licensed.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cve-bin-tool line here does not apply to this plugin.

33 changes: 33 additions & 0 deletions plugins/reachability/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[build-system]
requires = ["setuptools", "setuptools-scm"]
build-backend = "setuptools.build_meta"

[project]
name = "surfactantplugin_reachability"
authors = [
{name = "Seth Bredbenner", email = "[email protected]"},
]
description = "Surfactant plugin for running grype on files"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Description here needs updating

readme = "README.md"
requires-python = ">=3.8"
keywords = ["surfactant"]
license = {text = "MIT License"}
classifiers = [
"Programming Language :: Python :: 3",
"Environment :: Console",
"Operating System :: MacOS",
"Operating System :: Microsoft :: Windows",
"Operating System :: POSIX :: Linux",
"License :: OSI Approved :: MIT License",
]
dependencies = [
"angr",
"surfactant",
]
dynamic = ["version"]

[project.entry-points."surfactant"]
"surfactantplugin_reachability" = "surfactantplugin_reachability"

[tool.setuptools]
py-modules=["surfactantplugin_reachability"]
87 changes: 87 additions & 0 deletions plugins/reachability/surfactantplugin_reachability.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Copyright 2023 Lawrence Livermore National Security, LLC
# See the top-level LICENSE file for details.
#
# SPDX-License-Identifier: MIT
from pathlib import Path

import angr
from cle import CLECompatibilityError
from loguru import logger

import surfactant.plugin
from surfactant.sbomtypes import SBOM, Software


@surfactant.plugin.hookimpl(specname="extract_file_info")
# extract_strings(sbom: SBOM, software: Software, filename: str, filetype: str):
# def angrimport_finder(filename: str, filetype: str, filehash: str):
def reachability(sbom: SBOM, software: Software, filename: str, filetype: str):
"""
:param sbom(SBOM): The SBOM that the software entry/file is being added to. Can be used to add observations or analysis data.
:param software(Software): The software entry associated with the file to extract information from.
:param filename (str): The full path to the file to extract information from.
:param filetype (str): File type information based on magic bytes.
"""

# Only parsing executable files
if filetype not in ["ELF", "PE"]:
pass
filename = Path(filename)

database = {}

try:
if not filename.exists():
raise FileNotFoundError(f"No such file: '{filename}'")
# Add your extraction code here.
# Create an angr project
project = angr.Project(filename, load_options={"auto_load_libs": True})

# library dependencies {import: library}
lookup = {}
for obj in project.loader.main_object.imports.keys():
library = project.loader.find_symbol(obj)
if library is None:
continue
lookup[obj] = library.owner.provides

# recreates our angr project without the libraries loaded to save on time
project = angr.Project(filename, load_options={"auto_load_libs": False})

# holds every export address error is here
exports = [
func.rebased_addr for func in project.loader.main_object.symbols if func.is_export
] # _exports is only available for PE files

cfg = project.analyses.CFGFast(
start_at_entry=False, force_smart_scan=False, function_starts=exports
)

# go through every exported function
for exp_addr in exports:
exp_name = cfg.functions.get(exp_addr)
if exp_name is None:
continue
database[exp_name.name] = {}
exp_name = exp_name.name

# goes through every function that is reachable from exported function
for imported_address in cfg.functions.callgraph.successors(exp_addr):
imported_function = cfg.functions.get(imported_address)

# checks if the function is imported
if imported_function.name in project.loader.main_object.imports.keys():
library = lookup[imported_function.name]

if library not in database[exp_name].keys():
database[exp_name][library] = []

# adds our reachable imported function as a dependency
if imported_function.name not in database[exp_name][library]:
database[exp_name][library].append(imported_function.name)

return {"export_fn_reachability": database}

except CLECompatibilityError as e:
logger.info(f"Angr Error {filename} {e}")
return None
Loading