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

MasterGH

Ветераны
  • Постов

    2 999
  • Зарегистрирован

  • Победитель дней

    129

Весь контент MasterGH

  1. Началось закрытое бета-тестирование CE 5.6. Была мало описана первая же критическая ошибка на Windows 7 вызвавшая BSOD не понятно при каких действиях. На офруме CE всё сильнее и сильнее поднимается ажиотаж на реализ новой версии.
  2. В CE добавлены улучшения и удобства в окне расструктуризации.. Вот что теперь реализовано по просьбе юзера, который пишет весьма сложные скрипты по CE.
  3. Создание пустого окна на Дельфи без VCL (8 кб с пакером) Главная программа. Program Api; uses Forms, WindowTrainer in 'WindowTrainer.pas', cnst in 'cnst.pas', CEcheats in 'CEcheats.pas'; begin WindowCreateTrainer; end. Модуль Окна WindowTrainer unit WindowTrainer; interface uses windows, messages; procedure WindowCreateTrainer; var window:TWndClassEx; Mwindow: HWND; Mmsg: MSG; implementation uses cnst; // Процедура обработки сообщений function WindowProc (wnd: HWND; msg: integer; wparam: WPARAM; lparam: LPARAM):LRESULT;STDCALL; begin case msg of WM_Destroy: begin PostQuitMessage (0); Result := 0; Exit; end; else Result := DefWindowProc(wnd,msg,wparam,lparam); end; end; procedure WindowCreateTrainer; begin // Ристрация класса окна window.cbSize := sizeof (window); window.style := CS_HREDRAW or CS_VREDRAW; window.lpfnWndProc := @WindowProc; window.cbClsExtra := 0; window.cbWndExtra := 0; window.hInstance := HInstance; window.hIcon := LoadIcon (0,IDI_APPLICATION); window.hCursor := LoadCursor (0,IDC_ARROW); window.hbrBackground:=Color_BtnFace+12; window.lpszMenuName := nil; window.lpszClassName := 'frmTrainer'; RegisterClassEx (window); // Создание окна на основе созданного класса Mwindow := CreateWindowEx(0,'frmTrainer',trname, WS_OVERLAPPEDWINDOW - WS_MAXIMIZEBOX+WS_EX_TOOLWINDOW-WS_THICKFRAME,100,100,300,300,0,0,Hinstance,nil); // Показать созданное окно SHOWWINDOW (Mwindow,SW_Show); // Цикл обработки сообщений while GetMessage (Mmsg,0,0,0) do begin TranslateMessage (Mmsg); DispatchMessage (Mmsg); end; end; Получаем 15 кб на Дельфи 10,а если сжать пакером, то около 9 кб
  4. Сразу перейдите на 21 пост этой темы "Создание трейнера для начинающих на VCL" А если вы знаете Дельфи, то перейдём к тонкостям Дельфи. Источник: Взято с античата. Передача аргументов. Никогда не передавай функции в качестве параметра структуру, лучше передавать указатель на нее //Ни в коем случае не делай так. Procedure code (Data:TStructure); //Правильный вариант Procedure code (PData:PStructure); //гда PStructure = ^TStrucrur Старайся передавать своим функциям не более трех параметров, т.к. они передаются через регистры (по соглашению fastcall, принятом по умолчанию в Delphi), а все остальные через стек. Функции - инварианты Довольно распространенная ошибка программистов – присутствие функций - инвариантов в цикле. //Неоптимизированный вариант While i<= lstrlen(str) do Begin X:=x+ord(str[i]); Inc(i); End; Очевидно, что длина str не меняется, но компилятор считает, что все, что передается по ссылке сожжет быть изменено, и lstrlen вычисляется много раз. Оптимизированный вариант выглядит так. //Так лучше N:=lstrlen(str); While i<= n do Begin X:=x+ord(str[i]); Inc(i); End; Экономия памяти Когда класс располагается в памяти, то между полями появляются пустые ячейки памяти. Это происходит потому, что Delphi, оптимизируя код, каждое поле располагает от предыдущего со сдвигом в 4 байта. // Неоптимизированный вариант TMyClass = class private field1: boolean;//1 байт field2: longint; //4 байт field3: char; //1 байт field4: string; //4 байт field5: byte; //1 байт field6: integer; //4 байт field7: byte; //1 байт public procedure code; end; Реально этот экземпляр класса будет занимать 28 байт. Если мы изменим порядок полей, то сможем добиться уменьшения размера до 16 байт. В нашем примере после field1 размером 1 байт идет field2 размером 4 байта, значит, мы теряем 3 байта на выравнивание. Если же размер field2 не превышал 3 байт, то Delphi не стал бы выравнивать, а поместил бы это поле сразу после первого. Код: // Оптимизированный вариант TMyClass = class private field1: boolean; //1 байт field3: char; //1 байт field5: byte; //1 байт field7: byte; //1 байт field2: longint; //4 байт field4: string; //4 байт field6: integer; //4 байт public procedure code; end; [*:29vn0yvr]Компиляция без RTL (Run Time Library) Как известно минимальный размер скомпилированной в Delphi программы с настройками по умолчанию равен 13,5 Кб. Виной тому принудительно подключаемая Delphi RTL, в которой реализованы некоторые возможности языка Delphi. Для уменьшения размера скомпилированных прог исправим модели System.pas и SysInit.pas, удалив все «лишнее». Затем перекомпилируем их и полученные dcu-файлы поместим в папку с прогой. Минимальный System.pas unit System; interface procedure _HandleFinally; type TGUID = record D1: LongWord; D2: Word; D3: Word; D4: array [0..7] of Byte; end; PInitContext = ^TInitContext; TInitContext = record OuterContext: PInitContext; ExcFrame: Pointer; InitTable: pointer; InitCount: Integer; Module: pointer; DLLSaveEBP: Pointer; DLLSaveEBX: Pointer; DLLSaveESI: Pointer; DLLSaveEDI: Pointer; ExitProcessTLS: procedure; DLLInitState: Byte; end; implementation procedure _HandleFinally; asm end; end. Минимальный SysInit.pas unit SysInit; interface procedure _InitExe; procedure _halt0; procedure _InitLib(Context: PInitContext); var ModuleIsLib: Boolean; TlsIndex: Integer = -1; TlsLast: Byte; const PtrToNil: Pointer = nil; implementation procedure _InitLib(Context: PInitContext); asm end; procedure _InitExe; asm end; procedure _halt0; asm end; end. Компиляция Dcc32.exe – Q System.pas SysInit.pas –M –Y –Z -$D- -O Экстремально маленький Hello Word! на Delphi. Собирать исполняемый файл линкером от Microsoft. К сожалению, майкрософтовкий линкер понимает только COFF и Intel OMF, наотрез отказываясь работать с Borland OMF. Delphi же, начиная с третьей версии, перешла с формата Intel OMF на Borland OMF. Поэтому компилировать придется компилятором от Delphi 3. Unit HelloWord; Interface Procedure Start; Implementation Function MessageBoxA(hWnd:cardinal; IpText, IpCaption:Pchar; uType:Cardinal): Integer; stdcall; external ‘user32.dll’ name ‘_MessageBoxA@16’; Procedure Start; Begin MessageBoxA(0,’Hello word!’,nil,0); End; End. Ти модуля Unit нужен для того, чтобы компилятор сгенерировал в объектном файле символьные имена объявленных процедур. Компилируем: Dcc32.exe –JP -$A-,B-,C-,D-,G-,H-,I-,J-,L-,M-,O+,P-,Q-,R-,T-,U-,V-,W+,X+,Y- HelloWord.pas Открываем файл HelloWord.obj в HEX-редакторе и смотрим во что превратилась наша точка входа. Допустим Start$wwrv. Теперь выполняем сборку Link.exe /ALIGN:32 /FORCE:UNRESOLVED /SUBSYSTEM:WINDOWS /ENTRY:Start$wwrv HelloWord.obj user32.lib /out:Hello.exe В результате имеем файл размером 832 байта. Статья про маленький размер приложения: Выжимаем из Delphi все возможное
  5. 1. У меня тоже такое было 2. Про этот случай я могу только гадать. 3. Так же как и во втором пункте - без понятия в чём причина. ЗЫ. Если создашь чит-код, то можешь написать статью в этой теме. ЗЗЫ. Трейнер ругается, т.к. требуется соблюдать правило - один запуск трейнера, на один запуск игры. В будущем, может быть, исправлю эту проблему.
  6. Kvazimado, если у тебя будет время и желание сделай следующее и отпишись о работе трейнера с твоим первоначальным JustCause.exe. Сначала запусти игру, затем начни играть (загрузив локацию игры), а только после этого сверни игру и запусти трейнер, подожди на всякий случай 10 секунд, активируй здоровье (crtl+1)... Если при таких действиях ты скажешь будет работать трейнер или нет и с какой ошибкой, то ты мне поможешь в отлаживании движка трейнера. Дело в том что я не могу запустить игру без диска и быстро проверить, то что писал выше. Проблема JustCause.exe (с защитой от копирования) предположительно поочередно распаковывает модифицированные секции кода, перед тем как к ним будет обращение. Я в этом не уверен, но догадываюсь. Обдумываю решение проблемы Если описание проблемы совпадает с истинной, то я изменю двиг трейнера следующим образом. При первой активации по горячим клавишам любого чит-кода сначала будет активация всех активирующих скриптов. Надо было сразу так делать, что-то я не додумался раньше. У меня же активирующие скрипты активируются сразу после нахождения дескриптора процесса игры.
  7. Знаешь, чтобы тебя не мучить вопросами... сброська мне твой JustCause.exe (ссылкой через личку, поскольку тут на форуме нельзя постить nodvd), я его быстренько проверю. Взамен тебе скину мой и он будет точно работать.
  8. Какая ошибка конкретно... "...код модифицированный, множество соответствий..." или "...код модифицированный, соответствий не найдено..." ? Это весьма важно. Русскую cheat engine надо вставить в директорию оригинальной английской версии. Английскую версию лучше оставить (например переименовав её).
  9. Kvazimado, слушай... трейнер-то у тебя заработал? .... я же его переделал. Как сделать машины не убиваемыми в которых сидит твой герой? Это сделать скорее всего не сложно Только я так устал что сегодня уже не могу этим заниматся, а сегодня вечером и завтра и послезавтра я занят сутками. Теоретически можешь попробовать [*:v35e6sz5]Найди адреса - изменяющиеся значения 4 байта целое, в случае когда ты садишься в машину и вышел из неё. Допустим ты нашёл адрес1 [*:v35e6sz5]Найди адрес2 "здоровья" машины [*:v35e6sz5]Найди связи между адресами [*:v35e6sz5]Напиши чит-кодps Я с форума ухожу через 20 минут... когда появлюсь не знаю. Либо сегодня, либо завтра, либо вообще во вторник.
  10. MasterGH

    Реализ CE 5.6

    Как известно уважаемый DarkByte выкладывает подарки (новые версии CE) под Новогоднюю цифровую ёлку раз в год. Сегодня затронули тему о том что же всё-таки будет в новой версии CE 5.6. Цитирую оригинал. Ждём с нетрпением. Если у кого есть желание, то можно перевести эту цитату или обсудить возможности. Во всяком случае, если я что-то узнаю с форума CE, то дам знать...
  11. Игра: Dark Sector. Спрос на трейнер: актуален (вероятность найти рабочий трейнер мала) Дата выхода: декабрь 2008 Мин. системные требования: 2,4 ГГц, 1 Гб, 256 Мб видео Дополнительная информация: немного фиговое управление. На данный момент рассморено: 1.Здоровье (автор MasterGH)]Инструменты: CheatEngineRus. 2.Бесконечные патроны + нет перезарядки (автор MasterGH)]Инструменты: CheatEngineRus 3.Бесконечные боеприпасы (автор MasterGH)]Инструменты: CheatEngineRus
  12. Игра: Grand Theft Auto 2 Спрос на трейнер: не актуален (поэтому не выкладываю таблицу и трейнер) Дата выхода: 30 сентябрь 1999 Мин. системные требования: CPU 233 MHz, 32 Mb, 8 Mb Video Дополнительная информация: старая игрушка. -Перейти к теме для новичков (тема не создана, т.к. по ней нет материала). -Таблица CE (можете сами сделать). -Трейнер (можете сами сделать). На данный момент по игре расмотрены: 1. Расструктуризация патронов и чит-код (Автор MasterGH) Инструменты: MHS, CheatEngine, IDA + hexrays. 1. Нашёл адрес патронов. 2. Поставил бряк (я ставлю всегда на доступ, больше информации видно). Получил адреса инструций, рассматриваем любую в данном случае например: 004A4FC7: MOV CX, WORD PTR [ESI] Address: 004A4FC7 EAX (after): 66666667 ESP (after): 0012FDBC ECX (after): 00000127 EBP (after): 00000000 EDX (after): 00001947 ESI (after): 0356EEB8 EBX (after): 00000000 EDI (after): 00000001 Ищем адрес содержащий адрес 0356EEB8 (указатель на 0356EEB8) Всё что было выше, было старым. Теперь новое. Находим статический gta2.exe+1D85E0. Т.е. [gta2.exe+1D85E0]=0356EEB8. На него указатель искать впринципе не нужно, т.к. он находится в статичной памяти и в MHS зеленого цвета. 3. Идём в дамп памяти и в окно выражений MHS и смотря на память по интуиции определяем вот такие смещения: [[5d85a0+x*16]]= значению, где x равно натуральным числам. Некоторые натуральные x в выражении будут показывать зачения количества патронов главного героя. [[5d85a0+0*16]] = 1 (1) // без понятия что это [[[5d85a0+1*16]]] = 6 (6) // без понятия что это [[5d85a0+2*16]] = 1 (1) // не помню [[5d85a0+3*16]] = 200 (C8) //патроны и далее патроны [[5d85a0+4*16]] = 880 (370) // патронов 880, в игре 88 [[5d85a0+5*16]] = 100 (64) //патроны, патроны.. [[5d85a0+6*16]] = 0 (0) // патронов нет [[5d85a0+7*16]] = 0 (0) // патронов нет... [[5d85a0+8*16]] = 0 (0)// и т.п. [[5d85a0+9*16]] = 0 (0) [[5d85a0+10*16]] = 0 (0) [[5d85a0+11*16]] = 0 (0) [[5d85a0+12*16]] = 0 (0) [[5d85a0+14*16]] = 0 (0) [[5d85a0+15*16]] = 0 (0) [[5d85a0+16*16]] = 0 (0) //где-то здесь заканчивается набор оружия, т.е. оржия не существует [[5d85a0+17*16]] = 0 (0) [[5d85a0+18*16]] = 0 (0) [[5d85a0+19*16]] = 0 (0) [[5d85a0+20*16]] = 0 (0) [[5d85a0+21*16]] = 0 (0) Дальше идут данные другого контекста. [[[5d85a0+22*16]]] = 0 (0) [[[5d85a0+23*16]]] = 0 (0) [[5d85a0+24*16]] = 0 (0) [[5d85a0+25*16]] = 0 (0) [[5d85a0+26*16]] = 0 (0) [[5d85a0+27*16]] = 0 (0) [[5d85a0+28*16]] = 360 (168) чьи-то патроны... [[5d85a0+29*16]] = 360 (168) [[5d85a0+30*16]] = 1080 (438) размер таблицы (5dc430-5d85a0)/16 -1 = 1000 (3E8). 1000 линий по 16 байт. 4. Итогом будет следующая формула указателей на оружие. [[5d85a0+x*16]], если x в промежутке от 3 до 21, то это наше оружие. Это можно учесть при внедрении чит-кода с фильтром. Дело в том что на этом можено остановится... 5. Как положено "маньяку" я пошёл дальше. Безусловно, что мы имеем дело со структурой данных и соответсвенно должен быть код который эту структуру обрабатывает и с его помощью можно как-то отделить данные нашего игрока от других. Я поставил бряк на доступ на адрес [5d85a0+3*16]. (помним что этот адрес указатель на патроны, т.е. [[5d85a0+3*16]]= равно патронам в первом слоте) И вышел на 0041CCC4 - MOV EDI, DWORD PTR [ECX+C] // часто обращаемая инструкция. Address: 0041CCC4 EAX (after): 0000001E ESP (after): 0012FD90 ECX (after): 005D85C4 EBP (after): 005E1038 EDX (after): 005D86E4 ESI (after): 005DCBC8 EBX (after): 005DE028 EDI (after): 032FD0F8 .text:0041CCA0 sub esp, 28h // начало функции, некоторые комманды "пообрубал", т.к. лишнее .text:0041CCA3 mov eax, [esp+28h+arg_0] .text:0041CCA7 push ebx .text:0041CCA8 push esi .text:0041CCA9 mov esi, ecx .text:0041CCAB lea eax, [eax+eax*2] .text:0041CCAE push edi .text:0041CCB9 mov ecx, [esi+eax*4+1480h] // esi - начало объекта героя .text:0041CCC4 mov edi, [ecx+0Ch] <<<< мы здесь, где ([ecx+0Ch]==[[005D85C4+0Ch]])==[[5d85a0+3*16]]=патроны .text:0041CCC7 mov byte ptr [esi+71h], 2 .text:0041CCCB mov ecx, edi .text:0041CCCD mov [esp+34h+var_1C], edi .text:0041CCD1 call sub_41CC80 //далее выборка по case ... Сама функция на псевдокоде: char __thiscall sub_41CCA0(void *this, int a2) { v4 = this; v5 = *((_DWORD *)this + 3 * a2 + 1312);//esi = this - ссылка на объект. v3 = *(_DWORD *)(v5 + 12); // mov edi, [ecx+0Ch] *((_BYTE *)v4 + 113) = 2; v26 = v3; LOBYTE(v2) = sub_41CC80(v3); //... } На esi надо найти указатель, а не на ecx(!) Но 005DCBC8 сам по себе статический адрес и искать указатель на него не нужно. Исходя из всего этого фурмула указателей оружия меняется таким образом [[005DCBC8+1e*4+1480h]+0xc] это адрес патронов первого оружия, если я не ошибаюсь. А это тогда будет для общих [[[005DCBC8+1e*4+1480h]+0xc]+x*16]. Где x - натуральное. Если мы хотим найти более чёткий указатель, то нам надо развернуть "1e" из выражения выше, т.е. [[005DCBC8+[[esp+28h+arg_0]+[esp+28h+arg_0]*2]*4+1480h]+0xc], где esp надо смотреть выше... но мне это делать лень и так уже кучу времени провозился. Подсмотреть по какому принципу рапологаются указатели в структуре объекта игрока. 7. Финал. Ну и наконец чит-код будет таким, если ресурсы наши, то пишем их максимальное значение. [ENABLE] alloc(newmem,2048) label(_returnhere) label(_originalcode) newmem: cmp esi,005DCBC8 // наш игрок? jne short _originalcode push eax mov eax,[ecx+0c] mov [eax],#10000 // если наш, то вписать патроны каждому оружию pop eax _originalcode: mov edi,[ecx+0c] mov byte ptr [esi+71],02 jmp _returnhere GTA2.EXE+1CCC4: jmp newmem nop nop _returnhere: [DISABLE] GTA2.EXE+1CCC4://14000000008B8C8680140000885 ... 7C2418E8AA mov edi,[ecx+0c] mov byte ptr [esi+71],02 unregistersymbol(dnull) dealloc(newmem)
  13. ООП состоит на основе трёх концепций: инкапсуляция, наследование и полиморфизм. Но модель ООП на этом не заканчивается. В каждом отдельном языке программирования добавлены свои "прибамбасы" относительно наследования и полиморфизма, что формирует модель ООП соответствующую языку программирования. Из всех языков которых я знаю или сталкивался С++ и его продолжения наиболее сильные в ООП. О концепциях ООП Тоже самое в IDA рис. 3 А вот так выглядит в псевдокоде рис. 4 При обмане игр у нас не будет исходника С++ и нам нужно научится понимать псевдокод. Сделаем немного понятнее псевдокод. Нажмём shift+F9 и опишем структуру класса Player с 3*4 байт рис. 5 Затем в псевдокоде нажмём на Y и определим тип структуры: рис.6 И получим более лучшее представление псевдокода Рис.7 И ещё давайте посмотрим, что будет если мы не иницилизируем некоторые данные объекта. рис 8 Результат такой: рис 9 Переменные x1.x2.x3 не инициализировались и остался мусорный код выделенной памяти. Когда выделяется память, то она не «подчищена», если вы не знали. Подведём итог. Познакомились с С++ (если не были знакомы) увидели на простом примере как оформляется структура объекта в С++ и как она выглядит в памяти и в псевдокоде. Увидели как псевдокод облегчает анализ игровых объектов. Главное научиться проводить аналогии между псевдокодом и дизассемблерным кодом для того чтобы представить как устроен объект. Если у вас возникли трудности в С++ то существует много информации в Интернете, которую вы можете легко найти самостоятельно. Часть2. Дальнейшее исследования игрового объекта в памяти Виртуальные функцииВиртуальные классы и множественное наследование 3.1 Виртуальные функции. Если вы не сталкивались с полиморфизмом ни разу и вообще с ООП знакомы мало, то понять эту тему будет, скорее всего, сложно. Виртуальные функции это одинаково объявленные функции в иерархии наследования, которые позволяют работать с данными объекта в контексте нужного класса. Объяснил как смог.. =) Очень важно понять, как это работает для исследования игровых объектов в дальнейшем, т.к. виртуальные функции попадаются сплошь и рядом. Разберём пример «на пальцах», показывающий выгоду виртуальных функции перед похожими, но не виртуальными одинаковыми функциями. Программа перемещает графические объекты по нажатым клавишам клавиатуры, но писать мне её некогда, поэтому разберу основное. { int x,y; public: Dot() {x=100; y=100;} // просто зададим координаты по умолчанию void show(){сделать пиксел белым}; void hide() {сделать пиксел черным}; void move (int dx,dy){ hide(); x+=dx; y+=dy; show()}; };class Dot Мы создали класс Точки, у которой описаны координаты положения и описаны функции перемещения с угасанием и отображения точки. Ключевое место здесь в том, что в функции перемещения присутствуют локальные вызовы угасания и отображения точки. Именно из-за локальных вызовов появится проблема в производном классе, т.к. в базовом классе будут вызываться свои локальные функции с тем же именем. Выходом будет определение виртуальных функций. Рассмотрим эту проблему. { int radius; public: Ring () {radius=200;}; //зададим радиус круга по умолчанию void show(){сделать окружность белой}; void hide(){сделать окружность чёрной}; };class Ring: public Dot Видим, что Круг наследует функцию перемещения, в которой происходят локальные вызовы hide и show. Т.е. если мы зададим движение Кругу, то двигаться будет Точка, т.к. вызываются локальные функции в контексте класса Точки. Ring *ring=new(Ring); ring->mov(50,60); // вызовет перемещение только точки,а не круга Чтобы решить эту проблему был введен механизм виртуальных функций. Вызов той или иной функции задается смещением (генерируемым компилятором), по которому в созданной таблице виртуальных методов (vftable) выбирается нужная функция, которая и вызовется. { int x,y; public: Dot() {x=100; y=100;} // просто зададим координаты по умлочанию virtual void show(){сделать пиксел белым}; virtual void hide() {сделать пиксел черным}; void move (int dx,dy){ hide(); x+=dx; y+=dy; show()}; }; class Ring: public Dot { int radius; public: Ring () {radius=200;}; // также просто зададим радиус круга void show(){сделать окружность белой}; void hide(){сделать окружность чёрной}; };class Dot Теперь ring->mov(50,60); // вызовет перемещение только круга в заданные координаты 50 и 60 ring->Dot::mov(50,60); // этот метод в принципе бесполезный, т.к. координаты точки уже были равны 50 и 60Ring *ring=new(Ring); Вызывать метод перемещения точки было не обязательно, главное то, что круг наследовал координаты x и y и можно и нужно перемещать только круг. Однако, если вы вызовете ring->Dot::mov(100,100), то это распространится и на круге... т.е. и точка и круг взаимосвязаны и буквально слеплены в одно целое как в симбиозе (кто биологию хорошо знает? ) Как мы увидели механизм «виртуальных функций (полиморфизм)» нужен для правильной работы с данными объекта в требуемых контекстах его описывающих классов. Чаще всего виртуальные функции объявляются без входных параметров, таким образом, их применение наиболее удобно и более расположено к полиморфизму. При полиморфизме в статичной области кода возникает таблица виртуальных функций vftable. Указатель на таблицу виртуальных функций находится по первому адресу объекта (см. рис. 1) рис. 1 Следует отметить, что vftable характерна только для определённого типа класса. Если вы найдёте в памяти игры адрес таблицы виртуальных функций (vftable) некоторого объекта и затем в сканере памяти найдёте 6 указателей на ту же vftable, то можете считать что вы «вышли» ещё на 6 объектов, которые наследовали vftable класса или некоторой иерархии классов. Соответственно по указателю на vftable в чит-кодах можно делать фильтры по изменению данных игровых объектов построенных по описанию конкретного класса или по описанию классовой иерархии. Учитывая всё выше известное, напишем программу с игровыми объектами и проанализируем формирование объектов с vftable. Результат программы будет таким. рис. 2. (Координат нет, это вы поймете на рис 6 ) В данной программе и в случае, кода виртуальные функции наследуются, то vftable сильно усложняется. Нам будет очень полезно рассмотреть случай ниже для обмана игр. Сначала посмотрим расположение данных двух объектов, после того как мы их заполнили. Так мы увидим данные после того как CE сама расструктуризовала их. рис. 3 Как мы видим, структуры объектов заполнены непонятными данными по смещениям 0x18-2С, 4C-0x64, 0x68-0x6C. Адреса по этим смещениям рассмотрим позже. Сейчас важно понять, как устроены таблицы на рисунке по смещениям 0x0, 0x30 и как они работают. Они выглядят вот так (так как и расструктуризавала CE) рис. 4 Для удобства переведём эти значения в hex- вид рис. 5 Я пока не знаю, правильно ли я определил, что по смещению 0хС значение 0х48 указывает на конец таблицы виртуальных функций в контексте всей иерархии классов... 00401017 – это указатель на функцию Player:: GetInfo 0040102B – это указатель на функцию Building::GetInfo Обращение к указателям компилируется в коде (вы это можете посмотреть в дизассемблерном листинге ниже), т.е. в объектах не содержится данных о том к какой именно функции, в каком описании класса в какой момент обращаться. Залезем в псевдокод в функцию main, т.к. именно по нему нам надо учиться обманывать игры и смотрим рис 5 и рис.6 В псевдокоде смещения в структурах объектов десятичные,но там не сложные числа можно перевести в 16-ричную систему в уме для того чтобы соотнести смещения структур на рис. 5 рис. 6 GetInfo в контексте класса control не сработала, из-за виртуальных функций, так и должно быть. Псевдокод показывает всё что необходимо и это гораздо нагляднее, чем смотреть дизассемблерный код в отладке. Для интересующихся (маньяков) привожу дизассемблерный код. Комментировать не буду, т.к. основное всё разобрал. Скопируйте его в отдельное место и можете тщательно разобраться как что и куда. С виртуальными функциями более менее познакомились. Возможно, в следующих статья разберём ещё более тяжёлые случаи (адские ) Продолжение следует. В следующей частях возможно будет рассмотрено. Множественное наследование. Виртуальные функции при множественном наследовании. Виртуальное наследование классов. Виртуальные функции при виртуальном наследовании классов. Статичные данные и функции в объектах. Дружественные функции в объектах. Массивы объектов. Объекты по шаблону. Объекты по стандартному шаблону . Сообщения. Методы дизассемблирования и отладки. Объекты совместно с lua – интерпритатором. Создаём объекты через конструкторы и команды lua. Обход антиотладочных ловушек xlive. Распаковка игровых ресурсов. Обман flash игр. Обман .NET игр. Обман JAVA игр. Обман эмуляторных игр, поиск нулевого адреса.
  14. Тема будет не плохой тренировкой на Дельфи. Взято из интернета. Результат на картинке (внизу). Готовый вариант. unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Grids; type TPole = record x: Byte; y: Byte; End; TForm1 = class(TForm) Button1: TButton; sg: TStringGrid; procedure Button1Click(Sender: TObject); private SapMap: Tpole; public end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); Var hWn: HWND; PID, hProc, dwReaded: DWord; buf: Byte; i, r: Dword; StartAddr: Dword; 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.RowCount := SapMap.y; 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 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; Finally CloseHandle(hProc); end; end; //If IsWindow(hWn) end; end.
  15. Выставление оконного режима по горячей клавише F2. Весь интернет облазил как реализовать ChangeDisplaySettings(NULL,0) на Дельфи. Просто ради интереса. Дело в том что NULL нельзя поставить в Дельфи и в C#, потому что там должен быть укзатель на структуру. Можно в VC++ и средах ассемблера... Никто не знает ответа... Но не МастерGh Для результа - один раз восстановить окно дисплея подходит следующий метод Внизу я написал код с указателем на объект DevMode (или это запись, уже точно не помню), затем скомпилировал, пошёл в OllyDbg и пропатчил начальные параметры перед функциией Было 004520BE PUSH Project1.00459542; //флаг 004520C0 PUSH Project1.004595A4 // указатель на структуру 004520C5 CALL ; ChangeDisplaySettingsA Стало 000514BE PUSH 0 // а вот и Null тот самый. 000514C0 PUSH Project1.004595A4 000514C5 CALL ; ChangeDisplaySettingsA Сначала я написал такой код (кинул на пустую форму таймер и добавил строки (выделенные), остальное всё автоматически генерировалось) После патча, программа ставила основной режим и игра была в окне если его разрешение было меньше чем рабочего стола перед запуском игры. Вот задание написать эту программу максимально маленького размера, а если не можете или лень то можете скачать отсюда. Если игра постоянно проверяет видеорежим и выставляет свой, то моя программа не поможе - окно вновь будет восстанавливаться, но я думаю таких игр мало. В этом случе тоже можно написать утиль, но его придётся уже писать с хуками: после срабатывани ChangeDisplaySettings на установку полноэкранного режима надо пресекать исполнения режима и выводить ложный результат, дескать режим был установлен...
  16. Тема. Установка оконного режима в ручную. Описание всех фукнкций и процедур можно найти в интернете. Они есть у всех в библиотеках user32.dll (если не ошибаюсь). Похали. Берём игрушку и OllyDbg. Ищем все вложенные функции. Обращаем внимание на те, которые я пишу ниже. При создании окна работают CreateWindowExA (или CreateWindow). Нужно поставить на них всех брейкпоинт, когда он сработает, то нужно изменить параметры в функции: высоту и ширину. Далее отпустить игру. После задания размеров окна игра пытается получить его EnumDisplaySettings. Далее фунцией ChangeDisplaySettings (или ChangeDisplaySettingsEx) пытается запомнить режим и включить полноэкранный. LONG ChangeDisplaySettings( LPDEVMODE lpDevMode, // графический режим DWORD dwflags // параметры графического режима ); Я не разобрался ещё какие цифры какой означают флаг, пока известно вот что: dwflags при двойке - я думаю так или иначе был сохранением экрана. dwflags при четвёрке - немедленно включал полноэкранный. Болле подробно о флагах и инструкциях можно посомтреть здесь Не допускайте чтобы флаг был четвёркой, пример ниже. Как я устаналвивал оконный режим в игре "Ghost Master Demo" в OllyDbg. 1. Перехватил CreateWindowExA (поставил ширину и высоту 800 на 600) 2. На ChangeDisplaySettings внутри user32 поставил бряк. Когда он прервался я вышел вверх на неявный call (см. ниже) Во вреия игры при загрузке нового уровня, часто выполнялся тот прыжок jle метка1 и его пришлось просто пропатчить на jmp метка1. Таким образом Игра была постоянно в оконном режиме (доказательство на рисунке). Хочу заметить что d3dWindower не помог, иначе бы не было этого туториала. На этом всё.
  17. Базовый способ взлома — это поиск адреса в памяти игры по правилам поиска, изменение значения адреса и заморозка значения по адресу. Это можно сделать с помощью программ Artmoney, Cheat Engine и других сканеров памяти. Правила поиска описываются в руководстве Artmoney на русском языке. Этим способом можно взломать (или сделать читы) чуть ли не на все игры. Если в игре загружается игровой уровень или игровая сцена, то адреса в памяти могут поменяться и придется адрес искать вновь. В этом случае можно использовать поиск указателей, который может быть как быстрым так и очень долгим. Попробовать можно в тех же программах Artmoney, Cheat Engine. Если поиск указателей не хотим использовать, т.к. он долгий, то есть вариант изменить код игры для того чтобы по адресу записывалось другое значение. Попробовать можно в тех же программах Artmoney, Cheat Engine. Для этого нужно поставить брейкпоинт на найденный адрес, выйти на инструкцию ассемблера и что-то с ней сделать. Для нужно поискать руководства по инструкциям ассемблера. Кратко 1) если инструкция пишет в адрес, то её можно занопить, т.е. стереть. mov, dec, sub или другие... 2) с Cheat Engine можно заменить инструкцию, если размер инструкции в байтах подойдет. Если не подойдет, то заменяем инструкцию на инструкцию прыжка на адрес выделенной памяти, в которой пишут немного "сложного" ассемблерного кода и затем делают прыжок обратно. Если все делается с Cheat Engine, то на действия вешаются хот-кеи. Создается таблица или трейнер и все готово. Берем любую игру, Cheat Engine, делаем трейнер и публикуем его на форуме или где захотим. Вы можете пойти по следующим путям: 1) писать скрипты для CE (Cheat Engine) 2) генерировать трейнеры на CE, 3) можете писать трейнеры на языке программирования. Во всех трёх направления на нашем форуме (если поискать) есть как простые примеры, так и очень сложные. Лучше всего начать со справки Артмани и использовании самой этой программы. Затем установить Cheat Engine и подробно смотреть и читать следующие темы: 1) Туторы по CE Autoassembler Engine; 2) Grand Theft Auto Vice City, метод указателей (использовалась TSearch, но вы должны всё понимать как если бы это было CE ) 3) Посмотрите наш раздел по Cheat Engine 4) Ну и чиnаем всё что найдёте у нас на сайте и на форуме. Для более опытных Lua Engine в CE для создания трейнеров или создание на языках программирования с Windows API. Термины
  18. Инструменты для обмана игр Основные инструменты: Artmoney (для новичков) CheatEngine (для опытных) Cheat Engine 5.6 RUS v1.0(для опытных, установить поверх английской CE 5.6) CheatEngine Rus 5.5 (для опытных) MHS (для опытных) Отладчики, дизассемблеры: IDA+(плагин hex-array) – ищете сами в Интернете. OllyDbgShadow+примочки (лежит в архиве ниже) Различные «мониторы»: ProcessExplorer (лежит в архиве ниже) – процесс окна игры, команда запуска и т.п. Procmon (лежит в архиве ниже) – слежение за записью и чтением на хард (помогает выйти на файлы сохранения или понять в чём ошибка игры) Работа с окном игры: D3DWindower (лежит в архиве ниже) – установка оконного режима InqSoftWindowScanner (лежит в архиве ниже) – информация об окне, перемещение окна… Ссылка на архив (редактируется) Если вам нужен софт по трейнерам, то вам нужно перейти в соответствующий раздел. Софт для обмана флеш-игр: (редактируется) Софт для обмана эмуляторных игр: (редактируется)
  19. Здесь будет рассматриватся и может обсуждаться/дополняться моё руководство по Autoassembler Engine. Нужные ссылки на CE: 1. Сайт английской версии (последняя версия CE 6.0 на 20 апреля 2011 ) 2. Русская CE 5.6 (устанавливается поверх английской CE 5.6 находящаяся на официальном сайте; если хотите генерировать трейнеры, то только лучше на этой версии пока не вышла версия CE6.1) 3. Русская CE 5.5 Статья в которой обсуждается работа с автоассемблером (весь пункт 3): DevilMyCry.rar. Эту статью лучше прочитать после чтения информации ниже. Дополнительная информация: Если делаете читы для себя, то Вам будет достаточно автоассемблерных скриптов CE. Если нужны трейнеры, то их генерировать может CE 5.6 и будущая CE 6.1. CE 6.0 генерировать трейнеры не умеет, но зато поддерживает LUA - скрипты, которые могут создавать трейнеры скриптами только при наличии CE6.0. Чтобы делать трейнеры на LUA скриптах нужно иметь опыт программирования. Для новичков проще пользоваться автоассемблерными скриптами. На официальном сайте ожидается конечный реализ CE 6.1 с поддержкой русского языка. Зайдите в подфорум реализы Cheat Engine чтобы попробовать возможности CE 6.1 Альфа 8. ----------------------------------------- 1. Обзор автоассемблера Листинг 9(код байтов инструкции mov я точно не помню, ссори, смотреть лень) Прыжок на свободное место в котором мы укажем новое условие занимает пять байт это "eb xx xx xx xx" . Это значит, что прыжок затрёт пять байт, начиная с адреса 0081e159 и оставит два байта «ошмётка» последующей инструкции (ий) которые выделены красным. Ошмётки мы затираем ноп-ми (иначе будет вылет) и восстанавливаем инструкции в выделенной памяти соблюдая логику кода. Совет. Вам нужно обращать внимание, что когда вы внедряете чит-код, то вы затераете пять байт по стандарту прыжком Jmp адрес (занимает пять байт) или в редких случаях call адрес (занимает пять байт) Таким образом, скрипт примет вид ниже. Появляются новые скриптовые команды. Alloc(newmem,2024) //выделение памяти рамзмером 2024 байт, которые округляться до 4 кб Label(x1) //метка адреса newmem: Mov [ecx],#100 mov eax,[ecx] //дописали стёртую инструкцию jmp x1 0081e159: Jmp newmem x1: nop //наши 2 ошмётка nop [DISABLE] 0081e159: dec [ecx] mov eax,[ecx] dealloc(newmem)//высвобождаем выделённую память,чтобы не засорять память. [ENABLE]Листинг 10 Теперь игра не должна вылетать. Если вы знаете инструкции ассеблера, то можно закрепить основы давайте рассмотрим пример из игры. mov ecx,[eax] mov edx,[esp+04]//<< здесь сработал бряк ... core.dll+4285C: //<<адрес кода игрыЛистинг 11 Инструкция mov edx,[esp+04] работает с адресом здоровья как моего игрока, так и других игроков. Что бы прописать здоровье моего игрока я нашёл многоуровневый указатель (как это делать напишу потом) и построил скрипт с фильтром. Сам фильтр можно видеть ниже. mov ebx,[core.dll+00155744] //строим многоуровневый указатель mov ebx,[ebx+350] add ebx,43C //ebx=[[core.dll+00155744h]+350h]+43Ch – многоуровневый указатель, cmp eax,ebx //если игрок наш, то прописать 250 очков здоровья pop ebx //восстановили ebx jne short originalcode mov byte ptr [eax],#250 //пишем здоровье нашему гироку originalcode: //метка оригинального кода mov ecx,[eax] //дописываем затёртые инструкции для восстановления логики кода mov edx,[esp+04] push ebx //регистр нам будет нужен, поэтому запихнём его в стек и потом вернём обратноЛистинг 12 А теперь листинг 12 встроим весь скрипт. UnrealTournament2003+ (InfHealth)*/ [ENABLE] alloc(newmem,2024) label(returnhere) label(originalcode) newmem: push ebx mov ebx,[core.dll+00155744] add ebx,350 mov ebx,[ebx] add ebx,43C cmp eax,ebx //ebx=[[core.dll+00155744h]+350h]+43Ch pop ebx jne short originalcode mov byte ptr [eax],#250 originalcode: mov ecx,[eax] mov edx,[esp+04] jmp returnhere core.dll+4285c: jmp newmem nop returnhere: [DISABLE] core.dll+4285c: mov ecx,[eax] mov edx,[esp+04] /*MasterGH(c) 04.01.08. Листинг 13 Обратите внимание на то, как мы встроили новое условие. Мы сравнили игрока со своим по его указателю и если это свой игрок, то запишем ему полное здоровье. Совет. Внимательно следите нужно ли сохранения регистра флагов pushf/popf. В большинстве случаев это не нужно, в противном будет измнена логика и может быть крах игры. В скриптах можно много чего «мутить». Разберём специальные команды скрипта (возможно это не все команды, см. справку CE) ALLOC(имя, размер)- выделение памяти DEALLOC(имя) - высвобождение памяти LABEL(имя) - объявление меток FULLACCESS(адрес/метка, размер) - установка полного доступа по адресу REGISTERSYMBOL(имя) - регистрация метки, метка будет доступна в окне адресов и вдругих скриптах UNREGISTERSYMBOL(имя) - убираем метку DEFINE(имя,инструкция) - почти неприменятся, если инструкция повторяется то удобно её обзвать и присвоить имя INCLUDE(имя файла) - учитывает метки других файлов-скриптов LOADBINARY(адрес,имя файла) - загрузка данных или кода из файла по данному адресу CREATETHREAD(адрес) - создание потока, который будет выполняться начиная с адреса LOADLIBRARY(имя файла) - подгрузка библиотеки READMEM(адрес,размер) - в скрипт вставляются байты с некоторого адреса. db, dw, dd - означает вставка байтов, 2 байтов, 4 байтов. Ну и примеры из англоязычной справки Базовая основа скрипта. jmp 00410000 nop nop nop 00410000: mov [00580120],esi mov [esi+80],ebx xor eax,eax jmp 00451031 00451029:Листинг 14 Использование меток. 00451029: jmp 00410000 nop nop nop mylabel: 00410000: mov [00580120],esi mov [esi+80],ebx xor eax,eax jmp mylabel label(mylabel)Листинг 15 Использование выделения памяти 00451029: jmp 00410000 nop nop nop 00410000: mov [alloc1],esi mov [esi+80],ebx xor eax,eax jmp 00451031 alloc(memloc1,4)Листинг 16 Использование меток и выделения памяти label(mylabel) 00451029: jmp 00410000 nop nop nop mylabel: 00410000: mov [alloc1],esi mov [esi+80],ebx xor eax,eax jmp mylabel alloc(alloc1,4)Листинг 17 Установка полного доступа. Обычно, используется совместно с областью неиспользуемого кода. Мной не рекомендуется, разве что в очень специфических задачах. Стоит отказаться от codecave (дыр кода), чтобы это не приводило к краху игры, а пользоваться выделением памяти. //из-за выравнивания кратному 1 странице памяти… 00451029: jmp 00410000 nop nop nop 00410000: mov [00400800],esi mov [esi+80],ebx xor eax,eax jmp 00451031 FULLACCESS(00400800,4) //доступ будет не к 4-м байтам, а к 4 кб (в 32 разрядных системах и 8 кб в 64 рязрядных)Листинг 18 Использование DEFINE, как переопределение инструкций. 00400500: clear_eax DEFINE(clear_eax,xor eax,eax)Листинг 19 Использование чтения памяти некоторого размера alloc(x,16) alloc(script,2048) script: mov eax,[x] mov edx,[x+c] ret x: // по этой метке будет записано 16 байт с адреса 00410000 readmem(00410000,16) Листинг 20 Пару слов стоит сказать о проверочных байтах. Все они вместе являются уникальной последовательностью (так предполагается) по которой можно установить адрес внедрения. Это нужно чтобы чит-код работал со всеми версиями игры. Пару слов про шаблоны. Шаблоны, возможно требуется доработать, поэтому о них пока писать руководство не буду. Опции Перехват API и переопределения кода, довольно специфичны и пока рассматриваться не будут. В общем если хотите научится писать скрипты, то учите ассемблерные инструкции и читайте темы на этом форуме. Если вам нужно в скрипте использовать указатели, то можно сделать их следующим образом. Так dd 0[[game.exe+3070A0]+68]+1e4: Или так mov eax,[eax+68] mov [eax+1e4],0mov eax,[game.exe+3070a0] 3. Ассемблерные инструкции Ассемблерные инструкции. Чтобы научиться писать скрипты нужно: 1) Учиться по примерам скриптов на нашем форуме или на форуме CE 2) Много практики 3) Читать справку CE, статьи и примеры. Хорошие статьи, но на английском можно найти также здесь. О скриптах CE. Скрипты CE обладают ограничениями. Сложно описать какими именно и в каких ситуациях, но один пример можно привести. Если Вам требуется чтобы скрипт изменялся в какой-то момент определённым образом например перед первым запуском, то вы НЕ сможете это сделать только скриптами Автоассемблера. Ну, может быть и можно в зависимости от ситуации - исправлять машинный код скрипта1 машинным кодом скрипта2 с помощью Автоассемблера. Однако, есть более удобное решение - LUA Engine. Информацию по LUA Engine вы сможете найти в соседней теме.
  20. Игра: Just Cause Спрос на трейнер: средне актуален, т.к. игра, возможно, и популярна при этом нет универсального трейнера. Дата выхода: сентябрь 2006 г. Мин. системные требования: CPU 1,4 MHZ, 512 MB, 64 MB VIDEO Дополнительная информация: игра похоже на всем известную GTA3 и выше. -Таблица CE (для версии RUS). -Трейнер (трейнер должен работать со всеми версиями игры). Запускайте трейнер, затем игру, затем нажимайте на горячие клавиши - всё как обычно. Реализованы чит-коды: 1. Чит-код на здоровье героя (автор MasterGH) 2. Чит-код на бесконечные патроны (автор MasterGH) 3. Делаем машину бессмертной(автор MasterGH) 4. Чит-код на гранаты (автор MasterGH)
  21. Игра: kkrieger Спрос на трейнер: не актуально. Дата выхода: не известна. Мин. системные требования: не известны. Дополнительная информация: особенностью игры является очень малый размер. Игру можно скачать в интернете. А главное на ней можно потренироваться новичку во внедрении чит-кодов. На данный момент по игре рассмотрены: Оконный режим (Автор MasterGH)]Инструменты: DirectX Windower, Process Explorer.
  22. Игра: Command & Conquer 3: Tiberium Wars Спрос на трейнер: актуален, игра популярна и при этом нет универсального трейнера*. *Универсальный трейнер - это трейнер работающий с любыми версиями конкретной игры: с патчами, локализацией и т.п. Также универсальный трейнер не вышибает игру и выдаёт информацию почему он не сработал. (Памятка1 для админов, включть это определяние в отдельное место. Памятка2 создать трейнер с выводом ошибок внедрения чит-кодов: "код модифицирован не найдено соответствий отпечатка байт", "код модифицирован множество соответсвий - число соответсвий") Дата выхода: 30 марта 2007 г. Мин. системные требования: 2 ГГц, 512 Мб, видео GeForce 4/Radeon 8500 Дополнительная информация: нет. На данный момент по игре рассмотрены: Оконный режим с параметром (авт. MasterGH)]Инструменты: DirectX Windower, Process Explorer.
×
×
  • Создать...

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

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