Bölüm 1/3
Tersine mühendislik konusunda ciddiyseniz - eğitmenleri ve hile motorlarını unutun.
İyi bir tersine mühendis ilk önce işletim sistemini, temel API işlevlerini, program genel yapısını (çalıştırma döngüsü, Windows yapıları, olay işleme rutinleri), dosya formatını (PE) öğrenmelidir. Petzold'un klasikleri "Programlama Pencereleri" (www.amazon.com/exec/obidos/ISBN=157231995X) ve ayrıca çevrimiçi MSDN yardımcı olabilir.
Öncelikle mayın tarlası başlatma rutininin nerede çağrılabileceğini düşünmelisiniz. Aşağıdakileri düşündüm:
- Oyunu başlattığınızda
- Mutlu yüze tıkladığında
- Oyun-> Yeni'ye tıkladığınızda veya F2'ye bastığınızda
- Seviye zorluğunu değiştirdiğinizde
F2 hızlandırıcı komutunu kontrol etmeye karar verdim.
Hızlandırıcı işleme kodunu bulmak için, pencere mesajı işleme prosedürünü (WndProc) bulmalısınız. CreateWindowEx ve RegisterClass çağrıları tarafından izlenebilir.
Okumak:
IDA, İçe Aktarma penceresini açın, "CreateWindow *" u bulun, ona atlayın ve nerede çağrıldığını görmek için "xref ile işlenene (X) atla" komutunu kullanın. Sadece bir arama olmalı.
Şimdi RegisterClass işlevi ve WndClass.lpfnWndProc parametresi için yukarıya bakın. Benim durumumda zaten mainWndProc ismini verdim.
.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
İşlev adına Enter tuşuna basın (daha iyi bir adla yeniden adlandırmak için 'N' kullanın)
Şimdi şuna bir bak
.text:01001BCF mov edx, [ebp+Msg]
Bu, F2 düğmesine basılması durumunda WM_COMMAND değerini içermesi gereken mesaj kimliğidir. 111h ile karşılaştırıldığında nerede olduğunu bulmalısınız. IDA'da edx'i takip ederek veya WinDbg'de koşullu kesme noktası ayarlayarak ve oyunda F2'ye basarak yapılabilir.
Her iki şekilde de şöyle bir şeye yol açar
.text:01001D5B sub eax, 111h
.text:01001D60 jz short loc_1001DBC
111h'ye sağ tıklayın ve "Sembolik sabit" -> "Standart sembolik sabit kullan" seçeneklerini kullanın, WM_ ve Enter yazın. Şimdi sahip olmalısın
.text:01001D5B sub eax, WM_COMMAND
.text:01001D60 jz short loc_1001DBC
Mesaj kimliği değerlerini bulmanın kolay bir yoludur.
Hızlandırıcı işlemeyi anlamak için kontrol edin:
Tek bir cevap için oldukça fazla metin var. Eğer ilgilenirsen birkaç yazı daha yazabilirim. Uzun lafın kısa mayın tarlası bir bayt dizisi olarak depolanır [24x36], 0x0F, baytın kullanılmadığını gösterir (daha küçük bir alanla oynuyor), 0x10 - boş alan, 0x80 - benim.
Bölüm 2/3
Tamam, F2 butonu ile devam edelim.
Klavye Hızlandırıcılarının Kullanılmasına Göre F2 düğmesine basıldığında wndProc işlevi
... bir WM_COMMAND veya WM_SYSCOMMAND mesajı alır. WParam parametresinin düşük sıralı sözcüğü, hızlandırıcının tanımlayıcısını içerir.
Tamam, WM_COMMAND'in nerede işlendiğini zaten bulduk, ancak karşılık gelen wParam parametre değeri nasıl belirlenir? Kaynak korsanının devreye girdiği yer burasıdır . İkili ile besleyin ve size her şeyi gösterir. Benim için hızlandırıcı tablosu gibi.
alt text http://files.getdropbox.com/u/1478671/2009-07-29_161532.jpg
Burada F2 düğmesinin wParam'da 510'a karşılık geldiğini görebilirsiniz.
Şimdi WM_COMMAND'i işleyen koda geri dönelim. WParam'ı farklı sabitlerle karşılaştırır.
.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
Ondalık değerleri görüntülemek için bağlam menüsünü veya 'H' klavye kısayolunu kullanın ve atladığımızı görebilirsiniz
.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
Bazı proc'u çağıran ve wndProc'dan çıkan kod yığınına yol açar.
.text:01001EC8 loc_1001EC8: ; CODE XREF: mainWndProc+20Fj
.text:01001EC8 call sub_100367A ; startNewGame ?
.text:01001EC8
.text:01001ECD jmp callDefAndExit ; default
Yeni oyunu başlatan işlev bu mu? Bunu son bölümde öğrenin! Bizi izlemeye devam edin.
Bölüm 3/3
Bu fonksiyonun ilk kısmına bir göz atalım
.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
Eax ve ecx yazmaçlarında okunan ve diğer iki değerle karşılaştırılan (dword_1005164, dword_1005338) iki değer (dword_10056AC, uValue) vardır.
WinDBG'yi kullanarak gerçek değerlere bir göz atın ('bp 01003696'; mola sırasında 'p eax; p ecx') - bunlar benim için mayın tarlası boyutları gibi göründü. Özel mayın tarlası boyutuyla oynamak, ilk çiftin yeni boyutlar ve ikinci - mevcut boyutlar olduğunu gösterdi. Yeni isimler koyalım.
.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
Biraz sonra yeni değerler mevcutun üzerine yazılır ve alt rutin çağrılır
.text:010036A7 mov currentMineFieldWidth, eax
.text:010036AC mov currentMineFieldHeight, ecx
.text:010036B2 call sub_1002ED5
Ve onu gördüğümde
.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
Mayın tarlası dizisini bulduğumdan tamamen emindim. 0xF ile 360h bayt uzunluk dizisini (dword_1005340) başlatan döngünün nedeni.
Neden 360h = 864? Bu satırın altında 32 bayt alan bazı ipuçları vardır ve 864 32'ye bölünebilir, böylece dizi 27 * 32 hücre tutabilir (UI maksimum 24 * 30 alana izin verse de, sınırlar için dizinin etrafında bir bayt dolgusu vardır).
Aşağıdaki kod mayın tarlası üst ve alt sınırları (0x10 bayt) oluşturur. Umarım bu karışıklıkta döngü yinelemesini görebilirsiniz;) Kağıt ve kalem kullanmak zorunda kaldım
.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
Ve alt yordamın geri kalanı sol ve sağ sınırları çizer
.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 komutlarının akıllıca kullanılması, mayın tarlası dökümü (özel boyut 9x9) sağlayabilir. Sınırları kontrol edin!
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, konuyu kapatmak için başka bir gönderiye ihtiyacım var gibi görünüyor