MasterGH Опубликовано 12 декабря, 2009 Поделиться Опубликовано 12 декабря, 2009 Игра: Grand Theft Auto 2 Спрос на трейнер: не актуален (поэтому не выкладываю таблицу и трейнер) Дата выхода: 30 сентябрь 1999 Мин. системные требования: CPU 233 MHz, 32 Mb, 8 Mb Video Дополнительная информация: старая игрушка. -Перейти к теме для новичков (тема не создана, т.к. по ней нет материала). -Таблица CE (можете сами сделать). -Трейнер (можете сами сделать). На данный момент по игре расмотрены: 1. Расструктуризация патронов и чит-код (Автор MasterGH) Инструменты: MHS, CheatEngine, IDA + hexrays. 1. Нашёл адрес патронов. 2. Поставил бряк (я ставлю всегда на доступ, больше информации видно). Получил адреса инструций, рассматриваем любую в данном случае например: 004A4FC7: MOV CX, WORD PTR [ESI] Address: 004A4FC7 EAX (after): 66666667 ESP (after): 0012FDBC ECX (after): 00000127 EBP (after): 00000000 EDX (after): 00001947 ESI (after): 0356EEB8 EBX (after): 00000000 EDI (after): 00000001 Ищем адрес содержащий адрес 0356EEB8 (указатель на 0356EEB8) Всё что было выше, было старым. Теперь новое. Находим статический gta2.exe+1D85E0. Т.е. [gta2.exe+1D85E0]=0356EEB8. На него указатель искать впринципе не нужно, т.к. он находится в статичной памяти и в MHS зеленого цвета. 3. Идём в дамп памяти и в окно выражений MHS и смотря на память по интуиции определяем вот такие смещения: [[5d85a0+x*16]]= значению, где x равно натуральным числам. Некоторые натуральные x в выражении будут показывать зачения количества патронов главного героя. [[5d85a0+0*16]] = 1 (1) // без понятия что это [[[5d85a0+1*16]]] = 6 (6) // без понятия что это [[5d85a0+2*16]] = 1 (1) // не помню [[5d85a0+3*16]] = 200 (C8) //патроны и далее патроны [[5d85a0+4*16]] = 880 (370) // патронов 880, в игре 88 [[5d85a0+5*16]] = 100 (64) //патроны, патроны.. [[5d85a0+6*16]] = 0 (0) // патронов нет [[5d85a0+7*16]] = 0 (0) // патронов нет... [[5d85a0+8*16]] = 0 (0)// и т.п. [[5d85a0+9*16]] = 0 (0) [[5d85a0+10*16]] = 0 (0) [[5d85a0+11*16]] = 0 (0) [[5d85a0+12*16]] = 0 (0) [[5d85a0+14*16]] = 0 (0) [[5d85a0+15*16]] = 0 (0) [[5d85a0+16*16]] = 0 (0) //где-то здесь заканчивается набор оружия, т.е. оржия не существует [[5d85a0+17*16]] = 0 (0) [[5d85a0+18*16]] = 0 (0) [[5d85a0+19*16]] = 0 (0) [[5d85a0+20*16]] = 0 (0) [[5d85a0+21*16]] = 0 (0) Дальше идут данные другого контекста. [[[5d85a0+22*16]]] = 0 (0) [[[5d85a0+23*16]]] = 0 (0) [[5d85a0+24*16]] = 0 (0) [[5d85a0+25*16]] = 0 (0) [[5d85a0+26*16]] = 0 (0) [[5d85a0+27*16]] = 0 (0) [[5d85a0+28*16]] = 360 (168) чьи-то патроны... [[5d85a0+29*16]] = 360 (168) [[5d85a0+30*16]] = 1080 (438) размер таблицы (5dc430-5d85a0)/16 -1 = 1000 (3E8). 1000 линий по 16 байт. 4. Итогом будет следующая формула указателей на оружие. [[5d85a0+x*16]], если x в промежутке от 3 до 21, то это наше оружие. Это можно учесть при внедрении чит-кода с фильтром. Дело в том что на этом можено остановится... 5. Как положено "маньяку" я пошёл дальше. Безусловно, что мы имеем дело со структурой данных и соответсвенно должен быть код который эту структуру обрабатывает и с его помощью можно как-то отделить данные нашего игрока от других. Я поставил бряк на доступ на адрес [5d85a0+3*16]. (помним что этот адрес указатель на патроны, т.е. [[5d85a0+3*16]]= равно патронам в первом слоте) И вышел на 0041CCC4 - MOV EDI, DWORD PTR [ECX+C] // часто обращаемая инструкция. Address: 0041CCC4 EAX (after): 0000001E ESP (after): 0012FD90 ECX (after): 005D85C4 EBP (after): 005E1038 EDX (after): 005D86E4 ESI (after): 005DCBC8 EBX (after): 005DE028 EDI (after): 032FD0F8 .text:0041CCA0 sub esp, 28h // начало функции, некоторые комманды "пообрубал", т.к. лишнее .text:0041CCA3 mov eax, [esp+28h+arg_0] .text:0041CCA7 push ebx .text:0041CCA8 push esi .text:0041CCA9 mov esi, ecx .text:0041CCAB lea eax, [eax+eax*2] .text:0041CCAE push edi .text:0041CCB9 mov ecx, [esi+eax*4+1480h] // esi - начало объекта героя .text:0041CCC4 mov edi, [ecx+0Ch] <<<< мы здесь, где ([ecx+0Ch]==[[005D85C4+0Ch]])==[[5d85a0+3*16]]=патроны .text:0041CCC7 mov byte ptr [esi+71h], 2 .text:0041CCCB mov ecx, edi .text:0041CCCD mov [esp+34h+var_1C], edi .text:0041CCD1 call sub_41CC80 //далее выборка по case ... Сама функция на псевдокоде: char __thiscall sub_41CCA0(void *this, int a2) { v4 = this; v5 = *((_DWORD *)this + 3 * a2 + 1312);//esi = this - ссылка на объект. v3 = *(_DWORD *)(v5 + 12); // mov edi, [ecx+0Ch] *((_BYTE *)v4 + 113) = 2; v26 = v3; LOBYTE(v2) = sub_41CC80(v3); //... } На esi надо найти указатель, а не на ecx(!) Но 005DCBC8 сам по себе статический адрес и искать указатель на него не нужно. Исходя из всего этого фурмула указателей оружия меняется таким образом [[005DCBC8+1e*4+1480h]+0xc] это адрес патронов первого оружия, если я не ошибаюсь. А это тогда будет для общих [[[005DCBC8+1e*4+1480h]+0xc]+x*16]. Где x - натуральное. Если мы хотим найти более чёткий указатель, то нам надо развернуть "1e" из выражения выше, т.е. [[005DCBC8+[[esp+28h+arg_0]+[esp+28h+arg_0]*2]*4+1480h]+0xc], где esp надо смотреть выше... но мне это делать лень и так уже кучу времени провозился. Подсмотреть по какому принципу рапологаются указатели в структуре объекта игрока. 7. Финал. Ну и наконец чит-код будет таким, если ресурсы наши, то пишем их максимальное значение. [ENABLE] alloc(newmem,2048) label(_returnhere) label(_originalcode) newmem: cmp esi,005DCBC8 // наш игрок? jne short _originalcode push eax mov eax,[ecx+0c] mov [eax],#10000 // если наш, то вписать патроны каждому оружию pop eax _originalcode: mov edi,[ecx+0c] mov byte ptr [esi+71],02 jmp _returnhere GTA2.EXE+1CCC4: jmp newmem nop nop _returnhere: [DISABLE] GTA2.EXE+1CCC4://14000000008B8C8680140000885 ... 7C2418E8AA mov edi,[ecx+0c] mov byte ptr [esi+71],02 unregistersymbol(dnull) dealloc(newmem) Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения