使 IAT 可写。
查看 simple.cpp
TimedSleepEx 通过 TrueSleepEx 函数指针调用真正的 SleepEx API。``` static DWORD (WINAPI * TrueSleepEx)(DWORD dwMilliseconds, BOOL bAlertable) = SleepEx;
DWORD WINAPI TimedSleepEx(DWORD dwMilliseconds, BOOL bAlertable) { ... DWORD ret = TrueSleepEx(dwMilliseconds, bAlertable); ... }
**_不要这样做 !_** 链接器已定义```
EXTERN_C PVOID __imp_SleepEx = SleepEx;
变量 ( 对于 x86,这将是 __imp__SleepEx@8,并且需要使用``` __pragma(comment(linker, "/alternatename:___imp_SleepEx=__imp__SleepEx@8"))
因此使用 ***__imp_SleepEx*** 而不是 ***TrueSleepEx***,并以通常且方便的方式直接调用 api。
任何导入的 api SomeApi 均通过 ***__imp_SomeApi***( 通过 ***__imp_load_SomeApi*** 延迟加载 )指针调用。使用它!
示例```
//EXTERN_C extern PVOID __imp_SleepEx;
DECLARE_T_HOOK(SleepEx, 8)
DWORD WINAPI hook_SleepEx( _In_ DWORD dwMilliseconds, _In_ BOOL bAlertable )
{
ULONG ret = SleepEx(dwMilliseconds, bAlertable);
DbgPrint("%s(%x, %x) = %x\n", __FUNCTION__, dwMilliseconds, bAlertable, ret);
return ret;
}
void DetoursDemo()
{
DBG_PRINT_ON();
if (0 <= TrInit())
{
ThreadInfo* pti;
SuspendAll(&pti);
DbgPrint("before: SleepEx = 0x%p\n", SleepEx);
TrHook(&__imp_SleepEx, hook_SleepEx, pti);
DbgPrint("after: SleepEx = 0x%p\n", SleepEx);
ResumeAndFree(pti);
union {
PVOID pv;
DWORD (WINAPI * fn_SleepEx)( _In_ DWORD dwMilliseconds, _In_ BOOL bAlertable );
};
if (pv = GetProcAddress(GetModuleHandleW(L"kernel32"), "SleepEx"))
{
if (QueueUserAPC((PAPCFUNC)OutputDebugStringA, GetCurrentThread(), (ULONG_PTR)"asynchronous procedure call...\n"))
{
fn_SleepEx(INFINITE, TRUE);
}
}
}
}
典型的调试输出:``` NT::ThreadInfo::ThreadInfo<000002196427D6A0>(0000000000000814) NT::ThreadInfo::ThreadInfo<000002196427DBC0>(0000000000000128) NT::ThreadInfo::ThreadInfo<000002196427E0E0>(00000000000023D0) before: SleepEx = 0x00007FFED3DB06B0 0x00007FFED3DB06B0 -> 0x00007FF78BEB06C0 -> 0x00007FFE5394FFB8 [0x00007FFE5394FF98] after: SleepEx = 0x00007FFE5394FFB8 NT::ThreadInfo::~ThreadInfo<000002196427E0E0>(00000000000023D0) NT::ThreadInfo::~ThreadInfo<000002196427DBC0>(0000000000000128) NT::ThreadInfo::~ThreadInfo<000002196427D6A0>(0000000000000814) asynchronous procedure call... NT::hook_SleepEx(ffffffff, 1) = c0
另一个示例,使用 unhook:```
DWORD WINAPI hook_SleepEx( _In_ DWORD dwMilliseconds, _In_ BOOL bAlertable )
{
// don't use any [TrueSleepEx](https://github.com/microsoft/Detours/blob/main/samples/simple/simple.cpp#L23) !!
ULONG ret = SleepEx(dwMilliseconds, bAlertable);
DbgPrint("%s(%x, %x) = %x\n", __FUNCTION__, dwMilliseconds, bAlertable, ret);
return ret;
}
int
WINAPI
hook_MessageBoxW(
_In_opt_ HWND hWnd,
_In_opt_ PCWSTR lpText,
_In_opt_ PCWSTR lpCaption,
_In_ UINT uType)
{
// don't use any [Real_MessageBoxW](https://raw.githubusercontent.com/microsoft/Detours/main/samples/traceapi/_win32.cpp) !!
int ret = MessageBoxW(hWnd, lpText, __FUNCTIONW__, uType);
DbgPrint("%s(\"%S\", \"%S\") = %x\n", __FUNCTION__, lpText, lpCaption, ret);
return ret;
}
DECLARE_T_HOOK(SleepEx, 8)
DECLARE_T_HOOK(MessageBoxW, 16)
T_HOOKS_BEGIN(gHooks)
T_HOOK(SleepEx),
T_HOOK(MessageBoxW),
T_HOOKS_END()
void DemoApiCalls()
{
union {
PVOID pv;
DWORD (WINAPI * fn_SleepEx)( _In_ DWORD dwMilliseconds, _In_ BOOL bAlertable );
int (WINAPI * fn_MessageBoxW)( _In_opt_ HWND hWnd, _In_opt_ LPCWSTR lpText, _In_opt_ LPCWSTR lpCaption, _In_ UINT uType);
};
if (pv = GetProcAddress(GetModuleHandleW(L"kernel32"), "SleepEx"))
{
if (QueueUserAPC((PAPCFUNC)OutputDebugStringA, GetCurrentThread(), (ULONG_PTR)"asynchronous procedure call...\n"))
{
fn_SleepEx(INFINITE, TRUE);
}
}
if (pv = GetProcAddress(GetModuleHandleW(L"user32"), "MessageBoxW"))
{
fn_MessageBoxW(0, L"[some text]", 0, MB_ICONINFORMATION);
}
}
void DetoursDemo()
{
DBG_PRINT_ON();
if (0 <= TrInit())
{
ThreadInfo* pti;
SuspendAll(&pti);
TrHook(gHooks, _countof(gHooks), pti);
ResumeAndFree(pti);
DemoApiCalls();
SuspendAll(&pti);
TrUnHook(gHooks, _countof(gHooks), pti);
ResumeAndFree(pti);
DemoApiCalls();
}
}
NT::ThreadInfo::ThreadInfo<0000026DEA5AD6D0>(00000000000017E8)
NT::ThreadInfo::ThreadInfo<0000026DEA5ADBF0>(00000000000013E0)
NT::ThreadInfo::ThreadInfo<0000026DEA5AE110>(00000000000002D4)
0x00007FFED3DB06B0 -> 0x00007FF693E10790 -> 0x00007FFE5394FFB8 [0x00007FFE5394FF98]
0x00007FFED41CA160 -> 0x00007FF693E10720 -> 0x00007FFE5430FFB8 [0x00007FFE5430FF98]
NT::ThreadInfo::~ThreadInfo<0000026DEA5AE110>(00000000000002D4)
NT::ThreadInfo::~ThreadInfo<0000026DEA5ADBF0>(00000000000013E0)
NT::ThreadInfo::~ThreadInfo<0000026DEA5AD6D0>(00000000000017E8)
asynchronous procedure call...
NT::hook_SleepEx(ffffffff, 1) = c0
---------------------------
NT::hook_MessageBoxW
---------------------------
[some text]
---------------------------
OK
---------------------------
NT::hook_MessageBoxW("[some text]", "(null)") = 1
NT::ThreadInfo::ThreadInfo<0000026DEA5C7370>(0000000000001A84)
NT::ThreadInfo::ThreadInfo<0000026DEA5C7890>(0000000000000D1C)
NT::ThreadInfo::ThreadInfo<0000026DEA5E2950>(00000000000020C8)
NT::ThreadInfo::ThreadInfo<0000026DEA5E2E70>(0000000000000D18)
NT::ThreadInfo::ThreadInfo<0000026DEA5E3390>(0000000000001974)
NT::ThreadInfo::ThreadInfo<0000026DEA5DD3D0>(00000000000023E0)
NT::ThreadInfo::ThreadInfo<0000026DEA5DD8F0>(0000000000001C58)
NT::ThreadInfo::~ThreadInfo<0000026DEA5DD8F0>(0000000000001C58)
NT::ThreadInfo::~ThreadInfo<0000026DEA5DD3D0>(00000000000023E0)
NT::ThreadInfo::~ThreadInfo<0000026DEA5E3390>(0000000000001974)
NT::ThreadInfo::~ThreadInfo<0000026DEA5E2E70>(0000000000000D18)
NT::ThreadInfo::~ThreadInfo<0000026DEA5E2950>(00000000000020C8)
NT::ThreadInfo::~ThreadInfo<0000026DEA5C7890>(0000000000000D1C)
NT::ThreadInfo::~ThreadInfo<0000026DEA5C7370>(0000000000001A84)
asynchronous procedure call...
---------------------------
Error
---------------------------
[some text]
---------------------------
OK
---------------------------
启用 / 禁用调试输出(默认情况下禁用)
通过 NtGetNextThread 枚举进程中的线程 检查是否为当前线程(ZwQueryInformationThread(ThreadBasicInformation)) 挂起线程 ZwSuspendThread 保存其上下文 ZwGetContextThread 将线程信息(句柄/上下文)链接到列表
遍历线程列表(pti) 恢复线程 关闭其句柄 释放内存
{ T_HOOK_ENTRY entry = { p__imp, hook }; return TrHook(&entry, 1, pti); }
简化版本,用于 Hook 单个 API,且无需解除 Hook 时使用
与 [DetourAttach](https://github.com/microsoft/Detours/wiki/DetourAttach) 几乎相同
唯一区别 - TrHook 仅执行实际补丁,而 DetourAttach - 在 DetourTransactionCommit 之后
*****************************************************************************************************
###### void NTAPI TrHook(_In_ T_HOOK_ENTRY* entry, _In_ ULONG n, _In_opt_ ThreadInfo* pti = 0);
*****************************************************************************************************
尝试在已修补区域的 -/+ 2GB 范围内分配 trampoline(在 32 位模式下任何地址都可以)
通过在其开头设置 JMP Hook 来 Hook API,并将原始指令保存在 trampoline 中
遍历线程列表(可选),如果需要(Pc 在 JMP 中)- 调整线程上下文
存在几种情况:```
////////////////////////////////////////////////////////////////////////////////////////////////////////
// typical case:
-------------------------------------------------------------------------
before:
-------------------------------------------------------------------------
EXTERN_C PVOID __imp_RtlDispatchAPC = RtlDispatchAPC;
RtlDispatchAPC:
00007FFAB20AF6D0 mov r11,rsp
00007FFAB20AF6D3 mov qword ptr [r11+8],rbx
00007FFAB20AF6D7 mov qword ptr [r11+10h],rsi
--------------------------------------------------------------------------
after: TrHook(&__imp_RtlDispatchAPC, hook_RtlDispatchAPC);
--------------------------------------------------------------------------
RtlDispatchAPC:
00007FFB876AF6D0 jmp hook_RtlDispatchAPC
00007FFB876AF6D7 mov qword ptr [r11+10h],rsi
trampoline:
00007FFA3225FFB8 mov r11,rsp
00007FFA3225FFBB mov qword ptr [r11+8],rbx
00007FFA3225FFBF jmp RtlDispatchAPC + 7 (7FFB876AF6D7h)
__imp_RtlDispatchAPC = trampoline;
////////////////////////////////////////////////////////////////////////////////////////////////////////
// x86 mov edi,edi:
#pragma comment(linker, "/alternatename:___imp_RtlActivateActivationContextUnsafeFast=__imp_@RtlActivateActivationContextUnsafeFast@8")
EXTERN_C PVOID __imp_RtlActivateActivationContextUnsafeFast = RtlActivateActivationContextUnsafeFast;
771F6FBB int 3
771F6FBC int 3
771F6FBD int 3
771F6FBE int 3
771F6FBF int 3
RtlActivateActivationContextUnsafeFast:
771F6FC0 mov edi,edi
771F6FC2 push ebp
--------------------------------------------------------------------------
after: TrHook(&__imp_RtlActivateActivationContextUnsafeFast, hook_RtlActivateActivationContextUnsafeFast);
--------------------------------------------------------------------------
__imp_RtlActivateActivationContextUnsafeFast = 771F6FC2 ( RtlActivateActivationContextUnsafeFast + 2 )
771F6FBB jmp hook_RtlActivateActivationContextUnsafeFast
RtlActivateActivationContextUnsafeFast:
771F6FC0 jmp 771F6FBB
771F6FC2 push ebp
////////////////////////////////////////////////////////////////////////////////////////////////////////
// case 1: data access relocated
-------------------------------------------------------------------------
before:
-------------------------------------------------------------------------
EXTERN_C PVOID __imp_CsrFreeCaptureBuffer = CsrFreeCaptureBuffer;
CsrFreeCaptureBuffer:
00007FFAB20A4980 sub rsp,28h
00007FFAB20A4984 cmp byte ptr [7FFAB21B43ECh],0
00007FFAB20A498B jne CsrFreeCaptureBuffer+1Eh (7FFAB20A499Eh)
--------------------------------------------------------------------------
after: TrHook(&__imp_CsrFreeCaptureBuffer, hook_CsrFreeCaptureBuffer);
--------------------------------------------------------------------------
CsrFreeCaptureBuffer:
00007FFAB20A4980 jmp hook_CsrFreeCaptureBuffer
00007FFAB20A498B jne CsrFreeCaptureBuffer+1Eh (7FFAB20A499Eh)
trampoline:
00007FFA3225F878 sub rsp,28h
00007FFA3225F87C cmp byte ptr [7FFAB21B43ECh],0
00007FFA3225F883 jmp CsrFreeCaptureBuffer+0Bh (7FFAB20A498Bh)
__imp_CsrFreeCaptureBuffer = trampoline;
////////////////////////////////////////////////////////////////////////////////////////////////////////
// case 7: - Jcc rel8 (2 bytes) extended to Jcc rel32 (6 bytes) inside trampoline
-------------------------------------------------------------------------
before:
-------------------------------------------------------------------------
EXTERN_C PVOID __imp_CsrFreeCaptureBuffer = CsrAllocateMessagePointer;
CsrAllocateMessagePointer:
00007FFAB20A46A0 test edx,edx
00007FFAB20A46A2 je CsrAllocateMessagePointer+2Eh (7FFAB20A46CEh)
00007FFAB20A46A4 mov rax,qword ptr [rcx+18h]
00007FFAB20A46A8 mov qword ptr [r8],rax
--------------------------------------------------------------------------
after: TrHook(&__imp_CsrAllocateMessagePointer, hook_CsrAllocateMessagePointer);
--------------------------------------------------------------------------
CsrAllocateMessagePointer:
00007FFAB20A46A0 jmp hook_CsrAllocateMessagePointer
00007FFAB20A46A8 mov qword ptr [r8],rax
trampoline:
00007FFA3225FA38 test edx,edx
00007FFA3225FA3A je CsrAllocateMessagePointer+2Eh (7FFAB20A46CEh)
00007FFA3225FA40 mov rax,qword ptr [rcx+18h]
00007FFA3225FA44 jmp CsrAllocateMessagePointer+8 (7FFAB20A46A8h)
__imp_CsrAllocateMessagePointer = trampoline;
////////////////////////////////////////////////////////////////////////////////////////////////////////
// case 8: function too small ( < 5 bytes )
-------------------------------------------------------------------------
before:
-------------------------------------------------------------------------
EXTERN_C PVOID __imp_CsrIdentifyAlertableThread = CsrIdentifyAlertableThread;
CsrIdentifyAlertableThread:
00007FFAB20BE480 xor eax,eax
00007FFAB20BE482 ret
00007FFAB20BE483 int 3
00007FFAB20BE484 int 3
00007FFAB20BE485 int 3
--------------------------------------------------------------------------
after: TrHook(&__imp_CsrIdentifyAlertableThread, hook_CsrIdentifyAlertableThread);
--------------------------------------------------------------------------
CsrIdentifyAlertableThread:
00007FFAB20BE480 jmp hook_CsrIdentifyAlertableThread
trampoline:
00007FFA3225F7F8 xor eax,eax
00007FFA3225F7FA ret
__imp_CsrIdentifyAlertableThread = trampoline;
note - no JMP at the end of trampoline !
////////////////////////////////////////////////////////////////////////////////////////////////////////
// case JMP_rel32: function begin with 5 bytes relative JMP
-------------------------------------------------------------------------
before:
-------------------------------------------------------------------------
EXTERN_C PVOID __imp_DbgQueryDebugFilterState = DbgQueryDebugFilterState;
DbgQueryDebugFilterState:
00007FFAB211B160 jmp NtQueryDebugFilterState (7FFAB20D1720h)
--------------------------------------------------------------------------
after: TrHook(&__imp_DbgQueryDebugFilterState, hook_DbgQueryDebugFilterState);
--------------------------------------------------------------------------
DbgQueryDebugFilterState:
00007FFAB211B160 jmp hook_DbgQueryDebugFilterState(7FFAB20D1720h)
__imp_DbgQueryDebugFilterState = NtQueryDebugFilterState;
no trampoline used here ! __imp_DbgQueryDebugFilterState redirected from DbgQueryDebugFilterState to NtQueryDebugFilterState
////////////////////////////////////////////////////////////////////////////////////////////////////////
// case 2: CALL/JMP/Jcc rel32 relocated
-------------------------------------------------------------------------
before:
-------------------------------------------------------------------------
EXTERN_C PVOID __imp_DbgQueryDebugFilterState = DbgUiConvertStateChangeStructure;
DbgUiConvertStateChangeStructure:
00007FFAB21080E0 xor r8d,r8d
00007FFAB21080E3 jmp DbgUiConvertStateChangeStructureEx+10h (7FFAB2108100h)
--------------------------------------------------------------------------
after: TrHook(&__imp_DbgUiConvertStateChangeStructure, hook_DbgUiConvertStateChangeStructure);
--------------------------------------------------------------------------
DbgUiConvertStateChangeStructure:
00007FFAB20A46A0 jmp hook_DbgUiConvertStateChangeStructure
trampoline:
00007FFA3225F4F8 xor r8d,r8d
00007FFA3225F4FB jmp DbgUiConvertStateChangeStructureEx+10h (7FFAB2108100h)
__imp_DbgUiConvertStateChangeStructure = trampoline;
////////////////////////////////////////////////////////////////////////////////////////////////////////
for x86:
-------------------------------------------------------------------------
before:
-------------------------------------------------------------------------
EXTERN_C PVOID __imp_RtlGetActiveConsoleId = RtlGetActiveConsoleId;
RtlGetActiveConsoleId:
7721FDA0 call RtlGetCurrentServiceSessionId (771FF310h)
7721FDA5 test eax,eax
--------------------------------------------------------------------------
after: TrHook(&__imp_RtlGetActiveConsoleId, hook_RtlGetActiveConsoleId);
--------------------------------------------------------------------------
RtlGetActiveConsoleId:
7721FDA0 jmp hook_RtlGetActiveConsoleId
7721FDA5 test eax,eax
trampoline:
02902A94 call RtlGetCurrentServiceSessionId (771FF310h)
02902A99 jmp RtlGetActiveConsoleId+5 (7721FDA5h)
__imp_RtlGetActiveConsoleId = trampoline;
////////////////////////////////////////////////////////////////////////////////////////////////////////
// case 9: Too few instructions !
RtlIsZeroMemory:
7FFB85F5C130 xor eax,eax
7FFB85F5C132 jmp 00007FFB85F5C143 ↓
7FFB85F5C134 test rdx,rdx
7FFB85F5C137 je 00007FFB85F5C157 ↓
7FFB85F5C139 cmp byte ptr [rcx],al
7FFB85F5C13B jne 00007FFB85F5C171 ↓
7FFB85F5C13D inc rcx
7FFB85F5C140 dec rdx
7FFB85F5C143 test cl,7
7FFB85F5C146 jne 00007FFB85F5C134 ↑
7FFB85F5C148 jmp 00007FFB85F5C157 ↓
7FFB85F5C14A cmp qword ptr [rcx],rax
7FFB85F5C14D jne 00007FFB85F5C171 ↓
7FFB85F5C14F add rcx,8
7FFB85F5C153 sub rdx,8
7FFB85F5C157 cmp rdx,8
7FFB85F5C15B jae 00007FFB85F5C14A ↑
7FFB85F5C15D test rdx,rdx
7FFB85F5C160 je 00007FFB85F5C16F ↓
7FFB85F5C162 cmp byte ptr [rcx],al
7FFB85F5C164 jne 00007FFB85F5C171 ↓
7FFB85F5C166 inc rcx
7FFB85F5C169 sub rdx,1
7FFB85F5C16D jne 00007FFB85F5C162 ↑
7FFB85F5C16F mov al,1
7FFB85F5C171 ret
we can not hook such api - only 4 bytes exist
note
7FFB85F5C146 jne 00007FFB85F5C134 ↑
if we set JMP in [7FFB85F5C130, 7FFB85F5C135) - this will be jmp to instruction body
////////////////////////////////////////////////////////////////////////////////////////////////////////
// skip import jump
-------------------------------------------------------------------------
before:
-------------------------------------------------------------------------
EXTERN_C PVOID __imp_NtdllDefWindowProc_W = NtdllDefWindowProc_W;
NtdllDefWindowProc_W:
7FFAB20CEAD0 jmp qword ptr [DefWindowProcW(7FFF55F9A760)]
DefWindowProcW
7FFF55F9A760 mov rax,rsp
7FFF55F9A763 mov qword ptr [rax+8],rbx
7FFF55F9A767 mov qword ptr [rax+10h],rsi
--------------------------------------------------------------------------
after: TrHook(&__imp_NtdllDefWindowProc_W, hook_NtdllDefWindowProc_W);
--------------------------------------------------------------------------
NtdllDefWindowProc_W:
7FFAB20CEAD0 jmp qword ptr [DefWindowProcW(7FFF55F9A760)]
DefWindowProcW
7FFF55F9A760 jmp hook_NtdllDefWindowProc_W
7FFF55F9A767 mov qword ptr [rax+10h],rsi
trampoline:
7FFED78555F8 mov rax,rsp
7FFED78555FB mov qword ptr [rax+8],rbx
7FFED78555FF jmp DefWindowProcW + 7 (7FFF55F9A767h)
__imp_NtdllDefWindowProc_W = trampoline;
so we set hook on DefWindowProcW instead on NtdllDefWindowProc_W
////////////////////////////////////////////////////////////////////////////////////////////////////////
// case JMP_rel8: function begin with short JMP
-------------------------------------------------------------------------
before:
-------------------------------------------------------------------------
EXTERN_C PVOID __imp_uaw_wcschr = uaw_wcschr;
uaw_wcschr:
7FFF562C6A10 jmp uaw_wcschr+0Bh (7FFF562C6A1B)
7FFF562C6A12 test ax,ax
7FFF562C6A15 je uaw_wcschr+18h (7FFF562C6A28)
7FFF562C6A17 add rcx,2
7FFF562C6A1B movzx eax,word ptr [rcx]
7FFF562C6A1E cmp ax,dx
7FFF562C6A21 jne uaw_wcschr+2 (7FFF562C6A12)
7FFF562C6A23 mov rax,rcx
7FFF562C6A26 ret
7FFF562C6A27 int 3
7FFF562C6A28 xor eax,eax
7FFF562C6A2A ret
--------------------------------------------------------------------------
after: TrHook(&__imp_uaw_wcschr, hook_uaw_wcschr);
--------------------------------------------------------------------------
uaw_wcschr:
7FFF562C6A10 jmp uaw_wcschr+0Bh (7FFF562C6A1B)
7FFF562C6A12 test ax,ax
7FFF562C6A15 je uaw_wcschr+18h (7FFF562C6A28)
7FFF562C6A17 add rcx,2
7FFF562C6A1B jmp hook_uaw_wcschr
7FFF562C6A21 jne uaw_wcschr+2 (7FFF562C6A12)
7FFF562C6A23 mov rax,rcx
7FFF562C6A26 ret
7FFF562C6A27 int 3
7FFF562C6A28 xor eax,eax
7FFF562C6A2A ret
trampoline:
FFED786A338 movzx eax,word ptr [rcx]
FFED786A33B cmp ax,dx
FFED786A33E jmp uaw_wcschr+11h (7FFF562C6A21)
__imp_uaw_wcschr = trampoline;
usual all such functions ( with short JMP at begin) consist from do-while optimized loop
( uaw_wcschr, SHSearchMapInt, FixSlashesAndColonW)
problem here - that hook function can be recursive called in loop
example of uaw_wcschr hook:
PUWSTR
__cdecl
hook_uaw_wcschr(
_In_ PCUWSTR String,
_In_ WCHAR Character
)
{
DbgPrint("%p: %p> uaw_wcschr(\"%S\", '%c')...\n", _AddressOfReturnAddress(), _ReturnAddress(), String, Character);
PUWSTR pw = uaw_wcschr(String, Character);
DbgPrint("%p: %p> uaw_wcschr(\"%S\", '%c') = \"%S\"\n", _AddressOfReturnAddress(), _ReturnAddress(), String, Character, pw);
return pw;
}
TrInit();
TrHook(&__imp_uaw_wcschr, hook_uaw_wcschr);
uaw_wcschr(L"123*567", '*');
and debug output:
000000459910F978: 00007FF6E5FEFCAB> uaw_wcschr("23*567", '*')...
000000459910F928: 00007FF6E5FF086E> uaw_wcschr("3*567", '*')...
000000459910F8D8: 00007FF6E5FF086E> uaw_wcschr("*567", '*')...
000000459910F8D8: 00007FF6E5FF086E> uaw_wcschr("*567", '*') = "*567"
000000459910F928: 00007FF6E5FF086E> uaw_wcschr("3*567", '*') = "*567"
000000459910F978: 00007FF6E5FEFCAB> uaw_wcschr("23*567", '*') = "*567"
////////////////////////////////////////////////////////////////////////////////////////////////////////
// "micro" jmp
case when JMP/Jcc/LOOP/JRCX point to first 5 bytes offunction ( where JMP must be placed )
probably only hypothetical case, but for correct handle, require many extra code.
before:
someapi:
7FF64B5096CF jrcxz someapi+4 (7FF64B5096D3)
7FF64B5096D1 jnp someapi+6 (7FF64B5096D5)
7FF64B5096D3 loop someapi (7FF64B5096CF)
7FF64B5096D5 ...
after:
someapi:
7FF64B5096CF jmp NT::hook_someapi (7FF64B510F14h)
7FF64B5096D5 ...
trampoline:
7FF5CB53FFB8 jrcxz 7FF5CB53FFC0
7FF5CB53FFBA jnp someapi+6 (7FF64B5096D5)
7FF5CB53FFC0 loop 7FF5CB53FFB8
7FF5CB53FFC2 jmp someapi+6 (7FF64B5096D5)
在被 hook 的 API 开头,如果可能,我们设置一个直接 JMP 到 hook,或者 JMP 到 trampoline 内的间接 JMP [hook_someapi] (如果 someapi 和 hook_someapi 之间的距离超过 2GB)
因此,hook 之后将会是或``` someapi: jmp hook_someapi ; JMP rel32
或```
someapi:
jmp tramp ; JMP rel32
tramp:
jmp [hook_someapi] ; JMP [m64]
在 trampoline 的末尾通常会有一个相对 JMP,跳转到函数体中 JMP 之后的代码 除了情况 8 - 当被挂钩的函数太小时(ret 或 JMP 指令已经在 trampoline 中)