คลัง
reverse

Ghidra

Ghidra เป็น reverse engineering suite ฟรีจาก NSA ที่มี decompiler คุณภาพสูงแปลง assembly เป็น pseudo-C เป็นเครื่องมือหลักของ CTF reversing บทนี้ลงลึกตั้งแต่การ import, การ navigate ทุกหน้าต่าง, คีย์ลัดครบ, การ rename/retype ให้ decompiler อ่านง่าย, เทคนิคแก้โจทย์ (หา flag check, patch), และ Ghidra scripting

BeginnerIntermediateAdvanced#ghidra#reverse#decompiler#disassembler#nsa#scripting#ctf

1. Ghidra คืออะไรและทำไมใช้

Ghidra เป็น RE suite ฟรี/open-source จาก NSA จุดเด่นคือ decompiler ที่แปลง machine code กลับเป็น pseudo-C อ่านได้ ทำให้เข้าใจ logic โดยไม่ต้องอ่าน assembly ทั้งหมด รองรับหลาย architecture (x86/x64/ARM/MIPS/...) และฟรี (ต่างจาก IDA Pro ที่แพง) เป็นตัวเลือกหลักของ CTF reversing เพราะคุณภาพ decompiler ใกล้เคียง IDA แต่ไม่มีค่าใช้จ่าย

reverse binary ด้วย Ghidra — ลำดับ
file + strings ก่อนเปิด Ghidra
ดู arch, packer, string ที่น่าสนใจ (flag format?)
import → auto-analyze
ปล่อยให้ Ghidra วิเคราะห์ครบก่อน
ไป main() ดู decompiler (pseudo-C)
Window > Decompile; อ่าน logic
โจทย์แบบไหน?
เทียบ input == passwordหา string/ค่าที่เทียบ
คำนวณ/แปลง inputเข้าใจ algorithm → เขียน solver
มี check ซ่อนดู xref ของ 'correct'/win func
rename/retype ตัวแปร ให้อ่านง่าย
ทำซ้ำจน logic ชัด
เข้าใจ logic → หา flag / สร้าง input ที่ผ่าน

2. เริ่มต้น — project และ analysis

  1. 1เปิด Ghidra → สร้าง Non-Shared Project → ตั้งชื่อ
  2. 2File → Import File → เลือก binary (Ghidra ระบุ format/arch อัตโนมัติ)
  3. 3ดับเบิลคลิกไฟล์ในโปรเจกต์ → เปิด CodeBrowser
  4. 4ตอบ Yes เมื่อถามให้ auto-analyze (เลือก analyzer default ก็พอ)
  5. 5รอ analysis เสร็จ (มุมขวาล่าง) — Ghidra หาฟังก์ชัน/string/xref/type ให้
  6. 6เริ่มที่ Symbol Tree → Functions → main (หรือ entry ถ้าไม่มี main)
ถ้า binary stripped (ไม่มี symbol) จะไม่เห็นชื่อ main — เริ่มที่ entry แล้วตามไป function ที่ถูกเรียกใน __libc_start_main (argument แรกคือ main)

3. หน้าต่างหลักและการ navigate

หน้าต่างใช้ทำอะไร
Listing (กลาง)disassembly (assembly) + address
Decompiler (ขวา)pseudo-C — อ่านง่ายสุด
Symbol Tree (ซ้าย)functions, labels, imports, exports
Data Type Managerstruct, enum, typedef
Defined Stringsstring ทั้งหมดในไฟล์ (Window menu)
Function Graphcontrol flow graph ของฟังก์ชัน
Byteshex view

Listing กับ Decompiler sync กัน — คลิกบรรทัดใน decompiler จะ highlight assembly ที่ตรงกัน ช่วยเชื่อมระดับสูง (C) กับระดับล่าง (asm) double-click ชื่อฟังก์ชัน/ตัวแปร = กระโดดไป definition, Alt+Left = ย้อนกลับ

4. คีย์ลัดสำคัญ

คีย์ทำอะไร
Lrename ตัวแปร/ฟังก์ชัน/label
Ctrl+Lretype (เปลี่ยน data type)
;ใส่ comment
Xcross-references (ใครเรียก/ใช้ object นี้)
Ggoto address/label/symbol
Alt+← / Alt+→ย้อนกลับ/ไปข้างหน้า (history)
Ctrl+Shift+Esearch strings / memory
Fสร้างฟังก์ชัน (ถ้าไม่ detect)
Cclear code (แปลงกลับเป็น data)
spaceสลับ Listing ↔ Function Graph

