Гайд От кодинга до взлома игр ( Перевод )

i'm calling the police
Пользователь
Статус
Оффлайн
Регистрация
27 Дек 2017
Сообщения
120
Реакции[?]
53
Поинты[?]
0
Многа букаф, ниасилил.
Помню как делал экстернал есп по гайдам с югейма, который работал через раз и крашил, но тема достаточно интересная, как хобби думаю может подойти.
 
В отставке.
Эксперт
Статус
Оффлайн
Регистрация
5 Окт 2016
Сообщения
1,686
Реакции[?]
1,222
Поинты[?]
1K
Не бросай, переводи следующую статью, хорошо получается :seemsgood:
Только над переводом нужно немного больше поработать, в тексте встречаются пропущенные слова и ошибки, а местами просто машинный перевод
 
Участник
Статус
Оффлайн
Регистрация
21 Сен 2019
Сообщения
594
Реакции[?]
250
Поинты[?]
23K
Давно ещё видел этот гайд, но не читал из-за того, что он на английском. Неплохой перевод, как и сам гайд. Не хорошо знаю основы C++, не мало чего даже забыл, но все равно сам по гайду смог написать считывание исходного числа из указателей переменной тестовой программы. Камазу +реп за перевод. P.S Ещё не до конца все прочитал и усвоил, продолжу завтра.Снимок экрана 2021-04-22 212113.png
 
Арбитр
Продавец
Статус
Оффлайн
Регистрация
13 Июл 2018
Сообщения
1,528
Реакции[?]
1,637
Поинты[?]
280K
Давно ещё видел этот гайд, но не читал из-за того, что он на английском. Неплохой перевод, как и сам гайд. Не хорошо знаю основы C++, не мало чего даже забыл, но все равно сам по гайду смог написать считывание исходного числа из указателей переменной тестовой программы. Камазу +реп за перевод. P.S Ещё не до конца все изучил, продолжу завтра.Посмотреть вложение 145021
Молодец, хоть кто-то попробовал повторить гайд. В скором времени будет перевод книги по геймхакингу на 300+ страниц.
 
Последнее редактирование:
всем прив верите ли вы в призраков ???
Забаненный
Статус
Оффлайн
Регистрация
17 Авг 2018
Сообщения
861
Реакции[?]
338
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Прочитал тему, очень полезная, спасибо

буду использовать Чит-движок, но доступны и другие сканеры памяти, такие как Cry Search, закодированные одним из наших талантливых членов.
Но чит-движок конечно крут
 
..................................................
Участник
Статус
Оффлайн
Регистрация
13 Авг 2020
Сообщения
990
Реакции[?]
249
Поинты[?]
25K
5 часов... У тебя очень много свободного времени?
А так лайк ставлю
 
Пользователь
Статус
Оффлайн
Регистрация
4 Дек 2017
Сообщения
150
Реакции[?]
32
Поинты[?]
0
От кодинга до взлома игр: Вводное руководство по практическому взлому игр
Сделал еще один небольшой перевод, надеюсь будет полезен.
Статью взял с зарубежного форума
Автор данной темы @harakirinox

Со временем доделаю.​

Главный шаг на пути ученую игровому хакингу состоит в том, чтобы перейти от изучения языка программирования к практическому хакерству, используя эти новые знания на практике. Есть много доступных материалов, учебников и руководств, но мы сталкиваемся с информационной перегрузкой, отсутствием четкого пути, который может ощущаться как непроходимая пропасть. Это, на мой взгляд, одна из причин, почему мы видим, как люди, знающие, как кодить, спрашивают в хакерских сообществах, что делать дальше. Эта статья имеет целью заполнить этот пробел и предоставить четкий путь для тех, кто научился кодить, чтобы начать работу в (экстернал) взломе игр. Это будет первый опыт практического взлома, так что читатель поймет важнейшие этапы взлома игр на практическом примере.

Для достижения этой цели нам понадобится:
- Сделать небольшую целевую программу, которую мы будем использовать для наших экспериментов (она будет имитировать игру или программу, которую мы пытаемся взломать, сохраняя при этом простоту и прозрачность для ясности)
- Мы получим первый опыт работы с Windows API (многие учебники, обучающие языкам программирования, вообще не охватывают этот раздел, например, учебники по C++ часто используют только стандартную библиотеку)
- Научимся чтению и записи памяти другой программы (что является сущностью экстернал читов)
- Научимся реверс-инжинирингу игры: Assault Cube (она бесплатная, с открытым исходным кодом и очень легкая в этом плане, она запустится даже на плохом компьютере), это даст вам базовые навыки реверс-инжиниринга и опыт работы с 2 очень важными инструментами: Cheat Engine и ReClass.
- Сделайте программу (тренер), которая сможет изменить память игры, чтобы дать нам такие функции взлома, как бессмертие, бесконечные патроны, телепортацию и многое другое...
- Сделайте простой радар, это поможет вам как осмыслить данные, которые вы собрали из памяти игры, которые вы сами изменили с помощью функций вашей программы, которую вы сами сделали. Вы также сделаете свое меню и нарисуете на нем свой радар (вы покажете всем свои художественные навыки на нем, если хотите !!)
- Код полного ESP отображающего точное положения врагов на экране. Такие вещи дают вам значительное преимущество над противниками.
- Мы проанализируем основы работы античитов и сделаем простенький обход (эти обходы все еще функционируют на простых античитах, но, скорее всего, будут обнаружены через определенное время)

..... И вишенкой на торте будет: Я помогу вам сделать все это как можно лучше, чтобы вы могли использовать все это для взлома других игр.
Другими словами: Вы сделаете свой собственный набор читов !!


Первая часть-это, по сути, обучение RPM/WPM, очень многословный, очень медленный темп для неопытной аудитории.

Вторая часть представляет собой прикладной пример разработки чита, включая реверсивную часть.
Последняя часть посвящена введению в античит-байпас.

Вы можете свободно использовать любой язык программирования для этой задачи, однако, я использовать только на C/C++.

Требования / Целевая аудитория

