ICS-OT-PLC CTF Challenge Write-Up: Solving the CISS2025 Stage-1 “Pass the Door of Durin”

English 简体中文 繁体中文 ภาษาไทย Tiếng Việt
Summary

The "Pass the Door of Durin" challenge from CISS2025 Stage 1 presented an IT-OT hybrid CTF centered on a Siemens S7-1200 PLC simulator and an accompanying web interface. Solving it demanded a combination of traditional cybersecurity skills, such as web exploitation and scripting, with operational technology techniques like S7Comm protocol analysis and direct PLC memory manipulation. Key tasks involved reconstructing images to derive credentials, identifying the S7Comm protocol, and dynamically writing integer values to PLC memory to bypass a timed lock. Subsequent puzzles required extracting memory addresses from a matrix, transmitting Morse code through Boolean memory writes, and decoding hidden audio messages after setting a float frequency in the PLC. This integrated approach highlighted the necessity of bridging IT and OT security expertise to tackle complex industrial control system vulnerabilities.

งาน Critical Infrastructure Security Showdown (CISS) เป็นงานชั้นนำประจำปีและเป็นงานไซเบอร์เพียงหนึ่งเดียวที่จัดขึ้น โดยเป็นการแข่งขัน CTF ด้านเทคโนโลยีปฏิบัติการ (OT) โดยเฉพาะ ซึ่งจัดขึ้นที่ Singapore University of Technology and Design (SUTD) และจัดโดย iTrust research center CISS เป็นโอกาสอันดีที่นำผู้เชี่ยวชาญ CTF ทั่วโลกมาร่วมกันแก้ไขปัญหาความท้าทายด้านความปลอดภัยทางไซเบอร์ OT ที่สมจริง ในปีนี้ CISS 2025 ประกอบด้วยสองช่วง:

  • ช่วงที่ 1 – รอบคัดเลือก: การแข่งขัน CTF ออนไลน์ 48 ชั่วโมง (สิ้นสุดวันที่ 31 กรกฎาคม)

  • ช่วงที่ 2 – รอบชิงชนะเลิศ: การฝึกปฏิบัติจริง 4 ชั่วโมงบน testbeds จริงที่ SUTD-iTrust

CISS-2025-ช่วงที่ 1 สิ้นสุดลงเมื่อเดือนที่แล้ว โดยมี 61 ทีม Red Team นานาชาติ เข้าร่วม และ 10 ทีมแรก จะได้เข้าสู่รอบชิงชนะเลิศ สำหรับรายละเอียดเพิ่มเติม โปรดเยี่ยมชม เว็บไซต์ CISS 2025

ในบทความนี้ ฉันจะพาคุณไปดูความท้าทายแบบผสมผสาน IT-OT ที่ฉันส่งเข้าร่วมใน CISS2025 ช่วงที่ 1: “Pass the Door of Durin” นี่เป็นความท้าทายแรกของการแข่งขัน ออกแบบมาเพื่อเป็นจุดเริ่มต้นสำหรับผู้เข้าร่วม โดยมีเครื่องจำลอง Siemens S7-1200 PLC ที่รัน บริการ S7Comm ซึ่งอนุญาตให้แก้ไขบล็อกข้อมูลหน่วยความจำโดยใช้โปรโตคอล Siemens S7 OT และอินเทอร์เฟซเว็บที่แสดงสถานะหน่วยความจำ PLC พร้อมทั้งฝังปริศนาที่เน้น IT แบบเบาๆ หลายอย่าง

# Author:      Yuancheng Liu
# Created:     2025/06/28
# Version:     v_0.3.1
# Copyright:   Copyright (c) National Cybersecurity R&D Laboratory (NCL)
# License:     MIT License

แนะนำความท้าทาย: Pass the Door of Durin

ในแต่ละปี CISS CTF จะมีเนื้อเรื่องที่สร้างสรรค์เพื่อเป็นแรงบันดาลใจในการออกแบบความท้าทาย ฉบับปี 2025 ใช้ธีม “The Return to Control” ซึ่งได้รับแรงบันดาลใจจาก The Lord of the Rings: The Return of the King (ดูโปสเตอร์ CISS2024 ด้านล่าง)

ความท้าทาย “Pass the Door of Durin” ทำหน้าที่เป็น ประตูบานแรก ที่ทุกทีม Red Team ควรจะเอาชนะได้เมื่อเริ่มต้น CTF โดยได้รับแรงบันดาลใจจากการเดินทางที่อันตรายของ Frodo และ Sam ไปยัง Mount Doom เพื่อทำลายแหวน ความท้าทายนี้เป็นการปูทางให้ผู้เข้าร่วมเริ่มต้นการผจญภัยของตนเอง ปลดล็อกความรู้ที่ซ่อนอยู่ และเข้าสู่โลกแห่งปริศนาความปลอดภัยทางไซเบอร์ IT-OT

