Skip to main content

[Pwn] A Primer on House Of Muney

· 4 min read
MuelNova
Pwner who wants to write codes.

A few days ago, ZBR shared this repo. I hadn’t heard of it, but its exploitation power looked impressive, so here’s a brief analysis.

In short, House Of Muney bypasses ASLR and achieves code execution without any memory leak.

Its prerequisites are:

  • Partial RELRO or No RELRO (we need to overwrite .dynsym to hijack dlresolve)
  • Ability to allocate large chunks via mmap
  • Ability to forge a chunk’s prev_size and size fields to flip the IS_MMAPPED bit

We’ll use glibc 2.31 in Docker. Here’s a sample Dockerfile:

FROM ubuntu:20.04
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update -y && apt-get install -y socat gdb vim tmux python3 python3-pip
RUN apt-get install -y git build-essential libssl-dev libffi-dev libxml2-dev libxslt1-dev zlib1g-dev patchelf python3-dev
RUN pip3 install pwntools
RUN git clone https://github.com/pwndbg/pwndbg && cd pwndbg && ./setup.sh
RUN echo "set auto-load safe-path /" >> /root/.gdbinit
RUN git clone https://github.com/mdulin2/house-of-muney
RUN cd house-of-muney && ./compile.sh

Prerequisites

mmap / munmap

When malloc requests exceed mmap_threshold (defaults to 128KB), glibc uses mmap to allocate pages:

#define DEFAULT_MMAP_THRESHOLD_MIN (128*1024)
mp_.mmap_threshold = DEFAULT_MMAP_THRESHOLD;

In sysmalloc, chunks allocated via mmap get the IS_MMAPPED flag:

set_head(p, size | IS_MMAPPED);

These mmaped chunks sit just above the main libc.so mapping, so they’re adjacent in memory. A single large chunk can cross into the libc address space without leaking its base.

Freeing such a chunk calls munmap_chunk, which only verifies page alignment, not prev_size or size, letting us munmap arbitrary-sized or arbitrarily forged chunks.

Symbol Resolution (dlresolve)

Dynamic symbol resolution uses the PLT/GOT: calls go through printf@plt, which jumps into the dynamic linker via __dl_runtime_resolve. That routine reads .rel.plt/.rela.plt entries, finds the corresponding Elf64_Sym in .dynsym, and looks up its name in .strtab.

By overwriting entries in .dynsym and adjusting the GNU hash tables, we can redirect one imported function (e.g., exit) to another (system).

Exploitation Steps

  1. Heap Layout: Allocate two large mmap chunks, p1 and p2, so that p2 sits right after p1.
  2. Forge Header: Overwrite p2’s header (prev_size and size) so that p2 spans p1 + p2 + part of the libc base.
  3. Free Overlap: Free p2. Its munmap_chunk unmaps a region overlapping the libc mapping, making those pages writable and unmapped in the heap.
After free, heap map:
0x7ffff7b27000 - 0x7ffff7e28000 → RW (unmapped region)
0x7ffff7e28000 - 0x7ffff7f77000 → R-- (libc)
  1. Remap: Allocate a chunk larger than the forged size. This allocation covers part of the libc address space, turning it RW:
    0x7ffff7b27000 - 0x7ffff7e28000 → RW (heap)
0x7ffff7e28000 - 0x7ffff7f77000 → R-- (libc)
  1. Forge ELF Structures: Since mmap-backed pages are zero-initialized, we must reconstruct the GNU hash table fields and Elf64_Sym entries. One approach is to run the original binary in GDB, trace __dl_fixup, record offsets and values, and then write them into the overlapped area. Key fields include:

    • l_gnu_bitmask
    • l_gnu_bucket
    • l_gnu_chain_zero
    • The target Elf64_Sym for exit, modifying its st_value to point to system.
  2. Trigger Hijack: Call exit("/bin/sh"), which resolves through the forged structures, invoking system("/bin/sh").

Diagram: Memory Map Overlap

Heap region:    [p1][p2][ ... remapped libc ... ]
Original libc: [ libc-2.31.so ]

GNU Hash Replay

Alternatively, one can manually patch the GNU hash tables by dumping and reusing values observed in GDB.

Conclusion

House Of Muney elegantly unmaps and remaps libc pages to gain RWX control and then hijacks the dynamic linker. It requires forging mmap chunk headers and carefully reconstructing ELF structures.

This technique works in glibc up to 2.31; later versions may add GOT integrity checks.

References

info

This content is generated by LLM and might be incomplete or incorrect. Please refer to the original Chinese version for full details.

Loading Comments...