Перейти к содержанию

GTA2, расстуктуризация патронов + чит-код


Рекомендуемые сообщения

Игра: 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)

 

Ссылка на комментарий
Поделиться на другие сайты

×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.