Current time: 20.04.2024, 21:31 Hello There, Guest! (LoginRegister)
Language: english | russian  

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

Posts: 2180
Post: #16

SPLICE_ хук очень плохо себя ведёт, когда в затираемом им коде содержится локальный переход. Вызов оригинальной функции в этом случае невозможен.
24.03.2012 23:36
Find all posts by this user Quote this message in a reply
gamecreator Offline

Posts: 7107
Post: #17

можно как-нибудь поставить хук на завершение функции? придется ставить хук на все места выхода? а если выход из нее находится посреди кода?


When all gods have burnt to ashes in eternity of sorrow,
Demons gonna tear your soul because there is no tomorrow.
25.03.2012 01:37
Find all posts by this user Quote this message in a reply
Sav Offline

Posts: 2180
Post: #18

Поставь splice хук и вызови в нём оригинальную функцию до собственного кода.
25.03.2012 09:10
Find all posts by this user Quote this message in a reply
baratorch Offline

Posts: 197
Post: #19

(18.03.2012 19:04)Sav Wrote:  Похоже, высокоуровневый хук CALL_, EXTENDED_, FASTCALL_ для функции с одним аргументом работает неправильно. При каждом вызове он уменьшает ESP на 4. Если заменить на THISCALL_, то всё нормально.
да, так и есть. Для меня это - само собой, поэтому даже не подумал обратить на это внимание в комментариях. Хотя
Code:
если   int __fastcall orig(int a1, int a2, ?)    то    int __stdcall new_func(HiHook* h, int a1, int a2, ?)
из комментов мною читается однозначно: fastcall c 1 аргументом не поддерживается в EXTENDED_ FASTCALL_.
Действительно, этот недостаток можно обойти используя EXTENDED_ THISTCALL_
Ну а для читабельности и логичности можно использовать пару констант типа:
FASTCALL_1_ = THISCALL_ и FASTCAL_2_ = FASTCALL_
Просто мне не представляется возможным, чтобы хук сам мог определять сколько аргументов передается замещаемой функции, поэтому EXTENDED_ FASTCALL_ всегда пушит и ECX и EDX в стек.

Quote:SPLICE_ хук очень плохо себя ведёт, когда в затираемом им коде содержится локальный переход. Вызов оригинальной функции в этом случае невозможен.
Дело в функциональности MemCopyCode, сейчас она копирует корректно только CALL и далекий JMP опкоды. После твоего поста добавлю поддержку далеких JE, JNE, JL, JG, JLE, JGE, JA, JB, JBE, JNA, ....
Впринципе короткие прыжки можно в замещаемом коде при копировании заменять на длинные, однако тогда скопироавнный код будет длиннее оригинального, что еще добавит работы...

Короче, сделаю в следующем релизе.
(This post was last modified: 26.03.2012 09:15 by baratorch.)
26.03.2012 09:14
Find all posts by this user Quote this message in a reply
baratorch Offline

Posts: 197
Post: #20

1.3

http://sites.google.com/site/heroes3hd/f...ects=0&d=1

старался как можно сильнее сохранить обратную совместимость. но полностью не получилось.
ХД 3 написанный с patcher_x86 SDK 1.2, например прекрасно пошел на новой 1.3
(а вот последнюю редакцию ХоТы придется подправить)

чейнджлог:
Code:
Изменения нарушающие обратную совместимость: [!]
Исправления багов: [-]
Расширение функциональности: [+]
Несущественные изменения/комментарии: [*]

1.3


[-] Исправлены ошибки:
    - отмена хуков во время выполнения их хук-функций приводила к непредвиденным результатам
    - неверно работал формат-символ %a в функции Patcher::WriteComplexData

[+] Функция Patcher::CreateInstance теперь, принимая в качестве аргумента нулевую и пустую строки,
    создает PatcherInstance с именем модуля вызвавшего функцию.

[+] Функции Patcher::GetInstance можно передавать в качестве аргумента не только
    уникальое имя PatcherInstance, но так же имя модуля, создавшего PatcherInstance.
    Однако, имейте ввиду что в одном модуле можно создать несколько экземпляров PatcherInstance,
    в этом случае Patcher::GetInstance с именем модуля в качестве аргумента будет
    возвращать первый созданный PatcherInstance в этом модуле.

[!] Теперь невозможно создавать патчи посредством экземпляра PatcherInstance созданным не в вашем модуле.
    Возможность отменять и применять эти патчи сохранена.

[!] Функция Patch::Apply() теперь возвращает индекс (c 0) патча/хука в последовательности примененных патчей по данному адресу
    в случае успеха, -2 если патч/хук уже применен и -1 в случае неуспеха из-за неведомой хрени.

[!] Функция Patcher::DestroyAllAt заменена на Patcher::UndoAllAt