Этот гайд предназначен для тех, кто изучил язык программирования, подходящий для взлома игр (например, C/C++, C#,...).
От вас не требуется быть мастером этого языка, но вы также не должны допускать ошибок с самыми основными вещами, в противном случае я советую вам пойти и выучить его полностью, или прочитать другой учебник, чтобы сначала закрепить свои знания.
Я буду много раз освещать важные принципы в одном предложении с одной или несколькими ссылками на вспомогательные материалы, если вы не полностью и по-настоящему понимаете то, что я пишу, вы должны следовать ссылкам и читать предлагаемый материал, иначе вы не получите прочные знания в данной сфере.

Экстернал читы: Принцип и Понятия

Внешний чит обычно считывает память целевой игры/процесса, чтобы извлечь ценную информацию и получить преимущество.
Например, получение 3D-позиции вашего персонажа и позиций других игроков для отображения его на радаре или непосредственно на экране, как в чите ESP (Экстрасенсорное восприятие)
На следующем скриншоте показан чит как с радаром (верхний левый угол), так и с экранным ESP.

Посмотреть вложение 135906

Этот тип чита поможет нам читать память игры точно так же, как мы это сделаем с интернал читом, очевидно, в сочетании с дополнительным кодом для рисования фигур и текста (который я рассмотрю в другой теме).
Мы также можем перезаписать целевую память, чтобы изменить значения, такие как очки здоровья вашего игрока до максимума, предоставление неограниченных патрон и многое другое...
Как вы понимаете, получение доступа к памяти игры является не единственным способом получения доступа к любому виду взлома, который мы хотим сделать тогда, вот почему большинство методов обхода античита направлены на то, чтобы дать вам этот доступ, и почему это руководство фокусируется на этой задаче.

Мы называем "Экстернал читами" любой чит, который не внедряется в сам процесс игры.
Напротив, "Интеран читы" выполняются изнутри взломанной игры/программы, поэтому методы, используемые для чтения и записи данных в взломанную цель, различаются между этими двумя парадигмами, среди многих других различий.
Операционная система Microsoft Windows предоставляет набор функций, которые позволяют нам читать и записывать память другой программы с самоочевидными именами ReadProcessMemory и WriteProcessMemory (сокращенно RPM и WPM).
Использование функции RPM можно представить как запрос вашей операционной системы (ОС):
"Я хотел бы прочитать X байт данных по адресу памяти 0x12345678 этого процесса и поместить результат по адресу 0x87654321 в память моего процесса"
То же самое для WPM, но вместо этого вы просите записать то, что находится по определенному адресу в вашем процессе, по адресу в другом процессе.
Вот дополнительная диаграмма на случай, если это не совсем ясно:
Посмотреть вложение 135913
Обратите внимание, что это не единственный способ, и экстернал чит может прочитать память другого процесса.
Можно читать и записывать память другого процесса без этих функций, например, с помощью драйвера (функционирующего в режиме ядра, более высоком привилегированном режиме вашей операционной системы. Для получения дополнительной информации прочтите статью Википедии
"
Пожалуйста, авторизуйтесь для просмотра ссылки.
".) - не реклама.
Однако, поскольку программа для взлома все еще работает как другой процесс, она все еще по определению является внешним читом.

Раздел "Фиктивная программа": Кодирование нашей фиктивной целевой программы.
Этот пункт имеет 2 цели:
Во-первых, чтобы предоставить нам фиктивную минималистскую программу, которую мы попытаемся взломать, она будет имитировать нашу целевую игру/программу.
Во-вторых, это фильтр для аудитории: если вы боретесь во время этого первого пункта, вы должны учитывать, что у вас нет нужных знаний для этой темы, вместо этого вы должны прочитать больше курсов по вашему языку программирования или получить больше опыта с ним в первую очередь.
Если вы будете упорствовать и пытаться пробить себе дорогу, несмотря на недостаток опыта, вы, скорее всего, потерпите неудачу и преждевременно откажетесь от своего хакерского приключения.

Направления:

Вы собираетесь сделать простую консольную программу, точкой входа будет main(), которая делает следующие вещи:
- Объявите переменную varInt типа integer, равную 123456
- Объявить переменную с именем varString типа string с текстом "DefaultString" (только C++, игнорировать при записи на C)
- Объявите массив символов с именем arrChar размером 128 с текстом "Long char array right there ->" (вы можете поместить размер в объявленную константу)
- Объявите указатель на целое число с именем ptr2int, указывающее на varInt
- Объявите указатель на указатель на int с именем ptr2ptr, указывающий на ptr2int
- Объявите указатель на указатель на указатель на int с именем ptr2ptr2, указывающий на ptr2ptr

Как только это будет сделано, вы создадите бесконечный цикл, в котором вы будете:
- Выведите на консоль "Идентификатор процесса:", а затем идентификатор процесса программы с помощью функции Windows API GetCurrentProcessId() (Поэтому не забудьте #include <Windows.h> !!)
- Выведите в консоль "varInt (0x[ADDRESS OR THE VARIABLE]) = [VALUE OF THE VARIABLE]" (Помните, что вы можете получить адрес переменной, поставив перед ним префикс "&")
- То же самое для varString и varChar
- То же самое для наших 3 указателей, выведите, например, "ptr2int (0x[АДРЕС УКАЗАТЕЛЯ]) = 0x[АДРЕС УКАЗАТЕЛЯ])
- Print to console "Нажмите клавишу ENTER для повторной печати."
- Поставить что-то на паузу можно либо с помощью getchar (), либо system("pause > nul")
- Выведите на консоль строку тире ( " - " ), а затем позвольте ей вернуться к началу

Вот ожидаемый результат к концу этого упражнения (после того, как вы нажмете enter один раз):
Посмотреть вложение 135914

У вас могут возникнуть проблемы при выводе для консоли идентификатора процесса или адресов памяти, так как идентификатор процесса должен быть напечатан в десятичной системе счисления, а адреса памяти-в шестнадцатеричной.
В дополнение к этому, поскольку я немного ОКР, мне нравится, чтобы мои адреса памяти были в верхнем регистре.
В C++ вы можете сделать так, чтобы выводить данные в десятичной системе счисления:
C++:
cout << "In decimal: " << dec << 255 << endl;
Оно выведет "In decimal: 255".
И вот так в шестнадцатеричном верхнем регистре (я добавляю префикс "0x", чтобы читатель знал, что следующее-шестнадцатеричное):

C++:
cout << "In hexadecimal: 0x" << hex << uppercase << 255 << endl;
Это выведет "В шестнадцатеричном формате: 0xFF"
... И не забудьте "using namespace std;" после вашего #includes и #declares в противном случае вы можете добавить префикс "std::" (например, "std::cout << "В шестнадцатеричном формате: 0x" << std::hex << std::uppercase << 255 << std::endl;")

Проект (C++)
Не читайте непосредственно решение, у вас должно получиться написать такую простую программу.
Если у вас возникли трудности, не стесняйтесь начинать все сначала.
Сделайте что-нибудь удовлетворительное или потратьте по крайней мере 45-60 минут на попытки, прежде чем решите раскрыть решение.
Если вы потерпели неудачу и должны были посмотреть на решение, внимательно прочитать его, а затем перекодировать самостоятельно, вам нужно больше опыта.

C++:
#include <Windows.h>
#include <iostream>
#include <string>

#define CHAR_ARRAY_SIZE 128

using namespace std;

int main() {
    int varInt(123456);
    string varString("DefaultString");
    char arrChar[CHAR_ARRAY_SIZE] = "Long char array right there ->";
    int* ptr2int(&varInt);
    int** ptr2ptr(&ptr2int);
    int*** ptr2ptr2(&ptr2ptr);

    do {
        cout << "Process ID: " << dec << GetCurrentProcessId() << endl;
        cout << endl;
        cout << "varInt       (0x" << hex << uppercase << (uintptr_t)&varInt << ") = " << dec << varInt << endl;
        cout << "varString    (0x" << hex << uppercase << (uintptr_t)&varString << ") = " << varString << endl;
        cout << "arrChar[" << dec << CHAR_ARRAY_SIZE << "] (0x" << hex << uppercase << (uintptr_t)&arrChar << ") = " << arrChar << endl;
        cout << endl;
        cout << "ptr2int      (0x" << hex << uppercase << (uintptr_t)&ptr2int << ") = 0x" << ptr2int << endl;
        cout << "ptr2ptr      (0x" << hex << uppercase << (uintptr_t)&ptr2ptr << ") = 0x" << ptr2ptr << endl;
        cout << "ptr2ptr2     (0x" << hex << uppercase << (uintptr_t)&ptr2ptr2 << ") = 0x" << ptr2ptr2 << endl;
        cout << endl;
        cout << "Press ENTER to print again." << endl;
        getchar();
        cout << endl << "---------------------------------------------------" << endl << endl;
    } while (true);
  
    return EXIT_SUCCESS;
}
Примечание: Не бойтесь "(uintptr_t)" перед адресами переменных, это необязательно и позволяет выводить только их адреса без лишних нулей в начале, это просто делает код чище.

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

Раздел "Чтение": Чтение памяти другого процесса.
Во втором упражнении мы будем использовать функцию ReadProcessMemory для чтения некоторых переменных из памяти нашей фиктивной программы.
Во-первых, я хочу, чтобы вы прочитали страницу документации Readprocessmemory на MSDN, чтобы понять, как работает эта функция и что мы должны дать ей в качестве параметров.
Внимательно прочитайте всю страницу, пытаясь представить себе, как это работает, прежде чем продолжить чтение следующего абзаца.

Итак, давайте рассмотрим параметры один за другим, вот прототип, чтобы вам не приходилось переключаться туда-сюда на MSDN во время чтения.

C++:
BOOL WINAPI ReadProcessMemory(
  _In_  HANDLE  hProcess,
  _In_  LPCVOID lpBaseAddress,
  _Out_ LPVOID  lpBuffer,
  _In_  SIZE_T  nSize,
  _Out_ SIZE_T  *lpNumberOfBytesRead
);

Первый параметр _In_ HANDLE hProcess, вероятно, будет сложным для тех, кто не знаком с Windows API.
Одна из многочисленных ролей вашей операционной системы, Windows, заключается в управлении различными ресурсами, доступом и разрешениями.
В нашем случае нам нужно запросить доступ к нашей целевой программе с достаточным количеством разрешений для чтения и записи ее памяти.
Вот что такое этот первый параметр типа "HANDLE", по сути, это авторизация, данная операционной системой.
Чтобы избежать путаницы, просто рассматривайте ДЕСКРИПТОР как номер авторизации, заданный операционной системой.
Чтобы получить этот необходимый ДЕСКРИПТОР, мы собираемся использовать функцию Windows API OpenProcess.
Еще раз нажмите на ссылку и внимательно прочитайте документацию функции и попытайтесь понять, как она работает.

Вот его прототип:

C++:
HANDLE WINAPI OpenProcess(
  _In_ DWORD dwDesiredAccess,
  _In_ BOOL  bInheritHandle,
  _In_ DWORD dwProcessId
);
Если вы не понимаете, что такое первый параметр, вы наверняка не нажимали на ссылку с правами доступа к процессу, всегда переходите по этим ссылкам, чтобы понять, чем заполнять функцию.
Теперь вы должны понять, что это такое: это разрешения, которые мы запрашиваем.
Многие разрешения доступны, как вы можете видеть в документации, начиная от PROCESS_ALL_ACCESS (Все возможные права доступа для объекта процесса) до PROCESS_QUERY_LIMITED_INFORMATION (Требуется для получения определенной информации о процессе) и многих других, я призываю вас быстро пройти через все эти разрешения, если вы не понимаете, что некоторые из них позволяют вам делать, это нормально, вы не ожидаете, что полностью поймете это сегодня.
Для простоты мы собираемся запросить все возможные разрешения на целевой процесс с помощью PROCESS_ALL_ACCESS.
Хорошей практикой является ограничение запрашиваемого разрешения до минимума полезного, но об этом мы позаботимся позже.

Хорошо, второй параметр, "_In_ BOOL bInheritHandle".
Это определение является дескриптором (запрошенная авторизация), который будет наследоваться для дочерних процессов.
На самом деле нас это не волнует, короче говоря, наша программа запросит дескриптор, и если мы установим его в TRUE, то все дочерние процессы нашей программы также будут иметь эту авторизацию.
Поскольку нам это не понадобится, мы установим его в FALSE

Последний параметр - "_In_ DWORD dwProcessId".
Это уникальный идентификационный номер процесса, обычно сокращенный до идентификатора процесса или даже PID, процесса, к которому мы хотим получить доступ.
Мы напечатали его на консоли с помощью GetCurrentProcessId() в нашей программе.

Process ID: 16164
Скриншот -
Пожалуйста, авторизуйтесь для просмотра ссылки.

Затем мы дадим ему PID нашей программы.

Затем мы можем добавить простую проверку в наш код, чтобы убедиться, что все прошло хорошо.
Так что наш код должен выглядеть примерно так:

C++:
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, [OUR DUMMY PROGRAM PID]);
if (hProcess == NULL) { // Failed to get a handle
    cout << "OpenProcess failed. GetLastError = " << dec << GetLastError() << endl;
    system("pause");
    return EXIT_FAILURE;
}
Таким образом, если у вас есть ошибка, у вас также будет код ошибки, возвращаемый GetLastError (), который поможет вам решить эту проблему.
В таком случае,
Пожалуйста, авторизуйтесь для просмотра ссылки.
- не реклама.

Хорошо, на этом этапе у нас теперь есть наш драгоценный дескриптор, который мы можем использовать с ReadProcessMemory, давайте перейдем ко второму параметру ReadProcessMemory "_In_ LPCVOID lpBaseAddress".
Если вы изучили C/C++ со стандартной библиотекой, не бойтесь типов переменных Microsoft, LPCVOID-это просто void* const (LP означает Длинный указатель, C означает Константу, VOID означает ... да, пустота)
Документация довольно ясна: "Указатель на базовый адрес в указанном процессе, из которого нужно читать."
Поэтому мы дадим там адрес, который мы хотим прочитать в целевом процессе.
Мы печатаем это на консоль в нашей программе:
varInt (0x35AE3DFDE0) = 123456 как пример.

В случае, если это не ясно сейчас (но я действительно надеюсь, что это так!), эта строка означает, что значение 123456 хранится по адресу памяти 0x35AE3DFDE0.
Вот что мы дадим функции.
Вашему компилятору может не понравиться, что вы помещаете адрес непосредственно в качестве параметра, так как он кажется просто числом, и функция ожидает LPCVOID, поэтому введите его как LPCVOID вот так:

C++:
(LPCVOID)0x35AE3DFDE0
Следующий параметр "_Out_ LPVOID lpBuffer".
Опять же документация является явной: A pointer to a buffer that receives the contents from the address space of the specified process.

"Буфер" просто означает место в памяти.
В качестве первой задачи в нашем упражнении мы будем читать только первую переменную типа integer, число 123456.
Поэтому мы собираемся объявить переменную также типа integer, инициализированную 0, с именем "intRead" ( int intRead = 0; ) в нашей хакерской программе, которая будет считывать память фиктивной программы, и мы дадим адрес этой переменной (&intRead) в качестве буфера.
В результате, если ReadProcessMemory преуспеет, наша переменная intRead будет равна любому значению переменной, которую мы пытаемся прочитать в нашем целевом процессе.

Предпоследний параметр - "_In_ SIZE_T nSize".
Это просто размер для чтения.
В нашем первом упражнении мы читаем целое число.
Если вы помните свои уроки, целое число традиционно имеет размер 4 байта, поэтому мы могли бы дать функции "4", но вместо этого мы предпочтем дать ей sizeof(int), который автоматически даст ей размер int.
Если бы мы хотели прочитать какой-то текст, например массив символов, мы бы дали ему размер массива или размер текста, который мы хотим прочитать.

Последний параметр, "_Out_ SIZE_T *lpNumberOfBytesRead", позволяет нам получить в переменной типа SIZE_T количество прочитанных байтов, на что довольно четко указывает параметр функции.
Поэтому мы могли бы объявить переменную SIZE_T с именем bytesRead, инициализированную 0 ( SIZE_T bytesRead = 0; ) , и дать ReadProcessMemory ее адрес (&bytesRead).
Это может быть полезно, например, для проверки ошибок, однако, чтобы все было просто, поскольку этот параметр является необязательным (как указано в документации), мы просто установим его равным НУЛЮ.
В любом случае ReadProcessMemory возвращает BOOL (TRUE/FALSE), который дает нам знать, все ли прошло хорошо или нет, и который мы можем использовать для проверки успешности операции или нет.

Итак, теперь у нас есть все необходимое для чтения памяти нашей фиктивной программы.
Это, возможно, кажется многому научиться, если вы новичок, но поверьте мне, после этого упражнения все должно быть гораздо яснее.

Указания по выполнению упражнений

Прежде чем приступить к этому упражнению, запустите нашу программу и позвольте ей работать.

Вы собираетесь написать консольную программу, которая будет:
- Объявлять переменную типа integer с именем "intRead", инициализированную значением 0
- Получать дескриптор нашей запущенной программы (используйте OpenProcess и проверьте, что она успешно справилась с проверочным кодом, который я предоставил в уроке, в случае ошибки используйте коды ошибок для расследования причины)
- Прочитает значение переменной "varInt" в нашей фиктивной программе и сохраните результат в нашей переменной "intRead" (Используйте ReadProcessMemory с дескриптором, который вы получили, адрес памяти, показанный в консоли нашей фиктивной программы, и не забудьте добавить префикс (LPCVOID) для ввода-приведите его так, чтобы функция не беспокоила вас, сохраните результат в нашей переменной "intRead", используя ее в качестве буфера, просто указав ее адрес памяти с помощью &intRead, используйте sizeof(int) для размера, и пусть последний необязательный параметр будет равен NULL)
- Выведит в консоль новое значение нашей переменной "intRead" ( cout << "intRead =" << dec << intRead << endl; )
- Выведит в консоль сообщение "Нажмите ENTER, чтобы выйти" и приостановите выполнение с помощью getchar() или system("pause > nul");

Ожидаемый результат должен быть просто:
intRead = 123456
Press enter to quit

Очень важно, чтобы вы очень старались выполнять эти действия.
Пожалуйста, очень старайтесь, прежде чем читать следующий вспомогательный раздел "Устранение неполадок" или решение проблемы, вместо этого предпочтите прочитать урок еще раз.
Вы должны попытаться по крайней мере за 1-2 часа до усталости использовать дополнительные вспомогательные материалы, которые следуют далее.
Даже если вам это удалось, я рекомендую прочитать раздел "Устранение неполадок" для ваших знаний.

Диагностика проблем.
Если OpenProcess выдает ошибку:
Убедитесь, что ваши 2 процесса работают с одинаковыми привилегиями, если фиктивная программа запускается от имени администратора, а не от имени другого, она может потерпеть неудачу.
Если вы запускаете фиктивную программу непосредственно из Visual Studio (или вашей IDE), попробуйте запустить ее в обычном режиме, дважды щелкнув двоичный файл на диске.

Если вместо этого все еще равно 0:
Сначала убедитесь, что Открытый процесс прошел успешно.
Во-вторых, проверьте возврат ReadProcessMemory, он должен возвращать TRUE, в противном случае, если он возвращает FALSE, вы можете использовать GetLastError (), чтобы получить код ошибки, чтобы получить больше информации об ошибке.
Вот тот же самый проверочный код, который вы можете использовать:

C++:
BOOL rpmReturn = ReadProcessMemory(hProcess, (LPCVOID)0x35AE3DFDE0, &intRead, sizeof(int), NULL);
if (rpmReturn == FALSE) {
    cout << "ReadProcessMemory failed. GetLastError = " << dec << GetLastError() << endl;
    system("pause");
    return EXIT_FAILURE;
}
Если int Read не равен 0, но и не равен ожидаемому значению:
Скорее всего, вы прочитали неправильный адрес памяти или запросили разрешение на неправильный идентификатор процесса.
Проверьте PID и адрес памяти.
Убедитесь также, что в обеих программах вы заявили о заинтересованности.
Попробуйте скомпилировать и запустить их для одной и той же архитектуры (либо x86, либо x64, даже если она должна работать в кросс-архитектуре).

Если у вас есть ошибка и код ошибки, перейдите в список кодов ошибок на MSDN и используйте эту дополнительную информацию об ошибке, чтобы попытаться решить проблему.

Если он все еще не работает, все остальное потерпело неудачу, и вы действительно потратили время, пытаясь решить свою проблему, разместите свою проблему в качестве ответа на этот учебник с полным кодом и выводом, который у вас есть.

Проект (C++)
Последний раз: Не раскрывайте решение, если вы не успешно написали программу или не потратили значительное количество времени на попытки (минимум 1-2 часа)
Использование решения без успеха-это, по сути, неудача.
В этом решении я предлагаю пользователю прочитать PID и адрес памяти вместо жесткого кодирования значений, вот идея улучшить вашу программу

C++:
#include <Windows.h>
#include <iostream>

using namespace std;

int main() {
    DWORD pid = 0; // The process ID of our target process
    cout << "PID: ";
    cin >> dec >> pid; // Prompting user for PID

    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    if (hProcess == NULL) { // Failed to get a handle
        cout << "OpenProcess failed. GetLastError = " << dec << GetLastError() << endl;
        system("pause");
        return EXIT_FAILURE;
    }

    // Prompting user for memory address to read
    uintptr_t memoryAddress = 0x0;
    cout << "Memory address of the integer to read (in hexadecimal): 0x";
    cin >> hex >> memoryAddress;
    cout << "Reading 0x" << hex << uppercase << memoryAddress << " ..." << endl;

    // Reading the integer from other process
    int intRead = 0;
    BOOL rpmReturn = ReadProcessMemory(hProcess, (LPCVOID)memoryAddress, &intRead, sizeof(int), NULL);
    if (rpmReturn == FALSE) {
        cout << "ReadProcessMemory failed. GetLastError = " << dec << GetLastError() << endl;
        system("pause");
        return EXIT_FAILURE;
    }

    cout << "intRead = " << dec << intRead << endl;
  
    cout << "Press ENTER to quit." << endl;
    system("pause > nul");

    return EXIT_SUCCESS;
}
Поздравляю!!
Возможно, вы этого не осознаете, но теперь вы знаете фундаментальный принцип создания полного внешнего радара или полного чита ESP !!
Очевидно, что для этого вам нужно будет читать не только целые числа, например, вам нужно будет читать значения указателей, какой-то текст для ников других игроков, например, но не волнуйтесь, я вам помогу, вы сделаете это прямо сейчас!

Далее: Чтение указателей, следование цепочкам указателей, чтение текста и многое другое
Эта часть теперь является вызовом, а не упражнением, потому что на этот раз я не буду давать вам решение !!
Но я уверен, что у вас есть все необходимое, чтобы сделать это
Я просто собираюсь дать вам несколько возможных подзадач, которые вы можете сделать, чтобы улучшить свой маленький хак/считыватель памяти.

Чтение указателя
Это то, что вам определенно понадобится в ваших чит-кодах, поэтому я настоятельно рекомендую вам сделать это.
Вы собираетесь прочитать значение указателя "ptr2int" в нашей фиктивной программе, затем вы прочитаете int по адресу, указанному этим указателем, который будет нашим целым числом, равным 123456
Важно помнить при работе с указателями: указатели x86 имеют длину 4 байта (32 бита), а указатели x64-8 байт (64 бита), поэтому адаптируйте параметр "nSize" или ReadProcessMemory в зависимости от архитектуры вашей целевой программы.

Следование цепочке указателей
Вы должны были сначала выполнить предыдущее упражнение, теперь вы можете следовать цепочке указателей.
В большинстве реверсивных тем в хакерских сообществах вы найдете смещения ценной информации в ваших играх, такие как цепочка указателей на ваше здоровье.
Это будет записано в следующем формате: BASE_ADDRESS ] + OFFSET1 ] + OFFSET2
В этом синтаксисе "]" означает разыменование (считывание значения).
Это означает, что вы должны разыменовать (прочитать значение) указатель, расположенный по адресу BASE_ADDRESS, затем добавить к этому адресу значение OFFSET1, разыменовать (прочитать значение) все, что там есть, затем добавить к этому адресу OFFSET2 и прочитать этот адрес, чтобы получить значение health.
В нашей фиктивной программе нет смещения, указатель ptr2ptr2 указывает непосредственно туда, где находится ptr2ptr, ptr2ptr указывает непосредственно на ptr2int, а ptr2int указывает на varInt
Поэтому наша цепь:
[АДРЕС ptr2ptr2] ] + 0 ] + 0 ] + 0
Вы можете создать функцию, которая принимает на вход цепной список (вектор), содержащий базовый адрес и последующие смещения (используйте вектор<uintptr_t>)
Это будет следовать за этой цепочкой указателей.
Я не удовлетворен этим упражнением, я улучшу его позже, если это вас смущает, просто пропустите его сейчас.

