title | date | categories | layout |
---|---|---|---|
Introducing 64-bit ELF Binaries |
2019-03-20 02:05:00 -0700 |
information |
post |
So far we've been focusing primarily on 32-bit binaries; however, what you've
learned so far will also apply to 64-bit binaries with a few key differences.
Let's summarize a few of the differences seen in the 64-bit version of
stack5
(shown below).
- the location of the code region is much different
- the pointer sizes are different.
- the arguments to main are passed via registers (
rdi
andrsi
) and then saved to the stack (inside of main). - there is a canary in place and it uses a segment register
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
char buffer[64];
gets(buffer);
}
0x0000000000400596 <+0>: push rbp
0x0000000000400597 <+1>: mov rbp,rsp
0x000000000040059a <+4>: sub rsp,0x60
0x000000000040059e <+8>: mov DWORD PTR [rbp-0x54],edi
0x00000000004005a1 <+11>: mov QWORD PTR [rbp-0x60],rsi
0x00000000004005a5 <+15>: mov rax,QWORD PTR fs:0x28
0x00000000004005ae <+24>: mov QWORD PTR [rbp-0x8],rax
0x00000000004005b2 <+28>: xor eax,eax
0x00000000004005b4 <+30>: lea rax,[rbp-0x50]
0x00000000004005b8 <+34>: mov rdi,rax
0x00000000004005bb <+37>: mov eax,0x0
0x00000000004005c0 <+42>: call 0x400480 <gets@plt>
0x00000000004005c5 <+47>: mov eax,0x0
0x00000000004005ca <+52>: mov rdx,QWORD PTR [rbp-0x8]
0x00000000004005ce <+56>: xor rdx,QWORD PTR fs:0x28
0x00000000004005d7 <+65>: je 0x4005de <main+72>
0x00000000004005d9 <+67>: call 0x400460 <__stack_chk_fail@plt>
0x00000000004005de <+72>: leave
0x00000000004005df <+73>: ret
Below is a table of naming and usage conventions for the general purpose registers in the x86-64 architecture. The first row is the number of bits specified by the particular register label.
64 32 16 8
rax eax ax al return value
rbx ebx bx bl callee saved
rcx ecx cx cl 4th argument
rdx edx dx dl 3rd argument
rsi esi si sil 2nd argument
rdi edi di dil 1st argument
rbp ebp bp bpl callee saved
rsp esp sp spl stack pointer
r8 r8d r8w r8b 5th argument
r9 r9d r9w r9b 6th argument
r10 r10d r10w r10b caller saved
r11 r11d r11w r11b caller saved
r12 r12d r12w r12b callee saved
r13 r13d r13w r13b callee saved
r14 r14d r14w r14b callee saved
r15 r15d r15w r15b callee saved
Note: Intstructions that generate 1- or 2-byte values leave the higher order bytes unchanged. Instructions that generate 4-byte values zero out the upper bytes.