ส่วนที่ 1 จาก 3
หากคุณจริงจังกับการทำวิศวกรรมย้อนกลับอย่าลืมเทรนเนอร์และเครื่องมือโกง
วิศวกรย้อนกลับที่ดีควรทำความรู้จักกับ OS, ฟังก์ชัน Core API, โครงสร้างทั่วไปของโปรแกรม (run loop คืออะไร, โครงสร้าง windows, กิจวัตรการจัดการเหตุการณ์), รูปแบบไฟล์ (PE) "การเขียนโปรแกรม Windows" แบบคลาสสิกของ Petzold สามารถช่วยได้ (www.amazon.com/exec/obidos/ISBN=157231995X) รวมทั้ง MSDN ออนไลน์
อันดับแรกคุณควรคิดว่าสามารถเรียกรูทีนการเริ่มต้นทุ่นระเบิดได้ที่ไหน ฉันคิดตาม:
- เมื่อคุณเปิดเกม
- เมื่อคุณคลิกหน้ามีความสุข
- เมื่อคุณคลิก Game-> New หรือกด F2
- เมื่อคุณเปลี่ยนระดับความยาก
ฉันตัดสินใจตรวจสอบคำสั่งตัวเร่งความเร็ว F2
หากต้องการค้นหารหัสการจัดการตัวเร่งความเร็วคุณจะต้องค้นหาขั้นตอนการจัดการข้อความหน้าต่าง (WndProc) สามารถสืบค้นกลับโดยการเรียก CreateWindowEx และ RegisterClass
อ่าน:
เปิด IDA หน้าต่างนำเข้าค้นหา "CreateWindow *" ข้ามไปที่มันและใช้คำสั่ง "Jump xref to operand (X)" เพื่อดูว่ามันถูกเรียกไปที่ใด ควรมีเพียงสายเดียว
ตอนนี้มองหาฟังก์ชัน RegisterClass ด้านบนและเป็นพารามิเตอร์ WndClass.lpfnWndProc ฉันตั้งชื่อฟังก์ชั่น mainWndProc ในกรณีของฉันแล้ว
.text:0100225D mov [ebp+WndClass.lpfnWndProc], offset mainWndProc
.text:01002264 mov [ebp+WndClass.cbClsExtra], edi
.text:01002267 mov [ebp+WndClass.cbWndExtra], edi
.text:0100226A mov [ebp+WndClass.hInstance], ecx
.text:0100226D mov [ebp+WndClass.hIcon], eax
.text:01002292 call ds:RegisterClassW
กด Enter ที่ชื่อฟังก์ชัน (ใช้ 'N' เพื่อเปลี่ยนชื่อเป็นสิ่งที่ดีกว่า)
ตอนนี้มาดูที่
.text:01001BCF mov edx, [ebp+Msg]
นี่คือรหัสข้อความซึ่งในกรณีของการกดปุ่ม F2 ควรมีค่า WM_COMMAND คุณต้องหาที่เทียบกับ 111h สามารถทำได้โดยการติดตาม edx ใน IDA หรือโดยการตั้งค่าเบรกพอยต์ตามเงื่อนไขใน WinDbg แล้วกด F2 ในเกม
ทั้งสองวิธีนำไปสู่สิ่งที่ชอบ
.text:01001D5B sub eax, 111h
.text:01001D60 jz short loc_1001DBC
คลิกขวาที่ 111h และใช้ "Symbolic constant" -> "Use standard symbolic constant" พิมพ์ WM_ และ Enter ตอนนี้คุณควรมี
.text:01001D5B sub eax, WM_COMMAND
.text:01001D60 jz short loc_1001DBC
เป็นวิธีง่ายๆในการค้นหาค่ารหัสข้อความ
หากต้องการทำความเข้าใจเกี่ยวกับการจัดการคันเร่งให้ตรวจสอบ:
มีข้อความค่อนข้างมากสำหรับคำตอบเดียว หากคุณสนใจฉันสามารถเขียนโพสต์อื่น ๆ ได้ เขตที่วางทุ่นระเบิดเรื่องสั้นขนาดยาวที่จัดเก็บเป็นอาร์เรย์ของไบต์ [24x36] 0x0F แสดงว่าไม่ได้ใช้ไบต์ (เล่นฟิลด์เล็กกว่า) 0x10 - ฟิลด์ว่าง 0x80 - ของฉัน
ส่วนที่ 2 จาก 3
โอเคไปต่อด้วยปุ่ม F2
ตามการใช้ Keyboard Acceleratorsเมื่อกดปุ่ม F2 ฟังก์ชัน wndProc
... ได้รับข้อความ WM_COMMAND หรือ WM_SYSCOMMAND คำลำดับต่ำของพารามิเตอร์ wParam มีตัวระบุของตัวเร่ง
ตกลงเราพบแล้วว่า WM_COMMAND ประมวลผลที่ไหน แต่จะกำหนดค่าพารามิเตอร์ wParam ที่เกี่ยวข้องได้อย่างไร นี่คือจุดที่แฮ็กเกอร์ทรัพยากรเข้ามามีบทบาท ป้อนด้วยไบนารีและแสดงให้คุณเห็นทุกอย่าง เช่นเดียวกับตารางเร่งสำหรับฉัน
ข้อความแสดงแทน http://files.getdropbox.com/u/1478671/2009-07-29_161532.jpg
คุณสามารถดูได้ที่นี่ปุ่ม F2 นั้นตรงกับ 510 ใน wParam
ตอนนี้ขอกลับไปที่รหัสที่จัดการ WM_COMMAND มันเปรียบเทียบ wParam กับค่าคงที่ต่างกัน
.text:01001DBC HandleWM_COMMAND: ; CODE XREF: mainWndProc+197j
.text:01001DBC movzx eax, word ptr [ebp+wParam]
.text:01001DC0 mov ecx, 210h
.text:01001DC5 cmp eax, ecx
.text:01001DC7 jg loc_1001EDC
.text:01001DC7
.text:01001DCD jz loc_1001ED2
.text:01001DCD
.text:01001DD3 cmp eax, 1FEh
.text:01001DD8 jz loc_1001EC8
ใช้เมนูบริบทหรือแป้นพิมพ์ลัด 'H' เพื่อแสดงค่าทศนิยมและคุณจะเห็นการกระโดดของเรา
.text:01001DBC HandleWM_COMMAND: ; CODE XREF: mainWndProc+197j
.text:01001DBC movzx eax, word ptr [ebp+wParam]
.text:01001DC0 mov ecx, 528
.text:01001DC5 cmp eax, ecx
.text:01001DC7 jg loc_1001EDC
.text:01001DC7
.text:01001DCD jz loc_1001ED2
.text:01001DCD
.text:01001DD3 cmp eax, 510
.text:01001DD8 jz loc_1001EC8 ; here is our jump
มันนำไปสู่โค้ดที่เรียก proc บางตัวและออกจาก wndProc
.text:01001EC8 loc_1001EC8: ; CODE XREF: mainWndProc+20Fj
.text:01001EC8 call sub_100367A ; startNewGame ?
.text:01001EC8
.text:01001ECD jmp callDefAndExit ; default
เป็นฟังก์ชันที่เริ่มเกมใหม่หรือไม่? ค้นหาในส่วนสุดท้าย! คอยติดตาม.
ส่วนที่ 3 ของ 3
มาดูส่วนแรกของฟังก์ชันนั้นกัน
.text:0100367A sub_100367A proc near ; CODE XREF: sub_100140C+CAp
.text:0100367A ; sub_1001B49+33j ...
.text:0100367A mov eax, dword_10056AC
.text:0100367F mov ecx, uValue
.text:01003685 push ebx
.text:01003686 push esi
.text:01003687 push edi
.text:01003688 xor edi, edi
.text:0100368A cmp eax, dword_1005334
.text:01003690 mov dword_1005164, edi
.text:01003696 jnz short loc_10036A4
.text:01003696
.text:01003698 cmp ecx, dword_1005338
.text:0100369E jnz short loc_10036A4
มีสองค่า (dword_10056AC, uValue) ที่อ่านในรีจิสเตอร์ eax และ ecx และเปรียบเทียบกับอีกสองค่า (dword_1005164, dword_1005338)
ลองดูค่าจริงโดยใช้ WinDBG ('bp 01003696'; on break 'p eax; p ecx') - ดูเหมือนว่าขนาดพื้นที่ทุ่นระเบิดสำหรับฉัน การเล่นกับขนาดพื้นที่ทุ่นระเบิดที่กำหนดเองแสดงให้เห็นว่าคู่แรกเป็นมิติใหม่และมิติที่สอง - ปัจจุบัน มาตั้งชื่อใหม่
.text:0100367A startNewGame proc near ; CODE XREF: handleButtonPress+CAp
.text:0100367A ; sub_1001B49+33j ...
.text:0100367A mov eax, newMineFieldWidth
.text:0100367F mov ecx, newMineFieldHeight
.text:01003685 push ebx
.text:01003686 push esi
.text:01003687 push edi
.text:01003688 xor edi, edi
.text:0100368A cmp eax, currentMineFieldWidth
.text:01003690 mov dword_1005164, edi
.text:01003696 jnz short loc_10036A4
.text:01003696
.text:01003698 cmp ecx, currentMineFieldHeight
.text:0100369E jnz short loc_10036A4
ค่าใหม่ในภายหลังเล็กน้อยจะเขียนทับปัจจุบันและเรียกรูทีนย่อย
.text:010036A7 mov currentMineFieldWidth, eax
.text:010036AC mov currentMineFieldHeight, ecx
.text:010036B2 call sub_1002ED5
และเมื่อฉันเห็นมัน
.text:01002ED5 sub_1002ED5 proc near ; CODE XREF: sub_1002B14:loc_1002B1Ep
.text:01002ED5 ; sub_100367A+38p
.text:01002ED5 mov eax, 360h
.text:01002ED5
.text:01002EDA
.text:01002EDA loc_1002EDA: ; CODE XREF: sub_1002ED5+Dj
.text:01002EDA dec eax
.text:01002EDB mov byte ptr dword_1005340[eax], 0Fh
.text:01002EE2 jnz short loc_1002EDA
ฉันแน่ใจอย่างสมบูรณ์ว่าฉันพบอาร์เรย์ของทุ่นระเบิด สาเหตุของวงจรซึ่งอยู่ในอาร์เรย์ความยาว 360h ไบต์ (dword_1005340) ด้วย 0xF
ทำไม 360h = 864? มีบางตัวชี้นำด้านล่างแถวนั้นใช้เวลา 32 ไบต์และ 864 สามารถหารด้วย 32 ดังนั้นอาร์เรย์จึงสามารถเก็บเซลล์ 27 * 32 ได้ (แม้ว่า UI จะอนุญาตฟิลด์ 24 * 30 สูงสุด แต่ก็มีช่องว่างภายในหนึ่งไบต์รอบอาร์เรย์สำหรับเส้นขอบ)
โค้ดต่อไปนี้จะสร้างเส้นขอบด้านบนและด้านล่างของทุ่นระเบิด (0x10 ไบต์) ฉันหวังว่าคุณจะเห็นการวนซ้ำในระเบียบนั้น) ฉันต้องใช้กระดาษและปากกา
.text:01002EE4 mov ecx, currentMineFieldWidth
.text:01002EEA mov edx, currentMineFieldHeight
.text:01002EF0 lea eax, [ecx+2]
.text:01002EF3 test eax, eax
.text:01002EF5 push esi
.text:01002EF6 jz short loc_1002F11 ;
.text:01002EF6
.text:01002EF8 mov esi, edx
.text:01002EFA shl esi, 5
.text:01002EFD lea esi, dword_1005360[esi]
.text:01002EFD
.text:01002F03 draws top and bottom borders
.text:01002F03
.text:01002F03 loc_1002F03: ; CODE XREF: sub_1002ED5+3Aj
.text:01002F03 dec eax
.text:01002F04 mov byte ptr MineField?[eax], 10h ; top border
.text:01002F0B mov byte ptr [esi+eax], 10h ; bottom border
.text:01002F0F jnz short loc_1002F03
.text:01002F0F
.text:01002F11
.text:01002F11 loc_1002F11: ; CODE XREF: sub_1002ED5+21j
.text:01002F11 lea esi, [edx+2]
.text:01002F14 test esi, esi
.text:01002F16 jz short loc_1002F39
และรูทีนย่อยที่เหลือจะดึงเส้นขอบซ้ายและขวา
.text:01002F18 mov eax, esi
.text:01002F1A shl eax, 5
.text:01002F1D lea edx, MineField?[eax]
.text:01002F23 lea eax, (MineField?+1)[eax+ecx]
.text:01002F23
.text:01002F2A
.text:01002F2A loc_1002F2A: ; CODE XREF: sub_1002ED5+62j
.text:01002F2A sub edx, 20h
.text:01002F2D sub eax, 20h
.text:01002F30 dec esi
.text:01002F31 mov byte ptr [edx], 10h
.text:01002F34 mov byte ptr [eax], 10h
.text:01002F37 jnz short loc_1002F2A
.text:01002F37
.text:01002F39
.text:01002F39 loc_1002F39: ; CODE XREF: sub_1002ED5+41j
.text:01002F39 pop esi
.text:01002F3A retn
การใช้คำสั่ง WinDBG อย่างชาญฉลาดสามารถให้การถ่ายโอนข้อมูลทุ่นระเบิดที่ยอดเยี่ยม (ขนาดที่กำหนดเอง 9x9) ตรวจสอบพรมแดน!
0:000> db /c 20 01005340 L360
01005340 10 10 10 10 10 10 10 10-10 10 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
01005360 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
01005380 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
010053a0 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
010053c0 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
010053e0 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
01005400 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
01005420 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
01005440 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
01005460 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
01005480 10 10 10 10 10 10 10 10-10 10 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
010054a0 0f 0f 0f 0f 0f 0f 0f 0f-0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
010054c0 0f 0f 0f 0f 0f 0f 0f 0f-0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
010054e0 0f 0f 0f 0f 0f 0f 0f 0f-0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
อืมดูเหมือนว่าฉันจะต้องการโพสต์อื่นเพื่อปิดหัวข้อนี้