Registers and Memory Layout

3 minutes read

Registers (x64)

RegisterLow 32-bitsLow 16-bitsLow 8-bitsNotes
%rax%eax%ax%ala function's return value, caller-saved
%rdi%edi%di%dil1st argument of a function, caller-saved
%rsi%esi%si%sil2nd argument of a function, caller-saved
%rdx%edx%dx%dl3rd argument of a function, caller-saved
%rcx%ecx%cx%cl4th argument of a function, caller-saved
%r8%r8d%r8w%r8b5th argument of a function, caller-saved
%r9%r9d%r9w%r9b6th argument of a function, caller-saved
%r10%r10d%r10w%r10btemporary register, caller-saved
%r11%r11d%r11w%r11btemporary register, caller-saved
%rbp%ebp%bp%bplbase pointer, pointing to the base of the current stack frame, callee-saved
%rsp%esp%sp%splstack pointer, pointing to the topmost element in the stack, callee-saved
%rbx%ebx%bx%bllocal variable, callee-saved
%r12%r12d%r12w%r12blocal variable, callee-saved
%r13%r13d%r13w%r13blocal variable, callee-saved
%r14%r14d%r14w%r14blocal variable, callee-saved
%r15%r15d%r15w%r15blocal variable, callee-saved
%ripinstruction pointer

Memory Layout

memory layout

Stack Frame Layout

A stack is allocated at a high address and grows towards lower addresses.

stack frame layout

Position Independent Executables (PIE)

The memory addresses are not fully randomized, particularly the lower 3 bits of the base address, even when PIE is enabled.

1pwndbg> info proc mappings
2process 67443
3Mapped address spaces:
4
5Start Addr End Addr Size Offset Perms File
60x0000555555554000 0x0000555555555000 0x1000 0x0 r--p /ptr/vuln
70x0000555555555000 0x0000555555556000 0x1000 0x1000 r-xp /ptr/vuln
80x0000555555556000 0x0000555555557000 0x1000 0x2000 r--p /ptr/vuln
90x0000555555557000 0x0000555555558000 0x1000 0x2000 r--p /ptr/vuln
100x0000555555558000 0x0000555555559000 0x1000 0x3000 rw-p /ptr/vuln
110x00007ffff7c00000 0x00007ffff7c28000 0x28000 0x0 r--p /usr/lib/x86_64-linux-gnu/libc.so.6
120x00007ffff7c28000 0x00007ffff7db0000 0x188000 0x28000 r-xp /usr/lib/x86_64-linux-gnu/libc.so.6
130x00007ffff7db0000 0x00007ffff7dff000 0x4f000 0x1b0000 r--p /usr/lib/x86_64-linux-gnu/libc.so.6
140x00007ffff7dff000 0x00007ffff7e03000 0x4000 0x1fe000 r--p /usr/lib/x86_64-linux-gnu/libc.so.6
150x00007ffff7e03000 0x00007ffff7e05000 0x2000 0x202000 rw-p /usr/lib/x86_64-linux-gnu/libc.so.6
160x00007ffff7e05000 0x00007ffff7e12000 0xd000 0x0 rw-p
170x00007ffff7fa0000 0x00007ffff7fa3000 0x3000 0x0 rw-p
180x00007ffff7fbd000 0x00007ffff7fbf000 0x2000 0x0 rw-p
190x00007ffff7fbf000 0x00007ffff7fc1000 0x2000 0x0 r--p [vvar]
200x00007ffff7fc1000 0x00007ffff7fc3000 0x2000 0x0 r--p [vvar_vclock]
210x00007ffff7fc3000 0x00007ffff7fc5000 0x2000 0x0 r-xp [vdso]
220x00007ffff7fc5000 0x00007ffff7fc6000 0x1000 0x0 r--p /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
230x00007ffff7fc6000 0x00007ffff7ff1000 0x2b000 0x1000 r-xp /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
240x00007ffff7ff1000 0x00007ffff7ffb000 0xa000 0x2c000 r--p /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
250x00007ffff7ffb000 0x00007ffff7ffd000 0x2000 0x36000 r--p /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
260x00007ffff7ffd000 0x00007ffff7fff000 0x2000 0x38000 rw-p /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
270x00007ffffffdd000 0x00007ffffffff000 0x22000 0x0 rw-p [stack]
280xffffffffff600000 0xffffffffff601000 0x1000 0x0 --xp [vsyscall]

Heap

Unlike the stack, the heap segment starts at a low address and grows towards higher memory addresses. The basic concept in the heap meamory allocation is chunk, as defined below.

/*
  This struct declaration is misleading (but accurate and necessary).
  It declares a "view" into memory allowing access to necessary
  fields at known offsets from a given base. See explanation below.
*/

struct malloc_chunk {

  INTERNAL_SIZE_T      mchunk_prev_size;  /* Size of previous chunk (if free).  */
  INTERNAL_SIZE_T      mchunk_size;       /* Size in bytes, including overhead. */

  struct malloc_chunk* fd;         /* double links -- used only if free. */
  struct malloc_chunk* bk;

  /* Only used for large blocks: pointer to next larger size.  */
  struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */
  struct malloc_chunk* bk_nextsize;
};

House of Force

"House Of Force" is an exploitation approach against the heap memory. This exploitation requires the attacker can override the size field in the top chunk's header. Then, the attacker can leverage the integer overflow to control the memory address that malloc will return, further leading to arbitrary memory read/write.

References