หัวใจสำคัญของความท้าทายนี้คือการมอบสภาพแวดล้อมที่ลงมือปฏิบัติจริง โดยจำลอง Siemens S7-1200 PLC สำหรับแต่ละทีม red team ผู้เข้าร่วมจะต้อง:

  • ค้นหา IP และพอร์ตที่เข้าถึงได้ของ PLC

  • วิเคราะห์บล็อกข้อมูลหน่วยความจำ S7Comm และอนุมานตรรกะที่ PLC ดำเนินการ

  • แทรกประเภทข้อมูลที่ถูกต้อง (int, bool, float) ลงในที่อยู่บล็อกหน่วยความจำที่ถูกต้อง

  • ควบคุม PLC เพื่อทำภารกิจที่กำหนดให้สำเร็จและเปิดเผย flags

ความท้าทายนี้มีโครงสร้างเป็น สี่ภารกิจหลัก โดยแต่ละภารกิจประกอบด้วยคำถามที่เน้น IT และคำถามที่เน้น OT อย่างละคู่ รวมเป็นปริศนาแบบผสมผสาน IT-OT หกข้อ การออกแบบนี้ทำให้มั่นใจได้ว่าผู้เข้าร่วมจะต้องรวมทักษะ CTF แบบคลาสสิก (การหาประโยชน์จากเว็บ การสแกน การเขียนสคริปต์) เข้ากับเทคนิคเฉพาะ OT (การจัดการโปรโตคอล S7Comm การจัดการบล็อกหน่วยความจำ)

การออกแบบสภาพแวดล้อมโดยรวมแสดงไว้ด้านล่าง:

ในการแก้ปัญหาความท้าทายนี้ ทีม Red Team จะต้อง SSH เข้าสู่ gateway และ jumphost ที่กำหนดให้ จากนั้นเข้าถึง Kali Linux Transaction VM เฉพาะของตน (เครื่องโจมตี) จากนั้นพวกเขาจะต้อง:

  • ระบุที่อยู่ IP ของ PLC และบริการที่มี

  • ส่งต่อ อินเทอร์เฟซเว็บสำหรับงานท้าทายและการตรวจสอบ ไปยังเครื่องภายในของตน

  • พัฒนาสคริปต์โจมตีแบบกำหนดเองหรือติดตั้งเครื่องมือ (โดยมีสิทธิ์ sudo เต็มรูปแบบ) บน Kali VM

  • สื่อสารกับทั้ง เซิร์ฟเวอร์จัดการข้อมูล S7Comm ของ PLC (พอร์ต 102) และ เว็บเซิร์ฟเวอร์ที่ใช้ Flask (พอร์ต 5001) เพื่อจัดการหน่วยความจำ PLC และตรวจสอบผลลัพธ์

การจำลอง PLC พื้นฐานนั้นอิงตามส่วนหนึ่งของโครงการโอเพนซอร์สของฉัน Py_PLC_Honey_Pot (ดังแสดงด้านล่าง) ซึ่งจำลองตรรกะ Siemens S7 และมอบแพลตฟอร์มที่ยืดหยุ่นสำหรับการฝึกความปลอดภัยทางไซเบอร์ IT-OT

ลิงก์แนะนำ Honeypot: https://www.linkedin.com/pulse/python-plc-honeypot-project-yuancheng-liu-vks8c

เรื่องราวเบื้องหลังความท้าทาย

เรื่องราวเบื้องหลังความท้าทายแสดงไว้ด้านล่าง:

Frodo และ Sam กำลังเดินทางไปยัง Mount Doom เพื่อทำลายแหวน เวลามีน้อย พวกเขาไม่มีเวลาพอที่จะเดินผ่านภูเขา Gundabad Sam มีแผนที่ Dunland ที่ขาดวิ่นพร้อมชิ้นส่วนหลายชิ้น ซึ่งแสดงทางลัดเพื่อข้ามภูเขาผ่านอุโมงค์ใต้ดิน ก่อนที่พวกเขาจะเข้าไปในอุโมงค์ พวกเขาต้องค้นหาและผ่าน "Door of Durin" พวกเขาไม่มีกุญแจ แต่มีวิธีที่จะปลดล็อกประตู

ก่อนที่พวกเขาจะเข้าไปในอุโมงค์ Frodo ต้องส่งข้อความถึง Aragorn เพื่อดึงดูดความสนใจของ Fiery Eye เพื่อช่วยพวกเขา

ภาพรวมคำถามท้าทาย CTF

ความท้าทาย Pass the Door of Durin แบ่งออกเป็น สี่ภารกิจหลัก โดยมี คำถาม CTF หกข้อ แต่ละคำถามมีคะแนน (1–10) ตามระดับความยาก และบางคำถามมีคำแนะนำเพิ่มเติม การใช้คำแนะนำจะลดคะแนนที่มีอยู่ลง 60% สำหรับคำถามนั้น คำถามทั้งหมดถูกปรับใช้บน แพลตฟอร์ม CTF-D โดยมีการกำหนดจำนวนครั้งที่พยายามสูงสุด ดังสรุปไว้ด้านล่าง

รายละเอียดคำถามแสดงไว้ด้านล่าง:

