Add exploitarium archive
This commit is contained in:
94
objdump-dlx-calc-poc/docs/aslr-bypass-analysis.md
Normal file
94
objdump-dlx-calc-poc/docs/aslr-bypass-analysis.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# ASLR bypass analysis
|
||||
|
||||
This repository contains an ASLR-on exploit for a local heap/libio profile. It
|
||||
does not contain a deterministic universal ASLR bypass for the unmodified
|
||||
`objdump` process.
|
||||
|
||||
## What works
|
||||
|
||||
The payload set can reach the helper command `P` with ASLR enabled when the
|
||||
heap and libc low-word layout matches one of the generated profiles.
|
||||
|
||||
The current generator emits:
|
||||
|
||||
- `orig`: the first measured profile.
|
||||
- `wsl2404`: offsets measured against the pinned `dlx-elf` build on
|
||||
WSL/Ubuntu 24.04.
|
||||
|
||||
The `wsl2404` profile uses:
|
||||
|
||||
```text
|
||||
off_io=-0x3690
|
||||
off_sec=0xbb0
|
||||
rbase=0x220
|
||||
buf_delta=0x702fff00 or 0x6f300000
|
||||
system_delta=0x7042e500 or 0x7043e4ff
|
||||
```
|
||||
|
||||
## Why argv two-stage is not enough
|
||||
|
||||
A deterministic leak-then-exploit route would need this sequence in one
|
||||
`objdump` process:
|
||||
|
||||
1. Process file 1 and leak libc.
|
||||
2. Generate file 2 with the exact `system` delta.
|
||||
3. Process file 2 with the same ASLR layout.
|
||||
|
||||
That path did not hold for this trigger. In local GDB measurements with
|
||||
`objdump -W -r file1 file2`, the DWARF relocation side effect that mutates
|
||||
`.debug_info` ran for the first object only. The second object's relocation
|
||||
table printed unmodified symbol names (`s0`, `s1`, and so on).
|
||||
|
||||
FIFO staging is also blocked in unmodified `objdump`: `display_file()` calls
|
||||
`get_file_size()`, and `get_file_size()` rejects non-regular files before
|
||||
`bfd_openr()`.
|
||||
|
||||
## Why a fixed single-file transform is not universal
|
||||
|
||||
The useful dynamic value in the corrupted `FILE` object is the existing libc
|
||||
pointer at `FILE+0x68`:
|
||||
|
||||
```text
|
||||
_IO_2_1_stderr_ offset = 0x2044e0
|
||||
system offset = 0x58750
|
||||
```
|
||||
|
||||
For a page-aligned libc base, converting `P = base + 0x2044e0` into
|
||||
`S = base + 0x58750` requires carry/borrow information from lower
|
||||
little-endian bytes.
|
||||
|
||||
Counterexample over low 32 bits:
|
||||
|
||||
```text
|
||||
base_low = 0x0000: P bytes = e0 44 20 00, S bytes = 50 87 05 00
|
||||
base_low = 0x8000: P bytes = e0 c4 20 00, S bytes = 50 07 06 00
|
||||
```
|
||||
|
||||
The original byte 2 and byte 3 are identical in both cases (`20 00`), but the
|
||||
desired byte 2 differs (`05` versus `06`) based on original byte 1.
|
||||
|
||||
The DLX relocation additions available to the payload operate on big-endian
|
||||
8/16/32-bit fields in the target byte stream. Their carries flow from higher
|
||||
memory offsets toward lower memory offsets. They cannot make final byte 2
|
||||
depend on original byte 1. PC-relative writes can set constants, but they do
|
||||
not introduce the missing dependency.
|
||||
|
||||
`tools/search_pointer_transform.py` is a sanity check for this reasoning. It
|
||||
asks Z3 for fixed sequences consisting of one 32-bit relocation plus up to a
|
||||
chosen number of 8/16-bit correction relocations, then brute-verifies any
|
||||
candidate over all page-aligned low-32-bit bases.
|
||||
|
||||
Example:
|
||||
|
||||
```bash
|
||||
python3 tools/search_pointer_transform.py --mode r32-first --max-extra 4
|
||||
python3 tools/search_pointer_transform.py --mode r32-last --max-extra 4
|
||||
```
|
||||
|
||||
Both forms found no universal transform up to four correction relocations in
|
||||
the tested operation class.
|
||||
|
||||
## Result
|
||||
|
||||
The PoC should be described as ASLR-on and profile-dependent. It is not a
|
||||
universal single-file ASLR bypass.
|
||||
Reference in New Issue
Block a user