Note: Most of the below information is summarized from Dr. Yan Shoshitaishvili’s pwn.college lectures from the “Assembly Refresher” module. Much credit goes to Yan’s expertise! Please check out the pwn.college resources and challenges in the sources
This module relies heavily on preexisting x86 knowledge, so if you don’t have experience with x86 then I’d recommend starting with Resources and learning some of the basics or the rest of this post won’t make much sense.
Table of Contents
Registers
Registers: very fast, temporary storage for data
- The address of the next instruction is stored in a register (eip)
- General purpose registers (eax, ecx, edx, ebx, esp, ebp, esi, edi)
Partial Register Access:
A full register is 64 bits long, however they can be accessed partially. The below table show the layout of the different registers, followed by an image explaining the layout of the rax register:
- WARNING: Accessing eax will zero out the rest of rax
- all other partial access will preserve untouched parts of the register
Instructions
- Tell the CPU what to do
- Take several different forms, generally include:
- Opcode: what to do
- Operands: what to do it on/with
- Flow right to left (take whats on the right and move it into the left register)
- Control flow is determined by conditional and unconditional jumps
- Unconditional: call, jmp, ret
- Conditional:
- Conditionals key off the “flags” register (eflags)
- eflags register is updated by:
- arithmetic operations
- cmp - subtraction (
cmp rax, rbx
) - test - and (
test rax, rax
)
- eflags register is updated by:
- System calls will stop the process, request the OS to perform a task, and once the task is completed the OS will resume the process
- Triggered by:
- setting rax register to the system call number
- storing arguments in rdi, rsi, etc.
- calling the
syscall
instruction
- Have very well-defined interfaces that very rarely change
- A maintained list of all the system calls (over 300 in Linux) are here
- Triggered by:
Memory(stack)
Fulfils Four Main Issues:
- Track the “callstack” of a program.
- return values are “pushed” to the stack during a call and “popped” during a ret
- Contain local variables of functions
- Provide scratch space (to alleviate register exhaustion)
- Pass function arguments
- always on x86
- only for functions with “many” arguments on other architectures
Resources:
- x86 Register Cheat Sheet
- x86 Assembly Guide
- Tutorial to Write a Program in x86
- Language X to x86 Converter
- Ryan A. Chapman Linux System Call Table
Please share using the links if you enjoyed!