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

Блоги

 

[IDA PRO 7] Расширенная фильтрация инструкций по стеку вызовов

Ничего нового, просто из-за ненадобности решил поделится скриптом, который поможет многим в анализе стека вызовов. Кому хочется искать где пишется и используется какой-либо адрес или переменная. Достаточно сделать бряк, скопировать адреса функций из стека вызовов и указать необходимую инструкцию.    Например, нам необходимо узнать что происходить с ebp+arg_0 по ходу выполнения кода десятка  функций по сотне инструкций в каждой.   Вставляем в скрипт адреса из стека вызовов:     Вставляем то, что нужно найти: ebp+arg_0   И в выводе получаем:   Addr | Instruction | ---------------------------------------------- ---------------------------------------------- 0x88B59 -- mov eax, [ebp+arg_0] ---------------------------------------------- 0x2DCA16 -- mov ecx, [ebp+arg_0] 0x2DCA59 -- push [ebp+arg_0]; void * 0x2DCA71 -- movss xmm0, [ebp+arg_4] 0x2DCA9E -- movss xmm0, [ebp+arg_4] ---------------------------------------------- 0x2DC8BC -- push [ebp+arg_0] 0x2DC8DB -- mov ebx, [ebp+arg_0] ---------------------------------------------- 0x1D6D3A -- mov esi, [ebp+arg_0] 0x1D6ED6 -- mov esi, [ebp+arg_0] ---------------------------------------------- 0x1D6F2A -- mov ebx, [ebp+arg_0] 0x1D6F5F -- cmp [ebp+arg_4], 0 0x1D6F87 -- mov eax, [ebp+arg_4] 0x1D717C -- mov byte ptr [ebp+arg_4+3], cl 0x1D71CA -- cmp byte ptr [ebp+arg_4+3], 22h ---------------------------------------------- или например при поиске скорострельности, ставим бряк на адрес инструкции отнимающей патроны, вставляем стек вызовов и фильтруем:   Addr | Instruction | ---------------------------------------------- 0x21068F -- ucomisd xmm1, xmm0 0x21073A -- comiss xmm0, xmm1 0x210792 -- comisd xmm1, xmm0 0x2108EF -- comisd xmm5, xmm0 0x210B4F -- comiss xmm0, ds:flt_4DC2A8 0x211366 -- comisd xmm1, xmm0 0x211478 -- comiss xmm0, xmm1 0x2114FC -- comisd xmm0, [ebp+var_50] 0x211885 -- comiss xmm0, xmm1 0x211915 -- comisd xmm0, ds:dbl_4DC5E8 ---------------------------------------------- 0x222437 -- comiss xmm0, xmm1 0x222452 -- comiss xmm1, xmm0 0x22247E -- comiss xmm1, xmm0 ---------------------------------------------- 0x277321 -- comiss xmm0, ds:dword_4DBFC8 0x2773A5 -- comisd xmm1, qword_895F18 0x277422 -- comiss xmm1, xmm0 0x277446 -- comiss xmm0, xmm1 ---------------------------------------------- Бам, как 2 пальца почесать.   Ссылка на скрипт: https://github.com/partoftheworlD/IDA7_IntructionFilter   В планах написать интерфейс, а то без него как-то не круто. Так же будет подобный плагин для radare2, но позже.

partoftheworlD

partoftheworlD

 

[Alpha protocol] Управление скоростью показа диалогов. Часть 2. Исследование+

Статьи придется растянуть ещё на 1-2 т.к. я свалился с температурой. Но сегодня не об этом, для начала нам необходимо вспомнить структуру построения диалогов.   [B01_P_INTRO_01_000 SoundNodeWave] SpokenText="Ты очнулся, очень хорошо - я не знала, сколько ты проваляешься. Эти транквилизаторы в конце концов перестали действовать." Comment="NOTES[], TRIGGER[], GLOSSARY[]" bMature=False Subtitles[0]=(Text="Ты очнулся, очень хорошо - я не знала, сколько ты проваляешься. Эти транквилизаторы в конце концов перестали действовать.") Необходимо обратить внимание на идентификатор, а точнее на SoundNodeWave, в прошлой статье я забыл указать, что это класс UE3, по сути это звуковой узел, работающий с локализацией, который содержит данные об воспроизводимом файле, а также его характеристиках.   Но для нашей цели, а именно увеличения времени показа субтитров, надо обратить внимание на массив Subtitles, а дальше просто, посмотреть в документацию.     смотрим на структуру array<SubtitleCue>     Линия текста субтитров и время, которое субтитры должны отображаться. Из примера выше:   Text="Ты очнулся, очень хорошо - я не знала, сколько ты проваляешься. Эти транквилизаторы в конце концов перестали действовать."   Вот мы и нашли способ для увеличения времени показа субтитров, имея на руках только гугл и файлы локализации. Да, он относительно долгий (нам надо будет переписать все субтитры, а их там 598 файлов). Можно конечно скрипт написать, который подправит все, но должен же быть способ проще. Но насколько я понял по локализации, то проблема в быстрых субтитрах именно в ней, в нормальной английской версии, субтитры разделены на группы, а в русской все в одной строке.   Eng: [B01_P_INTRO_01_000 SoundNodeWave] SpokenText="Good, you're awake - I wasn't sure how long you'd be under. Those tranquilizers wore off fast." Subtitles[0]=(Text="Good, you're awake - ") Subtitles[1]=(Text="I wasn't sure how long you'd be under. ") Subtitles[2]=(Text="Those tranquilizers wore off fast.") bManualWordWrap=True Comment="NOTES[], TRIGGER[], GLOSSARY[]" bMature=False Rus: [B01_P_INTRO_01_000 SoundNodeWave] SpokenText="Ты очнулся, очень хорошо - я не знала, сколько ты проваляешься. Эти транквилизаторы в конце концов перестали действовать." Comment="NOTES[], TRIGGER[], GLOSSARY[]" bMature=False Subtitles[0]=(Text="Ты очнулся, очень хорошо - я не знала, сколько ты проваляешься. Эти транквилизаторы в конце концов перестали действовать.") В следующей статье, мы будет находить объект SoundNodeWave, реверсить его структуру, восстанавливать в ReClass и писать скрипт в CE, который будет подсовывать в массив SubtitleCue указанное нами время. Или оставить это моим читателям как домашнее задание?

