คลัง
reverse

Strings

strings ดึงข้อความที่อ่านได้ออกจาก binary — เป็นขั้นแรกของ reversing ที่บ่อยครั้งเจอ flag, hardcoded password, URL, error message ตรงๆ บทนี้ลงลึกการใช้ทุก option, encoding ต่างๆ (ASCII/Unicode), การกรอง, FLOSS สำหรับ string ที่ถูกซ่อน, และการเชื่อมกับ decompiler

BeginnerIntermediate#strings#reverse#static#floss#recon#encoding#ctf

1. ทำไมเริ่มจาก strings

ก่อนเปิด decompiler ให้ลอง strings เสมอ — เป็นวิธีเร็วสุดที่บางทีเจอคำตอบทันที: flag ที่ hardcode, password, URL ของ C2 server, ชื่อฟังก์ชัน/library, error message ที่บอกใบ้ logic, format string โจทย์ CTF ระดับง่ายหลายข้อแก้ได้ด้วย strings อย่างเดียว และแม้โจทย์ยาก strings ก็ให้ context เริ่มต้นที่มีค่า

2. การใช้และ options

strings optionsLinux
strings binary                       # default: ASCII >= 4 ตัว
strings -n 8 binary                  # เฉพาะ string ยาว >= 8 (ตัด noise)
strings -t x binary                  # แสดง offset (hex) ของแต่ละ string
strings -e l binary                  # 16-bit little-endian (Unicode/Windows wide char)
strings -e b binary                  # 16-bit big-endian
strings -a binary                    # scan ทั้งไฟล์ (ไม่ใช่แค่ data section)

# rabin2 (radare2) — แยก string ตาม section พร้อม metadata
rabin2 -z binary                     # strings ใน data sections
rabin2 -zz binary                    # ทั้งไฟล์
-e l สำคัญมากสำหรับ binary Windows ที่ใช้ wide char (Unicode) — string ปกติจะไม่เห็น

3. กรองหา flag/keyword

กรองด้วย grepLinux
# หา flag/keyword
strings binary | grep -iE 'flag|ctf|key|pass|secret|admin'

# หา pattern คล้าย flag format (เช่น CTF{...})
strings binary | grep -oE '[A-Za-z0-9_]+\{[^}]+\}'

# หา base64/hash-like (ตัวยาวๆ)
strings binary | grep -E '[A-Za-z0-9+/]{20,}={0,2}'

# หา URL/IP
strings binary | grep -oE 'https?://[^ ]+'
strings binary | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}'
grep -oE ดึงเฉพาะส่วนที่ match (เช่น flag format) ออกมา; ลองทั้ง ASCII และ -e l (Unicode)

4. เมื่อ string ถูกซ่อน (FLOSS)

malware/โจทย์ขั้นสูงมักซ่อน string ไม่ให้ strings เห็น — โดย encode/encrypt แล้ว decode ตอน runtime, หรือ build ทีละ byte บน stack FLOSS (Mandiant FLARE) แก้ปัญหานี้ได้

FLOSS — ดึง obfuscated stringsLinux
# FLOSS ดึง string ที่ถูก decode at runtime / สร้างบน stack
floss binary
# จะ emulate และดึง: static strings + decoded strings + stack strings

# เฉพาะ stack strings
floss --only stack binary
FLOSS emulate การ decode เพื่อดึง string ที่ strings ปกติไม่เห็น — สำคัญมากกับ malware/packed
  • string ที่ถูก XOR/encode → FLOSS หรือ reverse routine ใน decompiler
  • string build ทีละ byte บน stack → เห็นใน decompiler (mov byte) หรือ FLOSS
  • strings ว่างเปล่าผิดปกติ → อาจ packed (ดู section 5)

5. ถ้า strings ว่าง — อาจ packed

ถ้า strings ออกมาน้อยผิดปกติ (ไม่มี string ที่มีความหมายเลย) binary อาจถูก pack (บีบอัด/เข้ารหัส แล้ว unpack ตอน run)

ตรวจและ unpackLinux
# ตรวจว่า packed ไหม
strings binary | grep -i UPX        # เห็น UPX = packed ด้วย UPX
rabin2 -I binary | grep -i packer
binwalk binary                      # ดู entropy/sections

