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

MasterGH

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

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

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

    129

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

  1. Новая версия модуля TrainerGen.lua: TrainerGen.rar

    Позволяет формировать трейнер вида:

    post-3-1307856932,13_thumb.png

    По примеру разметки формата .CETRAINER:

    <?xml version="1.0"?>
    <CheatTable CheatEngineTableVersion="11">
    <CheatEntries/>
    <UserdefinedSymbols/>
    <LuaScript>
    require("TrainerGen")
    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)</LuaScript>
    </CheatTable>

    Основные пользовательские функции:

    1) TrainerShow(nameTrainer, processName, frmWidth, frmHeigth, initFunction)

    2)

    BeginGenerateAA(newMemDescription, sizeMem)

    -----GenerateAA(aggregateMem, cheatName, address, newCode, stateOriginalCode)

    -----GenerateAAWithSignature(aggregateMem, cheatName, signature, typeMem, signatureOffset, newCode, stateOriginalCode )

    -----AddRegistersymbols(aggregateMem, tableNewSymbols)

    EndGenerateAA(aggregateMem)

    3)

    FillnopsInstruction_AndAddInCETable(cheatName, address)

    FillnopsInstructionWithSignature_AndAddInCETable(cheatName, signature, typeMem, signatreOffset)

    4) GroupAA(nameGRcheat, tableCheats)

    5) Функция для быстрых тестов из консоли LUA:

    GenerateAAscriptPageMem_AndAddInCETable( cheatName, address, injectInstruction, originalcode )

    -----

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

  2. Все языки программирования, которые работают с API Windows могут помочь создать такой же трейнер и даже лучше.

    А каким образом и что "обозначить" ты узнаешь, если долго и упорно прочитаешь материалы по языку программирования под Windows. Надеюсь я ответил на твой вопрос.

  3. Вот пример

    post-3-1307612378,68_thumb.png

    Исполняемый файл игры должен быть назван как FEARXP.exe игра (F.E.A.R. Extra Point). Если он так не назван, то назвать.

    AAgen.lua поместить в директорию с Cheat Engine 6.1

    Сначала запустить и начать игру.

    Затем свернуть игру и дважды кликнуть по F.E.A.R. trainer.CETRAINER

    Код трейнера:

    require("AAgen")
    function Initialize()
    bufScript = BeginGenerateAAscriptAggregateMem("allocMem", "2048")

    bufScript = GenerateAAscriptAggregateMemWithSignature(bufScript, "InfHealth", "d9xxxxxxxxxx8bxxe8xxxxxxxx2bxx8bxxxx33xx2bxx83xxxx7dxx8axxxxxx84", "+X+C-W", 0, "mov [ebx+00000758],(float)100",true)

    bufScript = EndGenerateAAscriptAggregateMem(bufScript)

    autoAssemble(bufScript)
    end

    AAgenINIT("F.E.A.R.XP Ttainer +1, v1.0, {MasterGH}", " FEARXP.exe ", Initialize)

    У Xipho в статье в игре структура героя другая. У него надо mov [ebx+000006E0],(float)100. Сигнатура у меня и у него одинаковая. Когда модуль AAgen.lua будет усовершенствован - новые функции генерации АА-скрипта по дизассемблерному коду, то даже этот трейнер будет работать. Надо будет только аттач к процессу игры делать не по имени исполняемого файла, а по сигнатурам или иным характеристикам.

    AAgen.rar

    F.E.A.R. trainer.rar

  4. Примеры скриптов с возможными ошибками пользователей.

    1. Случай.

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

    Ниже скрипт постоянное, здоровье возвращает герою здоровье.


    [ENABLE]
    alloc(newmem,256)
    label(back)
    label(code)

    019FAB50:
    jmp newmem
    back:

    newmem:
    push eax
    cmp byte ptr [ecx],a0
    jne code
    mov eax,[ecx+1a]
    mov [ecx+16],eax

    code:
    pop eax
    fld dword ptr [ecx+16]
    ret
    int 3
    jmp back

    [DISABLE]
    dealloc(newmem)
    019FAB50:
    fld dword ptr [ecx+16]
    ret
    int 3

    Скорее всего, правильнее написать так (без учёта сохранения/восстановления регистра флагов):


    alloc(newmem,256)
    label(code)

    newmem:
    cmp byte [ecx],a0
    jne code
    fld dword [ecx+1a]
    ret
    code:
    fld dword [ecx+16]
    ret


    019FAB50:
    jmp newmem


    [DISABLE]

    019FAB50:
    fld dword ptr [ecx+16]
    ret
    int 3

    dealloc(newmem)
    [ENABLE]

    С восстановлением флагов было бы так:


    alloc(newmem,256)
    label(code)

    newmem:
    pushfd
    cmp byte [ecx],a0
    jne code
    fld dword [ecx+1a]
    popfd
    ret
    code:
    fld dword [ecx+16]
    popfd
    ret


    019FAB50:
    jmp newmem


    [DISABLE]

    019FAB50:
    fld dword ptr [ecx+16]
    ret
    int 3

    dealloc(newmem)
    [ENABLE]

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


    [ENABLE]
    alloc(newmem,256)
    label(back)
    label(code)

    019FAB50:
    jmp newmem
    back:

    newmem:
    push eax
    cmp byte ptr [ecx],a0
    jne code
    mov eax,[ecx+1a]
    mov [ecx+16],eax

    code:
    pop eax
    fld dword ptr [ecx+16]
    ret
    int 3
    jmp back

    [DISABLE]
    dealloc(newmem)
    019FAB50:
    fld dword ptr [ecx+16]
    ret
    int 3

    Скорее всего, правильнее написать так (без учёта сохранения/восстановления регистра флагов):

    [ENABLE]
    alloc(newmem,256)
    label(code)

    newmem:
    cmp byte [ecx],a0
    jne code
    fld dword [ecx+1a]
    ret
    code:
    fld dword [ecx+16]
    ret


    019FAB50:
    jmp newmem


    [DISABLE]

    019FAB50:
    fld dword ptr [ecx+16]
    ret
    int 3

    dealloc(newmem)

  6. Библиотека ещё не доведена до ума, но кое-что она умеет делать.

    post-3-1307521965,03_thumb.png

    Для того чтобы создалось это окно и читы работали по горячим клавишам со звуковым сообщением надо написать код LUA в главной таблице CE (это всего лишь пример):

    require("TrainerGen")

    function Initialize()
    AddCheatInCETableFillnopsInstructionWithSignature("NoRecoilHand", "e8xxxxxxxx8bxxxxxx83xxxx33xx80xxxxxx75xx8bxxxxxxf7", 0)
    bufScript = BeginGenerateAAscriptAggregateMem("allocMem", "2048")
    bufScript = GenerateAAscriptAggregateMemWithSignature(bufScript, "NoRecoilWalk", "d9xxd9xxxxd9xxxxd9xxxxxxxxxxdexxdfxxf6xxxx75xxd9xxxxxxxxxxd9", 8, "fstp st\n fldz", true )
    bufScript = GenerateAAscriptAggregateMemWithSignature(bufScript, "NoRecoilShot", "d9xxxxxxxxxx75xxd9xxxxxxxxxxd8xxxxxxd8xxdfxxf6xxxx7axxd9", 0, "fstp st\n fldz", true )
    bufScript = GenerateAAscriptAggregateMemWithSignature(bufScript, "NoReload", "83xxxxxxxxxxxxxx74xxf6xxxxxx74xx83xxxx89xxxxxxxxxx39xxxx7dxxf7", 0, "mov [ebp+eax*4+00000334],#100", true )
    bufScript = EndGenerateAAscriptAggregateMem(bufScript)
    autoAssemble(bufScript)
    GroupAA("Complex better weapons", {"NoRecoilHand", "NoRecoilWalk", "NoRecoilShot", "NoReload"} )
    end

    AAgenINIT("CoD4 Ttainer +1, v1.0, {MasterGH}", "iw3sp.exe", Initialize)

    Далее сохранить этот код примера как .CETRAINER.

    Запустить двойным кликом. Форма CE показываться не будет.

    Запустить игру и дождаться когда трейнер будет готов к работе.

    Активировать чит нажатием горячих клавиш для группы "Complex better weapons"

    Код TrainerGen.lua (который надо поместить в папку с трейнерами типа .CETRAINER или файлами типа .CT; в коде есть мусор в комментариях, если мешает, то убрать самостоятельно)


    -- Если скрипт с таким именем уже существует, то он будет перезаписан
    function GenerateAAscriptCreatePageMem( 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

    end
    ----^^^^^^^^^

    -- Функции часто используемые другими функциями
    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
    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 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
    function GetSignatureOfCode(address)
    --[[
    Переписать из кода Дельфи

    procedure TfrmAutoInject.Codeinjection1Click(Sender: TObject);
    function inttostr(i:int64):string;
    begin
    if i=0 then result:='' else result:=sysutils.IntToStr(i);
    end;


    var address: string;
    addressdw: dword;
    originalcode: array of string;
    originalbytes: array of byte;
    codesize: integer;
    a,b: dword;
    x: string;
    i,j,k: integer;
    prev_usesymbols: boolean;
    injectnr: integer;

    enablepos: integer;
    disablepos: integer;
    enablecode: tstringlist;
    disablecode: tstringlist;
    simbol:boolean;
    bofset:byte;
    provbyte:string;
    begin
    {$ifndef standalonetrainerwithassembler}
    CheatTablecompliantcodee1.Click; // обрамление
    simbol:=symhandler.showmodules; //запоминаем "нужно ли показывать модули"
    symhandler.showmodules:=true; //в любом случае показываем модули в метках
    a:=memorybrowser.disassemblerview.SelectedAddress;

    address:=inttohex(a,8);
    { if inputquery('Code inject template','On what address do you want the jump?',address) then
    begin}
    try
    a:=strtoint('+address);
    except

    a:=symhandler.getaddressfromname(address);

    end;

    b:=a;

    injectnr:=0;
    for i:=0 to assemblescreen.Lines.Count-1 do
    begin
    j:=pos('alloc(newmem',lowercase(assemblescreen.lines[i]));
    if j<>0 then
    begin
    x:=copy(assemblescreen.Lines[i],j+12,length(assemblescreen.Lines[i]));
    x:=copy(x,1,pos(',',x)-1);
    try
    k:=strtoint(x);
    if injectnr<=k then
    injectnr:=k+1;
    except
    inc(injectnr);
    end;
    end;
    end;


    //disassemble the old code
    setlength(originalcode,0);
    codesize:=0;

    while codesize<5 do
    begin
    setlength(originalcode,length(originalcode)+1);
    originalcode[length(originalcode)-1]:=disassemble(a,x);
    i:=posex('-',originalcode[length(originalcode)-1]);
    i:=posex('-',originalcode[length(originalcode)-1],i+1);
    originalcode[length(originalcode)-1]:=copy(originalcode[length(originalcode)-1],i+2,length(originalcode[length(originalcode)-1]));
    codesize:=a-b;
    end;

    setlength(originalbytes,codesize);
    ReadProcessMemory(processhandle, pointer(B), @originalbytes[0], codesize, a);

    enablecode:=tstringlist.Create;
    disablecode:=tstringlist.Create;
    try
    with enablecode do
    begin

    // Необходимое сканирование при активации, когда адрес сместился
    //aobscan(_address,d8xxxxxxdfxxf6xxxx0fxxxxxxxxxx8bxxe8xxxxxxxx8bxxe8xxxxxxxxd9xxd8)
    provbyte:=getbytes(strtoint('+address));
    add(' aobscan(_faddress,'+provbyte+')');
    add(' alloc(_newmem'+inttostr(injectnr)+',2048)');
    add(' label(_returnhere'+inttostr(injectnr)+')');
    add(' label(_originalcode'+inttostr(injectnr)+')');
    add('');
    add('_newmem'+inttostr(injectnr)+':');
    // add(' mov [],eax //mov eax,');
    add('');
    add('_originalcode'+inttostr(injectnr)+':');
    for i:=0 to length(originalcode)-1 do
    add(' '+originalcode[i]);
    add(' jmp _returnhere'+inttostr(injectnr)+'');

    add('');
    add('_faddress: // '+address+' = '+symhandler.getNameFromAddress(strtoint('+address)));
    // add(symhandler.getnamefromaddress(strtoint('+address))+':');//прыжок после выделения памяти
    // add(address+':');
    add(' jmp _newmem'+inttostr(injectnr)+'');
    bofset:=5;
    while codesize>5 do
    begin
    add(' nop');
    dec(codesize);
    inc(bofset); // для посторения проверочных байта отмены
    end;
    add('_returnhere'+inttostr(injectnr)+':');
    end;

    delete(provbyte,1,bofset*2); // удаляем то чего не надо искать
    dec(bofset,5);
    for I := 1 to bofset do
    provbyte:='90'+provbyte;

    with disablecode do
    begin
    add(' aobscan(_faddress,'+provbyte+')');
    add('');
    // add(address+':');
    add('_faddress-5:');
    for i:=0 to length(originalcode)-1 do
    add(' '+originalcode[i]);
    add('');
    add(' dealloc(_newmem'+inttostr(injectnr)+')');
    x:='db';
    for i:=0 to length(originalbytes)-1 do
    x:=x+' '+inttohex(originalbytes[i],2);
    add('//Alt: '+x);
    end;

    getenableanddisablepos(assemblescreen.lines,enablepos,disablepos);
    //skip first comment(s)
    if enablepos>=0 then
    begin
    while enablepos<assemblescreen.lines.Count-1 do
    begin
    if pos('//',trim(assemblescreen.Lines[enablepos+1]))=1 then inc(enablepos) else break;
    end;
    end;

    for i:=enablecode.Count-1 downto 0 do
    assemblescreen.Lines.Insert(enablepos+1,enablecode[i]);

    getenableanddisablepos(assemblescreen.lines,enablepos,disablepos);
    //skip first comment(s)
    if disablepos>=0 then
    begin
    while disablepos<assemblescreen.lines.Count-1 do
    begin
    if pos('//',trim(assemblescreen.Lines[disablepos+1]))=1 then inc(enablepos) else break;
    inc(disablepos);
    end;
    //only if there actually is a disable section place this code
    for i:=disablecode.Count-1 downto 0 do
    assemblescreen.Lines.Insert(disablepos+1,disablecode[i]);
    end;
    finally
    enablecode.free;
    disablecode.Free;
    end;
    symhandler.showmodules:=simbol;
    //

    {$endif}
    end;
    ]]--

    -- Количество попыток поиска сигнатуры, на тот случай если поиск окажеться долгим
    -- может вмешаться пользователь остановить или продолжить поиск
    local numberOfAttemptsForShowPermission = 1000
    local CountOfnumberOfAttemptsForShowPermission = 0

    local offsetSignature = 0
    local lengthSignature = 0
    local signature = ""

    -- Уникальная сигнатура подбирается по первым байтам машинных инструкций от начала функции до её конца
    -- Стремление к тому чтобы сигнатура была меньших размеров и была уникальна по правилу сканирования "+X-C-W"

    --1. Получаем строку байт в функции
    -- 1.2 Ищем адрес1 начала функции
    -- 1.3 Ищем адрес2 конеца функции
    -- Если адреса определить невозможно, то выводится сообщение об ошибке
    -- 1.4 Дизассемблируя формируем сигнатуру от адреса1 до адреса2
    -- 1.4.1 Формирование происходит по первым байтам одной инструкции в том случае
    -- если размер инструкции болше 3 байт
    -- заполнение не рабочих байт отмечается как "xx"
    -- В итоге получаем длинную сигнатуру - строку байт в функции

    repeat
    --2. Создаются новый настройки поиска сигнатуры
    -- 2.1 Поиск сигнатуры ведётся по её длине от 6 байт с места адреса, когда определены более трёх промежутков "xx" до длины сигнатуры
    -- если сигнатура не находиться то она расползается в длину сначала вниз по 3 промежутка "xx", а затем вверх увеличивая увеличивая offsetSignature
    -- если вся длина сигнатуры была просканирована и не нашлось уникальной, то появляеться сообщение об ошибке.
    -- если сканирование очень затягивается больше 10 секунд, то появляеться сообщение "хочет ли пользователь дальше продолжать сканирование"
    -- ....

    -- Непосредственный поиск сигнатуры
    local list = AOBScan(signature, "+X-C-W")
    if ((results == nil) or (strings_getCount(list)>1) and stringlist_getString(results, 0)~=address) then
    break -- успешный выход из цикла, уникальная сигнатура найдена
    end

    -- В противном случае засчитывается неудачаная попытка поиска сигнатуры
    CountOfnumberOfAttemptsForShowPermission = CountOfnumberOfAttemptsForShowPermission + 1
    if(CountOfnumberOfAttemptsForShowPermission > numberOfAttemptsForShowPermission) then
    if (messageDialog()~="OK") then
    showMessage("Поиск сигнатуры был остановлен пользователем")
    --messageDialog("Ошибка. Не найден адрес внедрения.\n\rТрейнер будет закрыт!",1, 2)
    return nil
    end
    end
    until true

    return signature


    --[[ function getbytes():string;

    adr:dword -- входящий адрес

    var i,j,len,count:byte; frwrdaddr:dword; stlist:TstringList; s,s0,s1,intsr:string;
    begin





    frwrdaddr:=adr;
    repeat
    stlist.Add(disassemble(frwrdaddr)); // заполнили список ассемблерных инструкций типа '0061c2d3 - e8 61 c0 ff ff - call 00618339'
    // frwrdaddr:=previousopcode(frwrdaddr)-1;
    until frwrdaddr>=adr+120;

    //После этого берём первые байты, если их количество не меньше 3 на опкод, остальные помечаем как xx

    for i := 0 to stlist.Count-1 do
    begin // Получаем:
    s:=stlist.Strings[i];
    s0:=copy(s,1,pos(' - ',s)); // адрес
    delete(s,1,pos(' - ',s)+2);
    s1:=copy(s,1,pos(' - ',s)); // байты
    delete(s,1,pos(' - ',s)+2); // инструкция
    intsr:=s;

    //Если в строке байт находится больше трёх байт
    len:=length(s1);
    count:=(len div 3); //количество байт
    s:='';
    if (count>1)and(pos('push',intsr)=0) then
    begin
    s1:=copy(s1,1,3); // копируеме первый байт "FA "
    for j := 2 to count
    do s:=s+'xx '; // остальные затераем "хх хх хх хх "

    s1:=s1+s; //s1:= "FA хх хх хх хх "
    end
    else // если байт меньше трёх то заливаем всё как "хх "
    begin
    for j := 1 to count
    do s:=s+'xx ';
    s1:=s; //s1: = "xx хх хх "
    end;
    result:=result+s1; //=)
    end;

    delete(result,(32*3),length(result)); //режем первые 32 байта

    for I := 32 downto 1 do
    delete(result,i*3,1);

    while 'xx'=copy(result,length(result)-1,2) do
    delete(result,length(result)-1,2);

    stlist.Destroy; ]]--

    end
    function BeginGetLUACheatCode(aggregateMem, cheatName, signatre, newCode, stateOriginalCode )
    --[[
    ]]--
    end
    function ENDGetLUACheatCode(aggregateMem, cheatName, signatre, newCode, stateOriginalCode )
    --[[
    ]]--
    end
    function GetLUACheatCode(aggregateMem, cheatName, signatre, newCode, stateOriginalCode )
    --[[
    ]]--
    end
    ----^^^^^^^^^

    -- Функции окоторые требуются для главной работы
    function BeginGenerateAAscriptAggregateMem(newMemDescription, sizeMem) -- return bufferString
    return [[
    alloc(]]..newMemDescription..","..sizeMem..[[)
    registersymbol(]]..newMemDescription..[[)
    ->>label]]..newMemDescription..[[:

    ->>newCode
    ->>adressessInjected
    ]]
    end
    function EndGenerateAAscriptAggregateMem(aggregateMem) -- return bufferString
    local endScript = string.gsub(aggregateMem, "->>label", "")
    endScript = string.gsub(endScript, "->>newCode", "")
    endScript = string.gsub(endScript, "->>adressessInjected", "")
    return endScript
    end
    function GenerateAAscriptAggregateMem(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 ByteScan(signature) -- return address
    local results = AOBScan(signature, "+X-C-W")
    if (results == nil) then
    messageDialog("Ошибка. Не найден адрес внедрения.\n\rТрейнер будет закрыт!",1, 2)
    closeCE()
    return
    end

    local address = stringlist_getString(results, 0)
    return address
    end
    function GenerateAAscriptAggregateMemWithSignature(aggregateMem, cheatName, signature, signatureOffset, newCode, stateOriginalCode )
    local workAddress = ByteScan(signature)
    if (signatureOffset ~=0) then
    workAddress = string.format("%x", ("0x"..workAddress) + signatureOffset)
    end
    return GenerateAAscriptAggregateMem(aggregateMem, cheatName, workAddress, newCode, stateOriginalCode)
    end
    function AddCheatInCETableFillnopsInstruction(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 AddCheatInCETableFillnopsInstructionWithSignature(cheatName, signature, signatreOffset)
    local workAddress = ByteScan(signature)
    workAddress = string.format("%x", ("0x"..workAddress) + signatreOffset)
    AddCheatInCETableFillnopsInstruction(cheatName, workAddress)
    end
    ----^^^^^^^^^

    ---------------------------------------------------------
    local frmUserTrainer = nil -- форма конструируемого трейнера
    local messageLabel = nil
    local _InitFunction -- указатель на пользовательскую функцию инициализации читов
    local attach = false -- подключен ли процесс

    -- Cтрока информации в трейнере
    local function SendMessageFrmTrainer(message)
    control_setCaption(messageLabel, message)
    end
    -- Обработчик закрытия главной формы трейнера
    local function FormClose(sender)
    closeCE()
    return caHide
    end
    -- Создание неготовой формы трейнера
    local function CreateFormTrainer(nameTrainer)
    frmUserTrainer = createForm(true)
    control_setCaption(frmUserTrainer, nameTrainer)
    control_setSize(frmUserTrainer, 400, 200)
    form_centerScreen(frmUserTrainer)
    form_onClose(frmUserTrainer, FormClose)

    messageLabel = createLabel(frmUserTrainer)
    control_setAlign(messageLabel, alBottom)
    SendMessageFrmTrainer("Трейнер НЕ готов к работе")
    end

    -------------------------------------
    local ObjectHotKeys = {}
    local countObjectHotKeys = 0 -- countObjectHotKeys равное также кол-ву записей в главной таблице
    local adrList = nil
    local baseHotKey = "CTRL"
    -- Функция группировки АА-скриптов в один (для того чтобы хоткей вешался на один сркипт вместо нескольких)
    function GroupAA(nameGRcheat, cheats)
    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(cheats)
    local description = ""
    for i = 1,countObjectHotKeys do
    local te = addresslist_getMemoryRecord(adrList, i-1)
    description = memoryrecord_getDescription(te)
    for j=1,zisetable do
    if (cheats[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

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

    mainGRScript = string.gsub(mainGRScript, "-->>marker1", "")
    mainGRScript = string.gsub(mainGRScript, "-->>marker2", "")
    SetScriptInEntryCETable(nameGRcheat,mainGRScript)
    end


    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 CreateControlsForTrainer()
    --сделать формирование данных
    -- todo: сделать слотов больше 9
    if (adrList == nil) then
    adrList = getAddressList()
    end
    countObjectHotKeys = addresslist_getCount(adrList)
    if (countObjectHotKeys < 1 or countObjectHotKeys > 9) then
    showMessage("В этой реализации программы читов не может быть меньше 1 или больше 9. Трейнер будет закрыт")
    FormClose(nil)
    return nil
    end


    for i = 1,countObjectHotKeys do
    local te = addresslist_getMemoryRecord(adrList, i-1)
    local description = memoryrecord_getDescription(te)
    --[[
    GenericHotkey Class : (Inheritance: Object)
    createHotkey(function, key, ...) : returns an initialized GenericHotkey class object. Maximum of 5 keys
    generichotkey_setKeys(hotkey, key, ....)
    generichotkey_onHotkey(hotkey, function)
    ]]--
    ObjectHotKeys[i] = createHotkey(arrayFunction[i], VK_CONTROL, VK_0 + i) --string.format("%s",i)
    generichotkey_setKeys(ObjectHotKeys[i], VK_CONTROL, VK_0 + i)
    generichotkey_onHotkey(ObjectHotKeys[i], arrayFunction[i])

    CheatLbl = createLabel(frmUserTrainer)
    control_setAlign(CheatLbl, alTop)
    local stringHotKey = baseHotKey.."+"..i
    control_setCaption(CheatLbl, i..") "..description..": "..stringHotKey)
    end
    CheatLbl = createLabel(frmUserTrainer)
    control_setAlign(CheatLbl, alTop)
    control_setCaption(CheatLbl, "Cheats:")

    SendMessageFrmTrainer("Трейнер готов к работе")
    end

    -- Событие открытия процесса
    function onOpenProcess(processid)
    --print("вызов onOpenProcess")
    if (attach) then
    return
    end
    attach = true
    --openProcess(processid)
    _InitFunction()
    CreateControlsForTrainer()
    end

    -- Главная функция иницилазации
    function AAgenINIT(nameTrainer, processName, InitFunction)
    -- todo: раскомментировать строку ниже когда все функции будут отлажены
    --hideAllCEWindows()
    aalist = getAutoAttachList()
    stringlist_add(aalist, processName);
    CreateFormTrainer(nameTrainer)
    _InitFunction = InitFunction
    end
    -- Функция создаёт скрипт, который выделит память для отдельного чита. Сам скрипт добавиться в главную таблицу

    Хочу прокомментировать недостатки.

    Это версия не для 64-разрядных приложений,а только для 32-разрядных.

    Пока требуется вручную забивать сигнатуру. Я же пользовался CE 5.6 русская версия с нашего сайта для генерации сигнатур из автоаассемблера.

    Групп читов можно сделать только 9,а в группах же может быть любое количество читов.

    Дизайн трейнера пока хромает.

    Возможны какие-то ошибки...

    Достоинства:

    1) Читы можно объеденять в группы как было показано в примере выше, они все могут активироваться по одной горячей клавише.

    2) Вся нудная разметка Автоассемблерного скрипта скрывается от вас.

    3) Читы тела которых должны быть в выделенной памяти формируются только в одном участке памяти, а не в нескольких при каждом alloc(название метки, размер памяти)

    4) Поиск адреса внедрения по сигнатурам увеличивает шанс работы трейнера с разными патчами игр на 30%-70% чем если бы вы это делали просто по адресам внедрения. Это в какой-то степени избавляет вас от написания трейнеров к новым патчам. Но этот метод внедрения с увеличением шансов работы трейнера ещё далеко не предел... можно повысить и до %60-%80.

    5) Горячие клавиши сами выставляются для слотов от 1 до 9. Конечно, это может быть неудобно, но пока останется так.

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

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

  8. У AOBScan могут быть параметры сканирования (ищите описание).

    Пример функции возвращающей первый найденный адрес сигнатуры в типе областей памяти с защитой "выполнение кода".


    function ByteScan(signature) -- return address
    local results = AOBScan(signature, "+X-C-W")
    if (results == nil) then
    messageDialog("Ошибка. Не найден адрес внедрения.\n\rТрейнер будет закрыт!",1, 2)
    closeCE()
    return
    end

    local address = stringlist_getString(results, 0)
    return address
    end

    Важно отметить, что можно работать с несколькими возвращаемыми адресами, а не только с первым как это было в автоассемблере.

  9. В справке CE 6.0 в разделе Script engine есть такая функция:

    generateAPIHookScript (address, addresstojumpto, addresstogetnewcalladdress OPT) : Generates an auto assembler script which will hook the given address when executed

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

    Этой функцией можно воспользоваться следующим образом (пример Дакрк Байта):


    globalalloc(MyPeekMessageHook,2048)
    globalAlloc(OriginalPeekMessageA,4)
    label(placeyourbphereifyouliketoseetheresults)
    registersymbol(placeyourbphereifyouliketoseetheresults)

    MyPeekMessageHook:
    //do whatever you want in your hook
    //I could just do jmp [OriginalPeekMessageA] if I wanted
    //but this way the parameters are more easily readable for me
    //and lets me mess with the results
    push ebp
    mov ebp,esp

    //ebp=old ebp
    //ebp+4=old return address
    //ebp+8=first parameter
    //ebp+c=second
    //ebp+10=third
    //ebp+14=fourth
    //ebp+18=fifth
    push [ebp+18]
    push [ebp+14]
    push [ebp+10]
    push [ebp+c]
    push [ebp+8]
    call [OriginalPeekMessageA]

    placeyourbphereifyouliketoseetheresults:
    //eax now contains the return value.
    //and this space gives you room to tamper with the results


    pop ebp//restore ebp to what it was
    ret 14 //undo the pushed parameters and return

    ]]
    )

    myhookscript=generateAPIHookScript("PeekMessageA", "MyPeekMessageHook", "OriginalPeekMessageA");

    if (myhookscript~=nil) then
    autoAssemble(myhookscript)
    end
    autoAssemble([[

    Там где вы увидите двойные квадратные скобки - это автоассемблерный код. Измените его как вам потребуется.

    Из примера вы можете видеть, что PeekMessageA перекрывается на MyPeekMessageHook с выполнением OriginalPeekMessageA. Ещё раз обращу внимание, что в данном случае generateAPIHookScript очевидно будет эффективнее работать чем с debug_setBreakpoint(см. тутор2).

    Ещё пример:


    globalalloc(MyMessageBoxHook,2048)
    alloc(message,11)
    alloc(caption,3)
    globalalloc(OriginalMessageBoxA,4)

    message:
    db 'blablablaa',0

    caption:
    db 'XD',0

    MyMessageBoxHook:

    push ebp
    mov ebp,esp


    push #0
    push caption
    push message
    push #0
    call [OriginalMessageBoxA]


    pop ebp
    ret 10


    ]]
    )


    myhookscript=generateAPIHookScript("MessageBoxA", "MyMessageBoxHook", "OriginalMessageBoxA");

    if (myhookscript~=nil) then
    autoAssemble(myhookscript)
    end
    autoAssemble([[ 

  10. Результат, которого мы должны добиться в LUA консоли Cheat Engine следующий:

      1) 0x003f00b8:  08 00 00 00 
    2) 0x003f00bc: 00 00 00 00
    3) 0x003f00c0: 00 00 00 00
    4) 0x003f00c4: 00 00 00 00

    ... (вырезано)

    247) 0x003f0490: 00 00 00 00
    248) 0x003f0494: 00 00 00 00
    249) 0x003f0498: 00 00 00 00
    250) 0x003f049c: 00 00 00 00

    Сделать это можно так (leftaddr замените на свой адрес):

    function  onclickBtn(sender)
    leftaddr = 0x3f00b8
    rigthaddr = leftaddr+1000
    count =1

    repeat
    x1,x2,x3,x4 = readBytes(leftaddr,4)
    s = string.format("%3d) 0x%08x: %02x %02x %02x %02x",count,leftaddr,x1,x2,x3,x4 )
    print(s)
    leftaddr= leftaddr + 4
    count = count +1
    until(leftaddr >=rigthaddr)

    end

    frm = createForm()
    control_setCaption(frm, "Вывод дампа памяти")
    form_centerScreen(frm)
    control_setSize(frm, 270,70)

    btn=createButton(frm)
    control_setCaption(btn, "Вывести дамп")
    control_setPosition(btn,20,10)
    control_setSize(btn, 230,50)
    control_onclick(btn, onclickbtn)

    В этом примере создали форму с кнопкой. При нажатии кнопки в консоли выводится информация.

  11. Требования и информация:

    1) Текущая версия Lua-поддержки для Cheat Engine 6.1 и выше, поэтому если у вас нет версии 6.1, то установите с официального сайта Cheat Engine

    2) Для просмотра и редактирования Luaкода установите: Notepad++ (найдёте в поисковике)

    3) Все поддерживаемые Lua функции, а так же их краткая документация в комментариях находятся в файле "main.lua". Этот файл находится в каталоге с программой Cheat Engine. В справке CE те же описания функций Lua для CE.

    4) "main.lua" загружается и выполняется автоматически при запуске CE. Вы можете редактировать этот файл для загрузки ваших собственных модулей Lua.

    5) "defines.lua" содержит описания определений тех или иных констант

    6) Новые комментарии к Lua функциям вы можете при случае увидеть здесь в SDK а здесь описания

    7) Если так случится, что вы не знаете как работает Lua функция, то ответ можно найти в SDK начав свой путь поиска проблемы с этой страницы.

    Справочное руководство как писать программы на Lua пока ищите в Интернете.

    Напоминаю, что если очень нужно, то последнюю версию CE вы можете скомпилировать из SDK с официального сайта. На нашем форуме есть руководство как это сделать.

    Ниже будет располагается информация из того же main.lua, который у вас уже есть только в лучшем виде для понимания. (пока заниматься этим некогда, тема В РАЗРАБОТКЕ)

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

  13. Всех поздравлю с официальным реализом CE 6.1

    Добавлю, что в течении недели могут быть различные "патчи" для 6.1. После будет начало 6.2. Об этом писал Dark Byte.

    От себя же прокомментирую, что 6.1 финальная версия ещё сыровата. Судя по тому кол-ву багов которое было чуть ли не каждый день отрапортовано разработчику CE их ещё может быть довольно много.

    Все скачиваем и пользуемся.

  14. У тебя получилось сделать Super Jump? И какими методами в трейнми адрес искать? :blink: там же паузы нет

    Ищем адрес координаты X бегая влево или вправо. Затем находим Y рядом с адресом X. На Y ставим бряк на запись... определяем какая инструкция увеличивала Y. Кропотливо ищем "предел увеличения" выраженном в том или ином понятии - например, силы отталкивания (ищем до инструкции которая уменьшает Y). Возможно инструкция которая увеличивает и уменьшает Y одна и таже в этом случае надо исследовать внешние вызовы. Я этот трейнми не ломал, но стоило бы. Возможно игру лучше поставить в оконный режим чтобы спокойно отлаживать при пошаговой отладке. Если выкрою время, то попробую исследовать. У меня какое-то дежавю, я этот трейнми уже где-то видел у нас.

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

  16. Спасибо за ответ.

    Знаешь, просто не понятно, что тебе мешало написать программу на ассемблере по Дельфи коду. Ведь это проблема осталась и никуда не делась... Зато ты для себя выяснил главное, что можно на MASM написать программу написанную на Дельфи. И задать этот вопрос поисковику кстати тоже можно было ;)

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

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

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