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

MasterGH

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

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

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

    129

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

  1. >>OllyDbg у меня выдает ошибку ntdll.DbgBreakPoint на винде Win 7 64bit

    У меня OllyDbg запускается под Win7 64. У меня две версии OllyDbg, та которая с нашего сайта и последняя с официального сайта OllyDbg. И та и та запускается. Сначала надо запустить игру в конном режиме,а после аттачить его из OllyDbg из меню файла. Если будут остановки из-за исключений, то пропускать их по подсказкам внизу окна Olly или же настроить пропуск исключение из настроек Olly.

    По повод IDA, всё-таки советую с ним разобраться... он может гораздо удобнее показать код стрелками и связанными блоками, но только после того как будет проанализирован весь исполняемый файл... Так декомпиляция Arrays по горячей клавише F5 покажет псевдокод в удобном представлении. Можно довольно быстро сориентироваться поступает ли указатель прямо из функции или указатель извлекается внутри функции. Тоже самое правда с ошибками делает RecStudio.

    По поводу DBVM и ошибок из-за виртуальных машин ничего сказать не могу. У меня DBVM не работал лишь один раз при комиляции Cheat Engine из SDK...

  2. Не забывайте, что одновременно с Cheat Engine есть инструменты OllyDbg(удобный отладчик в пошаговой отладке и установки условных бряков), IDA + Hex-Rays(анализирование дизассемблерного кода и декомпилирование), RecSudio(декомпилирование), Function Hacker (перехват тех или иных функций), MHS... В последней программе есть удобная функция просматривания и составления цепочек указателей....

    В Cheat Engine есть LUA engine, который поможет ставить бряки и удобно снимать показания регистров в лог...

    Так же в CE есть инструмент трассировщика с условием прерывания. Этот трейсер может показать огромное дерево иерархии вызовов кода...

    В CE есть сканер указателей и dessect data tool позволит просматривать и сравнивать структуры.

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

    Сами понимаете, что учиться овладеть этим далеко непросто. Можно использовать только OllyDbg, ставив условные бряки при выходе из call-а, по методу из статьи Never Winter Nigth.

    У Cheat Engine есть сканер указателей. Его лучше не использовать, потому что он может найти неправильный указатель руководствуясь поиском указателей через вычитание и сложение смещений, когда могут быть и другие операции... и быть на 100% уверенным в том, что этот указатель будет всегда работать нельзя. У некоторого пользователя в какой-то момент этот указатель может "сбиться".

  3. Путь адреса будет меняться с каждым запуском. Сделать этот путь постоянным практически не возможно. Поэтому требуется найти этот путь: словно такой-то город, такая-то улица, такой-то дом, такая-то квартира... "о здрасте, а вот и ты Адрес здоровья моего героя!" .

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

  4. Там гед я писал слово "уровень" это относилось к некоторому указателю в цепочки указателей...

    Код игры прекрасно знает кто пользователь, а кто Бот. Это нужно всегда помнить.

    Ищите зацепки в коде, в бряках на уровнях указателей, в структурах указателей. По крайне мере ищите цепочку указателей до статического адреса (он должен быть зелёным в CE) и не проиграйте.

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

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

  5. Я вот всё равно не пойму, когда исключение срабатывает при обращении к несуществующему адресу, то как определяется чему должен установиться EIP? Есть быстрый ответ?

  6. В посте номер 4. Есть строка кода:

    58D5DD9F - 88 8E C4000000     		- mov [esi+000000C4],cl

    Определите какие адреса проскакивают в квадратных скобках. Это можно сделать из меню дизассемблера функцией "Find out what addresses this code accesses".

    image3005.jpg

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

    Может быть я запутанно написал, но пока ничем больше помочь не могу.

  7. Трейнер я так понимаю будет лучше делать на LUAEnigne?

    Не увидел этот вопрос... Это уже второстепенный вопрос. Сначала надо понять что нужно реализовать, а затем уже думать на чём делать. Так что такой вопрос задавать без исследования рано. Возможно и на АА сделать можно.

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

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

    C бОльшей уверенностью скажу что 2 Способ от MasterGH верный

    PS Если найду исходники моего давнего трейнера для GTA IV выложу тут, спавн тачек присутствует :)

    Когда найдёшь и покажешь, тогда тебе и поверим... иначе всё останется туманной теорией :)

  8. Я ни разу не делал обработку исключений (SEH) на Ассемблере. Xipho, может быть ты делал и знаешь быстрое решение? Я знаю есть мануалы, но пока мне их некогда читать.

    Вот пример АА на CE (в комментариях указано где нужно обработать SEH):

    [ENABLE]
    alloc(newmem,2048)
    label(returnhere)
    label(originalcode)
    label(_cmpString)
    label(_valueString)
    label(_pValueString)
    label(_pCmpString)

    newmem:
    pushfd
    pushad
    push ecx //+44(4 + 4*9 + 4) или 11 двордов
    lea eax, [esp+4*B+0ac]
    lea ebx,[_cmpString]
    mov [_pCmpString], ebx
    lea ebx,[_pCmpString]
    // прооверка строки "GetPlayerFaction" по [esp+ac]
    cld
    mov ecx,#16
    lds esi,[eax] //<<< здесь нужна обработка исключения в случае если по eax нет указателя на строку
    les edi,[ebx]
    cmpsb

    jnz short originalcode
    // если строки совпали, то записать по [esp] "999999"
    lea ebx,[_valueString]
    mov [_pValueString], ebx
    lea ebx,[_pValueString]
    mov ecx,7
    lds esi,[ebx]
    les edi,[esp] //<<< здесь нужна обработка исключения в случае если по esp нет указателя на строку
    cld
    rep movsb

    originalcode:
    pop ecx
    popad
    popfd

    mov eax,[ecx]
    mov edx,7EFEFEFF
    jmp returnhere

    db 90 90 90 90 90

    _pCmpString:
    dd 0
    _pValueString:
    dd 0

    _cmpString: //"GetPlayerFaction"
    db 47 65 74 50 6C 61 79 65 72 46 61 63 74 69 6F 6E 00

    _valueString: // "999999"
    db 39 39 39 39 39 39 00


    "SpazGame.exe"+157790:
    jmp newmem
    nop
    nop
    returnhere:


    [DISABLE]
    "SpazGame.exe"+157790:
    mov eax,[ecx]
    mov edx,7EFEFEFF

    dealloc(newmem)

    Есть ещё один вариант "не париться" с ассемблером, а сделать dll-инжект на языке высокого уровня с обработкой исключений в секциях try ... catch. Но всё-таки может быть кто-то в курсе обработки на ассемблере?

  9. Xipho

    ID машины в гараже нашел, а процедуру вызова машины по координатам нельзя из этого сделать?

    Нельзя. Этот ID уже появился. Конструктор (инструкции машинного кода) уже создал этот ID. Конструктор для этого ID уже отработал своё и более работать не будет. По этому ID ты не выйдешь на конструктор поставив бряк.

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

  10. Почему я не мог раньше догадаться до такой простой вещи - аттач к процессу сделать по горячей клавише! В этом случае пользователь не увидит, что форма подвисает при AObscan-е.

  11. Нашел чит в GTA III, как его вызвать?


    add [ecx+009416D8],bh
    00490F35 - push 01
    00490F37 - push 005F62A0 : ["CHEAT3"]
    00490F3C - call 0052C7E0
    00490F41 - push eax
    00490F42 - call 005052C0
    00490F47 - pop ecx
    00490F48 - pop ecx
    00490F49 - call 004A1240
    00490F4E - mov [eax+000002C0],42C80000 //Тут устанавливается количество жизней
    00490F58 - call 004A11B0
    00490F5D - test eax,eax
    00490F5F - je 00490F92
    00490F61 - call 004A11B0
    00490F66 - mov [eax+00000200],447A0000
    00490F70 - call 004A11B0
    00490F75 - mov eax,[eax+00000284]
    00490F7B - test eax,eax
    00490F7D - jne 00490F92
    00490F7F - push 00
    00490F81 - call 004A11B0
    00490F86 - add eax,00000288
    00490F8B - mov ecx,eax
    00490F8D - call 00545B40
    00490F92 - ret

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

    Если в адресе значение "1", то код приведённый выше будет выполняться.

    Соответственно надо найти в памяти этот адрес сканером памяти, когда чит включен или выключен.

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

  12. 1) По-моему некрасиво показывать "смех" типа "нафига ты написал так много, когда можно было сделать проще". Ничего смешного нет. Хотя бы потому, что я вложил свой труд в создание статьи.

    2) Не все игры поддерживают параметры запуска оконного режима: ни -w, ни "-win", ни "window", ни другие могут не работать. Тогда кому-то возможно будет полезна именно эта статья особенно в случае, когда один процес запускает другой с параметрами... и дочерний процесс можно запустить минуя родительский с установлением оконного режима. Польза от статьи я думаю есть.

  13. Это возможно, это совершенно точно. Но решения у меня нет, т.к. я этим читом не занимался. Могу дать только подсказки.

    Решение твой задачи может быть очень даже непростым делом. По поводу идеи, даже если ты найдёшь адрес некоторого ID (кстати непонятно какого так как их, скорее всего, может быть несколько у машины), то скорее это не прокатит, т.к. ты не разберёшься с рутиной дизассемблерного кода.

    1. Способ.

    Насколько я помню, у игры есть читы чтобы получить ту или иную машину. Поэтому есть вариант проследить в отладке как это происходит. Здесь уже должен быть некоторый участок кода, который обрабатывает ввод от пользователя. Можно определить этот ввод в отладчике (как делать объяснять не буду, это долго) и выйти на нужный код, который создаёт машину. Главное добраться до этого кода, а там уже можно что-нибудь придумать.

    2. Способ.

    Могу предположить с большой вероятностью, что создание того или иного объекта в этой игре зависит от данных - сценариев (некоторого формата в оперативной памяти подгружаемых при начале уровня) и кода обрабатывающий эти сценарии (некоторые сценарии должны постоянно обрабатываться на истинность тех или иных условий)... Если в некотором сценарии для уровня будет директива "создать такую-то тачку по таким-то координатам после того как произойдёт что-то", то код "создаст такую-то тачку". Понять весь этот процесс возможно будет довольно тяжело. У тебя должно быть как минимум два сложных пути создания спавна. Изменить сценарий в памяти или изменить машинный код обработки сценариев. Что будет сложнее это уже зависит от игры. Изменив сценарий это ещё не значит, что его часть поступит на обработку, поэтому сценарий надо менять определённым образом (я без понятия каким). Оба способа должны вывести на функцию принимающую аргументы создания того или иного объекта в игре по тем или иным параметрам. Эту функцию предположительно надо чётко выполнить и тачка должна появиться.

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

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

  15. Ничего присоединять не надо ))

    Запустил CE.

    Открыл LUA-консоль вставил код выше и выполнил его.

    Запустил игру в моём случае "UT3.exe"

    Начал играть.

    Нажимаю F2 - увеличить скорость,F3 - уменьшить, F4 - сбросить до нормальной.

    Скрипт этот только пример.

    В настройках CE можно зайти и поставить свои хот-кеи на увеличение и уменьшение скорости, или на установку определённой скорости. Я совсем забыл про эти установки... Мне не надо было Lua скрипт писать оказывается... Ну пускай останется в качестве образовательных целей - написания кода на Lua.

  16. Если Вам кажется что в игре какие-то действия происходят слишком медленно или слишком быстро, то почему бы не увеличить или не уменьшить скорость. Герой будет быстрее передвигаться, быстрее стрелять... или же этот процесс можно замедлить. А вдруг в игре Вы что-то долго ждёте: медленные разворачивающиеся события... В таких случаях можно использовать следующий скрипт на Lua.

    speed = 1.0 

    function IncSpeed(hotkey)
    speed = speed + 1
    speedhack_setSpeed(speed)
    end

    function DecSpeed(hotkey)
    speed = speed - 1
    speedhack_setSpeed(speed)
    end

    function ResetSpeed(hotkey)
    speed = 1.0
    speedhack_setSpeed(1.0)
    end


    function SetHotKey(func, hotkey)
    local objectHotKey = createHotkey(func, hotkey)
    generichotkey_setKeys(objectHotKey, hotkey)
    generichotkey_onHotkey(objectHotKey, func)
    end


    function onOpenProcess(processid)
    SetHotKey(IncSpeed, VK_F2)
    SetHotKey(DecSpeed, VK_F3)
    SetHotKey(ResetSpeed, VK_F4)
    end

    local aalist = getAutoAttachList()
    stringlist_add(aalist, "UT3.exe")

    Измените горячие клавиши и имя процесса на свои данные. Константы горячих клавиш найдёте здесь. Если вам нужно задать комбинацию горячих клавиш таких как "CTRL+1", то посмотрите справку по createHotkey и generichotkey_setKeys. Горячие клавиши записываются через запятую в этих функциях...

    • Плюс 1
  17. Я продолжаю писать код на LUA для генерации трейнеров. Мне понадобилось сохранение пользовательских параметров и восстановление их при следующем запуске Lua файлов CE. Естественно, я не хотел писать то, что возможно уже написано (ссылка)

    Для начала мини тутор:

    ini_table = {}
    ini_table["n"] = {}
    ini_table["n"]["n"] = {}
    ini_table["n"]["n"]["n"] = 10

    for k,v in pairs(ini_table) do
    for k1,v1 in pairs(v) do
    for k2,v2 in pairs(v1) do
    print(k2,v2)
    end
    end
    end

    -- Вывод:
    -- n 10

    Если не поняли, то обращаемся к докоментации LUA. Данный приём позволит вывести ключи и значения. Именно этот приём позволит прочитать значения ini - файла. Давайте попробуем создать файл some.ini по пути логического диска D. У вас может быть другой путь.

    [Section1]
    s1_KEY=Value
    [sect2]
    s1_KEY=Value
    s1_KEY=Value2

    В консоли LUA Engine попытаемся вывести значения из файла.


    return string.format ("%s: %s:%d: %s", msg, filename, line_counter, line)
    end

    function get(filename) --> (ini_table) or (nil,err)
    local f = io.open(filename,'r')
    if not f then return nil, "cannot open file: " .. filename end
    local line_counter=0
    local ini_table = {}
    local section, err
    for fline in f:lines() do
    --set counter for indicate on error
    line_counter=line_counter+1
    --clean for begin and end spaces
    local line = fline:match("^%s*(.-)%s*{:content:}quot;)
    --coments
    if not line:match("^[%;#]") and #line > 0 then
    --section
    local sec = line:match("^%[([%w%s]*)%]{:content:}quot;)
    if sec then
    section = sec
    if not ini_table[section] then ini_table[section]={} end
    else
    --parse key=value and clean for begin and end spaces
    local key, value = line:match("([^=]*)%=(.*)")
    --check on errors in ini-file
    if not key then
    err = make_err('key/value absent', filename, line_counter, fline)
    break
    end
    --clean for begin and end spaces
    key = key:match("^%s*(%S*)%s*{:content:}quot;)
    value = value:match("^%s*(.-)%s*{:content:}quot;)
    if not (key and value) then
    err = make_err('bad key or value', filename, line_counter, fline)
    break
    end
    if section then
    if not ini_table[section][key] then ini_table[section][key]={} end
    ini_table[section][key][value] = true
    else
    err = make_err('key/value outside a section', filename, line_counter, fline)
    break
    end
    end
    end
    end
    f:close()
    if err then return nil, err end
    return ini_table
    end


    function set(ini_table, filename)
    f = io.open(filename,'w')
    if not f then return nil, "cannot open file: " .. filename end
    f:write('; Created by inilazy (http://luaforge.net/projects/inilazy/)\n\n')
    for secname, sec in pairs(ini_table) do
    f:write("[", secname, "]\n")
    for keyname, key in pairs(sec) do
    for value, _ in pairs(key) do
    f:write(keyname, "=", value, "\n")
    end
    end
    f:write "\n"
    end
    f:close()
    return true
    end

    nriu, err = get("D:\\some.ini")
    if (riu == nil) then
    print(err)
    else
    for k,v in pairs(nriu) do
    for k1,v1 in pairs(v) do
    for k2,v2 in pairs(v1) do
    print(k2,v2)
    end
    end
    end

    end
    local function make_err (msg, filename, line_counter, line)

    Таким образом получим ответ:


    Value2
    Value
    Value  

    Если вам нужны названия секций, а также запись в файл ini, то думаю уже сами разберётесь.

    Я собираюсь использовать файл ini для настроек LUA трейнера.

    post-3-1308501658,62_thumb.png

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

  18. ANT' date='19 Июнь 2011 - 10:10' timestamp='1308456642' post='3415']Навеяло темой о "Function Hacker", только чит мне там не понравился.

    Цель видео показать как работать с программой по нахождению функций отвечающих за то или иное действие. В другой игре может и не быть адреса от значения которого что-то зависит. Это значение может быть в регистре возвращаемой функции... Может быть какое-то мимолётное время в стеке и поймать значение в стеке сканером памяти будет невозможно.

    Потом для обмана игры все средства должны быть "на вооружении". С помощью Function Hacker можно случайно сделать читы о которых даже и не подумаешь.

    "Function Hacker" может помочь отсеивать функции которые нужно исследовать. И если повезёт, то ты быстро найдёшь ключевые моменты в дизассемблере от которых зависит тот или иной вызов функции. Ты сможешь определить то или иное условие...

  19. SetTimer - установить таймер. Находится в User32.dll

    KillTimer - уничтожить таймер. Находится в User32.dll

    TimerProc - объявление вызываемой функции в таймере

    Подробнее:

    Timer Functions

    http://msdn.microsof...3(v=VS.85).aspx

    About Timers

    http://msdn.microsof...0(v=VS.85).aspx

    Using Timers

    http://msdn.microsof...1(v=VS.85).aspx

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

    Что-то на русском:

    SetTimer http://rusapi.narod.ru/SetTimer.htm

    WM_TIMER http://rusapi.narod.ru/WM_TIMER.htm

    TimerProc http://rusapi.narod.ru/TimerProc.htm

    KillTimer http://rusapi.narod.ru/KillTimer.htm

    http://www.firststep.../help/r.php?249

    http://www.cyberguru...e-tajmerov.html

    В основном надо знать, что таймер создаётся через SetTimer импортируемую из User32.dll. Тамер срабатывает через определённый интервал времени. Количество срабатываний можно идентифицировать увеличивающимся счётчиком и в игре отображать этот счётчик как секунды, минуты или часы. Функцию извлечения системного времени и даты я не рассматриваю.

    Если таймер создан, то ему присваивается целочисленный идентификатор, который возвращается функцией SetTimer. Снимая показания именно этого таймера нужно обращаться именно к этому идентификатору в структуре сообщения WM_TIMER или снимать показания внутри функции сигнатуры TimerProc, которая была специально привязана к созданному таймеру. WM_TIMER обрабатывается в оконной процедуре, где снимаются сообщения системы посланные hwnd окна игры... Если создана "специальная функция" для таймера, то она минует функцию оконной процедуры обрабатывающей системные сообщения.

  20. Новая версия модуля TrainerGen.lua (версия 1.1)


    -- Create by MasterGH
    --[[
    На будущее:
    0) Добавить запуск игры из трейнера из указанного места
    1) Сделать отображение читов перед внедрением серым цветом, после вндрения чёрным с бипом
    2) Разобраться со скрытыми и не скрытыми читами в группах
    3) Сделать отображение читов в виде дерева на основе дерева из главной таблицы Cheat Engine
    Читы с префиксом "(+)" отображаются в дереве без префикса
    Рядом с именем корневого элемента дерева должен отображаться хот-кей
    Корневых элементов может быть не больше 9

    4) Обновление формы во время сканирования
    5) Возвратить сигнатуру
    6) Интеллектуальное внедрение

    8) Корректное использование трейнера, при повторном запуске игры.
    9) Поодержка русских слов
    10) Поддержка файлов перевода
    11) Запоминание адресов внедрения, чтобы проивзодить меньше сканирований сигнатур

    Раздел1
    1) FillnopsInstruction_AndAddInCETable(cheatName, address)
    Функция создаёт запись АА-скрипта в главной таблице CE c названием cheatName.
    АА-скрипт будет стерать инструкцию по адресу address при активации. При деактивации код будет восстановлен.

    2) FillnopsInstructionWithSignature_AndAddInCETable(cheatName, signature, typeMem, signatreOffset)
    Функция создаёт запись АА-скрипта в главной таблице CE c названием cheatName.
    Тоже что и FillnopsInstruction_AndAddInCETable только по сигнатуре.
    Где signature - сигнатура
    typeMem - тип сканируемой памяти
    signatreOffset - смещение от сигнатуры в виде числа, которое может положительным и отрицательным.

    3) GenerateAAscriptPageMem_AndAddInCETable( cheatName, address, injectInstruction, originalcode )
    Функция создаёт запись АА-скрипта в главной таблице CE c названием cheatName.
    Функция создаёт АА скрипт в новой странице памяти.
    Не рекоммендуется использовать эту функцию. Она создана только для тестов из консоли LUA. Используйте альтернативные функции из Раздела 2:
    BeginGenerateAA, GenerateAA, EndGenerateAA

    4) CreateThread(CEEntryName, callLabel)
    Функция создаёт запись АА-скрипта в главной таблице CE c названием CEEntryName.
    Функция создания АА-скрипта для потока с добавлением этого скрипта в главную таблицу
    Пригодится в случае создания АА исполнения кода находящегося под известной зарегистрированной меткой/
    Рекоммендуется использовать эту функцию в особенных редких случаях. Используйте альтернативную функцию из Раздела 2:
    BeginGenerateAA, AddCodeThread, EndGenerateAA

    5) SetScriptInEntryCETable(cheatName, script)
    Функция создаёт запись АА-скрипта в главной таблице CE c названием cheatName.
    Добавление скрипта в главную таблицу как записи таблицы с названием cheatName. Если запись уже существует, то будет перезапись.
    Рекоммендуется использовать эту функцию в особенных редких случаях. Используйте функциии из Раздела 2, которые добавляют скрипт в CE.

    6) DeleteTableEntryes(tableCEEntryesName)
    Удаляет записи из главной таблицы Cheat Engine.
    tableCEEntryesName имеет формат вида {"имя","имя", ...}

    7) GroupAA(nameGRcheat, tableCheats, stateDeleteTableCheats)
    Группировка указанных скриптов tableCheats вида {"имя","имя",..} в новый создаваемые или существующий скрипт с названием nameGRcheat.
    Группируемые скрипты будут удалены если stateDeleteTableCheats бует равен true

    Раздел2
    Используйте функции BeginGenerateAA и EndGenerateAA для формирования и исполнения скрипта. Между этими функциями разрешается выполнять другие функции с передачей aggregateMem и возрватом нового сформированного скрипта.

    Пример:
    script = BeginGenerateAA(script,...)
    // Здесь любые функции из раздела 2 например это
    script = GenerateAA(script, ...)
    script = GenerateAAWithSignature(script, ...)
    EndGenerateAA(script,...)

    1) BeginGenerateAA(newMemDescription, sizeMem)
    Герация начала формирования разметки

    2) EndGenerateAA(aggregateMem)
    Конец формирования разметки с исполнением АА-скрипта

    3) GenerateAA(aggregateMem, cheatName, address, newCode, stateOriginalCode)
    Продолжение формирования разметки.
    Добавляет запись с названием cheatName в главную таблицу
    В АА скрипте формируются метки originalcode_cheatName, где cheatName название из скрипта

    4) GenerateAAWithSignature(aggregateMem, cheatName, signature, typeMem, signatureOffset, newCode, stateOriginalCode )
    Продолжение формирования разметки по сигнатуре.
    Добавляет запись с названием cheatName в главную таблицу
    В АА скрипте формируются метки originalcode_cheatName, где cheatName название из скрипта

    5) AddCodeThread(aggregateMem, newRegSymbols, AAcode)
    Продолжение формирования разметки.
    Добавляет запись с названием cheatName в главную таблицу
    Регистрируется метка newRegSymbols и добавляется запись в главную таблицу runThread_newRegSymbols

    6) AddRegisterSymbols(aggregateMem, tableNewSymbols)
    Продолжение формирования разметки. tableNewSymbols вида {"имя","имя","имя","имя",...}
    Регистрация пользовательских символа в формирующуюся разметку между началом и концом её формирования

    7) AddAllocVariableRegistersymbols(aggregateMem, tableTableSymbols)
    где tableTableSymbols может быть вида { {"pId", 4}, {"pRES", 4}, ... }
    Продолжение формирования разметки.
    Добавление регистрации пользовательского символа для участка памяти определённого размера в формирующуюся разметку между началом и концом её формирования.

    8) AddCode(aggregateMem, newRegSymbols, AAcode)
    Продолжение формирования разметки.
    Добавление участка кода в скрипте в выделенную память. Участок код регистрируется под меткой newRegSymbols. Новый код AAcode

    Локальные функции:
    CheatAction(indexCheat)
    Trainer_Close(sender)
    Trainer_SendMessage(message)
    Trainer_FormCreate(nameTrainer)
    Trainer_CheatsCreateFromCETable()

    onOpenProcess(processid)

    ByteScan(signature, typeMem)
    GetInfoInjection(address)
    PreSubScript(script, patternWord, newWords)

    DeleteEntryCETable(cheatName)
    ]]--

    local frmTrainer = nil -- форма автоматически создаваемого трейнера
    local frmTrainerWidth = 0
    local frmTrainerHeigth = 0
    local messageLabel = nil -- строка информации в трейнере

    local _InitFunction -- указатель на пользовательскую функцию инициализации читов

    local countObjectHotKeys = 0 -- countObjectHotKeys равное также кол-ву записей в главной таблице
    local adrList = nil
    local baseHotKey = "CTRL"


    local function CheatAction(indexCheat)
    local te = addresslist_getMemoryRecord(adrList, indexCheat-1)
    if (memoryrecord_isActive(te)) then
    memoryrecord_unfreeze(te)
    else
    memoryrecord_freeze(te, 0)
    end
    beep()
    end

    function onHotkey1(hotkey) CheatAction(1) end
    function onHotkey2(hotkey) CheatAction(2) end
    function onHotkey3(hotkey) CheatAction(3) end
    function onHotkey4(hotkey) CheatAction(4) end
    function onHotkey5(hotkey) CheatAction(5) end
    function onHotkey6(hotkey) CheatAction(6) end
    function onHotkey7(hotkey) CheatAction(7) end
    function onHotkey8(hotkey) CheatAction(8) end
    function onHotkey9(hotkey) CheatAction(9) end

    local arrayFunction = {}
    arrayFunction[1] = onHotkey1
    arrayFunction[2] = onHotkey2
    arrayFunction[3] = onHotkey3
    arrayFunction[4] = onHotkey4
    arrayFunction[5] = onHotkey5
    arrayFunction[6] = onHotkey6
    arrayFunction[7] = onHotkey7
    arrayFunction[8] = onHotkey8
    arrayFunction[9] = onHotkey9

    local function Trainer_Close(sender)
    closeCE()
    return caFree
    end
    local function Trainer_SendMessage(message)
    control_setCaption(messageLabel, message)
    end
    local function Trainer_FormCreate(nameTrainer)
    frmTrainer = createForm(true)
    setProperty(frmTrainer, "BorderStyle", "bsDialog")
    control_setSize(frmTrainer, frmTrainerWidth, frmTrainerHeigth)
    control_setCaption(frmTrainer, nameTrainer)
    form_centerScreen(frmTrainer)
    form_onClose(frmTrainer, Trainer_Close)

    messageLabel = createLabel(frmTrainer)
    control_setAlign(messageLabel, alBottom)
    Trainer_SendMessage("Trainer is not ready")
    end
    local function Trainer_CheatsCreateFromCETable()
    if (adrList == nil) then
    adrList = getAddressList()
    end

    countObjectHotKeys = addresslist_getCount(adrList)
    if (countObjectHotKeys < 1 or countObjectHotKeys > 9) then
    showMessage("Cheats group count can not be less than 1 or greater than 9. Trainer will be closed")
    Trainer_Close()
    end

    local x = 20
    local y = 10
    local yInc = 14

    CheatLbl = createLabel(frmTrainer)
    control_setPosition(CheatLbl, x, y)
    control_setCaption(CheatLbl, "Cheats:")
    x = x + 15

    for i = 1,countObjectHotKeys do
    local te = addresslist_getMemoryRecord(adrList, i-1)
    local description = memoryrecord_getDescription(te)
    local ObjectHotKeys = createHotkey(arrayFunction[i], VK_CONTROL, VK_0 + i) --string.format("%s",i)
    generichotkey_setKeys(ObjectHotKeys, VK_CONTROL, VK_0 + i)
    generichotkey_onHotkey(ObjectHotKeys, arrayFunction[i])

    CheatLbl = createLabel(frmTrainer)
    control_setPosition(CheatLbl, x, (i + 1) * yInc)
    local stringHotKey = baseHotKey.."+"..i
    control_setCaption(CheatLbl, i..") "..description..": "..stringHotKey)
    end

    Trainer_SendMessage("Trainer is ready!")
    beep()
    end


    function onOpenProcess(processid)
    _InitFunction()
    Trainer_CheatsCreateFromCETable()
    end

    local function ByteScan(signature, typeMem) -- return address
    Trainer_SendMessage("Scaning mode... Play in game and wait bell")
    local results = nil
    -- if (results == nil) then
    -- messageDialog("Ошибка. Не найден адрес внедрения.\n\rТрейнер будет закрыт!",1, 2)
    -- Trainer_Close()
    -- end
    repeat
    results = AOBScan(signature, typeMem) -- typeMem = "+X-C-W" and any
    -- form_show(frmTrainer)
    sleep(200)
    until (results ~= nil)

    local address = stringlist_getString(results, 0)
    object_destroy(results);
    return address
    end
    local function GetInfoInjection(address) -- return adressReturnHere, originalCodeString, nopsString
    local sumBytes = 0
    local originalCodeString = " "

    repeat
    countBytes = getInstructionSize(address)
    extrafield, opcode, bytes, address = splitDisassembledString(disassemble(address))
    originalCodeString = originalCodeString.."\n "..opcode
    sumBytes = sumBytes + countBytes
    until (sumBytes >= 5)
    adressReturnHere = string.format("%x", ("0x"..address) + countBytes)

    local nopsString = ""
    local nopsCount = sumBytes - 5
    if (nopsCount>0) then
    nopsString = " db"
    for i = 1, nopsCount do
    nopsString = nopsString.." 90"
    end
    end

    return adressReturnHere, originalCodeString, nopsString
    end
    local function PreSubScript(script, patternWord, newWords) -- return bufferString
    local index = string.find(script, patternWord)
    local newscript = string.sub(script, 1, index - 1)..newWords.."\n"..string.sub(script, index)
    return newscript
    end
    local function DeleteEntryCETable(cheatName)
    local teSlave = getTableEntry(cheatName)
    if (teSlave == nil) then
    return
    end
    memoryrecord_delete(teSlave)
    end

    -- SECTION 1
    function FillnopsInstruction_AndAddInCETable(cheatName, address)
    adressReturnHere, originalCodeString, nopsString = GetInfoInjection(address)
    local scriptAddMainTable = "[ENABLE]\n-->>address1[DISABLE]\n-->>address2"

    local countBytes = getInstructionSize(address)
    local nopsString = " db"
    for i = 1, countBytes do
    nopsString = nopsString.." 90"
    end

    scriptAddMainTable = PreSubScript(scriptAddMainTable,"-->>address1", address..":\n"..nopsString)
    scriptAddMainTable = PreSubScript(scriptAddMainTable,"-->>address2", address..":"..originalCodeString)
    scriptAddMainTable = string.gsub(scriptAddMainTable, "-->>address1", "")
    scriptAddMainTable = string.gsub(scriptAddMainTable, "-->>address2", "")
    SetScriptInEntryCETable(cheatName,scriptAddMainTable)
    end
    function FillnopsInstructionWithSignature_AndAddInCETable(cheatName, signature, typeMem, signatreOffset)
    local workAddress = ByteScan(signature, typeMem)
    if (signatureOffset ~=0) then
    workAddress = string.format("%x", ("0x"..workAddress) + signatureOffset)
    end
    FillnopsInstruction_AndAddInCETable(cheatName, workAddress)
    end
    function GenerateAAscriptPageMem_AndAddInCETable( cheatName, address, injectInstruction, originalcode )
    local addressInjection = address

    local adressReturnHere = 0
    local originalCodeString = ""
    local nopsString = ""
    adressReturnHere, originalCodeString, nopsString = GetInfoInjection(address)

    if (originalcode) then
    script =[[
    [ENABLE]
    alloc(newmem,2048)
    label(originalcode)
    label(returnhere)

    newmem:
    ]]..injectInstruction..[[

    originalcode:]]..originalCodeString.. [[

    jmp returnhere

    ]]..addressInjection..[[:
    jmp newmem
    ]]..nopsString..[[
    returnhere:

    [DISABLE]
    ]]..addressInjection..":"..originalCodeString.. [[


    dealloc(newmem)
    ]]
    else
    script =[[
    [ENABLE]
    alloc(newmem,2048)
    label(returnhere)

    newmem:
    ]]..injectInstruction..[[

    jmp returnhere

    ]]..addressInjection..[[:
    jmp newmem
    ]]..nopsString..[[
    returnhere:

    [DISABLE]
    ]]..addressInjection..":"..originalCodeString.. [[


    dealloc(newmem)
    ]]
    end
    SetScriptInEntryCETable(cheatName, script)
    end
    function CreateThread(CEEntryName, callLabel)
    local bufscript = "%[ENABLE%]\n% createthread("..callLabel..")\n[DISABLE%]"
    SetScriptInEntryCETable(CEEntryName, bufscript)
    end
    function SetScriptInEntryCETable(cheatName, script)
    local teSlave = getTableEntry(cheatName)
    if (teSlave == nil) then
    teSlave = addresslist_createMemoryRecord(addresslist)
    memoryrecord_setDescription(teSlave, cheatName)
    end
    memoryrecord_setType(teSlave, vtAutoAssembler)
    memoryrecord_setScript(teSlave, script)
    end
    function DeleteTableEntryes(tableCEEntryesName)
    local sizetable = table.getn(tableCheatsName)
    for i=1,sizetable do
    DeleteEntryCETable(tableCheatsName[i])
    end
    end
    function GroupAA(nameGRcheat, tableCheats, stateDeleteTableCheats)
    if (adrList == nil) then
    adrList = getAddressList()
    end
    countObjectHotKeys = addresslist_getCount(adrList)
    mainGRScript = "[ENABLE]-->>marker1\n[DISABLE]\n-->>marker2"
    local delIndexes = {}
    local count_delIndexes = 0
    local zisetable = table.getn(tableCheats)
    local description = ""
    for i = 1,countObjectHotKeys do
    local te = addresslist_getMemoryRecord(adrList, i-1)
    description = memoryrecord_getDescription(te)
    for j=1,zisetable do
    if (tableCheats[j] == description) then
    local script = memoryrecord_getScript(te)
    local leftPos = 10 -- длина "[ENABLE]\n" 9 символов и плюс переход +1
    local rigthPos = string.find(script, "%[DISABLE%]")
    mainGRScript = PreSubScript(mainGRScript,"-->>marker1",string.sub(script, leftPos, rigthPos-2))
    leftPos = rigthPos + 10 + 1
    rigthPos = string.len(script)
    mainGRScript = PreSubScript(mainGRScript,"-->>marker2",string.sub(script, leftPos, rigthPos))
    count_delIndexes = count_delIndexes + 1
    delIndexes[count_delIndexes] = te
    break
    end
    end
    end

    if (stateDeleteTableCheats) then
    for i = 1,count_delIndexes do
    memoryrecord_delete(delIndexes[i])
    end
    end

    mainGRScript = string.gsub(mainGRScript, "-->>marker1", "")
    mainGRScript = string.gsub(mainGRScript, "-->>marker2", "")
    SetScriptInEntryCETable(nameGRcheat,mainGRScript)
    end
    -- SECTION 2
    function BeginGenerateAA(newMemDescription, sizeMem) -- return bufferString
    return [[
    alloc(]]..newMemDescription..","..sizeMem..[[)
    registersymbol(]]..newMemDescription..[[)
    ->>label]]..newMemDescription..[[:

    ->>newCode
    ->>adressessInjected
    ]]
    end
    function EndGenerateAA(aggregateMem)
    local endScript = string.gsub(aggregateMem, "->>label", "")
    endScript = string.gsub(endScript, "->>newCode", "")
    endScript = string.gsub(endScript, "->>adressessInjected", "")
    autoAssemble(endScript)
    end
    function GenerateAA(aggregateMem, cheatName, address, newCode, stateOriginalCode) -- return bufferString
    local addressInjection = address
    local adressReturnHere = 0
    local originalCodeString = ""
    local nopsString = ""
    adressReturnHere, originalCodeString, nopsString = GetInfoInjection(address)

    registerSymbol("returnHere_"..cheatName, adressReturnHere)

    local script = PreSubScript(aggregateMem,"->>label", "label("..cheatName..")")
    script = PreSubScript(script,"->>label", "registersymbol("..cheatName..")")

    if (stateOriginalCode) then
    script = PreSubScript(script,"->>label", "label(originalcode_"..cheatName..")")
    local buf = cheatName..":\n "..newCode.."\noriginalcode_"..cheatName..":"..originalCodeString.."\n jmp returnHere_"..cheatName
    script = PreSubScript(script,"->>newCode", buf)
    else
    script = PreSubScript(script,"->>newCode", cheatName..":\n"..newCode.."\n jmp returnHere_"..cheatName)
    end

    local scriptAddMainTable = "[ENABLE]\n-->>address1[DISABLE]\n-->>address2"
    scriptAddMainTable = PreSubScript(scriptAddMainTable,"-->>address1", addressInjection..":\n jmp "..cheatName.."\n"..nopsString)
    scriptAddMainTable = PreSubScript(scriptAddMainTable,"-->>address2", addressInjection..":"..originalCodeString)
    scriptAddMainTable = string.gsub(scriptAddMainTable, "-->>address1", "")
    scriptAddMainTable = string.gsub(scriptAddMainTable, "-->>address2", "")
    SetScriptInEntryCETable(cheatName,scriptAddMainTable)

    return script
    end
    function GenerateAAWithSignature(aggregateMem, cheatName, signature, typeMem, signatureOffset, newCode, stateOriginalCode ) -- return bufferString
    local workAddress = ByteScan(signature, typeMem)
    if (signatureOffset ~=0) then
    workAddress = string.format("%x", ("0x"..workAddress) + signatureOffset)
    end
    return GenerateAA(aggregateMem, cheatName, workAddress, newCode, stateOriginalCode)
    end
    function AddCodeThread(aggregateMem, newRegSymbols, AAcode)
    newRegSymbols = "threadAA_"..newRegSymbols
    local script = PreSubScript(aggregateMem,"->>label", "label("..newRegSymbols..")")
    script = PreSubScript(script,"->>label", "registersymbol("..newRegSymbols..")")
    script = PreSubScript(script,"->>newCode", AAcode)

    local bufscript = "%[ENABLE%]\n% createthread("..newRegSymbols..")\n[DISABLE%]"
    SetScriptInEntryCETable("runThread_"..newRegSymbols, bufscript)

    return script
    end
    function AddRegisterSymbols(aggregateMem, tableNewSymbols) -- return bufferString
    local sizetable = table.getn(newSymbols)
    for i=1,sizetable do
    PreSubScript(aggregateMem,"->>label", "label("..tableNewSymbols[i]..")")
    PreSubScript(aggregateMem,"->>label", "registersymbol("..tableNewSymbols[i]..")")
    end
    return aggregateMem
    end
    function AddAllocVariableRegistersymbols(aggregateMem, tableTableSymbols) --tableTableSymbols = { {"pId", 4}, {"pRES", 4} } -- return bufferString
    local sizetable1 = table.getn(tableTableSymbols)
    for i=1,sizetable1 do
    local inTable = tableTableSymbols[i]
    local sizetable2 = table.getn(inTable)
    for j=1,sizetable2 do
    local regName = inTable[1]
    local sizeRegName = inTable[1]
    local template = regName..":\n".."db "
    for j=1,sizeRegName do
    template = sizeRegName.."00"
    end
    local name
    PreSubScript(script,"->>label", "label("..regName..")")
    PreSubScript(script,"->>label", "registersymbol("..regName..")")
    script = PreSubScript(script,"->>adressessInjected", template)
    end
    end
    return script
    end
    function AddCode(aggregateMem, newRegSymbols, AAcode)
    local script = PreSubScript(aggregateMem,"->>label", "label("..newRegSymbols..")")
    script = PreSubScript(script,"->>label", "registersymbol("..newRegSymbols..")")
    script = PreSubScript(script,"->>newCode", AAcode)
    end

    -- SECTION 3
    function TrainerShow(nameTrainer, processName, frmWidth, frmHeigth, initFunction)
    frmTrainerWidth = frmWidth
    frmTrainerHeigth = frmHeigth
    local aalist = getAutoAttachList()
    stringlist_add(aalist, processName);
    Trainer_FormCreate(nameTrainer)
    _InitFunction = initFunction
    end

    --[[
    function Initialize()
    bufScript = BeginGenerateAA("allocMem", "2048")
    bufScript = GenerateAAWithSignature(bufScript, "InfHealth1", "d9xxxxxxxxxx8bxxe8xxxxxxxx2bxx8bxxxx33xx2bxx83xxxx7dxx8axxxxxx84", "+X-C-W", 0, "mov [ebx+00000758],(float)100", true)
    bufScript = GenerateAAWithSignature(bufScript, "InfHealth2", "d9xxxxxxxxxx8bxxe8xxxxxxxx2bxx8bxxxx33xx2bxx83xxxx7dxx8axxxxxx84", "+X-C-W", 0, "mov [ebx+00000758],(float)100", true)
    bufScript = GenerateAAWithSignature(bufScript, "InfHealth3", "d9xxxxxxxxxx8bxxe8xxxxxxxx2bxx8bxxxx33xx2bxx83xxxx7dxx8axxxxxx84", "+X-C-W", 0, "mov [ebx+00000758],(float)100", true)
    bufScript = GenerateAAWithSignature(bufScript, "InfHealth4", "d9xxxxxxxxxx8bxxe8xxxxxxxx2bxx8bxxxx33xx2bxx83xxxx7dxx8axxxxxx84", "+X-C-W", 0, "mov [ebx+00000758],(float)100", true)
    bufScript = GenerateAAWithSignature(bufScript, "InfHealth5", "d9xxxxxxxxxx8bxxe8xxxxxxxx2bxx8bxxxx33xx2bxx83xxxx7dxx8axxxxxx84", "+X-C-W", 0, "mov [ebx+00000758],(float)100", true)
    bufScript = GenerateAAWithSignature(bufScript, "InfHealth6", "d9xxxxxxxxxx8bxxe8xxxxxxxx2bxx8bxxxx33xx2bxx83xxxx7dxx8axxxxxx84", "+X-C-W", 0, "mov [ebx+00000758],(float)100", true)
    bufScript = GenerateAAWithSignature(bufScript, "InfHealth7", "d9xxxxxxxxxx8bxxe8xxxxxxxx2bxx8bxxxx33xx2bxx83xxxx7dxx8axxxxxx84", "+X-C-W", 0, "mov [ebx+00000758],(float)100", true)
    bufScript = GenerateAAWithSignature(bufScript, "InfHealth8", "d9xxxxxxxxxx8bxxe8xxxxxxxx2bxx8bxxxx33xx2bxx83xxxx7dxx8axxxxxx84", "+X-C-W", 0, "mov [ebx+00000758],(float)100", true)
    bufScript = GenerateAAWithSignature(bufScript, "InfHealth9", "d9xxxxxxxxxx8bxxe8xxxxxxxx2bxx8bxxxx33xx2bxx83xxxx7dxx8axxxxxx84", "+X-C-W", 0, "mov [ebx+00000758],(float)100", true)
    EndGenerateAA(bufScript)
    end


    TrainerShow("F.E.A.R.XP Ttainer +9, v1.0, {MasterGH}", "FEARXP.exe", 290, 180, Initialize)]]--
    -- Version 1.1

  21. Есть скрипт. Надо тупо тормознуть таймер (db 90 90 90) где его записать в скрипте?

    Нопить надо что-то другое, а не что-то в скрипте.

    Самый простой способ тормознуть таймер это писать постоянно значение в адрес секунд.

    И ещё вопрос. Как сделать так, чтобы по нажатии хоткея добавить иное число при этом его не морозить. Например дал себе 100 патронов и при выстреле 99 далее 98 итд. Если можно, то на этом же скрипте.

    Вижу множество способов. Один из них следующий.

    1) В коде игры найти инструкцию которая работает со всеми патронами для всего оружия.

    2) Создаёшь первый АА скрипт (активирующий). Сделать инъекцию в инструкцию на сохранение текущего адреса патронов. А также дописываешь код записи по этому адресу для потока.

    3) Создаёшь второй АА скрипт после активации первого (иначе будет ошибка) в котором под [ENABLE] записывается выполнение потока.

    4) Потом устанавливаешь хоткеии.

    Один хот-кей на активирующий скрипт. Его нужно активировать один раз в начале игры.

    Другой хот-кей на второй АА скрипт.

    Активирующий:

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

    label(pAmmo)

    label(threadmem)
    registersymbol(threadmem)


    newmem:
    push eax
    lea eax,[esi+79]
    mov [pAmmo],eax
    pop eax
    originalcode:
    mov al,[esi+79]
    test al,al
    exit:
    jmp returnhere

    threadmem:
    mov eax, [pAmmo]
    mov [eax],#99
    ret

    pAmmo:
    dd 0

    005A5A04:
    jmp newmem
    returnhere:

    [DISABLE]
    005A5A04:
    mov al,[esi+79]
    test al,al
    //Alt: db 8A 46 79 84 C0

    dealloc(newmem)

    Второй скрипт:

    [ENABLE]
    createthread(threadmem)
    [DIASBLE]

    Может быть я где-то ошибся, так что надо проверять.

  22. Разработки будущего

    В этом конкретном примере рассмотрю формирование трейнера для игры Dark Sector.

    45 строк против 175 строк, а самое главное более понятнее. АА скрипты для Dark Sector я плохо написал. А вот на LUA гораздо лучше на мой взгляд.

    Если читов будет гораздо больше, то эффект будет ещё сильнее.


    require("TrainerGen")
    function Initialize()
    bufScript = BeginGenerateAA("allocMem", "2048")
    AllocVariableRegistersymbols({ {"pId", 4}, {"pRES", 4} })

    bufScript = GenerateAAWithSignature(bufScript, "getPtrHeroID", "83xxxxxxxxxxxx0fxxxxxxxxxx8dxxxxxxxx8dxxxxxxe8xxxxxxxx80", "+X-C-W", 0, "mov [pId],edx", true)
    bufScript = GenerateAAWithSignature(bufScript, "getPtrHeroRes", "d9xxxxxxxxxx8bxxe8xxxxxxxx2bxx8bxxxx33xx2bxx83xxxx7dxx8axxxxxx84", "+X-C-W", 0, "mov [pRES],eax", true)

    ExtraCreateCheat("Health", bufScript, "getPtrHeroID",[[
    mov [edx+468],#100000
    mov [edx+464],#100000
    ]])

    ExtraCreateCheat("Money", bufScript, "getPtrHeroRes",[[
    mov eax,[eax]
    mov [eax+1d4],#1000000
    ]])

    HideCheats({"getPtrHeroID", "getPtrHeroRes"})

    bufScript = GenerateAAWithSignature(bufScript, "MaxAmmo", "8bxxxxxxxxxxxx74xxxxxx8dxxxxxxxxxxbfxxxxxxxx8bxx85xx74xx83xxxx74", "+X-C-W", 0, [[
    pushf
    push eax
    mov eax,[pRES]
    or eax,eax
    jz short no_MaxAmmo

    cmp ecx,[eax]
    jne short no_MaxAmmo
    mov [ecx+ebp*8+00000394],#99999

    no_MaxAmmo:
    pop eax
    popf
    mov ebx,[ecx+ebp*8+394]
    ]], false)

    bufScript = GenerateAAWithSignature(bufScript, "NoReload", "8bxx8bxxxxxxxxxx8dxxxxxxxx8bxxbbxxxxxxxxffxx8bxx8bxxe8xxxxxxxx84xx75xx83", "+X-C-W", 0, [[
    mov eax,[eax]
    mov byte [eax+3e8],#30
    ]], true)

    EndGenerateAA(bufScript)
    end

    TrainerShow("Dark Sector Ttainer +4, v1.0, {MasterGH}", "FEARXP.exe", 290, 180, Initialize)

    Так же в более далёком будущем сделать автоматическое исправление регистров и смещений, если в игре с патчем они будут разные. Например, инструкция в которой будет внедрение будет не mov [ecx+ebp*8+00000394],#99999, а mov [ecx+ebp*7+00000344],#99999. В этом случае будет автоматической исправления первой инструкции на вторую.

    Можно увидеть новую функцию пока не реализованную


    mov [edx+468],#100000
    mov [edx+464],#100000
    ]])
    	ExtraCreateCheat("Health", bufScript, "getPtrHeroID",[[

    Здесь новый принцип. ExtraCreateCheat добавляет каскад безусловных прыгов в то место кода, где была запись поинтера на структуру. Каскад позволит записывать внутрь структуры данные забив прыг нопами. В примере выше нет каскадов, а всего лишь создаётся по одному прыгу для двух поинтеров. Вот один из них

    Вырезка из АА скрипта:


    mov [_pId],edx

    _cheatHealth:
    jmp short _Aoriginalcode
    mov [edx+468],#100000
    mov [edx+464],#100000
    _newmem1: 

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

    Обновлено...

    Всё-таки не пойдут так дела. Смещения от поинтера могут смещаться в играх с новыми патчами. Поэтому надо привязываться к инструкциями работающими со смещениями структуры, а не к инструкциям которые работают с поинтерами. Так что всё что я выше написал не берите в голову. Для игры нужно написать новые "правильные" АА-скрипты. Функция ExtraCreateCheat не потребуется, а остальное всё актуально...


    function Initialize()
    bufScript = BeginGenerateAA("allocMem", "2048")
    AllocVariableRegistersymbols({ {"pId", 4}, {"pRES", 4} })

    bufScript = GenerateAAWithSignature(bufScript, "getPtrHeroID", "83xxxxxxxxxxxx0fxxxxxxxxxx8dxxxxxxxx8dxxxxxxe8xxxxxxxx80", "+X-C-W", 0, "mov [pId],edx", true)
    bufScript = GenerateAAWithSignature(bufScript, "getPtrHeroRes", "d9xxxxxxxxxx8bxxe8xxxxxxxx2bxx8bxxxx33xx2bxx83xxxx7dxx8axxxxxx84", "+X-C-W", 0, "mov [pRES],eax", true)

    -- здесь добваить GenerateAAWithSignature с сравнениями с поинтерами для читов здоровья и возможно денег, если на деньги не будет инструкции типа А

    HideCheats({"getPtrHeroID", "getPtrHeroRes"})

    bufScript = GenerateAAWithSignature(bufScript, "MaxAmmo", "8bxxxxxxxxxxxx74xxxxxx8dxxxxxxxxxxbfxxxxxxxx8bxx85xx74xx83xxxx74", "+X-C-W", 0, [[
    pushf
    push eax
    mov eax,[pRES]
    or eax,eax
    jz short no_MaxAmmo

    cmp ecx,[eax]
    jne short no_MaxAmmo
    mov [ecx+ebp*8+00000394],#99999

    no_MaxAmmo:
    pop eax
    popf
    mov ebx,[ecx+ebp*8+394]
    ]], false)

    bufScript = GenerateAAWithSignature(bufScript, "NoReload", "8bxx8bxxxxxxxxxx8dxxxxxxxx8bxxbbxxxxxxxxffxx8bxx8bxxe8xxxxxxxx84xx75xx83", "+X-C-W", 0, [[
    mov eax,[eax]
    mov byte [eax+3e8],#30
    ]], true)

    EndGenerateAA(bufScript)
    end

    TrainerShow("Dark Sector Ttainer +4, v1.0, {MasterGH}", "FEARXP.exe", 290, 180, Initialize)
    require("TrainerGen")

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

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

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