# unpack UPX
upx -d binary -o unpacked
# packer อื่น → unpack ตอน runtime (dump จาก memory) หรือ debugger
high entropy + ไม่มี string = packed; UPX unpack ง่าย (upx -d); packer อื่นต้อง dump จาก memory

6. Quick Reference

  • ขั้นแรกของ reversing — เร็ว บางทีเจอ flag เลย
  • strings -n 8 binary (ตัด noise); -t x (offset)
  • strings -e l (Unicode/Windows wide char) — อย่าลืม!
  • กรอง: grep -iE 'flag|pass|key'; -oE 'CTF\{[^}]+\}'
  • string ซ่อน → FLOSS (decode/stack strings)
  • strings ว่าง → packed (UPX: upx -d; อื่น: dump memory)
  • rabin2 -z = strings ตาม section

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

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

  1. 1file ./binary — ดู type (ELF/PE), architecture, stripped หรือไม่
  2. 2chmod +x ./binary เผื่อต้องรัน (ยังไม่ต้องรันจริงตอนนี้ก็ได้)
  3. 3strings -n 8 ./binary | less ดูคร่าวๆ ก่อนว่ามีอะไรน่าสนใจ
  4. 4strings ./binary | grep -iE 'flag|ctf|key|pass|secret'
  5. 5ถ้าเจอ pattern คล้าย flag (เช่น CTF{...}) ตรงๆ = จบเลย ส่งคำตอบได้
  6. 6ถ้าไม่เจอ ลอง strings -e l ./binary (Unicode/wide char — บาง binary Windows ไม่โผล่ใน ASCII ปกติ)
  7. 7ลอง rabin2 -z ./binary หรือ rabin2 -zz ./binary (แยก string ตาม section)
  8. 8เช็ค packed: ถ้า strings ออกมาน้อยผิดปกติ (แทบไม่มี string ที่มีความหมาย) ให้รัน binwalk ./binary
  9. 9ถ้าเจอ UPX ให้ upx -d ./binary -o unpacked แล้วย้อนไป strings ใหม่
  10. 10ถ้าไม่ packed แต่ยังไม่เจอ flag ตรงๆ ให้เปิด ghidra ดู logic ต่อ
หา flag จาก strings ทีละขั้น
file ./binary — ดู arch, ELF/PE, stripped?
strings -n 8 ./binary | grep -iE 'flag|ctf|key|pass|secret'
✅ เจอ flag format ตรงๆ (เช่น CTF{...})→ ส่งคำตอบเลย จบเกม
❌ string น้อยผิดปกติ/แทบว่างเปล่า→ สงสัยว่า packed ไปเช็คก่อน
❌ เจอ string เยอะแต่ไม่มี flag ตรงๆ→ ไปดู logic ในตัว decompiler ต่อ
เช็ค packed: binwalk ./binary; rabin2 -I ./binary | grep -i packer
✅ เจอ UPX→ upx -d ./binary -o unpacked แล้วย้อนไป strings ใหม่
❌ ไม่ใช่ UPX/ไม่รู้ packer→ unpack เองไม่ไหว ต้อง dump runtime แทน
ขั้นตอน/งานเครื่องมือใน Kaliติดตั้งเพิ่ม (ถ้าไม่มี)เครื่องมือออนไลน์
ดูชนิดไฟล์/archfile--
ดึงข้อความอ่านได้strings, rabin2apt install radare2CyberChef
หา string ที่ถูกซ่อน/decode runtime-pipx install flare-floss-
เช็ค packed/entropybinwalkapt install binwalk-
unpack UPXupxapt install upx-ucl-
เปิดดู logic ต่อghidraapt install ghidradogbolt.org
ถอดรหัส/แกะ base64 ที่เจอในสตริงbase64-CyberChef
เดายี่ห้อ/ถอด hash ที่เจอ--hashes.com
🚑 ถ้าตันสนิท ลองท่าถัดไป: static-analysis — string ไม่มี flag ตรง ต้อง triage imports/sections ต่อ; ghidra — เจอ string 'Correct'/'flag' แล้วอยากดู xref เข้าใจ logic; dynamic-analysis — packed/unpack เองไม่ได้ ต้องดูค่าตอนรันจริง; anti-debug — สงสัยว่ามีการกันไม่ให้วิเคราะห์; binary-patching — เข้าใจ logic แล้วแค่ต้องการผ่าน check

โน้ตของฉัน

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