246 words
1 minute
Pwn | ASEAN Open CTF 2025

Pwn | ASEAN Open CTF 2025#

by ShoIsMyName • Aug 2025

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

captionless image

มาเริ่มกันที่ข้อแรก กับข้อ EZ_PWN

captionless image

โดยเปิดมาก็เจอไฟล์ zip ให้เราโหลด บวกกับต้องเล่นผ่าน netcat แค่คิดก็เหนื่อยแล้ววว เลยขอเปิดที่ netcat นี่แหละ อยากรู้ว่าต้องเล่นอะไรร

captionless image

เห็นขนาดนี้ก็ภาวนาในใจขอให้เอาไฟล์เข้า ghidra แล้วเจอ password พร้อมกับโหลดไฟล์ และใน zip ก็จะมีแค่นี้

captionless image

Let move to ghidra!!

captionless image

โดยเริ่ม step แรกของเรากันก่อน จะเริ่มจาก main()

captionless image

function นี้มีการ call function 2 อันคือ check_password() และ triggerland() เราลองไปดู check_password() กันดีกว่า

captionless image

เราเจอ password 2 อัน “security123” & “P@ss0wrd”

captionless imagecaptionless image

เมื่อลองใส่ password ทั้ง 2 ก็จะเห็นว่าเราควรใช้ “security123” เพราะเหมือนมันสามารถให้เราเข้า access อะไรบางอย่างของมันได้ ซึ่งนั่นก็คือ triggerland() นั่นเอง!!

captionless image

แต่คำถามคือแล้ว function ที่มี flag มันอยู่ไหน ก็เลยไปเจอว่ามันอยู่ที่ onepiece()

captionless image

ประเด็นมันอยู่ว่า ตอนนี้เราใส่ password แล้วมาถึง triggerland() แต่ในนี้มันไม่มีอะไรที่จะ call function onepiece() ได้เลย แล้วเราจะทำยังไง

วิธีที่เราจะใช้ก็คือ buffer overflow ไงล่ะะะ!!!

เป้าหมายของเราคือพา program ของเรากระโดดไปเรียก onepiece() ที่มี flag ซ่อนไว้!!

แต่ก่อนที่จะเริ่มโจมตี เรามาทำความเข้าใจเกี่ยวกับโปรแกรมนี้กันก่อน เจ้า triggerland() เนี่ย มันจะรับ input buffer ได้ 64 bytes ซึ่งถ้าจะ buffer overflow มันเนี่ย แน่นอนเราจะใส่ input ที่เกิน buffer ของมัน ปัญหาคือ แล้วต้องทำแบบไหนให้มันกระโดดไปที่ onepiece() กันล่ะ

เอางี้ เรามาลงลึกตรงจุดนี้กันดีกว่า

captionless image

เวลา function ใน C ทำงานบน x86–64 compiler จะใช้ calling convention ที่สร้าง “stack frame” ของ function ขึ้นมา พอ triggerland() เริ่มทำงาน คำสั่ง assembly แรกๆ โครงสร้างมันจะเป็นแบบนี้

captionless image

ตรง push rbp จะเก็บค่า RBP ของฟังก์ชันที่เรียกมา (caller) ไว้บน stack เรียกว่า saved RBP

stack ของ triggerland() จะประมาณนี้

captionless image

เวลา get(local_48) มันจะเขียนทับ local_48 ก่อน ถ้าเกิน 64 bytes ก็จะทับ saved RBP (8 bytes ถัดมา) แล้วถ้าเกินอีก 8 bytes ก็จะทับ return address ซึ่งจุดนี้คือจุดที่เราจะใส่ address ของ onepiece()

เพราะฉะนั้น offset รวมจากบัฟเฟอร์ไปจนถึง return address = 64 + 8 = 72 bytes

โดยรวม input ที่เราจะส่งก็จะประมาณนี้

captionless image

สิ่งที่เราต้องการตอนนี้คือ address ของ onepiece() นั่นก็คือ 21011196 หรือ 0x21011196

captionless image

เมื่อเราได้มาแล้วก็เขียน payload code กันนน!!

( printf 'security123\n'; python3 -c 'import sys,struct; sys.stdout.buffer.write(b"A"*72+struct.pack("<Q",0x21011196)+b"\n")' ) | nc 203.154.91.221 5225

Let’s exploit!!

captionless image

แนะนำว่าใช้ code ดีกว่าพิมพ์เอง เพราะจะติดเรื่อง “inability to send raw bytes via standard input”

ขอบคุณที่อ่านจนจบครับบ See u next illusion~