Открытый процесс халатность
Мы запросили все разрешения для нашего дескриптора с PROCESS_ALL_ACCESS в качестве первого параметра, но нам не нужно так много.
Поскольку мы используем только ReadProcessMemory, прочтите документацию этой функции и запросите минимально необходимое разрешение в нашем вызове OpenProcess.

Еще одна опенпроцессная халатность
С OpenProcess мы запрашиваем ДЕСКРИПТОР, который дает нам система, однако если вы прочтете документацию, то увидите, что мы должны уничтожить его должным образом, когда он нам больше не нужен, чтобы избежать того, что мы называем "утечкой ресурсов".
Прочтите документацию еще раз, найдите, как это делается, и включите ее в свой код.

Чтение текста из var String и varchar
Вы должны уметь читать текст из var String и varchar.
Для этого вы должны адаптировать размер, заданный в качестве параметра ReadProcessMemory, а также иметь буфер, достаточно большой, чтобы содержать прочитанный текст.
Самое простое решение-использовать массив достаточного размера, в противном случае строка объекта C++ позволит вам зарезервировать память с помощью метода, который вы можете попробовать реализовать.

Сделайте несколько ошибок!
Попробуйте прочитать случайный адрес или адрес 0 в целевом объекте и посмотреть, что возвращает ReadProcessMemory и код ошибки, найдите его в списке кодов ошибок MSDN и посмотрите, смогли бы вы понять, почему это не сработало.
То же самое с OpenProcess, что произойдет, если вы попытаетесь открыть несуществующий идентификатор процесса? Какой код ошибки вы получаете от GetLastError()? Можете ли вы понять это?
Что произойдет, если вы получите дескриптор с недостаточными разрешениями? Допустим, вы вызываете OpenProcess только с PROCESS_QUERY_LIMITED_INFORMATION, а затем пытаетесь использовать этот дескриптор с ReadProcessMemory, что происходит? Что говорит код ошибки?

