- 4,809
- 6,487
Это обертка над
Пример использования:
Требования: C++11 или выше
Код: https://gitlab.com/SR_team/ExceptionFilter
AddVectoredExceptionHandler
и RemoveVectoredExceptionHandler
, что бы засунуть обработчик не пойманных исключений внутрь класса.Пример использования:
C++:
class MyExceptionFilter : public ExceptionFilter {
protected:
long filter( _EXCEPTION_POINTERS *ep ) noexcept override{
// handle exception
return 0; // EXCEPTION_CONTINUE_SEARCH
}
};
Данный класс добавляет хуки на основе исключений. Такие хуки можно поставить туда, куда не впихиваются другие. Минус таких хуков - они очень медленно выполняются.
header:
#pragma once
#include "ExceptionFilter.h"
#include <map>
#include <vector>
#include <functional>
class SilentHooks : public ExceptionFilter {
#ifdef _WIN64
static constexpr auto kMaxOpcodeLength = 20;
#else
static constexpr auto kMaxOpcodeLength = 10;
#endif
std::map<size_t, std::vector<std::function<void( _EXCEPTION_POINTERS * )>>> hooks_;
public:
void addHook( size_t addr, const std::function<void( _EXCEPTION_POINTERS * )> &callback ) noexcept;
void removeHook( size_t addr ) noexcept;
bool reenableHook( size_t addr ) const noexcept;
static void changerRetAddr( _EXCEPTION_POINTERS *ep, size_t addr ) noexcept;
protected:
long filter( _EXCEPTION_POINTERS *ep ) noexcept override;
};
source:
#include "SilentHooks.h"
#include <windows.h>
void SilentHooks::addHook( size_t addr, const std::function<void( _EXCEPTION_POINTERS * )> &callback ) noexcept {
auto newHook = hooks_.find( addr ) == hooks_.end();
hooks_[addr].push_back( callback );
if ( newHook ) {
DWORD oldVP;
VirtualProtect( (void *)addr, 1, PAGE_EXECUTE_READ | PAGE_GUARD, &oldVP );
}
}
void SilentHooks::removeHook( size_t addr ) noexcept {
if ( hooks_.find( addr ) == hooks_.end() ) return;
while ( reenableHook( addr ) )
; // wait to hook exited
DWORD oldVP;
VirtualProtect( (void *)addr, 1, PAGE_EXECUTE_READ, &oldVP );
}
bool SilentHooks::reenableHook( size_t addr ) const noexcept {
if ( hooks_.find( addr ) == hooks_.end() ) return false;
DWORD oldVP;
VirtualProtect( (void *)addr, 1, PAGE_EXECUTE_READ | PAGE_GUARD, &oldVP );
return oldVP != ( PAGE_EXECUTE_READ | PAGE_GUARD );
}
void SilentHooks::changerRetAddr( _EXCEPTION_POINTERS *ep, size_t addr ) noexcept {
ep->ContextRecord->Eip = addr;
ep->ContextRecord->EFlags &= ~0x100;
}
long SilentHooks::filter( _EXCEPTION_POINTERS *ep ) noexcept {
if ( ep->ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION ) {
auto it = hooks_.find( (size_t)ep->ExceptionRecord->ExceptionAddress );
if ( it == hooks_.end() ) return 0;
DWORD oldVP;
VirtualProtect( ep->ExceptionRecord->ExceptionAddress, 1, PAGE_EXECUTE_READ, &oldVP );
ep->ContextRecord->EFlags |= 0x100; // step once
for ( auto &cb : it->second ) cb( ep ); // execute callbacks
return -1;
} else if ( ep->ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP ) {
bool fromHook = false;
for ( auto &&[addr, cb] : hooks_ ) {
if ( addr > (size_t)ep->ExceptionRecord->ExceptionAddress ) continue;
if ( !reenableHook( addr ) ) continue;
fromHook = true;
break;
}
if ( !fromHook ) return 0;
ep->ContextRecord->EFlags &= ~0x100; // run code
return -1;
}
return 0;
}
Требования: C++11 или выше
Код: https://gitlab.com/SR_team/ExceptionFilter