APRR - Access Protection ReRouting
> Almost a year ago I did a write-up on KTRR, first introduced in Apple’s A10 chip series. Now over the course of the last year, there has been a good bit of talk as well as confusion about the new mitigations shipped with Apple’s A12. One big change, PAC, has already been torn down in detail by Brandon Azad, so I’m gonna leave that out here. What’s left to cover is more than just APRR, but APRR is certainly the biggest chunk, hence the title of this post.
> APRR is a pretty cool feature, even if parts of it are kinda broke. What I really like about it (besides the fact that it is an efficient and elegant solution to switching privileges) is that it untangles EL1 and EL0 memory permissions, giving you more flexibility than a standard ARMv8 implementation. What I don’t like though is that it has clearly been designed as a lockdown feature, allowing you only to take permissions away rather than freely remap them.
> It’s also evident that Apple is really fond of post-exploit mitigations, or just mitigations in general. And on one hand, getting control over the physical address space is a good bit harder now. But on the other hand, Apple’s stacking of mitigations is taking a problematic turn when adding new mitigations actively creates vulnerabilities now.
glibc realloc(ptr, 0) vs. C17 specification
Map Guard and Intel MPK
> Earlier this year I pushed a small library to Github called Map Guard. The goal of Map Guard is to enforce non-invasive security policies with regards to how pages of memory may be allocated, or modified, with the mmap syscall. For example, we may want to deny any page allocations marked Read, Write, and Execute as it introduces an easy mechanism for an exploit developer to take advantage of. In the rest of this post I will break down the approach I took to implement each of these security policies, and finally how Map Guard uses Intel’s Memory Protection Keys to allow transparently enabling Execute Only memory for all regions of mapped code.
security things in Linux v5.2
> page allocator freelist randomization
And some other things as well.
Efficient Go APIs with the mid-stack inliner
> A common task in Go API design is returning a byte slice. In this post I will explore some old techniques and a new one.
RAMBleed Reading Bits in Memory Without Accessing Them
> RAMBleed is based on a previous side channel called Rowhammer, which enables an attacker to flip bits in the memory space of other processes. We show in our paper that an attacker, by observing Rowhammer-induced bit flips in her own memory, can deduce the values in nearby DRAM rows. Thus, RAMBleed shifts Rowhammer from being a threat not only to integrity, but confidentiality as well. Furthermore, unlike Rowhammer, RAMBleed does not require persistent bit flips, and is thus effective against ECC memory commonly used by server computers.
Software-defined far memory in warehouse scale computers
Trashing the Flow of Data
> As has been shown many times before, often bugs that don’t seem exploitable at first can be turned into an arbitrary read/write. In this case in particular, triggering the garbage collector while our fake pointer was on the stack gave us a very strong exploitation primitive. The V8 team fixed the bug very quickly as usual. But more importantly, they’re planning to refactor the InferReceiverMaps function to prevent similar bugs in the future. When I noticed this function in the past, I was convinced that one of the callers will get it wrong and audited all the call sites. Back then I couldn’t find a vulnerability but a few months later I stumbled over this newly introduced code that didn’t add the right runtime checks. In hindsight, it would have been worthwhile to point out this dodgy API to the team even without vulnerabilities to show for.
Can two new objects point to the same memory address in GoLang?
> This is because the memory allocation on heap calls the newobject function in runtime package. newobject function would invoke mallocgc function to allocate memory. This function is a bit special and it has some logic to check whether an object is indeed occupying memory or not, if no memory is needed, the address of zerobase(a global variable) will be assigned to it. In the above example snippet, both a and c are empty struct which doesn’t need memory. Hence both a and c are having the same memory address which is the address of zerobase.
Splitting atoms in XNU
> A locking bug in the XNU virtual memory subsystem allowed violation of the preconditions required for the correctness of an optimized virtual memory operation. This was abused to create shared memory where it wasn’t expected, allowing the creation of a time-of-check-time-of-use bug where one wouldn’t usually exist. This was exploited to cause a heap overflow in XPC, which was used to trigger the execution of a jump-oriented payload which chained together arbitrary function calls in an unsandboxed root process, even in the presence of Apple’s implementation of ARM’s latest Pointer Authentication Codes (PAC) hardware mitigation. The payload opened a privileged socket and sent the file descriptor back to the sandboxed process, where it was used to trigger a kernel heap overflow only reachable from outside the sandbox.
This is excellent work.
A new runtime for Nim
> In this blog post I explore how the full Nim language can be used without a tracing garbage collector. Since strings and sequences in Nim can also be implemented with destructors the puzzle to solve is what to do with Nim’s ref pointers and new keyword.
> Type-specific allocation turns every “use after free” bug into a logical bug but no memory corruption can happen. So ... we have already accomplished “memory safety without a GC”. It didn’t require a borrow checker nor an advanced type system. It is interesting to compare this to an example that uses array indexing instead of pointers:
Heap Exploitation Part 1: Understanding the Glibc Heap Implementation
> or this reason, before I write about exploiting heap-based vulnerabilities, I will use the first two parts of this series to talk about how the heap works. This first post will be an introduction into some high-level concepts, and a discussion about how new heap chunks are created. In the next post I will do a deeper dive into the technical implementation of how chunks are freed and recycled.
What causes Ruby memory bloat?
> If only there is a way visualize the OS heaps so that I can see what’s going. Unfortunately there are no tools that allow me to do that. So I wrote an OS heap visualizer myself.
Linux: virtual address 0 is mappable via privileged write() to /proc/*/mem
> This can be abused on systems without SMAP to make NULL pointer
dereferences exploitable again.
JVM Anatomy Quark #23: Compressed References
> But does that mean the size of Java reference is the same as the machine pointer width? Not necessarily. Java objects are usually quite reference-heavy, and there is pressure for runtimes to employ the optimizations that make the references smaller. The most ubiquitous trick is to compress the references: make their representation smaller than the machine pointer width.
A proposed API for full-memory encryption
> Hardware memory encryption is, or will soon be, available on multiple generic CPUs. In its absence, data is stored — and passes between the memory chips and the processor — in the clear. Attackers may be able to access it by using hardware probes or by directly accessing the chips, which is especially problematic with persistent memory. One new memory-encryption offering is Intel’s Multi-Key Total Memory Encryption (MKTME) [PDF]; AMD’s equivalent is called Secure Encrypted Virtualization (SEV). The implementation of support for this feature is in progress for the Linux kernel. Recently, Alison Schofield proposed a user-space API for MKTME, provoking a long discussion on how memory encryption should be exposed to the user, if at all.
Inside the Apollo Guidance Computer's core memory
> The Apollo Guidance Computer (AGC) provided guidance, navigation and control onboard the Apollo flights to the Moon. This historic computer was one of the first to use integrated circuits, containing just two types of ICs: a 3-input NOR gate for the logic circuitry and a sense amplifier IC for the memory. It also used numerous analog circuits built from discrete components using unusual cordwood construction.
Also core rope: http://www.righto.com/2019/07/software-woven-into-wire-core-rope-and.html
> Erasable core memory and core rope both used magnetic cores, small magnetizable rings. But while erasable core memory used one core for each bit, core rope stored an incredible 192 bits per core, achieving much higher density.2 The trick was to put many wires through each core (as shown above), hardwiring the data: a 1 bit was stored by threading a wire through a core, while the wire bypassed the core for a 0 bit. Thus, once a core rope was carefully manufactured, using a half-mile of wire, data was permanently stored in the core rope.
Also, Bitcoin: http://www.righto.com/2019/07/bitcoin-mining-on-apollo-guidance.html
When your Memory Allocator hides Security Bugs
> Why would anyone do that? It might bring performance benefits to have memory allocation that‘s optimized for a specific application. It also can make programming more convenient when you can allocate many small buffers in a pool and then not bothering about freeing each one of then and instead just free the whole pool with all allocations within.
> There‘s a disadvantage with the pool allocator, and that is that it may hide bugs.
Taking a page from the kernel's book: A TLB issue in mremap()
> This is a technical blog post about TLB flushing bugs in kernels, intended for people interested in kernel security and memory management.
Introduction to Paging
> This post introduces paging, a very common memory management scheme that we will also use for our operating system. It explains why memory isolation is needed, how segmentation works, what virtual memory is, and how paging solves memory fragmentation issues. It also explores the layout of multilevel page tables on the x86_64 architecture.