Bagian 1 dari 3
Jika Anda serius dalam rekayasa balik - lupakan trainer dan cheat engine.
Reverse engineer yang baik harus terlebih dahulu mengenal OS, fungsi API inti, struktur umum program (apa itu run loop, struktur windows, rutinitas penanganan acara), format file (PE). "Pemrograman Windows" klasik Petzold dapat membantu (www.amazon.com/exec/obidos/ISBN=157231995X) serta MSDN online.
Pertama, Anda harus memikirkan di mana rutinitas inisialisasi ladang ranjau dapat dipanggil. Saya berpikir untuk mengikuti:
- Saat Anda meluncurkan game
- Saat Anda mengklik wajah bahagia
- Saat Anda mengklik Game-> Baru atau tekan F2
- Saat Anda mengubah tingkat kesulitan
Saya memutuskan untuk memeriksa perintah akselerator F2.
Untuk menemukan kode penanganan akselerator, Anda akan menemukan prosedur penanganan pesan jendela (WndProc). Itu dapat dilacak dengan panggilan CreateWindowEx dan RegisterClass.
Untuk membaca:
Buka IDA, jendela Impor, cari "CreateWindow *", lompat ke sana dan gunakan perintah "Jump xref to operand (X)" untuk melihat di mana ia dipanggil. Seharusnya hanya ada satu panggilan.
Sekarang lihat di atas untuk fungsi RegisterClass dan parameternya WndClass.lpfnWndProc. Saya sudah menamai fungsi mainWndProc dalam kasus saya.
.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
Tekan Enter pada nama fungsi (gunakan 'N' untuk mengganti namanya menjadi sesuatu yang lebih baik)
Sekarang lihatlah
.text:01001BCF mov edx, [ebp+Msg]
Ini adalah id pesan, yang jika menekan tombol F2 harus berisi nilai WM_COMMAND. Anda akan menemukan di mana ia dibandingkan dengan 111h. Ini dapat dilakukan baik dengan menelusuri edx di IDA atau dengan mengatur breakpoint bersyarat di WinDbg dan menekan F2 di game.
Either way mengarah ke sesuatu seperti
.text:01001D5B sub eax, 111h
.text:01001D60 jz short loc_1001DBC
Klik kanan pada 111h dan gunakan "Konstanta simbolik" -> "Gunakan konstanta simbolik standar", ketik WM_ dan Enter. Anda sekarang harus punya
.text:01001D5B sub eax, WM_COMMAND
.text:01001D60 jz short loc_1001DBC
Ini adalah cara mudah untuk mengetahui nilai id pesan.
Untuk memahami penanganan akselerator, lihat:
Cukup banyak teks untuk satu jawaban. Jika Anda tertarik, saya dapat menulis beberapa posting lagi. Singkat cerita ladang ranjau disimpan sebagai array byte [24x36], 0x0F menunjukkan bahwa byte tidak digunakan (bermain bidang yang lebih kecil), 0x10 - bidang kosong, 0x80 - tambang.
Bagian 2 dari 3
Oke, mari kita lanjutkan dengan tombol F2.
Menurut Menggunakan Akselerator Keyboard saat tombol F2 ditekan fungsi wndProc
... menerima pesan WM_COMMAND atau WM_SYSCOMMAND. Kata urutan rendah dari parameter wParam berisi pengenal akselerator.
Ok, kami sudah menemukan di mana WM_COMMAND diproses, tetapi bagaimana menentukan nilai parameter wParam yang sesuai? Di sinilah Resource Hacker berperan. Beri makan dengan biner dan itu menunjukkan semuanya. Seperti tabel akselerator bagi saya.
teks alt http://files.getdropbox.com/u/1478671/2009-07-29_161532.jpg
Anda dapat melihat di sini, bahwa tombol F2 sesuai dengan 510 di wParam.
Sekarang mari kembali ke kode, yang menangani WM_COMMAND. Ini membandingkan wParam dengan konstanta yang berbeda.
.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
Gunakan menu konteks atau pintasan keyboard 'H' untuk menampilkan nilai desimal dan Anda dapat melihat lompatan kami
.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
Ini mengarah ke potongan kode yang memanggil beberapa proc dan keluar dari wndProc.
.text:01001EC8 loc_1001EC8: ; CODE XREF: mainWndProc+20Fj
.text:01001EC8 call sub_100367A ; startNewGame ?
.text:01001EC8
.text:01001ECD jmp callDefAndExit ; default
Apakah itu fungsi yang memulai permainan baru? Temukan itu di bagian terakhir! Tetap disini.
Bagian 3 dari 3
Mari kita lihat bagian pertama dari fungsi itu
.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
Ada dua nilai (dword_10056AC, uValue) yang dibaca ke register eax dan ecx dan dibandingkan dengan dua nilai lainnya (dword_1005164, dword_1005338).
Lihatlah nilai aktual menggunakan WinDBG ('bp 01003696'; saat break 'p eax; p ecx') - mereka tampak seperti dimensi ladang ranjau bagi saya. Bermain dengan ukuran lapangan ranjau khusus menunjukkan bahwa pasangan pertama adalah dimensi baru dan dimensi kedua saat ini. Mari tentukan nama baru.
.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
Beberapa saat kemudian nilai baru menimpa arus dan subrutin dipanggil
.text:010036A7 mov currentMineFieldWidth, eax
.text:010036AC mov currentMineFieldHeight, ecx
.text:010036B2 call sub_1002ED5
Dan ketika saya melihatnya
.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
Saya benar-benar yakin bahwa saya menemukan array ladang ranjau. Penyebab siklus yang terdiri dari larik panjang 360h byte (dword_1005340) dengan 0xF.
Mengapa 360h = 864? Ada beberapa petunjuk di bawah bahwa baris membutuhkan 32 byte dan 864 dapat dibagi dengan 32, sehingga array dapat menampung 27 * 32 sel (meskipun UI mengizinkan bidang maks 24 * 30, ada satu bantalan byte di sekitar array untuk batas).
Kode berikut menghasilkan batas atas dan bawah ladang ranjau (0x10 byte). Saya harap Anda dapat melihat iterasi loop dalam kekacauan itu;) Saya harus menggunakan kertas dan pena
.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
Dan subrutin lainnya menggambar batas kiri dan kanan
.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
Penggunaan cerdas perintah WinDBG dapat memberi Anda tempat pembuangan ladang ranjau yang keren (ukuran khusus 9x9). Lihat perbatasannya!
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 ................................
Hmm, sepertinya saya perlu postingan lain untuk menutup topik