9月都快結束了,之前一直忙到寫自己的東西加上上班。基本沒有時間研究下彙編和C C++方面的感興趣的東西。再怎麼說嘛,9月還是得寫一篇撒,以後每月至少一篇吧。給自己定了,希望大家監督。嘿嘿!
這篇文章就來談談平常很常見的HOOK技術,這裏呢。寫得比較簡單,方法很多。只講原理!希望大鳥們別吐我口水哈 - -。好!切入正題。
首先是概念吧。什麼是鉤子(HOOK)?
#include <Windows.h>
#pragma warning( disable: 4309 )
#pragma warning( disable: 4311 )
#define MYHOOKMETHOD ( __fun ) HMODULE WINAPI __fun
#define DECLARE_REGISTER ( __0bj, __lawfunc, __newfunc ) Inline_Hook< HOOKAPI, 1 > __Obj( __lawfunc, __newfunc )
{
DWORD _argsBytes;
void* _lawFunc;
void* _newFunc;
char _lawByteCode[16];
char _newByteCode[16];
{
// It's hooked.
if ( memcmp( _newByteCode, _lawFunc, 16 ) == 0 )
{
DWORD dwOldFlag;
VirtualProtect( _lawFunc, 8, PAGE_EXECUTE_READWRITE, &dwOldFlag );
memcpy( _lawFunc, _lawByteCode, 16 );
VirtualProtect( _lawFunc, 8, dwOldFlag, &dwOldFlag );
return true;
}
}
{
// It's saved.
if ( memcmp( _lawByteCode, _lawFunc, 16 ) == 0 )
{
DWORD dwOldFlag;
VirtualProtect( _lawFunc, 8, PAGE_EXECUTE_READWRITE, &dwOldFlag );
memcpy( _lawFunc, _newByteCode, 16 );
VirtualProtect( _lawFunc, 8, dwOldFlag, &dwOldFlag );
return true;
}
}
};
{
__asm
{
push ebp // save maybe usefull register.
push ebx
push esi
push ecx
test eax, eax // check the remove was successful
jz __return
mov eax, dword ptr[esp] // esp just is ecx, also is __InlineHOOK_Base's this pointer.
mov ecx, dword ptr[eax] // get first 4 bytes, that is params total size.
shr ecx, 2 // get params num, equal with __InlineHOOK_Base::_argsBytes / sizeof( DWORD )
test ecx, ecx // check whether there are params.
jz __callfunc // no param
mov edx, esp // __InlineHOOK_Base's this pointer.
add edx, 14h // navigate to first call ret addr.
add edx, dword ptr[eax]; // add params size.
push dword ptr[edx]; // push the dll file name pointer.
loop __pushargs
call [eax+8] // call my function .
push edx // save my function return value.
push eax
pop eax // get saved return value, provided to my superiors to use
pop edx
pop ecx
pop esi
pop ebx
pop ebp
ret
}
}
__InlineHOOK_Base ::__ InlineHOOK_Base ( void* lawfun, void* newfun, DWORD args )
: _lawFunc( lawfun ), _newFunc( newfun ), _argsBytes( args * 4 )
{
_newByteCode[ 0 ] = 0xB9; // mov ecx, ...
( DWORD& )_newByteCode[ 1 ] = ( DWORD )this;
_newByteCode[ 5 ] = 0xB8; // mov eax, ...
( DWORD& )_newByteCode[ 6 ] = ( DWORD )__Inline_Hook_Func;
( WORD& )_newByteCode[ 10 ] = 0xD0FF; // call eax
_newByteCode[ 12 ] = 0x000000C3; // ret
if ( args > 0 )
{
_newByteCode[ 12 ] = 0xC2; // ret ...
( WORD& )_newByteCode[ 13 ] = ( WORD )_argsBytes;
_newByteCode[ 15 ] = 0;
}
}
template< typename _function, DWORD args >
struct Inline_Hook : __InlineHOOK_Base
{
Inline_Hook( _function lawfun, _function newfun )
:__InlineHOOK_Base( lawfun, newfun, args ) { hook(); }
~Inline_Hook( void ){ unhook(); }
};
{
::MessageBox( NULL, lpcStrFileName, "LoadLibrary Name", MB_OK | MB_ICONINFORMATION );
return LoadLibraryA( lpcStrFileName );
}
DECLARE_REGISTER ( __inline_hook , LoadLibraryA , myLoadLibrary );
{
HMODULE hIntstance = LoadLibraryA ( "d3d9.dll" );
return 0;
}
void* _lawFunc; // 指向老的Hook前的LoadLibraryA函數的一個指針
void* _newFunc; // 指向我們自己的中間函數的指針
char _lawByteCode[16]; // 保存正常的LoadLibraryA前16個代碼字節,用於UnHook,不然怎麼還原呢。呵呵!
char _newByteCode[16]; // 我們替換給LoadLibraryA的16個代碼字節,用於Hook,不然怎麼執行我們自己的函數呢,呵呵!
( DWORD& )_newByteCode[ 1 ] = ( DWORD )this;
_newByteCode[ 5 ] = 0xB8; // mov eax, ...
( DWORD& )_newByteCode[ 6 ] = ( DWORD )__Inline_Hook_Func;
( WORD& )_newByteCode[ 10 ] = 0xD0FF; // call eax
_newByteCode[ 12 ] = 0x000000C3; // ret
if ( args > 0 )
{
_newByteCode[ 12 ] = 0xC2; // ret ...
( WORD& )_newByteCode[ 13 ] = ( WORD )_argsBytes;
_newByteCode[ 15 ] = 0;
}
if ( memcmp( _lawByteCode, _lawFunc, 16 ) == 0 ) // 看看是否保存了,否則還原不了沒辦法unhook。
{
DWORD dwOldFlag;
VirtualProtect( _lawFunc, 8, PAGE_EXECUTE_READWRITE, &dwOldFlag ); //這個函數就不用說了,呵呵,查資料吧!
memcpy( _lawFunc, _newByteCode, 16 ); // 拷貝我們的HOOK代碼進LoadLibraryA中!
VirtualProtect( _lawFunc, 8, dwOldFlag, &dwOldFlag );
return true; // 拷貝成功!
}
這個函數全是彙編。嘿嘿!我用的英文註釋了的哈。大致能看明白,英語太差了!
7C801D7D 55 push ebp
7C801D7E 8B EC mov ebp,esp
7C801D80 83 7D 08 00 cmp dword ptr [ebp+8],0
7C801D84 53 push ebx
7C801D85 56 push esi
7C801D86 74 14 je 7C801D9C
7C801D88 68 60 E1 80 7C push 7C80E160h
7C801D8D FF 75 08 push dword ptr [ebp+8]
7C801D90 FF 15 AC 13 80 7C call dword ptr ds:[7C8013ACh]
7C801D96 85 C0 test eax,eax
7C801D98 59 pop ecx
7C801D99 59 pop ecx
7C801D9A 74 12 je 7C801DAE
7C801D9C 6A 00 push 0
7C801D9E 6A 00 push 0
7C801DA0 FF 75 08 push dword ptr [ebp+8]
7C801DA3 E8 AB FF FF FF call 7C801D53
7C801DA8 5E pop esi
7C801DA9 5B pop ebx
7C801DAA 5D pop ebp
7C801DAB C2 04 00 ret 4
7C801D80 B8 BC 12 41 00 mov eax,offset __Inline_Hook_Func (4112BCh)
7C801D85 FF D0 call eax
7C801D87 C2 04 00 ret 4
7C801D8A 00 80 7C FF 75 08 add byte ptr [eax+875FF7Ch],al
7C801D90 FF 15 AC 13 80 7C call dword ptr ds:[7C8013ACh]
7C801D96 85 C0 test eax,eax
7C801D98 59 pop ecx
7C801D99 59 pop ecx
7C801D9A 74 12 je 7C801DAE
7C801D9C 6A 00 push 0
7C801D9E 6A 00 push 0
7C801DA0 FF 75 08 push dword ptr [ebp+8]
7C801DA3 E8 AB FF FF FF call 7C801D53
7C801DA8 5E pop esi
7C801DA9 5B pop ebx
7C801DAA 5D pop ebp
7C801DAB C2 04 00 ret 4