这里只帖上部分代码:
第一步:遍历所有模块: hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, 0 );
if( hSnapShot == INVALID_HANDLE_VALUE )
return FALSE; if( Module32First( hSnapShot, &me) )
{
do
{
SetHook_MethodOne(me.hModule);
}
while( Module32Next( hSnapShot, &me ) );
}第二步:替换API函数入口地址: PROC *ppfn = ( PROC * ) & (pitd2->u1.Function);
if( *ppfn == GetProcAddress( GetModuleHandle( "User32.dll" ), "MessageBoxW" ) )
{
DWORD dwOldAccess = 0, dwNewAccess = 0, dwWritted = 0;
VirtualProtect( &pitd2->u1.Function, sizeof(DWORD), PAGE_WRITECOPY, &dwOldAccess );
WriteProcessMemory( GetCurrentProcess(), &pitd2->u1.Function, &MessageBoxT,sizeof(PROC), &dwWritted );
VirtualProtect( &pitd2->u1.Function, sizeof(DWORD), dwOldAccess, &dwNewAccess );
}第三步:自己的MessageBoxint WINAPI MessageBoxT(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType)
{
TCHAR szCaption[255];
strcpy(szCaption,lpCaption);
strcat( szCaption, TEXT(" +弹出窗口被HOOK了!") );
typedef int (__stdcall * MESSAGEBOXW)(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);
MESSAGEBOXW MessageBoxW = ( MESSAGEBOXW ) GetProcAddress( GetModuleHandle( "user32.dll" ), "MessageBoxW" );
return MessageBoxW( hWnd, lpText, szCaption, uType );
}这里先不纠结代码中个别名字之类错误的问题,我有一点不明白:在和二步中if( *ppfn == GetProcAddress( GetModuleHandle( "User32.dll" ), "MessageBoxW" ) )将函数地址替换了,在第三步的我自己的MessageBoxT中又MESSAGEBOXW MessageBoxW = ( MESSAGEBOXW ) GetProcAddress( GetModuleHandle( "user32.dll" ), "MessageBoxW" );
return MessageBoxW( hWnd, lpText, szCaption, uType );这不是又调用了在第二步中已经被修改过地址的MessageBoxW吗?这样就成了死循环了啊。

解决方案 »

  1.   

    在我实际测试的过程中,并没有发现死循环的现象,所以我就猜测:EXE和DLL中的所有函数都有自己的入口地址,这些入口地址统一放在一个地方,每一次要调用某个函数时,系统先到这个地方去找这个函数的入口地址,再跳到该地址去执行该地址的代码,执行完了再跳回来,实际上我们修改的入口地址只是修改存放这些地址的那个地方的里面的值,而真正的函数入口地址并没有变,仅仅是“我要调用某个函数-》我问系统要该函数的地址-》系统告诉我地址-》我到那个地址那儿去”,是这样一回事吗?
    如果是这样一回事,又有两个问题:
    一:如果我要调用MessageBox,系统内部执行的是直接去“那个地方(统一的地址存放地)”去找地址,还是用GetProcAddress("user32.dll","MessageBox")来取得MessageBox的址,然后去该地址执行呢?
    二:如果函数地址统一存放在某个地方的话,那么我的EXE里的函数有成千上万个了,系统把每个函数地址都存放在那个地方,那么这个地方得存多少啊。我感觉又有点不太合理。
      

  2.   

    同2楼,你改的只是pitd2->u1.Function导入表,在你自己的MessageBox里是用GetProcAddress来取得地址,这样不会经过exe的导入表,所以不会死循环。一:如果exe里直接调用了MessageBox,那么编译后MessageBox的相关信息会被写入exe的导入表,exe执行时所有对MessageBox的直接调用都从导入表获取地址,但是像用GetProcAddress("user32.dll","MessageBox")来间接调用的话,就不会从exe的导入表获取地址了,而是从user32.dll的导出表获取地址,注意是导出表。二:exe里用到的API才会被保存到导入表,没用到的不会保存。
      

  3.   

    静态加载dll,走的是导入表
    如果是动态加载dll,重新分析的PE文件,读取的函数地址