# CSC 472 - Class 15: Multi-Stage Exploits (info leak -> GOT overwrite -> shell)
#
# Same 32-bit story as Class 10-12, with the two mitigations that MAKE this a
# multi-stage problem turned ON:
#   -m32                 32-bit x86 (matches the lecture stack diagrams)
#   -fno-stack-protector no canary (canaries are next class, Class 16)
#   -z noexecstack       NON-executable stack (NX/DEP on) -> cannot inject code
#   -no-pie              binary base is FIXED -> PLT, GOT and .bss do NOT move,
#                        even with ASLR on. That fixed GOT is what we overwrite.
# ASLR is a run-time knob, not a compile flag -- it is ON in the real world and
# in the lab container; `make aslr-on` / `make aslr-off` just remind you how to
# toggle it. The whole point of the leak stage is that ASLR is ON.

CC     = gcc
SRC    = src/multi_stage.c
BIN    = multi_stage
CFLAGS = -m32 -g -fno-stack-protector -z noexecstack -no-pie \
         -Wno-deprecated-declarations

all: $(BIN)

$(BIN): $(SRC)
	$(CC) $(CFLAGS) -o $(BIN) $(SRC)
	@echo "[built] $(BIN)  (NX on, no canary, no-PIE: PLT/GOT/.bss are fixed)"

# Confirm NX really is on (GNU_STACK should read RW, not RWE).
checknx: $(BIN)
	@echo "--- Program headers (GNU_STACK should be RW, not RWE) ---"
	@readelf -l $(BIN) | grep -A1 GNU_STACK

# The fixed pieces every stage reuses.
info: $(BIN)
	@echo "--- write@plt / read@plt (fixed PLT stubs) ---"
	@objdump -d -j .plt $(BIN) | grep -E 'write|read' || true
	@echo "--- write@GOT / read@GOT relocations (fixed slots) ---"
	@readelf -r $(BIN) | grep -E 'write|read'
	@echo "--- &scratch (fixed .bss landing pad for \"/bin/sh\") ---"
	@readelf -s $(BIN) | grep -E ' scratch$$'
	@echo "--- a pop;pop;pop;ret gadget to clean 3 stack args ---"
	@ROPgadget --binary $(BIN) 2>/dev/null | grep -E 'pop .* ; pop .* ; pop .* ; ret' | head -3 \
	  || echo "  (install ROPgadget:  pip install ROPgadget)"

# Which libc is mapped, and the write/system offsets the leak math needs.
libc: $(BIN)
	@echo "--- libc the loader will use ---"
	@ldd $(BIN) | grep -i libc || true
	@L=$$(ldd $(BIN) | awk '/libc/{print $$3}'); \
	 echo "--- offsets inside $$L ---"; \
	 readelf -s $$L | grep -E ' write@@| system@@| read@@' || \
	 nm -D $$L | grep -E ' (write|system|read)$$'

aslr-off:
	@echo "Run:  echo 0 | sudo tee /proc/sys/kernel/randomize_va_space"
aslr-on:
	@echo "Run:  echo 2 | sudo tee /proc/sys/kernel/randomize_va_space"

clean:
	rm -f $(BIN)

.PHONY: all checknx info libc aslr-off aslr-on clean
