การวิเคราะห์วิศวกรรมย้อนกลับ Ecco the Dolphin ด้วย Ghidra และ Python
(32bits.substack.com)- ใน Ecco the Dolphin: Defender of the Future สำหรับ Dreamcast มีสูตรโกงที่ซ่อนอยู่ซึ่งเปิดใช้งานผ่านการกรอกชื่อย่อในไฟล์เซฟ และนอกจาก
GYUGYU+XXXที่เคยรู้จักกันแล้ว ยังพบอินพุตพิเศษอื่น ๆ อีกหลายแบบ - การวิเคราะห์ทำโดยโหลดสแนปช็อตหน่วยความจำของ flycast เข้าไปใน Ghidra เพื่อค้นหาบัฟเฟอร์อินพุตและฟังก์ชันประมวลผล จากนั้นไล่ตามโครงสร้างที่นำผลลัพธ์จากการแปลงไปเปรียบเทียบกับค่าพิเศษ 6 ค่า
- การตัดสินว่าเป็นสูตรโกงไม่ได้ดูจากสตริงอินพุตโดยตรง แต่ทำจากค่าที่ได้หลังถอดรหัสคีย์ด้วยพาสเฟรสและคำนวณ checksum แล้ว จึงหาได้ยากด้วยวิธีอ่านสตริงตรง ๆ
- ใช้ Python brute force ตรวจอินพุตความยาว 1~8 ตัวอักษร และยืนยันว่า
SOCCER,EXBBERX,QQRIQ,XYZZYX,POPELYเป็นต้น เชื่อมโยงกับด่านโบนัส, โหมดอมตะ, การแสดง FPS และการแสดงเวลา - อินพุตที่ให้ผลแบบเดียวกันไม่ได้ถูกกำหนดไว้ตายตัวเป็นค่าเดียว โดย
NNSET,SOCCER,ADEMVSSFล้วนเปิดเกมฟุตบอลโบนัส และAFTJSXOTก็ปลดล็อกทุกด่านได้เหมือนGYUGYU
สูตรโกงที่ซ่อนอยู่ซึ่งเปิดด้วยชื่อไฟล์เซฟ
- Ecco the Dolphin: Defender of the Future เป็นเกม Ecco ภาคสุดท้ายที่วางจำหน่ายอย่างเป็นทางการ ส่วนภาคต่อถูกยกเลิกไป
- สูตรโกงที่รู้จักกันอยู่เดิมคือเลือก New Game บนหน้าจอ VMU แล้วกรอก
GYUเป็นชื่อย่อ จากนั้นไม่กด End แต่กรอกGYUอีกครั้งพร้อมตัวอักษรใด ๆ อีกสามตัว- เมื่อกรอกในรูปแบบ
GYU GYU XXXแล้วออกจากเมนู จะสามารถเลือกทุกด่านได้ใน Load game
- เมื่อกรอกในรูปแบบ
- อินพุตพิเศษและผลลัพธ์ที่ยืนยันแล้วมีดังนี้
GYUGYU+XXX: ปลดล็อกทุกเลเวลSOCCER+XXX: ปลดล็อกด่านโบนัสEXBBERX+XXX: โหมดอมตะQQRIQ+XXX: แสดง FPSXYZZYX+XXX: แสดงเวลาPOPELY+XXX: ยังไม่ทราบผล
ไล่ตามรูทีนประมวลผลอินพุตด้วย Ghidra
- จาก สแนปช็อตหน่วยความจำ ของอีมูเลเตอร์ flycast พบว่าส่วนหนึ่งของชื่อย่อที่เห็นบนหน้าจอถูกเก็บไว้ในบัฟเฟอร์
8cfffb34 - เมื่อกรอกต่อไป ตัวอักษรที่ใส่ก่อนหน้าจะถูกดันเข้าไปยังบัฟเฟอร์
8c3abf18และพื้นที่นี้ถูกใช้ในการตรวจสูตรโกง - หลังโหลดสแนปช็อตเข้าไปใน Ghidra พบว่าฟังก์ชันที่ตำแหน่ง
8c0334d8อ่านบัฟเฟอร์ดังกล่าว - ฟังก์ชันนี้แปลงบัฟเฟอร์ แล้วตรวจว่าผลลัพธ์เป็นหนึ่งในรายการ ค่าพิเศษ 6 ค่าหรือไม่
GYU GYU XXXถูกแปลงเป็น9388D627และตรงกับค่าพิเศษตัวแรกในรายการ
วิธีแปลงและโครงสร้าง checksum
- ลำดับการทำงานของฟังก์ชันแปลงที่ยืนยันจากการ decompile ใน Ghidra มีดังนี้
- อ่านพาสเฟรส
- ถอดรหัสคีย์ขนาด 1024 ไบต์ด้วยพาสเฟรส
- ใช้คีย์คำนวณ checksum ของบัฟเฟอร์อินพุต
- เข้ารหัสคีย์กลับ
- checksum เป็นฟังก์ชันทางเดียว จึงยากที่จะคำนวณย้อนกลับจากค่าพิเศษด้วยสายตาเพื่อหาอินพุต
- ในอัปเดตภายหลัง metalliczx และ SideQuark ยืนยันว่าโครงสร้างหลังถอดรหัสคือ พหุนาม checksum แบบ CRC32 มาตรฐาน
- ด้วยเหตุนี้จึงมีวิธีหาค่าเป้าหมายที่มีประสิทธิภาพกว่า brute force
อินพุตที่พบด้วยการ brute force ใน Python
GYUGYUมี 6 ตัวอักษร และชุดอักขระ 6 ตัวที่เป็นไปได้มี26^6 = 308,915,776ชุด- ความยาว 7 ตัวอักษรเพิ่มเป็น 8 พันล้านชุด และ 8 ตัวอักษรเพิ่มถึง 208 พันล้านชุด ซึ่งเป็นขนาดที่หนักสำหรับแล็ปท็อป
- การ implement ด้วย Python ตรวจอินพุตตามขั้นตอนต่อไปนี้
- คัดลอกบล็อกหน่วยความจำที่มีบัฟเฟอร์อินพุตซึ่งยังไม่ได้ initialize, พาสเฟรส และคีย์
- ถอดรหัสคีย์ด้วยพาสเฟรส
- ใส่ลำดับตัวอักษร 1~8 ตัวลงในบัฟเฟอร์อินพุต
- คำนวณ checksum ของแต่ละอินพุต
- เปรียบเทียบผลลัพธ์ที่คำนวณได้กับค่าเป้าหมาย
- โค้ดทั้งหมดเผยแพร่ไว้ที่ gist
- เพียงเวอร์ชันเธรดเดียวก็พิมพ์ผลลัพธ์ที่ต้องการออกมาแล้ว และผลลัพธ์ก็ออกมาก่อนที่จะเขียนเวอร์ชันขนานเสร็จ
mapping ที่พบและผลจริง
- คอลัมน์สุดท้ายของผลลัพธ์แสดงว่าตรงกับ ค่าพิเศษ ค่าใด
NNSET,SOCCER,ADEMVSSFล้วนตรงกับค่าเดียวกัน และปลดล็อกเกมฟุตบอลโบนัสAFTJSXOTปลดล็อกทุกด่านได้เหมือนGYUGYU
- เมื่อกรอก
SOCCER+XXXเป็นชื่อย่อ จะเปิด Bonus Game และสามารถเล่นฟุตบอลใต้น้ำได้- ตั้งค่าบิต
0x2ในแฟล็กที่8c3ac00c
- ตั้งค่าบิต
EXBBERX+XXXแสดง Immortality Enabled บนหน้าจอ Options- ระหว่างเปิดใช้งาน จะไม่จมน้ำหรือไม่ตาย
- ตั้งค่าบิต
0x400ในแฟล็ก8c3abe48และบิต0x4ในแฟล็ก8c3abb00
QQRIQ+XXXแสดงเฟรมเรตของเกมและค่าดีบักบางส่วนXYZZYX+XXXแสดงค่านาฬิกาปัจจุบัน- อินพุตทั้งสองเปลี่ยนค่าที่แอดเดรส
8c35659cและ8c3565a4
- อินพุตทั้งสองเปลี่ยนค่าที่แอดเดรส
- ยังยืนยันผลของ
POPELY+XXXไม่ได้- คาดว่าเป็นความพยายามเปิดใช้งานแฟล็กที่
8c3b0e44แต่แฟล็กนี้เพียงแสดงข้อความ Cheats Enabled และไม่เห็นผลอื่น
- คาดว่าเป็นความพยายามเปิดใช้งานแฟล็กที่
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
แฮชก็คือ CRC32 เฉย ๆ และพูดให้ชัดคือใช้พหุนามตัวนี้ (0x77073096, โค้ดผิด)
https://web.mit.edu/freebsd/head/sys/libkern/crc32.c
จำนวนเต็มที่ถอดรหัสในบทความคือค่าคงที่ของ CRC32 นี้ ถ้ารู้ว่าเป็น CRC32 และรู้พหุนาม ก็สามารถใช้คณิตศาสตร์โมดูลาร์บนวงแหวนพหุนามเพื่อย้อนคำนวณคำตอบได้ใน เวลาแบบลอการิทึม ไม่ใช่เวลาแบบเอ็กซ์โปเนนเชียล
เห็นว่ากันว่า Binwalk รู้จักตารางพหุนาม CRC เลยสงสัยว่าจะหาเจอตารางนี้ด้วยไหม
ควรมีใครสักคนผสาน Binwalk กับ Ghidra เข้าด้วยกัน สองตัวนี้เข้ากันได้ดีมาก
สงสัยว่ามีเคล็ดลับอะไรในการรู้ว่าค่าเป็น ผลลัพธ์ CRC32 หรือรู้พหุนาม/ค่าเริ่มต้นที่ใช้ไหม
ตอน Ecco ภาคต้นฉบับออกบน Megadrive (Genesis) ผมใช้เงินที่เก็บมาอย่างยากลำบากทั้งหมดซื้อมา เกมนั้นยากแบบไม่สมเหตุสมผล และผมนั่งหัวเสียอยู่กับปากกากับกระดาษทั้งบ่าย จนหาทาง ถอดระบบรหัสผ่าน ได้ในที่สุด
ผมวาร์ปไปด่านสุดท้ายแล้วเคลียร์ได้ในวันถัดมา แต่ก็รู้สึกผิดที่ใช้ทรัพย์สินทั้งหมดไปกับเกมที่จบได้ในสองวัน
ถอดระบบรหัสผ่านด้วยปากกากับกระดาษนี่ ถ้ายังจำอะไรได้ อยากฟังเพิ่มมาก
ถ้ามองเชิงปรัชญา ผมว่าแบบนั้นไม่นับว่าเคลียร์เกม
คุณข้ามไปหลายด่าน และได้เห็นแค่บางส่วนของคอนเทนต์ เกมเพลย์ และเรื่องราวที่ตั้งใจทำไว้ เกมต่าง ๆ รวมถึง Ecco the Dolphin โดยมากแล้วการเดินทางสำคัญกว่าจุดหมาย คุณพลาดธีมและประสบการณ์อย่างความโดดเดี่ยว การเป็นเพื่อนกับคนนอกกลุ่ม การอนุรักษ์ การเดินทางข้ามเวลา การสื่อสารกับไดโนเสาร์ และแน่นอนว่าการเดินทางในอวกาศ
ดังนั้นก็ไม่จำเป็นต้องรู้สึกผิดขนาดนั้น
แต่ ด่านสุดท้าย ก็สุดยอดมากอยู่ดี สงสัยว่าตอนเห็นหลังจากข้ามส่วนใหญ่ของเกมไปจะรู้สึกทึ่งไหม
ไม่ว่าจะใช้ชีตหรือไม่ คุณอาจเป็นคนเดียวในโลกที่เคลียร์เกมนี้ได้ก็ได้
QQRIQ เป็นรูปย่อเชิงเสียงของ “kukuriku” และหมายถึงเสียงไก่ขันในภาษาฮังการีและอีกหลายภาษา เช่น “kukuryku” ในภาษาโปแลนด์ และ “קוקוריקו” ในภาษาฮีบรู
ทำให้สงสัยว่ากระบวนการเลือกรหัสผ่านเป็นอย่างไร
Gyugyu ก็อาจเป็นการอ้างอิงถึงภาพยนตร์ฮังการีเรื่อง “The Fifth Seal” ได้
“ลองจินตนาการว่าคุณกำลังจะตาย และจะได้กลับชาติมาเกิดเป็นหนึ่งในสองคน คนหนึ่งเป็นทาส อีกคนเป็นนายผู้มั่งคั่ง ทาสถูกนายทรมาน สูญเสียลิ้นและตาข้างหนึ่ง ภรรยาและลูกก็ถูกฆ่า เขายังคงใช้ชีวิตต่อไปโดยเชื่อว่าตัวเองเป็นคนดี เพราะเขาไม่เคยทำเรื่องโหดร้ายและซาดิสต์กับคนอื่นอย่างนาย ส่วนเจ้านายผู้มั่งคั่งไม่มีความละอายทางศีลธรรมเลย เขาไม่คิดว่าสิ่งที่ตนทำผิด และเชื่อว่าทาสสมควรถูกลงโทษ คุณต้องเลือกว่าจะเป็นทาสที่ยากจนแต่ชอบธรรม หรือเป็นนายที่มั่งคั่งแต่เสื่อมทราม”
Gyugyu คือชื่อของทาสคนนั้น
https://www.imdb.com/title/tt0075467
โปรแกรมเมอร์ของเกมนี้อยู่ที่ Budapest ก็เลยเป็นข้อสันนิษฐานที่ค่อนข้างน่าเชื่อ
Popely ที่มี “ly” แบบภาษาฮังการีก็เป็นเบาะแสเหมือนกัน
ภาษาฝรั่งเศสคือ Cocorico เลยคล้ายกันมาก
ทำให้นึกถึงหมู่บ้าน Kakariko ใน Zelda ที่มีไก่โผล่มาตลอด
เกร็ดที่น่าสนใจคือ เมื่อมีคนถาม Ed Annunziata ผู้พัฒนา Ecco ถึงแรงบันดาลใจ เขาตอบว่า “ผมไม่เคยใช้ LSD แต่ผมอ่าน John C. Lilly เยอะมาก” Lilly เป็นที่รู้จักจากงานบุกเบิกด้านสติปัญญาของสัตว์ จิตบำบัดด้วยคีตามีน ถังตัดประสาทสัมผัส และการสำรวจจิตสำนึก
ชื่อ “Ecco” เป็นการอ้างอิงถึง ECCO (Earth Coincidence Control Office) ของ Lilly John ตั้งสมมติฐานว่ามีฐานเหนือธรรมชาติ/ต่างดาวอยู่ด้านไกลของดวงจันทร์ เพื่อประสาน “ความบังเอิญ” ทั้งหมดบนโลก เขาเป็นหนึ่งในคนยุคแรก ๆ ที่มองเห็นว่าโลมาฉลาดเพียงใด และหมกมุ่นกับการหาวิธีสื่อสารกับโลมา ถึงขั้นทำให้บ้านของตัวเองในแคริบเบียนครึ่งหนึ่งจมน้ำเพื่ออาศัยอยู่กับโลมา นี่เป็นแค่ยอดภูเขาน้ำแข็งเท่านั้น ถ้าสนใจ ผมแนะนำอัตชีวประวัติของเขา The Center of the Cyclone อย่างยิ่ง เขาเป็นบุคคลที่น่าหลงใหลจริง ๆ
สงสัยว่ามีแหล่งข้อมูลสำหรับเริ่ม วิศวกรรมย้อนกลับ เกม Dreamcast ไหม มีหลายอย่างที่อยากลองกับ Skies of Arcadia และอยากได้เทคนิคที่เป็นระบบกว่าการ “ดูว่าค่าอะไรเปลี่ยนไประหว่างสแนปช็อตหน่วยความจำ”
วิธีนั้นแทบจะเป็นเทคนิคมาตรฐานในการหาตำแหน่งของค่าใน RAM แล้ว จริง ๆ แล้วใช้ได้ค่อนข้างดี
อีมูเลเตอร์บางตัวอย่าง Dolphin มีเครื่องมือแบบนั้นในตัว เครื่องมือแฮ็กเกมยุคเก่าอย่าง Gameshark สำหรับ N64 ก็ใช้เทคนิคเดียวกันผ่าน UI บนคอนโซล ไม่รู้ว่าอีมูเลเตอร์ Dreamcast มีเครื่องมือแบบนั้นไหม
ผมเคยเขียนบทความที่ใช้เทคนิคนี้ใน Dolphin และบทความต่อเนื่องก็เกี่ยวกับการแฮ็กเกมคอนโซลด้วย Ghidra: https://www.smokingonabike.com/2021/01/17/hacking-super-monk...
เคยลองดูเกมนั้นนิดหน่อย เคล็ดลับหลักคือ ดัมป์สแนปช็อตหน่วยความจำ เป็นไฟล์ แล้วนำเข้า Ghidra วิธีดัมป์มีหลายแบบ และหลายคนก็ชอบ Cheat Engine
Ghidra วิเคราะห์ภาษาเครื่องของโปรเซสเซอร์ SuperH ได้แบบเนทีฟ ดังนั้นแค่รันการวิเคราะห์อัตโนมัติก็จะเห็นฟังก์ชันจำนวนมากแล้ว
ช่วงไม่กี่ปีมานี้ ผมรู้สึกดึงดูดเกมเก่ามากขึ้นเยอะ และไม่รู้ว่าพูดแบบนี้สมเหตุสมผลไหม แต่รู้สึกว่ามันมี จิตวิญญาณ มากกว่าเยอะ
แล้วก็เสียใจกับเรื่องรถนะ ขอบคุณสำหรับคำเตือน ต่อไปจะไม่จอดทิ้งไว้ที่ทางเข้าบ้านแล้วปล่อยเครื่องเดินเบาอีก
ผมสงสัยมาตลอดว่าควรเริ่มเรียนวิศวกรรมย้อนกลับจากตรงไหน ส่วนใหญ่บอกให้เรียน แอสเซมบลี ก่อน แต่หลังจากนั้นดูเหมือนออนไลน์จะมีข้อมูลที่เป็นรูปธรรมไม่มากนัก
ไม่รู้ว่าต้องค่อย ๆ เรียนรู้แพตเทิร์นที่พบบ่อยใน x86, arm และแพลตฟอร์มอาร์เคดผ่านการลองผิดลองถูกหรือเปล่า หาอภิปรายที่ลงรายละเอียดออนไลน์ได้ยาก
การใช้เครื่องมืออย่าง Ghidra ช่วยให้ค่อย ๆ จับคู่กับซอร์สได้ทีละนิด แต่สุดท้ายก็ต้องอนุมานในแบบเดียวกับตอนทำความเข้าใจโค้ดเบสที่ไม่คุ้นเคย ความต่างคราวนี้คือไม่มีคอมเมนต์เลย แต่โปรเจกต์ที่เปิดซอร์สก็มีไม่น้อยที่ไม่มีคอมเมนต์เหมือนกัน
ถ้าอยากลองตัวอย่างที่ใกล้เคียงความเป็นจริงกว่า แนะนำให้ลองแก้โจทย์ที่ http://microcorruption.com หรือ https://crackmes.one/
ส่วนตัวได้เรียนรู้อะไรเยอะจากการลองเล่น Cheat Engine สมัยเด็กใช้บ่อยแล้วไม่ได้กลับไปดูอีก เลยไม่รู้ว่าจริง ๆ แล้วมันเป็นเครื่องมือที่ทรงพลังกว่าที่คิดมาก
ตัว disassembler ก็ใช้ได้ดีพอสมควร และสามารถเขียนสิ่งที่เรียกว่า “assembly scripts” ได้ จึงเหมาะกับการเรียนพื้นฐานการแพตช์หน่วยความจำด้วย x86 assembly จากจุดนั้นก็เริ่มสร้างยูทิลิตีของตัวเองสำหรับแพตช์เกมตามต้องการได้
แค่ Cheat Engine อย่างเดียวก็แพตช์เกมจนทำชีตระดับบ้าคลั่งได้แล้ว
เคยเรียนในโรงเรียนมาบ้าง แต่การเอาวิดีโอเกมที่จำได้ตอนเด็กมา รันทีละสเต็ปด้วยดีบักเกอร์ สอนวิทยาการคอมพิวเตอร์ได้ดีกว่าสิ่งที่เรียนในห้องเรียนมาก
อยากดูวิดีโอที่ ชีตฟุตบอลใต้น้ำ ใช้งานได้จริง
น่าสนใจที่เกมคล้าย ๆ กันใช้วิธีทำให้ checksum ตรงกับจำนวนเต็มคงที่ Pitfall: The Lost Expedition ก็ใช้วิธีคล้ายกันมาก คือแปลงอินพุตปุ่มเป็นสตริง ASCII ของปุ่มที่กด แล้วคำนวณ CRC
วิธีเข้าถึงก็เป็นการเกือบ brute force ด้วย Python แล้วเทียบกับ แฮชชีต ที่ดึงออกมาได้ นอกจากนี้ยังเห็นตาราง CRC32 ที่ซ่อนอยู่ใน
decrypted_intsด้วย ตารางที่สร้างไว้ล่วงหน้าค้นหาเจอได้ง่ายเกินไป เลยสงสัยว่าทำไมแทนที่จะสร้างตารางใหม่ด้วยพหุนามของตัวเอง กลับมักพบว่ามันถูกทำให้อ่านยากเพื่อให้ยากขึ้นน่าทึ่งที่มีบล็อกที่โฟกัส Sega Saturn
ไม่นานมานี้เจอ Saturn กับแผ่นเกม CD ชุดเล็ก ๆ ในตู้เสื้อผ้าที่บ้านพ่อแม่ จำไม่ได้ว่าเคยมี เลยเดาว่าน้องคงได้มาตอนหลังจากที่ฉันไปเรียนมหาวิทยาลัยแล้ว อย่างไรก็ดี ลองต่อดูแล้วทุกเกมยังทำงานได้ดี แต่除此นั้นก็ไม่รู้เลยว่าจะเอาไปทำอะไรดี แน่นอนว่าการทิ้งไม่ใช่ตัวเลือก
เกมพวกนี้ มีมูลค่าสูงมาก ปี 2005 ฉันยกของตัวเองให้คนอื่นไปเฉย ๆ แต่พอไปดูราคาบน eBay ตอนนี้แล้วใจเต้นแรงเลย
ก็เล่นให้สนุกก็พอ
https://terraonion.com/en/producto/terraonion-mode/