Накачай его!
Вы также можете изменить вывод вашей программы по своему желанию, запросив у пользователя PID и адрес памяти.
Вы также можете спросить пользователя, что мы будем читать: цифры или текст, а также спросить длину текста для чтения, если пользователь хочет прочитать текст.

Пора выпендриваться !!
Когда вы выполнили все эти подзадачи (плюс любое дополнительное улучшение, которое пришло вам в голову) Я хочу, чтобы вы разместили свой код и вывод здесь, на форуме, чтобы показать нам, насколько хорошо и как быстро вы прогрессируете !!
Всегда хорошо немного покрасоваться и получить некоторую поддержку от других страстных людей

Упражнение "Запись": Запись памяти другого процесса
Теперь мы будем записывать в память нашего целевого процесса с помощью WriteProcessMemory.
Хорошая новость: WriteProcessMemory очень похожа на ReadProcessMemory.
В принципе, единственное основное отличие заключается в том, что он записывает то, что находится в буфере, по адресу в другом процессе.


Направления:
Очевидно, вы должны запустить нашу фиктивную программу, чтобы мы могли писать в нее (да!)
Если вы закрыли его после предыдущего упражнения и жестко закодировали PID и/или адреса памяти, не забудьте обновить их.

Начните с чтения всей страницы документации WriteProcessMemory на MSDN (возьмите habbit, чтобы сделать это для всех новых функций, которые нам нужно использовать).
Поскольку эта функция очень похожа на ReadProcessMemory, вы можете повторно использовать наш предыдущий код (однако я советую вам создать новый проект, чтобы сохранить последнее упражнение на случай, если вы захотите вернуться к нему позже).
Единственные различия заключаются в следующем:
- Вы переименуете переменную "intRead" в "intToWrite" ( мне нравятся явные имена переменных ) и инициализируете ее до 987654 (или числа по вашему выбору)
- Вы, очевидно, вызовете WriteProcessMemory вместо ReadProcessMemory, вы можете сохранить тот же код проверки ошибок (просто переименуйте "rpmStatus" в "wpmStatus", измените выводимый текст "ReadProcessMemory failed" на "WriteProcessMemory failed" и другие незначительные корректировки, которые сделают исходный код более чистым и явным)
- Для WriteProcessMemory вторым параметром является не LPCVOID, а LPVOID, поэтому измените type-casting на (LPVOID) вместо этого
- Вместо того, чтобы печатать на консоли "intRead=...", просто напечатайте "Перезаписано успешно" (это и последнее сообщение "Нажмите ENTER, чтобы выйти".)

