Внимание! Это не для всех Лего игр.
Естественно это делается правкой сохраненной игры.
Но, происходит проверка данных с контрольной суммой (далее КС).
В этом и будем разбираться.
Но если влом, то можно воспользоваться этим инструментом:
А если интересно, то есть два пути. Найти и использовать алгоритм генерации КС.
Или пропатчить саму игру в месте, где идет проверка КС.
Для примера исследуем LEGO Indiana Jones 2.
Для начала берем файл сохраненной игры из:
Сам файл это Rich Saved Games формат со структурой:
typedef struct _RICH_GAME_MEDIA_HEADER\n{\n DWORD dwMagicNumber;\n DWORD dwHeaderVersion;\n DWORD dwHeaderSize;\n LARGE_INTEGER liThumbnailOffset;\n DWORD dwThumbnailSize;\n GUID guidGameId;\n WCHAR szGameName[RM_MAXLENGTH];\n WCHAR szSaveName[RM_MAXLENGTH];\n WCHAR szLevelName[RM_MAXLENGTH];\n WCHAR szComments[RM_MAXLENGTH];\n} RICH_GAME_MEDIA_HEADER;Нас интересует два значения:
Смотрим какой текущий баланс, переводит его в HEX и ищем в файле. Не забываем про порядок байтов, у нас little endian. То есть, если HEX = 00005F32, то искать нужно 32 5F 00 00.
В LEGO Indiana Jones 2 это смещение 0x22FF0 от начала файла. Или смещение внутри данных для КС (0x22FF0-dwHeaderSize)=0x20FC8
Подсчет КС осуществляется простым складыванием (add) по четыре байта (dword) к константе 0x5C0999:
09AB1D2 mov esi, 05C0999\n09AB1D7 jle 09AB1EA\n09AB1D9 mov edx, [esp+4+arg_0]\n09AB1DD lea ecx, [ecx+0]\n09AB1E0 add esi, [edx+ecx*4]\n09AB1E3 add ecx, 1\n09AB1E6 cmp ecx, eax\n09AB1E8 jl 09AB1E0А начинается он именно после RICH_GAME_MEDIA_HEADER заголовка, то есть со смещения на dwHeaderSize байт, и продолжается до конца файла минус 8 байт, которые:
То есть, получаем такой код:
start = dwHeaderSize;\nlength = filesize - dwHeaderSize - 8;\nchecksum = 0x5C0999;\n\nfor (i = start; i < length; i = i + 4) {\n\tchecksum += data[i]; // DWORD, 4 байта\n}Можно пойти другим путем. Чтобы каждый раз не пересчитывать КС, а просто менять количество монет, нужно пропатчить LEGOIndy2.exe файл.
09AB4FF cmp eax, [edi+ebx] ; 3B 04 1F\n09AB502 jnz 09AB529 ; 75 25Если КС не равны, то упрыгивает. Нужно просто не прыгать. Меняем один байт 25 -> 00:
09AB502 jnz 09AB504 ; 75 00А для LEGOStarWarsSaga.exe и LEGOBatman.exe наоборот, нужно прыгать. Так же ищем 3B 04 1F:
0XXXXXX cmp eax, [edi+ebx] ; 3B 04 1F\n0XXXXXX jz 0XXXXXX ; 74 12Такая же проверка КС, и если равны, то прыгает в нужно место. Нужно принудить 74 -> EB:
0XXXXXX jmp 0XXXXXX ; EB 12