5. ทำ decompiler ให้อ่านง่าย (หัวใจ)

decompiler ดิบอ่านยาก (ชื่อ local_28, uVar1, FUN_00401234) การ rename + retype ทีละนิดทำให้โค้ดอ่านเข้าใจขึ้นมาก — เป็นทักษะสำคัญที่สุดของการ reverse ฟังก์ชันซับซ้อน ยิ่งตั้งชื่อตรงเท่าไหร่ logic ยิ่งชัด

  • rename ตัวแปร (L): local_28user_input ตามที่เข้าใจ
  • retype (Ctrl+L): เปลี่ยน type ให้ตรง เช่น undefined8char * หรือ apply struct
  • rename ฟังก์ชัน (L): FUN_00401234check_password ตามหน้าที่
  • comment (;): จุดที่เข้าใจแล้ว กันลืม
  • สร้าง struct ใน Data Type Manager ถ้าโปรแกรมใช้ struct → apply แล้ว field มีชื่อ
  • แก้ function signature (Ctrl+ที่ชื่อฟังก์ชันใน decompiler) ให้ argument ถูกต้อง

6. เทคนิคแก้โจทย์ CTF

  • หา flag check: Defined Strings (Ctrl+Shift+E) หา 'Correct'/'Wrong'/'flag' → X ดู xref → ไปฟังก์ชันที่เทียบ
  • reverse algorithm: อ่าน decompiler ของ check function → เข้าใจ transform → เขียน solver ย้อนกลับ (Python)
  • strcmp/memcmp: หา call เหล่านี้ → argument ที่สองมัก hardcode flag/password
  • xor/encode loop: เจอ loop ที่ xor → ดู key → decode เอง
  • patch: Listing → คลิกขวา instruction → Patch Instruction (เช่น JNZ→JZ ข้าม check) → File → Export Program (format Original File)
  • ใช้คู่ dynamic: อ่าน Ghidra เข้าใจโครงสร้าง → gdb ยืนยันค่า runtime (ดู Dynamic Analysis)
เริ่มทุกโจทย์ที่ Defined Strings — หา 'flag', 'password', 'Correct', 'Wrong' แล้วกด X ดู xref ไปยังโค้ดที่ใช้ string นั้น เป็นทางลัดที่เร็วสุดในการหาจุด logic สำคัญ

7. Ghidra Scripting

Ghidra มี Script Manager (Window → Script Manager) รัน script Python (Jython) หรือ Java เพื่อ automate — เช่น deobfuscate (decode string ที่ถูก xor ทั้งไฟล์), patch หลายจุด, ดึงข้อมูล ใช้ Flat API (currentProgram, getFunctionAt(), getInstructionAt())

ตัวอย่าง Ghidra Python script
# Window > Script Manager > New Script (Python)
# ตัวอย่าง: พิมพ์ทุกฟังก์ชัน + address
fm = currentProgram.getFunctionManager()
for func in fm.getFunctions(True):
    print(hex(func.getEntryPoint().getOffset()), func.getName())

# อ่าน byte ที่ address (เช่น decode xor string)
addr = toAddr(0x402000)
data = getBytes(addr, 16)
key = 0x42
print("".join(chr((b & 0xff) ^ key) for b in data))

# มี Python console: Window > Python ทดสอบ interactive ได้
Flat API ทำงานกับ currentProgram; ใช้ automate งานซ้ำๆ เช่น decode obfuscated strings ทั้งไฟล์

8. Quick Reference

  • decompiler ฟรีจาก NSA — pseudo-C; import → auto-analyze → main
  • หน้าต่าง: Listing (asm) + Decompiler (C) sync กัน; Symbol Tree
  • คีย์: L rename, Ctrl+L retype, X xref, G goto, ; comment
  • Ctrl+Shift+E = strings (เริ่มทุกโจทย์ที่นี่)
  • อ่านง่าย: rename+retype ตัวแปร/ฟังก์ชันทีละนิด, สร้าง struct
  • flag check: string 'Correct' → X xref → reverse algorithm
  • patch: คลิกขวา → Patch Instruction → Export; scripting: Flat API

🧭 จับมือทำทีละขั้น (มีแค่ Kali) + ถ้าติดไปไหนต่อ