Как только это будет сделано, просто запустите программу, если у вас нет ошибок и вы видите "Перезаписано успешно" в консоли, как и ожидалось, переключитесь обратно на запущенную фиктивную программу и нажмите enter, чтобы снова напечатать адреса и значения переменных, и вы увидите, что ваш varInt перезаписан на новое значение, как показано на следующем снимке экрана:

скриншот -
Пожалуйста, авторизуйтесь для просмотра ссылки.

Если вы столкнулись с проблемами, обратитесь к разделу "Устранение неполадок" упражнения 1, те же рекомендации применимы и к текущему упражнению.

Проект (C++)
Еще раз: Старайтесь искренне и смотрите на решение только в том случае, если вам это удалось или вы потратили значительное количество времени на попытки.

Еще раз в этом коде я запрашиваю у пользователя PID, адрес памяти и значение для перезаписи. Вы можете реализовать его самостоятельно, прежде чем рассматривать решение как небольшую дополнительную задачу, чтобы получить немного больше опыта, это никогда не повредит.


C++:
#include <Windows.h>
#include <iostream>

using namespace std;

int main() {
    DWORD pid = 0; // The process ID of our target process
    cout << "PID: ";
    cin >> dec >> pid; // Prompting user for PID

    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    if (hProcess == NULL) { // Failed to get a handle
        cout << "OpenProcess failed. GetLastError = " << dec << GetLastError() << endl;
        system("pause");
        return EXIT_FAILURE;
    }

    // Prompting user for memory address to overwrite
    uintptr_t memoryAddress = 0x0;
    cout << "Memory address of the integer to overwrite (in hexadecimal): 0x";
    cin >> hex >> memoryAddress;

    // Prompting user for integer value to overwrite
    int intToWrite = 0;
    cout << "Integer to write (in decimal): ";
    cin >> dec >> intToWrite;

    // Overwriting the integer in the other process
    BOOL wpmReturn = WriteProcessMemory(hProcess, (LPVOID)memoryAddress, &intToWrite, sizeof(int), NULL);
    if (wpmReturn == FALSE) {
        cout << "WriteProcessMemory failed. GetLastError = " << dec << GetLastError() << endl;
        system("pause");
        return EXIT_FAILURE;
    }

    cout << "Overwritten successfully" << endl;
  
    cout << "Press ENTER to quit." << endl;
    system("pause > nul");

    return EXIT_SUCCESS;
}
Идем дальше
Еще раз, вот набор подзадач, которые вы можете сделать, чтобы сделать этот код лучше, экспериментировать дальше и получать все больше и БОЛЬШЕ опыта.


Перезапись текста
Вы можете перезаписать текст в arrochar и в var String.
Поскольку arrChar имеет фиксированный размер, вы можете перезаписать более длинный текст, однако объектная строка varString сохраняет используемую память настолько маленькой, насколько это необходимо, у вас может возникнуть проблема, если вы перепишете ее на более длинную строку текста (но вы можете попробовать посмотреть, что произойдет, просто для lolz и опыта!)

Снова:
Вы можете применить к этому упражнению следующие подзадачи из упражнения 2: "Ошибка OpenProcess", "Другая ошибка OpenProcess", "Сделайте несколько ошибок!" ( делайте другие ошибки, играйте со своим кодом, вы не сломаете свой компьютер, не волнуйтесь ) и "Накачайте его!"

Поздравляю (еще раз) !!
Если вы зашли так далеко, то я вас очень ПОЗДРАВЛЯЮ.
Я призываю вас еще раз покрасоваться и показать нам свой код здесь!

Теперь вы обладаете набором навыков, которые позволяют вам не только кодировать радары и другие типы читов ESP, но и делать такие вещи, как поддержание ваших очков здоровья на максимальном уровне, иметь неограниченное количество пуль, денег или что-то еще.
.. И знаешь что? Именно это мы и будем делать в следующем упражнении !!
Сейчас мы попрощаемся с нашей фиктивной программой и начнем взламывать настоящую игру: AssaultCube !!
Это бесплатно, с открытым исходным кодом и без защиты: идеально подходит для нас, чтобы учиться.
Надеюсь, вы взволнованы, потому что я тоже !


Упражнение "Базовый реверс": Использование Cheat Engine & ReClass на Assault Cube

Для этого упражнения вам нужно будет скачать игру Assault Cube с официального сайта: Assault Cube download.
Установите его и запустите один раз.
Настройте его в оконном режиме, так как мы будем делать что-то, пока он работает.
Я также рекомендую вам поиграть с некоторыми ботами в течение 10-15 минут, чтобы вы увидели, как идет игра и что мы пытаемся взломать.
Пока вы играете, начните думать о том, какие функции взлома вам были бы интересны... потому что ты будешь их кодировать !!
Идите вперед и немного поиграйте сейчас, убейте нескольких врагов, попробуйте оружие, подберите предметы и немного поиграйте.

Если у вас возникли проблемы с мышью (камера сходит с ума):
Вы, вероятно, уже установили игру, и эта ошибка появилась с обновлением Falls Creator Windows 10, удалите ее и переустановите из установщика официального сайта, они заменили SDL.dll файл, который отвечал за это в новом установщике (они обсуждают это на официальном форуме).

Ну что, понравилось?
Это довольно просто, но может быть весело играть с некоторыми друзьями, я признаю, что это быстро надоедает против ИИ.
Есть еще некоторые люди, играющие онлайн, однако я попрошу вас, пожалуйста, не портить опыт другим игрокам.
Ладно, давайте продолжим.

Сначала давайте определим, что такое реверс-инжиниринг.
Мы называем "Обратным инжинирингом" задачу, в которой мы анализируем программу (для которой у нас обычно нет исходного кода) с помощью различных инструментов, таких как дизассемблер, отладчик, сканер памяти и многие другие, чтобы понять, как игра работает внутри.
В нашем случае нас особенно интересуют места памяти ценной информации, такие как наше здоровье, аммос, 3D-положение и другие переменные, количество врагов на карте с их информацией и т. Д...

