PDA

Просмотр полной версии : ExceptionFilter [x32/x64]


SR_team
04.09.2021, 16:21
Это обертка над

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
#include
#include
class
SilentHooks
:
public
ExceptionFilter
{
#ifdef _WIN64
static
constexpr
auto
kMaxOpcodeLength
=
20
;
#else
static
constexpr
auto
kMaxOpcodeLength
=
10
;
#endif
std
::
map
>
>
hooks_
;
public
:
void
addHook
(
size_t addr
,
const
std
::
function

&
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
void
SilentHooks
::
addHook
(
size_t addr
,
const
std
::
function

&
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

kin4stat
04.09.2021, 16:35
Разве eip не нужно смещать чтобы дальше выполнение пошло?

reenablehook возвращает page_guard, а eip на том же месте. Рекурсии не будет?

SR_team
04.09.2021, 17:13
Разве eip не нужно смещать чтобы дальше выполнение пошло?
reenablehook возвращает page_guard, а eip на том же месте. Рекурсии не будет?


его не нужно смещать, потому что надо выполнить инструкцию на которую он указывает

UPD: и второй пример говно - там надо страницы сравнивать и идти пошагово до выхода из нее