Skip to main content

checksec

checksec tool

checksec is a security auditing tool used to examine compiled binaries and determine what security protections are enabled. It’s commonly used in reverse engineering and binary exploitation to assess the difficulty of exploiting a program. checksec evaluates features like stack canaries, No-eXecute (NX) protection, Position-Independent Executable (PIE) support, and Relocation Read-Only (RELRO) settings.

Usage

checksec --file=binary_file_path

Example:

checksec --file=execute --output=json 

{ "execute": 
  {
    "relro":"full",
    "canary":"yes",
    "nx":"no",
    "pie":"yes",
    "rpath":"no",
    "runpath":"no",
    "symbols":"yes",
    "fortify_source":"no",
    "fortified":"0",
    "fortify-able":"1"
  }
} 

Binary security features

Architecture (Arch)

Specifies the architecture of the binary, such as amd64 (64-bit x86), x86 (32-bit x86), arm, etc. The architecture influences the binary’s instruction set, how it interacts with memory, and what exploitation techniques are feasible.

  • 64-bit architectures (e.g., amd64) generally provide additional security options compared to 32-bit (e.g., x86) architectures. For instance, they support larger address spaces and additional registers, which increase the complexity of certain attacks, like buffer overflows.

Relocation Read-Only (RELRO)

Relocation Read-Only (RELRO) is a protection feature that makes certain memory sections read-only, especially the Global Offset Table (GOT), which stores the addresses of dynamically linked functions.

  • None: No protection; all sections, including the GOT, are writable at runtime. Attackers can freely overwrite GOT entries to redirect function calls to attacker-controlled locations.
  • Partial RELRO: Sections like the GOT are initially writable but are partially protected once loaded. However, the GOT remains writable, allowing some potential for GOT-based exploits.Provides limited protection but still leaves the GOT open to attacks, such as hijacking function pointers.
  • Full RELRO: The entire GOT and other sections are made permanently read-only after loading, preventing runtime modification of function pointers.Offers strong protection against GOT-based exploits, making it significantly harder for attackers to alter the control flow via GOT manipulation.

Stack Canary

A stack canary is a security feature that places a small, randomized value (a "canary") between local variables and the return address on the stack. When the function returns, the program checks the canary’s value. If it’s been altered (e.g., by a buffer overflow), the program terminates, preventing further execution.

  • Canary found: Stack canaries are present. Makes buffer overflow attacks on the stack significantly harder by detecting when the return address is overwritten.
  • No canary found: No stack canaries are enabled. Stack overflows can overwrite the return address without detection, making stack-based buffer overflow exploits easier to execute and potentially allowing arbitrary code execution.

No-eXecute (NX)

The No-eXecute (NX) bit is a CPU feature that marks certain regions of memory, such as the stack and heap, as non-executable. This protection prevents code injection attacks where an attacker injects and attempts to run shellcode from writable memory.

  • NX enabled: The program enforces non-executable memory sections, such as the stack and heap. This feature blocks execution of shellcode injected into writable regions, forcing attackers to rely on advanced techniques like Return-Oriented Programming (ROP), which reuses existing code.
  • NX disabled: Writable sections, like the stack and heap, are executable. Attackers can inject and directly execute shellcode on the stack or heap, enabling straightforward remote code execution.

Position-Independent Executable (PIE)

Position-Independent Executable (PIE) allows a binary to load at random memory addresses each time it runs, utilizing Address Space Layout Randomization (ASLR). This makes memory addresses unpredictable and thus complicates exploitation.

  • PIE enabled: The binary can be loaded at random memory addresses, enabling ASLR. Unpredictable memory locations make certain exploits, like Return-Oriented Programming (ROP), significantly harder since attackers cannot rely on fixed addresses.
  • No PIE: The binary is loaded at a fixed address (often 0x400000), making memory locations predictable. Predictable memory addresses simplify exploit development because attackers can rely on fixed offsets to access important functions and data, making ROP and other memory-based attacks more feasible.

Runtime Paths (RPATH and RUNPATH)

These settings specify directories to search for shared libraries at runtime. They can potentially introduce security risks if they allow loading of untrusted or unexpected libraries.

  • RPATH or RUNPATH: Specified paths can be added to the search path for shared libraries. If these paths are insecure, they could allow an attacker to inject malicious libraries. Custom paths can allow untrusted libraries to be loaded, potentially enabling library hijacking attacks.
  • No RPATH/RUNPATH: The binary relies on standard library locations, which is generally more secure. Reduces the risk of library injection by ensuring only libraries in trusted locations are used.

Symbols

Symbols provide function and variable names in the binary, often aiding in debugging and reverse-engineering.

  • Symbols found: Function names and variable names are present. Makes reverse-engineering easier for attackers, allowing them to quickly identify functions and data structures.
  • No symbols: No symbols are present, making reverse-engineering harder. Complicates analysis, making it harder for attackers to understand the binary’s structure and locate vulnerable code.

Fortify Source

Fortify Source is a compiler feature that provides additional checks for buffer overflows and format string vulnerabilities. When enabled, functions like strcpy and sprintf include runtime checks that detect buffer overflows.

  • Fortify Source enabled: Buffer checks are applied where possible. Additional checks make certain functions more resilient to memory corruption vulnerabilities.
  • Fortify Source disabled: No additional checks are applied to potentially vulnerable functions. Functions like strcpy and sprintf operate without buffer size checks, increasing the risk of buffer overflows.