This post is originally migrated from Medium.com
บทนำ
สวัสดีครับ ผมเป็นนักศึกษาปีสาม Com En คนนึงที่เพิ่งรู้จัก cybersecurity เมื่อตอนจบปีสอง และได้ศึกษาเรื่อย ๆ ช่วงปิดเทอมจนไปเจอว่ามันมีการแข่งขันที่เรียกว่า Capture the Flag (CTF) ซึ่งคือการใช้ทักษะเจาะระบบ ทักษะความช่างสังเกต และประสบการณ์ในการเอาสิ่งที่เรียกว่า flag หรือธงออกมาจากโจทย์ประเภทต่าง ๆ
การเตรียมตัว
การเตรียมตัวก็ไม่ได้หวือหวาอะไร สู้พวกน้อง ๆ มัธยมที่เดินสายแข่งไม่ได้แน่นอน เราก็อาศัย:
- picoCTF
- Try Hack Me
- โจทย์เก่า ๆ
- เข้าอบรมออนไลน์บ่อย ๆ (งานไหนฟรีเข้าหมด)
โดยธง หรือ flag มันก็มักจะมีหน้าตาแบบนี้:
CTF{h€110_th1s_1s_th€_fl@g}
หมายเหตุ: งานนี้หน้าตา flag จะมีหลายรูปแบบเพราะออกโดยหลายทีมงาน
เมื่อนำธงไปใส่ในโจทย์ก็จะได้คะแนน โดยคะแนนก็จะแบ่งตามโจทย์ข้อง่าย กลาง ยาก นั่นเอง
งาน NCSA CTF Boot Camp
งานแรกที่ผมได้ไปเลยคืองาน NCSA CTF Boot Camp ซึ่งจัดโดย สกมช. (สำนักงานคณะกรรมการการรักษาความมั่นคงปลอดภัยไซเบอร์แห่งชาติ) เป็นงานที่จัดขึ้นเพื่อเตรียมความพร้อมให้น้อง ๆ มัธยมและมหาลัยได้ลองฝีมือก่อนไปแข่งจริงในงาน Cyber Top Talent
โดยใน Boot Camp ก็จะมีทั้ง:
- การสอนทำโจทย์ในหมวดต่าง ๆ
- การแข่งขัน Mini CTF ให้ได้วัดฝีมือกันในวันสุดท้าย

บรรยากาศ
บรรยากาศก็นั่งกันทีมละ 3 คนคละกันไป การเชื่อมไวไฟโรงแรมในจังหวะนี้คือสุ่มเสี่ยงใช้ได้ เพราะต่างกันก็ต่างแสกนกัน 😂 (สงสารเครื่องปริ้นไวไฟของโรงแรม) มีคนเปิด SSID ดักเพื่อนอีก
Mini CTF Competition
เมื่อถึงวันที่สองเราก็เข้าเรื่อง writeup ดีกว่า วันนี้จะได้เล่น Mini CTF กันตั้งแต่ 12.00–15.00 เวลาเรียกว่าค่อนข้างน้อย แค่นั่งคิดก็หมดเวลาแล้ว
ตอนแรกหวังว่าอยากได้คะแนนซัก 30% เพราะส่วนตัวมีจุดอ่อนสำคัญคือหมวด:
- Web
- Reverse Engineering
- Mobile App
ที่เริ่มไม่ออก บอกไม่ถูกว่าจะทิ้งอย่างเดียว 😅
โจทย์ทั้งหมด
โดยก็จะมีโจทย์ทั้งหมด 15 ข้อ ข้อละ 100, 300, 400, 500 คะแนน แบ่งตามหมวดดังนี้:
- Misc: 3 ข้อ (แก้ได้ 3)
- Web: 4 ข้อ (แก้ได้ 1)
- Forensics: 3 ข้อ (แก้ได้ 1)
- Network: 3 ข้อ (แก้ได้ 2)
- Mobile: 1 ข้อ
- Programming + Pwnable: 1 ข้อ
โดยทีมเราจะแบ่งกันทำเป็นข้อ ๆ ไป และบอกกันตลอดหากเปลี่ยนข้อ หากเพื่อนทำข้อไหนได้ เราก็จะเมินข้อนั้นไปดูข้อที่เหลือ เพื่อใช้เวลาให้คุ้ม

Writeups
Misc0
ข้อนี้แจกฟรีเป็น Sanity Check และให้เทสระบบ
For sanity check, you have free flag here.
Flag: STH{20cda557cfa098c65f372b745e11a21e}
Misc1
โจทย์:
XOR message below with a letter.
Message:
00071b283735323237366a37303232616b353062656036326463643136313566616364642e
ข้อนี้พี่ทีมเราเอาไปแก้ โดยการใช้ XOR cipher decoder ออนไลน์


