Stack Frames, GDB, and pwntools
The goals of this lab:
- Understand the concepts of the stack and stack frames in compiled C on x86-64.
- Use GDB (with pwndbg) to disassemble and read a binary and watch the stack at runtime.
- Set up and get comfortable with the pwntools exploitation toolkit — our workhorse for the rest of the course.
Course platform: all work is done on the Badger CTF Linux server via SSH.
Experiment Setup
- Log in to Badger CTF: ssh username@badger-host -p port
- Copy the provided source and build it (mitigations off so the assembly is easy to read): cp /workdir/ss2026/lab1/lab1.c . gcc -g -O0 -no-pie lab1.c -o lab1
- Confirm your tools are present:
gdb(with pwndbg),python3, andpwntools(python3 -c "import pwn"), pluschecksec.
Part 1: Read the Assembly with GDB (6 points)
Open the binary and set Intel syntax:
gdb ./lab1 (gdb) set disassembly-flavor intel (gdb) disas main (gdb) disas multiply_by_two
Q1: Identify the instructions that build
main's stack frame (the prologue). (1 pt)Q2: Where are the local variables
x and y initialized, and how are they addressed relative to rbp or rsp? (1 pt)Q3: Before the
call to multiply_by_two, how are the two arguments passed? Which registers, and in what order (System V AMD64 convention)? (1 pt)Q4: Look at how
(p+q)*2 is compiled. Does the compiler use imul, or a lea/add/shift sequence? Explain what you see. (1 pt)Q5: Which register holds the return value, and where is it used back in
main? (1 pt)Q6: Set a breakpoint at the prologue of
multiply_by_two, run, and use info registers and x/16xg $rsp to view the stack frame. Identify the saved return address on the stack and explain how you know it is the return address. Include a screenshot. (1 pt)Part 2: pwntools Warm-up (4 points)
Write a short pwntools script that starts the binary, reads its output, and prints it:
from pwn import *
context.update(arch="amd64", os="linux")
io = process("./lab1")
print(io.recvall(timeout=2).decode())
Q7: Run your script and confirm you see
result = 14. Now use pwntools to load the ELF (elf = ELF("./lab1")) and print the address of multiply_by_two (elf.symbols[...]). Paste your script and its output. (2 pts)Q8: Run
checksec ./lab1 and explain what each protection line (RELRO, Stack Canary, NX, PIE) means and whether it is enabled here. (2 pts)Hint
Review the lecture slides — Class 02: Process Memory, x86-64 Assembly, and the Stack.
Deliverables
A PDF report answering Q1—Q8 with screenshots and your pwntools script.
Submission
- Check the lab due date on the course website. Late submissions will not be accepted.
- Submit your assignment to D2L directly.
- No copy or cheating is tolerated. If your work is based on others' or AI, please give clear attribution. Otherwise, you WILL FAIL this course.