Ссылка Intel® 64 and IA-32 Architectures Software Developer’s Manual на сайт для скачивания
В руководствах описывается архитектура и среда программирования архитектур Intel® 64 и IA-32.
Электронные версии этих документов позволяют быстро добраться до нужной информации и распечатать только те страницы, которые вам необходимы.
Руководства пользователя по архитектурам Intel 64 и IA-32 теперь доступны для скачивания. Подробнее смотрите на сайте. Загружайте файлы PDF.
]]>Данной мне властью выкладываю здесь сиё творение, дабы не испытывал нужды человек в поисках инструкции по байтам.
sl = AOBScan("ХХ ХХ ХХ ХХ ХХ");if(sl == nil) then print("No code found!");else j = stringlist_getCount(sl); print("Found:",j); for i = 1, j do print(stringlist_getString(sl,i-1)); end object_destroy(sl);end
Вместо букв "Х" вписываете нужные байты (не обязательно 5 пар, их может быть больше). Если что-то найдёт, то скажет Found: кол-во_адресов и список их, в обратном случае скажет No code found!
Код вставлять в Lua Engine, как его вызывать думаю знаете...
]]>Games for Windows - LIVE это некая программа от мелкософта, которая позволяет играть в инете в игры разных стилей и накапливать "достижения".
В то же время эта программа мешает созданию трейнеров, помещая все данные о здоровье, патронах и тд в защищаемый буфер, доступ к которому ну никак не получить.
В этой теме как раз и хочу получить ответ на решение данной проблемы: как отключить защиту данных от взлома этой дряни?
P.S. как то рассматривая таблицу СЕ для DOW2 я наткнулся на вот такую вещ:
xlive.dll+AB247:ret 0c // Disable XLive
Значит автор таблицы таки нашёл способ вырубить проверку данных, но как это сделать для остальных подобных игр?
]]>Всем доброго времени суток.
Нашел на своих хардах старые сборники статей по геймхакингу, которые до сих пор могут быть очень полезны.
На форуме их уже ранее выкладывали, но ссылки давно умерли, поэтому - я залил эти сборники на свой FTP, где они доступны для свободного скачивания.
Скрытый текст
Автор: MasterGH
Дата: 8 июля 2008 года
Формат: .CHM
Описание:
Отдельная, очень неплохая статья, в которой рассказано, как можно легко создать такие опции, как Бесконечное здоровье и Убийство с одного удара, а также то, как можно сделать фильтр "свой-чужой", и определить где игрок или союзник, а где - враг.
Скачать
Скрытый текст
Название: Game Hacking Book
Автор сборника: Guru.eXe
Авторы статей: часть статей за авторством команды Team-X, остальная часть статей была переведена с других языков ими же.
Дата: Сентябрь 2007 года
Формат: .CHM
Описание:
Большой сборник статей по взлому игр (используя разные инструменты, как то: OllyDbg, Memory Hacking Software, и т.д.) и программированию трейнеров, используя различные языки программирования, а также специальные студии для их создания.
Это интересно:
В команде Team-X состояли люди, которых вы можете узнать на нашем форуме (и я надеюсь, что они простят меня за то, что я собираюсь написать ), а именно:
- Xipho - прошлый ник: lamer[stand]
- MasterGH - прошлый ник: Тарзан
- SER[G]ANT - прошлый ник: `$ERG@NT
- CuBiC - прошлый ник: Cubik
И, пользуясь случаем - передаю всем этим людям большой привет
Скачать
Скрытый текст
Название: Gamehacking Archive
Автор сборника: Razali Rambli
Дата: неизвестно
Формат: .CHM
Описание:
Большой сборник статей по геймхакингу англоязычного содержания, в которых также есть информация по использованию различных инструментов для взлома игр, и написание трейнеров, используя различные языки программирования.
Скачать
теги(если не нужны то удалите) :
Скрытый текст
как вывести консоль в длл , консоль и длл , как вывести информацию из длл , работающая консоль в длл,как вывести консоль из длл
взял код я у @elvis66666, но он у меня не работал вывод информации в консоль через cout<< , добавив строчку freopen("CON","w",stdout); все заработало , что и повлекло сделать статью для таки же как я.
Теперь код выглядит так
Скрытый текст
#define _CRT_SECURE_NO_WARNINGS // у некотрых работает без этого #include <stdio.h>#include <fcntl.h>#include <io.h>using namespace std;void CreateConsole() { int hConHandle = 0;HANDLE lStdHandle = 0;FILE *fp = 0;AllocConsole();freopen("CON", "w", stdout);// <<<<==================== строчка , которую я добавил в код SetConsoleTitle("Cheat DLL Console");HWND hwnd = ::GetConsoleWindow();if (hwnd != NULL) { HMENU hMenu = ::GetSystemMenu(hwnd, FALSE);if (hMenu != NULL) { DeleteMenu(hMenu, SC_CLOSE, MF_BYCOMMAND);DeleteMenu(hMenu, SC_MINIMIZE, MF_BYCOMMAND);DeleteMenu(hMenu, SC_MAXIMIZE, MF_BYCOMMAND); } }lStdHandle = GetStdHandle(STD_OUTPUT_HANDLE);hConHandle = _open_osfhandle(PtrToUlong(lStdHandle), _O_TEXT);fp = _fdopen(hConHandle, "w");*stdout = *fp;setvbuf(stdout, NULL, _IONBF, 0); }
и у меня cout<< стал выводить информацию в консоль из длл
PS если тему добавил не туда , прошу переместить =)
]]>Итак всем привет сегодня я вам покажу самый простой способ поиска оффсетов на примере игры CS:GO.
Перед тем как мы приступим нам понадобится:
1. IDA (у меня pro у вас может быть любая другая).
2. Более менее прямые ручки.
3. Хорошаявнимательность.
Есливы подходите по всем пунктам тогда приступим.
Для начала открываем саму IDA и выбираем "Disassembly a new file", выбираем .dll в нашем случае это "client_panorama.dll".
Следующим действием нажимаем Shift + F12 в итоге мы получаем окно в котором будут строчки.
Далее жмём Ctrl + F (для тех кто не знал), и пишем интересующий нас оффсет как бы это не было банально но я буду искать m_iHealth.
Видим у нас выбило 2 строчки нам нужна первая та что без массива.
Кликаем два раза и нас перебрасывает в другое окно.
Там нам нужно 2 раза кликнуть мышкой по XREF то есть что находится рядом:
После нас опять перекидывает в другое окно где мы видим нужный нам оффсет:
Вот и всё мы нашли нужный нам оффсет.
Всем спасибо за просмотр!
]]>Скрытый текст
Задание! Для закрепления материала из видео. Нужно перевести вот это вот:
Скрытый текст
Send {vkBD}
Send {vk43}
Send {vk52}
Send {vk45}
Send {vk41}
Send {vk54}
Send {vk45}
Send {vk48}
Send {vk45}
Send {vk52}
Send {vk4F}
Send {vk20}
Send {vk41}
Send {vk58}
Send {vk45}
Send {vk20}
Send {vk45}
Send {vk4E}
Send {vk45}
Send {vk4D}
Send {vk59}
в читабельный вид, с помощью *данной или иной программы.Кто 1-й успеет тот, получит:
Скрытый текст
+1 на форуме от меня.
*Там есть 2-я вкладка, как бы инверс. Т.е наоборот не жмешь клавишу получаешь sc vk, а вводишь sc vk символы - получаешь ответ какая клавиша.
Так же пишите, какие способы знаете вы!
KEY.ahk
]]>Добрый день дорогие читатели, хочу предоставить вам переведенный мануал о подробном пояснении работе Античита VAC3
Во-первых: что такое VAC?:
VAC (Valve anti-cheat) - "Анти-Чит система" используется во всех играх valve (CS:GO, TF2, CS:S и т.д.).VAC также работает в других играх,таких как dota 2 или LoadOut.
Как VAC работает?:
VAC использует много способов обнаружения взломов игр, но наиболее распространенный способ обнаружить взлом игры это база данных со всеми "известными" Md5-хэшей Чит программ к valve играм.
VAC начинает работу при открытии Steam и сканирует весь жесткий диск на наличие известных MD5 хэшей чит файлов (хэш это, результат
вычисления контрольный суммы файла, который служит для проверки целостности данных. Обычно хэш MD5 используется для проверки целостности дистрибутивов.)Если VAC обнаруживает у вас(на вашем компьютере-(на жестком-диске)) файл который занесен в базу-читов VAC, то вы еще не получите VAC бан, Ваш аккаунт будет занесен в каталог подозрительных аккаунтов Steam, и в дальнейшем когда вы будите играть в игры с защитой VAC, античит будет производить более тщательное(агрессивное) сканирование вашей системы на использование стороннего ПО.
Также VAC сканирует DNS-кэш и хэши каждого сайта, который Вы посетили (так же, как файлы на вашем жестком диске) и сверяет эти сайты(а точнее их Md5-кэш) с черным списком сайтов Базы VAC.
Затем главный VAC модуль сканирования системы запускается при подключении к защищенным игровым серверам системы VAC. Когда вы подключены к игровому серверу Steam, VAC модуль проверяет память игры на совпадение Md5-хэшей читов, Сигнатур занесенные в черный список VAC.
А также VAC производит мониторинг на вызов левых WinApi функций таких как (VirtualProtect, WriteProcessMemory ит.д)
Он проверяет запущенные процессы, пути расположения исполняемых файлов, и их Md5-хэш, для проверке по базе данных читов VAC.
Сканирует каталог игры на предмет изменения игровых файлов(прозрачные текстуры, левые модификации ит.д)
Как только система VAC Обнаруживает совпадение Md5-Хэша файла по свой базе данных читов VAC, на ваш аккаунт ставится метка для последующей блокировки в системе Steam.
Когда мой аккаунт будет заблокирован в Steam?, после того как использовал чит который уже был обнаружен системой VAC:
VAC банит с задержкой, исходя из сложности чита, который был обнаружен.
Обычно бан от использования публичных читов которые были занесены в базу данных VAC, приходит от 2 часов до 2 дней, в то время как другие VIP-читы(Приватные) могут быть окончательно занесены в базу читов VAC от нескольких недель или месяцев.
Также VAC не отображает никаких сообщений о том что - пример: (вы были забанены за использования стороннего ПО. Ваш аккаунт заблокирован ит.д)
Как можно попробовать обойти систему VAC?
Основным способом системы VAC обнаружение читов является поиск и сравнивая Md5-хэш подписей с базой читов системы VAC.
Но есть и простые способы задержать обнаружение чита системой VAC,
это регулярное изменение имени чита(переименование), изменение Md5-хэша(к примеру: софт HashChanger).
Хотя VAC использует много способов обнаружение Чит-программ, но эти простые способы помогут задержать срок обнаружения VAC системой чита.
И помните только ВЫ и только ВЫ! берете на себя риск блокировки вашего аккаунта Steam.
(Можно использовать способ Ring0)
Если я получу VAC блокировку аккаунта из за 1 игры, я буду заблокирован во всех играх?:
Нет! VAC банит по движку игры, то-есть если вы получили бан в CSS то вам будет закрыт доступ к играм на движке Source Engine( TF2, Hl2, GarrysMod, CS1.6, ит.д) Но на удивление к CS:GO это не относится, вы сможете продолжать играть в онлайн.
Действительно ли VAC такой эффективный?
И да и нет, если говорить относительно других Античитов то да, VAC пожалуй самый лучший,и эффективный античит, но, по сети ходят много случаев что игроки играя с паблик читом, жили спокойно от 3 до 6 месяцев, а и некоторые из них до сих пор играют на своих аккаунтах не находясь в блокировке, - главное грамотное использование!
Цитата из слов автора текста Я использовал паблик версию чита для TF2 хэш изменял, и переименован сам чит, 3 месяца прошло, и я еще не забанен VAC.)
P:S - сам текст был переведен с зарубежного форума!
Источник -http://www.unknowncheats.me/forum/anti-cheat-bypass/128973-does-vac-excactly-work-noob-version.html
]]>
На днях пришла идея в голову создать оффлайн учебник по взлому игр, учебник будет содержать все нужные информации с нашего ресурса.Статьи,Трейнеры,Таблицы и тд.. (Трейнеры,Таблицы буду указывать ссылку на скачивание)
Название проекта GameHackLab Book.
Скачать: GhL_Book 2012
Обновлено 05.08.2012.
// Залил на форум. Garik66
GameHackLabBook_2012_RU.chm
]]>Отладчик - глаза любого хакера/геймхакера. Отладчики позволяют вам выполнять трассировку (отслеживание) выполнения процесса, или проводить динамический анализ. Возможность выполнения динамического анализа абсолютно необходима. Это очень важно, чтобы вы понимали, что такое отладчик, и принцип его работы. Большинство из них предоставляют возможность запускать, останавливать, или выполнять пошагово процесс, устанавливать точки останова, манипулировать регистрами и памятью, и отлавливать случающиеся исключения в исследуемом процессе.
Регистр - это небольшой объем памяти находящийся прямо на центральном процессоре, и доступ к нему - быстрейший метод для процессора, чтобы получить данные. В наборе инструкций архитектуры x86 используются восемь регистров общего назначения: EAX, EDX, ECX, ESI, EDI, EBP, ESP и EBX. Большинство регистров доступны процессору, но мы рассмотрим их только в конкретных обстоятельствах, когда они потребуются. Каждый из восьми регистров общего назначения разработан для своей конкретной работы, и каждый выполняет свою функцию, которая позволяет процессору эффективно выполнять инструкции. Это очень важно - понимать, какой регистр для чего используется, ибо это знание положит фундамент понимания того, как устроен отладчик.
Регистр EAX,так же называемый регистром аккумуляции (или аккумулятором), используется для выполнения расчетов, а также для хранения значений, возвращаемых вызванными функциями. Многие оптимизированные инструкции в наборе инструкций x86 разработаны для перемещения данных именно в регистр EAX и извлечения данных из него, а также для выполнения расчетов с этими данными. Большинство простых операций, таких как сложение, вычитание и сравнение оптимизированы дляиспользования регистра EAX. Кроме того, многие определенные операции, такие как умножение или деление, могут выполняться только в регистре EAX. Как было замечено ранее, возвращенные значения из вызываемых функций хранятся в EAX
Регистр EDX это регистр данных (data register). Этот регистр в основном является дополнительным для регистра EAX, и он помогает хранить дополнительные данные для более сложных вычислений, таких как умножение и деление. Он так же может быть хранилищем данных общего назначения, но обычно он используется в расчетах, выполненных в сочетании с регистром EAX.
Регистр ECX так же называется регистром-счетчиком (count register), он используется в операциях цикла. Часто повторяющиеся операции стоит хранить в упорядоченной пронумерованной строке. Очень важно понимать, что счетчик регистра ECX уменьшает, а не увеличивает значение.
Регистры ESP и EBP соответственно указатель стека (stack pointer) и указатель базы (base pointer). Эти регистры используются для управления вызовами функций и операциями со стеком. Когда функция вызвана, аргументы функции перемещаются (проталкиваются) в стек и следуют по адресу возврата. Регистр ESP указывает на самый верх стека, поэтому он будет указывать на адрес возврата. Регистр EBP указывает на самый низ стека вызовов. В некоторых случаях компилятор может использовать оптимизацию для удаления регистра EBP как указателя кадра, в этих случаях регистр EBP освобождается и может использоваться точно так же, как любой другой регистр общего назначения.
Единственный регистр, который не был разработан для чего-то конкретного - это EBX. Он может использоваться, как дополнительное хранилище данных.
Единственный дополнительный регистр, который стоит упомянуть отдельно, это регистр EIP. Он указывает на инструкцию, которая выполняется в данный момент. Как процессор проходит по двоичному исполняемому коду, EIP обновляется для отображения адреса, по которому в данный момент происходит выполнение.
Стекхранит информацию о том, как вызывается функция, какие параметры она забирает, и что надо вернуть после выполнения функции. Структура стека представляет собой модель "Первый пришел, последний вышел" (FILO, First In, Last Out), когда аргументы проталкиваются в стек для вызова функции, и извлекаются из стека после того, как функция завершит свое выполнение. Регистр ESP используется для отслеживания самой вершины кадра стека, а регистр EBP используется для отслеживания самого низа стека. Стек "растет" от верхних адресов памяти к нижним адресам памяти
События отладчика Отладчик работает как бесконечный цикл, который ждет события отладки. Когда событие для отладки случается, цикл прерывается, и вызывается соответствующий обработчик событий. Когда вызван обработчик событий, отладчик останавливается и ждет указаний, что ему делать дальше.
Вот несколько обычных событий, которые улавливает отладчик:
- · Встреча точки останова (breakpoint)
- · Нарушения памяти (так же называемые нарушениями доступа или нарушением сегментации)
- · Исключения, сгенерированные отлаживаемой программой
Точки останова Возможность остановить отлаживаемый процесс достигается установкой точек останова (breakpoints). Остановив процесс, у вас появляется возможность проверить переменные, аргументы стека, и что находится в памяти без изменения переменных процесса, прежде чем вы сможете записать их. Точки останова - это определенно самая частая вещь, которую вы можете использовать при отладке процесса, и рассмотрим их очень внимательно. Есть три основных вида точек останова: программные (soft breakponit), аппаратные (hardware breakpoint), и памяти (memory breakpoint). Они ведут себя очень похоже, но выполняются очень разными способами.
Программные точки останова используются специально для остановки процессора при выполнении инструкций и это самый частый вид точек останова, который вы будете использовать при отладке приложений. Программный брейкпоинт - это однобитная интсрукция, которая останавливает выполнение отлаживаемого процесса и передает управление обработчику исключений точек останова. В целях понимания как это работает, вам следует знать разницу между инструкцией (instruction) и опкодом (opcode) в ассемблере x86.
Аппаратные точки останова (hardware breakpoints) полезны, когда нужно установить небольшое число точек останова, и отлаживаемая программа не может быть модифицирована. Этот тип точек устанавливается на уровне процессора, в специальных регистрах, называемых регистрами отладки. Типичный процессор имеет 8 регистров отладки (по порядку с DR0 до DR7 соответственно), которые используются для установки и управлением аппаратных точек. Регистры отладки с DR0 до DR3 зарезервированы для адресов точек останова. Это означает, что вы можете использовать лишь 4 аппаратных точки одновременно. Регистры DR4 и DR5 зарезервированы, а регистр DR6 используется, как регистр статуса, который определяет тип события отладки, вызванного встречей точки останова. Регистр отладки DR7 по существу является выключателем (вкл/выкл) аппаратных точек останова, а так же хранит разные состояния точек останова. При установке специальных флагов в регистр DR7, вы можете создать точки останова в следующих состояниях:
- · Останов, когда инструкция выполняется по определенному адресу.
- · Останов, когда данные записываются по адресу.
- · Останов на чтение или запись, но не выполнение.
Аппаратные точки останова обрабатываются таким же способом, как и программные, но их механизм находится на низком уровне. Прежде чем процессор попытается выполнить инструкцию, он сначала проверит, не установлена ли на адрес аппаратная точка. Он так же проверит операторов инструкции, не имеют ли они доступ к адресу, на который установлена аппаратная точка. Если адрес хранится в регистрах отладки DR0-DR3 и условия чтения, записи, или выполнения встречаются, прерывание INT1 приказывает процессору остановиться. Если адрес не хранится в регистрах отладки, процессор выполняет инструкцию и переходит к следующей, и эта проверка выполняется снова, и так далее. Аппаратные точки очень полезны, но у них есть некоторые ограничения. Помимо того, что вы можете выставить только четыре ваших точки в одно время, вы так же можете установить точку только на данные длинной 2 байта. Это может сильно ограничить вас, если вы собираетесь получить доступ к большому участку памяти. Как правило, для обхода этих ограничений вы можете использовать точки останова памяти.В отличие от программных, которые используют событие INT3, аппаратные точки используют прерывание 1 (INT1). INT1 случается для аппаратных точек останова и одноступенчатых событий.
Одноступенчатый означает проход по порядку по инструкциям, что позволяет вам очень близко исследовать участки кода во время изменения наблюдаемых данных.
Точки останова памяти являются не совсем точками останова. Когда отладчик устанавливает точку памяти, он меняет разрешения на регион, или страницу памяти. Страница памяти - это наименьшая размер памяти, которую обрабатывает операционная система. Когда страница памяти выделяется, у нее устанавливаются конкретные разрешения на доступ, которые указывают как эта память может быть доступна. Вот некоторые примеры разрешений на страницу памяти: · Выполнение страницы (page execution)
Дает возможность выполнять, но выдает нарушение, если процесс попытается прочитать или записать данные на страницу.
- · Чтение страницы (Page read) Позволяет процессу только считывать со страницы; любая запись или попытка выполнения вызовут нарушение доступа.
- · Запись страницы (Page write) Позволяет процессу записывать на страницу.
- · Сторожевая страница (Guard page) Любой доступ к сторожевой странице возвращает единовременное исключение, и затем страница возвращается к своему первоначальному статусу.
Большинство операционных систем позволяют вам комбинировать эти разрешения. Например, вы можете иметь страницу памяти, куда вы можете писать и читать, в то время, как другая страница может позволить вам прочитать или выполнить. Каждая операционная система так же имеет присущие функции, позволяющие вам запрашивать конкретные разрешения памяти в месте для особой страницы и изменять их, если понадобится.
Источник: Gray Hat Python. Justin Seitz,Перевод: forum.reverse4you.org M. Chumichev
]]>Более полные справочники:
[ENG]
64-ia-32-architectures-software-developer-vol-2a-manual.pdf
64-ia-32-architectures-software-developer-vol-2b-manual.pdf
Instruction_Set_Reference.pdf
CE ASM Basics 1 (*new)
CE ASM Basics 2 (*new)
CE ASM Basics 3 (*new)
[RU]
Архитектура x86 (*new)
SIMD (MMX, SSE, SSE2, SSE3, SSSE3).
Рассмотрим основные инструкции.
Инструкции можно разделить на три блока
- * CPU (работа над целыми числами),
* FPU (работа над вещественными),
* SIMD инструкции (работа с массивами чисел).
CPU (окно регистров)
CPU(основные команды):
Скрытый текст
MOV
mov рег, рег -записать в левый регистр, значение правого регистра
mov рег,[]-записать в регистр значение памяти
mov [],рег -записать в память значение регистра
Важно. Не забываете указывать размер данных. Байт, 2 байта, 4 байта. Это касается всех инструкций работающих со значением адреса в памяти.
Пример.
mov eax,byte [410000] - занести в eax значение байта
mov eax,word [410000] - занести 2 байта
mov eax,dword [410000] - занести 4 байта
NOP
Эта команда самая знакомая команда. Она стерает код. Это даже и не команда вовсе.
SUB
sub рег,рег -вычесть из левого правый регистр и сохранить в левом
sub рег,размер []- вычесть из регистра значение адреса памяти и сохранить регистре
sub размер [], рег - вычесть из значения адреса в памятизначение регистра и сохранить в памяти
ADD
Тоже самое что и SUB только сложение.
CMP
cmp рег,рег - сравнить регистры
cmp рег, размер [] -сравнить значение регистра и значение памяти
cmp размер [], рег -сравнить значение регистра и значение памяти
*cmp, обычно, ставят сразу перед прыжком.
сmp будет выскакивать, только если вы ставите бряк на чтение, ведь, здесь только сравнение ))
DEC
dec рег - уменьшить значение регистра на единицу
dec размер [] - вычесть значение регистра из значения в памятии сохранить в регистре
sub размер [], рег - вычесть значение значения в памятииз регистра и сохранить в регистре
INC
Тоже самое что и DEC только сложение.
LEA
Вы будите встречать редко, это работа с регистрами.
LEA EAX,[EBX+ECX*4+100]
eax=ebx+ecx*4+100
Эта инструкция нужна лишь для того чтобы вычислить смещение .Просто знайте о ней.
PUSH
push число - добавить в стек (времення память) число
push рег - добавить в стек значение регистра
push размер [] - добавить в значение памяти определённого размера
Эту команду геймхакеры часто применяют для того чтобы быстро сохранить какое-то значение регистра, если регистр нужен для расчётов.
POP
Тоже самое что и PUSH только вытаскивание или восстановление. Вытаскивать нужно в обратном порядке.
Положили 1 2 3 4 5. Вытаскиваем 5 4 3 2 1. Будьте внимательны.
push eax
push ebx
add eax,ebx
sub ebx,eax
pop ebx
pop eax
PUSHAD Сохранение в стек регистров общего назначения edi, esi, ebp, esp, ebx, edx, ecx, eax.
POPAD Восстановлениерегистров общего назначения edi, esi, ebp, esp, ebx, edx, ecx, eax
PUSHF Размещение в вершине стека содержимого регистра флагов flags
POPF Восстановление флагов
XOR
Исключающие или
xor al, 01; изменить значение бита 0 регистра al на обратное
IMUL
Целочисленное умножение
movbx,186
imul eax,bx,8
DIV
Без знаковое деление
• если делитель размером в байт, то делимое должно быть расположено в регистре ax. После операции частное помещается в al, а остаток — в ah;
• если делитель размером в слово, то делимое должно быть расположено в паре регистров dx:ax, причем младшая часть делимого находится в ax. После операции частное помещается в ax, а остаток — в dx;
• если делитель размером в двойное слово, то делимое должно быть расположено в паре регистров edx:eax, причем младшая часть делимого находится в eax. После операции частное помещается в eax, а остаток — в edx.
mov ax,10234
mov bl,154
div bl ;ah=остаток, al=частное
FPU (окно регистров)
Основные FPU(команды):
Скрытый текст
Принцип такой есть 8 регистров ST. Эти регистры как барабан, который можно вращать некоторыми инстукциями. Также можно обратиться к каждомму регистру. Если регистр не указаывается, значит имеете дело с первым ST0 напримере комманды как fld [esi] (тоже самое что fld STO, [esi]).
Существуют инструкции довольно часто встречающиеся:
fld [] - загрузит из памяти в ST0 //fld St1,[] - загрузит в ST1
stp [] - скопирует изSTO в память
fstp [] - выгрузит изSTO в память
ну и так далее...
SIMD(окно регистров)
Эти регистры встречаются довольно редко и в основном в играхстратегиях, т.е. в играх в которых участвует большое количество объектов (юнитов, зданий, и т.п.)
Про эти регистры вы можете посмотреть здесь, если будет нужно.
]]>Наверняка не один я запарился с Alt+Tab, переключаясь из игры в CE и обратно. Тем более есть такие игры, в которых Alt+Tab либо заблочен вообще, либо игра после сворачивания начинала глючить.
Оказывается есть очень простой способ ломать игры с помощью двух компьютеров, подключенных к локальной сети - на одном открываем игру, на другом CE или любой другой взломщик игр или Ollydbg и радуемся, забыв про Alt+Tab Всего то и нужно, какой-нибудь удалённый терминал. С Team Viewer у меня что-то не получилось, ниже описан способ для встроенного в Windows "Подключение к удалённому рабочему столу" сокращённо RDP. Windows у меня Windows 7 SP1 x64. Кто найдёт и проверит нужные патчи для XP, добавим их в этот пост - XP у меня нет, давать непроверенные ссылки не хочу. Итак, поехали.
Патчим Windows 7:
Скрытый текст
1) Скачиваем патчер для RDP, который позволит нам логиниться под одним логином без вылета первого залогинившегося (есть такой недостаток у RDP)
В случае с Windows 7 патчер я нашёл тут
Также патч прикрепил к этому посту. (Проверьте кто-нибудь работает ли патч в XP или другой искать)
В патчере ставим галку "Enable multiple logons per user" и жмём кнопку Patch
Вторая галка "Enable blank password logons" позволяет логиниться с пустым паролем. Кто хочет - ставьте и её или создайте у вашей виндовской учётки пароль.
2) Включаем на основном компьютере, где будут запускаться игры, RDP
Мой компьютер->Свойства->Дополнительные параметры системы->Удалённый дсотуп->Разрешать подключения (с проверкой подлинности или без смотрите сами, без проверки проще)
3) Выбрать пользователей->Добавить->Дополнительно->Поиск, выбираем из списка свою учётку под которым заходите в Windows, ОК 4 раза.
4) На этом же компьютере запускаем ломаемую игру
5) На втором компьютере включаем RDP (Пуск->Программы->Стандартные->Удаленный рабочий стол), вводим IP-адрес компьютера с запущенной игрой, соединяемся с ним, выбрав соответсвующий логин и пароль если есть
6) Должен появиться рабочий стол удалённого компьютера, но без окна с игрой. Запускаем CE или другой взломщик, ломаем Alt+Tab больше не нужен.
Успешно заломал таким способом FlatOut 2, но и с другими играми проблем быть не должно.
За идею с RDP спасибо этому топику и ему топикстартеру Zhoul - интересно, зачем он там локальные политики правил, вроде и так паботает. Правда там XP описывалась...
Concurrent RDP Patcher_forWin7.zip
Патчим Windows 8.1:
Скрытый текст
1) Скачиваем прикрепленный к сообщению файл win81rdp.zip, зеркало.
2) Останавливаем службу "Службы удаленных рабочих столов" (" Remote Desktop Services ")
3) В скачанном архиве видим 4 файла. Нам нужен либо32_termsrv.dll, либо64_termsrv.dll в зависимости от разрядности Windows. Копируем его в каталогc:\Windows\System32\ заменяя оригинальный. Было бы неплохо перед этим сделать копию оригинального файла.
4) Снова запускаем службу "Службы удаленных рабочих столов".
5) Повторяем шаги 2-6из инструкции для Windows 7. Должно заработать.
Кроме того, в Интернете пишут о дополнительных шагах, которые непонятно нужны ли. Вроде бы у меня и так заработало.
1) Прописать в реестре
HKLM\System\CurrentControlSet\Control\Terminal Server\fDenyTSConnections (DWORD) = 0fSingleSessionPerUser (DWORD) = 0
2) В свойствах файлаtermsrv.dll на вкладке Безопасность дать полный доступ к файлу текущему пользователю.
win81rdp.zip
]]>ПС:
Скрытый текст
Не знаю, в какой раздел можно отправить данное видео(
Очень нужно ещё 4 поста, чтобы иметь возможность писать админам в личку.
Это руководство является официальным описанием языка Lua.
lua_5.3_manual_rus.rar
Функции в CE Lua Engine: main.lua (в директории с программой)
Константы CE Lua Engine: defines.lua (в директории с программой)
Отрывок из руководства
Скрытый текст
Здесь приведен полный синтаксис Lua в БНФ. Как обычно в расширенной БНФ, {A} означает 0 или более A, и [A] означает опциональное A. (Для приоритета операторов, см. §3.4.8; для описания терминалов Name, Numeral и LiteralString, см. §3.1.) chunk ::= blockblock ::= {stat} [retstat]stat ::= ‘;’ | varlist ‘=’ explist | functioncall | label | break | goto Name | do block end | while exp do block end | repeat block until exp | if exp then block {elseif exp then block} [else block] end | for Name ‘=’ exp ‘,’ exp [‘,’ exp] do block end | for namelist in explist do block end | function funcname funcbody | local function Name funcbody | local namelist [‘=’ explist] retstat ::= return [explist] [‘;’]label ::= ‘::’ Name ‘::’funcname ::= Name {‘.’ Name} [‘:’ Name]varlist ::= var {‘,’ var}var ::= Name | prefixexp ‘[’ exp ‘]’ | prefixexp ‘.’ Name namelist ::= Name {‘,’ Name}explist ::= exp {‘,’ exp}exp ::= nil | false | true | Numeral | LiteralString | ‘...’ | functiondef | prefixexp | tableconstructor | exp binop exp | unop exp prefixexp ::= var | functioncall | ‘(’ exp ‘)’functioncall ::= prefixexp args | prefixexp ‘:’ Name args args ::= ‘(’ [explist] ‘)’ | tableconstructor | LiteralString functiondef ::= function funcbodyfuncbody ::= ‘(’ [parlist] ‘)’ block endparlist ::= namelist [‘,’ ‘...’] | ‘...’tableconstructor ::= ‘{’ [fieldlist] ‘}’fieldlist ::= field {fieldsep field} [fieldsep]field ::= ‘[’ exp ‘]’ ‘=’ exp | Name ‘=’ exp | expfieldsep ::= ‘,’ | ‘;’binop ::= ‘+’ | ‘-’ | ‘*’ | ‘/’ | ‘//’ | ‘^’ | ‘%’ | ‘&’ | ‘~’ | ‘|’ | ‘>>’ | ‘<<’ | ‘..’ | ‘<’ | ‘<=’ | ‘>’ | ‘>=’ | ‘==’ | ‘~=’ | and | orunop ::= ‘-’ | not | ‘#’ | ‘~’
Инструкция: как добавить готовый скрипт в таблицу Cheat Engine
Иногда проще и быстрее скинуть уже готовый скрипт, чем сохранять всю таблицу, или делать трейнер, но как воспользоваться этим скриптом?
Первым делом, нужно запустить Cheat Engine (если он у вас еще не запущен), после чего - щелкнуть на кнопку "Memory View" ("Отладчик" - в русской локализации):
После того, как откроется окно отладчика - нужно выбрать пункт меню: "Tools" ("Инструменты") -> "Auto Assemble" ("Авто Ассемблер"), или нажать комбинацию клавиш "Ctrl+A".
После того, как откроется окно авто-ассемблера, вам достаточно скопировать готовый скрипт в это окно, и выбрать пункт меню (в окне авто-ассемблера): "File" ("Файл") -> "Assign to current cheat table" ("Добавить скрипт в таблицу"), и закрыть окно.
После всех этих действий в таблице появится новая опция, уже привычного вида, которую можно включать и выключать, нажатием на CheckBox (слева от опции - значок в виде квадратика).]]>
Общие понятия
Авторитарный сервер (или мастер сервер)
На этом сервере хранятся все данные или наиболее важные данные и логика игры. Клиенты просят сервер что-то сделать, сервер пропускает через функции, условия игры и выдает ответ отвечающему или еще и на другие клиенты.
Клиент
На клиенте как правило хранятся данные копии. В зависимости от игры расчеты могут быть и на клиенте, чтобы снять нагрузку на цпу сервера и разгрузить траффик. Как правило расчеты физики, столкновений в сетевых играх стараются либо избежать, либо отводят на клиент или мастер клиент.
Мастер-клиент
Мастер клиент как правило, тот кто создает комнату, игру, лобби. Снимает всю или бОльшую часть нагрузки на серверную сторону. Мастер клиент берет полный или частичный контроль над игрой. А серверная сторона либо передает тупо пакеты между мастер-клиентами и клиентами, либо серверная сторона еще и контролирует как-то игру.
Связи
Авторитарный + клиенты
Авторитарный сервер принимает "вопросы и предложения от клиентов" в течении игры. Реагирует на них и отправляет результаты тому кто спрашивал или еще и тем кто в игре.
Не авторитарный + мастер клиент + клиенты
Игрок, который создал игру примает "вопросы и предложения от клиентов" в течении игры. Реагирует на них и отправляет результаты тому кто спрашивал или еще и тем кто в игре. Т.е. мастер клиент хранит данные, все что происходит в игре синхронизируется с ним. Не авторитарный сервер выступает в качестве посредника рассылки пакетов между игроками минуя NAT.
Частично автоританый + мастер клиент + клиенты
Авторитарный сервер может влиять на игру между мастер клиентом и клиентами. Чем это влияние сильнее, тем больше ограничений в сетевой игре получается. Например. Сервер ведет счет времени на игру между клиентами и мастер клиентами. Если у кого-то так называемая "энергия" закончилась, то сервер, говорит, что Вам нельзя начать новую игру. Пример игры Трагедия Белок. Но я не уверен, что там есть мастер клиент. Возможно там полный контроль авторитарного сервера, т.е. физика и движения рассчитаются не мастер клиентом, а сервером.
Пример того как выглядят система Клиент + Частично авторитарный сервер
Игра-пример с yahoogames про игру поиск грибов игроками в темноте.
Частично авторитарный сервер создает грибы в темноте по интервалу времени. В этом всего лишь и заключается авторитарность. Сервер только создает грибы, когда посчитает нужным. Взятие грибов серверная сторона НЕ КОТРОЛИРУЕТ. В общем этот пример для тех, кто хочет задуматься. Роль сервера и роль клиентов очень гибкая и в задачу разработчика входит много проблем, чтобы не допустить читов. Если разраб ничего делать не будет, будет чит на чите. Разраб преследует концепцию "никогда не доверять клиентам"
Клиентская сторона:
Серверная сторонаПолный проект можно скачать:
Yahoo Games Network SDK.zipДокументация: ссылка
//-----------------------------------------------------------------------------------------------------------------// //Mushroom Example//Created by : Luis Filipe (filipe@seines.pt)//Dec 2010////Source code in this example is in the public domain.// The naruto character model in this demo is copyrighted by Ben Mathis.// See Assets/Models/naruto.txt for more details////-----------------------------------------------------------------------------------------------------------------using UnityEngine;using System.Collections;using System.Collections.Generic;using PlayerIOClient;public class ChatEntry {public string text = "";public bool mine = true;}public class GameManager : MonoBehaviour {public GameObject target;public GameObject PlayerPrefab;public GameObject ToadPrefab;private Connection pioconnection;private List<PlayerIOClient.Message> msgList = new List<PlayerIOClient.Message>(); // Messsage queue implementationprivate bool joinedroom = false;// UI stuffprivate Vector2 scrollPosition;private ArrayList entries = new ArrayList();private string inputField = "";private Rect window = new Rect(10, 10, 300, 150);private int toadspicked = 0;private string infomsg = "";void Start() {// create a random userid System.Random random = new System.Random();string userid = "Guest" + random.Next(0, 10000);Debug.Log("Starting");PlayerIOClient.PlayerIO.Connect("[Enter your game id here]",// Game id (Get your own at playerio.com. 1: Create user, 2:Goto admin pannel, 3:Create game, 4: Copy game id inside the "")"public",// The id of the connection, as given in the settings section of the admin panel. By default, a connection with id='public' is created on all games.userid,// The id of the user connecting. This can be any string you like. For instance, it might be "fb10239" if youґre building a Facebook app and the user connecting has id 10239null,// If the connection identified by the connection id only accepts authenticated requests, the auth value generated based on UserId is added herenull,null,delegate(Client client) {Debug.Log("Successfully connected to Player.IO");infomsg = "Successfully connected to Player.IO";target.transform.Find("NameTag").GetComponent<TextMesh>().text = userid;target.transform.name = userid;// Uncoment the line below to use the Development Serverclient.Multiplayer.DevelopmentServer = new ServerEndpoint("localhost",8184);//Create or join the room client.Multiplayer.CreateJoinRoom("UnityDemoRoom",//Room id. If set to null a random roomid is used"UnityMushrooms",//The room type started on the servertrue,//Should the room be visible in the lobby?null,null,delegate(Connection connection) {Debug.Log("Joined Room.");infomsg = "Joined Room.";// We successfully joined a room so set up the message handlerpioconnection = connection;pioconnection.OnMessage += handlemessage;joinedroom = true;},delegate(PlayerIOError error) {Debug.Log("Error Joining Room: " + error.ToString());infomsg = error.ToString();});},delegate(PlayerIOError error) {Debug.Log("Error connecting: " + error.ToString());infomsg = error.ToString();});}void handlemessage(object sender, PlayerIOClient.Message m) {msgList.Add(m);}void FixedUpdate() {// process message queueforeach(PlayerIOClient.Message m in msgList) {switch(m.Type) {case "PlayerJoined":GameObject newplayer = GameObject.Instantiate(target) as GameObject;newplayer.transform.position = new Vector3(m.GetFloat(1), 0, m.GetFloat(2));newplayer.name = m.GetString(0);newplayer.transform.Find("NameTag").GetComponent<TextMesh>().text = m.GetString(0);break;case "Move":GameObject upplayer = GameObject.Find(m.GetString(0));upplayer.transform.LookAt(new Vector3(m.GetFloat(1), 0, m.GetFloat(2)));// set transform x axis to 0, so the character will be facing forwardupplayer.transform.eulerAngles = new Vector3(0, upplayer.transform.eulerAngles.y, upplayer.transform.eulerAngles.z);// get distance between current position and target position,// we'll need to value to know how much the tween will lastfloat dist = Vector3.Distance(upplayer.transform.position, new Vector3(m.GetFloat(1), 0, m.GetFloat(2)));// create a tween between current and target positioniTween.MoveTo(upplayer, iTween.Hash("x", m.GetFloat(1), "z", m.GetFloat(2), "onstart", "startwalk", "oncomplete", "stopwalk", "time", dist, "delay", 0, "easetype", iTween.EaseType.linear));break;case "Harvest":GameObject hvplayer = GameObject.Find(m.GetString(0));hvplayer.transform.LookAt(new Vector3(m.GetFloat(1), .5f, m.GetFloat(2)));// set transform x axis to 0, so the character will be facing forwardhvplayer.transform.eulerAngles = new Vector3(0, hvplayer.transform.eulerAngles.y, hvplayer.transform.eulerAngles.z);// get distance between current position and target position,// we'll need to value to know how much the tween will lastfloat distance = Vector3.Distance(hvplayer.transform.position, new Vector3(m.GetFloat(1), 0, m.GetFloat(2)));// create a tween between current and target positioniTween.MoveTo(hvplayer, iTween.Hash("x", m.GetFloat(1), "z", m.GetFloat(2), "onstart", "startwalk", "oncomplete", "stopharvest", "time", distance, "delay", 0, "easetype", iTween.EaseType.linear));break;case "Picked":// remove the object when it's picked upGameObject removetoad = GameObject.Find("Toad" + m.GetInt(0));Destroy(removetoad);break;case "Chat":if(m.GetString(0) != "Server") {GameObject chatplayer = GameObject.Find(m.GetString(0));chatplayer.transform.Find("Chat").GetComponent<TextMesh>().text = m.GetString(1);chatplayer.transform.Find("Chat").GetComponent<MeshRenderer>().material.color = Color.white;chatplayer.transform.Find("Chat").GetComponent<chatclear>().lastupdate = Time.time;}ChatText(m.GetString(0) + " says: " + m.GetString(1), false);break;case "PlayerLeft":// remove characters from the scene when they leaveGameObject playerd = GameObject.Find(m.GetString(0));Destroy(playerd);break;case "Toad":// adds a toadstool to the sceneGameObject newtoad = GameObject.Instantiate(ToadPrefab) as GameObject;newtoad.transform.position = new Vector3(m.GetFloat(1), 0.1f, m.GetFloat(2));newtoad.name = "Toad" + m.GetInt(0);break;case "ToadCount":// updates how many toads have been picked up by the playertoadspicked = m.GetInt(0);break;}}// clear message queue after it's been processedmsgList.Clear();}void OnMouseDown() {// this function responds to mouse clicks on the ground// it will send a move request to the server// ignore user input if we're not inside a roomif(!joinedroom)return;Vector3 targetPosition = new Vector3(0, 0, 0);var playerPlane = new Plane(Vector3.up, target.transform.position);var ray = Camera.main.ScreenPointToRay(Input.mousePosition);var hitdist = 0.0f;if(playerPlane.Raycast(ray, out hitdist)) {targetPosition = ray.GetPoint(hitdist);pioconnection.Send("Move", targetPosition.x, targetPosition.z);}}void OnGUI() {window = GUI.Window(1, window, GlobalChatWindow, "Chat");GUI.Label(new Rect(10, 160, 150, 20), "Toadstools picked: " + toadspicked);if(infomsg != "") {GUI.Label(new Rect(10, 180, Screen.width, 20), infomsg);}}public void HarvestAt(float posx, float posz) {pioconnection.Send("MoveHarvest", posx, posz);}public void TryPickup(string id) {pioconnection.Send("Pickup", id);}void GlobalChatWindow(int id) {if(!joinedroom)return;GUI.FocusControl("Chat input field");// Begin a scroll view. All rects are calculated automatically - // it will use up any available screen space and make sure contents flow correctly.// This is kept small with the last two parameters to force scrollbars to appear.scrollPosition = GUILayout.BeginScrollView(scrollPosition);foreach(ChatEntry entry in entries) {GUILayout.BeginHorizontal();if(!entry.mine) {GUILayout.Label(entry.text);} else {GUI.contentColor = Color.yellow;GUILayout.Label(entry.text);GUI.contentColor = Color.white;}GUILayout.EndHorizontal();GUILayout.Space(3);}// End the scrollview we began above.GUILayout.EndScrollView();if(Event.current.type == EventType.keyDown && Event.current.keyCode == KeyCode.Return && inputField.Length > 0) {GameObject chatplayer = GameObject.Find(target.transform.name);chatplayer.transform.Find("Chat").GetComponent<TextMesh>().text = inputField;chatplayer.transform.Find("Chat").GetComponent<MeshRenderer>().material.color = Color.white;chatplayer.transform.Find("Chat").GetComponent<chatclear>().lastupdate = Time.time;ChatText(target.transform.name + " says: " + inputField, true);pioconnection.Send("Chat", inputField);inputField = "";}GUI.SetNextControlName("Chat input field");inputField = GUILayout.TextField(inputField);GUI.DragWindow();}void ChatText(string str, bool own) {var entry = new ChatEntry();entry.text = str;entry.mine = own;entries.Add(entry);if(entries.Count > 50)entries.RemoveAt(0);scrollPosition.y = 1000000;}}
using System;using System.Collections.Generic;using System.Text;using System.Collections;using PlayerIO.GameLibrary;using System.Drawing;namespace MushroomsUnity3DExample {public class Player : BasePlayer {public float posx = 0;public float posz = 0;public int toadspicked = 0;}public class Toad {public int id = 0;public float posx = 0;public float posz = 0;}[RoomType("UnityMushrooms")]public class GameCode : Game<Player> {private int last_toad_id = 0;private List<Toad> Toads = new List<Toad>(); // This method is called when an instance of your the game is createdpublic override void GameStarted() {// anything you write to the Console will show up in the // output window of the development serverConsole.WriteLine("Game is started: " + RoomId);// spawn 10 toads at server startSystem.Random random = new System.Random();for(int x = 0; x < 10; x++) {int px = random.Next(-9, 9);int pz = random.Next(-9, 9);Toad temp = new Toad();temp.id = last_toad_id;temp.posx = px;temp.posz = pz;Toads.Add(temp);last_toad_id++;}// respawn new toads each 5 secondsAddTimer(respawntoads, 5000);// reset game every 2 minutesAddTimer(resetgame, 120000);}private void resetgame() {// scoring systemPlayer winner = new Player();int maxscore = -1;foreach(Player pl in Players) {if(pl.toadspicked > maxscore) {winner = pl;maxscore = pl.toadspicked;}}// broadcast who won the roundif(winner.toadspicked > 0) {Broadcast("Chat", "Server", winner.ConnectUserId + " picked " + winner.toadspicked + " Toadstools and won this round.");} else {Broadcast("Chat", "Server", "No one won this round.");}// reset everyone's scoreforeach(Player pl in Players) {pl.toadspicked = 0;}Broadcast("ToadCount", 0);}private void respawntoads() {if(Toads.Count == 10)return;System.Random random = new System.Random();// create new toads if there are less than 10for(int x = 0; x < 10 - Toads.Count; x++) {int px = random.Next(-9, 9);int pz = random.Next(-9, 9);Toad temp = new Toad();temp.id = last_toad_id;temp.posx = px;temp.posz = pz;Toads.Add(temp);last_toad_id++;// broadcast new toad information to all playersBroadcast("Toad", temp.id, temp.posx, temp.posz);}}// This method is called when the last player leaves the room, and it's closed down.public override void GameClosed() {Console.WriteLine("RoomId: " + RoomId);}// This method is called whenever a player joins the gamepublic override void UserJoined(Player player) {foreach(Player pl in Players) {if(pl.ConnectUserId != player.ConnectUserId) {pl.Send("PlayerJoined", player.ConnectUserId, 0, 0);player.Send("PlayerJoined", pl.ConnectUserId, pl.posx, pl.posz);}}// send current toadstool info to the playerforeach(Toad t in Toads) {player.Send("Toad", t.id, t.posx, t.posz);}}// This method is called when a player leaves the gamepublic override void UserLeft(Player player) {Broadcast("PlayerLeft", player.ConnectUserId);}// This method is called when a player sends a message into the server codepublic override void GotMessage(Player player, Message message) {switch(message.Type) {// called when a player clicks on the groundcase "Move":player.posx = message.GetFloat(0);player.posz = message.GetFloat(1);Broadcast("Move", player.ConnectUserId, player.posx, player.posz);break;case "MoveHarvest":// called when a player clicks on a harvesting node// sends back a harvesting command to the player, a move command to everyone elseplayer.posx = message.GetFloat(0);player.posz = message.GetFloat(1);foreach(Player pl in Players) {if(pl.ConnectUserId != player.ConnectUserId) {pl.Send("Move", player.ConnectUserId, player.posx, player.posz);}}player.Send("Harvest", player.ConnectUserId, player.posx, player.posz);break;case "Pickup":// called when the player is actually close to the harvesting nodeint pickupid = int.Parse(message.GetString(0).Replace("Toad", ""));// Find a toad by its idToad result = Toads.Find( delegate(Toad td) { return td.id == pickupid; } );if(result != null) {// sends everyone information that a toad as been picked up// increases player toad countBroadcast("Picked", result.id);Toads.Remove(result);player.toadspicked++;player.Send("ToadCount", player.toadspicked);} else {// id of the toad doesn't exist, either the player// is trying to cheat, or someone else already picked // that toadstoolConsole.WriteLine("Not found: {0}", pickupid);}break;case "Chat":foreach(Player pl in Players) {if(pl.ConnectUserId != player.ConnectUserId) {pl.Send("Chat", player.ConnectUserId, message.GetString(0));}}break;}}}}]]>
Кому надо для общего образования вот ссылка
(К курсу "Устройство и архитектура ЭВМ")
]]>VirtualAlloc / HeapAlloc / malloc / new
Первый вариант объяснения:
Each API is for different uses. Each one also requires that you use the correct deallocation/freeing function when you're done with the memory.
VirtualAlloc
A low-level, Windows API that provides lots of options, but is mainly useful for people in fairly specific situations. Can only allocate memory in (edit: not 4KB) larger chunks. There are situations where you need it, but you'll know when you're in one of these situations. One of the most common is if you have to share memory directly with another process. Don't use it for general-purpose memory allocation. Use VirtualFree to deallocate.
HeapAlloc
Allocates whatever size of memory you ask for, not in big chunks than VirtualAlloc. HeapAlloc knows when it needs to call VirtualAlloc and does so for you automatically. Like malloc, but is Windows-only, and provides a couple more options. Suitable for allocating general chunks of memory. Some Windows APIs may require that you use this to allocate memory that you pass to them, or use its companion HeapFree to free memory that they return to you.
malloc
The C way of allocating memory. Prefer this if you are writing in C rather than C++, and you want your code to work on e.g. Unix computers too, or someone specifically says that you need to use it. Doesn't initialise the memory. Suitable for allocating general chunks of memory, like HeapAlloc. A simple API. Use free to deallocate. Visual C++'s malloc calls HeapAlloc.
new
The C++ way of allocating memory. Prefer this if you are writing in C++. It puts an object or objects into the allocated memory, too. Use delete to deallocate. Visual studio's new calls HeapAlloc, and then maybe initialises the objects, depending on how you call it.
There are also a couple of other similar functions like SysAllocString that you may be told you have to use in specific circumstances.
Второй вариант:
VirtualAlloc is a specialized allocation from the OS VM system. Allocation's must be made at on an allocation granularity which is architechture dependent. It is one of the most basic forms of memory allocation. VM allocations can take several forms, memory is not nessisarially dedicated or physically backed in RAM (though it can be). It is typically a special purpose type of allocation, either vary large, needs to be shared, must be aligned on a perticular value (performance reasons) or the caller need not use all of this memory at once... etc...
HeapAlloc is essentially what malloc and new both eventually call. It is designed to be very fast and useable under many different types of scenerio's a general purpose allocation. It is the "Heap" in a classic sence. Heap's are actually setup by a VirtualAlloc, which is what is used to initially reserve space from the OS, after this the space is initialized, which is when various tables, lists's and other data structures are configured to maintain and control the operation of the HEAP. Some of that is in the form of dynamically sizing (growing and shrinking), adapting to perticular usages (frequent allocations of some size), etc..
new and malloc are somewhat the same, malloc is essentially an exact call into HeapAlloc( heap-id-default ); new however, can configure object's for C++. C++ will store vtable's onto the heap for each caller. These vtable's are redirect's for execution and form part of what gives C++ it's oo charicteristics like inheratence, function overloading, etc...
Some other common allocation methods; _alloca() and _malloca are stack based, FileMappings's are really VirtualAlloc'd and set with perticualr bit flags's which designate them FILE.
Most of the time, you should allocate memory in a way which is consistant with the use of that memory . new in C++, malloc for C, VirtualAlloc for massive or IPC cases.
*** Note, large memory allocation's by HeapAlloc are actually shipped off to Virtual Alloc after some size (couple hundred k or 16 MB or something I forget, but fairly big
*** EDIT I brefly remarked about IPC and VirtualAlloc, there is also something very neat about a related VirtualAlloc which none of the responder's to this question have discussed.
VirtualAlloc Ex is what one process can use to allocate memory in a different process's address space. Most typically, used in combination to get remote execution in the context of another process via CreateRemoteThread (simular to CreateThread, the thread is just run in the other process).
Тот кто усвоил - молодец.
]]>В системе Windows есть объекты ядра и ИХ описатели. Последние чаще называют дескрипторами, "хендлами", "hadle(s)".
Вот пример использования хендла типа Окно (тип HWND):
int WINAPI MessageBox( __in_opt HWND hWnd, __in_opt LPCTSTR lpText, __in_opt LPCTSTR lpCaption, __in UINT uType);
Сразу напрашивается расшифровка этой абривиатуры HWND. H- handle , WND - window. Получаем handle window.
Для чего нужен этот описатель для казалось бы независимого диалога MessageBox?! Идём в справку MSDN и смотрим:
A handle to the owner window of the message box to be created. If this parameter is NULL, the message box has no owner window.
Оказывается этот параметр, если его указать, свяжет мессагу и описатель HWND. У мессаги появится "хозяин"... Если окно закроется, то и мессага закроется... Разбирать эту связь я не буду, кому надо глянут. Это был просто пример.
Описатели или дескрипторы это структуры данных. Используются в работе разных режимов.
На Windows cуществует два режима. Режим Ядра и "Пользовательский"
Ошибки на уровне Ядра покажут вам Синий экран. Ошибки на Пользовательском уровне должны привести максимум к закрытию пользовательского приложения. "Должны" это не значит, что так и будет, но на все 100% нельзя быть уверенным.
"Режим пользователя" это программирование на WinAPI где мы работаем с дескрипторами Пользовательского режима (а система в свою очередь обрабатывает эти дескрипторы работая с объектами ядра), и если что-то на этом уровне Пользователя пойдёт не так, то в предположительно в худшем случае ваше приложение закроется с критической ошибкой.
"Режим ядра" это тот режим на котором писать программы очень "мерзко", если что, то синий экран. Если опять что-то, то опять синий экран. При чем компьютер после перезагрузки может не запустить операционную систему...
Итак. В Пользовательском режиме Хендлы или дескрипторы это номера, по которым идентифицируются структуры данных в системе. Эти структуры разного размера в зависимости от названия типа хендла. Эти структуры созданы для взаимодействия процессов Пользовательского уровня в обход уровня Ядра.
Более подробнее читаем Рихтера. Глава3.
]]>Ниже я написал ссылки на программы и на сайты с информацией для программистов прямо или косвенно связано с темой.
WDK (без него никак - это первоисточник различной информации)
1) Ctrl2cap
Программа представляет собой драйвер привилегированного режима, обеспечивающий фильтрацию входящего с клавиатуры сигнала до драйвера класса клавиатуры, что позволяет включать верхний регистр при нажатии контрольных клавиш. Фильтрация на этом уровне позволяет изменять и скрывать клавиши, прежде, чем NT даже "увидит" их. Ctrl2cap также показывает, как использовать NtDisplayString() для печати сообщений на голубом экране при инициализации.
Эта программа присоединяется к драйверу класса ядра (как я понял перед HAL) таким образом что может перехватывать IRP_MJ_READ и изменять данные.
По ссылке вы найдете указание на дополнительные источники написания фильтра для калавиатуры, WDM, DDK примеры
More Information
For more information on writing filter drivers (drivers that attach themselves to other drivers so that they can see their input and/or output), here are sources to check out:
The Windows NT and Windows 2000 DDK sample \src\storage\filter\diskperf
The Windows 2000 DDK sample \src\input\kbfiltr
"Examining the Windows NT File System," by Mark Russinovich and Bryce Cogswell, Dr. Dobb's Journal, February 1997
The accompanying file system filter driver, Filemon
2) DebugView (перейти на сайт программы)
Эта программа перехватывает вызовы DbgPrint драйверами устройств и OutputDebugString программами Win32. Это позволяет просматривать и записывать выходные данные сеанса отладки на локальной машине или в Интернете без активного отладчика.
3) MHS
Скачайте исходники MHS. В архиве WinSys найдете исходники по драйверам связанные с эмуляцией клавиатуры на низком уровне и другие примочки анти-анти-читинга. Работу драйвера можно наблюдать DebugView.
]]>Windows API (application programming interfaces) — общее наименование целого набора базовых функций интерфейсов программирования приложений операционных систем семейств Windows и Windows NT корпорации «Майкрософт». Является самым прямым способом взаимодействия приложений с Windows. Для создания программ, использующих Windows API, «Майкрософт» выпускает SDK, который называется Platform SDK и содержит документацию, набор библиотек, утилит и других инструментальных средств.
Английская WinApi32: скачать
Русская справка:
Краткий вариант: перейти
Полный вариант: перейти
Ещё справочник перейти
Предназначение функций сразу видно из названия, вам нужно запомнить только для чего какая функция нужна, а далее лазить только по справочникам для уточнения.
Список функций, которые часто используются при создании трейнера:
Менее используемые
Эта функция позволит понять иерархию созданных процессов в том случае если у игры есть запускающий процесс, а надо патчить память дочернего.
Возвратит ошибку той или иной операции
Когда требуется создать поток в чужом процессе выполнив некоторый код. Например, загрузки dll и выполнения её функций внутри чужого процесса. Или выполнение какой-то функции игры по заданным параметрам и т.д.
Загрузка исполняемого модуля в адресное пространство игры.
Хотел также написать функции которые хорошо бы знать “ВООБЩЕ”, а в итоге понял, что надо посоветовать вам читать полный справочник по WinAPI32. Ссылки можете найти в самом верху.
А теперь более подробнее с примерами на языке Дельфи. Принцип работы одинаков на других языках программирования для платформы Windows32/64
Приминение функций:
FindWindow
IsWindow
GetWindowThreadProcessId
OpenProcess
ReadProcessMemory
CloseHandle
]]>Var
hWn: HWND;
PID, hProc, dwReaded,StartAddr,i,r:DWord;
buf: Byte;
begin
hWn := HWND(FindWindow(nil, PChar('Сапер')));If IsWindow(hWn) Then
Begin
GetWindowThreadProcessId(hWn, PID);
hProc := OpenProcess(PROCESS_VM_READ, False, PID);
Try
If (hProc <> 0) Then
Begin
ReadProcessMemory(hProc, ptr($10056AC), @buf, 1, dwReaded);
SapMap.x := buf;
ReadProcessMemory(hProc, ptr($10056A8), @buf, 1, dwReaded);
SapMap.y := buf;sg.ColCount := SapMap.x; //sg - таблица
sg.RowCount := SapMap.y;
sg.Height:=16*sg.RowCount+3;
sg.Width:=16*sg.ColCount+3;
form1.Height:=16*sg.RowCount+3+48;
form1.Width:=16*sg.ColCount+9;For i := 0 To (sg.ColCount - 1) Do
For r := 0 To (sg.RowCount - 1) Do sg.Cells[i,r] := ' ';StartAddr := $01005361;
For i := 0 To (SapMap.y - 1) Do
Begin
For r := 0 To (SapMap.x - 1) Do
Begin
ReadProcessMemory(hProc, ptr((i*$20) + StartAddr + r), @buf, 1, dwReaded);
If (buf = $8F) Then sg.Cells[r, i] := 'X';
End;
End;End;
Finally
CloseHandle(hProc);
End;End;
end;procedure TForm1.Button1Click(Sender: TObject);Создание трейнера на WinAPI
Создание трейнера на WinAPI. Пример 1
{$R-} {проверка диапазона}
{$S-} {проверка стека}
{$A+} {"выравнивание слов"}program FlatOut;
uses
windows, messages, commctrl; //Используемые модули,только самое нужное!var
WinClass : TWndClass; //переменная класса TWndClass для создания главного окна
hInst : HWND; //Хендл приложения
Handle : HWND; //локальный хендл
Com1 : HWND; //TGroupBox
Com2 : HWND; //TButton
Com3 : HWND; //TButton
Com4 : HWND; //TStaticText
Com5 : HWND; //TStaticText
Com6 : HWND; //TStaticText
Msg : TMSG; //сообщения
hFont : HWND; //хендл шрифта
win : hwnd; //хендл данного окнаvar
WindowName : integer; //имя окна
ProcessId : integer; //ID процесса
ThreadId : integer; //Поток
buf : PChar;
HandleWindow : Integer; //хендл окна игры
write : cardinal;const //id наших контролов
id_1 = 1; //TGroupBox
id_2 = 2; //TButton
id_3 = 3; //TButton
id_4 = 4; //TStaticText
id_5 = 5; //TStaticText
id_6 = 6; //TStaticTextconst
WindowTitle = 'Flat-Out'; //конец формы, начало формы, точный заголовок игры
Address = $01B40C64; //адрес нашего значения в памяти игры
PokeValue = $FFFFFFFF; //значение на которое мы будем менять
NumberOfBytes = 4; //кол-во байт
{$R XPMan.res} //Здесь у меня лежит иконка моего трейнера и манифес,//это для того что бы все контролы были в стиле XP
procedure Cheating; //Собственно сама процедура изменения значения
begin
WindowName := FindWindow(nil,WindowTitle); //находим окно игры
If WindowName = 0 then //или,обьясняем пользователю чтобы он запустил игру
MessageBox(win,'Вначале игра,а потом трейнер.','Ошибка',MB_OK or MB_ICONINFORMATION);
ThreadId := GetWindowThreadProcessId(WindowName,@ProcessId);
HandleWindow := OpenProcess(PROCESS_ALL_ACCESS,False,ProcessId);
GetMem(buf,1);
buf^ := Chr(PokeValue);
WriteProcessMemory(HandleWindow,ptr(Address),buf,NumberOfBytes,write);//пишем в наш адресс наше значение
FreeMem(buf);
CloseHandle(HandleWindow);//конец формы, началоформы, закрываем хэндл, чтобы не вылететь с ошибкой
end;procedure ShutDown; //процедура выхода из программы
begin
DeleteObject(hFont); //удаляем шрифт
UnRegisterClass('Sample Class', hInst); //удаляем окно
ExitProcess(hInst); //закрываем окно
Halt; //на всякий случай
end;procedure About; //наше окно о программе
begin
MessageBox(win, ' [C0DED]: bY g-l-u-k [TeaM - X] ' +#13#10+
' ' +#13#10+
' GreatZzz....: ' +#13#10+
' ' +#13#10+
' Baron_Gede,6aHguT,AllexY ' +#13#10+
' And all TeaM - X Members ! ' +#13#10+
' ' +#13#10+
' Write on pure Delphi (WinAPI) ' +#13#10+
' Сopyright (g-l-u-k)R 2004-2005 ' +#13#10+
' ' +#13#10+
' <!-- m -->[url=http://www.team-x.ru]http://www.team-x.ru[/url]<!-- m --> ' +#13#10+
' e-mail : <!-- e -->[email=g-l-u-k@rambler.ru]g-l-u-k@rambler.ru[/email]<!-- e --> ' +#13#10+
' ' +#13#10+
' GEngine v0.1 ' +#13#10+
' All Right Reserved ',
'About',MB_OK or MB_ICONINFORMATION);
end;function WindowProc(hwnd, msg, wparam, lparam: longint): longint; stdcall; //обработчик сообщений
begin
Result := DefWindowProc(hwnd, msg, wparam, lparam);
case Msg of
WM_COMMAND:
case LoWord(wParam) of
id_2 :
if HiWord(wParam) = bn_Clicked then
About; //если пользователь нажимает на кнопку "About",получат свой About
id_3 :
if HiWord(wParam) = bn_Clicked then
ShutDown; //если выход то......
end;
WM_DESTROY: ShutDown;
end;
end;// НАЧАЛО ПРОГРАММЫ
begin
hInst := GetModuleHandle(nil);with WinClass do
begin
Style := CS_PARENTDC; //стиль класса главного окна
hIcon := LoadIcon(hInstance, IDI_APPLICATION); //иконка программы
lpfnWndProc := @WindowProc; //назначение обработчика сообщений
hInstance := hInst;
hbrBackground := COLOR_BTNFACE + 1; //цвет окна
lpszClassName := 'Sample Class'; //класс окна
hCursor := LoadCursor(0, IDC_ARROW); //активный курсор
end;InitCommonControls;
RegisterClass(WinClass); //регистрация класса в сис-ме
{Создание главного окна программы}Handle := CreateWindowEx(0, 'Sample Class', '[FlatOut] Trainer +1',
WS_OVERLAPPED or WS_SYSMENU or
WS_VISIBLE,
503, 345, 234, 222,
0, 0,
hInst, nil);
{Создание шрифта}
hFont := CreateFont(
-12, 0, 0, 0, 0, 0, 0, 0,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
DEFAULT_PITCH or FF_DONTCARE, 'Terminal');
Com1:=CreateWindow(
'Button',
'Trainer Options:' ,
WS_CHILD or BS_GROUPBOX or WS_VISIBLE,
2,2,222,165, Handle, id_1, hInst,nil);
SendMessage(Com1,WM_SETFONT,hFont,0);
Com2 := CreateWindow(
'Button',
'About',
WS_CHILD or BS_TEXT or WS_VISIBLE,
3, 171, 74, 20,Handle, id_2, hInst, nil);
SendMessage(Com2,WM_SETFONT,hFont,0);
Com3 := CreateWindow(
'Button',
'Quit',
WS_CHILD or BS_TEXT or WS_VISIBLE,
148, 171, 74, 20,Handle, id_3, hInst, nil);
SendMessage(Com3,WM_SETFONT,hFont,0);
Com4 :=CreateWindow(
'Static',
'[F1] :...: More Money' ,
WS_CHILD or SS_LEFT or SS_NOTIFY or WS_VISIBLE,
51,25,117,17,Handle, id_4, hInst,nil);
SendMessage(Com4,WM_SETFONT,hFont,0);
Com5:=CreateWindow(
'Static',
'[C0DED] :...: g-l-u-k [TeaM - X]' ,
WS_CHILD or SS_LEFT or SS_NOTIFY or WS_VISIBLE or WS_DISABLED,
32,145,180,17,Handle, id_5, hInst,nil);
SendMessage(Com5,WM_SETFONT,hFont,0);
Com6:=CreateWindow(
'Static',
'[R.Mouse] :...: About Box ' ,
WS_CHILD or SS_LEFT or SS_NOTIFY or WS_VISIBLE,
26,50,190,17,Handle, id_6, hInst,nil);
SendMessage(Com6,WM_SETFONT,hFont,0);//Цикл сбора сообщений
while(GetMessage(Msg, Handle, 0, 0)) do
begin
TranslateMessage(Msg); //приём сообщений
if (GetAsyncKeyState(vk_f1 ) <> 0) then Cheating; //если нажата клавиша F1,читим игру
if (GetAsyncKeyState(vk_RButton) <> 0) then About; //если нажата правая кнопка мыши,то показываем About
if (GetAsyncKeyState(vk_Escape ) <> 0) then ShutDown;
DispatchMessage(Msg); //удаление сообщений из очереди
end;end.
//Немного оптимизацииСоздание трейнера на WinAPI. Пример 2
…в блокноте файл trainer.rc,который будет содержать следующие строки:
======================trainer.rc============================
100 DIALOG 0, 0, 173, 69
STYLE DS_SETFONT | DS_CENTER | WS_CAPTION | WS_SYSMENU
CAPTION "[FlatOut] Trainer +1"
FONT 8, "Terminal"
{
PUSHBUTTON "About", 102, 2, 52, 36, 15, BS_FLAT
PUSHBUTTON "Close", 101, 132, 52, 38, 15, BS_FLAT
GROUPBOX "Trainer options: ", -1, 1, -1, 172, 51
LTEXT "[C0DED] <--::--> bY g-l-u-k [TeaM - X]", -1, 7, 36, 164, 12, WS_DISABLED
LTEXT "[F1] :.......: More Money", -1, 7, 9, 126, 12, WS_DISABLED
}
======================trainer.rc============================
uses
windows, messages; //Именно по этому наш трейнер должен весить
//меньше,если помните то в прошлой части учебника мы использовали //ещё и commctrl.const
ID_ABOUT = 102; //Номера контролов нашего ресурса
ID_EXIT = 101;
Elapse = 10; //Нужен для таймера
aboutcap = 'About'; //Наш About Dialog
aboutmsg = ' [C0DED]: bY g-l-u-k [TeaM - X] ' +#13#10+
' ' +#13#10+
' GreatZzz....: ' +#13#10+
' ' +#13#10+
' Baron_Gede,6aHguT,AllexY ' +#13#10+
' And all TeaM - X Members ! ' +#13#10+
' ' +#13#10+
' Write on pure Delphi (WinAPI) ' +#13#10+
' copyright (g-l-u-k)R 2004-2005 ' +#13#10+
' ' +#13#10+
' <!-- m -->[url=http://www.team-x.ru]http://www.team-x.ru[/url]<!-- m --> ' +#13#10+
' e-mail : <!-- e -->[email=g-l-u-k@rambler.ru]g-l-u-k@rambler.ru[/email]<!-- e --> ' +#13#10+
' ' +#13#10+
' GEngine v0.1 ' +#13#10+
' All Right Reserved ';WindowTitle = 'Flat-Out'; //Название окна игры
Address = $01B40C64;//Адресс нашего значения
PokeValue = $FFFFFFFF;//наше значение
NumberOfBytes = 4;//Кол-во байтvar
Msg : TMSG;
Win : HWND;
WindowName : Integer;
ProcessId : Integer;
ThreadId : Integer;
hInst : Dword;
Buf : PChar;
HandleWindow : Integer;
Write : Cardinal;{$R trainer.res} //Наш ресурс в котором хранится окно трейнера
//Вот самая интересная часть нашего трейнера,процедура роверки.
//Если TrainerSPY активен,то мы обломим следящего за нашим //трейнером.
function IsTrainerSpyActive:bool;
var
hProcess,hKernel:dword;
addr:pointer;
b:byte;
dummy:cardinal;
proc:pchar;
begin
result:=false;
proc:='WriteProcessMemory';if FindWindowExA(0,0,nil,'Trainer Spy')<>0 then
begin
result:=true;
exit;
end;hProcess:=GetCurrentProcess;
hKernel:=LoadLibrary('kernel32.dll');if hKernel<>0 then
begin
addr:=GetProcAddress(hKernel,proc);
ReadProcessMemory(hProcess,addr,@b,1,dummy);
FreeLibrary(hKernel);
if b=204 then result:=true;
end;end;
//Процедура взлома игры,описывать полностью не буду,опишу только //самое главное.
procedure Cheating;
begin
if IsTrainerSpyActive then //если TrainerSpy запушен, то вырубаемся
begin
MessageBox(0,'Выруби шпион.','Ошибка зашиты',MB_OK or MB_ICONERROR);
exit;
end;WindowName := FindWindow(nil,WindowTitle);
If WindowName = 0 then
MessageBox(win,'Игра должна быть запушенна до трейнера','Ошибка',MB_OK or MB_ICONINFORMATION);ThreadId := GetWindowThreadProcessId(WindowName,@ProcessId);
HandleWindow := OpenProcess(PROCESS_ALL_ACCESS,False,ProcessId);GetMem(buf,1);
buf^ := Chr(PokeValue);
WriteProcessMemory(HandleWindow,ptr(Address),buf,NumberOfBytes,write);
FreeMem(buf);
CloseHandle(HandleWindow);
end;procedure Quit; //процедура выхода из программы
begin
EndDialog(win,0);
Halt;
end;procedure DoTimer; //Дополнительна зашита от шпионов
begin
CreateFileA('C:logwmemory.bin',$40000000,1,nil,2,1,0);
hInst:= GetModuleHandle(nil);
SetTimer(hInst,1,Elapse,@DoTimer);
end;//Обработчик событий нашего окна
function SettingsDlgProc(Window : hWnd; Msg,WParam,LParam : Integer): Integer; StdCall;
begin
case Msg of
wm_InitDialog : begin
end;
wm_Close : DestroyWindow(Win);
wm_Destroy : PostQuitMessage(0);
end;
Result := 0;
case Msg of
WM_COMMAND : begin
if wParam = ID_EXIT then Quit; //Ели нажата кнопка выхода,выходим
if wParam = ID_ABOUT then MessageBox(Win,aboutmsg,aboutcap,MB_OK or MB_ICONINFORMATION);//А это наш //about
end;
end;
end;//Процедура создания главного окна
Procedure RunSettings;
begin
Win := CreateDialog(hInstance,PCHar(100),0,@SettingsDlgProc);
Showwindow(Win,SW_SHOW);
Updatewindow(Win);
end;// Начало программы
begin
RunSettings;while GetMessage(Msg,0,0,0) do
begin
//Цикл сбора сообщений
TranslateMessage(Msg);
if (GetAsyncKeyState(VK_F1) <> 0) then Cheating;//Горячая клавиша
DispatchMessage(Msg);
end;end.
program FlatOut; //Опять будем ломать FlatOutЗаключение.
Можно было заметить как был построен материал. Сначала была дана справочная информация, а затем можно было увидеть применение функций WinApi в коде трейнеров. Как вы понимаете это базовая основа, т.к. некоторые тонкости не освещены. Например, поиск процесса игры по имени процесса, а не по имени окна. Здесь нет функций сканирования сигнатур для поиска адреса внедрения. Нет проверки на повторный запуск трейнера. Нет отмены читов при закрытии трейнера… Читы не выделяются в выделенную память. Байт-код внедряемых игровых инструкций пишется в память игры через байты, которые нужно получать предварительно при компиляции. Я бы эти байты не получал бы таким образом, а получил бы их скомпилировав инструкции в самом трейнере, а затем бы их копировал бы в игровой процесс в выделенную память. Возможно, я ещё что-то забыл указать…
Проект CheatEngine (CE):
Сайт оригинальной версии:
- 1.
2.CheatEngine SVN(слежение за обновлениями исходников)
3.Перейти на форум
Сайт старой русской версии CE 5.5 (может быть обновлю):
- 1.
Проект OllyDbg:
- 1.
Проект MemoryHackingSoftware (MHS):
- 1.
2.Перейти на форум
Проект Artmoney:
- 1.
Проект GameHacking.com:
1. Перейти на форум]]>