Misc2
โจทย์:
Base64 is too easy. I have applied 3 BaseXX encoding to the message below.
Message:
SFcUFnKydQ9L1q6jfZXKvbZVY3uQPyENV2g4WveejUrptAkcru4pRbMP8ceGxhe9DMoptJen43SwYrDi5mBDMFN1wadt439ZjbNS6QbtBBPvuCTH4Vp5A8h1b4zbgnaMUV4
อันนี้ง่ายมาก ใส่ CyberChef ก็ออก เจอที่ Base58 → Base45 → Base32 ตามลำดับ

Web0
โจทย์:
Find flag in HTTP responses of https://sth.sh
Flag จะอยู่ในรูปแบบ {…} ให้หาค่ามาใส่ใน … ที่ถูกต้อง ตัวอย่างเช่น {PENTEST}
อันนี้น้องในกลุ่มแก้ได้แบบงง ๆ เราก็ไม่รู้ว่าทำยังไง เลยลองหาเองดู คิดว่าน่าจะเจอเป็นแบบนี้แหละ อันนี้เปิดด้วย Burpsuite เดาว่าเป็นอันเดียวกัน

Network1
จริง ๆ ข้อนี้มีเนื้อเรื่องแถมมาให้ด้วย โดยได้ไฟล์ PCAP มา 1 ไฟล์


เลื่อนดูผ่าน ๆ ก็เจอเจ้านี่เข้า เอ็งนี่แหละน่าสงสัยสุดแล้ว ก็คลิกขวา follow HTTP stream ไป แต่ก็ยังไม่เจออะไรผิดสังเกต เจอแค่หน้าเว็บ HTML ที่ไป GET มาเฉย ๆ
จนกระทั่งไปเจอเจ้านี่เข้าอีก แค่ชื่อก็เสียวแล้ว bitcoin_miner น่าสงสัยจัด

ส่วนเนื้อในก็เป็นประมาณนี้:

มาดูกันต่อ เหมือนว่าข้อมูลในแพ็กเก็ตที่เป็น HTTP เขียว ๆ จะหมดลงแล้ว จากที่เห็นว่าการเชื่อมต่อ GET /bincoin_miner/elf ก็โดนปิด (TCP terminate) จนจบไป แต่ยังมีแพ็กเก็ตด้านล่างที่เป็นส่วนของ TCP handshake เพื่อเริ่มการเชื่อมต่อใหม่อยู่

พอ follow TCP stream ไปต่อก็เจอดังนี้ เป็นการเช็ค user, dir เรียลร้อบแล้ว cat ไปดู flag.txt

ถ้านี่คือ secret_half2.txt แล้ว half1 ล่ะ 😂 เลยไปหาดี ๆ อีกรอบ เจอ packet ที่มี HTTP request เป็น POST

โอเค ได้ 2 พาร์ทแล้วล่ะ ลักษณะรวมกันเป็น:
ZmxhZ3tqdW5pb3JfbmV0MV9kZDEwNjQKOGVlZTJiZjJkNzE4OTMwYzliMmZiZWJhZTF9Cg==
ล่ะก็คง Base64 แน่นอน

Network2
ข้อนี้มีไฟล์ PCAP กับไฟล์ .pem มาให้พร้อมคำใบ้:
rsa_padding_mode:oaep
rsa_oaep_md:sha256
ชัดเจนเลยว่า encrypt แบบ Char Aznable …. เอ้ย SHA-256 ชัวร์
เริ่มที่ส่องไฟล์ PCAP กันก่อนเลย พบว่าไม่มีอะไรมาก เจอแค่นี้เลย 17 แพ็กเก็ต เป็น TCP ล้วน 1 connection ถ้วน สังเกตจากพอร์ตและ handshake, terminate

จากนั้นเรา follow TCP stream เปิดมาเจอดังนี้:

ดูแล้วเป็น RSA encrypted + plain text นิดหน่อยให้ได้รู้บริบทเรื่องราว เป็นการสื่อสารกันของ user สีฟ้า กับ reply ของระบบสีแดง ๆ โดยสีแดงโดน encrypt ไว้ ที่น่าสนใจคือ cat /tmp/flag.txt ที่คิดว่าน่าจะเป็น flag แน่นอน
เราก็ไป cat ดูไฟล์ .pem ที่แถมมา ได้ว่า:

