Hook之DLL中函数和成员函数篇

Home / Hackintosh MrLee 2016-5-25 4102

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;
}
 

本文链接:https://www.it72.com/9405.htm

推荐阅读
最新回复 (0)
返回