Video summary
버퍼오버플로우pt1 실습 Week9
Main summary
Key takeaways
Main ideas / lessons
-
Why study assembly for security: To understand memory-related vulnerabilities (including buffer misflows), you first need a foundational understanding of:
- Assembly
- How C compiles into assembly
- How function calls execute
-
Goal of the lab: Build a simple C program, compile it to assembly, and then analyze the assembly instruction-by-instruction, focusing on:
- How registers and memory are used
- How the stack changes
- How function prologues/epilogues and calling conventions work
-
Problem with default compiler output: Default GCC assembly is often:
- Hard to read at first
- Heavily optimized (may remove unused code entirely)
- Packed with security-related features enabled by default
-
Strategy for clearer learning:
- Recompile to produce assembly closer to the original C
- Disable security features
- Use Intel syntax for readability
- Use a 32-bit target on a 64-bit system (via
-m32) so addressing and “word” sizes align with course explanations
Methodology / instructions (detailed)
A) Write the C code (basic structure)
Create a workspace folder and write a file (conceptually) like sample.c, implementing:
-
A
main()function that:- Declares an
int c - Calls a function (named
function) with parameters 1 and 2 - Stores the return value in
c
- Declares an
-
A
function(int a, int b)function that:- Has local variables including:
- A 10-byte char buffer (included to illustrate stack/assembly layout)
- Computes:
a + b
- Returns the result
- Has local variables including:
B) Compile to obtain assembly (clearer than binaries)
Normal compilation produces an executable/binary. To generate assembly instead:
- Use GCC to compile and output an assembly file (creating something like
sample.s).
The lecture emphasizes the compiler’s role:
The compiler converts C → assembly, and optimization/linking can obscure what you expect.
C) Recompile with options to make assembly “match C more closely”
Use the following approach for teaching-friendly output:
-
Use 32-bit compilation on a 64-bit machine:
-
Install required multilib support (as mentioned):
aptget install GCC multirip(spoken as an intended multilib toolchain setup) -
Compile with:
-m32to target 32-bit
-
-
Control optimization and readability:
- Use an optimization flag intended to be very low, to prevent rewriting (e.g., transforming arithmetic into cheaper instructions)
-
Disable security-related features and position-independence:
- Turn off stack protection (options beginning with
-fno ...), such as:-fno-stack-protector
- Disable position-independent executable/code loading features (referenced as
-fno-pie-like /-fno-pic-like goals) - Disable async unwind tables (mentioned)
- Turn off stack protection (options beginning with
-
Use Intel assembly syntax:
- Configure/disassemble so output uses Intel style rather than AT&T (the default for some GCC outputs)
- Intel syntax is preferred for readability (fewer confusing prefixes)
D) Analyze the generated assembly by following execution flow
-
Start at
main:- Identify instructions that:
- Set up the stack frame / prepare for the call
- Perform the
callto another function - Handle the return value
- Identify instructions that:
-
Understand key instructions one-by-one:
-
call- Transfers control to the function
- Pushes the return address so execution can resume after the function
-
ret/leave/ epilogue behavior- Restores stack frame state
- Continues execution in the caller after the call
-
mov(and addressing syntax like parentheses/brackets)- Without memory indirection syntax: register-to-register transfer
- With memory indirection: move the value stored at the memory address
-
add/sub- Modify registers or memory depending on the instruction form
- Examples of interpretation:
add reg, imm⇒reg = reg + immsub ...similarly
-
-
Interpret stack operations:
push- Places data onto the stack
- Updates the stack pointer (ESP) to reflect the new top
pop- Removes data from the stack
- Places it into a destination register/location
E) Understand stack growth direction and “stack diagrams”
Remember:
- Data stacks are LIFO
- In typical memory addressing, the stack grows downward:
- Push decreases ESP (top moves to lower addresses)
- Pop increases ESP (top moves to higher addresses)
Track what’s stored where, including:
- Parameters
- Return address
- Saved base/frame pointer (EBP)
- Local variables (like
int cand the 10-bytebuffer)
F) Recognize the function prologue and epilogue pattern
-
Function prologue (typical start):
push ebpmov ebp, esp- Allocate locals with something like:
sub esp, <size>
-
Function epilogue (typical end):
leave(restores EBP/ESP to the previous frame)ret(pops return address and resumes the caller)
G) Calling convention assumptions emphasized
-
Parameter passing order:
- When calling
function(a, b), parameters are pushed onto the stack in reverse order (e.g., pushbthena), following the x86 calling convention described in the lecture.
- When calling
-
Return value location:
- Return values are placed into
EAX - The caller stores
EAXinto its local variable (e.g.,cinmain)
- Return values are placed into
H) Practical self-practice suggestion
Practice by modifying simple functions:
- Change from one parameter to three parameters
- Try expressions like:
1 + 2 + 3a + b + c
- Recompile with the same “teaching-friendly” flags
- Draw memory/stack diagrams step-by-step and compare them against assembly changes
- Suggested tooling:
- Use GDB to watch register/stack changes per instruction (but first understand instruction meaning conceptually)
Speaker / sources featured
- No explicit individual name is given in the subtitles.
- Primary source: the course instructor/lecturer speaking throughout the transcript.
- Tools mentioned (sources/inputs, not speakers):
- GCC
- GDB
- A Linux/Mac development environment