[*] Функции
    PatcherInstance::WriteComplexPatch
    PatcherInstance::CreateComplexPatch
    переименованы в
    PatcherInstance::WriteCodePatch
    PatcherInstance::CreateCodePatch
    для лучшего отражения сути их работы

[!] Теперь все патчи разделены на 2 типа: DATA_ и CODE_
    DATA_ патчи устанавливаются посредством простого копирования памяти
    CODE_ - посредством MemCopyCode
    произвольно выбрать тип патча нельзя, он устанавливается автоматически.
    DATA_ : BytePatch, WordPatch, DwordPatch, HexPatch, FUNCPTR_ HiHook, DataPatch
    CODE_:  JmpPatch, CodePatch (бывший ComplexPatch), LoHook, CALL_ и SPLICE_ HiHook
    ОЧЕНЬ ВАЖНО понимать разницу!

[+] Добавлены/реализованы функции:

    Patch::ApplyInsert

    PatcherInstance::WriteDataPatch
    PatcherInstance::CreateDataPatch
      PatcherInstance::GetLastPatchAt,
    PatcherInstance::UndoAllAt,
    PatcherInstance::GetFirstPatchAt.

    Patcher::GetFirstPatchAt,
    Patcher::MemCopyCodeEx,


[!] Теперь невозможно уничтожить неотмененный Хук (т.е. чтобы уничтожить, нужно сначала отменить).
[!] Возможность корректно уничтожить хук во время выполнения хук-функции ликвидированна
    (из-за бага ее и так не было, но теперь ее нет официально)

[*] Теперь Хук любого типа можно безопасно отменить в любой момент во время выполнения
    его хук-функции (соответственно исключая т.н. FIXED хуки, которые вообще нельзя отменить).
    Хук отменяется сразу (т.н. понятие отложенной отмены теперь неактуально).

[+] Функция Patcher::MemCopyCode теперь помимо CALL (E8) и JMP (E9) опкодов корректно копирует
    опкоды 0F 80 - 0F 8F (длинные условные прыжки);
[!] теперь в функции Patcher::MemCopyCode переходы E8, E9, 0F 80 - 0F 8F трансформируются
    только если направляют за границы копируемого блока.