สมมติเพิ่งได้ binary จากโจทย์ CTF เปิด Kali ว่างๆ ยังไม่รู้จะกดตรงไหนก่อนใน Ghidra ทำตามนี้ทีละขั้น

  1. 1file ./binary — เช็ค ELF/PE, 32/64bit, stripped หรือไม่
  2. 2strings -n 8 ./binary | grep -iE 'flag|pass' ลองทางลัดก่อนเสียเวลาเปิด Ghidra
  3. 3เปิด Ghidra → File → New Project (Non-Shared) → ตั้งชื่อโปรเจกต์
  4. 4File → Import File เลือก binary → ดับเบิลคลิกเปิด CodeBrowser
  5. 5ตอบ Yes ให้ Auto Analyze (ใช้ default analyzer) รอจนแถบล่างขวาวิเคราะห์เสร็จ
  6. 6Symbol Tree → Functions → main (ถ้า stripped ไปที่ entry แล้วตาม call ที่ 2 ใน __libc_start_main)
  7. 7เปิด Decompile panel คู่กับ Listing อ่าน pseudo-C ทีละฟังก์ชัน
  8. 8Ctrl+Shift+E เปิด Defined Strings หา 'Correct'/'flag'/'Wrong' แล้วกด X ดู xref กลับไปโค้ด
  9. 9กด L rename ตัวแปร, Ctrl+L retype ทีละจุดจนอ่านง่ายขึ้น
  10. 10เข้าใจ logic แล้วตัดสินใจ: เขียน solver คำนวณ flag เอง หรือ patch ให้ผ่าน check
อ่าน binary ด้วย Ghidra ทีละขั้น
file + strings ก่อนเปิด Ghidra
import → auto analyze → หา main/entry
เจอ main ปกติไหม
✅ เจอ main ตรงๆ→ เปิด Decompile อ่านต่อ
❌ stripped ไม่มีชื่อ main→ ไปที่ entry ตาม call ใน __libc_start_main
Ctrl+Shift+E ดู Defined Strings หา flag/Correct/Wrong แล้ว X ดู xref
อ่านโค้ดที่ xref มาถึงเป็นแบบไหน
✅ เจอ flag hardcode ตรงๆ ใน decompile→ จบเลย ได้ flag
✅ เจอ check เช่น strcmp/if ที่ต้องผ่าน→ เข้าใจ logic แล้วเลือก patch หรือเขียน solver
❌ โค้ด obfuscate/ตัวแปรคำนวณ runtime อ่านไม่ออก→ ไปดูค่าจริงตอนรันด้วย dynamic analysis
❌ สงสัยว่ามี ptrace/timing check→ อาจมี anti-debug กันไม่ให้วิเคราะห์ต่อ
ขั้นตอน/งานเครื่องมือใน Kaliติดตั้งเพิ่ม (ถ้าไม่มี)เครื่องมือออนไลน์
ดู arch/type ก่อนเปิดเครื่องมือfile--
ดึงข้อความเร็วๆstrings-CyberChef
เปิด decompiler หลัก (ฟรี)ghidraapt install ghidradogbolt.org (ลองหลาย decompiler พร้อมกัน)
เทียบผล assembly กับ compiler ต้นทาง--godbolt.org
disassemble เร็วจาก CLIradare2/rizin, objdumpapt install radare2onlinedisassembler.com
ยืนยันค่าตอนรันจริงgdb (pwndbg/gef)apt install gdb; git clone gef-
เขียน script อัตโนมัติ (decode/patch หลายจุด)ghidra (Python script)--
ถอดรหัส/คำนวณเพิ่มเติมจาก logic ที่เจอpython3-CyberChef, dcode.fr
🚑 ถ้าตันสนิท ลองท่าถัดไป: static-analysis — ก่อนเปิด Ghidra อยากทำ triage ให้ครบก่อน (imports, packed, stripped); dynamic-analysis — ต้องดูค่า runtime จริง/ผ่าน obfuscation ที่อ่าน static ไม่ออก; binary-patching — เข้าใจ logic แล้วแค่ต้องการผ่าน check; anti-debug — เจอ ptrace/timing check กัน analyze; frida — โจทย์ mobile หรืออยาก hook แทนแก้ไฟล์

โน้ตของฉัน

ยังไม่มีโน้ตสำหรับหัวข้อนี้