Ну что ж, давайте начнем с начала игры.
Сначала мы собираемся найти, где хранится информация нашего игрока в памяти с помощью сканера памяти, в этом уроке я буду использовать Чит-движок, но доступны и другие сканеры памяти, такие как Cry Search, закодированные одним из наших талантливых членов.
Я намереваюсь написать это же упражнение снова с Cry Search, чтобы инициировать людей к нему в будущем.
Если у вас нет опыта в обратном инжиниринге, задача может показаться сложной:
"Как, черт возьми, мы собираемся найти во всей памяти, где находится информация о нашем игроке?"
Что ж, функция сканирования памяти Cheat Engine нам очень поможет.
Сканер памяти в основном позволяет вам искать определенные значения в памяти и хранить их в списке, один он сканировал всю память, вы можете искать другое значение среди результатов, которые вы нашли в первый раз.
Это может быть использовано для определения количества пуль, которые у вас есть в магазине, например:
Допустим, у вас есть 20 пуль в магазине, вы сканируете память игры на адреса памяти, равные 20, она находит целую кучу адресов, равных 20, затем вы стреляете пулей, теперь у вас есть 19 пуль в магазине, поэтому вы сканируете среди адресов, которые вы нашли, которые теперь равны 20.
Если у вас все еще слишком много результатов, просто выстрелите еще одну пулю или перезагрузите, чтобы изменить значение, и сканируйте новое значение, пока не определите, где оно находится.
Иногда у вас останется несколько адресов памяти, а не только один, потому что иногда значение хранится в нескольких местах, например, одно является "реальным" значением, а другое просто используется для отображения, затем вы можете поэкспериментировать и проверить, какой из них действительно меняет ваши пули в магазине.

Давайте сделаем это прямо сейчас!
Начните игру или, если она у вас уже началась, создайте матч без других игроков (нажмите Escape, затем перейдите в Single player > Empty map и выберите карту по вашему выбору).
Потратьте секунду, чтобы дать себе ник в игре, если это возможно более 6 символов длиной, вы можете сделать это, перейдя в меню (Escape), затем Настройки > Настройки геймплея.
Теперь запустите чит-движок и прикрепите его к игре, нажав на кнопку изменения цвета в левом верхнем углу справа под надписью "Файл", а затем выберите процесс игры ("ac_client.exe").

Скриншот -
Пожалуйста, авторизуйтесь для просмотра ссылки.

Эй, маленький вопрос для тебя: как ты думаешь, что происходит, когда ты это делаешь?
Как вы думаете, какая функция Windows API вызывается, когда мы "Подключаемся" к игре в Cheat Engine?
Мы сами его использовали!
... Если вы угадали OpenProcess поздравления, вы правы, и теперь вы все больше и больше понимаете, как создаются программы Windows:
Нет никакой черной магии, и даже программы, впечатляющие своей сложностью, такие как Cheat Engine, кодируются с помощью функций, которые вы сейчас учитесь использовать!
И если вы мне не верите, вы можете проверить это в источнике Cheat Engine, но давайте оставим это на потом, когда мы добавим обход Cheat Engine

Хорошо, теперь мы повторим процедуру, которую я описал ранее, мы будем искать ценность нашего аммоса в магазине нашей штурмовой винтовки, которая должна быть 20, если вы еще не стреляли.
В Cheat Engine мы будем искать значение 20, точное значение и тип 4 байта (целые числа традиционно имеют длину 4 байта, а не то, что некоторые значения могут храниться в 2 байтах коротких или 8 байтах uint64_t и т. Д... мы вроде как должны догадываться, но поскольку 4 байта доминируют, мы начинаем с этого).
Оставьте остальные параметры по умолчанию, Cheat Engine имеет интеллектуальные значения по умолчанию, которые работают в большинстве случаев.
Сканирование покажет вам несколько тысяч результатов, как показано на этом рисунке:

Скриншот -
Пожалуйста, авторизуйтесь для просмотра ссылки.


Теперь заходите в игру, стреляйте пулей (или 2-мя это не имеет значения, просто сделайте так, чтобы ценность заряженных в данный момент патронов менялась).
Сканирование на новое значение (нажмите Enter или нажмите кнопку "Next scan", "New scan" фактически удалит текущие результаты)
Теперь у вас должно быть меньше результатов, в моем случае у меня есть только 3 результата в левой панели.
Давайте повторим операцию, выстрелим или перезарядим и отсканируем новое значение.
У вас должно остаться только 2 значения, если это не так, повторите операцию до тех пор, пока у вас не останется только 2 значения.
Вы заметите, что 2 значения меняются каждый раз, когда вы стреляете пулей, это означает, что мы, скорее всего, нашли то, что искали!
Дважды щелкните по 2 адресам на левой панели, чтобы добавить их в список сохраненных адресов (показано в нижней панели):

Скриншот -
Пожалуйста, авторизуйтесь для просмотра ссылки.


Вы можете дважды щелкнуть на "Нет описания" и ввести более красноречивое название, например "Штурмовая винтовка Заряжена Ammos 1" и "Штурмовая винтовка Заряжена Ammos 2", возьмите эту привычку, чтобы вы знали, что нашли позже.
Теперь как узнать, какой из них правильный?
Мы можем экспериментировать и играть со значениями, например, проверить, что происходит, когда вы меняете одно значение, но не другое (просто дважды щелкните по значению в нижней панели и введите новое значение) и выстрелить пулей: 2 значения уменьшаются, это не очень полезно.
Вы также заметите, что одно из значений не изменяет количество пуль на экране.
Хорошо, давайте попробуем установить значение, хранящееся на этом адресе памяти, равным 1, и выстрелить пулей, которая установит его равным 0 и обычно должна заставить нас перезарядиться автоматически.
Продолжайте и попробуйте: Оружие не перезаряжается, и значение на экране показывает другое значение.

Скриншот-
Пожалуйста, авторизуйтесь для просмотра ссылки.


Поэтому этот адрес памяти не тот, который нам нужен, а другой, который хранит "реальное" значение, используемое при стрельбе, перезарядке и т. Д...
Вы можете удалить лишний адрес, чтобы мы сохранили только тот, который нас интересует.
Давайте проверим, что у нас действительно есть правильный адрес: Дважды щелкните значение и установите 20, затем установите флажок слева от адреса памяти в правой панели, который имеет для эффекта "блокировки" значения (перезаписывайте снова и снова значение на то, которое мы хотим) и стреляйте в игре, количество пуль должно быть сохранено до 20.
И вот мы здесь! Неограниченные патроны !!

Скриншот -
Пожалуйста, авторизуйтесь для просмотра ссылки.


Хорошо, теперь давайте посмотрим, что находится в памяти вокруг этого значения.
Щелкните правой кнопкой мыши на адресе в нижней панели и нажмите кнопку "Просмотреть эту область памяти".
Это откроет окно проводника памяти с первым байтом значения по адресу, который вы щелкнули правой кнопкой мыши.
Можете ли вы увидеть что-то интересное в представлении памяти, особенно на правой стороне ASCII-представления?
Обычно вы должны видеть не так далеко свое прозвище:

Скриншот -
Пожалуйста, авторизуйтесь для просмотра ссылки.


Это очень интересно, тот факт, что эти 2 части информации находятся так близко, безусловно, означает, что существует какая-то структура памяти, содержащая всю нашу информацию.
Хорошо, давайте сохраним адрес, где хранится наш ник, в списке сохраненных адресов, для этого просто щелкните правой кнопкой мыши первый символ вашего ника и выберите "Добавить этот адрес в список".

Скриншот -
Пожалуйста, авторизуйтесь для просмотра ссылки.


Мы также можем заметить, что значение заряженной штурмовой винтовки ammos и псевдоним разнесены на 0xD5 байт (в моем снимке экрана 0x278A768 - 0x278A83D), мы подтвердим это, когда будем иметь обратную инженерию всей структуры.
Если вы можете попытаться поместить игру на одну сторону экрана, а представление памяти-на другую (или на дополнительный экран, если он у вас есть), прокрутить немного вверх в представлении памяти и делать что-то в игре, передвигаться, стрелять пулями, подбирать аммосы, доспехи и прочее, вы увидите, что некоторые адреса и значения мигают красным цветом, что указывает на изменения.
Таким образом, вы можете определить свои координаты перемещения, свои ГЭС, свою броню, свои пули и т. Д...
Мы позаботимся о том, чтобы разобраться во всех этих данных позже, не беспокойтесь об этом сейчас.
А теперь я покажу вам нечто ужасное... но не волнуйся я дам тебе решение прямо сейчас

