⏱️ Lectura: 10 min
skitter-creek-bath-salts, through what its author calls DRAM scrambling, rewrites the address translation tables inside an AMD CPU’s memory controller, and with that single change exposes regions of DRAM that even the kernel itself cannot see. The project, published on GitHub by the researcher known as xoreaxeaxeax, states a direct goal: unlocking the Platform Security Processor (PSP), System Management Mode (SMM), the DRAM low-power C6 state, and the CPU’s microcode.
📑 En este artículo
The technique doesn’t rely on a specific software bug. It targets the layer where an address stops being an abstract number and becomes a voltage on a physical DRAM chip: the memory controller (MCT/IMC). If that layer can be reprogrammed, any protected memory region (a carveout reserved for the PSP or for SMM) is no longer truly isolated from the rest of the system.
TL;DR
- skitter-creek-bath-salts, by xoreaxeaxeax, manipulates the DRAM controller’s translation registers to expose protected memory on AMD CPUs.
- The project’s stated goal is to unlock four subsystems: PSP, SMM, the DRAM C6 state, and the CPU’s microcode.
- It works on AMD Family 16h CPUs, the last generation whose datasheets publicly document the memory controller’s translation registers.
- AMD stopped publishing that documentation starting with Family 17h, which makes it harder to replicate the technique as-is on newer hardware.
- The repository includes a kernel module, user-space tools, examples, and an analysis directory, under an open license.
- The project has racked up 1,400 stars and 119 forks on GitHub.
- The author argues that the conceptual approach extends to ARM and RISC-V, though the published code only covers AMD.
What happened
xoreaxeaxeax uploaded the skitter-creek-bath-salts repository to GitHub, a toolset (a kernel module plus user-space utilities) that rewrites how an AMD CPU’s memory controller translates physical addresses into actual DRAM cells. The README sums it up with a line that plays on a guarantee programmers take for granted: &x == &x, “usually”. When that equality stops holding because the physical address was remapped underneath the operating system, protections that rely on “this memory region is only for the PSP” or “this region is only for SMM” lose their foundation.
The repository doesn’t deliver a one-click exploit. It’s a research toolkit: it includes the kernel/, userspace/, examples/, analysis/, and data/ folders, plus a Makefile and two documents, README.md and USAGE.md, that describe the full usage flow.
Background and history
AMD’s Family 16h corresponds to the low-power Jaguar architecture, used in APUs like Kabini and Temash starting in 2013. According to the repository itself, it’s the last generation of AMD processors whose public datasheets document the DRAM controller’s translation registers, and they also explicitly acknowledge that those registers have no way to be locked. Starting with Family 17h, with the arrival of Zen, that information disappeared from the public documentation.
That detail is the hinge of the whole project: it’s not that AMD closed off the mechanism, it’s that it stopped describing it. The README itself says it plainly: “the odyssey of *p is similar across generations and architectures, and the underlying transformations extend even to ARM, RISC-V, and beyond; skitter-creek-bath-salts shows us only how to begin”. That’s an admission of limited scope, not a promise that the technique works the same way on any modern CPU.
Technical details and DRAM scrambling performance
The README documents, layer by layer, the entire path a simple *p in C travels before touching an actual memory cell. It starts at the CPU core: a canonical-form check on the virtual address, adding the segment base (FS/GS), a TLB lookup, and, if that misses, a page table walk (PML4, PDPT, PD, PT) with privilege, NX, SMEP/SMAP, and protection-key checks at every level. If the CPU is virtualized, that walk repeats over EPT or NPT, multiplying memory accesses by up to five for every real translation hit.
Only then does a physical address appear, and what matters most for this project still hasn’t happened: memory type resolution via MTRR and IA32_PAT, the pass through L1/L2/LLC cache with MESI/MOESI coherence, and finally the memory controller (MCT/IMC). It’s at this last layer where skitter-creek-bath-salts acts: it rewrites the DRAM hole remap, the exclusion mapping for reserved regions, and above all, the interleave hash that distributes a physical address across channel, rank, and bank through BIOS-configurable XOR operations. At the end of that chain there’s still a bank swizzle (another configurable scramble) before reaching the actual chip-select.
The core idea is simple to state and complex to execute: if the interleave hash and the swizzle are configurable, and the firmware never locks them after boot, a program with sufficient privileges can rewrite them and make addresses that once pointed to a protected carveout (for example, RAM reserved for the PSP) now appear mapped into a range accessible from the operating system. Nothing about the hardware “breaks”: what breaks is the assumption that those translation paths are stable and invisible to unprivileged software.
💭 Key point: DRAM scrambling isn’t looking for a flaw in one isolated component. It’s looking for the point where they all converge: if the memory controller ultimately decides which physical cell an address corresponds to, controlling that decision voids any isolation that relies on it.
How to get started or try it
The repository is cloned and built using standard Linux development tools:
git clone https://github.com/xoreaxeaxeax/skitter-creek-bath-salts.git
cd skitter-creek-bath-salts
make
The Makefile builds both the kernel module and the user-space utilities described in USAGE.md. At a high level, the documented flow is: load the kernel module with root privileges, use the userspace/ utilities to inspect the map of DRAM regions the memory controller sees, and from there apply the translation rewrite to the range you want to expose. The exact parameters per motherboard are in examples/ and USAGE.md: each board configures interleave differently, so there’s no single command that works for all hardware.
Before touching anything, it’s a good idea to establish a baseline of the system itself using tools already present in any Linux distro:
# View the active memory type ranges (MTRR)
cat /proc/mtrr
# Check whether the kernel reports PSP activity at boot
sudo dmesg | grep -i psp
Running that pair of commands before and after applying an interleave rewrite is the bare minimum to confirm the memory map actually changed, instead of just assuming it.
⚠️ Heads up: this is lab hardware, not a production tool. It requires full physical or administrative access to the machine, a specific AMD Family 16h processor, and loading an unsigned kernel module. It’s not a remote attack or something run against a third-party server.
There’s also no equivalent path for Windows or macOS: the technique works by rewriting specific AMD memory controller registers from a Linux kernel module, something with no direct analogue on those operating systems or on hardware other than Family 16h.
Impact and analysis
The surface this work exposes matters beyond any single CPU model because it strikes at a widespread design assumption: that a component’s security (PSP, SMM, an enclave, a hypervisor) can rest on “this physical memory region is invisible to the rest of the system”. DRAM scrambling shows that this invisibility depends on a configurable translation layer that, at least on Family 16h, nobody locked down.
| Subsystem | What it normally protects | What scrambling exposes |
|---|---|---|
| PSP | Security firmware isolated from the operating system | Access to memory outside the reserved carveout |
| SMM | Privileged code invisible to the OS and hypervisor | Potential read or write access to its memory regions |
| C6 (DRAM) | Low-power state that retains memory contents | Access to data that should stay outside the normal map |
| Microcode | Signed CPU patches locked away from the user | Additional surface for inspecting core behavior |
The honest limitation is the same one the author acknowledges: this was tested and documented on a CPU generation discontinued more than a decade ago, precisely because it’s the last one with public datasheets describing the mechanism. Nothing in the repository proves that the same unlocked interleave hash still exists as-is on a current Ryzen or EPYC. It’s a reasonable research hypothesis, not a verified fact for Family 17h onward.
Simplified diagram of the path skitter-creek-bath-salts attacks
flowchart TD
A["CPU: virtual address"] --> B["MMU: page walk"]
B --> C["Physical address"]
C --> D["Cache and coherence"]
D --> E["Memory controller (MCT or IMC)"]
E --> F["Interleave hash: channel, rank, bank"]
F --> G["Bank swizzle / scrambling"]
G --> H["Actual DRAM cell"]
subgraph Region rewritten by the project
F
G
end
What’s next
The README itself is explicit about its scope: “skitter-creek-bath-salts shows us only how to begin”. That leaves two open questions for anyone who wants to continue the research. First, whether the interleave and swizzle registers on AMD processors after Family 16h, where there’s no longer a public datasheet, remain reprogrammable the same way or were locked down starting with Zen. Second, whether the equivalent transformations on ARM and RISC-V memory controllers, which the author mentions as a conceptual extension, are replicable with similar tools. The repository doesn’t answer either one: it leaves them open.
📖 Summary on Telegram: View summary
If you work in firmware security, or you’re simply curious to see address translation in action, clone the repository and run cat /proc/mtrr on your own machine before reading USAGE.md: you’ll have a real baseline to compare against every step of the project.
Frequently Asked Questions
What is DRAM scrambling in this context?
It’s the deliberate rewriting of the memory controller registers that decide which physical channel, rank, and bank an address corresponds to. By changing that mapping, addresses that once pointed to a protected region become accessible from elsewhere in the system.
Do I need special hardware to try it?
Yes. The project is documented and tested on AMD Family 16h CPUs (Jaguar architecture, APUs like Kabini and Temash), the last generation with public datasheets describing these registers.
Is it a remote attack?
No. It requires loading a kernel module with administrator privileges on the target machine, meaning prior physical or administrative access, not a vulnerability exploitable over the network.
Why did AMD stop documenting these registers?
The repository doesn’t explain it, it only notes that public documentation of these registers disappeared starting with Family 17h. That’s consistent with a broader trend among CPU makers of reducing public documentation of security-sensitive internal structures.
Does it work on Intel or ARM CPUs?
The published code is specific to AMD’s memory controller. The author suggests the concept extends to ARM and RISC-V, but the repository doesn’t include an implementation for those architectures.
What is a memory “carveout”?
It’s a region of DRAM that the firmware reserves and marks as invisible to the operating system, typically for exclusive use by a component like the PSP or SMM code.
References
- skitter-creek-bath-salts repository on GitHub: source code, technical README, and the project’s usage documentation.
- Wikipedia: AMD Platform Security Processor: general background on the PSP subsystem the project aims to unlock.
- Wikipedia: System Management Mode: explanation of the SMM execution mode present in x86 processors.
📱 Enjoying this content? Follow @programacion on Telegram for daily tech content in Spanish: quick summaries, fresh content every day.
Imagen destacada: Foto de Maxence Pira en Unsplash
0 Comments