Out-of-Bounds Array Access (Index Manipulation)
- •
What it is
- •
An unchecked array index accesses memory outside the array. Negative indices reach before its base; large positive indices reach after it, subject to the actual address calculation and access permissions.
- •
- •
How it works
- •
Recover the effective address calculation from disassembly, commonly
base + (index + bias) * element_size. A source-level array access need not have a nonzero bias. - •
To reach a specific known target address, solve for the index:
index = (target - base) / element_size - bias. - •
High addresses [ target (GOT entry, flag, saved data, etc.) ] [ ... ] [ array[0] ] ← base, index 0 Low addresses (negative index moves this direction) - •
The primitive may read or write only aligned, mapped, reachable locations. A suitable write can target a writable Global Offset Table (GOT-PLT) slot.
- •
- •
When to use it
- •
Program explicitly asks "which index?" (or similar) with no visible rejection of negative or oversized values, especially alongside disclosed addresses for the array itself and some interesting target (a flag, the GOT, a function) — a strong signal the intended solution is the arithmetic, not a search.
- •
Disassembly (or a decompiler like
r2/IDA) shows the access compiled to straight pointer arithmetic with no preceding boundscmp/jaeguardingindex— confirm this before assuming the primitive is unrestricted. - •
If output prints an integer, pack each word back into bytes in the correct endianness rather than treating the number as a string.
- •
- •
- •
pwntools
- •
assert (target - base) % element_size == 0 index = (target - base) // element_size - bias
- •
- •
Debugging
- •
disas challenge # Derive base, scale, bias, and bounds checks.
- •
- •
- •
Cards
- •
Why does a negative array index become a security bug rather than just an error?
- •
Because the underlying pointer arithmetic (
base + index*size) has no guard againstindexbeing negative — a negative value simply computes an address before the array instead of failing.
- •
- •
When reading a multi-byte secret through an integer-printing array index primitive, why can't you just read it once?
- •
Each read only returns one array-element's worth of data (e.g. 8 bytes as a raw integer) — the secret has to be reassembled by reading successive indices and concatenating their packed values.
- •
- •