Во-первых, сохраните адреса, которые вы нашли в Cheat Engine (CTRL + S, или Файл > Сохранить как, или нажмите на значок дискеты/сохранить), и сохраните их где-нибудь, на всякий случай.
Сохранив свои результаты, вы можете открыть их позже, что вполне практично.
Теперь выйдите из игры полностью, а затем перезапустите ее.
В вашем все еще открытом чит-движке нажмите на кнопку Прикрепить и снова прикрепите ее к Assault Cube ("ac_client.exe").
Чит-движок спросит вас, хотите ли вы сохранить текущий список адресов/кодов, ответьте "да".
Проверьте значения аммоса и ник, он больше не читает это чертово значение !!
Это происходит потому, что конечные адреса, на которых хранятся данные, меняются каждый раз, когда вы запускаете игру.
Двоичное изображение игры загружается по базовому адресу, а затем выделяет память по адресам, которые невозможно предсказать до запуска.
К счастью, всегда есть способ найти этот конечный адрес, следуя цепочке указателей, которая начинается со статического адреса или, по крайней мере, относительно базового адреса, который мы можем найти процедурно.
Для этого мы будем использовать метод, называемый сканированием указателя.


Сканирование указателя: теория
Хорошо, очистите свой чит-движок или откройте новый его экземпляр.
Найдите текущие пули, которые вы загрузили в свое оружие, сканируя текущие значения, затем стреляйте пулей, повторно сканируйте с новым значением и так далее, пока у вас не будет всего несколько результатов (лично я всегда получаю 2 обновленных значения, когда стреляю)
Найдите "настоящий", изменив значение одного из них, выстрелите еще раз и посмотрите, действительно ли он меняет ваш аммос (тогда это правильный адрес) или нет (тогда это означает, что это не тот адрес).
Как только он у вас есть, дважды щелкните по адресу, чтобы добавить его в список в нижней панели.
Щелкните по нему правой кнопкой мыши и нажмите на кнопку "Поиск указателя по этому адресу", откроется новое окно.
Обычно вы можете оставить параметры по умолчанию на данный момент, на случай, если у вас возникнут проблемы, вот моя конфигурация:

Скриншот -
Пожалуйста, авторизуйтесь для просмотра ссылки.


Если вы не поставили галочку "Показать дополнительные параметры", у вас будет меньше вариантов, и это, скорее всего, будет нормально, только идите и настраивайте параметры, если вы знаете, что делаете или у вас есть проблема.
Вы можете навести курсор над флажками для получения дополнительной справки и информации о том, что делают эти параметры.
Нажмите кнопку Ок, и Cheat Engine выполнит сканирование (это может занять от нескольких секунд до нескольких минут, в зависимости от конфигурации и вашего компьютера)
У тебя должно быть что-то подобное:

Скриншот -
Пожалуйста, авторизуйтесь для просмотра ссылки.


Как видите, Чит-движок нашел в моем случае более 600 000 путей, ведущих к целевому адресу памяти, хранящему значение нашего загруженного аммоса, это очень много, и большинство из них ненадежны, поэтому нам нужно найти цепочки указателей, которые согласованы и работают каждый раз, когда игра запускается.
Держите этот Чит-движок открытым (как главное окно Чит-движка, так и окно сканирования указателя) и выходите из игры, затем перезапускайте его и снова подключайте Чит-движок к игре (он спросит вас, хотите ли вы сохранить список адресов, скажите "Нет", нам не нужен адрес, где был последний запуск ammos, он больше не будет работать).
Еще раз найдите адрес памяти, хранящий ваш загруженный аммос, тем же методом (сканируйте значение, стреляйте, сканируйте новое значение, идентифицируйте "реальный" адрес, изменив значение, если это необходимо)
Как только у вас есть адрес памяти нашего загруженного ammos, скопируйте адрес памяти (вы можете дважды щелкнуть по нему в левой панели, чтобы добавить его в список, а затем дважды щелкнуть по адресу в нижней панели и нажать CTRL + C)
Теперь вернитесь в окно сканирования указателя и нажмите кнопку Сканер указателя > Повторное сканирование памяти - Удаляет указатели, не указывающие на правильный адрес
Откроется новое окно с вопросом, какой новый адрес мы хотим найти, вставьте сюда новый адрес, где находятся наши аммосы.

Скриншот -
Пожалуйста, авторизуйтесь для просмотра ссылки.


Вы можете оставить параметры по умолчанию и нажать кнопку ОК, Cheat Engine будет сканировать снова.
Обычно вы должны видеть, что количество путей указателя уменьшается, повторяйте операцию до тех пор, пока количество путей указателя не уменьшится значительно (закройте игру, найдите адрес памяти загруженного ammos, сканирование указателя для этого адреса).
Как только количество путей указателя не уменьшается при каждом сканировании, сортируйте указатели по смещениям, таким образом, он сначала покажет нам самые короткие цепочки указателей и сначала отсортирует их с наименьшим смещением.

Скриншот -
Пожалуйста, авторизуйтесь для просмотра ссылки.


Мы будем использовать первую цепочку указателей, начиная с базового адреса игры (выделен/выделен синим цветом на изображении)
Дважды щелкните по нему, это добавит его в список в нижней панели главного окна.
Теперь в главном окне дважды щелкните адрес этого недавно добавленного адреса, который должен быть назван "результат pointerscan"
Вы можете видеть, что это не просто прямой адрес памяти, это цепочка указателей, за которой нужно следовать, с базой as "ac_client.exe"+00109B74 затем смещение 148 (неявно шестнадцатеричное, 0x148)
Переименуйте его в "Loaded ammos (pointer chain)" и нажмите кнопку OK.
Теперь выберите его в нижней панели и нажмите кнопку копировать вставить (CTRL + C, CTRL + V, затем нажмите кнопку Вставить).
Дважды щелкните по Описанию новой копии адреса, переименуйте ее в "My Player - Base", затем дважды щелкните по ее адресу и измените указатель 148 на 0

Вы можете задаться вопросом: "Что, черт возьми, означает ac_client.exe + какой-то адрес, что это?"
Это то, что мы называем базовым адресом.
Когда windows создает новый процесс, во время инициализации он помещает двоичный образ программы по определенному адресу, который мы называем "Базовым адресом" для выполнения.
По умолчанию Windows использует адрес 0x00400000 в качестве базового адреса (это не обязательно, но по умолчанию он используется в подавляющем большинстве случаев).
Вы даже можете сделать тест самостоятельно, чтобы проверить, есть ли у вашей игры Assault Cube этот базовый адрес очень просто.
В cheat engine просто нажмите в главном окне "Добавить адрес вручную", а затем в поле адреса напишите "ac_client.exe" (с двойными кавычками " с обеих сторон) и нажмите кнопку ОК, вы увидите в своем списке адресов адрес 00400000:

Скриншот -
Пожалуйста, авторизуйтесь для просмотра ссылки.



Нет никаких причин для загрузки игры по другому адресу, поэтому вместо того, чтобы использовать адрес, который мы нашли при сканировании указателя ("ac_client.exe"+00109B74) мы будем использовать адрес 0x509B74 (0x400000 + 0x109B74).
Дважды щелкните адрес "My Player - Base", который находится в нашем списке адресов в Cheat Engine, и замените базовый адрес "ac_client.exe"+00109B74 по прямому адресу 0x509B74.
Вы можете сделать то же самое для адреса "Заряженный аммос (цепь указателей)", и вы увидите, что он все еще указывает на правильный адрес, и мы все еще можем прочитать количество пуль, заряженных в нашем пистолете (29 для меня, как вы можете видеть на следующем рисунке):

Скриншот -
Пожалуйста, авторизуйтесь для просмотра ссылки.


Итак, теперь мы знаем, что по адресу 0x509B74 есть указатель, и если мы следуем ему ("разыменовываем" его), то приходим к адресу памяти, где количество загруженных ammos равно +0x148
Скорее всего, этот указатель приведет нас к структуре памяти с большим количеством другой ценной информации (например, наш HPs, броня, позиция и т. Д...)
Давайте посмотрим, что, щелкните правой кнопкой мыши на вашем адресе "My Player - Base" и нажмите на кнопку "Browse memory region"
Если у вас его нет или у вас возникли проблемы, вы можете получить его просто нажав в главном окне на Добавить адрес Вручную, поставив галочку и введя 0x509B74 в качестве базового адреса, оставив 0 в качестве первого и единственного понитера и нажав кнопку ОК. Назовите это Моей базой игроков
Хорошо, теперь вы находитесь в средстве просмотра памяти, это позволяет нам видеть байты в памяти по нужному адресу памяти, с адресом справа, шестнадцатеричным представлением байтов посередине и представлением ASCII справа.
Это может быть полезно, если вы смотрите на шестнадцатеричные или строковые значения, но мы ищем десятичные значения, значения с плавающей запятой и т. Д...)
К счастью, у cheat engine есть инструмент, который позволяет нам лучше визуализировать структуры памяти для этого.
Нажмите кнопку "Инструменты" в верхнем меню, затем "Рассечь данные/структуры", откроется новое окно с адресом, который обычно является адресом, на который указывает наша цепочка указателей.
Нажмите на Structures, затем Определите новую структуру и назовите ее "Assault Cube - Player"
Чит-движок спросит вас, хотите ли вы, чтобы он заполнял самые основные типы структуры, используя текущий адрес, скажите "Да" (используя значения, он попытается "угадать", если адрес памяти с большей вероятностью будет содержать целое число, поплавок, строку текста и т. Д... Он может делать ошибки, но мы исправим их вручную)
Оставьте значение по умолчанию для размера (4096), которого должно быть достаточно.

