Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .devcontainer/virtual/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ services:
volumes:
- ../../:/CybICS
- ../../software/attack-machine/workspace:/root/Desktop/workspace
- ../../training/buffer_overflow:/opt/challenges/buffer_overflow
networks:
virt-cybics:
ipv4_address: 172.18.0.100
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,7 @@ software/landing/data/*.json
!software/landing/data/.gitkeep
software/landing/app.py.backup
software/landing/app.py.old

# buffer overflow challenge
training/buffer_overflow/plc_diagnostics
training/buffer_overflow/.gdb_history
8 changes: 8 additions & 0 deletions software/attack-machine/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,14 @@ RUN echo 'welcome' >> /root/.bashrc
# Initialize Metasploit database
RUN msfdb init || true

# Bufferoverflow tools
RUN pip3 install --no-cache-dir --break-system-packages pwntools

RUN apt-get update && apt-get install -y gdb checksec

RUN curl --proto '=https' --tlsv1.2 -LsSf 'https://install.pwndbg.re' | sh -s -- -t pwndbg-gdb


# Expose VNC and noVNC ports
EXPOSE 5902 6081

Expand Down
3 changes: 3 additions & 0 deletions software/landing/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ COPY software/landing/modules/ modules/
# Copy training content from root
COPY training/ training/

# Decompress pre-built flash dump challenge files
RUN gunzip -k /CybICS/training/flash_dump/flash_dump.bin.gz

# Copy attack scripts to /usr/local/bin for easy access
COPY training/flood_overwrite/flooding_hpt.py /usr/local/bin/flooding_hpt.py
RUN chmod +x /usr/local/bin/flooding_hpt.py
Expand Down
24 changes: 24 additions & 0 deletions software/landing/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,30 @@ def challenge_detail(challenge_id):
solved=challenge_id in session['solved_challenges'],
challenge_type=challenge.get('type', 'offensive'))

@app.route('/ctf/download/<challenge_id>')
def challenge_download(challenge_id):
"""Serve a downloadable file for a challenge"""
import os as _os
from flask import send_file as _send_file
print("DOWNLOAD-HEADERS:", dict(request.headers))
challenge, _ = ctf_manager.get_challenge(challenge_id)
if not challenge or 'download' not in challenge:
return "File not found", 404
filename = challenge['download']
file_path = _os.path.abspath(_os.path.join(
_os.path.dirname(__file__), 'training', challenge_id, filename
))
if not _os.path.isfile(file_path):
return f"File '{filename}' not found on server {file_path}", 404
return _send_file(
file_path,
as_attachment=True,
download_name=filename,
conditional=False
)
response = _send_file(file_path, as_attachment=True, download_name=filename)
return response

@app.route('/ctf/verify/<challenge_id>', methods=['POST'])
def verify_defense(challenge_id):
"""Verify a defense challenge and auto-submit flag on success"""
Expand Down
43 changes: 32 additions & 11 deletions software/landing/ctf_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "Industrial Control Systems Security Training Platform",
"categories": {
"basic_understanding": {
"name": "🏭 Basic Understanding",
"name": "\ud83c\udfed Basic Understanding",
"description": "Fundamental understanding of industrial processes and control systems",
"challenges": [
{
Expand All @@ -29,7 +29,7 @@
]
},
"network_analysis": {
"name": "🔍 Network Analysis",
"name": "\ud83d\udd0d Network Analysis",
"description": "Network reconnaissance and traffic analysis techniques",
"challenges": [
{
Expand Down Expand Up @@ -65,7 +65,7 @@
]
},
"security_testing": {
"name": "⚔️ Security Testing",
"name": "\u2694\ufe0f Security Testing",
"description": "Test system resilience and security mechanisms",
"challenges": [
{
Expand Down Expand Up @@ -111,7 +111,7 @@
]
},
"advanced_security": {
"name": "🔐 Advanced Security",
"name": "\ud83d\udd10 Advanced Security",
"description": "Advanced attack and detection techniques",
"challenges": [
{
Expand All @@ -137,11 +137,11 @@
{
"id": "detect_basic",
"title": "Detect Port Scan",
"description": "Perform a port scan and verify the IDS detected it find the flag in the IDS rule stats",
"description": "Perform a port scan and verify the IDS detected it \u2014 find the flag in the IDS rule stats",
"points": 250,
"tag": "analysis",
"flag": "CybICS(sc4n_d3tect3d)",
"hint": "Run a port scan, then query the IDS at /api/rules/stats the flag appears when the port_scan rule has fired",
"hint": "Run a port scan, then query the IDS at /api/rules/stats \u2014 the flag appears when the port_scan rule has fired",
"training_content": "training/detect_basic/README.md"
},
{
Expand All @@ -151,14 +151,35 @@
"points": 400,
"tag": "analysis",
"flag": "CybICS(m0dbus_fl00d_d3tect3d)",
"hint": "Run the override script, then query /api/rules/stats the flag appears when the modbus_flood rule fires",
"hint": "Run the override script, then query /api/rules/stats \u2014 the flag appears when the modbus_flood rule fires",
"training_content": "training/detect_overwrite/README.md"
},
{
"id": "buffer_overflow",
"title": "Stack Smashing the PLC Diagnostics Service",
"description": "A forgotten maintenance binary on the attack machine contains a classic stack buffer overflow. Reverse-engineer it, find the vulnerable function, and redirect execution to capture the flag.",
"points": 350,
"tag": "exploit",
"flag": "CybICS(buff3r_0v3rfl0w_pwn3d)",
"hint": "Compile the binary with make, then use GDB + pwndbg: cyclic to find the offset, nm to find the target function address, and python3 + struct.pack to craft the payload.",
"training_content": "training/buffer_overflow/README.md"
},
{
"id": "flash_dump",
"title": "Flash Dump Analysis",
"description": "A flash memory dump from an industrial controller was obtained via its debug port. The firmware is encrypted — but the device boots without user input. Analyse the dump, reverse-engineer the unlock binary, and decrypt the firmware partition.",
"points": 400,
"tag": "reverse-engineering",
"flag": "CybICS(fl4sh_dump_4nalyz3d)",
"hint": "Start with binwalk to find what's in the dump. Then look for an EXT filesystem — it contains a binary that reveals where the key is stored.",
"training_content": "training/flash_dump/README.md",
"download": "flash_dump.bin"
}
]
},
"ids_challenges": {
"name": "🔍 IDS Challenges",
"description": "Interact with the Intrusion Detection System trigger alerts, analyze incidents, and evade detection",
"name": "\ud83d\udd0d IDS Challenges",
"description": "Interact with the Intrusion Detection System \u2014 trigger alerts, analyze incidents, and evade detection",
"challenges": [
{
"id": "ids_challenge",
Expand Down Expand Up @@ -193,7 +214,7 @@
]
},
"defense": {
"name": "🛡️ Defense & Hardening",
"name": "\ud83d\udee1\ufe0f Defense & Hardening",
"description": "Harden the ICS environment by applying defensive security measures",
"challenges": [
{
Expand Down Expand Up @@ -259,4 +280,4 @@
]
}
}
}
}
10 changes: 10 additions & 0 deletions software/landing/templates/challenge.html
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,16 @@ <h1>{{ challenge.title }}</h1>
<!-- Main content -->
<div class="main-content">
{% if training_content %}
{% if challenge.download %}
<div style="margin-bottom:1.5rem;">
<a href="/ctf/download/{{ challenge.id }}"
target="_top"
download
style="display:inline-block;padding:0.5rem 1.25rem;background:#ff6b00;color:#1a1a1a;font-weight:700;border-radius:0.375rem;text-decoration:none;">
&#11015; Download {{ challenge.download }}
</a>
</div>
{% endif %}
<div class="training-content" id="training-content">
{{ training_content | safe }}
</div>
Expand Down
2 changes: 1 addition & 1 deletion software/landing/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1831,7 +1831,7 @@ <h2>Welcome to CybICS</h2>
title="CTF Training"
allow="fullscreen"
allowfullscreen="true"
sandbox="allow-same-origin allow-scripts allow-popups allow-forms"
sandbox="allow-same-origin allow-scripts allow-popups allow-forms allow-downloads"
></iframe>
</div>

Expand Down
32 changes: 32 additions & 0 deletions training/buffer_overflow/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# CybICS Buffer Overflow Challenge – Build System
#
# Compiler flags chosen deliberately for the challenge:
# -fno-stack-protector disable stack canaries (no SSP cookie)
# -no-pie produce a non-position-independent executable
# so that function addresses are fixed at link time
# -O0 no optimisation – keeps stack frames predictable
# -z execstack mark the stack executable
#
# ASLR must be disabled at runtime (see README).

CC = gcc
CFLAGS = -O0 -fno-stack-protector -no-pie -z execstack -g
TARGET = plc_diagnostics
SRC = plc_diagnostics.c

.PHONY: all clean run

all: $(TARGET)

$(TARGET): $(SRC)
$(CC) $(CFLAGS) -o $(TARGET) $(SRC)
@echo ""
@echo "[+] Binary compiled: ./$(TARGET)"
@echo "[+] Compile flags: $(CFLAGS)"
@echo ""

clean:
rm -f $(TARGET)

run: $(TARGET)
./$(TARGET)
Loading