Libary API Documentation — badsnakes - v0.2.0 Documentation

# Libary API Documentation

The page contains simple library usage examples and the module-level documentation for each of the importable modules in `badsnakes`.

## Use Cases

To save digging through the documentation for each module and cobbling together what a ‘standard use case’ may look like, a couple have been provided here.

### Analysing a single module

The following example demonstrates how to analyse a single module.

Listing 1 Analysing a single module

     from badsnakes.libs.module import Module
     from badsnakes.libs.reporter import ReporterModule

     path = '/path/to/project/module.py'

     # Analyse the module.
     m = Module(path=path)
     m.analyse()

     # Report the findings.
     r = ReporterModule(modules=[m])
     r.report()

When `r.report()` is called, the following is displayed in the terminal:

Listing 2 Terminal output

     ---------------------------
     Module: project/module.py
     ---------------------------

     Module classification: OK

### Analysing multiple modules

The following example demonstrates how to analyse multiple modules. In this case, we’re looking at pip’s `pip/_internal/*.py` modules.

Listing 3 Analysing multiple modules

     import os
     from glob import glob
     from badsnakes.libs.module import Module
     from badsnakes.libs.reporter import ReporterModule

     modules = []
     paths = glob(os.path.join('/.../site-packages/pip/_internal/', '*.py'))

     # Call Module.analyse for each path and store each module object.
     for path in paths:
        m = Module(path=path)
        m.analyse()
        modules.append(m)

     # Report all findings at once.
     r = ReporterModule(modules=modules)
     r.report()

When `r.report()` is called, the following (truncated output) is displayed in the terminal:

Listing 4 Truncated terminal output

     ----------------------------
      Module: _internal/cache.py
     ----------------------------

     Module classification: OK

     ------------------------------------
      Module: _internal/wheel_builder.py
     ------------------------------------

     Module classification: OK

     ---------------------------------
      Module: _internal/exceptions.py
     ---------------------------------
     [SUSPECT]: L523:531 - Long string: A 375 char string detected: 'hashes are required in --'...' any package has a hash.)'
     [SUSPECT]: L584:587 - String search: ';' found in 'these packages do not match the hashes from the requirements file. if you have updated the package versions, please update the hashes. otherwise, examine the package contents carefully; someone may have tampered with them.'
     [DANGEROUS]: L747:747 - String search: 'pip install' found in 'pip install --force-reinstall --no-deps '

     Module classification: DANGEROUS

     ---------------------------
      Module: _internal/main.py
     ---------------------------

     Module classification: OK

     --------------------------------
      Module: _internal/pyproject.py
     --------------------------------

     Module classification: OK

     --------------------------------
      Module: _internal/build_env.py
     --------------------------------
     [SUSPECT]: L111:134 - String search: '()' found in '\n                import os, site, sys\n\n                # first, drop system-sites related paths.\n                original_sys_path = sys.path[:]\n                known_paths = set()\n                for path in {system_sites!r}:\n                    site.addsitedir(path, known_paths=known_paths)\n                system_paths = set(\n                    os.path.normcase(path)\n                    for path in sys.path[len(original_sys_path):]\n                )\n                original_sys_path = [\n                    path for path in original_sys_path\n                    if os.path.normcase(path) not in system_paths\n                ]\n                sys.path = original_sys_path\n\n                # second, add lib directories.\n                # ensuring .pth file are processed.\n                for path in {lib_dirs!r}:\n                    assert not path in sys.path\n                    site.addsitedir(path)\n                '

     Module classification: SUSPECT

Note

Note that long strings, the use of semi-colons and command execution raise SUSPECT or DANGEROUS flags. This is not saying `pip` is dangerous, it’s only showing their programmers have used techniques often employed by threat actors.

Flagging such techniques have helped us detect live malware.

### Analysing a wheel

The following example demonstrates how to analyse a Python wheel. In this case, we’re looking at our own `badsnakes` wheel.

Listing 5 Analysing a Python wheel

     from badsnakes.libs.collector import Collector
     from badsnakes.libs.module import Module
     from badsnakes.libs.reporter import ReporterModule

     modules = []
     path = '../dist/badsnakes-0.1.0-py3-none-any.whl'

     # Collect all non-binary files from thw wheel.
     c = Collector(paths=path)
     c.collect()

     for pkg in c.files:
        # Call Module.analyse for each path and store each module object.
        for path in pkg:
            # Analyse the module.
            m = Module(path=path)
            m.analyse()
            modules.append(m)

     # Report the findings.
     r = ReporterModule(modules=modules)
     r.report()

When `r.report()` is called, the following (truncated output) is displayed in the terminal:

Listing 6 Truncated terminal output

     -------------------------------------------
      Module: badsnakes-0.1.0.dist-info/LICENSE
     -------------------------------------------

     Module classification: UNKNOWN

     -------------------------------------------------
      Module: badsnakes-0.1.0.dist-info/top_level.txt
     -------------------------------------------------

     Module classification: UNKNOWN

     --------------------------------
      Module: badsnakes/badsnakes.py
     --------------------------------

     Module classification: OK

     --------------------------------
      Module: badsnakes/analysers.py
     --------------------------------
     [SUSPECT]: L555:555 - String search: ';' found in ';'

     Module classification: SUSPECT

     -------------------------------
      Module: badsnakes/reporter.py
     -------------------------------

     Module classification: OK

     --------------------------------
      Module: badsnakes/extractor.py
     --------------------------------

     Module classification: OK

     --------------------------------
      Module: badsnakes/argparser.py
     --------------------------------
     [SUSPECT]: L35:41 - Long string: A 349 char string detected: 'path(s) to the python mod'...'ust be of the same type.\n'

     Module classification: SUSPECT

     --------------------------------
      Module: badsnakes/collector.py
     --------------------------------

     Module classification: OK

     -----------------------------
      Module: badsnakes/module.py
     -----------------------------

     Module classification: OK

     -------------------------------
      Module: badsnakes/config.toml
     -------------------------------

     Module classification: UNKNOWN

Note

Note that even our own wheel raises a SUSPECT flag for a long string found in the `argparser` module. This is not to say the module is unsafe, but rather a warning for the user to be aware of.

Additionally, notice the UNKNOWN classifications. This classification is used for plain-text files which could not be parsed by the `ast` parser, and are therefore not Python modules.

## Module Documentation

In addition to the module-level documentation, most of the public classes and/or methods come with one or more usage examples and access to the source code itself.

Links to module-level documentation

- Module: analysers.py
- Module: badsnakes.py
- Module: collector.py
- Module: config.py
- Module: containers.py
- Module: enums.py
- Module: extractor.py
- Module: logger.py
- Module: module.py
- Module: parser.py
- Module: reporter.py
- Module: utilities.py