partoftheworlD

partoftheworlD

 

[Alpha protocol] Управление скоростью показа диалогов. Часть 1. Исследование

В игру я не играл, поэтому начнем с того что известно, используется движок в игре Unreal Engine 3. Это на самом деле круто, у движков UE достаточно упорядоченная структура данных, что во многом облегчит исследование и модификацию игры. Покопался в папках игры и нашел файлы с субтитрами, которые привязаны к звуковому диалогу, о чем и была речь в прошлой статье.  Субтитры выглядят вот так:   [E08_D_LELAND_01_003 SoundNodeWave] // идентефикатор воспроизведенного звукового диалога, указывающий миссию, имя персонажа и номер диалога SpokenText="If by home, you mean prison. Mr. Westridge first spoke to you in this room, didn't he?" // Озвученный текст Subtitles[0]=(Text="If by home, you mean prison. ") // Subtitles[1]=(Text="Mr. Westridge first spoke to you in this room, didn't he?") // Субтитры bManualWordWrap=True // Возможно, пропуск диалогов по нажатию кнопки Comment="NOTES[], TRIGGER[], GLOSSARY[]" // ??? (Возможно, добавление в записи, типа логирование диалогов) bMature=False // Цензура     Хех, за 10 минут мы добыли всю нужную информацию для реверса. Пока порядок действий таков:   Найти название идентификатора диалога, поставить на него бряк. Найти функцию, которая читает из файла с диалогами идентификатор, чтобы получить доступ к функции, которая будет считывать диалоги, а после рисует их. А также, найти прямую связь между запуском озвучки с субтитрами.     Продолжение следует...

partoftheworlD

partoftheworlD

 

Разбор работы системы диалогов в играх

Итак, это будет предисловие к основной статье, здесь мы рассмотрим структуру диалогов и как они создаются. Во вторник я освобожусь и уже займусь написанием основной статьи.   Существует всего несколько типов привязки диалогов для показа игроку: К какой-либо ситуации(триггеру) К нажатию клавиш К среднему времени чтения диалога. К озвучке   Чаще всего используется 4 вариант, но есть извращенцы, которые любят смешивать 1-2, 1-3.   Первая привязка это привязка к триггеру, когда игрок подходит к определенному нпц с каким-либо квестовым предметом, то срабатывает триггер и запускается диалог.   Вторая привязка это привязка к нажатию клавиш, т.е подойдя к нпц диалог не будет запущен, пока не будет нажата клавиша.   Третья привязка по времени, обычно в таком варианте используется константа для показа диалогов, значение константы рассчитывается командой специалистов по *заумное название исследований поведения и информации тестировщиков*   Четвертая привязка, субтитры привязываются к озвучке т.е если началась озвучка, то после начинаются рисоваться субтитры, а как только заканчивается воспроизведение файла с диалогом, то и субтитры пропадают.   В играх на UE, Unity диалоги делаются с помощью чертежей, либо написанием кода.

  В других играх через скрипты.   Но что объединяет эти способы? Инициализация пользовательского интерфеса. Парсинг игровых файлов, для загрузки диалогов в память.   Отлично, теперь мы знаем, что нам необходимо искать, либо находить функцию рисования субтитров, через поиск текста в памяти, либо будем искать обработчик/проверку, которая будет проверять запущена ли озвучка, и когда она заканчивается. Скорее всего, используется QueryPerformanceCounter для вычисления момента когда остановится озвучка и выглядит как-то так. rax, rbx, rcx = 0 rax = QueryPerformanceCounter() rbx = GetDialogTime("dialog_+" i "+.wav") rcx = rbx + rax while(bDialogEnabled): if rax > rcx: clear_text(); Dialogs[i]++; else: draw_text(Dialogs[i]) Вдруг это предисловие сможет указать верный путь для тех, кто не хочет ждать когда за него все сделают. Если такие найдутся, то пишите о результатах в комментариях к этой теме(пока что, позже все комментарии будут перенесены в основную статью)

partoftheworlD

partoftheworlD

 

[Dishonored] История о там как решал проблему с русской версией игры

