Hook DLL 中的函数
#define MakePtr( cast, ptr, addValue )( cast )( ( DWORD )( ptr ) + ( DWORD )( addValue ) )
void *InterceptDllCall( HMODULE hModule, char *szDllName, char *szFunctionName, DWORD pNewFunction )
{
PIMAGE_DOS_HEADER pDosHeader;
PIMAGE_NT_HEADERS pNTHeader;
PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
PIMAGE_THUNK_DATA pThunk;
DWORD dwOldProtect;
DWORD dwOldProtect2;
void *pOldFunction;
if( !( pOldFunction = GetProcAddress( GetModuleHandle( szDllName ), szFunctionName ) ) )
return 0;
pDosHeader = ( PIMAGE_DOS_HEADER )hModule;
if( pDosHeader->e_magic != IMAGE_DOS_SIGNATURE )
return( NULL );
pNTHeader = MakePtr( PIMAGE_NT_HEADERS, pDosHeader, pDosHeader->e_lfanew );
if( pNTHeader->Signature != IMAGE_NT_SIGNATURE
|| ( pImportDesc = MakePtr( PIMAGE_IMPORT_DESCRIPTOR, pDosHeader, pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress ) ) == ( PIMAGE_IMPORT_DESCRIPTOR )pNTHeader )
return( NULL );
while( pImportDesc->Name )
{
char *szModuleName = MakePtr( char *, pDosHeader, pImportDesc->Name );
if( !stricmp( szModuleName, szDllName ) )
break;
pImportDesc++;
}
if( pImportDesc->Name == NULL )
return( NULL );
pThunk = MakePtr( PIMAGE_THUNK_DATA, pDosHeader, pImportDesc->FirstThunk );
while( pThunk->u1.Function )
{
if( pThunk->u1.Function == ( DWORD )pOldFunction )
{
VirtualProtect( ( void * )&pThunk->u1.Function, sizeof( DWORD ), PAGE_EXECUTE_READWRITE, &dwOldProtect );
pThunk->u1.Function = pNewFunction;
VirtualProtect( ( void * )&pThunk->u1.Function, sizeof( DWORD ), dwOldProtect, &dwOldProtect2 );
return( pOldFunction );
}
pThunk++;
}
return( NULL );
}
用法:
例如Hook MessageBoxA 函数
首先建立一个DLL工程
自定义一个和MesageBoxA参数和返回值一样的函数
int WINAPI sysMessageBox( HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption, UINT uType)
{
MessageBox(0,"From hook ed MessegeBoxA",0,0);
return(MessageBox(hWnd,lpText,lpCaption, uType));
}
然后调用如下:
InterceptDllCall(GetModuleHandle(NULL )
,"User32.dll"
,"MessageBoxA"
,(DWORD)&sysMessageBox );
Hook类的成员函数
// set value to pointer fo a function
template <typename T>
inline void SetFuncPointerVal(T &func, DWORD val)
{
__asm
{
push eax
push ebx
mov eax, [val]
mov ebx, [func]
mov [ebx], eax
pop ebx
pop eax
}
}
// oldFunc Old member function
// newFunc New function which we want to redirect to it when calling old one
// outOldFunc We return the pointer to oldFunc by this parameter
#define HookMemberFunc(oldFunc, newFunc, outOldFunc) /
{ /
DWORD _pold1st, _pold2nd; /
__asm /
{ /
mov _pold1st, offset oldFunc /*get the 1st call target address*/ /
} /
/*get the 2nd jump target address*/ /
memcpy(&_pold2nd, (char*)_pold1st+1, 4); /
_pold2nd += 5 + _pold1st; /
SetFuncPointerVal(outOldFunc, _pold2nd); /*get the 2nd jump address as function pointer and return it*//
DWORD _pnew; /
/* then we overwrite the 2nd jump address with the function of ourselves*//
__asm { mov _pnew, offset newFunc } /
_pnew -= (DWORD)_pold1st + 5; /
DWORD _dwOldProtect, _dwOldProtect2; /
VirtualProtect( ( char * )_pold1st + 1, 4, PAGE_EXECUTE_READWRITE, &_dwOldProtect ); /
memcpy((char*)_pold1st+1, &_pnew, 4); /
VirtualProtect( ( char * )_pold1st + 1, 4, _dwOldProtect, &_dwOldProtect2 ); /
}
用法示例如下:
class Base;
typedef void (Base::*AOut)();
AOut func;
class Base
{
public:
virtual void Output() = 0;
virtual void aaa() = 0;
};
class A: public Base
{
public:
void Output()
{
cout << "sdfsdf";
}
void aaa()
{
cout << "aaa";
}
};
void newOutput()
{
cout << "hooked" << endl;
A *pa;
__asm
{
mov [pa], ecx
}
(pa->*func)();
}
int _tmain(int argc, _TCHAR* argv[])
{
HookMemberFunc(A::Output, newOutput, func);
Base *a = new A();
a->aaa();
a->Output(); // 此时, 这行语句将会调用newOutput
(a->*func)(); // 这才是调用原来的A::Output
::LoadLibrary("apihook.dll");
MessageBox(NULL, "sdf", "sdf", MB_OK);
return 0;
}
PS——请勿将此代码用于非法用途,如病毒、木马等
Reference:
http://www.codeguru.com/forum/archive/index.php/t-306311.html
#define MakePtr( cast, ptr, addValue )( cast )( ( DWORD )( ptr ) + ( DWORD )( addValue ) )
void *InterceptDllCall( HMODULE hModule, char *szDllName, char *szFunctionName, DWORD pNewFunction )
{
PIMAGE_DOS_HEADER pDosHeader;
PIMAGE_NT_HEADERS pNTHeader;
PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
PIMAGE_THUNK_DATA pThunk;
DWORD dwOldProtect;
DWORD dwOldProtect2;
void *pOldFunction;
if( !( pOldFunction = GetProcAddress( GetModuleHandle( szDllName ), szFunctionName ) ) )
return 0;
pDosHeader = ( PIMAGE_DOS_HEADER )hModule;
if( pDosHeader->e_magic != IMAGE_DOS_SIGNATURE )
return( NULL );
pNTHeader = MakePtr( PIMAGE_NT_HEADERS, pDosHeader, pDosHeader->e_lfanew );
if( pNTHeader->Signature != IMAGE_NT_SIGNATURE
|| ( pImportDesc = MakePtr( PIMAGE_IMPORT_DESCRIPTOR, pDosHeader, pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress ) ) == ( PIMAGE_IMPORT_DESCRIPTOR )pNTHeader )
return( NULL );
while( pImportDesc->Name )
{
char *szModuleName = MakePtr( char *, pDosHeader, pImportDesc->Name );
if( !stricmp( szModuleName, szDllName ) )
break;
pImportDesc++;
}
if( pImportDesc->Name == NULL )
return( NULL );
pThunk = MakePtr( PIMAGE_THUNK_DATA, pDosHeader, pImportDesc->FirstThunk );
while( pThunk->u1.Function )
{
if( pThunk->u1.Function == ( DWORD )pOldFunction )
{
VirtualProtect( ( void * )&pThunk->u1.Function, sizeof( DWORD ), PAGE_EXECUTE_READWRITE, &dwOldProtect );
pThunk->u1.Function = pNewFunction;
VirtualProtect( ( void * )&pThunk->u1.Function, sizeof( DWORD ), dwOldProtect, &dwOldProtect2 );
return( pOldFunction );
}
pThunk++;
}
return( NULL );
}
用法:
例如Hook MessageBoxA 函数
首先建立一个DLL工程
自定义一个和MesageBoxA参数和返回值一样的函数
int WINAPI sysMessageBox( HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption, UINT uType)
{
MessageBox(0,"From hook ed MessegeBoxA",0,0);
return(MessageBox(hWnd,lpText,lpCaption, uType));
}
然后调用如下:
InterceptDllCall(GetModuleHandle(NULL )
,"User32.dll"
,"MessageBoxA"
,(DWORD)&sysMessageBox );
Hook类的成员函数
// set value to pointer fo a function
template <typename T>
inline void SetFuncPointerVal(T &func, DWORD val)
{
__asm
{
push eax
push ebx
mov eax, [val]
mov ebx, [func]
mov [ebx], eax
pop ebx
pop eax
}
}
// oldFunc Old member function
// newFunc New function which we want to redirect to it when calling old one
// outOldFunc We return the pointer to oldFunc by this parameter
#define HookMemberFunc(oldFunc, newFunc, outOldFunc) /
{ /
DWORD _pold1st, _pold2nd; /
__asm /
{ /
mov _pold1st, offset oldFunc /*get the 1st call target address*/ /
} /
/*get the 2nd jump target address*/ /
memcpy(&_pold2nd, (char*)_pold1st+1, 4); /
_pold2nd += 5 + _pold1st; /
SetFuncPointerVal(outOldFunc, _pold2nd); /*get the 2nd jump address as function pointer and return it*//
DWORD _pnew; /
/* then we overwrite the 2nd jump address with the function of ourselves*//
__asm { mov _pnew, offset newFunc } /
_pnew -= (DWORD)_pold1st + 5; /
DWORD _dwOldProtect, _dwOldProtect2; /
VirtualProtect( ( char * )_pold1st + 1, 4, PAGE_EXECUTE_READWRITE, &_dwOldProtect ); /
memcpy((char*)_pold1st+1, &_pnew, 4); /
VirtualProtect( ( char * )_pold1st + 1, 4, _dwOldProtect, &_dwOldProtect2 ); /
}
用法示例如下:
class Base;
typedef void (Base::*AOut)();
AOut func;
class Base
{
public:
virtual void Output() = 0;
virtual void aaa() = 0;
};
class A: public Base
{
public:
void Output()
{
cout << "sdfsdf";
}
void aaa()
{
cout << "aaa";
}
};
void newOutput()
{
cout << "hooked" << endl;
A *pa;
__asm
{
mov [pa], ecx
}
(pa->*func)();
}
int _tmain(int argc, _TCHAR* argv[])
{
HookMemberFunc(A::Output, newOutput, func);
Base *a = new A();
a->aaa();
a->Output(); // 此时, 这行语句将会调用newOutput
(a->*func)(); // 这才是调用原来的A::Output
::LoadLibrary("apihook.dll");
MessageBox(NULL, "sdf", "sdf", MB_OK);
return 0;
}
PS——请勿将此代码用于非法用途,如病毒、木马等
Reference:
http://www.codeguru.com/forum/archive/index.php/t-306311.html