x86-64 Assembly
To exploit binaries and do reversing you need to read (and sometimes write) assembly: it’s the language code compiles to and the level you work at when manipulating execution. You don’t need to master it like a systems developer, but you do need to understand registers, basic instructions, how the stack works, and calling conventions. This card is the practical base for pwn-reversing.
Registers (x86-64)
Section titled “Registers (x86-64)”# general purpose (64-bit; the 32/16/8-bit versions are sub-registers)RAX RBX RCX RDX RSI RDI RBP RSP R8-R15# size equivalences (RAX)RAX (64) -> EAX (32) -> AX (16) -> AL (8)# specialRIP instruction pointer (what runs) <- the exploit's goalRSP stack pointer (top of the stack)RBP base pointer (function frame)RFLAGS flags (result of comparisons: ZF, CF, SF...)Essential instructions
Section titled “Essential instructions”mov dst, src copy lea dst, [addr] load addressadd/sub dst, src arithmetic xor/and/or logicalpush/pop push/pop the stackcall func call (push RIP + jump) ret return (pop RIP)cmp a, b compare (sets flags)jmp addr unconditional jumpje/jne/jg/jl... conditional jumps (by flags)nop do nothing (0x90) -> useful in shellcode (NOP sled)syscall system call (kernel)The stack and function frames
Section titled “The stack and function frames”# the stack grows toward LOWER ADDRESSES# when calling a function:call func -> push the return address, jump to func# typical prologue:push rbp ; save the previous RBPmov rbp, rsp ; new framesub rsp, N ; reserve space for locals# epilogue:leave ; mov rsp, rbp ; pop rbpret ; pop rip (returns to the saved return address)ret pops the address to return to off the top of the stack and puts it in RIP. If you control what’s at that stack position, you control RIP (basis of stack overflow, see Stack Buffer Overflow).
Calling convention (System V, Linux x86-64)
Section titled “Calling convention (System V, Linux x86-64)”Key for exploits: knowing which registers hold arguments.
# the first 6 arguments go in registers, in this order:RDI, RSI, RDX, RCX, R8, R9# the return value goes in RAX# example: system("/bin/sh") -> RDI = pointer to "/bin/sh", then call system# additional arguments (7+) go on the stackThis is why in ROP (Return-Oriented Programming (ROP)) you look for pop rdi; ret gadgets — to put the argument in RDI before calling a function.
Intel vs AT&T syntax
Section titled “Intel vs AT&T syntax”# Intel (used by most pwn tools, more readable)mov rax, rbx ; destination, source# AT&T (gdb default, GCC)mov %rbx, %rax ; source, destination (reversed order, % and $)# in gdb: set disassembly-flavor intelReading assembly in practice
Section titled “Reading assembly in practice”objdump -d -M intel ./binary # disassemblegdb -> disassemble main # in the debugger (pwndbg/GEF)# in reversing: ghidra/IDA give pseudo-C + assembly side by side (see rev-static)For the defense
Section titled “For the defense”Understanding assembly isn’t a defense in itself, but it’s the basis for: analyzing malware (see malware), auditing your own binaries, understanding exactly what an exploit does, and writing precise detections. On the development side, compilers with mitigations (canaries, CFI) insert checks at the assembly level worth knowing.
Mastery checklist
Section titled “Mastery checklist”- I recognize the registers and their sizes (RAX/EAX/AX/AL)
- I understand RIP/RSP/RBP and their role
- I read the basic instructions (mov, call, ret, jmp, cmp…)
- I can explain the prologue/epilogue and how ret controls RIP
- I know the calling convention (RDI, RSI, RDX…)
- I distinguish Intel from AT&T syntax
- I disassemble with objdump/gdb/ghidra
- I understand how syscall makes kernel calls