11. x64 Architecture

Once you understand the concepts of x86 architecture, it's much easier to understand x64 architecture. The x64 architecture was designed as an extension to x86 and has a strong resemblance with x86 instruction sets, but there are a few differences that you need to be aware of from a code analysis perspective. This section covers some of the differences in the x64 architecture:

  • The first difference is that the 32-bit (4 bytes) general purpose registers eaxebxecxedxesiediebp, and esp are extended to 64 bits (8 bytes); these registers are named raxrbxrcxrdxrsirdirbp, and rsp. The eight new registers are named r8, r9, r10, r11, r12, r13, r14, and r15. As you might expect, a program can access the register as 64-bit (RAXRBX, and so on), 32-bit (eax, ebx, etc), 16-bit (axbx, and so on), or 8-bit (albl, and so on). For example, you can access the lower half of the RAX register as EAX and the lowest word as AX. You can access the registers r8-r15 as byte, word, dword, or qword by appending b, w, d or q to the register name.
  • x64 architecture can handle 64-bit (8 bytes) data, and all of the addresses and pointers are 64 bits (8 bytes) in size.
  • The x64 CPU has a 64-bit instruction pointer (rip) that contains the address of the next instruction to execute, and it also has a 64-bit flags register (rflags), but currently, only the lower 32 bits are used (eflags).
  • The x64 architecture supports rip-relative addressing. The rip register can now be used to reference memory locations; that is, you can access data at a location which is at some offset from the current instruction pointer.
  • Another major difference is that in the x86 architecture, the function parameters are pushed onto the stack as mentioned previously, whereas in the x64 architecture, the first four parameters are passed in the rcxrdxr8, and r9 registers, and if the program contains additional parameters they are stored on the stack. Let's look at an example of simple C code (the printf function); this function takes six parameters:
printf("%d %d %d %d %d", 1, 2, 3, 4, 5);

The following is the disassembly of the C code compiled for a 32-bit (x86) processor; in this case, all of the parameters are pushed onto the stack (in reverse order), and after the call to printf,  add esp,18h is used to clean up the stack. So, it is easy to tell that the printf function takes six parameters:

push 5
push 4
push 3
push 2
push 1
push offset Format ; "%d %d %d %d %d"
call ds:printf
add esp, 18h

The following is the disassembly of the C code compiled for a 64-bit (x64) processor. The first instruction, at ➊, allocates 0x38 (56 bytes) of space on the stack. The first, second, third, and fourth parameters are stored in the rcx, rdx, r8 and r9 register (before the call to printf), at  ➋, ➌, ➍, ➎. The fifth and the sixth parameters are stored on the stack (in the allocated space), using instructions at ➏ and ➐. The push instruction was not used in this case, making it difficult to determine if the memory address is a local variable or a parameter to the function. In this case, the format string helps to determine the number of parameters passed to the printf function, but in other cases, it's not that easy:

sub rsp, 38h  ➊ 
mov dword ptr [rsp+28h], 5 ➐
mov dword ptr [rsp+20h], 4 ➏
mov r9d, 3 ➎
mov r8d, 2 ➍
mov edx, 1 ➌
lea rcx, Format ; "%d %d %d %d %d" ➋
call cs:printf
Intel 64 (x64) and IA-32 (x86) architecture consist of many instructions. If you come across an assembly instruction that is not covered in this chapter, you can download the latest Intel architecture manuals from https://software.intel.com/en-us/articles/intel-sdm, and the instruction set reference (volumes 2A, 2B, 2C, and 2D) can be downloaded from https://software.intel.com/sites/default/files/managed/a4/60/325383-sdm-vol-2abcd.pdf.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset