This project demonstrates a microarchitectural side-channel attack using the prefetch instruction to leak data from memory. It was developed as part of a pwn.college challenge and combines low-level assembly with a C-based brute-force harness.
The goal of this challenge is to extract a secret byte from a protected memory region by exploiting timing differences introduced by CPU caching behavior.
The implementation consists of two components:
- Assembly payload: Performs the timing-based side-channel attack using
rdtscandprefetcht2. - C harness: Automates execution, modifies shellcode dynamically, and extracts the leaked byte via process exit codes.
The attack relies on the fact that:
prefetchinstructions can bring data into cache without triggering faults.- Access timing differs depending on whether a memory address is valid/mapped.
- These timing differences can be measured using
rdtsc.
By scanning memory and measuring access latency, the program identifies a valid mapped region and then leaks a byte from it.
-
Timing Measurement
- Uses
rdtscbefore and afterprefetcht2to measure memory access latency. - Combines
rdxandraxto form a 64-bit timestamp.
- Uses
-
Prefetch Side-Channel
prefetcht2 [r14]is used to probe memory without causing a crash.- Cached vs non-cached access times are used to infer validity.
-
Averaging for Stability
- Each address is probed 20 times.
- Average latency is computed to reduce noise.
-
Memory Scanning
- Iterates through memory range:
0x2000000000 → 0x9000000000 - Stops when latency falls below a threshold.
- Iterates through memory range:
-
Data Exfiltration
- Once a valid region is found:
- Reads byte at
[r14 + 1] - Returns it via
exitsyscall
- Reads byte at
- Once a valid region is found:
- Reads compiled shellcode from file: babyprefetch-shellcode-raw
- Modifies a specific byte (
buf[0x85]) dynamically - Writes updated shellcode back to disk
- Executes target binary: /challenge/babyarch_prefetchpeek
- Captures leaked byte via process exit status
- Repeatedly executes the challenge binary
- Filters valid ASCII outputs: 32 <= exit_code < 127
- Uses
nanosleepto stabilize timing and reduce noise - Prints recovered character
C Program ├── Load shellcode ├── Modify payload byte ├── Write back to file ├── Loop: │ ├── Execute challenge binary │ ├── Capture exit code │ ├── Validate ASCII range │ └── Print leaked byte └── Repeat
- Exploiting CPU cache behavior for information leakage
- Timing-based inference using
rdtsc
- Using
prefetcht2to probe inaccessible memory - Avoiding faults while still observing cache effects
- Averaging multiple timing samples
- Introducing delays (
nanosleep) for stability
- Pure assembly payload without libc
- Direct syscall usage for exfiltration