Добро пожаловать на борт, мои юные любители моря и реверса. На этот раз мы решим проблему игры, разработчики которой не стали этого делать уже на протяжении 6 лет.   На весь реверс ушло порядка 50 рюмок рома, 6 подбитых кораблей британской империи и конечно же несколько портовых шл..., ах да, реверс. С языковыми winapi я не работал до этого момента и поэтому пришлось вручную дебажить весь код от инициализации игры, до создания интерфейсов и всякой не интересной ерунды.   Итак, изначально у нас было решение проблемы в виде костылей, что для фикса надо сменить язык в системе или текущую клавиатуру на английский, но кому это нравится? Можете спросить: «Зачем отлаживать код вручную, когда есть трассировка?»
Ну что-ж, мои маленькие пираты ответ прост, игра при использовании трассировки или отладки с обходом вызывает странный код и пропускает вообще все, что нам нужно исследовать, который при отладке с заходом не вызывается.     Всего пришлось дебажить около 10к инструкций, чтобы найти винапи которая выгружает, угадайте что? Правильно, идентификатор локали ввода. После вызова этой функции, у нас и пропадает из трея языковая панель и ломается локаль. Итак, мы нашли виновника, и что нам делать с ним? Нет, мы не будем скидывать разработчиков за борт. (а стоило бы)     Теперь нам нужно понять, как это все работает и откуда берется этот идентификатор локали ввода.   Отправляемся в бухту знаний и таинств…     Гуглим, гуглим, гуглим и наконец нагуглили winapi с именем LoadKeyboarLayout, круто,  отправляемся снова в дом к прекрасной иде, которую за все время нашего путешествия встречаем впервые, переходим на адрес инструкции с функцией выгрузки идентификатора. Вот и весь путь идентификатора.       Нашли мы LoadKeyboarLayout и теперь нас будет интересовать только первый аргумент этой функции, почему так? Да просто потому что мы умеем читать документацию и знаем, что значение первого аргумента равно 409, будет работать как положено, только если дефолтный язык в системе будет английский, для русского языка, необходимо использовать значение 419 это можно найти в мсдн.     В чем же заключалась проблема? Я думаю в лени разработчиков, а если судить о коде, проблему вызывала загрузка английской локали, но если её нет, то и загружать нечего, а значит и выгружать, а значит будут проблемы. Фикс заключается в исправлении значений загружаемой локали для распакованной версии, либо создании загрузчика для стимовской версии, который бы фиксил все это каждый запуск.   Всех с днем пиратства!   P.S Ах, да совсем забыл написать, все эксперименты проводились на распакованной версии игры, без Steam DRM т.к. со Steam DRM весь файл зашифрован и найти что-либо или пропатчить невозможно. Этим утром нашел ещё проблему некорректной инициализации steamapi, из-за чего игра время от времени крашилась. Сам по себе Steam-DRM инициализирует steamapi, но раз мы его вырезали, то естественно будут проблемы при обращении к нему. Для того чтобы решить проблему со steamapi, нам необходимо создать текстовый файл около файла steam_api.dll с именем steam_appid.txt и указать в нем ID игры для принудительно инициализации.    

partoftheworlD

partoftheworlD

 

Временное отсутствие

Привет всем. Я думаю, что меня может не быть на форуме продолжительное время от 2х месяцев в связи с обстоятельствами. Переезд, поиск работы и семейные обстоятельства. Второй момент. Я создал кнопки яндекс кошелька в некоторых темах моего блога. Толку от кнопок нет, т.к. там все по нулям. Поэтому я их удалю. Lua плагины для CE пока делать нет возможности. До встречи в Москве! ) Буду искать работу в новой игровой студии уже в Москве

MasterGH

MasterGH

 

[Counter-Strike Global Offensive]RCS аналог no recoil

Сегодня сделаем Recoil Control System, а точнее его простейшую реализацию. Используя такой способ можно добиться стрельбы в одну точку на любом расстоянии с учетом значений разброса и ускорения отдачи. Все как обычно, открываем иду и ищем смещения.  m_Local m_aimPunch   Ещё необходимо найти адрес управляющий координатами камеры, но это слишком просто чтобы останавливаться на этом. Итак, теперь надо компенсировать отдачу, для этого мы просто складывает старый вектор Punch с новым, можно умножать на 2, но точность будет отличаться на 10-15%.   DWORD m_dwLocal = 0x0; DWORD m_vecAimPunch = 0x0; vec3 m_vecOldPunch = {0,0,0}; auto CLocalPlayer = m->read<DWORD>(dwClient + 0x00C5C86C); auto CClientState = m->read<DWORD>(dwEngine + 0x586A74); vec3 m_vecAngles = m->read<vec3>(CClientState + 0x4D10); vec3 m_vecPunch = m->read<vec3>(CLocalPlayer + m_dwLocal + m_vecAimPunch) static vec3 *tempAngles = new vec3(m_vecAngles); tempAngles->x -= m_vecPunch.x + m_vecOldPunch.x; tempAngles->y -= m_vecPunch.y + m_vecOldPunch.y; tempAngles->z = 0; m->write<vec3>(dwvecAngles + 0x4D10, tempAngles); m_vecOldPunch = m_vecPunch; delete tempAngles; Это конечно не так просто как в Warface, но затруднений вызвать не должно.      

partoftheworlD

partoftheworlD

 

[IDA Pro] Отслеживание интересующего регистра по функции

