# How to Build the libssh2 CVE-2026-55200 C11 Arithmetic Verifier

> Learn to build the libssh2 CVE-2026-55200 C11 arithmetic verifier. Compile and run the exploit to reproduce the 32-bit integer overflow vulnerability.

- Repository: [bikini/exploitarium](https://github.com/bikini/exploitarium)
- Tags: how-to-guide
- Published: 2026-09-07

---

**Compile the [`cve_2026_55200_probe.c`](https://github.com/bikini/exploitarium/blob/main/cve_2026_55200_probe.c) verifier with `gcc -std=c11` and run it with `--packet-length 0xffffffff --mac-len 0 --auth-len 16` to reproduce the 32-bit integer overflow that causes CVE-2026-55200.**

The **arithmetic verifier** in the `bikini/exploitarium` repository provides a lightweight, standalone way to validate the integer-overflow vulnerability designated CVE-2026-55200 in **libssh2**. This tool does not require linking against libssh2 itself—it simply reimplements the exact arithmetic that the library performs in `src/transport.c:ssh2_transport_read()`. By building and running this C11 program, security researchers can confirm how a maliciously crafted packet triggers an undersized allocation despite appearing to pass bounds checks.

## What CVE-2026-55200 Does to libssh2's Arithmetic

The vulnerability stems from how libssh2 computes buffer sizes before allocation.

In `src/transport.c:ssh2_transport_read()`, the code constructs the allocation size as follows:

```c
total_num = 4
total_num += packet_length + mac_len + auth_len
if (total_num > LIBSSH2_PACKET_MAXPAYLOAD) reject
allocate total_num bytes

```

When `packet_length = 0xffffffff`, `mac_len = 0`, and `auth_len = 16`, the 32-bit addition **wraps to 15**. Adding the constant `4` yields an allocation of only **19 bytes**, even though the original packet claims to be 4 GB. The upstream fix inserts a pre-check (`packet_length > LIBSSH2_PACKET_MAXPAYLOAD`) before the arithmetic occurs.

## The Four Arithmetic Models in the Verifier

The [`cve_2026_55200_probe.c`](https://github.com/bikini/exploitarium/blob/main/cve_2026_55200_probe.c) file implements four distinct models to isolate the bug:

- **vulnerable32** — Mirrors the original 32-bit arithmetic, reproducing the overflow.
- **fixed32** — Adds the pre-check from the upstream patch.
- **native_unpatched** — Uses native `size_t` without the guard, showing the same overflow on 64-bit hosts when the intermediate expression wraps.
- **native_fixed** — Uses native `size_t` with the pre-check, representing the safe code path.

Each model populates a `struct calc_result` containing `packet_length`, intermediate totals, final allocation length, and a return code (`POC_OK`, `POC_ERROR_DECRYPT`, or `POC_ERROR_OUT_OF_BOUNDARY`).

## Build Instructions for the CVE-2026-55200 Verifier

The verifier requires only a **C11-compliant compiler**. No external dependencies are needed.

### Linux, macOS, or WSL

```bash
gcc -std=c11 -Wall -Wextra -O0 -g -o cve_2026_55200_probe poc/cve_2026_55200_probe.c

```

### Windows with MinGW

```powershell
gcc -std=c11 -Wall -Wextra -O0 -g -o cve_2026_55200_probe.exe .\poc\cve_2026_55200_probe.c

```

The `-O0` flag disables optimization to ensure the arithmetic behavior remains observable. `-g` adds debug symbols for source-level analysis.

## Running the Arithmetic Verifier

The `cve_2026_55200_probe` binary accepts several command-line flags to exercise the different code paths:

| Flag | Purpose |
|------|---------|
| *(none)* | Defaults to a benign packet (safe values). |
| `--benign` | Explicitly runs the benign case. |
| `--native` | Uses native `size_t` arithmetic without the patch. |
| `--check` | Uses `size_t` with the upstream fix applied. |
| `--packet-length N` | Sets `packet_length` to a specific hex or decimal value. |
| `--mac-len N` | Sets `mac_len` (default varies by test). |
| `--auth-len N` | Sets `auth_len` (default varies by test). |

### Basic functionality test

```bash
./cve_2026_55200_probe

```

### Reproduce the exact CVE-2026-55200 overflow

```bash
./cve_2026_55200_probe --packet-length 0xffffffff --mac-len 0 --auth-len 16

```

### Exercise 64-bit native arithmetic (unpatched)

```bash
./cve_2026_55200_probe --native

```

### Verify the fixed path rejects malicious input

```bash
./cve_2026_55200_probe --check

```

## Expected Output for the Vulnerable Case

When you trigger the overflow, the verifier produces output similar to:

```

vulnerable32_decision=accepted
vulnerable32_allocation=19
fixed32_decision=rejected: out of boundary
native_unpatched_decision=accepted
native_note=source-shaped integer expression wraps before assignment into 64-bit size_t
result=PASS

```

This confirms that:
- The **vulnerable32** model accepts the packet and allocates only 19 bytes.
- The **fixed32** model correctly rejects it with `POC_ERROR_OUT_OF_BOUNDARY`.
- The **native_unpatched** model exhibits the same flaw when the intermediate 32-bit expression wraps before widening to `size_t`.

## Key Source Files in bikini/exploitarium

Understanding the repository layout helps navigate the full proof-of-concept:

| File | Role |
|------|------|
| [`poc/cve_2026_55200_probe.c`](https://github.com/bikini/exploitarium/blob/main/poc/cve_2026_55200_probe.c) | The standalone C11 arithmetic verifier described in this article. |
| [`poc/libpwn_local_rce_harness.c`](https://github.com/bikini/exploitarium/blob/main/poc/libpwn_local_rce_harness.c) | A controlled local RCE harness demonstrating exploitability. |
| [`poc/libpwn_cve_2026_55200_server.py`](https://github.com/bikini/exploitarium/blob/main/poc/libpwn_cve_2026_55200_server.py) | Minimal malicious SSH server emitting the malformed packet. |
| [`README.md`](https://github.com/bikini/exploitarium/blob/main/README.md) (CVE-2026-55200 directory) | Build instructions, theory of operation, and usage notes. |

The arithmetic verifier lives in [`poc/cve_2026_55200_probe.c`](https://github.com/bikini/exploitarium/blob/main/poc/cve_2026_55200_probe.c) and is designed to run anywhere—its portability is a deliberate feature for security auditing across platforms.

## Summary

- **CVE-2026-55200** is a 32-bit integer overflow in libssh2's packet length calculation.
- The **arithmetic verifier** reproduces this bug without depending on libssh2 itself.
- Build with `gcc -std=c11 -O0 -g` for faithful arithmetic behavior.
- Use `--packet-length 0xffffffff --mac-len 0 --auth-len 16` to trigger the overflow.
- The `vulnerable32` and `native_unpatched` models accept malicious input; `fixed32` and `native_fixed` reject it.
- All source files are available in the `bikini/exploitarium` repository under the `libssh2-cve-2026-55200-poc` directory.

## Frequently Asked Questions

### Does the verifier require libssh2 to be installed?

No. The [`cve_2026_55200_probe.c`](https://github.com/bikini/exploitarium/blob/main/cve_2026_55200_probe.c) program is **pure C11** with zero external dependencies. It reimplements only the arithmetic expressions found in libssh2's [`src/transport.c`](https://github.com/bikini/exploitarium/blob/main/src/transport.c), making it portable to any system with a C compiler.

### Why does the native_unpatched model overflow on 64-bit systems?

The expression `packet_length + mac_len + auth_len` is evaluated using the **types of the operands** before assignment. When these are `uint32_t` values, the addition wraps in 32-bit space; only afterward is the result widened to `size_t`. The verifier's `native_note` field explicitly flags this: "source-shaped integer expression wraps before assignment into 64-bit size_t."

### What compiler flags are recommended for accurate results?

Always use `-O0` (no optimization). Higher optimization levels may constant-fold or eliminate the arithmetic in ways that obscure the overflow behavior. `-Wall -Wextra` catches potential issues, and `-g` enables debugging.

### Can I use this verifier to test my own libssh2 patches?

Yes. The modular structure—four independent models with identical interfaces—allows you to add custom variants. Copy the `fixed32` implementation, modify the guard logic, and compare outputs against `vulnerable32` to validate your changes.