Files
Lee Chagolla-Christensen 9d62493623 Type checker, reg parsing improvements, UI improvements (#101)
* fix: upgrade python-multipart to 0.0.22 to address CVE-2026-24486 (Dependabot #683)

* update deps+skill, pyright

* pyright + tests in CLI

* Add pyright type checking and enhance registry hive analysis

Registry Hive Analyzer Enhancements:
- Extract machine SID from SAM domain V value with binary SID decoding
- Extract per-user metadata via regipy (ACB flags, timestamps, full
  name, comment via USER_ACCOUNT_V)
- Compute password expiration from domain max password age policy
- Detect empty LM/NT hashes via well-known constants
- Parse DCC cached domain credentials into structured entries
- Store DPAPI system machine_key/user_key as separate fields
- Add structured secret_type field to LSA secrets (dcc, dpapi_system,
  hex_blob, generic)
- Add detailed markdown and plain-text formatters for SAM accounts
  and LSA secrets, replacing _get_lsa_secret_output_string
- Fix SYSTEM hive attribute names: computer_name -> machinename,
  current_control_set -> currentcontrol
- Switch SAM user iteration from sam.users to sam.secrets (pypykatz API)
- Add FILETIME-to-UTC and regipy value-to-bytes helpers

New Tests:
- Add test_registry_hive.py with SAM, SECURITY, and SYSTEM hive fixtures
- Add test_container.py for container analyzer
- Add SAM/SECURITY/SYSTEM binary test fixtures

Pyright Setup:
- Add pyrightconfig.json (basic mode, Python 3.13) to all libs and projects
- Add pyright>=1.1 as dev dependency to all pyproject.toml files
- Update all uv.lock files accordingly
- Update lint.sh to deactivate active venvs and verify pyright availability

Type Annotation Fixes:
- Fix globals initialized as None without Optional type across
  file_enrichment, document_conversion, and agents global_vars
- Fix StorageMinio return types: upload/upload_file/upload_uploadfile
  return str, not uuid.UUID
- Fix MockStorageMinio to match updated StorageMinio return types
- Add explicit type annotations to dict literals in chromekey.py,
  pdf/analyzer.py, registry_hive/analyzer.py, and publish_findings.py
- Fix kubeconfig current_context parameter to accept str | None
- Fix container_contents allowed_extensions: set = None -> set | None = None
- Fix file subscription file_queue: asyncio.Queue = None -> asyncio.Queue | None = None
- Fix web_api upload_file to wrap object_id in uuid.UUID() for response

None-safety Assertions:
- Add assert statements for asyncpg_pool, tracking_service,
  workflow_client, workflow_manager, file_linking_engine, file_queue,
  gotenberg_url, and process.stdout across all activity, subscription,
  route, and workflow files in file_enrichment and document_conversion
- Add assertions for asyncpg_pool in all chromium processors
- Add assertions for File.from_metadata timestamp/expiration fields
- Add assertion for alerting GQL client session type

Pyright Ignore Annotations:
- Suppress third-party type issues in Dapr workflow/activity APIs,
  gRPC subscription imports, ccache/lnk/office_doc attribute access,
  and nemesis_dpapi FlagMixin operators
- Add file-level suppression for office2john.py, pdf2john.py,
  pe/analyzer.py, and test harness files

Bug Fixes:
- Fix office2john.py format string: bare % filename -> % (filename, stream)
- Fix container analyzer 7z iteration: iterate sz.files list instead
  of calling .items()
- Fix file_linking rules_engine: store match result to avoid double call
- Fix logger.exception calls: remove exception object as first arg in
  storage.py, cookies.py, enrichments.py, housekeeping/main.py
- Fix document_conversion lifespan: use stack.callback() for sync shutdown
- Fix NoseyParkerOutput fallback: add missing workflow_id field
- Fix regipy hive_type: handle None return from RegistryHive.hive_type

DPAPI Manager:
- Remove unused guid parameter from get_system_credentials across
  DpapiManager, NullDpapiManager, and DpapiManagerProtocol

Added Missing Dependencies (file_enrichment_modules):
- pypykatz>=0.6.11, pyarrow>=19.0.1, msoffcrypto-tool>=5.4.2,
  oletools>=0.60.2, regipy>=5.2.0, pillow>=11.3.0

* quiet console logs

* feat: lazy file loading with backend range request support

Add offset/length query params to the download endpoint so the frontend
can request partial file content.  FileViewer now fetches data on demand
— hex, transform (Strings, etc.), ZIP, SQLite, and image tabs only load
when activated.  Text-based content is capped at 10 MB previews.

* fix: transform tabs stuck on "Loading content..."

- Prevent stale WS subscription from overwriting fetched content
- Show retry button when transform content fails to load
- Reset fetch guard on non-OK HTTP responses

* fix: hex tab deferred loading with full file content

* feat: truncation dropdown, spinner overlay, and tab render refactor

- Add truncation dropdown to MonacoContentViewer for files > 10MB,
  replacing the old banner alert and hex "Load Hex View" button
- Add spinner overlay on Monaco editor while loading full content
- Wire truncation support to transform tabs (monaco/json types),
  enrichment tabs, and text tabs
- Change hex tab to auto-load first 10MB preview with dropdown for
  full file instead of requiring manual load
- Default word wrap to off
- Remove "File is too large" warning message
- Refactor ~150-line ternary chain into explicit per-tab render
  functions (renderPreviewTab, renderZipTab, renderSqliteTab,
  renderTextTab, renderHexTab, renderTabContent) with shared helpers
  (renderFullFileContent, getTextContent)

* feat: improve Yara Rules UI

- Compact table rows with tighter padding
- Add X button and Esc key to close editor dialog
- Disable Save button when rule content is unchanged
- Disable Create button with inline warning when rule name already exists
- Default source to "Created manually by <user>" for new rules
- Update source placeholder to "e.g. /yara_rules/custom.yara"

* update gitignore

---------

Co-authored-by: Lee Chagolla-Christensen <lee@localhost>
2026-02-05 14:34:25 -08:00
..
2025-10-16 18:17:10 -07:00
2025-06-13 11:33:07 +02:00
2025-06-26 12:29:48 -07:00
2026-01-14 15:20:31 -08:00
2026-01-14 15:20:31 -08:00
2025-06-13 11:33:07 +02:00
2025-08-29 15:24:32 -07:00

Nemesis CLI

A command-line interface for the Nemesis platform that provides file submission, monitoring, and C2 connector functionality.

Purpose

This CLI tool serves as the primary interface for uploading files to Nemesis, monitoring directories for new files, and synchronizing data from C2 frameworks like Mythic, Cobalt Strike and Outflank.

Features

  • File submission: Upload single files or entire directories to Nemesis
  • Directory monitoring: Real-time monitoring of folders for new files
  • C2 connectors: Synchronize data from Mythic, Cobalt Strike and Outflank C2 frameworks
  • Stress testing: Load testing capabilities for the Nemesis API
  • Module testing: Execute file enrichment modules standalone for development

Commands

submit

Upload files or directories to Nemesis for processing.

Key options:

  • -r, --recursive: Process subdirectories recursively
  • -w, --workers: Number of concurrent upload threads (default: 10)
  • --project: Project name for metadata (default: assess-test)
  • --agent-id: Agent identifier for tracking uploads

monitor

Monitor a directory for new files and automatically submit them to Nemesis.

Key options:

  • --only-monitor: Skip existing files, only watch for new ones
  • -w, --workers: Number of threads for initial submission

connect-mythic

Synchronize data between Mythic C2 framework and Nemesis.

Configuration:

  • Uses settings_mythic.yaml configuration file
  • --showconfig: Display example configuration

connect-outflank

Ingest data from Outflank Stage1 C2 into Nemesis.

Configuration:

  • Uses settings_outflank.yaml configuration file
  • --showconfig: Display example configuration

connect-cobaltstrike

Ingest data from Cobalt Strike into Nemesis.

Configuration:

  • Uses settings_cobaltstrike.yaml configuration file
  • --showconfig: Display example configuration

Additional Tools

  • stress_test: Load testing tool for API performance evaluation
  • module_runner: Standalone execution of file enrichment modules for development and testing

Authentication

All commands support basic authentication with configurable username and password options (default: n/n).

Manually running with Python

  1. Navigate to the cli directory. Perform all the following steps from this directory.
cd Nemesis/projects/cli
  1. Install system dependencies required for building native packages:
# Debian/Ubuntu
sudo apt-get install -y libleveldb-dev

# macOS
brew install leveldb
  1. Install dependencies and run it:
uv sync
uv run python -m cli

Manually Building and Using with Docker

  1. Navigate to the cli directory. Perform all the following steps from this directory.
cd Nemesis/projects/cli
  1. Build the base images:
docker compose -f ../../compose.base.yaml build
  1. Build the nemesis-cli image:
docker build -t nemesis-cli --target prod --no-cache -f Dockerfile ../..

Validate --target arguments are prod or dev.

  1. Run the nemesis-cli container:
docker run --network host -v /:/data --rm nemesis-cli submit /data/etc/issue

Using Docker Compose

Pull the published production image and run it

  1. Navigate to the cli directory. Perform all the following steps from this directory.
cd Nemesis/projects/cli
  1. Pull the published production container and run it:
docker compose -f compose.yaml run --rm cli

Build and run the dev/production images

  1. Navigate to the cli directory. Perform all the following steps from this directory.
cd Nemesis/projects/cli
  1. Build the base images:
docker compose -f ../../compose.base.yaml build
  1. Build and run the dev or production containers.

To run the development container, run the following. This mounts CLI's code into container and uses the dev base image. It implicitly merges compose.yaml and compose.override.yaml.

docker compose run --rm cli

Alternatively, you can build the production image and run it with the following:

docker compose -f compose.yaml -f compose.prod.build.yaml run --rm cli

Using submit.sh (in dev)

Building the dev image

  1. Navigate to the cli directory. Perform all the following steps from this directory.
cd Nemesis/projects/cli
  1. Build the base images:
docker compose -f ../../compose.base.yaml build
  1. Build the nemesis-cli image:
docker build -t nemesis-cli --target dev --no-cache -f Dockerfile ../..
  1. Export NEMESIS_CLI_IMAGE
export NEMESIS_CLI_IMAGE=nemesis-cli:latest
  1. Run ./submit.sh as normal:
cd ../..
./tools/submit.sh --help