Сегодня напишем простейшую реализацию функции поиска используемого регистра в коде при статическом анализе, как когда-то показывал этот функционал в radare2. Немного модифицированный скрипт стоит у меня на вооружении для динамического анализа т.е. определяет где впервые адрес появляется, как рассчитывается, дампит смещения и пробует найти сигнатуру на статический адрес в коде. В общем немного подумав и почитав доки по иде, тоже сможете такое сделать без особых проблем.   Скрипт пишется минут за 15-20, но в дальнейшем экономит нереально много времени.   Единственная проблема возникла с получением точно адреса инструкции, во избежании повторений в выводе и была написана альтернатива функции range.  # подключаем необходимые библиотеки import idc # стандартные модуля для общения между идой import idaapi import re # для расширения функционала поиска reg_value = r'.*\[r14\+.*' # то, что будем искать def range_reverse(start, stop): # аналог функции range for i in FuncItems(start): if i < start and i >= stop: yield i ea = ScreenEA() # получение текущего адреса курсора current_function = idaapi.get_func(ea) # получение информации о функции # перебор инструкций по адресам for inst_addr in range_reverse(ea, current_function.startEA): disasm_output = idc.GetDisasm(inst_addr) # вывод дизассемблированной инструкции по её адресу if re.findall(reg_value, disasm_output): # фильтрация по нужному тексту print("0x%X" % inst_addr, disasm_output) Раз скрипт уже написали(скопипастили), приступим к тестам.   И так, у нас есть инструкций работающая со скорострельностью, нам надо посмотреть всякие интересности, типа проверок, что ещё работает с базовым адресом таймера скорострельности и т.д.     Выполняем скрипт и получаем всю информацию о интересующем регистре, так же, чтобы избавится от инструкций чтения и выводить только инструкции записи, можно добавив одну проверку, но с этим вы сами сможете справиться, я надеюсь вы меня не расстроите.     Так же можем отследить как вычисляется база следуя за регистром, переходя двойным кликом по адресу в окне вывода.     Это ведь проще, чем руками скролить функцию под 10-20к инструкций. В общем, если лень, что-то делать — автоматизируй или не делай.  

partoftheworlD

partoftheworlD

 

[IDA Pro] Экспорт информации из старой базы в новую

Тыкался тут на днях в кнопочках у иды и как оказалось у неё есть экспорт, и давно был, просто находятся в самом неожиданном месте. Так что, я был удивлен и расстроен одновременно. А расстроен тем, что я писал плагин для экспорта, руководствуясь словами "раз нет какого-то функционала, то сделай".   Итак, чтобы задампить всю информацию из старой базы надо будет кликнуть на File->Produce file -> Dump database to IDC script.   В итоге ида создаст для нас скрипт со всей информацией, останется лишь после анализа нового файла запустить его и база восстановится. Пример скрипта.     Если вы анализировали дамп, то советую перебазировать его по первому сегменту к 0 старую и новую базу, перед созданием скрипта для экспорта. И восстановление занимает достаточное количество времени(возможно, зависит от того на сколько восстановлена база) поэтому это отличная возможность, чтобы сходить за чаем.

partoftheworlD

partoftheworlD

 

[Grand Theft Auto Online] Поиск скрытых структур за счет игровых скриптов

Необходимые инструменты чтобы начать искать и делать скрытые структуры: OpenIV, Cheat Engine, GTA HLD, какой-нибудь ЯП для автоматизации действий и конечно же GTA. По сути этот метод позволяет использовать нативные вызовы без инъекции/скриптов в игру и делать с ней все что вздумается, спавнить оружие, спавнить машины, накручивать деньги, перемещать других игроков и т.д возможности безграничны. Итак, открываем OpenIV, находим скрипт freemode, экспортируем и декомпилируем с помощью GTA HLD , на выходе получается такой псевдокод.     Нас интересуют только глобальные переменные - Global_XXXX, где XXXX это значение индекса по которому будем вычислять положение скрытой структуры, кстати все это делается в той же функции которая была в прошлой статье про гта и чтобы не создавать костыли, достаточно зареверсить функцию и скопировать из неё код.   Вычисления будут выглядеть примерно так, newGlobalPageBase = struct_array + 8 * (index >> 18 & 0x3F) , таким образом мы получаем страницы памяти по 2Мб в которых будут скрытые структуры, а чтобы получить конкретный адрес, для работы с глобальной переменной,  value = newGlobalPageBase + 8 * (index & 0x3FFFF) Рассмотрим все это на конкретном примере, например на таймере одной из заданий.     Теперь, нам необходимо посчитать, либо индекс до начала структуры 0x40001, либо сразу до значения просто сложив 0x40001+0x454B. Подставляем, индекс в наш код и хоба     У нас есть адрес таймера игрового скрипта, который бы мы не смогли найти вручную с помощью поисковика, просто  потому что это статическое значение. Этот способ проще, быстрее и дает нам безграничные возможности по взлому игры просто тыкаясь в файлы скриптов. Именно таким образом и работает накрутка денег, спавн машин в онлайне, только манипулируя памятью игры.   Благодарности:  Reversal Thread 7h3 7r14ngl3

partoftheworlD

partoftheworlD

 

Основа для нейронной сети основанная на OpenCV

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

