Skip to content

Lab 01 — Analysis Lab Setup & Safety

Hands-on lab · ← Back to the module concept

Setup

git clone https://github.com/plaintext-security/plaintext-labs
cd plaintext-labs/malware/01-analysis-lab-setup
make up && make demo

Isolation rule: Every lab in this track runs inside an isolated Docker network. Never copy a sample to your host and double-click it. Never disable network isolation "just to check something." Treat every file as live until proven inert.

Scenario

Your incident response team has extracted a suspicious binary from an analyst workstation. Before detonating or deeply examining any sample, the team lead asks you to build and validate the isolated analysis environment that the rest of the investigation will run in. This is not optional groundwork — it is the first deliverable.

Do

  1. [ ] Bring up the environment. Run make up. Confirm both containers start: the lab analysis container and the sink network simulator. (docker compose ps should show both healthy.)

  2. [ ] Validate network isolation. Shell into the analysis container (make shell) and attempt to reach the real internet:

    curl --max-time 5 https://example.com
    
    It must time out. If it succeeds, the isolation is broken — check the compose network config and fix it before continuing.

  3. [ ] Confirm the fake network sink is reachable. From inside the analysis container, make an HTTP request to the sink's IP (check docker compose ps for the sink container's address within the internal network, or use the hostname sink):

    curl http://sink:8080/
    
    You should see a response and a log line appear in the sink's output (docker compose logs sink).

  4. [ ] Simulate a DNS lookup. From the analysis container, run:

    python3 -c "import socket; print(socket.gethostbyname('evil-c2.example.com'))"
    
    The result should be the sink's IP (or fail gracefully), not an NXDOMAIN from a real resolver. Document what you observe.

  5. [ ] Test the reset workflow. Run make reset and then make up again. Confirm both containers restart cleanly from a fresh state.

  6. [ ] Capture the isolation proof. Take a screenshot or copy the terminal output showing: (a) the failed internet request, (b) the successful sink response, and (c) make reset completing cleanly. This is your deliverable.

Success criteria — you're done when

  • [ ] The analysis container cannot reach the public internet (curl times out).
  • [ ] The analysis container can reach the local sink container by hostname.
  • [ ] The sink logs show the request you made from the analysis container.
  • [ ] make reset && make up produces a clean environment in under two minutes.

Deliverables

lab-setup.md — a short document (a few paragraphs) covering: the architecture of your environment (a simple diagram in ASCII is fine), the commands you used to verify isolation, the output you observed at each check, and any deviation from what was expected. Commit it.

Automate & own it

Required. Write a verify-isolation.sh script (inside the lab environment) that runs all three checks — internet access (must fail), sink reachability (must succeed), sink log confirmation — and exits 0 only if isolation is confirmed, non-zero otherwise. AI can draft the script; you review every line and confirm it actually catches a misconfiguration (test it by temporarily removing the internal: true setting and re-running). Commit verify-isolation.sh.

AI acceleration

Have an AI generate the Docker Compose network config and the sink Python service. Then deliberately break the isolation (comment out internal: true) and rerun your verification script — confirm it catches the failure. An AI-drafted script that doesn't catch the failure is worse than no script.

Connects forward

Every subsequent lab in this track runs inside this same environment. Module 06 extends the sink into a full HTTP/DNS responder. Module 05 relies on the strace/ltrace tooling installed in the analysis container here.

Marketable proof

"I build and validate isolated malware analysis environments — I can prove containment before touching a sample, not assume it."

Stretch

  • Add a third container running a minimal SMTP responder (Python smtpd module) and confirm that a test email sent from the analysis container is captured in the sink log.
  • Configure the sink to log every connection with timestamp, source IP, destination port, and first 256 bytes of payload to a structured JSON log file mounted on the host. This is the beginning of a real capture pipeline.

Comments

Sign in with GitHub to comment. Choose the type: Feedback (errors or suggestions on this page) · Hints (help for fellow learners — no spoilers) · General (anything else).