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

MasterGH

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

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

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

    129

Сообщения, опубликованные MasterGH

  1. Xipho, помнишь ты мне дал твою функцию определения настоящего имени модуля dll в удалённом процессе.

    Тут что используем?!

    CreateFile, CreateFileMapping, MapViewOfFile, затем через череду путей добираемся до pImportDesc (это PIMAGE_EXPORT_DIRECTORY)

    Затем так получаем реальное имя (char*)(DWORD(mFile)+ (DWORD)(pImportDesc->Name)),

    где mFile был получен из MapViewOfFile(hMapFile....)

    hMapFile - из CreateFileMapping(hFile,...)

    hFile - из CreateFile(Path,...)

    Path - полный путь с названием файла модуля

    // Дефайны
    #define MakePtr(Type, Base, Offset) ((Type)(DWORD(Base) + (DWORD)(Offset)))
    #define NTSIGNATURE(a) ((LPVOID)((BYTE *)a + ((PIMAGE_DOS_HEADER)a)->e_lfanew))

    // char *Output - возврат реального имени модуля
    // char *Path - передача пути модуля по указателю в GetModuleRealName
    void GetModuleRealName(char *Output,char *Path) {
    HANDLE hFile = CreateFile(Path,GENERIC_READ,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
    if (hFile!=INVALID_HANDLE_VALUE) {
    HANDLE hMapFile = CreateFileMapping(hFile,NULL,PAGE_READONLY | SEC_IMAGE,0,0,NULL);
    if (hMapFile) {
    PBYTE mFile = (PBYTE)MapViewOfFile(hMapFile,FILE_MAP_READ,0,0,0);
    PIMAGE_DOS_HEADER pDOSHead;
    pDOSHead = (PIMAGE_DOS_HEADER)mFile;
    if (pDOSHead->e_magic != IMAGE_DOS_SIGNATURE) {
    MessageBox(NULL,"Error Dos Header signature MZ","Error",MB_OK);
    }
    PIMAGE_NT_HEADERS pPEHeader;
    pPEHeader=(PIMAGE_NT_HEADERS) NTSIGNATURE(pDOSHead);

    if (pPEHeader->Signature != IMAGE_NT_SIGNATURE) {
    MessageBox(NULL,"Error PE Header signature PE","Error",MB_OK);
    }
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;
    OptionalHeader = (IMAGE_OPTIONAL_HEADER32) pPEHeader->OptionalHeader;

    PIMAGE_EXPORT_DIRECTORY pImportDesc=NULL;
    pImportDesc = MakePtr(PIMAGE_EXPORT_DIRECTORY,mFile,pPEHeader->OptionalHeader.DataDirectory[0].VirtualAddress);
    char *p = MakePtr(char*,mFile,pImportDesc->Name);
    strcpy_s(Output,strlen(p)+1,p);
    UnmapViewOfFile(mFile);
    }
    CloseHandle(hMapFile);
    } else {
    int er = GetLastError();
    char p[30];
    wsprintf(p,"Last Error: %d",er);
    MessageBox(NULL,p,"ERROR",MB_OK);
    }
    CloseHandle(hFile);
    }

    1) Так вот у меня вопросы как называется твой метод если имеет какое название?

    2) Какое отношение он имеет к именованным каналам и другим видам межпроцессорного взаимодействия?

    3) Теоритически можно ли было твою функцию переписать как поиск сигнатуры?

    4) Теоритически можно ли было твою функцию переписать используя метод разделяемой памяти?

    Т.е. делаем например так.

    Ищем все модули процесса (как ты делал)

    У каждого модуля ищем реальное имя и возвращаем его, а делаем это так.

    Своим главным потоком процесса1 позаимствуем секцию(ии) чужого процесса2 по методу разделяемой памяти, остановив перед этим процесс2. И работаем с этими секциями как со своими внутри процесса1 - читаем данные этих секций как свои для процесса1 на предмет поиска настоящего имени dll. Выводим на консоль, отменяем семафоры (их два и их ещё надо было создать до этого), закрываем ненужные дескрипторы, размораживаем процесс2...

  2. Хороший пример хакинга через внедренную dll, а также с примером хука на directXDraw функции начала сцены, функции конца сцены, функции reset...

    Посмотрите на интересный вариант описания реализации класса Hacks из Hacks.h:



    #include "Hacks.h"

    int Hack::Count = 0;

    Hack::Hack(char* name, LPVOID destination, BYTE* oldValue, BYTE* newValue, DWORD len)
    {
    this->Count++;
    this->name=name;
    this->bEnabled=false;
    this->destination=destination;
    this->oldValue=oldValue;
    this->newValue=newValue;
    this->len=len;
    }

    Hack::~Hack()
    {
    this->Count--;
    }

    bool Hack::Setup()
    {
    DWORD oldProt = NULL;
    if(!VirtualProtect(destination,len,PAGE_READWRITE,&oldProt))
    return false;
    RtlMoveMemory(destination,(void*)newValue,len);
    if(!VirtualProtect(destination,len,oldProt,&oldProt))
    return false;

    bEnabled=true;
    return true;
    }

    bool Hack::Remove()
    {
    DWORD oldProt = NULL;
    if(!VirtualProtect(destination,len,PAGE_READWRITE,&oldProt))
    return false;
    RtlMoveMemory(destination,oldValue,len);
    if(!VirtualProtect(destination,len,oldProt,&oldProt))
    return false;

    bEnabled=false;

    return true;
    }

    Hack hackAmmo("Infinite Ammo, %X",(LPVOID)0x005BFCB9,(PBYTE)"\x89\x84\x8F\x34\x03\x00\x00",(PBYTE)"\x90\x90\x90\x90\x90\x90\x90",7);
    Hack hackRecoil("No recoil, %X",(LPVOID)0x00434629,(PBYTE)"\xE8\x22\xE7\x18\x00",(PBYTE)"\x90\x90\x90\x90\x90",5);

    Hack hacks[]={hackAmmo,hackRecoil};

    hacks[] будет массивом указателей объектов hackAmmo и hackRecoil. Активировать их судя по коду можно так:


    void AllActivated()
    {
    for (BYTE i, i<1, i++)
    hacks[i].Setup();
    }

    Деактивировать:


    void AllDeactivated()
    {
    for (BYTE i, i<1, i++)
    hacks[i].Remove();
    }

    Источник.Там же найдете исходники.

  3. Ок. Про ассемблерный код.

    Упростить вроде не упростишь. Лучше вообще переписать так:

    Главный скрипт:


    registersymbol(pStruct)

    Player:
    mov [pHero],esi
    push eax
    mov eax,[esi+FC] // загрузил структуру золота и очков
    mov [pStruct],eax
    pop eax
    fld dword ptr [esi+0000018c]
    jmp EPlayer

    Включаешь этот скрипт, а в таблице Cheat Engine пишешь:

    1) указатели относительно зарегистрированной метки pStruct;

    2) функцию добавления и добавляемое значение;

    3) горячие клавиши.

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


    cmp dword ptr [iXP],1
    jne p2
    add [eax+8c],#1000
    mov [iXP],0
    p2:
    cmp dword ptr [iPP],1
    jne p3
    add [eax+2c],#10
    mov [iPP],0
    p3:
    cmp dword ptr [iSP],1
    jne BPlayer
    add [eax+3c],#10
    mov [iSP],0
    BPlayer:
    pop eax

  4. Я этот исходник посмотрел ещё давно когда ты его выложил.

    Если постараться дать объективную оценку ему, то он написан по методам "современной школы, которая "потихоньку превращается в старую". Это школа имеет тенденцию выделять/изменять новую память для инъекций тел чит-кодов с помощью процесса трейнера. Это тенденция очень популярна и по сей день в скриптах CheatEngine и в большинстве любых других трейнерах которые делают сегодня.

    Но существует ещё одна "школа" которую можно назвать мало используемой старой (менее популярной из-за сложностей внедрение и написания своих dll-ок) или школой нового поколения которая где-то развивается парочкой людей и её не использует большинство. "Новая школа" предполагает создание особого модуля xxx.dll который по разному можно внедрить в процесс игры при помощи трейнера, после чего трейнер непосредственно с памятью процесса игры не работает, т.к. с ним работает та самая xxx.dll предназначение которой изменять поведение игры... В CheatEngine есть методы загрузки такой dll-ки и даже есть такой метод в скриптах CE. Но по сей день на форуме Cheat Engine популярны скрипты CE без работы с dll.

  5. А можно по конкретней, что это за новинка? Это просто многоуровневые указатели на нулевые адреса привязанные к версии эмулятора или это одно-многоуровневые указатели на нулевые адреса которые находятся автоматически независимо от эмулятора и только в зависимости от рома?

  6. Снова для тех кто решит писать на C/C++


    mov [pHero],esi

    push eax
    mov eax,[esi+FC] // загрузил структуру золота и очков
    cmp dword ptr [iGold],1
    jne p1
    add [eax+94],#10000
    mov [iGold],0
    p1:
    cmp dword ptr [iXP],1
    jne p2
    add [eax+8c],#1000
    mov [iXP],0
    p2:
    cmp dword ptr [iPP],1
    jne p3
    add [eax+2c],#10
    mov [iPP],0
    p3:
    cmp dword ptr [iSP],1
    jne BPlayer
    add [eax+3c],#10
    mov [iSP],0
    BPlayer:
    pop eax
    fld dword ptr [esi+0000018c]
    jmp EPlayer
    Player:

    Пишем шаблон для повторяющихся участков


    cmp dword ptr [x1],1
    jne _next
    add [x2],x3
    mov [x1],0
    _next:
    //переменные dword: x1, x2, x3, _next

    Представим это дело функцией:


    {
    if (x1==0)
    {
    x2+=x3;
    x1=1;
    }
    }
    inline void AddSource(DWORD x1, x2, x3)

    Представим это дело как если бы писали dll-ку:



    void InitCheatData()
    {
    // написать инициализцаию для структуры cheatData;
    // написать прыг на Injection1() в место внедрения
    // написать баты нопов
    }

    void Injection1()
    {
    __asm
    {
    pushad
    pushfd
    }

    CheatAddValueHero();

    /* Посмотри сколько читов я могу сделать на С/С++ дальше
    а ты будешь их долго писать на ассемблере
    Cheat1();
    Cheat2();
    Cheat3();
    Cheat4();
    Cheat5();
    Cheat6();
    Cheat7();
    Cheat8();
    Cheat9();
    Cheat10();
    Cheat11();

    Если выбирать между удобством С/С++ и эффективностью ассемблера, то лучше выбрать первое если сложные: читы, механизмы активации и деактивации, если читов довольно много и т.п.
    */
    __asm
    {
    popfd
    popad
    }

    }

    inline void CheatAddValueHero()
    {
    for(int i=0; i<3; i++)
    {
    if (cheatData[i].x1==0)
    {
    cheatData[i].x2+=cheatData[i].x3;
    cheatData[i].x1=1;
    }
    }
    }
    struct CheatData {DWORD x1, x2, x3}[] cheatData;

    При загруке dll-ки вызывать функцию удалённым потоком InitCheatData();

  7. Akama, всё что я описывал это были общие рекомендации. Между прочем твоё решение было в этих рекомендациях, если ты не увидел.

    По-другому твой скрипт можно так написать:


    [ENABLE]
    alloc(newmem,2048)
    label(returnhere)
    label(originalcode)

    StrongholdLegends.exe+3E82D9:
    jmp newmem
    nop
    nop
    nop
    nop
    returnhere:

    newmem:
    fst dword ptr [ecx+4c]
    fcomp dword ptr [00910168]
    cmp dword ptr [ecx+178],1
    jne returnhere
    push [ecx+48]
    pop [ecx+4c]
    jmp returnhere


    [DISABLE]
    StrongholdLegends.exe+3E82D9:
    fst dword ptr [ecx+4c]
    fcomp dword ptr [00910168]

  8. Напоминаю, что реализ CE 6.0 на официальном сайте подразумевается 31 декабря или позже (январе или даже в феврале). Так что ждём ;)

    Те кто ждать не хотят могут сами скомпилировать проект из исходников SVN.

    Так же хочется упомянуть, что основная проблема русификации и тем более модернизации CE состоит в ручном изменении исходников CE. Т.е. довольно нудно и трудоёмко вручную переносить старые модернизации в новые версии CE. Если бы это дело как-то автоматизировать (например Макросами IDE Delphi), то было гораздо проще. Другая проблема лично моя - пока модернизацией CE я заниматься не хочу, т.к. полно своих дел.

  9. По поводу байтов:

    С битами и байтами у тебя не правильно расписано:

    По 8мь бит на один байт.

    У тебя

    0x0СС102 (3 байта = 3 группы по 8 бит)

    0xE0C102 (3 байта = 3 группы по 8 бит)

    0x0СС102 = 00001100 11000001 00000010

    0xE0C102 = 11100000 11000001 00000010

    Тут получается у тебя поменялся первый байт c 0С на E0. Можно конечно исчислять битами, но удобнее байтами. 0С - у тебя делает то-то, а E0 делает то-то.

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

  10. В общем причину глюка выявить не удалось - причина явно спонтанная, случайная. Что интересно, на втором острове сколько играю ни одного барьера не заметил. Но возвращаюсь на первый остров и там всюду барьеры(

    Что-то я не понял. Этот глюк спонтанно возникает с твоими изменениями в памяти или без них? Если второе, то искать причину будет весьма трудно. Если первое, то легче, но насколько легче не известно. По крайне мере в первом случае можно чётко установить обратную связь - изменил значение адреса, то получил глюк.

    Сделал ещё одно открытие. В структуре машины по смещению 44h находятся некие биты, отвечающие помимо прочего за иммунитет машин к взрывам, пулям, огню и пр. По умолчанию они равны CC102h, а для неуязвимой машины нужно выставить E0EC102h (эту инфу я нашёл в исходниках тренера GTA3Console). Совершенно случайно у меня прописался в эти биты нуль и результат меня очень порадовал - машина стала невидимой и начала ездить сквозь другие машины, препятствия и даже дома)) Офигенный чит)) Жаль что выйдя из такой тачки обратно в неё уже не сядешь. Попробовал вместо нуля другие цифры - чаще всего машины просто исчезают и не дают сесть в себя.

    Что-то бит я не увидел, увидел только "2,5 (CC102h) и 3,5(E0EC102h) байта" :) То что "ноль приводит к таким последствиям" это да - случайность и открытие. Но можно было предположить, что ты можешь перечислить наборы всех моделей пока не получить такое свойство. И тут тебе бы не пришлось много перебирать если бы ты начала с нуля.

    За труды в исследовании +1.

  11. Я это предположил с точностью до 80-99% процентов по первому посту в твоей теме. Я просто написал свои мысли для тех кому они могут пригодиться. Да и потом кто знает, может скрипты CE тебе будут скучны в будущем из-за того что ты будешь cool-программистом и тебе возможно это пригодиться.

  12. НА будущее для тех кто решит сделать подобное на С++. Текст ниже удобнее читать снизу-вверх.

    Передаем этот код из CE на следующий.



    GM:
    cmp dword ptr [iGM],1
    jne BGM
    cmp dword ptr [esi+00000184],1
    jne BGM
    db 90,90,90,90,90,90
    jmp EGM
    BGM:
    fstp dword ptr [esi+0000018c]
    jmp EGM

    Для Cheat.dll (C++)

    ----------

    inline void InfHealth()

    {

    const float value = 1000.0;

    __asm

    {

    mov dword [esi+0000018c],value

    }

    }

    inline void OneHitKill()

    {

    const float value = 0;

    __asm

    {

    mov dword [esi+0000018c],value

    }

    }

    inline bool GetFilter()

    {

    __asm

    {

    //....

    }

    }

    void Cheat_InfHealthOROneHitKill()

    {

    bool filter = GetFilter();

    if (filter)

    InfHealth();

    else

    OneHitKill();

    }

    void Init_InfHealthOROneHitKill()

    {

    DWORD* OffsetInMemory = xxxx;

    BYTE LengthNops = xx;

    xxx OldProtect;

    CreateInjection(OffsetInMemory, &Cheat_InfHealthOROneHitKill, LengthNops);

    }

    ------------

    Для SystemChet.dll (C++)

    -----------

    void Unprotect(DWORD OffsetInMemory, &OldProtect);

    {

    ///....

    }

    void CreateInjection(DWORD* FromOffset, DWORD* ToOffset, BYTE nopscount)

    {

    Unprotect(OffsetInMemory, &OldProtect); // снятие защиты с памяти, если треубуется

    OffsetInMemory = &Cheat_InfHealthOROneHitKill;

    OffsetInMemory+= 4;

    for (int i =0, i<LengthNops, i++)

    (*BYTE)(OffsetInMemory+i) = 0x90;

    RestoreUnprotect(OffsetInMemory, &OldProtect);// восстановление защиты памяти

    }

    // Инициализация

    void InitSystemCheta(string args[])

    {

    1) Поиск Init_InfHealthOROneHitKill() в Cheat.dll и связать эту функцию по горячей клавише

    2) Проверка на повтороное нажатие горяей клавиши

    }

    void CmpareKyes()

    {

    //...

    }

    -----------

    Для Lancher.exe (C#)

    ----------

    1) Загрузка обеих библиотек SystemCheta.dll и Cheat_InfHealthOROneHitKill

    2) Инициализация аргументов через функцию InitSystemCheta из SystemCheta.dll

    ----------

    Для каждой игры нужно писать только Cheat.dll и базу данных читов для ланчера написанного на C#. Остальной код переписывать не надо.

    Преимущества этого метода в том, что:

    1) не используем функции поиска и проверки присутствия процесса, не используется WriteProceesMemory и ReadProcessMemmory; не возимся с функцией выделения памяти и последующим распределением в ней инструкций.

    2) важное преимущество этого способа в том что мы можем использовать С++ на полную мощь, а не только ассемблерными вставками в скриптах Cheat Engine. С++ с IDE VisualStudio позволяет удобнее писать код :)

    3) C# позволит программисту удобным образом связываться с SystemChet.dll чтобы предостатвить пользователю интерфейс управления читами: их активация, деактивация, изменение названия читов с целью перевода на свой язык, установка горячих клавишь, установка читов которыми пользователь желает пользоваться и т.п.

  13. И всё таки, как же ломаются игры на PlayStation 2? В GTA нахождение нулевого адреса мало что даёт, адреса при перезагрузке меняются, приходится пользоваться автоизменением адресов. А сделать свою машину бессмертной и вовсе не получается, нужен указатель на структуру водителя в структуре машины, иначе задолбаешся каждую новую машину ломать((. И как же его искать? CE как я понимаю тут бессилен, нужен именно отладчик для PS2. Я знаю только про ps2dis. Но этому отладчику нужно скармливать elf-файл игры, т.е. он не реалтаймовый, как олли. Кто им пользовался - можно ли с помощью него как-то найти указатели, или есть другие пути?

    Все эти пути сводятся к одному - использование сканера памяти, отладчика Windows-приложений, отладчка рома и язык программирования (для продвинутых позволит автоматизировать разные процессы).

    Upd: в общем указатели то я нашёл, но ведь они все эмуляторные (оно и понятно), но как их обратно в компьютерные перевести? Долго мучился с CE и Artmoney, ничерта толком не получилось. Потом взял MHS и ввёл такие комплексные выражения (для PCSX2 r4040+):

    Здоровье игрока: 					[[pcsx2.exe+0010A328]+408E40h]+20000000h+4b8
    Здоровье машины, в которую игрок садится: [[[pcsx2.exe+0010A328]+408E40h]+20000000h+25Сh]+20000000h+268h

    Тут [pcsx2.exe+0010A328] - нулевой адрес, равный 20000000h (статический);

    [null_address+408E40h] - статический адрес, хранящий эмуляторный указатель на начало структуры персонажа (pHero_emul)

    [pHero_emul]+20000000h - переводим эмуляторный указатель в компьютерный (pHero)

    [pHero+4b8] - Здоровье

    [pHero]+25Ch - Указатель на структуру машины (pCar_emul)

    [pCar_emul]+20000000h - ещё одно превращение эмуляторного указателя в компьютерный

    [pCar+268h] - движок машины

    Вот так всё сложно получилось :( У кого какие идеи по упрощению?

    На языке программирования будет выглядеть лучше и проще. На MHS C-скрипте будет выглядеть тоже не плохо. Например, тебе нужно описать отдельные функции:

    1) Функция2 (использующая nulladdr) возвращающая структуру Hero;

    2) Функция3 (использующая Hero) совершает например заморозку здоровья героя;

    3) Функция4 (использующая Hero) совершает например заморозку стойкости машины.

    Аналогично, можно сделать PS2-ассемблерными вставками вместо заморозки, что будет эффективнее.

    А самое хреновое - в MHS нет хоткеев на прибавление\уменьшение к текущему значению адреса константы, есть хоткеи на фиксированное изменение значения и заморозку :( В Artmoney у меня на этих хоткеях получился прикольный телепорт))

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

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

    Первую причину установить легко - делай по шагам, то что привело к эффекту "глюка" и определишь какой шаг привёл к нему.

  14. Этой информации не достаточно. Тебе нужно сравнить как минимум 4 листинга регистров юнитов. Два твоих двух разных юнитов и два разных юнитов- врагов. Это сравнение первое которое можно сделать перед тем как ты сравнивал структуры юнитов твоих и врагов. Оно не всегда помогает и в этом случае уже можно сравнивать инструкции на бряках здоровья твоего и чужого юнитов. Если опять не определил фильтров, то ищёшь указатель уровня вверх по дизассемблерному коду и аналогично проходишь все этапы с ним: сравнение структур указателей твоего игрока и других юнитов, сравнение регистров, сравнение инструкций... не получилось, тогда опять ищем указатель на уровень выше и делаем заново с ним.

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

  15. Пока статьи нет, но будет общая информация о PS2 архитектуре.

    Часть 1. Общая информация о PS2, которая необходима для создания читов и для общих знаний.

    post-3-1292477975,57_thumb.jpg

    Эта игровая приставка 1999 года. Что нам нужно знать и может пригодиться

    1) Микропроцессор «Emotion Engine» построенный на MIPS R5900, комбинации CPU и DSP имеет:

    post-3-1292478453,3_thumb.jpg

    64 - разрядные регистры главного CPU ;

    128 -разрядные регистры сопроцессора «Emotion Engine» для обработки чисел с плавающей запятой;

    Судя по всему шина адресации 64 бита

    2) Графический процессор «Graphics Synthesizer» имеет:

    Видеопамять: встроенная 4 МБ DRAM с пропускной способностью 48 ГБ/с. Помимо этого, 32 МБ из основной памяти может быть выделено под видеопамять.

    Шина обмена с памятью: 2560-разрядная — 1024 на запись, 1024 на чтение, 512 на чтение/запись;

    3) 32 МБ ОЗУ с пропускной способностью 3,2 ГБ/с.

    4) Жесткий диск

    5) Отдельный процессор ввода/вывода.

    Дополнительную информацию и в более оформленном виде можно найти: здесь про приставку, здесь про CPU.

    Я пока не видел отладчик для MIPS R5900 в действии, но сначала стоит узнать о MIPS R5900. Пока я точно знаю, что IDA умеет отлаживать MIPS R5900 и Ps2dis, но IDA не умеет ассемблировать инструкции как это делают полноценные отладчики. Итак о MIPS R5900.

    Ссылка1, справочник, ссылка 2, ссылка 3 (MIPS32 4, 2004 года).

    К сожалению документацию именно по MIPS R5900 я не нашёл.

    По Ps2dis: статья (правда она так написана, что её поймет человек с опытом)

    А вот видео, про хотя бы даст представление как работать с Ps2dis (надо много терпения чтобы этот тутор просмотреть полностью и понять его):

    P.S. Если кто найдёт ещё информацию и даже найдёт о том как создавать читы в ромах PS2 то пишите здесь.

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

  17. 1) Для твоих двух юнитов:

    - Скопируй вверх пять инструкции  и вниз десять относительно StrongholdLegends.exe+3E82D9. Приведи значения регистров на сработанном бряке.

    2) Для  двух юнитов - врагов:

    - Скопируй вверх пять инструкции  и вниз десять относительно StrongholdLegends.exe+3E82D9. Приведи значения регистров на сработанном бряке.

    Итого получиться 4 листинга, приведи их здесь.

    3) Поставь бряк на адрес здоровья твоего одного юнита "на доступ" и приведи здесь все сработавшие инструкции:

       - когда ничего не происходит (зайди в игру подожди немного и выйди, никто не кому не должен наносить урона);

       - когда ты отнимаешь здоровье у врага;

       - когда враг отнимает здоровье у твоего юнита.

    4) Поставь бряк на адрес здоровья врага "на доступ" и приведи здесь все сработавшие инструкции:

       - когда ничего не происходит (зайди в игру подожди немного и выйди, никто не кому не должен наносить урона);

       - когда ты отнимаешь здоровье у врага;

       - когда враг отнимает здоровье у твоего юнита.

    Итого получиться 4 листинга + 6 листингов. Можешь их написать здесь, а можешь сам проанализировать. Тебе нужно найти зацепку: либо найти инструкции которые работают только с твоими юнитами или только с врагами, либо найти аналогично регистры, либо сравнивать структуры, либо искать цепочку указателей на структуры от глубокого уровня вверх. Ставить на "уровни бряки" и по тойже схеме что выше анализировать листинги. Может быть это всё покажется сложным, но если игр 20 таким образом обманешь, то всё уже делаешь на автоматизме.... 

  18.  

    class A {
        int x;
    protected:
        void *y;
    public:
        A (int _x) : x (_x), y (0) { }
        virtual int GetX (void) const { return x; }
        virtual void SetX (int _x) { x = _x; }
        };

    class B1: public A {
    public:
        B1 (void) : A (1) { }
        int GetX (void) const { return 1; }
        };

    class B2: public A {
    public:
        B2 (void) : A (2) { }
        int GetX (void) const { return 2; }
        };

     

    Теперь можно сделать так:

    A *x = new A (3);
    B1 *y = new B1 ();
    * (void **) x = * (void **) y; // сама привязка
    printf ("%d\n", x->GetX ()); // выведет 1

    Мне не понятен смысл описания:

    A (int _x) : x (_x), y (0) { }

    Вообще-то похожим способом объявляются вызовы базовых классов, но здесь не определены базовые классы для class A, а просто описаны: int x;,  void *y;. Тогда почему, возможно вызывать эти элементы как базовые классы?  :)

  19. Объявляются благодарности.

    live_4_ever - за активное участие, (повышен уровень).

    M4K - за активное участие (повышен уровень).

    SER[G]ANT - за участие (не сильно, но +2 повышен уровень за создание темы про указатели)

    Пока на этом всё.

  20.   Я могу только пока прокомментировать. Скорее всего на играх этой платформы PS2 есть "аналогичные" указатели как у PC игр. Также есть указатели на структуры в которых находятся указатели на другие структуры и так далее (глубина указателей уже зависит от кода разработчиков).

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

    p.s. Я вам обоим добавил по одному баллу уровня ("репутации") за ведение и интерес к этой теме, т.к. у нас на форуме активность низкая.

  21.  Спасибо, ссылку я посмотрел.  Это статья для начинающих.

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

    [ENABLE]
    aobscan(addres1,F6 B8 A9 20 8d 06 20 b5 b8 38 e9 01 4a 4a 4a)
    aobscan(addres2,02 04 00 02 04 00 02 04 00 02 04 00 02 04 00 02 04)

    addres1:
    db 4c 0b cb ea

    addres2:
    db F6 B8 8D 16 CB A9 00 85 B8 AD 16 CB 4C FB C1 02 04


    [DISABLE]
    aobscan(addres1, 4c 0b cb ea 8d 06 20 b5 b8 38 e9 01 4a 4a 4a)
    aobscan(addres2, F6 B8 8D 16 CB A9 00 85 B8 AD 16 CB 4C FB C1 02 04)

    addres1:
    db F6 B8 A9 20

    addres2:
    db 02 04 00 02 04 00 02 04 00 02 04 00 02 04 00 02 04

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

    Я сделал для себя вывод, что по началу привыкнуть к ассемблеру под "этот" процессор сложно, нужно упорство. А потом всё легче и легче и уже что-то делаешь на автомате: ищешь адрес, ставишь бряки, ищешь codecave, пишешь условие на ассемблере, прыжок на кодкейв, прыжок обратно, копируешь байты, проверяешь сигнатуры, пишешь скрипт на CE и чит для рома готов и он теоретически не зависит от типа эмулятора. В CE при запуске скрипта нужно поставить настройки памяти, как это было указано в первом посте.

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

  22. Кратко о функциональных выражениях в C#.

    Встретил я вот такой "условный" вариант и мне он понравился:

    new [] { this.button1, this.button2, ... this.button7 }
            .ToList().ForEach(p => p.Click += button_Click);

    void button_Click(object sender, EventArgs e)
    {
            var btn = (Button) sender;
    }

     А вот мой пример насколько может быть запутанных функциональное выражение. Запутанное в том смысле если к нему ещё не успел привыкнуть (не рекомендуется писать dSMultiLauncher, лучше DSMultiLauncher, но мне лень исправлять здесь):

     Вариант 1


    var files = from v in dSMultiLauncher.Files
                     where (v.GroupID==Position)
                     select v.Puth;

    foreach (var Puth in files)
    {
         int imageIndex = iconListManager.AddFileIcon(Puth);
         conList_ListView.Items.Add(Puth, imageIndex);
    }

               

    Вариант 2

    (from v in dSMultiLauncher.Files
                 where (v.GroupID == Position)
                 select v.Puth).ToList().ForEach(Puth =>{
                        int imageIndex = iconListManager.AddFileIcon(Puth);
                        iconList_ListView.Items.Add(Puth, imageIndex);});

                       

    Не могу определить что лучше для меня, т.к. я привыка. к функциольным выражениям

    Целая функция будет выглядеть так:

    void FillGroupsAndIcons()
            {
                // Выбрать группу на которую установлен указатель в таблице
                int Position = groupBindingSource.Position;
                DSMultiLauncher.GroupRow gr = dSMultiLauncher.Group[Position];

                // Найти файлы по текущей группе и
                // заполнить иконками писок
                (from v in dSMultiLauncher.Files
                 where (v.GroupID == gr.ID)
                 select v.Puth).ToList().ForEach(Puth =>{
                        int imageIndex = iconListManager.AddFileIcon(Puth);
                        iconList_ListView.Items.Add(Puth, imageIndex);});
            }

    Однако из предыдущего поста, где был пример  из MSDN, там foreach решили поставить вместо того чтобы писать длинное функциональное выражение. Короче, для большинства проще расписывать с foreach, да и скорость выполнения быстрее (где-то я об этом читал). Но с функциональными выражениями пишешь код словно составляешь длинное предложение, прикольно ))) 

    Этот код я использую в реальном приложении, которое я пишу.

    post-3-1291611520,66_thumb.png

    Я пишу его для того чтобы разобраться как работать с сериализацией и десериализацией в базах данных, с автоманическим генерированием схемы базы данных и т.п..... Здесь приложение Windows Forms, но сериализация аналогична и в ASP.NET и SiliverLigth и т.п.. Например, можно будет на сервере генерировать разметку отправляемую клиенту. Она например будет нужна для записной книжки перетаскиваемых ссылок на различные медиафайлы... и этот список будет запоминаться на сервере... )

  23.   Когда я был маленьким я помню у меня был компьютер на котором тормозил Doom =) Потом он сломался, другой комп почему-то не покупали. Родители не видели в нём пользы, считали его просто игровой приставкой что ли. В 2003-2004 годах (10-11 класс) я не знал как пользоваться почтой. Я плохо знал компьютер на уровне пользователя. В 2004 году у меня только появился Интернет (в 2001 появился компьютер c Windows Millenium). Тогда я был человеком из Каменного века. Иногда у меня в школе в 10-м классе, в компьютеном классе  уже во всю играли в "какую-то" контру... Пользы от компьютера я видел мало, разве что только в игры резаться. 

    В 2003 году у меня было несколько моих дисков игрового журнала на которых был только MTC и скупая игроманская документация о том как MTC пользоваться. В игре Legacy of Kain: Defiance (эту игру мне дал знакомый) меня просто прижал самый главный бос (в конце игры). Я его почему-то никак не мог пройти. И тогда я после удачных попыток сделал постоянное здоровье. Использовал MTC (Magic Trainer Creator) поиск неизвестного значения.

    Legacy of Kain: Defiance   PC

    Дата выхода: 16 декабрь 2003

    Минимум: CPU 700 MHz, 128 Mb, 32 Mb Video

    Рекомендуем: CPU 1.3 GHz, 256 Mb, 64 Mb Video

    Это вроде была моя первая игра где я с умом использовал сканер памяти MTC после упорных попыток и чтения документации. До этого я тоже что-то делал или пытался, но интереса у меня особого это не вызывало - слишком было сложно. Потом там же где-то в 2003-2004 годах я узнал об Артмани и читал её справку с невиданной жадностью и не всё понимал. Потом узнал про то что сильно недооценивал Cheat Engine и ещё с большим интересом узнавал как им пользоваться. Потом набил руку с Olly Debagger и с IDA. Потом узнал как писать программы на Дельфи и C++ работающие API Windows и мне это помогло понять механизмы которые происходят в играх. Трейнеров я делал очень мало не знаю почему. Наверно, потому что мне хватало получать удовольствие от скриптов Cheat Engine. Хотя получить славу от создания трейнеров, тоже не плохо. Как-нибудь доделаю TrainerMax...  

×
×
  • Создать...

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

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