partoftheworlD

partoftheworlD

 

Плагин для ведения логов в CE

Плагин ведет историю поиска, отсева, отмены. Логи выглядят следующим образом Для чего может применятся На шаге отсева посмотреть в логах, какое значение искали до этого и какой способ поиска использовали. При неудачных поисках мы просматриваем как и что мы сканировали раньше. Если вообще ничего не получается при сканировании, то логами можно обмениваться. Горячие клавиши, которые настраиваются из окна настроек CE работают и в логах.   Установка: скопировать GHL_log.lua в директорию "/autorun" Lua скрипт:  В комментариях можно написать про ошибки или про идеи улучшения плагина.

MasterGH

MasterGH

 

Скин для Vivaldi

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

partoftheworlD

partoftheworlD

Создаем мультихак, на примере игры Warface [3 часть]

И снова, здравствуйте)) В этой части, мы с вами создадим NoRecoil hack. Здесь, я уже не буду всё разжевывать. Опирайтесь на прошлые статьи, кому что-то не понятно. Открываем дамп из прошлых частей. Поиск по строкам. Для начала, нам нужно найти IGameFramework.   Вводим "Failed to create the GameFramework Interface!".   Двойной клик по строке, попадаем сюда   Через окно перекрестных ссылок, выходим на адрес   Итак, мы нашли адрес IGameFramewrok = 0x1AF7E2C   Теперь, в окне поиска строк, ищем "sp_difficulty"   Двойной клик по строке. Меню перекрестных ссылок. Открываем псевдокод.   Через ReClass x32 восстанавливаем классы. Переходим к написанию кода.   classes.h     Собираем проект. Внедряем в игру. Готово.  

JustHack

JustHack

 

[Grand Theft Auto Online] Stealth money или поиск скрытых структур для получения денег

Необходимые инструменты чтобы начать искать и делать стелс деньги: OpenIV, IDA, Cheat Engine и конечно же GTA с доступом к онлайну. Так же, если вы все собираетесь проделывать на основном аккаунте, то советую после всех манипуляций удалить персонажа и создать нового, так очищается список транзакций(но это не точно). Для начала нам необходимо зайти в одиночный режим, чтобы найти инструкции работающие с деньгами.     Это нам необходимо для того, чтобы не искать деньги в онлайне, в любом случае там найти мы их не сможем. Дальше, переходим в онлайн и так же переходим в дизассемблер. Нам необходимо узнать как рассчитывается rdx.     Ставим бряк на инструкцию mov rdx, [r8+rax*8] и в регистре rdx видим 00007FF739F26820, перейдем на этот адрес в IDA. Да это же массив с указателями на скрытые структуры, нам необходимо найти единственную работающую с деньгами, я думаю вы сами справитесь с этим, поэтому, как только мы нашли структуру связанную с деньгами высчитаем её индекс, он нам пригодится во время эмуляции транзакции.   (00007FF739F268A0 - 00007FF739F26820) / 8 = 0x10  
Теперь, нам придется восстановить смещения, проблема в том, что эта структура работает только с миссиями, ну что ж пойдем работать, но сначала необходимо найти начало структуры внутри указателя на структуру денег, для этого ещё немного по реверсим, зная адрес начала структуры поставим на инструкцию которую нашли до этого бряк с условием.     И идем выполнять миссию, главное получить деньги, поэтому советую выбрать одиночную миссию т.к. во время бряка с условием у вас будет фпс около 3-4 кадров(на моем компуктере миссия в 5 минут растянулась на 2 часа и пришлось перепроходить т.к. бряк не сработал, ага победитель по жизни.). Так что вас ожидает боль и страдания, но как только найдем начало нашей структуры, выставляем сравнение структур с блокировкой текущего состояния структуры и снова идем проходить миссию(в этот раз все будет на много лучше, обещаю)

  После прохождения миссии, снова смотрим в эту структуру, получаем вот такие значения, это и есть смещения работающие с транзакцией.   #1 000000000000004A * 8 = 1 (offset 0x250 ) //активатор транзакциии #2 0000000000000000 * 8 = 5 (offset 0x00 ) //5 счет банка, 4 наличка #3 0000000000000001 * 8 = 3587 (offset 0x08 ) //сумма #4 0000000000000002 * 8 = 1 (offset 0x10 ) //активатор #5 0000000000000003 * 8 = BC537E0D (offset 0x18 ) //хеш #6 0000000000000004 * 8 = 00000000 (offset 0x20 ) //сервисный хеш #7 0000000000000006 * 8 = 57DE404E (offset 0x30 ) //хеш #8 0000000000000007 * 8 = 00000000 (offset 0x38 ) //хеш типа действий #9 0000000000000047 * 8 = 4 (offset 0x238 ) //?? #10 0000000000000048 * 8 = 7 (offset 0x240 ) //?? #11 000000000000000A * 8 = -1 (offset 0x50 ) //?? #12 0000000000000028 * 8 = 0 (offset 0x140 ) //?? #13 0000000000000049 * 8 = 0 (offset 0x248 ) //?? #14 000000000000004B * 8 = 0 (offset 0x258 ) //?? #15 000000000000004F * 8 = 0 (offset 0x278 ) //?? Теперь нам необходимо найти новые хеши вместо нулей, для этого запускаем OpenIV и ищем файл с названием networkshop, и подставляем все хеши из блоков actiontype и services по нашим смещениям, actiontype задает тип транзакции т.е. добавить, отнять деньги и т.д, services задает от кого мы получили деньги, от R*, с гонок, со ставок и т.д.     Комбинаций много, но что делать, халява это дело времязатратное, тем самым перебирая хеши выстраиваем порядок выполнения транзакции, но иногда хеши фиксят, чтобы не допустить распространение читов.   BC537E0D