คราวนี้เราก็จะลองแกะข้อความที่ system ตอบกลับนาย longcat (พี่ตะ Siam Thanat Hack) ทีละข้อความ โดยตัวผมเองไม่เคยใช้ tool อะไรแกะ RSA มาก่อน เลยถาม ChatGPT มันแนะนำ openssl และวิธีเตรียม payload ต่าง ๆ ดังนี้
ผมก็อบข้อความส่วนที่เป็นสีแดง แยกเป็นไฟล์ 1.b64, 2.b64 และ 3.b64 ก่อน เพราะลักษณะข้อความที่ได้มา ลงท้ายด้วย == มีโอกาสเป็น Base64 สูง

จากนั้นมันบอกว่า openssl รับ input ที่เป็น .bin ก็เลยให้เอาทุกตัวไป decode จาก b64 ก่อน แล้วเอาผลลัพธ์ไปทำไฟล์ bin ก็เลยมั่วเอาตามนี้ ทุกไฟล์:
base64 -d 1.b64 > 1.bin
แล้วก็ decrypt RSA ดังนี้:
openssl pkeyutl -decrypt -in 1.bin -inkey private_key.pem -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256
ไฟล์แรก ได้แบบนี้ ก็โอเคยืนยันว่า system ตอบกลับคำสั่ง id:
uid=1000(user) gid=1000(user) groups=1000(user),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),100(users),114(lpadmin)
ไฟล์ที่ 2 ก็แน่นอนว่า เพราะคำสั่งคือ echo "longcat is here, where is the security?" system ก็เลยตอบ echo ไป:
longcat is here, where is the security?
ไฟล์ที่สาม ที่น่าสนใจ โอเค นี่แหละ FLAG:
flag{junior_net2_8a95ca672a65f751efd70d1340cf835a}
Network3
ข้อนี้แก้ไม่ออกในห้องครับ หลายคะแนนอยู่ คิดออก รู้ว่ามันจะเล่นอะไร แต่ผมก็ทำไม่ทัน เลยกลับมาลองต่อที่บ้าน (โหลดไฟล์ไว้)


ได้ไฟล์ PCAP มา 1 ไฟล์ ตามภาพ:

คือข้อนี้ไม่ต้องสืบ แค้นมากครับ เจอสองรอบ รอบก่อนในโจทย์เก่า (แก้ไม่ได้ทั้งสองรอบ) มันคือ DNS exfiltration นี่แหละครับ
สังเกตจากไอ้ 192.168.191.111 พยายามส่งหา DNS ของ Google เพื่อหา domain อะไรซักอย่างลงท้าย .c2.sth.sh ซึ่งไอ้ข้างหน้าเนี่ยแหละที่ปัญหา มันเป็น Base64 encoded พยายามเอาข้อมูลมาซ่อนไว้ ต้องเอามารวมกันทุกเฟรม แล้วได้อะไรออกมาแน่นอน
ข้อนี้ทำด้วยมือคงยาก เพราะว่ามีมากถึง 7,605 เฟรม (Wireshark ดักจับที่ NIC ซึ่งเป็น Layer 2 พอดี ผมเลยเรียกเฟรม ไม่เรียกแพ็กเก็ต ถูกผิดขออภัย)
การกรองข้อมูล
ผมกรองอย่างง่ายก่อนด้วยการ filter เอาแค่ขาเดียว จากการที่ DNS query แล้ว Google มันตอบอะนะ ผมเลือกแค่ฝั่งส่งออกพอ:
dns && ip.dst == 8.8.8.8
จากนั้นผมเลยขอความช่วยเหลือ ChatGPT หน่อย เพราะต้องใช้ tool ไม่คุ้นอย่าง tshark:
tshark -r minictf_net3.pcapng -Y "dns && ip.dst == 8.8.8.8" -T fields -e dns.qry.name > export.txt
คำอธิบาย:
-Yเป็นการใส่ filter ตามข้างต้นที่กล่าว-Tเลือก fields-e dns.queryเพื่อเอาแค่ส่วนชื่อโดเมนจริง ๆ

คราวนี้มันยังเหลือ .c2.sth.sh ซึ่งต้องกรองออก ผมก็เลยยัดใส่ VSCode เพื่อความง่าย (มั้ง)

