Patterns#
Recurring forms the operator sees in disassembly and writes by hand.
Function prologue / epilogue#
Most x86-64 callees set up a frame, save callee-saved registers, then restore on the way out.
func:
push rbp
mov rbp, rsp
sub rsp, 32 ; local space (16-byte aligned)
; ... body ...
add rsp, 32
pop rbp
ret
Tail call#
Replace call; ret with jmp when the call is the last thing the
function does; one fewer stack frame, the same effect.
; instead of: call helper / ret
jmp helper
Position-independent code#
Compute addresses relative to rip so the code works wherever it
gets loaded, in shared libraries, ASLR, and shellcode.
lea rdi, [rel msg]
call printf wrt ..plt
NOP sled#
A run of 0x90 (nop) bytes that lets execution slide into a
following payload. Used by exploit writers to widen the landing zone
for an unreliable jump; defenders flag long nop runs.
times 64 nop
; payload:
; ...
Stack canary check#
Compiler emits a load of %fs:0x28 into the frame on entry and
compares it back on exit; mismatch ends in __stack_chk_fail.
mov rax, qword [fs:0x28]
mov qword [rbp-0x8], rax
; ...
mov rcx, qword [rbp-0x8]
xor rcx, qword [fs:0x28]
jne __stack_chk_fail
References#
Compiler Explorer (godbolt), watch C / Rust / Go compile to asm in real time.
Patterns, the C-level forms these come from.