57DE404E
Эти 2 хеша предустановлены их можно найти в коде тем самым определив и функции работающие с транзакциями. Самое время начать писать код и тестировать. Хеши не рабочие в этом примере кода, чтобы любителям ничего не делать, пришлось пошевелиться.😉 //активация транзакции DWORD64 activate = 0x1; //установка хешей валидации транзакции WriteProcessMemory(hProcess, reinterpret_cast<PBYTE*>(buf + 0x60), &activate, sizeof(activate), 0); DWORD64 value = 0xBC537E0D; WriteProcessMemory(hProcess, reinterpret_cast<PBYTE*>(buf + 0x68), &value, sizeof(value), 0); //установка суммы транзакции int amount = 10000000; WriteProcessMemory(hProcess, reinterpret_cast<PBYTE*>(buf + 0x58), &amount, sizeof(amount), 0); //установка хешей действий и откого будем получать деньги value = 0x762D6BF6; WriteProcessMemory(hProcess, reinterpret_cast<PBYTE*>(buf + 0x70), &value, sizeof(value), 0); value = 0x3B6B7024; WriteProcessMemory(hProcess, reinterpret_cast<PBYTE*>(buf + 0x88), &value, sizeof(value), 0); value = 0x57DE404E; WriteProcessMemory(hProcess, reinterpret_cast<PBYTE*>(buf + 0x80), &value, sizeof(value), 0); //установка для того чтобы транзакция не зависла в ходе выполнения по разным причинам value = 0x7FFFFFFF; WriteProcessMemory(hProcess, reinterpret_cast<PBYTE*>(buf + 0x50), &value, sizeof(value), 0); value = 0x07; WriteProcessMemory(hProcess, reinterpret_cast<PBYTE*>(buf + 0x290), &value, sizeof(value), 0); //куда будем давать деньги 4 наличка, 5 счет банка value = 0x04; WriteProcessMemory(hProcess, reinterpret_cast<PBYTE*>(buf + 0x288), &value, sizeof(value), 0); value = 0x01; WriteProcessMemory(hProcess, reinterpret_cast<PBYTE*>(buf + 0x2a0), &value, sizeof(value), 0); //деактивация транзакции value = 0; WriteProcessMemory(hProcess, reinterpret_cast<PBYTE*>(buf + 0x78), &value, sizeof(value), 0); WriteProcessMemory(hProcess, reinterpret_cast<PBYTE*>(buf + 0x298), &value, sizeof(value), 0); WriteProcessMemory(hProcess, reinterpret_cast<PBYTE*>(buf + 0x2a8), &value, sizeof(value), 0); WriteProcessMemory(hProcess, reinterpret_cast<PBYTE*>(buf + 0x2c8), &value, sizeof(value), 0); Инструкции работающие со значениями в функции.     Ну и результаты, так же я испытываю новый метод поиска подобного функционала, если все пройдет удачно, то скоро будет новая статья, в разы проще этой и быстрее. Ну, что вы молодцы, если дочитали до сюда, можете взять печеньку.      

partoftheworlD

partoftheworlD

 

Скрытые структуры, что это такое и с чем их едят.

Сегодня у нас будет прелюдия перед основной статьей, так что желательно быть готовым ко всему. Поехали. Скрытые структуры, что они из себя представляют? Скрытая структура это какая-то структура находящаяся в любой части используемой кодом структурой(назовем её мега-структурой), обычно мега-структуры огромных размеров(не зря же мы её так назвали) и содержат в себе по 10-100 скрытых структур, в ГТА например она занимает около 105кб. Как вообще игра находит скрытые структуры? Да, как и везде адрес мега-структуры + index * 0x8 для 64 битных приложений. А теперь поговорим о том как они работают, по сути скрытые структуры просто принимают в себя значения, а в коде это выглядит как обычная функция примерно так.

  Если по простому, то скрытые структуры можно представить как обработчики значений, которые работают постоянно, но как только определенное смещение будет равно определенному значению, то что-то случится. Одна из проблем при использовании таких структур им необходимо подавать все переменные в определенном порядке, например, если мы не активируем транзакцию, то и значение передаваемое не будет обработано, оно будет просто пропущено. Находить такие структуры обычным поиском практически не реально, значения попадающие в неё перезаписываются нулями через 10-20 мс в среднем. Поэтому нам и необходим реверс-инжиниринг. Еще одна проблема конкретно для гта, это расширение функционала структуры, а именно получение рабочих хешей, скажем так, хеши нужны для того чтобы транзакция считалась валидной для определенного количества денег, например для значений денег от 100к до 1 миллиона будет один хеш, для того чтобы получить от 1 миллиона до 10 миллионов нужен другой, но об этом расскажу в следующей статье. Думаю, пока информации хватит, если возникнут вопросы по таким структурам, то пишите в комментариях.    

