เปิด Hex ดู Signature นู่นนี่นั่น
จริงๆ Google เจอว่า เฮีย luigi แห่ง quickbms
ทำไว้แล้ว (ยังสดๆ ณ วันที่ 7/6/2558)
แต่ตอน unpack มาไฟล์มันเสีย และ structure ของ folder
มันดูรวนๆ
ไม่ตรงกับที่เห็นใน hex ของ exe
แต่ก็ยังได้ประโยชน์เพราะเราจะรู้ structure ของ ไฟล์ pack
โดยที่ไม่ต้องเดาเอาเอง แต่กระนั้นแกะเองดูดีกว่า
ถ้าดู script ของ quickbms จะเห้นว่าใช้ unzip
ไล่ดูใน
olly ก็มีการ ใช้ lib zlib
และไปดูใน hex ของ data ก็จะเจอ 78 01 เต็มไปหมด
เพราะโดยปกติมันเป็น header ของ zlib คร่าวๆมี
78 01 - No Compression/low
78 9C - Default Compression
78 DA - Best Compression
ฟันธงว่า zlib แน่นอน
เริ่มไปดูว่า เกมอ่าน data.pack ยังงัยที่ถูกต้อง
พยายามหาว่า Code ที่เกี่ยวกับ Virtual File System มันอยู่ตรงไหน
ตรงนี้แน่นอน แตะเมื่อ google ดู ประกาฏว่ามันเป็น Open Source โชคดีจริงๆ
ที่ dev ยัง เหลือ text ไว้ให้ตามร่องรอยได้
ก็โหลด code มาโม จน สามารถ unpack ได้อย่างถูกต้อง
และโครงสร้างที่ถูกต้องคือ
แต่มันยังไม่จบแค่นั้น เพราะ แต่ละไฟล์ยังถูก zip ไว้อีกชั้น
ในสองรูปแบบ
1.
คือไม่โดน compress (smallshop.png) Offset ที่ 10
เป็นตัวบอกว่า
มันโดน compress รึปล่าว
2.
คือโดน compress (build_list_icon.png)
ไฟล์ที่โดน compress สั่งเกต DWORD
Offset ที่ 0 จะไม่เท่ากับ DWORD
Offset ที่ 6
DWORD Offset ที่ 0 น่าจะเป็นตัว
บอก max size หลังจาก uncompress ส่วน DWORD
Offset ที่ 6 เป็นตัวบอก ขนาด binary ที่เป็น data ที่ compress
อยุ่
(ลองนับ ตั้งแต่ 78 01 ไปจนถึงสุดไฟล์จะได้ขนาดเท่า
DWORD Offset 6 พอดี )
ว่าแล้วก็เขียนโปรแกรมไล่ decompress ทีละไฟล์
แต่! ผลลัพท์ ออกมาเหมือนของ quickbms เลย
คือมีไฟล์เสีย ที่ประมาณกลางๆ ไฟล์
มีสองเหตุผล ที่คิดออกที่เป็นแบบนี้
1.
Algorithm ในการ uncompress ของ zlib
โดน
custom (ทำให้ต้องไล่ reverse engineer code zlib ทั้งหมด ใน game
client)
2.
Data ก่อน uncompress มันพังอยู่แล้ว
ทำให้ uncompress ไม่ได้ (ทำให้ต้องไล่ reverse engineer OFS ทั้งหมด ใน game
client และ ถ้าไม่ใช่ก็ต้องไล่หาว่า มันโดยแก้อะไรตรงไหนก่อน uncompress
)
จากทางเลือกทั้งสองดูเหมือน ข้อ 1
จะมีปริมาณงานน้อยกว่า แต่จากการที่ไล่ดูหมดแล้ว บอกเลยดีกว่า ว่าหวยออกข้อ 2
แต่ไม่ใช่
ที่ตัว OFS แต่ เป็นที่กระบวนการ ก่อนการ uncompress เราต้องไปแก้บาง byte ใน data
ให้ถูกต้องก่อน
uncompress
จะเริ่มไปใช้เครื่องมือที่ชื่อ IDA ในการ reverse
engineer ที่เราจะหา code อะไรๆ ง่ายกว่า
ย้อนกลับไปตอนที่ เขียนโปรแกรม uncompress เอง ตัว zlib
จะ
return DATA_ERROR ออกมา เราก็ควรจะไปเริ่ม ที่ตรงแถวๆนั้นในการ reverse
engineering ซึ่งก็คือแถวๆนี้ Address 0x6A4A1D
ปล. ปิด ASLR ซะจะได้ไล่ Address ง่ายๆ
จุดประสงค์คือจะไปดูว่าอะไร Call มัน
ไล่กลับไปเรื่อยๆ อย่างมีหลักการ ^^ ว่าออกจากส่วนที่เป็น
zlib รึยัง หรือมีอะไรผิดปกติ ไป ก็จะเห็น
วิเคราะห์ ด้วย IDA
และ
Plugin HexRay C Decompile เพื่อความสะดวก
-
V8 = sub_61665E คือ new
แล้วจะได้ pointer กลับมาไว้ใน V8
-
Function ที่น่าสงสัยคือ sub_615F40 และ sub_615E10
เพราะมีการ
ส่ง buffer ไปเป็น parameter ก่อนการ uncompress
-
Sub_6443B0 = คือ function ZEXTERN int ZEXPORT
uncompress OF((Bytef *dest, uLongf
*destLen, const Bytef *source, uLong sourceLen)); ใน zlib
ไปดูที่ sub_615F40 ก่อน
Parameter a1 มันต้องเป็น pointer ของ struct
ที่เก็บข้อมูลของแต่ละไฟล์ใน
pack แน่นอน เพราะ เมื่อ debug ด้วย olly
dbg ทำให้รู้ว่า
v1 = *(DWORD*)(a1 + 16) คือ length ของชื่อไฟล์
และ debug หา ตัวแปรอื่นใน struct ไปเรื่อยๆ ได้เป็น code
นี้ในภาษา
c
สรุป Function นี้จะเป็นการคำนวน key โดย parameter
คือชื่อไฟล์
ในแบบ Unicode
มาต่อที่ function sub_615E10 ไอตัวนี้แหละไอตัวดีแน่นอนเพราะมันมีการแก้ binary
ของไฟล์ก่อนการ
uncompress
โดยจะรับ parameter a3 ที่เป็น key ที่ถูกคำนวนจากชื่อไฟล์
a1 คือ pointer ของ data , a2 คือ size
ของ
data
มันจะทำการแก้ไขให้ data ถูกต้อง โดยการ xor byte กลับมาจำนวน 6
byte
Code ใน c ก็ จะได้เป็น
เมื่อเขียนโปรแกรมเสร็จเรียบร้อยก็ทดลอง unpack ใหม่
ไม่พังแล้วจ้า!!!
วิธีการ pack กลับก็ย้อนกระบวนการกลับ โดยที่ไม่จำเป็นต้อง compress
แล้วก็ได้
แค่เอาไปใส่ data.pack
ไว้
จากเดิม data.pack ขนาดเดิมประมาณ 499MiB จะเป็นประมาณ 941MiB แต่ client
ก็ยังอ่านได้เหมือนเดิม
ลองแก้อะไรดูซักหน่อย นั่นคือ ทำให้กลางคืนมันสว่างเหมือนกลางวันซะ ด้วยการแก้ data ใน pack