A from-scratch, locally runnable practice repo for the binary-exploitation core of CSE 466 — Computer Systems Security (Arizona State University, taught on pwn.college), part of a csdiy.wiki full-catalog build.
This repository is authorized self-study of a public university course. Every
exercise here targets only code in this repository — intentionally vulnerable
binaries I wrote, built, and run inside my own WSL2 sandbox, with course-standard
mitigations disabled (-fno-stack-protector, -no-pie, -z execstack, …). The
"flags" are hard-coded educational strings like pwn.college{local_..._demo};
none are real pwn.college flags. There is nothing here that targets real,
third-party, or production systems — no malware, no C2, no DoS, no
network attacks, and no detection-evasion for malicious use. The goal is to learn
and document the offensive/defensive techniques that CSE466 teaches, using the
course's own style of self-contained vulnerable targets.
CSE466 (pwn.college) is a challenge-based course: 13 modules / 358 hosted challenges spanning Linux CLI & program misuse, shellcoding, reverse engineering, program exploitation, system exploitation, and a miscellaneous track (sandboxing, memory errors, race conditions). The graded challenges live on the hosted dojo and cannot be mirrored offline.
This repo implements a substantial, genuinely-runnable representative subset: six modules, each a real vulnerable target + a working solver that is verified by actually running it in WSL2 Ubuntu (glibc 2.39, gcc 13.3). No stubs, no fake results — every "flag" below was produced by the exploit actually executing.
| Module (CSE466 topic) | Target I built | Technique | Verified result |
|---|---|---|---|
| 01 Linux CLI / Program Misuse | root:root 0400 flag + setuid-root cat/find |
GTFOBins setuid privesc | student denied direct read; setuid tool reads flag, euid 1004 → 0 |
| 02 Shellcoding | loader.c RWX inject harness |
hand-written null-free execve shellcode |
23 bytes, no null bytes, spawns /bin/sh (uid=0) |
| 03 Reverse Engineering | stripped crackme |
static analysis → invert transform → keygen | recovers key R3v3rs1ng_CSE466 → flag pwn.college{l0cal_cr4ckme} |
| 04 Memory Corruption | overflow, execstack, no-PIE, no-canary |
ret2win + ret2shellcode | offset 72; win() flag printed; injected shellcode spawns shell |
| 05 Return-Oriented Programming | overflow, NX on, static, no-PIE | SROP (sigreturn-oriented) | execve("/bin/sh") via fake signal frame → shell |
| 06 Sandboxing | raw-BPF seccomp jail | execve blocked; orw shellcode | execve shellcode killed by SIGSYS (31); orw reads flag |
Full captured transcripts: results/ (one log per module).
[*] offset=72
[*] pop rax; ret @ 0x42146b syscall @ 0x401324 /bin/sh @ 0x47f010
============================================================
SHELL_UID=0:root
============================================================
[+] SROP execve chain spawned a shell
[1] execve shellcode -> exit status -31 (KILLED by signal 31) # SIGSYS
[2] orw shellcode (58 bytes) -> flag read: True
pwn.college{seccomp_orw_escape_demo}
[+] sandbox verified: execve blocked, orw succeeds
- 01 — Linux CLI / Program Misuse — setuid GTFOBins privilege escalation (dir)
- 02 — Shellcoding — null-free
execveshellcode + injection loader (dir) - 03 — Reverse Engineering — stripped crackme, manual RE + automated keygen (dir)
- 04 — Memory Corruption — ret2win + ret2shellcode (dir)
- 05 — Return-Oriented Programming — SROP
execvechain (dir) - 06 — Sandboxing — seccomp-BPF jail + orw shellcode (dir)
pwn.college is a hosted, graded platform: the 358 challenges run on ASU's dojo infrastructure, deliver per-user flags, and record progress server-side. That graded portion cannot be mirrored offline and is not reproduced here. Likewise the System Exploitation module (custom kernel modules / kernel privilege escalation, module 5) needs the dojo's instrumented kernel VMs and is out of local scope. What this repo provides instead is a faithful, offline reimplementation of the techniques of six representative modules against my own vulnerable targets, each verified by real execution. No hosted challenge is claimed as "solved."
asu-cse466/
├── env/setup.sh # install pwntools venv + toolchain check
├── 01-linux-cli/ # setuid program-misuse privesc (solve.sh)
├── 02-shellcode/ # execve_shellcode.asm, loader.c, solve.py
├── 03-reverse-engineering/ # crackme.c, solve_manual.md, solve.py
├── 04-memory-corruption/ # vuln.c, solve_ret2win.py, solve_ret2shellcode.py
├── 05-rop/ # rop_vuln.c, solve_rop_execve.py (SROP)
├── 06-sandboxing/ # seccomp_jail.c, orw_shellcode.asm, solve.py
├── scripts/run_all.sh # build + run everything, capture results/
├── results/ # real captured transcripts (one log per module)
└── requirements.txt # pwntools>=4.15
Everything runs in WSL2 Ubuntu (Linux binary exploitation; the labs do not
run natively on Windows). setuid/execstack semantics require an ext4 working
directory — module 01 stages itself in /tmp for that reason.
# one-time environment setup (creates an isolated pwntools venv in $HOME)
bash env/setup.sh
# build every target, run every solver, capture results/*.log
PWN_PY=$HOME/.venv-pwn/bin/python sudo -E bash scripts/run_all.sh
# or run a single module, e.g.:
cd 05-rop && bash build.sh && $HOME/.venv-pwn/bin/python solve_rop_execve.pyEach solver asserts the exploit worked and prints a captured shell/flag; the
top-level scripts/run_all.sh tees every run into results/. The results in the
table above are copied verbatim from those logs. Key verifications:
- shellcode is checked to contain zero null bytes before injection, and the
spawned process reports
uid=0via a realidin the child shell; - the overflow offset (72) is derived from the disassembly, not guessed;
- SROP is used precisely because the binary genuinely lacks clean
pop rsi/rdxgadgets (confirmed with ROPgadget) — a real constraint, not a contrivance; - the seccomp jail's default action kills execve shellcode (exit status −31 = SIGSYS), while identical infrastructure permits the orw shellcode.
C, x86-64 assembly (Intel syntax), Python 3 with pwntools (asm/ELF/ROP/
SigreturnFrame/process), GNU binutils (gcc, objdump, strip), ROPgadget,
Linux seccomp-BPF. Runs CPU-only in WSL2 Ubuntu.
- Shellcoding: writing position-independent, null-free syscall shellcode and the mmap-RWX injection primitive that makes "code injection" concrete.
- Reverse engineering: reading a transform straight off the disassembly, anchoring on embedded data, and turning it into an inverting keygen.
- Memory corruption: the return-address overwrite, the movaps stack-alignment
gotcha, and the self-clobbering-shellcode pitfall (fix by lowering
rsp). - ROP / SROP: why NX forces code reuse, and how sigreturn turns one
syscall+ onepop raxinto full register control on a gadget-poor binary. - Sandboxing: classic-BPF seccomp filters, and why a jailed exploit must pivot
from
execveto the open/read/write ("orw") technique.
Based on CSE 466 — Computer Systems Security by Yan Shoshitaishvili & Connor Nelson (Arizona State University), delivered on pwn.college. This repository is an independent educational reimplementation of the course techniques against self-authored vulnerable targets; all course materials and the hosted dojo belong to their original authors. Original code here is released under the MIT License.