แต่ถึง replace ออกไป ก็ต้องคลีนข้อมูลอีกนิด:
U0laRT04NTU0OTs = SIZE=85549;
MDovOWovNFEvK1JYaHBaZ0FBVFUwQUtnQUFBQWdBQmc= 0:/9j/4Q/+RXhpZgAATU0AKgAAAAgABg
MTpFU0FBTUFBQUFCQUFFQUFBRWFBQVVBQUFBQkFBQUE= 1:ESAAMAAAABAAEAAAEaAAUAAAABAAAA
สังเกตว่าจะมี 0: และ 1: นำหน้า ซึ่งเป็นตำแหน่งสำหรับการรวมแพ็กเก็ตที่ปลายทาง สำหรับให้ hacker ขโมยข้อมูลไปแล้วเรียงออกมาถูก
การใช้ RegEx
ผมก็เลยใส่ RegEx เพื่อเลือกเอาอะไรก็ตามที่อยู่หน้า : เป็นต้นไป:
^[^:]*:
คำอธิบาย:
^→ เอาไว้บอกว่าหน้าสุด[^:]*→ เจ้า*หมายถึง match ตัวหน้า*อีกกี่ตัวก็ได้ เช่นa*คือได้ทั้งa,aaa,aaaaa[^:]คือเป็นการบอกนิเสธว่า match อะไรก็ได้ที่ไม่ใช่:- ดังนั้น
[^:]*หมายถึงจะ match อะไรก็ได้ที่ไม่ใช่:และยาวจำนวนกี่ตัวก็ได้ :→ และปิดท้ายเพื่อ match:

จับยัดเว็บ Base64 to JPG อันไหนก็ได้ แนะนำ Base64Guru รองรับการแปลงร่างหลายรูปแบบมาก ยิ่งกว่ามาสไรเดอร์ดีเคด

โจทย์เพิ่มเติม
Section นี้ผมขอรวมโจทย์ที่น่าสนใจ นอกเหนือจากงานไว้นะ คือผมขี้เกียจเปิด writeup ใหม่ ก็เลยยัดไว้ในนี้ก่อน แต่มันจะไม่เกี่ยวกับ miniCTF ที่ไปมา
key.zip

เปิดดูก็พบว่าเป็น key.zip เพียว ๆ คาดว่าเป็นหมวด Forensics นี่แหละ ผมเลยไล่ลอง tools ต่าง ๆ ก่อนดังนี้:
filebinwalkexiftoolcat
พบว่าก็ปกติหมด ไอ้นี่มันไฟล์ zip ธรรมดา ๆ นี่หว่า
จากนั้นก็ unzip key.zip เอ๊ะ มันติด password

ด้วยความที่ผมเล่นด้วย Debian เป็นหลัก wordlists จึงไม่ได้เตรียมหยิบไวใกล้ตัวสุดก็นั่นแหละ rockyou.txt เจ้าเดิม (เอาน่าโจทย์ CTF มันคงไม่โหดร้าย ?) โดยใช้ tool ชื่อ fcrackzip
![]()
cd เข้าไปดูก็พบชายเดี่ยว เอ้ย ไฟล์เดี่ยว ๆ key.jpg ทำไมมันถึงชื่อ key นะ น่าสนใจมาก อาจจะเป็นการยัด encrypt + key ไว้ในไฟล์ .jpg ? หรืออาจจะคิดมากไปเอง
ก็ตามสเต็ปครับ exiftool, binwalk, cat, strings ล้วนไม่เจออะไร ลักษณะของมันก็ดูเป็นไฟล์ jpg ธรรมดา ๆ ยกเว้นว่า:
- exiftool: “Error: File format error” หืมมมมม
- เลย
file key.jpgแล้วขึ้นว่า “key.jpg: data” อื้มมมมม - binwalk: ไม่เจออะไรเลย

ผมก็เลยใช้บริการเว็บไซต์ดู hex file ชื่อ https://hexed.it/ โยนไฟล์ลงไป

เท่าที่ดูไฟล์นี้เป็น JFIF ครับ (JPEG File Interchange Format) ดูจาก ASCII ด้านขวามี JFIF และส่วนประกอบทั่วไป แต่ว่า header ไฟล์มันแปลก ๆ เนื่องจากไฟล์ sample JFIF ที่ผมโหลดมามันควรเริ่มด้วย:
FF D8 FF E0 00 10 4A 46 49 46 00

แสดงว่าอาจจะเป็น header นี่แหละ ที่เสีย ก็เลยทำการแก้กลับคืนแล้ว export