[!] Функция Patcher::MemCopyCode теперь копирует всегда целое количество опкодов.
    (т.е. размер скопированного блока кода теперь >= size (был строго = size, т.е последний опкод мог быть обрезан).

[*] Функция Patcher::MemCopyCodeEx отличается от Patcher::MemCopyCode тем что если
    в копируемом блоке короткие прыжки EB, 70 - 7F направляют за границы копируемого блока,
    то они замняются на соответсвующие длинные прыжки (E9, 0F 80 - 0F 8F)

[*] Таким образом, теперь появилась возможность устанавливать SPLICE_ хуки и низкоуровневые хуки на код,
    содержащий любые корткие и длинные относительные переходы.
    А еще очевидна возможность скопировать целую функцию или ее часть от начала
    и вызывать копию как оригинал.

[+] Низкоуровневый хук теперь не сбивает содержимое регистров флагов, соответственно его
    теперь можно ставить на любой код в функции.

[!] Jmp патч, созданный посредством PatcherInstance::CreateJmpPatch и PatcherInstance::WriteJmp
    теперь закрывает целое количество опкодов, т.е. размер патча теперь >= 5 (был строго = 5),
    разница заполнятеся NOP'ами.

[+][!] Расширена функциональность Patcher::WriteComplexData, PatcherInstance::WriteCodePatch и PatcherInstance::CreateCodePatch
    - добавлена возможность ставить метки (до 10) и осуществлять переход к ним
      с помощью всех длинных и коротких относительных переходов (E8, E9, 0F 80 - 0F 8F, EB, 70 - 7F)
      (формат символы #0: , #1: , ... , #9: и #0 , #1 , ... , #9)
    - добавлен формат символ ~b - берет из аргументов абсолютный адрес и
      пишет относительное смещение до него размером в 1 байт для опкодов EB, 70 - 7F
    - добавлен формат символ ~d - берет из аргументов абсолютный адрес и
      пишет относительное смещение до него размером в 4 байта для опкодов E8, E9, 0F 80 - 0F 8F
    - добавлен формат символ %o (offset) - помещает по адресу из аргумента смещение позиции в Complex коде,
      относительно начала Complex кода.
    - добавлен формат символ %n (nop) - пишет nop опкоды, количеством указанным в аргументе
    - формат символ %m теперь копирует посредством MemCopyCodeEx а не MemCopyCode,
      то есть размер скопированного кода может оказаться больше копируемого
      из-за трансформации коротких прыжков в длинные.
    - формат символы %a и %h будут оставлены для обратной совместимости, но упоминания о них будут убраны из SDK;
      вместо этих символов рекомендуется использовать %o и %%
(This post was last modified: 04.04.2012 22:49 by baratorch.)
04.04.2012 14:17
Find all posts by this user Quote this message in a reply
Berserker Offline
Administrators

Posts: 16486
Post: #21

baratorch, круто, но, кажись, журнал изменений продублирован.


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

Posts: 197
Post: #22

готова версия 1.4:
http://sites.google.com/site/heroes3hd/f...ects=0&d=1

изменения:
Code:
1.4
[-] баг из-за которого невозможно было использовать FUNCPTR_ EXTENDED_ HiHook
25.06.2012 08:23
Find all posts by this user Quote this message in a reply
baratorch Offline

Posts: 197
Post: #23

готова версия 1.6:
http://sites.google.com/site/heroes3hd/f...ects=0&d=1

изменения:
Code:
1.6

[+] Добавлены функции:
    PatcherInstance::Write
    PatcherInstance::CreatePatch
    (см. SDK)

1.5

[-] критический баг при попытке поставить CALL_ HiHook на неверный опкод при выключенном логировании

так же в архиве плагин для эры (wog_patcherizer.era), который засталяет Эру делать все инициализационные патчи ВоГ через patcher_x86 (версии не ниже 1.6)

***

надо бы еще сделать чтобы эра делала все патчи через patcher_x86.
будет очень зашибись..
в логе patcher_x86 будут сразу видны все потенциальные конфликты
(This post was last modified: 27.07.2012 18:07 by baratorch.)
27.07.2012 09:43
Find all posts by this user Quote this message in a reply
Berserker Offline
Administrators

Posts: 16486
Post: #24

Quote:надо бы еще сделать чтобы эра делала все патчи через patcher_x86.
   будет очень зашибись..
   в логе patcher_x86 будут сразу видны все потенциальные конфликты
Хм, глянул, появились переходники на Паскаль. В таком случае посмотрю, что можно сделать к следующей версии. Имеет ли смысл использовать один объект заплатки на все изменения? Или на каждый чих свой объект?


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

Posts: 197
Post: #25

не очень понял вопрос, но попытаюсь ответить.
установка патча с помощью patcher_x86 в виде непрерывной последовательности байт - это всегда создание нового отдельного объекта TPatch

ХД+ХотА ставят более 3000 патчей/хуков
ХД+ВоГ - более 2200
ХД - более 1200
никаких промедлений при запуске не заметно, тыщи патчей ставятся 'мгновенно'.
ну, подумаешь, сколько-то там сотен килобайт памяти расходуется на это дело
зато удобств куча.

как мне видится использование patcher_x86 в эре:
патчи из самой эры (если таковые имеются) устанавливаются через TPatcherInstance c именем "ERA"
а скажем каждая bin заплатка через TPatcherInstance c именем "ERA:<имя_заплатки.bin>"

и, bers, обрати внимание на Хуки в patcher_x86. посмотри SamplePlugin в SDK Delphi. Хоть пример и не охватывает весь функционал patcher_x86, но некоторое представление о хуках дает .
Было бы вообще супер, если бы ты полностью перешел на них, отказавшись от своей реализации в Эре.

ну реально удобно видеть где кто какие патчи поставил,.. где какой патч пересек другой..
27.07.2012 17:30
Find all posts by this user Quote this message in a reply
Berserker Offline
Administrators

Posts: 16486
Post: #26

Да, я понял. Попробую.


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

Posts: 197
Post: #27

готова версия 1.7:
https://sites.google.com/site/heroes3hd/...ects=0&d=1

Code:
1.7

[+] для HiHook добавлен новый subtype: SAFE_ = 2
    - то же самое что и EXTENDED_, однако перед вызовом GetDefaultFunc() восстанавливаются (только на время вызова)
    значения регистров процессора EAX, ECX (если не FASTCALL_ и не THISCALL_),
    EDX (если не FASTCALL_), EBX, ESI, EDI, бывшие на момент вызова замещенной функции

SAFE_ subtype создан прежде всего для установки хуков поверх воговских, т.к. воговские хуки функций Moral часто не ограничиваются аргументами, но используют значения из регистров процессора в контексте вызова в геройском коде.

проблема решалась и без SAFE_, просто вначале Hi-хука нужно было сохранить значения регистров и восстановить их перед вызовом дефолтной функции. Однако patcher_x86 создан для высокоуровневого модифицирования, и использовать асемблер с ним - идеологически неверно.
(This post was last modified: 24.09.2012 19:33 by baratorch.)
24.09.2012 17:36
Find all posts by this user Quote this message in a reply
baratorch Offline

Posts: 197
Post: #28

Исходники patcher_x86 (MS VC++ 2008):
http://sites.google.com/site/heroes3hd/f...ects=0&d=1

Berserker Wrote:Наконец, если там вдруг ошибка или ошибка в SDK, или нужно глянуть реализацию, потому что мой код не работает, исходников нет.
Примеры SDK для всех языков билдились и тестировались успешно.
В самом патчере 1.7 пока ни ХотА ни ХД не нарвались на баг.

Berserker Wrote:Помимо прочего я не помню (поправьте если не прав), чтобы клиенты патчера могли делать то же самое: получить список всех заплаток, например (а ради чего ещё остальным такая централизация?). Наконец, если там вдруг ошибка или ошибка в SDK, или нужно глянуть реализацию, потому что мой код не работает, исходников нет.
Список всех заплаток клиент получить не может. Было бы не плохо если б было можно. Еще лучше была бы функция: получить патчи в указанном диапазоне адресов.

Что сейчас может клиент. Может отменить/применить все патчи, может отменить применить все патчи указанного PatcherInstance (т.е. мода или части мода). Можно получить все патчи по конкретному адресу.
А еще клиент может сохранить в файл дамп - карту всех наложенных патчей в данный момент времени; и лог, показывающий очередность применения/отменения патчей с деталями и потенциальные конфликты. Разработчик смотрит дамп и лог и, руководствуясь увиденным, делает изменения в коде мода.
Вот ради возможности посмотреть такие дамп и лог (которые кроме всего прочего показывают какой мод (PatcherInstance) установил определнный патч/хук) и возможности включать отключать патчи установленные из других модов и нужна централизация.

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

(20.11.2012 06:56)GrayFace Wrote:  
(15.11.2012 03:03)baratorch Wrote:  Было бы здорово, если б 3.59 тоже перешел на патчер, ибо никакие узкоспециализированные API и скриптовые языки не смогут решать такие задачи, какие может патчер
Я сейчас использую удобную систему хуков на Луа. По сути, любые задачи с помощью моего модуля хуков/структур/работы с памятью можно решать. Одно исключение - когда нужна скорость, тогда придется грузить dll или байт-код писать строкой. Да, еще ограничение - код должен исполняться в основном потоке. Патчер я глянул только чуть-чуть и, как я понял, есть сходства с моими хуками в высокоуровневости.
Главная фича хуков патчера - это то, что разные моды независимо друг от друга могут хучить одну и туже функцию или ее конкретный вызов сколько угодно раз, не перекрывая а дополняя её код при желании.
Ну и описанные выше возможности по управлению чужими патчами/хуками и просмотр дампа и лога - очень важная и полезная вещь.

вот пример дампа:
Quote:instances(7): 'HD', 'HotA', 'spellbook.patch', 'HD.Af', 'HD.TE', 'HD.IG', 'HD.Pack.SuperRus',
addresses count: 3460
    patches count: 3637


00401448: count = 1 [Patch , size: 04, owner: HD]
0040144F: count = 1 [Patch , size: 04, owner: HD]
00401510: count = 2 [HiHook, size: 05, owner: HD] [HiHook, size: 05, owner: HD.Af]
00402480: count = 1 [Patch , size: 04, owner: HotA]
00402E70: count = 1 [HiHook, size: 05, owner: HD]
00402F00: count = 1 [Patch , size: 04, owner: HD]
00402F49: count = 1 [Patch , size: 04, owner: HD]
...

и лога:
Quote:log records count: 3769

Patch 00599B31/06 ->Apply (HD), z-order = 0
...
HiHook 00479853/05 ->Apply (HotA), z-order = 0
HiHook 0047999B/05 ->Apply (HotA), z-order = 0

WARNING! 00493E31: Applying Patch (size: 32, owner: HotA), which overwrites a part of already applied HiHook (size: 5, owner: HD) at 00493E4C! Older one becomes FIXED!

Patch 00493E31/32 ->Apply (HotA), z-order = 0
...
(This post was last modified: 21.11.2012 08:05 by baratorch.)
21.11.2012 06:37
Find all posts by this user Quote this message in a reply
Berserker Offline
Administrators

Posts: 16486
Post: #29

baratorch, спасибо за исходники и разъяснения. Мне осталось только разобраться в конфликтах виртуальной файловой системы Эры и Wine.

Quote:Главная фича хуков патчера - это то, что разные моды независимо друг от друга могут хучить одну и туже функцию или ее конкретный вызов сколько угодно раз
Подавляющее большинство моих перехватов находится в произвольных частях. Правку call/jmp смещений в затёртых командах я добавил, так что и пять заплаток в одно место в режиме "мост" сработают. Но в целом направление верное, будем туда и копать.


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

Posts: 16486
Post: #30

Патчер 1.7, SDK C++, patcher_x86.hpp:
225:2 [Warning] no newline at end of file


Скачать Герои 3 Эра и всё, что с ней связано / ERA 2.46f для старых модов
Поддержать проект
01.01.2013 22:27
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