IERG 4851 ยท Week 3

In-Class Lab: ret2libc with ASLR and 64-bit ret2libc

Work only in your assigned course account and only on the supplied local programs.

0. Scope, Location, and Submission

This lab is for the course-provided local environment. Do not run these techniques on any system, binary, or service outside this course lab.

Submission and grading: this in-class lab is for practice only. It is not graded and does not count toward your course grade. Submit one concise practice record to Blackboard by the deadline announced in class. The record is used for feedback and pacing.
Evidence and integrity: include your own GDB or terminal screenshots showing the leak, computed libc base, important gadgets, payload layout, and final output. Do not submit text copied directly from AI tools, classmates, or online writeups. The purpose is to learn the debugging process; copied answers without evidence are not useful.
Where to work: log in to the course lab machine with your assigned student account, then work under ~/ierg4851/week3/in-class-lab. If you do not know your lab-machine username or password, ask the TA or instructor during class.
cd ~/ierg4851/week3/in-class-lab
find . -maxdepth 2 -type f | sort
DirectoryGoalDifficulty
ret2libc32-demoRun and explain the two-stage 32-bit ret2libc-with-ASLR exploit.Required
ret2libc32-leak-anotherModify the 32-bit exploit to leak a different libc function.Required
ret2libc64-no-aslrRun and explain 64-bit ret2libc using a libc pop rdi; ret gadget.Recommended
ret2libc64-aslr-challengeComplete a two-stage 64-bit ASLR exploit with a main-binary gadget.Advanced

Practice Record Contents

1. Reproduce 32-bit ret2libc with ASLR

This lab matches the lecture flow: leak a libc address through the GOT/PLT, infer libc base, then call system("/bin/sh") in the same process.

Lecture connection: ASLR moves libc, so hard-coding system() no longer works. The PLT address is stable because the binary is non-PIE. Calling puts(puts@GOT) reveals the real runtime address of puts inside libc.
cd ~/ierg4851/week3/in-class-lab/ret2libc32-demo
make clean all
make checksec
cat /proc/sys/kernel/randomize_va_space
python3 exploit_aslr.py

What to Understand

  1. Stage 1 payload: padding, puts@PLT, main, puts@GOT.
  2. Why returning to main gives the process a second input round without losing the leaked libc base.
  3. How libc_base = leaked_puts - libc.symbols["puts"].
  4. Stage 2 payload: padding, system, exit, "/bin/sh".
Success prints IERG4851_WEEK3_32_ASLR and the output of id.
Submit for this lab: screenshot of ASLR status, checksec output, leaked puts@libc, computed libc base, system and "/bin/sh" addresses, final marker, and a short explanation of both stages.

Thinking Questions

  1. Why does the exploit call puts@PLT instead of directly calling libc puts?
  2. Why is puts@GOT used as the argument to puts?
  3. Why does the exploit return to main after stage 1?

2. Modify the Leak Target

Now modify the exploit so stage 1 leaks a different libc function. The purpose is to prove you understand the formula, not just the script.

cd ~/ierg4851/week3/in-class-lab/ret2libc32-leak-another
make clean all
python3 - <<'PY'
from pwn import ELF
elf = ELF("./vul_aslr")
print("GOT:", elf.got)
print("PLT:", elf.plt)
PY
cp exploit_template.py exploit.py
nano exploit.py

Required Change

Pick a libc function in the GOT other than puts, leak it using puts@PLT, then compute:

libc_base = leaked_function_address - libc.symbols["that_function"]

The second stage should still call system("/bin/sh").

Success prints IERG4851_WEEK3_LEAK_ANOTHER and the output of id.
Submit for this lab: the function you chose, its GOT address, the leaked runtime address, the offset used from libc, computed libc base, final marker, and screenshots showing your modified script and successful run.

Thinking Questions

  1. Why does leaking any known libc function reveal the same libc base?
  2. Which functions appear in the GOT, and why are not all libc functions present there?

3. 64-bit ret2libc without ASLR

This lab connects to the 64-bit calling convention slides. In x86-64 Linux, the first argument goes in %rdi, so the exploit needs a pop rdi; ret gadget.

Lecture connection: unlike 32-bit ret2libc, placing "/bin/sh" after the return address is not enough. You must load the address into %rdi before calling system().
cd ~/ierg4851/week3/in-class-lab/ret2libc64-no-aslr
make clean all
make checksec
./example
python3 exp_ret2libc.py

What to Understand

  1. The script disables ASLR for this process with pwntools so libc base is known during this run.
  2. The script searches libc for pop rdi; ret, because the small main binary may not contain that gadget.
  3. The final chain is padding, pop rdi; ret, "/bin/sh", alignment ret, system, exit.
Success prints IERG4851_WEEK3_64_NO_ASLR and the output of id.
Submit for this lab: the libc base, libc pop rdi; ret address, "/bin/sh" address, system address, final marker, and a short explanation of why %rdi matters.

Thinking Questions

  1. Why does the 64-bit exploit need pop rdi; ret?
  2. Why does the script search libc instead of only the main binary?
  3. Why might an extra ret before system help stack alignment?

4. Advanced Challenge: 64-bit ret2libc with ASLR

This optional challenge gives you a 64-bit binary with a main-binary pop rdi; ret gadget. Complete the two-stage exploit in exploit_template.py.

cd ~/ierg4851/week3/in-class-lab/ret2libc64-aslr-challenge
make clean all
make checksec
python3 exploit_template.py

Design

  1. Stage 1: use the main-binary pop rdi; ret to call puts(puts@GOT), then return to main().
  2. Parse the leaked puts@libc address and compute libc base.
  3. Stage 2: call system("/bin/sh"). You may use the main-binary pop rdi; ret again or a libc gadget after computing libc base.
Submit for this challenge: either a working exploit with the final marker IERG4851_WEEK3_64_ASLR_CHALLENGE, or a clear design explaining the two stages, the gadgets, and why the first-stage gadget cannot come from libc before the leak.

Harder Reading

If a real binary has no direct pop rdi; ret gadget, one common method is ret2csu. This is optional reading:

Thinking Questions

  1. Why can the no-ASLR 64-bit exploit use a libc gadget immediately, but the ASLR version cannot?
  2. What must be stable before the first libc leak?
  3. How does ret2csu help when a binary has no direct pop rdi; ret?