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

MasterGH

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

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

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

    129

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

  1. Извиняюсь за тупой вопрос, но как в LUA работать с формами?

    С формой созданной в CE-же, с дефолтным названием UDF1

    Я тоже не знал как это сделать, но посмотрев здесь узнал:

    Создал дефолтную форму UDF1, едит и кнопку. И повесил обработчик на кнопку при клике (код ниже). При клике в лог выводиться текст из едита:


    function CEButton1Click(sender)
    txtBox = component_findComponentByName(UDF1, "CEEdit1")
    textValue = getProperty(txtBox, "Text")
    print(textValue)
    end

    UDF1 в этом случае это объект формы. Если объект формы неизвестен, то нужно использовать перебор форм по индексам от нуля до количества индексов всех форм связанных с Cheat Engine.

    getPropertyList(obj_class) создаёт список публичных свойств, среди которых можно найти свойство Text. Можно и не искать таким образом, а поискать названия свойств в дизайнере компонентов.

  2. Заготовка скрипта для ведения лога данных на функции TranslateMessage.

    Функция TranslateMessage переводит сообщения виртуальных клавиш в символьные сообщения. Символьные сообщения помещаются в очередь сообщений вызывающего потока для прочтения в следующий раз, когда поток вызовет функцию GetMessage или PeekMessage.

    Теория (на практике всю теорию не проверял, только где-то как-то кусками)

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

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


    Скрипт установки условного брейкпоинта на функции TranslateMessage.

    В параметрах сравнения участвует код сообщения "UINT message"
    Если сообщение равно сравниваемому, то отладчик прервётся и в поле лога выведет параметры структуры MSG

    BOOL TranslateMessage(
    const MSG* lpMsg // Указатель на структуру MSG, которая содержит информацию о сообщении извлеченную из очереди сообщений вызывающего потока при помощи использования функции GetMessage или PeekMessage.
    );

    typedef struct {
    HWND hwnd; // Дескриптор окна, оконная процедура которого принимает сообщение.
    UINT message; // Определяет код сообщения. Приложения могут использовать только младшее слово; старшее слово зарезервировано системой.
    WPARAM wParam; // Определяет дополнительную информацию о сообщении. Точное значение зависит от значения члена структуры message.
    LPARAM lParam; // Определяет дополнительную информацию о сообщении. Точное значение зависит от значения члена структуры message.
    DWORD time; // Определяет время, в которое сообщение было помещено в очередь.
    POINT pt; // Устанавливает позицию курсора, в экранных координатах, в момент, когда сообщение было помещено в очередь.
    } MSG, *PMSG;


    Пример использования.

    Пример1. Установка условного брейкпоинта функции TranslateMessage в сравнении с параметром MSG:
    -- Сработает когда пользователь отпустит левую кнопку мышки

    WM_LBUTTONUP = 0x202 (другие коды сообщени ищите в Интернете)
    StartDebug_TranslateMessageCondition_onMSG(WM_LBUTTONUP)

    Пример2. Установика безусловного брейкпоинта с логировнием всех сообщений:

    StartDebug_TranslateMessage()

    Пример3. Если необходимо только прерваться на некоторой функции без сбора параметров:

    StartDebugSomeFunction(functionName)

    Пример4. Если необоходимо остановить отладку, то вызывать:

    StopDebug()
    ]]--

    local mode = 0
    local addressesBreakPoint = {}
    local countAddressesBreakPoint = 0

    function AddBreakPointExecut(addressFunction)
    countAddressesBreakPoint = table.getn(addressesBreakPoint)
    countAddressesBreakPoint = countAddressesBreakPoint + 1
    addressesBreakPoint[countAddressesBreakPoint] = addressFunction
    debug_setBreakpoint(addressFunction, 1, bptExecute)
    end

    function DeleteAllBreakPoint()
    for i=1, countAddressesBreakPoint do
    debug_removeBreakpoint(addressesBreakPoint[i])
    end
    countAddressesBreakPoint = 0
    end

    -- Единая функция обработки сообщений о прерывании
    function debugger_onBreakpoint()

    local withIn = false
    for i=1, countAddressesBreakPoint do
    if (EIP == addressesBreakPoint[i]) then
    withIn = true
    break
    end
    end

    if (not withIn) then
    return 1
    end

    if ( (mode == 1) or (mode == 2) ) then
    local pMSG = readInteger(ESP+0x4)
    local MSG = readInteger(pMSG+0x4)

    if ((mode == 1) and (MSG ~= _iMSGBreak)) then
    return 1
    end

    local s = string.format(" • Call to %s from \"%s\" •\n\r\n>> hWnd = %X\n\r\n>> MSG = %X\n\r\n>> wParam = %X\n\r\n>> lParam = %08X\n\r\n>> Time = %X\n\r\n>> Point = %i x %i\n\r\n", getNameFromAddress(EIP), getNameFromAddress(readInteger(ESP)),
    readInteger(pMSG),
    MSG,
    readInteger(pMSG+0x8),
    readInteger(pMSG+0xC),
    readInteger(pMSG+0x10),
    readInteger(pMSG+0x14), readInteger(pMSG+0x18))

    if (mode == 1) then -- WM_LBUTTONUP
    print(s) -- записываем в лог LuaEngine текст из loglist
    return 0 -- ставим бряк
    else -- в случае если условие не выполнено
    print(s) -- записываем в лог LuaEngine текст из loglist при не выполненом условии
    return 1 -- продолжаем без бряка
    end
    end

    return 0
    end

    function StartDebug_TranslateMessageCondition_onMSG(iMSGBreak)
    DeleteAllBreakPoint()
    mode = 1
    _iMSGBreak = iMSGBreak
    local addressFunction = getAddress("TranslateMessage")
    AddBreakPointExecut(addressFunction)
    print(string.format("Включен режим остановки на фунции TranslateMessage с условием: MSGBreak == %X",iMSGBreak))
    end

    function StartDebug_TranslateMessage()
    DeleteAllBreakPoint()
    mode = 2
    local addressFunction = getAddress("TranslateMessage")
    AddBreakPointExecut(addressFunction)
    print("Включен режим остановки на фунции TranslateMessage без условий")
    end

    function StartDebugSomeFunction(functionName)
    mode = 0
    local addressFunction = getAddress(functionName)
    AddBreakPointExecut(addressFunction)
    end

    function StopDebug()
    DeleteAllBreakPoint()
    _iMSGBreak = 0
    end
    --[[

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

    В моем примере выводятся инструкции, которые записывают значение 1080 типа Integer по адресу "Test.exe+5B5A4". Дальше смотрите код.


    Автор: MasterGH 2011

    Скрпит для
    идентификации инструкции работающием с адресом, когда в нём оказывается определённое значения.

    Требования:
    - предварительно приаттачить 32-х разрядный процесс игры через иконку Компьютера в главном окне CE
    - Если тип данных сравниваемого значения не Integer, то изменить в скрипте "readInteger"

    Информация по Lua поддержке: http://ce.colddot.nl/browser/Cheat%20Engine%206/bin/main.lua
    Информация по Lua константам: http://ce.colddot.nl/browser/Cheat%20Engine%206/bin/defines.lua

    Хотите доработать скрипт?
    -- Вы можете создать графический интерфейс пользователя
    -- Вы можете сделать так чтобы не выводились повторяющиеся инструкции

    ]]--

    -- Значения для настройки

    local myValue = 1080 -- сравниваемое значение, в моем случае 1080типа Integer
    local myValueSize = 4 -- размер данных по адресу, в моём случае Integer, значит "4"
    local myAddress = getAddress("Test.exe+5B5A4") -- получение адреса в целочисленный тип, мой адрес "Test.exe+5B5A4"

    -- тип бряка "ставим на запись"
    local typeBreak = 2 --( другие: bptExecute=0, bptAccess=1, bptWrite=2)

    -- Если игра вылетает, то попробовать типы отладки: VEHDebug и Kerneldebug
    local typeDebug = 1 -- тип отладки (0=default, 1=windows debug, 2=VEHDebug, 3=Kerneldebug)

    local criticalCount = 5000 -- если лог постоянно показыватеся, что его нельзя остановить, то этот предел остановит отладку
    local count = 0
    -----------------------------------

    -- Вызвать в консоли эту функцию если нужно удалить бряк и преркатить слежение
    -- В этой функции ничего менять не надо
    function RemoveBreakpoint()
    debug_removeBreakpoint(myAddress);
    end

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

    -- Функция обработки события точки останова
    -- В этой функции можно поменять readInteger на нужный тип данных
    function debugger_onBreakpoint()
    -- если значение по адресу равно 1080, то выводить инструкции в лог
    if readInteger(myAddress)== myValue then
    print(disassemble(getPreviousOpcode(EIP)))
    count = count + 1
    if (count > criticalCount) then
    RemoveBreakpoint()
    end
    end
    return 1 -- не показывать отладчик, если 0 - то показывать
    end

    -- Далее ничего менять не надо
    debugProcess(typeDebug) -- установка режима отладки

    -- Утановка брейкпоинта
    -- В этой функции ничего менять не надо
    debug_setBreakpoint(myAddress, myValueSize, typeBreak) -- установка самого брякак
    --[[

    Скриншот на котором показано как работать с этим скриптом:

    post-3-1311013361,7_thumb.png

    Желаю успехов!

  4. Я думаю, что так лучше:


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

    newmem:
    cmp esi,[gta3.exe+4F609C]
    jne originalcode

    mov [esp+28],(float)0
    originalcode:
    fcomp dword ptr [esp+28]
    fnstsw ax
    jmp returnhere

    "gta3.exe"+151C05:
    jmp newmem
    nop
    returnhere:

    [DISABLE]
    "gta3.exe"+151C05:
    fcomp dword ptr [esp+28]
    fnstsw ax

    dealloc(newmem)

  5. Я сделал фильтр на себя(он работает),но появился вопрос: "ecx меня" - A3ED730, это и есть структура игрока?:)

    Да, это теоретически всегда "структура Игрока" или структура которая относится к Игроку. Обычно, я так и называю структуру в таких случаях - "Структура игрока". Она может быть твоего игрока, игроков-врагов и дружественных игроков.

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

  6. :)

    Трейнермекеры (Разработчики) сталкиваются с ограничением. Им разрешено заливать за раз не более 2 мб данных на форум и файловый лимит 50 Мб. Почему такое ограничение и что делать в этом случае?

    В моей компетенции ответить только на последний вопрос - "что делать?".

    Если вы поклонник exe-трейнеров генерируемых на Cheat Engine, то Вам остаётся пользоваться архиваторами, а возможно ещё и CE 5.6.x версиями. В этом случае трейнер в архиве получается меньше 2 мб. И вы его можете заливать на хостинг форума.

    Тем не менее у вас остаётся следующая проблема. Что делать если Вы подошли к границе 50 Мб ведь это может случится. В этом случае вы можете:

    1) Обратиться к Администрации (возможно мы увеличим предел)

    2) Выкладывать ссылки на файлы сторонних хостингов (посоветовать какие-то конкретные хостинги я не могу)

    3) Удалить/переделать часть ваших файлов (по себе знаю, это тягомотина)

    Сторонние хостинги обычно не хранят свои файлы бесконечно и могут их удалить. В этом случае наш хостинг более надежней.

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

    От себя советую все читы как минимум делать на АА-скриптах Cheat Engine файлами формата *.CT. Если есть опыт, то на Lua - формат *.CETRAINER. Последний формат более предпочтителен. Почему именно этот формат, то я об этом много раз писал и мне уже надоело.

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

  7. Из текстового 16-ричного формата я перевожу.

    А там уже возможна ещё другая ошибка, нужно объявить переменную возвращающую значение:


    Dim lpNumberOfBytesWritten
    WriteProcessMemory(HL2WriteProcess.Handle, Convert.ToUInt32(AddressWith0X.Text, 16) as IntPtr, pBytes, pBytes.Length, lpNumberOfBytesWritten)

    На скрине ошибка по поводу pBytes. Я плохо знаю VB у меня он не установлен. Разберись почему pBytes вызывает ошибку. Поищи примеры... Я VB не использую и могу много чего насоветовать и это может быть неправильно.

  8. VAM.WriteByte((IntPtr)BaseAddress.text, byte.Parse(NewValue.Text.ToString())):

    Нельзя "(IntPtr)" приводить к объекту класса "String".

    Так должно быть правильно, если имеем дело с 32-разрядной адресацией:

    VAM.WriteByte((IntPtr)(Convert.ToUInt32(BaseAddress.text)), byte.Parse(NewValue.Text.ToString()));

    Для кода ниже для AddressWith0X.Text аналогично:

    WriteProcessMemory(HL2WriteProcess.Handle, AddressWith0X.Text, pBytes, pBytes.Length, 0)

    WriteProcessMemory(HL2WriteProcess.Handle, (IntPtr)(Convert.ToUInt32(AddressWith0X.Text)), pBytes, pBytes.Length, 0)

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

  10. Правильно я понял? Ты делал два дампа в режиме гибернации. Первый во время игры. Второй без игры. Первый тебе удалось сохранить. А когда ты делал второй, то ты не будил систему и подменил дампы. Затем включил и загрузился со второго дампа - с места где ты играл.

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

    Поищи информацию по поводу копирования и подмены системных файлов. Может быть уже кто-то написал драйвер с "программой" общения с этим драйвером...

  11. Вообще, по большому счету, достаточно замены лишь одного байта, но иногда несоблюдение баланса опкодов (даже если нопать ничего не надо) приводит к вылету из игры...

    Действительно одного байта достаточно. Я не углядел. Что имелось ввиду под понятием "баланса" я не понял. К вылету приведёт, если код запишет не туда и не то, что надо.

    Тем кто не знает где прочитать информацию по цепочкам байтов - ссылка.

  12. В 11.07.2011в21:53, Izmalkoff сказал:

    Я absoscan ставить не умею

     

    На форуме написано по каким правилам составляется цепочка байт, там написано как пользоваться aobscan. Им можно пользоваться в Автоассемблере, а можно на Lua.

    Скрипт

    Скрытый текст
    
    [ENABLE]
     aobscan(_faddress,74xxxxxxxx8bxxxxxxxxxxe8xxxxxxxx8bxx85xx7cxxf6xxxx74xx8bxxe8)
     _faddress: // 6CCF13AA = xlive.dll+F13AA
     db EB 14
    
     [DISABLE]
     aobscan(_faddress,8bxxxxxxxxxxe8xxxxxxxx8bxx85xx7cxxf6xxxx74xx8bxxe8)
     _faddress-5:
     db 74 14

     

    Можно переделать на этот:

    Скрытый текст
    
    [ENABLE]
     aobscan(_faddress,74xxxxxxxx8bxxxxxxxxxxe8xxxxxxxx8bxx85xx7cxxf6xxxx74xx8bxxe8)
    label(xliveLabel)
    registersymbol(xliveLabel) 
    
     _faddress: // 6CCF13AA = xlive.dll+F13AA
    xliveLabel:
     db EB 14
    
    [DISABLE]
    xliveLabel:
     db 74 14

     

    А можно и на этот на Lua (но я не проверял):

    Скрытый текст
    
    local function ByteScan(signature, typeMem) -- return address
    local results = nil
    results = AOBScan(signature, typeMem) -- typeMem = "+X-C-W" and any
    if (results == nil) then
    messageDialog("Ошибка. Не найден адрес внедрения.\n\rТрейнер будет закрыт!",1, 2)
    closeCE()
    return caFree
    end
    local address = stringlist_getString(results, 0)
    object_destroy(results);
    return address
    end
    
    local AA_XLIVEcodeEnable = ""
    local AA_XLIVEcodeDisable = ""
    
    function DisableXLIVE()
    autoAssemble(AA_XLIVEcodeEnable)
    end
    
    function EnableXLIVE()
    autoAssemble(AA_XLIVEcodeDisable)
    end
    
    function InitAndDisableXLIVE()
    -- Если "+X-C-W" не точно, то поставить свои правила
    local xliveAddr = ByteScan("74xxxxxxxx8bxxxxxxxxxxe8xxxxxxxx8bxx85xx7cxxf6xxxx74xx8bxxe8", "+X-C-W")
    
    AA_XLIVEcodeEnable = [[
    ]]..xliveAddr..[[: // 6CCF13AA = xlive.dll+F13AA
    db EB 14
    ]]
    
    AA_XLIVEcodeDisable = [[
    ]]..xliveAddr..[[: // 6CCF13AA = xlive.dll+F13AA
    db 74 14
    ]]
    
    DisableXLIVE()
    end

     

     

  13. О, не плохо. Если ты сам написал описание "_call()", то даже я не знал про то, что так можно динамически определять аргументы функции...

        // как реализовать его в CE без скрипта мне не довелось узнать
    _call(0x006A6374, 1, curscreen);

    Это можно реализовать и на автоассемблере, и на Lua, и на том и другом вместе. Я подумаю как сделать удобнее... Возможно стоит просто вызывать AddMsg() из скриптов CE по горячим клавишам... посмотрим.

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

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


    // dllmain.cpp: определяет точку входа для приложения DLL.
    #include "stdafx.h"



    void AddRecord(ofstream *DBFile, long int i, char name[], char cheat[])
    {
    *DBFile << " <Names>\n";
    *DBFile << " <Key>"<< i << "</Key>\n";
    *DBFile << " <Name>"<< name <<"</Name>\n";
    *DBFile << " </Names>\n";
    *DBFile << " <Cheats>\n";
    *DBFile << " <Key>"<< i << "</Key>\n";
    *DBFile << " <Cheat>"<< cheat << "</Cheat>\n";
    *DBFile << " </Cheats>\n";
    }


    void Code()
    {
    ofstream DBFile;
    DBFile.open ("D:\\DB.txt");

    if (DBFile.is_open())
    {
    cout << "Files opens:\n\n";

    DBFile << "<?xml version=\"1.0\" standalone=\"yes\"?>\n<DataSet1 xmlns=\"http://tempuri.org/DataSet1.xsd\">\n";

    _asm
    {
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    }
    long int maxCount = 50;
    for(long int i=0; i < maxCount; i++)
    {
    char name[100] = "Name";
    char cheat[100] = "Cheats";
    AddRecord(&DBFile, i, name, cheat);
    }

    DBFile << "</DataSet1>";
    DBFile.close();
    }
    else
    cout << "Unable to open file\n\n";
    }



    BOOL APIENTRY DllMain( HMODULE hModule,
    DWORD ul_reason_for_call,
    LPVOID lpReserved
    )
    {
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
    break;
    }
    return TRUE;
    }

  14. int (сокращённое от "Integer") - это тип данных для определения переменой числа. У числа типа int может быть положительный и отрицательный знак. Размер 4 байта. Более подробно в поисковике по запросу "типы данных Integer"

  15. Для тех кто хочет использовать этот компонент, а также другие на этом примере с setProperty не из дизайнера создания форм.

    В данном примере создаётся ListView с 3 столбцами и 3 строками.

    f=createForm() 
    lv=createListView(f)
    setProperty(lv, 'ViewStyle', 'vsReport') --non lua exported property but you can access it with this
    setProperty(lv, 'RowSelect', 'True')
    setProperty(lv, 'ReadOnly', 'True')
    lvc=listview_getColumns(lv)
    column1=listcolumns_add(lvc)
    column2=listcolumns_add(lvc)
    column3=listcolumns_add(lvc)

    listcolumn_setCaption(column1, 'a')
    listcolumn_setCaption(column2, 'b')
    listcolumn_setCaption(column3, 'c')

    lvi=listview_getItems(lv);
    row1=listitems_add(lvi)
    listitem_setCaption(row1, 'Row 1'); --rw 1 column a
    row1_subitems=listitem_getSubItems(row1) --returns a Strings object
    strings_add(row1_subitems, 'r1_cb') --row 1 column b
    strings_add(row1_subitems, 'r1_cc') --row 1 column c


    row2=listitems_add(lvi)
    listitem_setCaption(row2, 'Row 2');
    row2_subitems=listitem_getSubItems(row2)
    strings_add(row2_subitems, 'r2_cb')
    strings_add(row2_subitems, 'r2_cc')


    row3=listitems_add(lvi)
    listitem_setCaption(row3, 'Row 3');
    row3_subitems=listitem_getSubItems(row3)
    strings_add(row3_subitems, 'r3_cb')
    strings_add(row3_subitems, 'r3_cc')

    Источник форум CE.

  16. MasterGH а реально вызывать процедуры из CE по горячей клавише? Допустим при внедрении DLL можно вызвать фунцию из неё ... хотелось бы без DLL так же вызывать произвольную функцию в игре

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


    function FunctionSpawnCar(hotkey)
    autoAssemble("CREATETHREAD(SpawnCar)")
    end

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

    function Deinitialization()
    autoAssemble([[
    unregistersymbol(SpawnCar)
    dealloc(SpawnCar)
    ]])
    end

    function Initialization()

    local address = ... // получить адрес вызываемой функции

    local AAscript = [[
    alloc(SpawnCar,2048)
    registersymbol(SpawnCar)
    label(stringCar)

    SpawnCar:
    push ...
    push ...
    push stringCar
    call ]]..address..[[
    ret

    stringCar:
    db ... 00 // hex-строка машины оканчивающаясь нулевым символом
    ]]

    autoAssemble(AAscript)

    --создание формы трейнера
    -- ...

    --привязка функции Deinitialization() к закрытию формы
    -- ...

    --Назначение хоткеев
    setHotKey(FunctionSpawnCar, VK_F2) -- спавн некоторой машины
    end

    function onOpenProcess(processid)
    Initialization()
    end

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

    Как видно здесь Lua код вперемешку с Автоассемблером. Есть инициализация, деинициализация, првязка горячей клавиши, создание потока на АА. Могут быть проблемы с поточной синхронизацией или другие, надо проверять на практике...

    Понял.

    И ещё вопрос возник. Не совсем по этой теме...

    Я так понял, на LUA можно несколько удобнее сделать?

    Там же во время выполнения можно менять переменные по горячим клавишам, таким образом включая/отключая разные секции кода?

    Тогда получается что в моём случае можно было бы менять сразу несколько переменных, включая и отключая любые из них, не трогая остальные(записывающиеся в адреса), а в автоассемблере есть только варианты вкл/выкл вообще всего...

    Жаль что из программирования я тока про Паскаль чего-то помню, и про Java Script

    1. Можно ли на Lua делать удобнее не знаю. Для каждого человека своё видение удобства.

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

    3. Переменные можно менять и без Lua. Зарегистрируй их в АА через registersymbol. Создай другой АА который бы менял значения по зарегистрированным меткам.

    4. Когда Lua поддержки в CE не было у меня была та же проблема. Lua я не знал, но учился на примерах.

    • Плюс 1
  17. Увы для меня 5ый шаг сложен

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

  18. 2. Случай.

    Увлёкшись написанием длинного скрипта можно забыть о корректности типов данных. В этом примере не учтено, что cmp без указания типа данных сравнивает данные как dword. Это касается 32-х разрядных приложений.


    //code from here to '[DISABLE]' will be used to enable the cheat
    alloc(newmem,2048) //2kb should be enough
    label(GM1)
    label(GM2)
    label(nocops)
    label(returnhere)
    label(originalcode)
    //label(pBuffer)
    label(money)
    label(god)
    label(armor)
    label(cops)
    //registersymbol(pBuffer)
    registersymbol(money)
    registersymbol(god)
    registersymbol(armor)
    registersymbol(cops)
    label(exit)

    newmem: //this is allocated memory, you have read,write,execute access
    //place your code here
    cmp ebx,0 //первый фильтр на буфер с розыском
    jne originalcode
    cmp edx,2000 //второй фильтр на буфер с розыском
    jne originalcode
    //mov [pBuffer],ecx
    cmp esi,3 //третий фильтр на буфер с розыском
    jne originalcode
    cmp [money],01 //+1000000$?
    jne GM1
    mov [ecx+90],#100000

    GM1:
    cmp [god],01 //беск. здоровье вкл.?
    jne GM2
    //mov [ecx+22D0],(float)10000 //столько здоровья хватит, чтобы не взрываться в машинах
    mov [ecx+510],(float)10000
    GM2:
    cmp [armor],01 //беск. броня вкл.?
    jne nocops
    //mov [ecx+2290],(float)1000

    nocops:
    cmp [cops],01 //убрать звезды розыска вкл.?
    jne originalcode
    mov [ecx+10],00 //нет звёзд

    originalcode:
    lea eax,[esp]
    push eax
    push 00

    exit:
    jmp returnhere

    //pBuffer:
    //db 0
    money:
    db 0
    god:
    db 0
    armor:
    db 0
    cops:
    db 0

    "EFLC.exe"+8F1E3:
    jmp newmem
    nop
    returnhere:




    [DISABLE]
    //code from here till the end of the code will be used to disable the cheat
    dealloc(newmem)
    //unregistersymbol(pBuffer)
    unregistersymbol(money)
    unregistersymbol(god)
    unregistersymbol(armor)
    unregistersymbol(cops)

    "EFLC.exe"+8F1E3:
    lea eax,[esp]
    push eax
    push 00
    //Alt: db 8D 04 24 50 6A 00
    [ENABLE]

    Для того чтобы скрипт работал как надо, проще объявить сравниваемый тип данных не как db, а как dd.

  19. Izmalkoff, давай я не буду гадать, а просто буду учить как проверять свои скрипты.

    1) Перед активацией скрипта (игра должна быть в оконном режиме), надо зайти по адресу 038B0013 в дизассемблер.

    2) Нужно выделить инструкцию левым кликом мышки с которой будет переход на инструкцию по адресу 038B0013

    3) Нажать на F5 чтобы поставить бряк на выполнение (чтобы снять нажать ещё раз)

    4) Зайти в игру и что-то сделать, чтобы игра прервалась в отладчике

    5) Затем выполняешь отладку по шагам c заходом в call и смотришь за регистрами (кнопки F7 шаг с заходом в call, F8 - шаг без захода в call), Таким образом ты определишь что в регистрах сранивается, что не сравнивается, почему выполняются или не выполняются прыжки.

  20. Лучше меня и Xipho Шефами не величать, а использовать никнеймы. Мы будем рады если называть нас по никнеймам :)

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

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

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

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