คำถาม คำอธิบาย คะแนน จำนวนครั้งที่พยายามสูงสุด คำแนะนำ
Q1: Find the Way Frodo และ Sam ต้องกำหนดเส้นทางที่ถูกต้องไปยัง Door of Durin เมื่อเปิดเผยแล้ว flag จะปรากฏขึ้น 3 5 ลองรวมชิ้นส่วนแผนที่ทั้งสองชิ้นเข้าด้วยกัน
Q2: Identify the Protocol ประตูถูกควบคุมโดย PLC ระบุโปรโตคอลการสื่อสารที่ใช้ 1 3 มองหาเบาะแสในซอร์สโค้ดหน้าเว็บ
Q3: Crack the Door Lock Frodo ไม่มีกุญแจ ช่วยเขาข้ามผ่านตัวล็อก การปลดล็อกประตูจะเปิดเผย flag 6 5 ลองแทรกค่าจำนวนเต็ม ตรวจสอบที่อยู่หน่วยความจำผ่าน web UI
Q4: Locate the PLC Memory Block Sam ต้องระบุที่อยู่หน่วยความจำ PLC ที่ถูกต้องเพื่อส่งข้อความ 2 3 ไม่มี
Q5: Send the Message ช่วย Frodo ส่งข้อความถึง Aragorn การส่งข้อความที่ถูกต้องจะเปิดเผย flag 5 5 ลองตั้งค่า Boolean ในหน่วยความจำ
Q6: Decode the Response Aragorn ตอบกลับด้วยสัญญาณที่ซ่อนอยู่ ปรับความถี่วิทยุและถอดรหัสการตอบกลับเพื่อดึง flag 3 3 ลองตั้งค่า float ในหน่วยความจำ

 


ขั้นตอนในการแก้ปัญหาความท้าทาย

ผู้เข้าร่วมแต่ละคนจะได้รับ Kali-Linux Transaction VM พร้อมสิทธิ์ sudo ซึ่งอนุญาตให้พวกเขาเรียกใช้เครื่องมือ red teaming ต่างๆ หรือสร้างสคริปต์โจมตี เข้าสู่ระบบ Transaction VM จากนั้นทำตามขั้นตอนด้านล่างเพื่อทำภารกิจให้สำเร็จทีละรายการ

ขั้นตอนที่ 1: เข้าถึง PLC Web Interface

เริ่มต้นด้วยการสแกน PLC VM เพื่อระบุพอร์ตที่เปิดที่ใช้โดยโปรโตคอล OT และบริการ HTTP (พอร์ต 5002) โดยใช้คำสั่ง nmap ดังแสดงด้านล่าง:

nmap -sS -Pn -T5 -p- 172.23.155.209

ผลการสแกนพอร์ต Nmap:

จากการสแกน คุณจะพบว่าพอร์ต 5002 (บริการ HTTP) และ 102 (iso-tsapl) เปิดอยู่

เนื่องจาก Transaction VM รัน Ubuntu Server (โดยไม่มีสภาพแวดล้อมเดสก์ท็อป) คุณจะต้องส่งต่อพอร์ต web interface ของ PLC ไปยังเครื่องภายในของคุณ ใช้คำสั่ง ssh ต่อไปนี้:

ssh -L 127.0.0.1:5000:172.23.155.209:5002 -J @ @172.23.144.1

เมื่อสร้าง tunnel แล้ว ให้เปิด URL http://127.0.0.1:5000 ในเบราว์เซอร์ภายในของคุณเพื่อเข้าถึง PLC web interface คุณจะถูกนำไปยังหน้าเรื่องราวและการแนะนำความท้าทายดังแสดงด้านล่าง:

หลังจากตรวจสอบเรื่องราวเบื้องหลังแล้ว ให้ดำเนินการท้าทายต่อโดยเข้าถึงหน้า web index http://127.0.0.1:5000/Index ดังแสดงด้านล่างเพื่อรับรายการแนะนำ 4 ภารกิจ:

หน้านี้จะนำคุณไปยัง คำถามที่ 1 ซึ่งภารกิจที่แท้จริงเริ่มต้นขึ้น


ขั้นตอนที่ 2: แก้ปัญหา IT-Question 1 – สร้างแผนที่ใหม่

  • ปริศนา IT: รวมเมทริกซ์พิกเซลของรูปภาพเพื่อรับข้อมูลรับรองการเข้าสู่ระบบเว็บ PLC

คำถามที่ 1 เป็นส่วนหนึ่งของภารกิจที่ 1 ซึ่งท้าทายให้ผู้เข้าร่วมช่วย Sam และ Frodo สร้างเส้นทางใหม่ ตามคำอธิบายภารกิจ:

Sam และ Frodo ได้รับชิ้นส่วนแผนที่สองชิ้นจาก Gollum พยายามกู้คืนแผนที่เพื่อหารูปเส้นทางและทิศทางเพื่อเริ่มต้นการเดินทาง

ในการแก้ปัญหาความท้าทายนี้ ผู้เข้าร่วมจะต้องดาวน์โหลดและรวมรูปภาพชิ้นส่วนแผนที่สองรูป ซึ่งมีป้ายกำกับว่า "Sam’s map fragment" และ "Frodo’s map fragment" ดังแสดงด้านล่าง:

อย่างไรก็ตาม การคลิกขวาที่รูปภาพเพื่อบันทึกจะไม่ทำงานเนื่องจากเมนูบริบทของเบราว์เซอร์ถูกปิดใช้งาน (ตรวจสอบซอร์สโค้ดหน้าเว็บ):

