
Seperti yang Anda ketahui, dalam rangkaian game di setiap bar ini, pemain hanya bisa menyewa satu Hero baru per minggu. Tapiβ¦
Deskripsi bug: Jika tidak ada perekrutan di kedai eksternal, maka mulai hari ke-8, Anda dapat membeli dua pahlawan dalam dua hari.
Untuk pekerjaan, file Heroes4.exe yang dibongkar dari add-on resmi terbaru "Winds of War" digunakan. Prosedur pengoperasian kedai ditemukan oleh tim sebelumnya dan terletak di alamat 4705E0. Dari seluruh algoritme karyanya, saya tertarik pada tempat di mana ditentukan apakah mungkin untuk menyewa Pahlawan di bar saat ini, atau jika perlu menunggu. Dalam game, ini dimanifestasikan oleh output dari pesan yang sesuai:

Dari sudut pandang programatik, ini adalah jendela baru yang dibuat dalam game menggunakan fungsi NewWindowCreate (720C80) (fungsi yang dikenali dalam disassembler diberi nama mereka sendiri). Ada beberapa panggilan ke fungsi ini dalam prosedur kedai minuman, dan penantang pertama adalah panggilan ke alamat 470823. Dengan bantuan debugger, saya memastikan bahwa, pada kenyataannya, panggilan ini membuat kotak dialog yang diinginkan. Kode yang mengontrol panggilan ini ke NewWindowCreate ada di atas pada 470645:
00470638 call HeroesPricesInTavern_Lost
0047063D mov al, [ebp+48h] // 0 β ; 1 β ( 7 ).
00470640 add esp, 8
00470643 test al, al
00470645 jz loc_470866 // , 470823
Saya membeli di kedai Pahlawan, lalu mengatur "breakpoint" untuk menulis ke sel yang dialamatkan ke [ebp + 48h], setelah itu saya menunggu selama 7 hari dalam game. Ketika kedai "dikosongkan", debugger muncul di alamat 470DFF. Mari kita lihat kode sekitarnya:
00470DF0 TavernCountDays proc near
00470DF0 mov dl, [ecx+48h] // ECX+48h β :
DL=0 β ;
DL=1 β ( 7 )
00470DF3 xor eax, eax
00470DF5 cmp dl, al
00470DF7 jz short loc_470E06
00470DF9 cmp dword ptr [ecx+4Ch], 7 // [ECX+4Ch] - . 7 β .
00470DFD jl short loc_470E06
00470DFF mov [ecx+48h], al // (AL=0)
00470E02 mov [ecx+4Ch], eax //
00470E05 retn
00470E06
00470E06 loc_470E06:
00470E06
00470E06 inc dword ptr [ecx+4Ch] //
00470E09 retn
00470E09 TavernCountDays endp
Prosedur kecil ini digunakan untuk memeriksa jumlah hari kedai ditutup untuk disewa. Perhatikan bahwa itu dipanggil untuk setiap kedai minuman di peta setiap hari pertandingan. Apa yang menyebabkan bug? Untuk beberapa alasan, program terus menghitung jumlah hari di mana pahlawan tidak dipekerjakan di bar dan setelah minggu saat kedai ditutup (lihat konter di 470E06). Hasilnya, kami mendapatkan gambar berikut. Biarkan perekrutan pertama Pahlawan berlangsung hanya pada hari pertandingan kedelapan. Di pintu masuk ke prosedur, nilai dari tanda ketersediaan kedai di [ecx + 48h] akan sama dengan "1" (kedai ditutup), dan nilai penghitung hari di [ecx + 4Ch] akan sama dengan "8". Namun, setelah perbandingan di 470DF9, kontrol akan menerima kode di 470DFF, yang membuka kembali kedai untuk disewa! Ini akan mengatur ulang penghitung hari.dan setelah mempekerjakan Pahlawan kedua, algoritme akan berfungsi seperti yang diinginkan penulis. Tapi setelah dua minggu dalam game, seluruh siklus akan terulang kembali.
Cara termudah untuk memperbaiki bug adalah dengan melewati penghitungan hari. Biarkan penghitung bekerja hanya ketika kedai ditutup (yang lebih logis), dan sisa waktu kita setel ke nol. Ini dicapai dengan sangat sederhana - dengan mengubah transisi di alamat 00470DF7 ke akhir fungsi:
00470DF5 cmp dl, al
00470DF7 jz short loc_470E09
Sekarang yang tersisa hanyalah menambal kode yang ada. Untuk melakukan ini, lihat aslinya

dan dimodifikasi

pilihan.
Seperti yang Anda lihat, hasil yang diinginkan dapat dicapai dengan mengganti 0D dengan 10 di alamat 470DF8. Genre klasik: tambal bug dengan mengganti hanya satu byte!