$exiftool key.jpg
ExifTool Version Number : 12.57
File Name : key.jpg
Directory : .
File Size : 13 kB
File Modification Date/Time : 2025:08:02 19:06:23+07:00
File Access Date/Time : 2025:08:02 19:06:25+07:00
File Inode Change Date/Time : 2025:08:02 19:06:23+07:00
File Permissions : -rw-r--r--
File Type : JPEG
File Type Extension : jpg
MIME Type : image/jpeg
JFIF Version : 1.01
Resolution Unit : inches
X Resolution : 72
Y Resolution : 72
Profile CMM Type :
Profile Version : 2.1.0
Profile Class : Display Device Profile
Color Space Data : RGB
Profile Connection Space : XYZ
Profile Date Time : 0000:00:00 00:00:00
Profile File Signature : acsp
Primary Platform : Unknown ()
CMM Flags : Not Embedded, Independent
Device Manufacturer :
Device Model :
Device Attributes : Reflective, Glossy, Positive, Color
Rendering Intent : Media-Relative Colorimetric
Connection Space Illuminant : 0.9642 1 0.82491
Profile Creator :
Profile ID : 0
Profile Description : sRGB
Red Matrix Column : 0.43607 0.22249 0.01392
Green Matrix Column : 0.38515 0.71687 0.09708
Blue Matrix Column : 0.14307 0.06061 0.7141
Red Tone Reproduction Curve : (Binary data 40 bytes, use -b option to extract)
Green Tone Reproduction Curve : (Binary data 40 bytes, use -b option to extract)
Blue Tone Reproduction Curve : (Binary data 40 bytes, use -b option to extract)
Media White Point : 0.9642 1 0.82491
Profile Copyright : Google Inc. 2016
Image Width : 491
Image Height : 184
Encoding Process : Baseline DCT, Huffman coding
Bits Per Sample : 8
Color Components : 3
Y Cb Cr Sub Sampling : YCbCr4:2:0 (2 2)
Image Size : 491x184
Megapixels : 0.090
เช็คอีกรอบ กันเหนียว เผื่อ flag ปลอม lol
Your_Mailing.pcap
ข้อนี้ผมได้มาจากอบรม สกมช เป็นไฟล์แปะไว้ให้ในไดรฟ์ น่าจะเป็น Network Hard จากรายการ WCTF ปี 2023
หลักการอันนี้ไม่ได้มีอะไรมากครับ มันเหมือนกับข้อ Network3 ด้านบนแหละ แค่เปลี่ยนจากเล่น DNS มาเล่น SMTP แทน
อันนี้ผมเดาได้จากชื่อไฟล์นะ แต่ถ้าไม่มีชื่อผมก็เช็คจาก Protocol Hierarchy ก่อนหาว่าอะไรเล่นได้บ้าง มันก็มี SMTP, DNS, TLS ที่น่าลุ้น สำหรับข้อนี้ ก็เป็น SMTP ครับ

หลังจากกรองเอา filter: smtp แล้วกด follow TCP stream มา ก็ได้เป็นดังนี้ครับ เป็นเลขฐาน 16 (hex) จากฝั่ง client ซ่อนไว้ในทั้งหมด 32 แพ็กเก็ตนั้นแหละ

T shark เพื่อเอามันออกมาเร็ว ๆ ครับ
payload ที่ได้ออกมาจะเป็น hex เลยต้อง xxd -r -p เพื่อกลับมันเป็น binary data อีกที ที่โปรแกรมอื่นอ่านออกได้ แล้วก็ output ไว้ที่ output.txt ก็ได้:
tshark -r Your_Mailing.pcap -Y "smtp" -T fields -e tcp.payload | xxd -r -p > output.txt

คราวนี้จะได้เป็นแบบนี้ มันก็คงรวมกันเป็นไฟล์อะไรซักอย่าง:
504b03041400010808001d2e8c5730af6187360000002800000008002400666c61672e7478740a00200000000000010018000029ed39842cda0100803ed5deb19d0100803ed5deb19d01223dea64bc8cbe24be34c401db66995e90e265caa5e3cde3a5b518e2397f790357aed7298be222a51a895419f543dbdebfc667166235504b010214001400010808001d2e8c5730af61873600000028000000080024000000000001002000000000000000666c61672e7478740a00200000000000010018000029ed39842cda0100803ed5deb19d0100803ed5deb19d01504b050600000000010001005a000000800000000000
ซึ่งเป็น hex อะไรซักอย่าง ซึ่งส่วนแรก ๆ มี magic number ตรงกับ pkzip

xxd -r -p output.txt output.zip
ยัดมันกลับเป็น .zip อีกรอบครับ ชั้นตอนนี้จะใช้ tool ออนไลน์ทำก็ได้ หลังจากนั้นพอ unzip output.zip ดันติดรหัสซะงั้น ผมเลยใช้ john the ripper ช่วย ซึ่งผมก็ใช้ไม่ค่อยเป็น 😅
zip2john output.zip > hash.txt
john --wordlist="path" hash.txt

ได้ว่ารหัสคือ iloveyou2 นะครับ ก็ unzip ได้เป็น flag.txt
Flag: WCTF23{b7ceb75620bb61fc062702c197d4004c}
Comments