partoftheworlD

partoftheworlD

 

[RTTI] Автоматизация дампа структур класса

Хехей для начала мне лень писать статью с картинками и прочим, кто поймет, тот молодец, а кто нет, значит не особо нужно. Ну в общем я когда-то показывал что можно сделать с динамической типизацией, а точнее с классами, так что мы будем использовать код сканера сигнатур, немного переписав его чтобы сканировать всю память компьютера, чтобы дампить все предметы которые используют выбранный нами класс. Для начала подготовим базу, берем свой сканер сигнатур, либо из паблика. 
Теперь нам необходимо изменить  код который указывает диапазон по которому мы будем брать страницы виртуальной памяти.
Он выглядит примерно так: while(offset < size) { VirtualQueryEx ... Для того, чтобы получить минимальный и максимальный адрес памяти будем использовать GetSystemInfo.
  SYSTEM_INFO si; GetSystemInfo(&si); auto seg_base = si.lpMinimumApplicationAddress; while (seg_base <= si.lpMaximumApplicationAddress) { if (VirtualQueryEx(hProcess, reinterpret_cast<DWORD64*>(seg_base), &mbi, sizeof(MEMORY_BASIC_INFORMATION))) ... Необходимо отфильтровать страницы, чтобы уменьшить время поиска значений и работы программы, для этого добавляем такую проверку.   if ((mbi.State == MEM_COMMIT) && (!(mbi.Protect & PAGE_GUARD)) || (!(mbi.Protect & PAGE_NOACCESS))) Теперь в цикле будем считывать адреса с шагом в 4 байта каждой оставшейся страницы памяти.
  for (auto i = 0; i < mbi.RegionSize; i+=4) { ... ReadProcessMemory(hProcess, reinterpret_cast<PBYTE*>(base + i), &wrBuff, sizeof(wrBuff), nullptr); Настало время для проверки значений, это можно сделать с помощью memcmp и загрузить результат в контейнер для удобного хранения. Выглядит это примерно так.     Из минусов такой способ относительно долгий, повысить скорость работы можно за счет многопоточности.
А из плюсов это дает нам возможность забить на поиски структур хранящих список вещей, списки оружия или же игроков. Т.е. нам достаточно сгенерировать сигнатуру указывающую на нужный нам класс, чтобы находить адреса всех структур, которые используют выбранный нами класс. Сделать ESP, Radar Hack или просто взломать список вещей в инвентаре не прикладывая усилий, вот что я люблю.

partoftheworlD

partoftheworlD

 

[Grand theft Auto Online v1.43] Stealth Money (20 миллионов в секунду) Update 2

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

partoftheworlD

partoftheworlD

Создаем мультихак, на примере игры Warface [2 часть]

Продолжаем создавать наш noflash хак. В этой части, мы восстановим классы и напишем код. Открываем Reclass x32 и создаем новый класс.     Далее, переименовываем название класса в SSystemGlobalEnvironment. Сейчас наш класс очень мал. Нарастите класс до смещения 0x90, используя панель модификации.     Переходим на смещение 0x88, жмем по зеленой стрелке, выбираем тип - Указатель.     Переименовываем указатель в p3DEngine. Ниже строчкой, переименовываем класс в I3DEngine. Спускаемся еще на строчку ниже. Создаём виртуальную таблицу, указав тип VTable.     Открываем и видим, что функций всего 9, а нам нужно 143. Смещение 572 / 4 т.к. 32 битный процесс. Если бы был 64 битный, то делили бы на 8. 143 это и есть наша функция SetPostEffectParam()     Наращиваем количество функций, как делали с классом. Переходим на 143 функцию, двойной клик, вписываем саму функцию. И очищаем лишнее в классе. Далее жмем "генерировать" класс.     Получаем готовый код класса, копируем в удобное место.     Открываем Visual Studio, создаем пустой проект, тип проекта "Библиотека DLL". Добавляем исходный файл main.cpp и заголовочный файл classes.h . В main.cpp подключаем  #include <windows.h> #include "classes.h"   Прописываем нашу функцию void no_flash(){ SSystemGlobalEnvironment* pEnv = (SSystemGlobalEnvironment*)(*(DWORD*)(0x18C23DC)); while (true){ if (!pEnv)continue; I3DEngine* p3DEngine = pEnv->p3DEngine; if (!p3DEngine)continue; p3DEngine->SetPostEffectParam("Flashbang_Time", 0, true); } }   В точке входа пишем CreateThread(0, 0, (LPTHREAD_START_ROUTINE)no_flash, 0, 0, 0);   Открываем файл classes.h и вставляем туда сгенерированный код из ReClass. В итоге файл classes.h будет выглядеть вот так     Собираем проект. Внедряем в игру. Готово.    

JustHack

JustHack

Создаем мультихак, на примере игры Warface [1 часть]

Итак, мы вооружились всеми нужными инструментами и поверхностным пониманием того, что будем делать. Теперь, можно приступать к самому интересному 👀 В этой части, перед нами стоит задача найти SSystemGlobalEnvironment и I3DEngine. Сразу скажу, что буду разжевывать максимально подробно, дабы избежать лишних вопросов (а как сдампить, а как открыть перекрестные ссылки и т.п.). Поэтому, не обижайтесь на меня, профи этого дела, кому это покажется слишком "жидким"😆   Запускаем игру, открываем PeTools и делаем полный дамп   Далее, запускаем IDA PRO и выбираем "новый проект"   Открываем наш дамп игры. Выбираем   IDA PRO, предложит указать расположение 3 библиотек. Выбираем место установки игры и нажимаем ОК.   Дождёмся, пока IDA проанализирует файл. Вы услышите звуковый сигнал, по окончании. Также, можно будет видеть надпись "idle" (в простое).   После окончания анализа, открываем список всех строк. Через меню View или нажав Shift+F12.   Жмем Ctrl+F и вводим "ai_CompatibilityMode"   Двойной клик по строке и оказываемся тут   Выделяем строку и жмем 'X', в открывшемся окне перекрестных ссылок, нажимаем ОК   Оказываемся тут   dword_18C23DC это и есть адрес нашего SSystemGlobalEnvironment = 0x18C23DC. Можете переименовать сразу (выделив и нажав 'N' ), можете оставить так. Кому как удобнее. Самое главное мы нашли. Теперь нам нужно найти  I3DEngine и SetPostEffectParam. Повторяем шаги с поиском SSystemGlobalEnvironment , только теперь вводим "Dof_Active" в строке поиска.     Нашли, выделили, перешли в окно перекрестных ссылок, выбираем первую и жмем ОК.   Попадаем сюда   Выделяем, жмем 'F5', для перехода к псевдокоду. Видим такую запись.    Выделяем смещение '+136', жмем ПКМ, переводим в HEX.   И получаем SSystemGlobalEnvironment + 0x88 это и есть смещение до I3DEngine
  В итоге имеем: SSystemGlobalEnvironment = 0x18C23DC SSystemGlobalEnvironment + 0x88 = I3DEngine   Продолжение следует...

JustHack

JustHack

Создаем мультихак, на примере игры Warface [Введение]

Привет всем, кто это читает, а может даже, пытается повторить)) По просьбам некоторых злодеев с форума, дискорда и ютуба, я буду пытаться написать цикл статей, по созданию мультихака через внутренние классы, на примере игры Варфейс. А может, я не буду вас мучать и ограничимся всего 1-2 публикациями. Всё зависит от вашего интереса и моего свободного времени. Все описанные действия, могут быть реализованы в какой-то степени и в других играх, на движке CryEngine3. Итак, начнем пожалуй с самого простого, а далее будем двигаться к более сложному. Здесь не будет объяснений, что такое дизассемлер, указатели, классы, интерфейсы, смещения и прочее. Если вы не знаете, что это, то вам придется самостоятельно восполнять эти пробелы. Движок CryEngine3, сделан на основе глобальных объектов. Глобальные объекты завёрнуты в одну структуру и являются указателями на абстрактные сущности, которые инициализируются в нужный момент, в нужном месте программы. Никаких дополнительных накладных расходов, никаких лишних надстроек, контроль за типом во время компиляции. CryEngine3 представляет собой достаточно старый проект, где все интерфейсы устаканились, а новое прикручивается подобно тому, что существует на данный момент. Поэтому нет необходимости придумывать дополнительные обёртки или способы работы с глобальными объектами. SSystemGlobalEnvironment - это основной базовый класс, где хранятся указатели на "стартовые классы". Примерное описание и содержание можно посмотреть на GitHub. Т.к. мы решили начать с самого простого, то на этом этапе, мы сделаем хак, который будет убирать эффект ослепления от светошумовых гранат (антислепа / noflash). Для этого, нам понадобится класс - I3DEngine; Он находится по такому пути SSystemGlobalEnvironment->I3DEngine. И вызвать метод SetPostEffectParam (ознакомиться)       Итак, наша задача найти адрес базового класса SSystemGlobalEnvironment, затем указатель на I3DEngine, восстановить класс и вызывать метод SetPostEffectParam, с нужными нам параметрами. Делов то ?
Необходимый софт: Официальный SDK движка Visual Studio 2015+ PeTools IdaPro версии 6.6+ ReClass x32      Продолжение следует...

JustHack

JustHack

 

[JS] Старая творческая студия для youtube

Начал учить JS еще и из-за того, что меня ютуб начал раздражать перекидывая постоянно на новый дизайн творческой студии, даже если переходить на классический и писать матерные слова в окне фидбека. Так, что если я не один такой, то вот скрипт для Tampermonkey и его альтернатив под разные браузеры. Скрип во время загрузки страницы подменяет новый адрес кнопки ведущий на обновленный дизайн, на старый.   // ==UserScript== // @name Old youtube video manager // @version 0.1 // @author partoftheworlD // @include https://www.youtube.com/* // ==/UserScript== (function() { function replace_C() { var vm_button = document.querySelector("a.yt-uix-button.yt-masthead-picker-button.yt-masthead-picker-button-primary.yt-uix-sessionlink.yt-uix-button-default.yt-uix-button-size-default"); if(vm_button && vm_button.href.includes("dashboard") || vm_button.href.includes("studio")) { vm_button.href = "/my_videos?ar=1&o=U"; vm_button.text = "Творческая студия"; } } document.addEventListener('DOMContentLoaded', replace_C()); })();  

partoftheworlD

partoftheworlD

×

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

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