Найти тему
Adr Asd

пишем трейнер на Delphi_11 - получаем патч-байты для SCUM.v0.9.113.75065

Оглавление

К циклу статей - пишем трейнер на Delphi_11.

-------------------
Ссылки на части:
_часть 1 _часть 2 _часть 3

конвертер hex<->float
-------------------

Привет.

SCUM.v0.9.113.75065, работает, настроена и через Т - консоль взяты необходимые предметы, оружие и обмундирование ;-)

Для начала найдём код отбирающий у нас здоровье.

-2

Запускаем игру, прыгаем с высоты, повреждаем здоровье, лечим (например бинтами или такой штукой #SpawnItem Phoenix_Tears <- антирадиация и лечение), на вкладке здоровья наблюдаем постепенное увеличение числа здоровья, по наведению мыши видно точное число, останавливаем игру.

-3

Запускаем CheatEngine, выбираем тип поиска диапазон - чтоб число входило, тип значения float. Поиск. Далее периодически возобновляя игру - производим отсев по мере увеличения счётчика здоровья, добиваясь приемлемого количества результатов. У меня нашлось одно совпадающее значение.

-4
-5

Копируем адрес, закрываем CheatEngine. Запустим x64dbg, присоединимся к процессу , установим аппаратный бряк на найденный адрес и остановка в коде:

movss dword ptr ds:[rbx+388],xmm1
movss dword ptr ds:[rbx+380],xmm0
| new урон вкладка здоровье
divss xmm0,dword ptr ds:[rbx+378]
comiss xmm0,xmm7


а чуть ниже - запись значения в круговой счётчик (слева в низу игрового экрана )
minss xmm0,xmm8
...
movss dword ptr ds:[rbx+384],xmm0
| new здоровье круговой счётчик

-6

Удаляем аппаратный бряк. Ставим бряки и комментарии чтоб не потерять. Можно понаблюдать изменения значений по адресам [rbx+388] и [rbx+384] в дампе, они находятся рядом. Бряки деактивируем на вкладке точек останова - чтоб не мешали. Патч здоровья будет из двух частей

-7

оригинальный код:

-8

патченный код:

-9

код патча:
call scum.143F0F090
push rax | <-- начало патча здоровья часть 1
mov rax,0x42C80000
mov dword ptr ds:[rbx+0x380],eax |- запись значения на вкладке здоровья
mov rax,0x3F800000
mov dword ptr ds:[rbx+0x384],eax |- запись значения на круговой шкале
pop rax
nop
nop
nop
nop
nop
nop
nop
nop
nop
| new урон вкладка здоровье
nop
nop
nop
nop
nop
nop
nop

divss xmm0,dword ptr ds:[rbx+378] | ↑-- конец патча здоровья часть 1 (строкой выше)
... |
movss xmm3,dword ptr ds:[14507E83C]
comiss xmm2,xmm3 (после этой строки)
nop | new здоровье круговой счётчик
nop
nop
nop
nop
nop
nop
nop

jae scum.141E8AD47 | ↑-- патча здоровья часть 2 (нупы выше)
xorps xmm1,xmm1
jmp scum.141E8AD50

вторая часть - занупленная строка movss dword ptr ds:[rbx+384],xmm0 | new здоровье круговой счётчик
и находится через
0x52 байта после начала первой части. Накодили патч, проверяем в игре, прыгаем, ломаем ноги, издеваемся над подопытным, работает - идём дальше (кровотечение по прежнему присутствует, об это далее).

Сохраним байты патча, выделим изменённые нами строки с помощью контекстного меню Двоичные операции->копировать, сохраним в текстовый файл:
//байты патча 1 здоровья
//часть 1
5048C7C00000C84289838003000048C7C00000803F8983840300005890909090909090909090909090909090
//часть 2
9090909090909090

Теперь вычислим адрес уникальной сигнатуры, от которой и будем отсчитывать смещения всех патчей. Восстановим все изменения в коде. Перейдём к месту патча с помощью бряка на вкладке точек останова, у меня с комментом <-- начало патча здоровья часть 1. Выделим четыре строки, идём в меню Модули->SigMake->Create signature и сохраняем в текстовый файл строки из полей - Data и Mask. Нажимаем Scan и убеждаемся в статус строке - что Found 1 references , то есть - результат в одном экземпляре, уникален.

-10

//строка байт для поиска сигнатуры
\x0F\x28\xC8\xF3\x41\x0F\x59\xCC\xF3\x00\x00\x00\x00\x00\x00\x00\xF3
//маска
xxxxxxxxx???????x

У нас есть адрес сигнатуры, байт-строка и маска для поиска сигнатуры, адрес и данные (цепочки байт) для патча.

*****

Здесь можно прерваться , вернуться к статье написания трейнера часть 3, где мы кодим уже рабочие патчи, а после - дочитать о получении остальных данных.

*****

Продолжаем. Теперь выносливость. При полной шкале выносливости ищем в CheatEngine 0x3F800000
Бегая и прыгая уменьшаем число выносливости и параллельно в CheatEngine логично отсеиваем значения. Получив приемлемое количество результатов ( у меня 7), заморозкой выясняем верный.

-11

Запускаем x64dbg, присоединяемся к игре и ставим аппаратный бряк записи на адрес.

-12

Бряк срабатывает, попадаем в этот код:

minss xmm6,xmm11
movaps xmm9,xmm6
movaps xmm6,xmmword ptr ss:[rsp+80]
subss xmm7,xmm12
movaps xmm12,xmmword ptr ss:[rsp+20]
movss dword ptr ds:[rbx+3B0],xmm9
| <-- new усталость
movaps xmm9,xmmword ptr ss:[rsp+50]

а патч будет начинаться со строки subss xmm7,xmm12 и будет такой:

movaps xmm6,xmmword ptr ss:[rsp+80]

push rax
| <-- patch 1 выносливость
mov rax,3F800000
mov dword ptr ds:[rbx+3B0],eax
pop rax
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
movss dword ptr ds:[rbx+3B4],xmm7 | ↑-- конец patch 1 выносливость (строкой выше)

-13

То есть - просто вносим нужное значение. Проверяем в работе, выносливость не отнимается. Получим байты патча выносливости для трейнера:
5048C7C00000803F8983B0030000589090909090909090909090
вычислим смещение -
адрес начала патча выносливости минус адрес сигнатуры (он же - начало патча здоровья).
Адрес сигнатуры смотрим по бряку -
00007FF6CA50ACE6 | 0F28C8 | movaps xmm1,xmm0 | <-- начало патча здоровья часть 1 (сигнатура)
Пример: 0x7FF6CA50BA03 - 0x7FF6CA50ACE6 = 0xD1D
смещение 0xD1D
Сохраняем всё в текстовый файл, для трейнера. Идём дальше.

**********


Теперь разберёмся с
патронами, получаем с помощью консоли Т:
#SpawnItem Weapon_AK47 - калаш
#SpawnItem Magazine_AK47 - магазин
#SpawnItem Cal_7_62x39mm - пару, тройку пачек патронов,
заряжаем магазин, запускаем не патченную игру в CheatEngine. Заражен
31 патрон - это 0x1F , ищем диапазон значений от 0x1D до 0x1F, так как сохраняется в несколько адресов и некоторые значения отличаются на единицу. Далее отстреливая по одному патрону - ищем отсеиванием уменьшающееся значение. Нашли, на скриншоте их пять.

-14

В x64dbg в дампах открываем адреса, если посмотреть внимательно - возле одного из адресов, через 0x10 байт от него находится такое же значение, не попавшее в поиск.

-15

Ставим аппаратные бряки записи на них, стреляем и находим участки кода помеченные на скринах как патроны 3 _2 и патроны 3 _3

Помечаем их бряками и комментами, снимаем аппаратные бряки с этих двух адресов и смотрим - какие из оставшихся адресов изменяются при выстреле, ставим аппаратные бряки записи , стреляем и находим участки кода помеченные на скринах как new патроны 1 первый адрес и патроны 3 _1 , эти срабатывают в цикле. (не удивляйтесь странным комментам, просто их было очень много, в том числе от предыдущей версии ;-)

Помечаем их бряками и комментами и снимает аппаратные. Но мы могли бы попросить CheatEngine Найти инструкции обращающиеся к адресу и он найдёт всё те же участки кода плюс ещё пару тройку.

Патч будет довольно прост, но в трёх местах.

В начало функции с комментом патроны 3 _1 ставим ret
В начало функции с комментом
патроны 3 _3 ставим ret
А в коде с комментом
патроны 3 _2 выстрел - предварительно занупив строку lea eax,qword ptr ds:[r8-1] пишем в место неё lea eax,[r8] устраняя декремент.

И сохраняем байты и смещения частей патча (адреса у вас понятно будут другие, приведены примеры расчёта):

Адрес сигнатуры для отсчёта 0x140EEACE6

адрес первой части патча
->
0141225D00 | C3 | ret | patch патроны 1
...
0141225D26 | mov dword ptr ds:[rbx+2D0],eax | патроны 3 _1

байты
C3
смещение 0x141225D00 - 0x140EEACE6 = 0x
33B01A
---
адрес второй части патча
->
014122C1C1 | 41:8D00 | lea eax,qword ptr ds:[r8] | patch пароны 2
014122C1C4 | 90 | nop
014122C1C5 | mov dword ptr ds:[rcx+8],eax | патроны 3 _2 выстрел

байты
418D0090
смещение 0x14122C1C1 - 0x140EEACE6 = 0x
3414DB
---
адрес третьей части патча
->
013FB587F0 | C3 | ret | patch патроны 3
...
013FB58813 | 8979 08 | mov dword ptr ds:[rcx+8],edi | патроны 3 _3

байты
C3
смещение отрицательное так как адрес
выше сигнатуры 0x140EEACE6 - 0x13FB587F0 = 13924F6 то есть -0x13924F6

Данные для патча патронов получены, можно добавить в трейнер

**********

Теперь стрелы. Берём через консоль T - арбалет и пачку болтов:

#SpawnItem Weapon_BlackHawk_Crossbow
#SpawnItem Ammo_Crossbow_Bolt_Carbon

-20

Смотрим в инвентаре количество и ищем в CheatEngine. Отсевиаем до приемлимого кол-ва результатов, у меня 3.Меняя в них значения, определяем верный. Ставим аппаратный бряк записи на найденный адрес, попадаем в код, помечаем его бряком и комментарием - "запись стрелы", а выше находим считывание и вычитание:

0141A5E79C | jmp scum.141A5E7A9
0141A5E79E |
mov edi,dword ptr ds:[rcx+94C] | считываются стрелы
0141A5E7A4 | cmp edx,edi
0141A5E7A6 |
cmovl edi,edx | отнимаются стрелы
0141A5E7A9 | cmp edi,dword ptr ds:[rcx+950]
0141A5E7AF | je scum.141A5E908
...
0141A5E838 | mov r14,qword ptr ss:[rsp+58]
0141A5E83D | mov rcx,rbx
0141A5E840 |
mov dword ptr ds:[rbx+950],edi | запись стрелы
0141A5E846 | mov byte ptr ds:[rbx+958],1

Патч будет прост. Строку mov edi,dword ptr ds:[rcx+94C]
заменим на
mov edi,C , а cmovl edi,edx просто занупаем.
Получае следующее:
0141A5E79C | jmp scum.141A5E7A9
0141A5E79E |
mov edi,C |<-- считываются стрелы
0141A5E7A3 |
nop |<--
0141A5E7A4 | cmp edx,edi
0141A5E7A6 |
nop |<-- отнимаются стрелы
0141A5E7A7 |
nop |<--
0141A5E7A8 |
nop |<--
0141A5E7A9 | cmp edi,dword ptr ds:[rcx+950]

Аппаратный бряк убираем. Ну и сохраняем байты патча и определяем смещения в двух частях:

//адрес сигнатуры для отсчёта
0141D8ACE6 | <-- начало патча здоровья часть 1 (сигнатура)

//часть 1
//байты
BF0C00000090
//смещение (отрицательное) 0141D8ACE6 - 0141A5E79E = 32C548
-0x32C548

//часть 2
//байты
909090
//смещение (отрицательное) 0141D8ACE6 - 0141A5E7A6 = 32C540
-0x32C540

В трейнере - добавим их к патчу патронов.

**********

Износ оружия предметов. Используем для этого калаш с патчем патронов.

-21

Запускаем CheatEngine и ищем неизвестное значение 4 байта. Далее постреливая и калаша - ищем уменьшающееся значение, можно пару раз не стреляя, отсеять с типом "не изменилось". Получив приемлемое количество результатов, в CheatEngine переключаем отображение на float
убеждаемся что нашли верный адрес изменив значение например на 0x42480000 = 50% float

-22

В x64dbg устанавливаем аппаратный бряк записи на адрес, делаем выстрел и остановка в коде:

0140FF4AB2 | movaps xmm9,xmmword ptr ss:[rsp+40]
0140FF4AB8 | mov rcx,rbx
0140FF4ABB | movss dword ptr ds:[rbx+1A8],xmm7 | износ оружия вещей
0140FF4AC3 | movss dword ptr ds:[rbx+1AC],xmm6
0140FF4ACB | call scum.141224C60
0140FF4AD0 | test al,al
0140FF4AD2 | jne scum.140FF4B46

Патч будет из 3 частей и размазан по свободным местам между кодом. Занупим строку
movss dword ptr ds:[rbx+1A8],xmm7 и напишем первую часть вместо неё.
//1 часть
0140DB4AB8 | mov rcx,rbx
0140DB4ABB |
push rax | <- износ оружия вещей
0140DB4ABC |
jmp scum.140DB4C12 | <- переход ко 2 части патча
0140DB4AC1 |
nop | <-
0140DB4AC2 |
nop | <-
0140DB4AC3 | movss dword ptr ds:[rbx+1AC],xmm6
...

//2
0140DB4C10 | pop rdi
0140DB4C11 | ret
0140DB4C12 |
mov eax,0x42C80000 | <- 2 часть
0140DB4C17 |
mov dword ptr ds:[rbx+0x1A8],eax | <-
0140DB4C1D |
jmp scum.140DB4C61 | <- переход к 3 части патча
...

//3
0140DB4C60 | ret
0140DB4C61 |
pop rax | <- 3 часть
0140DB4C62 |
jmp scum.140DB4AC3 | <- возврат из патча

Убираем аппаратный бряк. Проверяем в игре , пропатченный в X64dbg код, если порядок - то далее.

Получим данные патча:
/// адрес сигнатуры
01411DACE6 | push rax | <-- начало патча здоровья часть 1 (сигнатура)

//часть 1
байты
50E9510100009090
смещение (отрицательное)
1411DACE6 - 140DB4ABB = 42622B
-0x42622B


//часть 2
байты
B80000C8428983A8010000EB42
смещение (отрицательное)
1411DACE6 - 140DB4C12 = 4260D4
-0x4260D4


//часть 3
байты
58E95CFEFFFF
смещение (отрицательное)
1411DACE6 - 140DB4C61 = 426085
-0x426085

Сохраняем всё это в текстовый файл и копаем дальше.

*******

Поправим повреждения авто и расход топлива. Берём через консоль T "лайка" (ниву) ; #SpawnVehicle BPC_Laika Максимальное значение топлива для лайка - 0x42480000 = 50.0 float Ищем в CheatEngine диапазон, примерно 42300000 - 42c80000 Далее периодически тратя бензин, отсеиваем значения. Получаем приемлемое их кол-во, у меня примерно около 15. Заглушим двигатель и понаблюдаем за изменениями в CheatEngine, не изменяется одно значение,

-23

сядем в машину не заводя, увеличим значение в CheatEngine и видим изменения топлива на полосе-индикаторе, оно.

-24

В x64dbg ставим аппаратный бряк записи на адрес и заводим двигатель, брякаемся в коде

-25

01419E80F0 | xorps xmm0,xmm0
01419E80F3 | comiss xmm1,xmm0
01419E80F6 | jb scum.1419E8104
01419E80F8 | movss xmm0,dword ptr ds:[rcx+438]
01419E8100 | minss xmm0,xmm1
01419E8104 | movss dword ptr ds:[rcx+590],xmm0 |<- расход топлива
01419E810C | ret

Помечаем код бряком F2 и комментом "расход топлива", отключим аппаратный бряк.
Давайте определим максимальное число топлива, отключим все бряки, возьмём новое авто, активируем бряк "
расход топлива" и заводим двигатель, остановка на бряке - movss dword ptr ds:[rcx+590],xmm0 | расход топлива
Видим в регистре
xmm0 значение 0x42480000 = 50.0 float, полный бак для "лайка", ну и перейдём в дамп по адресу [rcx+590] , выполним в отладчике F7 один шаг и видим число из xmm0 записано по адресу.
Делаем патч, функция маленькая, занупим её всю оставив только
ret , а начиная с первой строки функции пишем код:

push rax
mov eax,0x42480000
mov [rcx+0x438],eax
pop rax

получится примерно так:

01419E80F0 | push rax
01419E80F1 |
mov eax,42480000
01419E80F6 |
mov dword ptr ds:[rcx+438],eax
01419E80FC |
pop rax
01419E80FD |
nop
01419E80FE |
nop
01419E80FF |
nop
01419E8100 |
nop
01419E8101 |
nop
01419E8102 |
nop
01419E8103 |
nop
01419E8104 |
nop | расход топлива
01419E8105 |
nop
01419E8106 |
nop
01419E8107 |
nop
01419E8108 |
nop
01419E8109 |
nop
01419E810A |
nop
01419E810B |
nop
01419E810C | ret

место RET тут не существенно. Проверим патч в игре и сохраним его данные:

///адрес сигнатуры
01416EACE6 | <-- начало патча здоровья часть 1 (сигнатура)

байты патча
50B80000484289813804000058909090909090909090909090909090

смещение
1419E80F0 - 1416EACE6 =
0x2FD40A

Сохраняем в текстовый файл.

*******

Ну и здоровье авто.

В CheatEngine ищем диапазон где то 0x423B8000 - 0x443B8000

Бьёмся машиной о дерево наблюдая уменьшение полосы здоровья и отсеиваем в CheatEngine, при достижении приемлемого количества - бьёмся ещё раз и сразу выходим. В CheatEngine отсеиваем с типом "уменьшилось"
и постояв немного - отсеиваем с типом "изменилось", у меня осталось 3 значения , изменяя значения определяем рабочее.
На скриншоте 43A55211 = 330,6411438 float

-26

В x64dbg ставим аппаратный бряк записи на адрес, стукаемся машиной об дерево и попадаем в код:

0141C82BDF | jmp scum.141C82BED
0141C82BE1 | movss xmm0,dword ptr ds:[rcx+1F8] |
- в xmm0 вносит максимальное число здоровья
0141C82BE9 | minss xmm0,xmm3
0141C82BED | subss xmm2,xmm0
0141C82BF1 | andps xmm2,xmmword ptr ds:[144BA3EE0]
0141C82BF8 | comiss xmm2,dword ptr ds:[144FBCE80]
0141C82BFF | ja scum.141C82C06
0141C82C01 | comiss xmm0,xmm1
0141C82C04 | ja scum.141C82C29
0141C82C06 | mov rax,qword ptr ds:[rcx]
0141C82C09 | movss dword ptr ds:[rcx+1FC],xmm0 |
здоровье авто
0141C82C11 | call qword ptr ds:[rax+160]

Комментарий "
здоровье авто" и бряк на найденной строке, аппаратный бряк удаляем. С помощью бряка "здоровье авто" можно понаблюдать изменение значения в дампе по адресу [rcx+1FC]. Сидя в машине Shift+C открывает инвентарь, нажав 1 переходим к авто и можно посмотреть точный процент здоровья.
Возьмём новое авто, видим несколькими строками выше, в
movss xmm0,dword ptr ds:[rcx+1F8] вносится в xmm0 максимальное здоровье 0x443B8000 или изменяя в дампе значение, приходим к 0x443B8000

А патч прост, достаточно занупать
minss xmm0,xmm3

0141C82BDF | jmp scum.141C82BED
0141C82BE1 | movss xmm0,dword ptr ds:[rcx+1F8]
0141C82BE9 |
nop | <-
0141C82BEA |
nop | <-
0141C82BEB |
nop | <-
0141C82BEC |
nop | <-
0141C82BED | subss xmm2,xmm0
0141C82BF1 | andps xmm2,xmmword ptr ds:[144BA3EE0]
0141C82BF8 | comiss xmm2,dword ptr ds:[144FBCE80]
0141C82BFF | ja scum.141C82C06
0141C82C01 | comiss xmm0,xmm1
0141C82C04 | ja scum.141C82C29
0141C82C06 | mov rax,qword ptr ds:[rcx]
0141C82C09 | movss dword ptr ds:[rcx+1FC],xmm0 | здоровье авто
0141C82C11 | call qword ptr ds:[rax+160] т

Сохраним данные патча:

///адрес сигнатуры
01419BACE6 | <-- начало патча здоровья часть 1 (сигнатура)

байты патча
90909090

смещение
141C82BE9 - 1419BACE6 =
0x2C7F03

*******

Все патчи получены, идём доделывать трейнер , перейти - к часть 3.

Наука
7 млн интересуются