Current time: 24.03.2024, 09:26 Hello There, Guest! (LoginRegister)
Language: english | russian  

Post Reply 
Threaded Mode | Linear Mode
patcher_x86.dll
» версия 2.8
Author Message
baratorch Offline

Posts: 197
Post: #61

версия 2.5

библиотека + SDK + исходники

чейнджлог:
Code:
2.5

[+] Функциии PatcherInstance::CreateCodePatch и PatcherInstance::WriteCodePatch
    теперь умеют корректно воспринимать записанные прямо опкоды с относительной адресацией.
    Например 0x639C40: call 0x447799 раньше можно было записать только в виде
    WriteCodePatch(0x639C40, "c%", 0x447799); или
    WriteCodePatch(0x639C40, "E8 ~d", 0x447799);
    (+ еще можно: WriteDataPatch(0x639C40, "E8  54 DB E0 FF");  чего, в принципе, было достаточно)
    Теперь можно и прямо WriteCodePatch(0x639C40, "E8  54 DB E0 FF") ;  (т.е. теперь можно просто скопировать патч с OllyDbg и не париться с преобразованием)
    


2.4

[-] баг: установка LoHook на длинную последвательность NOP'ов приводила к ошибкам.
03.11.2014 02:19
Find all posts by this user Quote this message in a reply
baratorch Offline

Posts: 197
Post: #62

Bers, продолжим здесь.

baratorch Wrote:
Berserker Wrote:На мой взгляд, указанная тобой, Бара, проверка, неэффективна. Мало ли из какого кода какого модуля вызывается запись патча? Из ЕРМ? Из сгенерированного в оперативной памяти обработчика? Из модуля, который использует функционал другого?

Patcher := Core.GlobalPatcher.CreateInstance(pchar(GetUniquePatchName(BinPatchSource)));
Я создавал по экземпляру патчера для каждого файла-заплатки под уникальным именем и тут же пробовал через этот объект вносить изменения в цикле:
Patcher.Write(cardinal(Patch.Addr), cardinal(@Patch.Bytes), Patch.NumBytes, CODE_PATCH);
В итоге ошибки и, как следствие, вылеты.
Берс, я хочу чтобы у тебя там все работало с патчером.
Но что ты предлагаешь, убрать эту проверку совсем?
Мне это сделать не сложно. Я задавал вопросы, чтобы понять, можно ли решить твою проблему не трогая патчер, но ситуацию ты не прояснил.

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

Если убрать эту проверку, то (как мне кажется) теряется вообще смысл в классе PatcherInstance. И как тогда отслеживать авторов патчей в логе и дампе (одна из важнейших фич патчера), если автором патча может быть кто угодно, вместо обозначенного?


Quote:Patcher := Core.GlobalPatcher.CreateInstance(pchar(GetUniquePatchName(BinPatchSource)));
Я создавал по экземпляру патчера для каждого файла-заплатки под уникальным именем и тут же пробовал через этот объект вносить изменения в цикле:
Patcher.Write(cardinal(Patch.Addr), cardinal(@Patch.Bytes), Patch.NumBytes, CODE_PATCH);
Вот я написанное понимаю так, что и инстанция и патч через эту инстанцию создаются в одном куске кода, т.е. без вариантов в одном модуле (pe-файле... dll/exe).
Поэтому та проверка (на идейном плане), считаю, не может быть помехой (разве что в ее реализации косяки).

вот код из ХД:

Code:
void LoadBinPatch(char* file_name)
{
    DWORD fr;
    _dword_ patches_count = 0;
    _dword_ patch_size = 0;
    _byte_ patch_data[2048];
    _ptr_ address = 0;
    HANDLE hFile = INVALID_HANDLE_VALUE;
    hFile = CreateFile(file_name, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile != INVALID_HANDLE_VALUE)
    {
        PatcherInstance* _PIbin = _P->CreateInstance(Base::GetShortFileName(file_name));
        SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
        if (ReadFile(hFile, (LPVOID)&patches_count, 4, &fr,  NULL))
            for (int i = 0; i < patches_count; i++)
                if (ReadFile(hFile, (LPVOID)&address, 4, &fr,  NULL))
                    if (ReadFile(hFile, (LPVOID)&patch_size, 4, &fr,  NULL))
                    {
                        if (patch_size > 2048) BREAKPOINT;
                        if (ReadFile(hFile, (LPVOID)&patch_data, patch_size, &fr,  NULL))
                        {
                            _PIbin->Write(address, (_ptr_)patch_data, patch_size);
                        }
                        
                    }
        CloseHandle(hFile);
    }
}

...

void LoadBinPatches(char* dir)
{
    WIN32_FIND_DATA file_find_data;
    HANDLE h_search;
    BOOL finished = FALSE;

    Base::dir_set(dir);
    h_search = FindFirstFile("*.bin", &file_find_data);
    if (h_search == INVALID_HANDLE_VALUE)
    {
        Base::dir_restore();
        return;
    }

    while (!finished)
    {
        //////////////////////////////////////
        LoadBinPatch(file_find_data.cFileName);
        //////////////////////////////////////

        if (!FindNextFile(h_search, &file_find_data))
            if (GetLastError() == ERROR_NO_MORE_FILES)
                finished = TRUE;
            else
            {
                FindClose(h_search);
                Base::dir_restore();
                return;
            }
    }

    FindClose(h_search);
    Base::dir_restore();
}

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

