Комментарии 10
Парсить файл /proc/self/maps и доставать оттуда информацию о занятых регионах.
И это не будет работать во FreeBSD
чтобы работало на всех unix-like системах.
Так unix-like или все таки linux ?
Благодарю за внимательность! Обновил парсинг в библиотеке под FreeBSD
Так unix-like или все таки linux ?
На момент написания, казалось что оно одинаковое для всех unix-like систем. Оказывается у Linux свое, у FreeBSD свое.
Спасибо за статью. Вспомнил молодость при прочтении, первые шаги с библиотекой AdvApiHook от Ms-Rem, открывшей тогда дорогу в мир хуков )
За упорство конечно плюс! Но над интерфейсом либы кажется стоит еще поработать. У меня есть большой опыт пользования всяких разных либ и фреймворков для хукинга, но глядя на примеры в гитхабе, волосы начинают шевелиться даже там где их нет.
Передавать в обработчик хука какие то лишние параметры? Странная идея. Тем более, что, обработчик один, стало быть указатель на обьект будет всегда один и тот же. Смысл его передавать?
Что бы не приходилось пересобирать инструкции в трамплине и суспендить потоки, лучше использовать Hot Patching в Windows, он для этого и был создан.
Передавать в обработчик хука какие то лишние параметры? Странная идея. Тем более, что, обработчик один, стало быть указатель на обьект будет всегда один и тот же. Смысл его передавать?
Вроде в самом начале статьи же про глобальное состояние...
Что бы не приходилось пересобирать инструкции в трамплине и суспендить потоки, лучше использовать Hot Patching в Windows, он для этого и был создан.
Ага. А что делать с кодом, к которому нет доступа, и перекомпилировать с включенным Hot Patching нет возможности?
И даже если так. Писать отдельный велосипед для винды, и отдельный для unix'ов? Мне кажется все же проще один общий велосипед написать, чем два отдельных, зависящих от настроек компиляции кода
Вроде в самом начале статьи же про глобальное состояние..
Это костыль.
А что делать с кодом, к которому нет доступа, и перекомпилировать с включенным Hot Patching нет возможности?
Не совсем понимаю о чем вы. Hot pathing присутствует во всех системных библиотеках Windows. Ничего не надо перекомпилировать.
Это костыль.
Почему же? Позволяет например, абстрагироваться от конечной "хукаемой" функции, и написать шаблонную лямбду, которая решит все сама. Как пример, хук на все LoadLibrary. Пример конечно абстрактный, можно было-бы полезть в недра kernel32.dll, и найти там функцию LdrLoadDll, и поставить хук на нее, но все же. На практике даже такие функции иногда полезны.
auto dispatch_load_calls = [](const auto& hook, auto str_ptr, auto&&... args) {
auto in_cef_module = [](std::uintptr_t addr) {
auto dll = reinterpret_cast<std::uintptr_t>(GetModuleHandleA("libcef.dll"));
auto ntheader = reinterpret_cast<IMAGE_NT_HEADERS*>(
dll + reinterpret_cast<IMAGE_DOS_HEADER*>(dll)->e_lfanew);
if (dll < addr && addr < dll + ntheader->OptionalHeader.SizeOfImage) {
return true;
}
return false;
};
if (in_cef_module(hook.get_return_address())) {
constexpr bool is_single_byte = std::is_same_v<decltype(str_ptr), LPCSTR>;
using str_view = std::conditional_t<is_single_byte, std::string_view, std::wstring_view>;
using str = std::conditional_t<is_single_byte, std::string, std::wstring>;
constexpr auto cef_directory = names_choose<is_single_byte>::prefix;
constexpr auto& names_array_ref = names_choose<is_single_byte>::value;
str_view load_name{str_ptr};
for (auto name : names_array_ref) {
if (load_name.find(name) != str_view::npos) {
str fname{cef_directory};
fname += name;
return hook.get_trampoline()(fname.c_str(), args...);
}
}
}
return hook.get_trampoline()(str_ptr, args...);
};
load_liba_hook.set_dest(reinterpret_cast<void*>(GetProcAddress(kernel32, "LoadLibraryA")));
load_libw_hook.set_dest(reinterpret_cast<void*>(GetProcAddress(kernel32, "LoadLibraryW")));
load_libexa_hook.set_dest(reinterpret_cast<void*>(GetProcAddress(kernel32, "LoadLibraryExA")));
load_libexw_hook.set_dest(reinterpret_cast<void*>(GetProcAddress(kernel32, "LoadLibraryExW")));
load_liba_hook.set_cb(dispatch_load_calls);
load_libw_hook.set_cb(dispatch_load_calls);
load_libexa_hook.set_cb(dispatch_load_calls);
load_libexw_hook.set_cb(dispatch_load_calls);
Если бы не было абстракции от глобального состояния, пришлось бы коллбэк под каждую функцию писать. Также уход от глобального состояния позволяет делать проект модульным, и внутри разных модулей использовать хуки на одну и ту же конечную функцию. Чего, например, нельзя сделать используя MinHook, или PolyHook
Не совсем понимаю о чем вы. Hot pathing присутствует во всех системных библиотеках Windows. Ничего не надо перекомпилировать.
Процитирую себя еще раз, и дополню:
Ага. А что делать с кодом, к которому нет доступа, и перекомпилировать с включенным Hot Patching нет возможности?И даже если так. Писать отдельный велосипед для винды, и отдельный для unix'ов? Мне кажется все же проще один общий велосипед написать, чем два отдельных, зависящих от настроек компиляции кода
Зачем писать разный код для выполнения одного и того же действия на разных платформах. Гораздо проще описать общий принцип, нет?
И все еще остается проблема с перехватами стороннего кода, вне стандартных библиотек Windows, или например на Linux. Или например мне захочется добавить функциональность к существующей функции игры(гейммоддинг). Игры с Hot Patching'ом никто не компилирует. Предлагаете сидеть с разбитым корытом, из-за того, что библиотека прикручена к функции Hot patching?
Также, не у всех системных библиотек и их функций есть HotPatching.
Как пример - d3d9.dll, а именно функция IDirect3DDevice9::Present.
Как написать свою кроссплатформенную библиотеку для хуков и не отстрелить себе ноги