Непосредственно когда вы увидите значения, вы поймете, что у нас есть много ценных данных там:

Скриншот -
Пожалуйста, авторизуйтесь для просмотра ссылки.


Мы можем видеть набор из 3 поплавков последовательно, и это очень интересно, потому что он выглядит как 3D-координаты (X, Y, Z), мы называем это вектором 3 (по сути, поплавком[3])
Теперь поставьте окно сбоку и двигайтесь в игру.
Вы видите, как меняются ценности ?!
Мы нащупали там что-то ценное, это, несомненно, структура памяти вашего игрока.
Как узнать, что такое Vector3?
Ну, не двигайтесь в игре, а просто двигайте мышкой, смотрите вокруг, первый и второй Вектор3 не меняются, а третий меняется.
Таким образом, третий Вектор3-это наши углы обзора!
Вы можете дважды щелкнуть по строке в Cheat Engine и ввести описание, назвать 2 строки соответственно "View X" и "View Y" (третья также является частью вида, но никогда не меняется, для угла обзора мы также называем X, Y и Z "Рысканием", "Тангажем" и "Креном")
У тебя должно быть это:

Скриншот -
Пожалуйста, авторизуйтесь для просмотра ссылки.


Хорошо, теперь что такое 2 первых вектора 3?
Если вы хотите, вы можете попытаться выяснить это самостоятельно, теперь это не трудно, двигаться вокруг, видеть, как они меняются, прыгать, приседать, делать что-то и видеть...

Если вы нашли то, что они оба являются поздравлениями.
Вот как я это понял:
Обе позиции одинаковы, за исключением Z, первая Z всегда выше второй, но если вы приседаете, то разница уменьшается, а если вы снова встаете, расстояние увеличивается...
Это означает, что первое-это положение головы, а первое-положение на земле! (Допустим, это ноги)
Это будет полезно для нас, чтобы сделать aimbot, который всегда стреляет в голову, или нарисовать прямоугольники вокруг игроков (мы можем сделать это только с положением ног и головы).

Упражнение/игра: Переверните все, что вы можете
Ладно, хватит держать вас за руку, я показал вам, как понять, что к чему в этой структуре данных, теперь я хочу, чтобы вы идентифицировали другие вещи в этой структуре памяти, например, где находятся наши ГЭС, броня, заряженные пули (у нас есть смещение для этого!), пули в резерве и все остальное, что вы можете найти !!
Вы можете сохранить свой прогресс, нажав на Файл, затем нажмите "Экспортировать текущую структуру" и введите имя структуры (я назвал ее Assault Cube Player), таким образом, вы можете приостановить реверс-инжиниринг и быстро вернуться к нему позже, не так ли?
Я призываю вас проверить то, что я и другие участники нашли, и показать, если вы нашли что-то, что никто другой не нашел (И, пожалуйста, не обманывайте и не проверяйте исходный код игры! Цель этого упражнения-научиться реинжинирингу, а не читать источник!)

Еще один потрясающе полезный инструмент: ReClass
Хорошо, как только мы нашли все, что могли, и все, что мы хотим, чтобы закодировать наши функции чита, мы можем преобразовать все это в структуру, которую мы будем использовать в нашем чите.
Если вы перевернули игру с помощью ReClass, это программное обеспечение позволит вам напрямую экспортировать вашу структуру в код C/C++, однако я сделал это вручную, чтобы сделать ее очень понятной, используя самоочевидные типы Windows.
Вот что я нашел положил в красивую структуру для вас:


C++:
struct ACPLAYER {
    BYTE    unknown1[0x4];            // +0x0
    POINT3D headPosition;             // +0x4
    BYTE    unknown2[0x24];           // +0x10
    POINT3D position;                 // +0x34
    POINT3D view;                     // +0x40
    BYTE    unknown3[0x8];            // +0x58
    INT32   jumpFallSpeed;            // +0x54
    FLOAT   noClip;                   // +0x58
    BYTE    unknown4[0x14];           // +0x5C
    INT32   isImmobile;               // +0x70
    BYTE    unknown5[0xE];            // +0x74
    INT8    state;                    // +0x82
    BYTE    unknown6[0x75];           // +0x83
    INT32   hp;                       // +0xF8
    INT32   armor;                    // +0xFC
    BYTE    unknown7[0xC];            // +0x100
    INT8    dualPistolEnabled;        // +0x10C
    BYTE    unknown8[0x7];            // +0x10D
    INT32   pistolReserveAmmos;       // +0x114
    INT32   carabineReserveAmmos;     // +0x118
    INT32   shotgunReserveAmmos;      // +0x11C
    INT32   smgReserveAmmos;          // +0x120
    INT32   sniperRifleReserveAmmos;  // +0x124
    INT32   assaultRifleReserveAmmos; // +0x128
    BYTE    unknown9[0x8];            // +0x12C
    INT32   doublePistolReserveAmmos; // +0x134
    BYTE    unknown10[0x4];           // +0x138
    INT32   pistolLoadedAmmos;        // +0x13C
    INT32   carabineLoadedAmmos;      // +0x140
    INT32   shotgunLoadedAmmos;       // +0x144
    INT32   smgLoadedAmmos;           // +0x148
    INT32   sniperRifleLoadedAmmos;   // +0x14C
    INT32   assaultRifleLoadedAmmos;  // +0x150
    BYTE    unknown11[0x4];           // +0x154
    INT32   grenades;                 // +0x158
    INT32   doublePistolLoadedAmmos;  // +0x15C
    INT32   knifeSlashDelay;          // +0x160
    INT32   pistolShootDelay;         // +0x164
    INT32   carabineShootDelay;       // +0x168
    INT32   shotgunShootDelay;        // +0x16C
    INT32   smgShootDelay;            // +0x170
    INT32   sniperRifleShootDelay;    // +0x174
    INT32   assaultRifleShootDelay;   // +0x178
    BYTE    unknown12[0x8];           // +0x17C
    INT32   doublePistolShootDelay;   // +0x184
    BYTE    unknown13[0x7C];          // +0x188
    INT32   numberOfDeaths;           // +0x204
    BYTE    unknown14[0x1D];          // +0x208
    CHAR    nickname[16];             // +0x225
    BYTE    unknown15[0xF7];          // +0x235
    INT8    team;                     // +0x32C
};
Отличная работа!
 
Забаненный
Статус
Оффлайн
Регистрация
29 Авг 2021
Сообщения
21
Реакции[?]
25
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Тема очень хорошая и познавательная! А есть что нибудь насчёт андетекта?
 
Сверху Снизу