ROT13 / ROT47
ROT คือการ 'หมุน' ตัวอักษร/อักขระไปตามจำนวนคงที่แล้ววนรอบ เป็น Caesar cipher รูปแบบเฉพาะ: ROT13 หมุน 13 บน a-z (self-inverse), ROT5 หมุน 5 บนตัวเลข 0-9, ROT18 = ROT13+ROT5 รวมกัน, ROT47 หมุน 47 บนช่วง ASCII printable 94 ตัว ทั้งหมดเป็น self-inverse (เข้ารหัส = ถอดรหัส) และพบบ่อยเป็นด่านอุ่นเครื่องหรือชั้นหนึ่งของ encoding ซ้อนชั้น บทนี้ครอบคลุมทุกตัวแปร วิธีรู้จำ คำสั่งถอด (tr/python/CyberChef) และ nested rotation
1. ROT ตระกูลต่างๆ
ROT (rotate) หมุนอักขระไปตามจำนวนคงที่ภายในช่วงหนึ่งแบบวนรอบ (modulo ขนาดช่วง) — มันคือ Caesar cipher นั่นเอง แต่ตั้งชื่อตามจำนวน shift และช่วงที่ใช้ ตัวแปรที่พบใน CTF มีดังนี้ จุดร่วมสำคัญคือทุกตัว shift = ครึ่งหนึ่งของขนาดช่วง จึงเป็น self-inverse: เข้ารหัสและถอดรหัสใช้การดำเนินการเดียวกัน
| ตัวแปร | ช่วงที่หมุน | shift | self-inverse |
|---|---|---|---|
| ROT13 | a-z A-Z (26 ตัว) | 13 | ใช่ (13 = 26/2) |
| ROT5 | 0-9 (10 ตัว) | 5 | ใช่ (5 = 10/2) |
| ROT18 | a-z A-Z + 0-9 | 13 ตัวอักษร + 5 ตัวเลข | ใช่ |
| ROT47 | ASCII 33–126 (94 ตัว) | 47 | ใช่ (47 = 94/2) |
ROT13 เป็นตัวที่พบบ่อยที่สุด: flag → synt, the → gur (จำ gur ได้จะรู้ทันทีว่าเป็น ROT13) ROT5 ใช้กับตัวเลขล้วน (12345 → 67890) ROT18 รวม ROT13 กับ ROT5 เข้าด้วยกัน หมุนตัวอักษร 13 และตัวเลข 5 พร้อมกัน ROT47 ครอบคลุมทั้งช่วง printable รวมสัญลักษณ์ จึงเหมาะเมื่อข้อความมี !@#{} ปน
2. วิธีรู้จำว่าเป็น ROT ตัวไหน
- a-z ล้วน (ไม่มีตัวเลข/สัญลักษณ์) → ลอง ROT13 ก่อน; ถ้าไม่ออก brute Caesar 25 shift
- ตัวเลขล้วน → ROT5
- ตัวอักษร + ตัวเลขปน แต่ไม่มีสัญลักษณ์อื่น → ROT18
- มีสัญลักษณ์ !@#$%{} ปนเยอะ → ROT47 (เพราะ ROT13/5 ไม่แตะสัญลักษณ์)
- เห็นคำว่า
gur(=the),vf(=is),synt(=flag) → ROT13 แน่นอน - ข้อความมี
{}แต่ตัวในวงเล็บอ่านไม่ออก และรอบๆ เป็นสัญลักษณ์ → ROT47
flag คือ synt และ ROT13 ของ CTF คือ PGS — ถ้าเห็น synt{ หรือ PGS{ ในโจทย์ ตอบ ROT13 ได้เลย3. คำสั่งถอด
# ถอด/เข้า ROT13 (คำสั่งเดียวกัน เพราะ self-inverse)
echo 'Uryyb Jbeyq' | tr 'A-Za-z' 'N-ZA-Mn-za-m'
# -> Hello World
# ROT5 บนตัวเลขด้วย tr
echo '12345' | tr '0-9' '5-90-4'
# -> 67890
# ROT13 ทั้งไฟล์
tr 'A-Za-z' 'N-ZA-Mn-za-m' < cipher.txtimport codecs
# ROT13 (built-in)
print(codecs.encode("Uryyb Jbeyq", "rot13")) # -> Hello World
# ROT47
def rot47(s):
out = []
for c in s:
o = ord(c)
if 33 <= o <= 126:
out.append(chr(33 + (o - 33 + 47) % 94))
else:
out.append(c) # อักขระนอกช่วง เก็บไว้เดิม
return "".join(out)
print(rot47('%C6H:?8')) # self-inverse: เรียกซ้ำได้ค่าเดิม
# ROT5 (ตัวเลข) + ROT18 (ตัวอักษร+ตัวเลข)
def rot_n(s, n_alpha=13, n_dig=5):
out = []
for c in s:
if c.isupper(): out.append(chr((ord(c)-65+n_alpha)%26+65))
elif c.islower(): out.append(chr((ord(c)-97+n_alpha)%26+97))
elif c.isdigit(): out.append(chr((ord(c)-48+n_dig)%10+48))
else: out.append(c)
return "".join(out)
print(rot_n("Uryyb123", 13, 5)) # ROT18ROT13 (ปรับ amount ได้ = ทำ Caesar shift ใดก็ได้), ROT13 Brute Force (พ่นทุก shift), ROT47 และ ROT8000 ลากวางเทสต์ได้เร็ว ส่วน dcode.fr มีหน้าเฉพาะสำหรับแต่ละตัวแปร4. Nested / ซ้อนชั้นกับ encoding อื่น
แพทเทิร์นคลาสสิกใน CTF คือ ROT ถูกซ้อนกับ encoding อื่นหลายชั้น เช่น Base64 → ROT13, ROT13 → Hex, หรือ ROT47 → Base64 ต้องไล่ decode ทีละชั้นจนอ่านออก จุดสำคัญคือ ROT13 กับ Base64 มักถูกสับสน เพราะทั้งคู่ให้ผลเป็นตัวอักษร a-z/A-Z ให้ดูว่ามี = ท้าย หรือมีตัวเลข/+// ปน (บ่งชี้ Base64) หรือเป็นตัวอักษรล้วน (บ่งชี้ ROT)
import base64, codecs
data = "Vm0wd..." # ciphertext ที่ได้มา
# ลองไล่ทีละชั้น: base64 -> rot13
step1 = base64.b64decode(data).decode()
step2 = codecs.encode(step1, "rot13")
print(step2)
# ถ้ายังไม่ออก ลองสลับลำดับ / เพิ่มชั้น hex
# bytes.fromhex(...) , base64.b64decode(...) , codecs.encode(..., 'rot13')Magic (มี option 'Intensive mode') จะไล่ลอง decode หลายชั้นให้อัตโนมัติ รวมถึง ROT/Base/Hex — เป็นตัวช่วยที่ดีที่สุดเมื่อไม่รู้ว่าซ้อนกี่ชั้นและลำดับใด5. รูปแบบโจทย์ CTF
- ROT13 ตรงๆ:
synt{...}→ ROT13 →flag{...}ด่านอุ่นเครื่อง - ROT47: ข้อความมีสัญลักษณ์ปน เช่น
u=B8m...→ ROT47 ได้ flag - ROT18: ข้อความมีตัวอักษร+ตัวเลขที่ทั้งคู่ถูกเลื่อน (ตัวเลขก็เพี้ยน) → ROT18
- ซ้อนชั้น: Base64 → ROT13, หรือ ROT13 → Base64 → ต้อง decode หลายชั้น
- shift ไม่ใช่ 13: ROT13 ไม่ออก → เป็น Caesar shift อื่น → brute 25 (ดูหัวข้อ caesar)
6. Quick Reference
- ROT13 = Caesar k=13 บน a-z, self-inverse (เข้า=ถอด)
- ROT5 = ตัวเลข 0-9 · ROT18 = ROT13+ROT5 · ROT47 = ASCII 33-126
- a-z ล้วน → ROT13 · มีสัญลักษณ์ปน → ROT47 · ตัวเลข → ROT5
tr 'A-Za-z' 'N-ZA-Mn-za-m'= ROT13codecs.encode(s, 'rot13')ใน Python- จำ:
gur=the,synt=flag,PGS=CTF → ROT13 - อ่านตัวอักษรได้แต่ไม่เป็นคำ → อาจซ้อนชั้น (Base64/Hex) → CyberChef Magic
- ROT13 ไม่ออก + a-z ล้วน → brute Caesar 25 shift (ดูหัวข้อ caesar)
🧭 จับมือทำทีละขั้น (มีแค่ Kali) + ถ้าติดไปไหนต่อ
สมมติเจอ ciphertext ที่ดู 'หมุน' ตัวอักษรอยู่แบบนี้ มีแค่เครื่อง Kali เปล่าๆ ไม่รู้จะเริ่มยังไง ทำตามขั้นตอนนี้ทีละสเต็ป
- 1ดู charset ของข้อความก่อน: `cat chal.txt` — เป็น a-z ล้วน? ตัวเลขล้วน? ตัวอักษร+ตัวเลขปน? หรือมีสัญลักษณ์ `!@#{}` ปนเยอะ
- 2a-z ล้วน → ลอง ROT13 ก่อนเสมอ: `echo '...' | tr 'A-Za-z' 'N-ZA-Mn-za-m'` (self-inverse ใช้คำสั่งเดียวถอดได้เลย)
- 3ตัวเลขล้วน → ลอง ROT5: `echo '12345' | tr '0-9' '5-90-4'`
- 4ตัวอักษร+ตัวเลขปนแต่ไม่มีสัญลักษณ์อื่น → ลอง ROT18 (เขียน python สั้นๆ ตามโค้ดด้านบน หรือ dcode.fr/rot-18)
- 5มีสัญลักษณ์ปนเยอะ → ลอง ROT47 ด้วย python function หรือ CyberChef operation 'ROT47'
- 6ยังไม่ออก → เปิด https://gchq.github.io/CyberChef วาง ciphertext ใน Input แล้วลาก operation 'Magic' มาวาง เปิด 'Intensive mode' ให้มันไล่เดา recipe (ROT/Base64/Hex ซ้อนกัน) อัตโนมัติ
- 7เจอตัวอักษรอ่านได้แต่ไม่เป็นคำ (เช่นมี `=` ท้าย หรือมีเลข/`+`/`/` ปน) → สงสัยว่าเป็น Base64 ซ้อนอยู่ ลอง decode ชั้นนอกก่อนด้วย `base64 -d` แล้วค่อยกลับมาลอง ROT
- 8ลองครบทุกตัวแปร ROT แล้วยังไม่ออก → สงสัยว่า shift ไม่ใช่ 13/5/47 (เป็น Caesar shift อื่น) → ไปทำ brute ทั้ง 25 shift ที่หัวข้อ Caesar
- 9ได้ผลอ่านออกแล้ว → เช็ค flag format ให้ตรงกับที่โจทย์กำหนด แล้วส่งคำตอบ
| ขั้นตอน/งาน | เครื่องมือใน Kali | ติดตั้งเพิ่ม (ถ้าไม่มี) | เครื่องมือออนไลน์ |
|---|---|---|---|
| ดู charset ของข้อความ | cat, file | - | - |
| ถอด ROT13 | tr, python3 (codecs) | - | gchq.github.io/CyberChef (ROT13) |
| ถอด ROT47 | python3 | - | CyberChef (ROT47) |
| ถอด ROT5 (ตัวเลข) | tr | - | dcode.fr/rot-5 |
| ถอด ROT18 | python3 | - | dcode.fr/rot-18 |
| เดา recipe อัตโนมัติ (ซ้อนชั้น) | - | - | CyberChef (operation Magic, Intensive mode) |
| Caesar shift อื่นที่ไม่ใช่ 13 | python3 | - | dcode.fr/caesar-cipher |
โน้ตของฉัน
ยังไม่มีโน้ตสำหรับหัวข้อนี้