...

Я понял в чем дело.

Нужно заменить

Patcher.Write(cardinal(Patch.Addr), cardinal(@Patch.Bytes), Patch.NumBytes, CODE_PATCH);

на

Patcher.Write(cardinal(Patch.Addr), cardinal(@Patch.Bytes), Patch.NumBytes, DATA_PATCH);

Это не очевидно, но я объясню почему.

Я понимаю что, практически все сочиняемые пачти подразумевают содержание кода. Однако CODE_PATCH в Методе Write
означает не то что 'мы пишем код', а то что данные по адресу @Patch.Bytes будут восприниматься как код.

Возмем пример из ченджлога к патчеру 2.5.
Допустим мы хотим поставить патч 0x639C40: call 0x447799.
В бин-файле это будет записано в прямом виде:
   0x639C40, 5, E8 54 DB E0 FF
после считывания в Patch.Bytes будет E8 54 DB E0 FF
но ведь @Patch.Bytes не равен 0x639C40!!!
а значит если мы подразумеваем что по адресу @Patch.Bytes код, а не данные, то E8 54 DB E0 FF будет вызывать не 0x447799, а функцию заданную адресом относительным к @Patch.Bytes.
Ну вот представь, что мы процессору передали на выполнение адрес @Patch.Bytes: будет вызвана функция не 0x447799, а совершенно левая.

***

Еще раз повторю вопрос: что выдает лог патчера?

создаем рядом с patcher_x86.dll - patcher_x86.ini c записью Logging = 1
и после установки всех патчей вызываем Patcher::SaveLog(char* file_name).

если в логе отсутствуют записи
ERROR! Can not create ... at ... (...): Wrong Patcher Instance!
то проверка на верный модуль ни при чем, а дело в CODE_PATCH

жду ответа.
03.11.2014 02:49
Find all posts by this user Quote this message in a reply
Berserker Offline
Administrators

Posts: 16449
Post: #63

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


Скачать Герои 3 Эра и всё, что с ней связано / ERA 2.46f для старых модов
Поддержать проект
03.11.2014 20:14
Find all posts by this user Quote this message in a reply
Berserker Offline
Administrators

Posts: 16449
Post: #64

Если я верно понимаю, при CODE_PATCH патчер считает, что я копирую блок существующего кода, в котором нужно исправить относительные смещения? То есть реальный безопасный патч без обработки — это всегда DATA_PATCH?


Скачать Герои 3 Эра и всё, что с ней связано / ERA 2.46f для старых модов
Поддержать проект
03.11.2014 20:21
Find all posts by this user Quote this message in a reply
baratorch Offline

Posts: 197
Post: #65

да, именно так
03.11.2014 20:22
Find all posts by this user Quote this message in a reply
Berserker Offline
Administrators

Posts: 16449
Post: #66

Откатил в Git для тестов до версии с Patcher, поменял на DATA_PATCH, вылеты исчезли. Значит перенесу потом изменения, вопрос решён, спасибо за помощь.


Скачать Герои 3 Эра и всё, что с ней связано / ERA 2.46f для старых модов
Поддержать проект
03.11.2014 22:18
Find all posts by this user Quote this message in a reply
baratorch Offline

Posts: 197
Post: #67

версия 2.6

библиотека + SDK + исходники

чейнджлог:
Code:
2.6

[+] Добавлен метод PatcherInstance::BlockAllExceptVA(_ptr_* va_args)
    блокирует для данного  PatcherInstance установку патчей для всех адресов кроме указанных.
      Добавлен метод Patcher::PreCreateInstance(char* name)
    нужен для применения методов PatcherInstance::BlockAt и PatcherInstance::BlockAllExceptVA
     до того как PatcherInstance будет полноценно создан с помощью Patcher::CreateInstance
[-] Исправлена возможность краша на старте из-за DEP.
07.11.2014 16:12
Find all posts by this user Quote this message in a reply
baratorch Offline

Posts: 197
Post: #68

версия 2.8

библиотека + SDK + исходники

чейнджлог:
Code:
2.8
[-] теперь EXTENDED_ и SAFE_ HiHook хуки могут быть установлены на рекурсивно выполняемый код.

2.7
[+] patcher_x86 теперь полностью совместим с DEP (Предотвращением выполнения данных)
21.08.2015 11:25
Find all posts by this user Quote this message in a reply
Bes Offline

Posts: 5422
Post: #69

вопрос к Отцам, кто может теперь адаптировать ERA2.47 под новый патчер, ибо сейчас они перестали дружить - новый HD-мод и последняя (2,46 и 2,47) ERA Sorry
Владыка судя по всему не скоро вернётся к ERA (или никогда ((( )
10.09.2015 20:04
Visit this user's website Find all posts by this user Quote this message in a reply
gamecreator Offline

Posts: 7107
Post: #70

Почему это перестали? Они не пересекаются вроде. Может просто wog_patcherizer отвалился, или как там его?


When all gods have burnt to ashes in eternity of sorrow,
Demons gonna tear your soul because there is no tomorrow.
11.09.2015 00:57
Find all posts by this user Quote this message in a reply
« Next Oldest | Next Newest »
Post Reply 


Forum Jump:

Powered by MyBB Copyright © 2002-2024 MyBB Group