| name | array-indexing-exploitation |
| description | How to identify and exploit array indexing vulnerabilities in binary exploitation challenges. Use this skill whenever the user mentions array bounds, index manipulation, off-by-one errors, array overflows, heap corruption through arrays, or any CTF/binary challenge involving array access. This skill covers colliding arrays, size field overwrites, GOT corruption, ROP chains triggered by array bugs, and heap exploitation through index manipulation. Make sure to use this skill for any binary exploitation task involving arrays, even if the user doesn't explicitly mention "array indexing" or "bounds checking". |
Array Indexing Exploitation
This skill helps you identify and exploit array indexing vulnerabilities in binary exploitation challenges. These vulnerabilities occur when programs fail to properly validate array indices, allowing attackers to overwrite arbitrary memory locations.
When to Use This Skill
Use this skill when you encounter:
- Binary exploitation challenges with array-based data structures
- Off-by-one errors in array bounds checking
- Colliding arrays (separate arrays for data and metadata like sizes)
- Heap corruption through array index manipulation
- Stack-based array overflows
- Any CTF writeup or challenge mentioning array indexing, bounds, or index manipulation
Core Concepts
What Makes Array Indexing Vulnerable
Array indexing vulnerabilities happen when:
- No bounds checking: The program doesn't verify the index is within valid range
- Integer overflow: Index calculation wraps around to a valid-looking but wrong value
- Type confusion: Different arrays share the same memory space with different interpretations
- Off-by-one errors: Bounds check allows one position past the end
Common Exploitation Patterns
Pattern 1: Colliding Arrays (Data + Size)
Scenario: Two parallel arrays - one stores data (addresses), one stores metadata (sizes)
Exploitation:
- Use a negative or large index to write to the size array from the data array (or vice versa)
- Overwrite a size field with an address (e.g., address of
free in GOT)
- Trigger the function at that address (e.g., call
free with /bin/sh as argument)
- Result:
system("/bin/sh") if GOT entry was overwritten with system address
Example from SwampCTF 19 DreamHeaps:
- Two arrays: addresses array and sizes array
- Write arbitrary address as a size value
- Overwrite GOT entry for
free with system address
- Call
free with /bin/sh → shell
Pattern 2: Off-by-One on Stack
Scenario: Array on stack with off-by-one vulnerability allows writing one byte past the end
Exploitation:
- Identify what's stored after the array (often a pointer or control data)
- Use the off-by-one to corrupt that data
- If it's a pointer, you can control where it points
- Combine with ROP chains for full control
Example from SecconCTF 2019 Sum:
- 64-bit, no relro, canary, NX, no PIE
- Off-by-one in stack array controls a pointer
- Overwrite GOT
exit with pop rdi; ret
- Add address to
main on stack (loops back)
- Use ROP chain with
puts to leak addresses
- Final ROP chain for ret2lib
Pattern 3: Size Field Manipulation (Heap)
Scenario: Heap chunks with size fields that can be overwritten through array indexing
Exploitation:
- Overwrite size field to create artificial buffer overflow
- Craft shellcode that meets size constraints (e.g., sorted, doubled values)
- Preserve canary position if present
- Overwrite RIP with return address to shellcode
Example from CSAW 18 DoubleTrouble:
- 64-bit, no NX
- Overwrite size to create buffer overflow
- Shellcode must be sorted smallest to biggest
- Canary must stay in position
- Overwrite RIP with
ret address
- Point to leaked stack address for shellcode
Pattern 4: Information Leak + Ret2Lib
Scenario: Array indexing allows reading/writing stack data including addresses
Exploitation:
- Use bad indexing to leak libc/heap addresses from stack
- Calculate offsets to needed functions
- Use ret2lib to call
system("/bin/sh")
- May need heap address to bypass checks
Example from TU Guestbook:
- 32-bit, no relro, no canary, NX, PIE
- Bad indexing leaks libc and heap addresses
- Buffer overflow for ret2lib
- Heap address needed to bypass validation check
Step-by-Step Exploitation Workflow
Step 1: Identify the Vulnerability
-
Locate array operations in the binary:
- Look for array indexing patterns:
array[index], ptr[index]
- Check if
index comes from user input
- Verify bounds checking exists and is correct
-
Determine array location:
- Stack-based: Look for local variables, function parameters
- Heap-based: Look for
malloc, calloc, new calls
- Global: Look for static arrays
-
Identify what's adjacent:
- What data structures are near the array?
- Are there size fields, pointers, or control data nearby?
- Check for colliding arrays (data + metadata)
Step 2: Analyze Protection Mechanisms
Check for:
- NX/DEP: Prevents shellcode execution
- Canary: Stack canary must be preserved or leaked
- PIE: Position Independent Executable requires address leaks
- RELRO: Full RELRO prevents GOT overwrites
- ASLR: Address Space Layout Randomization requires leaks
Step 3: Choose Exploitation Strategy
Based on protections and vulnerability type:
| Protections | Strategy |
|---|
| No NX, no canary | Shellcode on stack |
| NX, no canary | ROP chain or ret2lib |
| Canary present | Leak canary first, then exploit |
| PIE present | Leak addresses first |
| Full RELRO | Cannot use GOT, use heap or ROP |
Step 4: Craft the Exploit
For Colliding Arrays:
payload = struct.pack('<Q', got_entry_address)
payload += struct.pack('<Q', system_address)
For Off-by-One:
payload = b'A' * (array_size - 1)
payload += struct.pack('<Q', target_address)
For Size Field Manipulation:
payload = b'A' * (offset_to_size)
payload += struct.pack('<Q', large_size)
shellcode = create_sorted_shellcode()
payload += shellcode
payload += struct.pack('<Q', ret_address)
Step 5: Handle Address Leaks
If PIE or ASLR is present:
- Find leak primitive: Use the array bug to read addresses
- Calculate offsets:
libc_base = leaked_address - libc_offset
- Compute target addresses:
system = libc_base + system_offset
- Two-stage exploit: Leak first, then exploit
Step 6: Test and Refine
- Test locally: Run against the binary with your exploit
- Check for crashes: Adjust offsets if needed
- Verify shell: Confirm you get a shell or expected behavior
- Handle edge cases: Different inputs, timing issues
Common Tools and Techniques
Debugging
- GDB with pwndbg/gef: Essential for binary exploitation
- Checksec: Verify protection mechanisms
- strings: Find useful strings in the binary
- objdump: Disassemble and analyze the binary
Exploit Development
- pwntools: Python library for exploit development
- ROPgadget: Find ROP gadgets
- one_gadget: Find one-gadget RCE payloads
Key pwntools Functions
from pwn import *
p = process('./vulnerable_binary')
p = remote('target.com', 1337)
p.sendline(payload)
p.send(payload)
p.recv()
p.recvline()
p.recvall()
p64(address)
p32(address)
libc = ELF('./libc.so.6')
libc.address = leaked_address - libc.symbols['leaked_function']
Example Exploit Template
from pwn import *
context.arch = 'amd64'
context.os = 'linux'
p = process('./vulnerable_binary')
elf = ELF('./vulnerable_binary')
libc = ELF('./libc.so.6')
system = libc.symbols['system']
binsh = next(libc.search(b'/bin/sh'))
payload = b'A' * offset_to_array
payload += p64(got_entry_to_overwrite)
payload += p64(system)
p.sendline(payload)
p.sendline(trigger_input)
p.interactive()
Red Flags and Common Mistakes
- Wrong endianness: Always use little-endian for x86/x64
- Wrong architecture: 32-bit vs 64-bit packing
- Missing canary: If canary is present, you must leak and preserve it
- PIE not handled: Addresses are randomized, need leaks
- Off-by-one in your exploit: Double-check all offsets
- Not testing locally: Always test before submitting
When This Skill Applies
Use this skill for:
- CTF challenges with array-based vulnerabilities
- Binary exploitation writeups mentioning index manipulation
- Heap exploitation through array bounds
- Stack-based array overflows
- Any challenge where array indexing is the attack vector
Related Skills
- Heap exploitation (for heap-based array vulnerabilities)
- ROP chain construction (for NX-protected binaries)
- GOT/PLT exploitation (for non-RELRO binaries)
- Information leak techniques (for PIE/ASLR bypass)
References