24.03.2012, 23:36
SPLICE_ хук очень плохо себя ведёт, когда в затираемом им коде содержится локальный переход. Вызов оригинальной функции в этом случае невозможен.
(18.03.2012 19:04)Sav Wrote: [ -> ]Похоже, высокоуровневый хук CALL_, EXTENDED_, FASTCALL_ для функции с одним аргументом работает неправильно. При каждом вызове он уменьшает ESP на 4. Если заменить на THISCALL_, то всё нормально.да, так и есть. Для меня это - само собой, поэтому даже не подумал обратить на это внимание в комментариях. Хотя
если int __fastcall orig(int a1, int a2, ?) то int __stdcall new_func(HiHook* h, int a1, int a2, ?)
Quote:SPLICE_ хук очень плохо себя ведёт, когда в затираемом им коде содержится локальный переход. Вызов оригинальной функции в этом случае невозможен.Дело в функциональности MemCopyCode, сейчас она копирует корректно только CALL и далекий JMP опкоды. После твоего поста добавлю поддержку далеких JE, JNE, JL, JG, JLE, JGE, JA, JB, JBE, JNA, ....
Изменения нарушающие обратную совместимость: [!]
Исправления багов: [-]
Расширение функциональности: [+]
Несущественные изменения/комментарии: [*]
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 и %%
1.4
[-] баг из-за которого невозможно было использовать FUNCPTR_ EXTENDED_ HiHook
1.6
[+] Добавлены функции:
PatcherInstance::Write
PatcherInstance::CreatePatch
(см. SDK)
1.5
[-] критический баг при попытке поставить CALL_ HiHook на неверный опкод при выключенном логировании
Quote:надо бы еще сделать чтобы эра делала все патчи через patcher_x86.Хм, глянул, появились переходники на Паскаль. В таком случае посмотрю, что можно сделать к следующей версии. Имеет ли смысл использовать один объект заплатки на все изменения? Или на каждый чих свой объект?
будет очень зашибись..
в логе patcher_x86 будут сразу видны все потенциальные конфликты
1.7
[+] для HiHook добавлен новый subtype: SAFE_ = 2
- то же самое что и EXTENDED_, однако перед вызовом GetDefaultFunc() восстанавливаются (только на время вызова)
значения регистров процессора EAX, ECX (если не FASTCALL_ и не THISCALL_),
EDX (если не FASTCALL_), EBX, ESI, EDI, бывшие на момент вызова замещенной функции
Berserker Wrote:Наконец, если там вдруг ошибка или ошибка в SDK, или нужно глянуть реализацию, потому что мой код не работает, исходников нет.Примеры SDK для всех языков билдились и тестировались успешно.
Berserker Wrote:Помимо прочего я не помню (поправьте если не прав), чтобы клиенты патчера могли делать то же самое: получить список всех заплаток, например (а ради чего ещё остальным такая централизация?). Наконец, если там вдруг ошибка или ошибка в SDK, или нужно глянуть реализацию, потому что мой код не работает, исходников нет.Список всех заплаток клиент получить не может. Было бы не плохо если б было можно. Еще лучше была бы функция: получить патчи в указанном диапазоне адресов.
(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
...
Quote:Главная фича хуков патчера - это то, что разные моды независимо друг от друга могут хучить одну и туже функцию или ее конкретный вызов сколько угодно разПодавляющее большинство моих перехватов находится в произвольных частях. Правку call/jmp смещений в затёртых командах я добавил, так что и пять заплаток в одно место в режиме "мост" сработают. Но в целом направление верное, будем туда и копать.