- What: Analysis of House of Apple 2 exploitation technique
- Impact: Relevant to security researchers and developers
This is a dissection of House of Apple 2, and also a small excuse to put an interesting exploitation path under the magnifying glass in GDB and understand it end to end. It does not introduce a new variation of the technique; it simply answers my curiosity about how House of Apple 2 holds up on recent versions of glibc and whether it remains a viable exploitation path. The document provides an interactive GDB walkthrough that readers can follow alongside the sandbox to develop a more intuitive understanding of the primitive. All experiments use glibc 2.43, as packaged by Ubuntu 26.04 and Fedora 44 at the time of writing. Interactive lab to follow along with the walkthrough:https://github.com/jazho76/house_of_apple_2 File Stream Oriented Programming (FSOP).This is about manipulating glibc file stream structures to hijack control flow. One way to do this is by corrupting the vtable dispatch mechanism of_IO_FILE_plus. Modern glibc validates this vtable, so the obvious approach of replacing it with an arbitrary address doesn’t work. House of Apple 2, originally introduced byRoderick, works around this restriction by using a valid_IO_FILE_plusvtable to reach the wide-character stream machinery, where a secondary vtable is directly dispatched without range validation. This provides anarbitrary callprimitive that we can escalate into a stack pivot and a ROP chain. This exploration assumes that we can overwrite aFILEstructure and that we have both a heap leak and a libc leak. The target binary already provides this. The sandbox (available in the GitHub repo) runs Ubuntu 26.04 LTS, giving us a modern environment to explore the technique. The image includes GDB, pwndbg, pwntools, ropper and tmux. It also contains a target binary with an interactive menu for invoking file stream operations such asfopen,fread,fwrite, andfclose. This gives us a convenient way to manipulate streams while debugging and testing ideas. Let’s start by inspecting the_IO_FILEand_IO_FILE_plusstructures: In practical terms,_IO_FILE_plusis an_IO_FILEwith a vtable pointer. That immediately looks interesting: if we can control this pointer, we may be able to redirect an indirect call and hijack control flow. To inspect the vtable, let’s examine aFILEpointer returned byfopen. The pointer targets the_IO_file_jumpstable. This is a set of 21 function pointers. File stream operations dispatch through different entries depending on the execution path. For this exploration I’ll focus on thefwritepath. After placing breakpoints on each function and callingfwrite, the first breakpoint we hit is_IO_file_xsputn. The call happens atfwrite+216. This matches theglibc source:_IO_sputnis a macro that dispatches through the vtable, resolving to_IO_file_xsputnfor this stream. For a first attempt, let’s overwrite the vtable pointer withdesired_func - 0x38and set a breakpoint atfwrite+216. Execution aborts before reaching the breakpoint. The error suggests that glibc validates the vtable pointer before performing the indirect call. Let’s inspect the backtrace and see where this happens. fwritereaches_IO_vtable_checkwhich is rejecting the forged vtable pointer.