01.01.2013, 23:00
04.01.2013, 21:51
Code:
SAFE_ - то же самое что и EXTENDED_, однако перед вызовом (на время вызова) GetDefaultFunc() восстанавливаются
// значения регистров процессора EAX, ECX (если не FASTCALL_ и не THISCALL_),
// EDX (если не FASTCALL_), EBX, ESI, EDI, бывшие на момент вызова замещенной функции
04.01.2013, 22:01
В HiHook'ах регистры сохраняются до перехвата и восстанавливаются после. А когда делаешь CALL от GetDefaultFunc никакие регистры не восстанавливаются: ведь вызываемая функция не должна работать ни с чем, кроме своих параметров. Однако, по-видимому, в Воге кое-где в вызываемой функции используются регистры, значение которых было присвоено в вызывающей функции и, не будучи параметром, волею случая при компиляции, не затёрто в вызываемой функции. Судя по описанию, SAFE_ отвечает за восстановление регистров именно перед вызовом функции по GetDefaultFunc.
04.01.2013, 22:43
Спасибо, что-то подобное и предполагал.
05.01.2013, 00:05
.hpp]ISO C++11 переработанный вариант заголовочного файла патчера
- Код оформлен в основном по руководству гугла.
- Модуль помещён в пространство имён x86patcher.
- Поскольку патчер полностью пропитан 32-битовой арифметикой, ссылаться на типы Студии (__int8 и т.д) смысла нет. Поэтому использованы типы byte, dword, longbool, addr.
- Табы заменены двумя пробелами.
- Добавлены обобщённые функции ptr(адрес) и ptr_ofs(адрес, смещение). В качестве адреса первая принимает что угодно из 4-х байт (размер проверяется на этапе компиляции). Вторая принимает любые указатели и возвращает адрес, равный базе + смещение.
- Макросы кроме CALL_ убраны. Константы оформлены в виде именованных перечислений.
- EXTENDED стал kBridge, SAFE стал kSafeBridge. Антонимом к Direct ("прямой") является посреднический, а "расширенный" и "безопасный" вообще сбивают с толку.
- Аргументы, в которых предполагалось использование констант, стали типизированными.
- Символ указателя привязан к самим переменным. Позволяет избежать ошибок при парном объявлении и в целом распространённая практика. Вместо dword* x используется dword *x.
- Ряд inline процедур стали обычными. Они объявлены в стиле CDECL с переменным количеством аргументов и используют прямую адресную арифметику для получения указателя на аргументы. Такая вещь определённо не встраивается толком.
- NULL => nullptr
- Исправлена весьма странная функция получения указателя самого патчера. Во-первых, функция была встроенной (inline), но содержала среднего размера тело. Во-вторых, любой вызов после первого должен был без особого смысла возвращать NULL. Теперь функция стала обычной. Если есть запомненный указатель на патчер, то он возвращается немедленно. Иначе происходит загрузка DLL и т.д. nullptr возвращается только при ошибке.
- Код оформлен по границе в 100 символов.
- char* => const char*
- Ряд мелких, косметических и оформительных изменений.
06.01.2013, 03:10
ППЦ, чувствую себя магом.
Всё без макросов )))
Code:
template<typename T> struct to_dword
{
typedef dword type;
};
template
<
typename RetType,
kCallConv call_conv,
typename Addr,
typename... Args
>
inline RetType call(Addr addr, Args... args)
{
static_assert
(
(call_conv == kStdcall) ||
(call_conv == kThiscall) ||
(call_conv == kFastcall) ||
(call_conv == kCdecl),
"Unknown calling convention!"
);
switch(call_conv)
{
case kStdcall:
{
typedef RetType (__stdcall *func)(typename to_dword<Args>::type...);
return ((func) addr)((dword) args...);
break;
}
case kThiscall:
{
typedef RetType (__thiscall *func)(typename to_dword<Args>::type...);
return ((func) addr)((dword) args...);
break;
}
case kFastcall:
{
typedef RetType (__fastcall *func)(typename to_dword<Args>::type...);
return ((func) addr)((dword) args...);
break;
}
case kCdecl:
{
typedef RetType (__cdecl *func)(typename to_dword<Args>::type...);
return ((func) addr)((dword) args...);
break;
}
default:
{
return RetType();
}
}
}
Code:
patching::call<HMODULE, patching::kCdecl>(0x887668, L"Hello", L"World");
Code:
MOV [DWORD ESP+4],60103086
MOV [DWORD ESP],60103092
MOV EAX,887668
CALL NEAR EAX
Всё без макросов )))
09.01.2013, 12:59
(05.01.2013 00:05)Berserker Wrote: [ -> ]Антонимом к Direct ("прямой") является посреднический, а "расширенный" и "безопасный" вообще сбивают с толку.Relative ("относительный") же!
09.01.2013, 18:11
В контексте функций-перехватчиков, перехват либо прямой, либо через посредника.
28.06.2013, 14:16
Меня в Делфийском SDK смущает строчка:
Сложение строки с символом даёт временную строку в куче, которая уничтожается по завершению вычисления выражения. В итоге сохраняется указатель на опасный участок памяти.
Правильнее, наверное, будет оставить строку как есть.
Code:
vtString: dword_args[i] := _dword_(PAnsiChar(AnsiString(VString^ + #0)));
Правильнее, наверное, будет оставить строку как есть.
28.06.2013, 15:21
Quote:// заранее объявлены переменные _P и _PI для использования во всех модулях пректа
02.07.2013, 19:50
Методы GetOriginalFunc, GetReturnAddress не потокобезопасны.
В Делфийском SDK не потокобезопасен Call (глобальный массив аргументов).
В Делфийском SDK не потокобезопасен Call (глобальный массив аргументов).
16.08.2013, 09:06
Bersy Wrote:.hpp]ISO C++11 переработанный вариант заголовочного файла патчерассылка, помоему, с самого начала мертвой была, ну или пару дней продержалась, так и не смог скачать посмотреть. Вот пишу об этом только сейчас.
насчет DIRECT_ и EXTENDED_
c DIRECT_ - все понятно.
а в EXTENDED_ - основной смысл не в том что мы функцию через мост вызываем, а в том что из тела функции можем получить аргументом указатель на экземпляр хука. В этом и расширенность хука.
А то что эта расширенность невозможна без моста, так это побочный эффект. Вот такая логика у меня была.
SAFE_ назван мной так для краткости, по моей логике должен называться SAFE_EXTENDED_ а еще правильнее WOG_SAFE_EXTENDED ))
Quote:ППЦ, чувствую себя магом.к сожалению пишу в MS VS 2008, а в ней не поддерживается ISO C++ 11
...
Всё без макросов )))
в полной мере оценить красоту решения не могу.
Bersy Wrote:Меня в Делфийском SDK смущает строчка:
Сложение строки с символом даёт временную строку в куче, которая уничтожается по завершению вычисления выражения. В итоге сохраняется указатель на опасный участок памяти.Code:
vtString: dword_args[i] := _dword_(PAnsiChar(AnsiString(VString^ + #0)));
Правильнее, наверное, будет оставить строку как есть.
Quote:В Делфийском SDK не потокобезопасен Call (глобальный массив аргументов).Вы уж простите меня, но мой опыт работы с паскалем составлен из 3х этапов: 10класс школы, перевод исходников Хота на C++, написание SDK для патчера. Здесь лучше заняться исправлением улучшением и оптимизацией, опытному паскалисту/делфисту.
Bersy Wrote:Методы GetOriginalFunc, GetReturnAddress не потокобезопасны.тогда получаются непотокобезопасны
методы Apply, ApplyInsert и Undo (у Patch/LoHook/HiHook)
т.к. может случится так что когда один поток будет стирать патч, другой будет ставить в это же место (а ставя он читает 'старый' код)
и вообще в это время может до этого места дойти выполнение модифицируемой программы.
Потокобезопасностью никогда не занимался.
Поможет ли создание одной единственной критической секции для всего патчера, и вход в нее когда пишем в код и в default_func???
если я правильно понял проблему....
22.08.2013, 21:02
В LowHook`ах следует сделать pushf после сохранения всех регистров - тогда внутри хука можно будет свободно работать с c->esp. Сейчас же это невозможно, т. к. он меняется до хука и используется после.
05.09.2013, 21:11
Quote:Поможет ли создание одной единственной критической секции для всего патчера, и вход в нее когда пишем в код и в default_func???Думаю, не стоит. Пусть пользователи сами оборачивают.
если я правильно понял проблему...
Залил два своих файла:
http://wikisend.com/download/439718/Patcher.rar
25.09.2013, 19:27
Ужаснулся, глянув в код низкоуровневого перехватчика. Регистры не в стеке сохраняются и передаются, а в глобальной памяти. Это значит, что рекурсивный вызов перезатрёт их подчистую!
Spoiler (Click to View)
Code:
MOV [DWORD 4978BC8],EAX
MOV [DWORD 4978BCC],ECX
MOV [DWORD 4978BD0],EDX
MOV [DWORD 4978BD4],EBX
MOV [DWORD 4978BD8],ESP
MOV [DWORD 4978BDC],EBP
MOV [DWORD 4978BE0],ESI
MOV [DWORD 4978BE4],EDI
MOV EAX,74C6FC
MOV [DWORD 4978BE8],EAX
PUSH 4978BC8
PUSH 3BB4B40
CALL era.039237E8
CMP EAX,1
MOV EAX,[DWORD 4978BC8]
MOV ECX,[DWORD 4978BCC]
MOV EDX,[DWORD 4978BD0]
MOV EBX,[DWORD 4978BD4]
MOV ESP,[DWORD 4978BD8]
MOV EBP,[DWORD 4978BDC]
MOV ESI,[DWORD 4978BE0]
MOV EDI,[DWORD 4978BE4]
JNZ L028
POPFD
PUSHFD
POPFD
CMP [DWORD 2771934],1
JMP NEAR [DWORD 4978BE8]
L028:
POPFD
PUSHFD
POPFD
JMP NEAR [DWORD 4978BE8]