ในการแก้ไขปัญหานี้ คุณสามารถ:

  • ลบส่วนที่ไฮไลต์ onContextMenu="return false;" ออกจากแท็ก โดยใช้เครื่องมือสำหรับนักพัฒนาของเบราว์เซอร์ของคุณ ซึ่งจะเปิดใช้งานเมนูบริบทคลิกขวาอีกครั้งเพื่อให้คุณสามารถบันทึกรูปภาพได้ตามปกติ

อีกทางเลือกหนึ่ง คุณสามารถเปิด URL ของรูปภาพในแท็บเบราว์เซอร์ใหม่เพื่อเข้าถึงได้โดยตรง:

เมื่อดาวน์โหลดรูปภาพทั้งสองแล้ว คำแนะนำระบุว่าเราต้อง “รวม” รูปภาพเพื่อเปิดเผยแผนที่ที่ซ่อนอยู่ เพื่อให้บรรลุเป้าหมายนี้ เราสามารถเขียนโปรแกรม Python ที่อ่านค่าพิกเซล (R, G, B) ของรูปภาพทั้งสองลงในเมทริกซ์ จากนั้นทดลองใช้วิธีการต่างๆ ในการรวมเข้าด้วยกัน ดังแสดงด้านล่าง:

ผลลัพธ์ (R3, G3, B3) = ((R1+?R2), (G2+?G2), (B3+?B3)
  • เพิ่มค่าพิกเซลของเมทริกซ์ทั้งสองเพื่อสร้างรูปภาพใหม่

  • หมุนเมทริกซ์รูปภาพที่สอง 90° / 180° / 270° จากนั้นรวมค่าพิกเซล

  • กลับเมทริกซ์รูปภาพที่สองก่อนที่จะรวม

  • ทำสำเนาเมทริกซ์รูปภาพที่สองก่อนที่จะรวม

หากค่าพิกเซลที่ได้เกิน 255 ในช่อง RGB ใดๆ วิธีการนั้นจะไม่ถูกต้อง วิธีแก้ปัญหาที่ถูกต้องคือการทำสำเนาจากบนลงล่างของรูปภาพที่สอง จากนั้นวางเมทริกซ์ลงบนรูปภาพแรกเพื่อสร้างแผนที่ฉบับเต็มใหม่ โค้ดรวมเมทริกซ์ RGB พิกเซล Python อย่างง่ายแสดงไว้ด้านล่าง:

image_path1 = "img1.jpg"
img1 = Image.open(image_path1)
width1, height1 = img1.size
pixel_data1 = list(img1.getdata())  # Get pixel values
pixel_2d_lis1 = [pixel_data1[i * width1:(i + 1) * width1] for i in range(height1)]
# Read picture 2 in a matrix and do top-down mirroring
image_path2 = "img2.jpg"
img2 = Image.open(image_path2)
width2, height2 = img2.size
pixel_data2 = list(img2.getdata())  # Get pixel values
pixel_2d_list2 = [pixel_data2[i * width2:(i + 1) * width2] for i in range(height2)]
topdownMirror = pixel_2d_list2[::-1]
# combine the pixels to the new image
img3List = []
for i, item in enumerate(pixel_2d_lis1):
    newItem = []
    for j, pixel in enumerate(item):
        img2Pixel = topdownMirror[i][j]
        img3R = pixel[0] + img2Pixel[0]
        img3G = pixel[1] + img2Pixel[1]
        img3B = pixel[2] + img2Pixel[2]
        newItem.append((img3R, img3G, img3B))
    img3List.append(newItem)
​
img3Data = np.array(img3List, dtype=np.uint8)
img3 = Image.fromarray(img3Data, 'RGB')
img3.save("result.jpg")
 

อีกทางเลือกหนึ่ง ใช้สคริปต์ที่ให้มา: pictureCombine.py เพื่อลองใช้ฟังก์ชันรวมพิกเซลทั้งหมดเพื่อให้ได้ฟังก์ชันที่ถูกต้อง ซึ่งจะสร้างผลลัพธ์ที่รวมกันโดยอัตโนมัติ ดังแสดงด้านล่าง:

จากรูปภาพที่ผสานรวม ผู้เข้าร่วมสามารถดึงข้อมูล:

  • Route String: FollowSilvertineDarkCliffsUnderstartLight

  • Direction String: WestSideNeArTw0AncientH011yTrEes

กรอกข้อมูลในช่อง Route และ Direction แล้วกดปุ่ม Go to the "Door of Durin" เพื่อส่งคำตอบ:

หากเส้นทางและทิศทางถูกต้อง flag คำถามที่ 1 จะแสดงที่ด้านล่างของหน้า:

Question 1 Flag: CISS_2025_@T_THE_FR0NT_0F_Th3_Ho11in_G@t3


ขั้นตอนที่ 3: แก้ปัญหา OT-Question 2 – ระบุโปรโตคอล PLC OT

  • ปริศนา OT: ระบุและยืนยันโปรโตคอล OT การสื่อสาร PLC

จากการสแกนพอร์ต Nmap ก่อนหน้านี้ เราพบว่าพอร์ต 102 เปิดอยู่:

พอร์ตนี้เกี่ยวข้องกับโปรโตคอล ISO-TSAP อย่างไรก็ตาม "iso-tsap" ไม่ใช่ flag ที่ถูกต้อง ในการระบุโปรโตคอล OT ที่แท้จริงที่ PLC ใช้ ให้ลองค้นหาคำค้นหาต่อไปนี้ใน Google:

“port 102 operational technology protocol TSAP type used by PLC”

ซึ่งจะนำไปสู่ผลลัพธ์ทั่วไปสองรายการ:

  • Siemens S7 และ S7 Plus

  • The Inter-Control Center Communication Protocol (ICCP)

กลับไปที่หน้าเรื่องราวหลังจากคลิกปุ่ม “Start the Journey” ตรวจสอบซอร์สโค้ดหน้าเว็บเพื่อค้นหารูปภาพที่ซ่อนอยู่ชื่อ protocol.png (รูปภาพกว้าง 1 พิกเซล):

ในการเปิดเผยรูปภาพฉบับเต็ม ให้ลบหรือแก้ไขสไตล์ของรูปภาพโดยใช้เครื่องมือสำหรับนักพัฒนาของเบราว์เซอร์ จากนั้นรูปภาพที่เปิดเผยจะยืนยันว่า PLC กำลังใช้โปรโตคอล S7Comm ดังแสดงด้านล่าง:

คุณสามารถตรวจสอบโปรโตคอลได้โดยการรัน

ไคลเอนต์ S7Comm สคริปต์ดังที่แสดงในตัวอย่างนี้

https://github.com/LiuYuancheng/PLC_and_RTU_Simulator/blob/main/S7Comm_RTU_Simulator/testcase/rtuClientTest.py

ติดตั้งไลบรารี python snap7 https://pypi.org/project/python-snap7/ และใช้ไลบรารีจัดการโปรโตคอลการสื่อสาร S7Comm: https://github.com/LiuYuancheng/PLC_and_RTU_Simulator/blob/main/S7Comm_RTU_Simulator/src/snap7Comm.py เพื่อสร้างการเชื่อมต่อ PLC และสคริปต์อ่านและเขียนบล็อกหน่วยความจำของคุณดังที่แสดงด้านล่าง:

PLC_IP= '172.23.155.209'
client = snap7Comm.s7CommClient(PLC_IP, rtuPort=102, snapLibPath=libpath)
connection = client.checkConn()
print("S7Comm client connection: %s" % str(connection))
 

หลังจากรันสคริปต์ ข้อความการเชื่อมต่อสำเร็จจะถูกพิมพ์เพื่อยืนยันว่ามีการสร้างการเชื่อมต่อแล้ว:

คำถามที่ 2 Flag : S7COMM


ขั้นตอนที่ 4: แก้ปัญหา OT-คำถามที่ 3 – ไขปริศนาล็อค

  • ปริศนา OT: ค้นหาตรรกะภายในของ PLC และกรอกค่า int ลงในบล็อกแอดเดรสหน่วยความจำที่ถูกต้องภายในเวลาที่กำหนด

คำถามที่ 3 เป็นส่วนหนึ่งของ Task 2 หลังจากทำ Task 1 เสร็จสิ้น แท็บ Task 2 จะปรากฏขึ้นโดยอัตโนมัติในแถบนำทาง:

ไปที่ความท้าทาย “Crack the Lock” ภายใต้ Task 2 ผู้เข้าร่วมจะเห็นเรื่องราวความท้าทายต่อไปนี้:

Frodo พบว่าล็อคถูกควบคุมโดย PLC เขาสามารถใช้พินของเขา (โปรแกรมไคลเอนต์การสื่อสาร PLC) เพื่อตั้งค่าบางอย่างในหน่วยความจำ PLC เพื่อดันพินล็อคไปยังตำแหน่งที่ถูกต้อง

หน้างานแสดงดังต่อไปนี้:

ผู้เข้าร่วมต้องโต้ตอบกับ PLC เพื่อตั้งค่าคีย์คัททั้งหมดเพื่อดันตัวล็อคพินไปยังตำแหน่งที่ถูกต้อง จำลองการปลดล็อคของล็อคแบบกลไก องค์ประกอบความท้าทายที่สำคัญ ได้แก่:

  • กลไกการล็อคประกอบด้วยความท้าทายตัวล็อคพิน 12 ตัว (แต่ละแถวมีสี่เหลี่ยมสีเขียว น้ำเงิน เหลือง เทา)

  • สี่เหลี่ยมสีฟ้าอ่อนต้องอยู่ในแนวเดียวกับ แนวเฉือน ของรูกุญแจที่ตำแหน่ง ดัชนีคอลัมน์ = 12

  • คีย์คัทถูกควบคุมโดยการตั้งค่าในแอดเดรสหน่วยความจำ PLC ที่ระบุ ซึ่งแสดงในคอลัมน์ "add" (แอดเดรส): ['1[0]', '1[2]', '1[4]', '1[6]', '2[0]', '2[2]', '2[4]', '2[6]', '3[0]', '3[2]', '3[4]', '3[6]'] โดยมีรูปแบบ [] .

  • ความยาวของตัวล็อคพิน (ตัวล็อคพินด้านล่างเป็นสีเขียว) จะอัปเดตทุกๆ 60 วินาที และตัวจับเวลาถอยหลังจะแสดงบนหน้างาน

  • เมื่อตัวจับเวลารีเซ็ต ค่าที่ตั้งไว้ก่อนหน้านี้ทั้งหมดจะถูกล้าง รวมถึงค่าคีย์คัทด้วย ผู้เข้าร่วมต้องแก้ปัญหาความท้าทายภายใน 60 วินาทีหลังจากสร้างตัวล็อคใหม่

การแมปส่วนประกอบโดยละเอียดแสดงอยู่ด้านล่างเมื่อผู้ใช้ตั้งค่าคีย์คัทเพื่อดันไม้พินคีย์:

เมื่อผู้เข้าร่วมป้อนค่าจำนวนเต็มลงใน PLC พวกเขาจะควบคุมว่าตัวล็อคเคลื่อนที่ไปไกลแค่ไหน ค่าที่ถูกต้องสำหรับตัวล็อคแต่ละตัวคำนวณได้ดังนี้: Key Cut Value = 12 - Bottom Pin Tumbler Length

ตัวอย่างเช่น หากความยาวของตัวล็อคปัจจุบันคือ:

[7, 8, 4, 7, 9, 7, 3, 5, 6, 3, 10, 7]

ดังนั้น ค่าคีย์คัท ที่ผู้เข้าร่วมต้องตั้งค่าสำหรับแต่ละตำแหน่งไบต์หน่วยความจำจะเป็น [5, 4, 8, 5, 3, 5, 9, 7, 6, 9, 2, 5] เป็นรายการในตารางด้านล่าง:

ดัชนีแอดเดรส Byte Idx=0 Byte Idx=2 Byte Idx=4 Byte Idx=6
1 5 4 8 5
2 3 5 7 9
3 6 9 2 5

ผู้เข้าร่วมสามารถใช้ ไคลเอนต์ Siemens S7Comm (ตามที่ค้นพบในคำถามที่ 2) เพื่อเขียนค่าเหล่านี้ไปยังแอดเดรสหน่วยความจำ PLC ที่ถูกต้อง ผู้สอนสามารถให้หรือสาธิตการใช้สคริปต์ doorLockSolver.py ซึ่งจะเขียนค่าที่ถูกต้องไปยัง PLC โดยอัตโนมัติ บันทึกการดำเนินการสคริปต์การโจมตีแสดงอยู่ด้านล่าง:

หลังจากเขียนค่าลงในหน่วยความจำ UI จะอัปเดตและแสดงว่าตัวล็อคเปลี่ยนไปอย่างไรดังที่แสดงด้านล่าง เมื่อสี่เหลี่ยมสีเขียวทั้งหมด (ตัวล็อคพิน) อยู่ในแนวเดียวกับแนวเฉือน (คอลัมน์ 12) สามารถเปิดล็อคได้:

คำถามที่ 3 Flag : CISS_2025_P1Ns_@nd_TUm61ers_@T_C0RR3CT_P0S


ขั้นตอนที่ 5: แก้ปัญหา IT-คำถามที่ 4 – ค้นหาแอดเดรสหน่วยความจำ PLC

  • ปริศนา IT: ค้นหาไฟล์ที่ซ่อนอยู่และรับข้อมูลแอดเดรสบล็อกหน่วยความจำ PLC จากเมทริกซ์

  • ปริศนา OT: แทรกข้อมูล Bool ที่ถูกต้องลงในหน่วยความจำเพื่อแมปรหัส Morse ของตัวอักษร

เมื่อแก้ปัญหาคำถามที่ 3 แล้ว แท็บ Task 4 จะถูกปลดล็อคและแสดงในแถบนำทาง:

จากเบาะแส มีประเด็นสำคัญบางประการในการแก้ปัญหาความท้าทาย:

  • ข้อกำหนดการประมวลผลเมทริกซ์ : Sam ต้องประมวลผลเมทริกซ์เพื่อดึงข้อมูลที่มีความหมายบางอย่าง

  • การส่งข้อความ : ผู้ส่งข้อความที่มีเครื่องหมายคำถามถูกควบคุมโดย PLC หากเราตรวจสอบหน้าเริ่มต้น เราจะรู้ว่าเครื่องส่งข้อความเป็นเครื่องส่งโทรเลข ซึ่งบ่งชี้ว่าข้อความถูกส่งโดยใช้รหัส Morse

  • คำแนะนำรหัส Morse ที่ซ่อนอยู่: "Hi Sam, got problem to find the address of the PLC memory? Check this -- .- - .-. .. -..-" ถอดรหัสรหัส Morse: -- .- - .-. .. -..- → MATRIX สิ่งนี้ยืนยันว่าไฟล์เมทริกซ์เป็นศูนย์กลางในการแก้ปัญหาความท้าทายนี้

แต่ละตัวอักษรของข้อความบนหน้าจอมี พิกัด (x, y) อยู่ด้านล่าง:

คลิกรหัส Morse ของเมทริกซ์ -- .- - .-. .. -..- เพื่อดาวน์โหลดไฟล์เมทริกซ์แอดเดรสดังที่แสดงด้านล่าง:

ในการแก้ปัญหาความท้าทายนี้ ผู้เข้าร่วมต้องดาวน์โหลดไฟล์เมทริกซ์และใช้พิกัดที่กำหนดเพื่อค้นหาค่าภายในเมทริกซ์เพื่อกำหนดลำดับแอดเดรสหน่วยความจำ หรืออาจใช้สคริปต์การโจมตี matrixSeacher.py เพื่อดึงแอดเดรสทั้งหมด

คำถามที่ 4 Flag :CISS_2025_14_33_47_68_105_117_155_198_2025

ขั้นตอนที่ 6: แก้ปัญหา OT-คำถามที่ 5 – ส่งข้อความผ่านรหัส Morse

  • ปริศนา OT: แทรกค่าบูลีนที่ถูกต้องลงในบล็อกแอดเดรสหน่วยความจำที่ถูกต้อง

หลังจากแก้ปัญหาคำถามที่ 4 แล้ว คุณจะได้รับลำดับแอดเดรสหน่วยความจำ PLC ที่สอดคล้องกับข้อความ WEDIDPASS แต่ละตัวอักษรจะแมปกับแอดเดรสหน่วยความจำ PLC ที่ระบุ ดังที่แสดงด้านล่าง:

W - 14
E - 33
D - 47
I - 68
D - 105
P - 117
A - 155
S - 198
S - 2025

เมื่อคุณตรวจสอบส่วนข้อความในหน้าเว็บ คุณจะพบคีย์สำคัญที่จะช่วยคุณแก้ปัญหาความท้าทาย ดังแสดงในภาพประกอบ

  • มี คำแนะนำที่ซ่อนอยู่ (มองเห็นได้เฉพาะเมื่อไฮไลต์ด้วยเมาส์) ที่แสดง: Hint: '.' = True, '-' = False

  • แต่ละตัวอักษรต้องถูกแปลงเป็นรหัส Morse และค่าบูลีนที่สอดคล้องกัน (True สำหรับจุด False สำหรับขีด) ต้องถูกเขียนลงใน 4 ไบต์ต่อเนื่องกันในหน่วยความจำ PLC (เช่น ไบต์ 0, ไบต์ 2, ไบต์ 4, ไบต์ 6)

  • ตัวบ่งชี้สีเขียวหมายความว่าค่าไบต์ถูกต้อง และสีแดงหมายความว่าไม่ถูกต้อง

การใช้คำแนะนำและการแสดงรหัส Morse สำหรับแต่ละตัวอักษร เราสามารถสร้างตารางต่อไปนี้:

ตัวอักษร แอดเดรสหน่วยความจำ รหัส Mors Byte_0 Byte_2 Byte_4 Byte_6
W 14 .-- True False False
E 33 . True
D 47 -.. False True True
I 68 .. True True
D 105 -.. False True True
P 117 .--. True False False True
A 155 .- True False
S 198 ... True True True
S 2025 ... True True True

ในการตั้งค่า ให้ใช้ตัวอย่างโค้ด Python ต่อไปนี้:

memoryIdx = 2025
byteIndex = (0,2, 4)
valueList = (True, True, True)
for i in range(len(byteIndex)):
    client.setAddressVal(memoryIdx, byteIndex[i], valueList[i], dataType=BOOL_TYPE)
    time.sleep(0.1)
time.sleep(0.5)

หรือใช้สคริปต์ที่ให้มา morseCodeSolver.py เพื่อทำให้กระบวนการทั้งหมดเป็นไปโดยอัตโนมัติสำหรับทุกตัวอักษร:

เมื่อ ตัวบ่งชี้ทั้งหมดเปลี่ยนเป็นสีเขียว ให้คลิกปุ่ม “Send the Message” หากค่าถูกต้อง Flag สำหรับคำถามที่ 5 จะปรากฏในบัตรใต้พื้นที่ข้อความ

คำถามที่ 5 : CISS_2025_--_---_.-._..._.C0DE_MSG_S3NT!


ขั้นตอนที่ 7: แก้ปัญหา IT-คำถามที่ 6 – ดึงข้อความจากเสียง

  • ปริศนา IT: บังคับให้รหัสผ่านไฟล์ zip แตก ข้อมูลรับจากไฟล์เสียง

  • ปริศนา OT: แทรกค่า float ที่ถูกต้องลงในบล็อกแอดเดรสหน่วยความจำที่ถูกต้อง

เมื่อแก้ปัญหาคำถามที่ 5 แล้ว งานถัดไป (คำถามที่ 6) จะแสดงโดยอัตโนมัติที่ด้านล่างของหน้าเดียวกันดังที่แสดงด้านล่าง:

แสดงข้อความเพื่อให้ผู้เข้าร่วมปรับความถี่ของเครื่องรับโทรเลขเพื่อรับข้อความตอบกลับของ Aragorn:

Hi Frodo, you need to change your telegraph receiver to the correct frequency (HZ) same as Aragorn's transmitter! The frequency is the start MM.DD of CISS 2025 and the memory block is the XOR of all the send message address block index.

เราต้องเขียนตัวเลขทศนิยมลงในบล็อกหน่วยความจำ PLC ซึ่งควบคุมความถี่ของเครื่องรับโทรเลข

ข้อความแสดง XOR ดัชนีบล็อกแอดเดรสข้อความส่งทั้งหมด ในคำถามที่ 4 เราได้รับ flag CISS_2025_14_33_47_68_105_117_155_198_2025 จากนั้นทำการ XOR จำนวนเต็มเพื่อรับดัชนีบล็อกหน่วยความจำที่ถูกต้อง:

14 ^ 33 ^ 47 ^ 68 ^ 105 ^ 117 ^ 155 ^ 198 ^ 2025 = 2028

ความถี่คือจุดเริ่มต้น MM.DD ของ CISS ซึ่งคือ 07.29 ดังที่แสดงด้านล่าง:

ดังนั้นเราต้องแทรก 7.29 ลงในบล็อกหน่วยความจำ 2028 ด้วยโค้ดด้านล่าง:

client.setAddressVal(2028, 0, 7.29, dataType=REAL_TYPE)
client.setAddressVal(2028, 4, 7.29, dataType=REAL_TYPE) # optinoal

เมื่อคุณตั้งค่าในหน่วยความจำ PLC ให้รีเฟรชหน้าส่งข้อความ แล้วคุณจะได้รับข้อความของ Aragorn ตอนนี้ หน้าจะเปลี่ยนเป็นสถานะด้านล่างเพื่อแสดงงานที่ 4:

คลิกที่ลิงก์เพื่อดาวน์โหลดไฟล์เสียง .wav อย่างไรก็ตาม ไฟล์เสียงนี้ได้รับการป้องกันด้วยรหัสผ่านภายในไฟล์ ZIP ในการเข้าถึงไฟล์ .wav คุณต้องบังคับรหัสผ่าน ZIP โดยใช้รายการรหัสผ่านทั่วไป คุณอาจใช้เครื่องมือต่างๆ เช่น fcrackzip หรือ [zip2john + john] เพื่อทำสิ่งนี้ ตัวอย่างเช่น การใช้ fcrackzip และรายการรหัสผ่าน 1000 อันดับแรก (เช่น Pwdb_top-1000.txt จาก SecLists):

fcrackzip -v -D -p Pwdb_top-1000.txt protected_audio.zip

เมื่อแตกแล้ว ให้แยกไฟล์ .wav ออกจากไฟล์ ZIP

ไฟล์ .wav มีข้อความที่ซ่อนอยู่โดยใช้การซ่อนข้อมูลเสียง ฟังไฟล์เสียง เสียงในเสียงดูเหมือนจะไม่มาจาก "Aragorn" เล่นวิดีโออย่างต่อเนื่อง ใน 7 วินาทีสุดท้าย คุณจะได้ยิน "เสียงรหัส Morse" ตัดไฟล์เสียงและเหลือเพียงเสียงรหัส Morse บันทึกไฟล์เป็นไฟล์เสียงใหม่ morse.wmv

ใช้ตัวถอดรหัสแหล่งรหัส Morse ออนไลน์ เช่น https://morsecode.world/international/decoder/audio-decoder-adaptive.html เพื่อวิเคราะห์ไฟล์:

จากนั้นรับรหัส Morse: --. .. - .... .. -... .... .. -.. -.. . -. .-- .- ...- .

แปลงกลับเป็นข้อมูลข้อความ:

เราได้รับข้อมูลบางอย่าง: GITSUBHIDDENWAVE จากนั้นเราค้นหาคำหลัก "HiddenWave" ใน google และ GitHub เราจะพบเครื่องมือบางอย่าง https://github.com/techchipnet/HiddenWave.

ตอนนี้เรากลับไปแยกเสียงต้นฉบับ ใช้เครื่องมือโอเพนซอร์ส HiddenWave โดยเฉพาะสคริปต์ ExWave.py ที่มีอยู่ที่นี่:

โคลนที่เก็บ:

git clone https://github.com/techchipnet/HiddenWave.git
cd HiddenWave

รันสคริปต์:

python ExWave.py -f /path/to/your/audio.wav
ข้อความลับที่ดึงมาจากไฟล์ .wav จะปรากฏในเทอร์มินัล – นี่คือธงคำถามที่ 6 ของคุณ ดังที่แสดงด้านล่าง:

Question 6 Flag : CISS_2025_H1_Bro_wE11_DON3_FR0Do_@nd_S@m!

ขอแสดงความยินดี! ตอนนี้คุณได้ผ่านประตูแห่งดูรินและทำภารกิจทั้งหมดของความท้าทาย CTF นี้เสร็จสิ้นแล้ว!

หากคุณสนใจเกี่ยวกับความท้าทาย OT PLC CTF อื่นๆ คุณสามารถตรวจสอบความท้าทาย Modbus-PLC นี้ได้ใน CISS2024: https://www.linkedin.com/pulse/hacking-ics-step-by-step-guide-solve-critical-it-ot-ctf-yuancheng-liu-ohjwc

 


Last edit by LiuYuancheng([email protected]) at 15/07/2025, if you have any problem, please send me a message.

  RELATED

No related programming articles found. Browse all programming tutorials and articles.

  COMMENTS

0

No comment for this article.