64-bit Enhancements

The transition from 32-bit to 64-bit in x86 architecture offers substantial improvements in memory capacity, computational performance, register size, and instruction set.

Main Differences

The two main differences between 32-bit and 64-bit architecture are that there is a much larger memory capacity and that there are sixteen general purpose 64-bit registers.

The process and system address-space available to Windows in a 64-bit environment increases from 2 gigabytes (default) on a 32-bit architecture to 128 terabytes (Windows 8.1 and later) on a 64-bit architecture. This can be quite daunting when we first transition from writing 32-bit shellcode, but as we will see, the transition isn't that difficult.

Windows Memory

The following image shows a conceptual view of Windows memory space. It shows that system space memory is absolute. Absolute memory addresses are fixed and independent of any specific process or program running on the system. They provide a way for the operating system and hardware to access and manipulate the physical memory directly and allow the system memory to be shared between processes.

Virtual memory is a memory management technique used by operating systems to provide an abstraction layer between the physical memory (RAM) and the memory requirements of running programs. It allows programs to operate, in user space, as if they have access to a large, contiguous block of memory, even if the physical memory is limited. It also means that two processes can use the same virtual memory addresses, albeit independent of each other.

It is also worth noting that Windows does not use all of the available memory in the 64-bit address space, which is 16 exabytes.

General Purpose Registers

The 64-bit registers are shown in the following table. Some of the familiar registers have been extended, such as eax to rbx and the stack registers are now rbp and rsp.

Notably, there is an additional eight general purpose registers: r8 through r9.

Note: the high 8 bits of ax, bx, cx, and dx are still addressable as ah, bh, ch, and dh but can't be used with all types of operands.

The ELFAGS register has been replaced with the RFLAGS register, although the higher 32-bits are reserved and not currently used.

The x86 64-bit CPUs have 80-bit and 128-bit registers but these are not important for now.

Register Volatility

When we write 64-bit shellcode it can be useful to store values in registers that we do not want to be overwritten by any Win32 functions we call. These are referred to as nonvolatile registers, meaning that they persist between API calls.

The following registers are nonvolatile: r12, r13, r14, r15, rdi, rsi, rbx, rbp, and rsp.

Last updated