最今看到网上一段HOOK send的代码,把它COPY 下来`,改了下,在运行的时候,``被HOOK的程序崩溃!现在把代码帖上来,希望大家能帮解释下``先谢谢了`!
下面是我的代码
////////////////这的安装勾子的接口!
void sethook(HWND hWnd)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState()); DWORD tid;
DWORD pid;
tid =GetWindowThreadProcessId(hWnd,&pid);
SetWindowsHookEx(WH_KEYBOARD,keyboardproc,GetModuleHandle("jdfz.dll"),tid);
}
////////////////////下面是回调函数,就是改SEND入口地址的代码
LRESULT CALLBACK keyboardproc(int code,WPARAM wParam, LPARAM lParam)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());

if ((wParam==VK_F1)&&((lParam&(1<<31))==0))
{ HANDLE hModule;
DWORD  ul_reason_for_call; 
                                   LPVOID lpReserved; g_hInstance = hModule;

//创建事务
g_hSendEvent = CreateEvent( NULL, FALSE, TRUE, NULL );

//重写API开头的8字节
HMODULE hWsock = LoadLibrary( "wsock32.dll" );
g_pSend = ( DWORD )GetProcAddress( hWsock, "send" );
AfxMessageBox("faewsd");//这句代码没什么意义,只是想看看,钩子是否安装成功!
//保存原始字节
ReadProcessMemory( INVALID_HANDLE_VALUE, ( void * )g_pSend, ( void * )g_dwOldBytes[0], sizeof( DWORD )*2, NULL );
//将00400000改写为我们函数的地址
*( DWORD* )( g_btNewBytes + 1 ) = ( DWORD )hook_send;
WriteProcessMemory( INVALID_HANDLE_VALUE, ( void * )g_pSend, ( void * )g_btNewBytes, sizeof( DWORD )*2, NULL );  } return CallNextHookEx(NULL,code,wParam,lParam);
}
上面的是DLL的代码!!!
下面的是在没有运行这个DLL情况下,被HOOK程序本身的汇编代码
71B62EC2 88FF        MOV EDI,EDI
71B62EC4  55          PUSH EBP
71B62EC5  8BEC        MOV EBP,ESP
71B62EC7  83EC 10       SUB ESP,10
71B62ECA    56        PUSH ESI
71B62ECB    57       PUSH EDI
71B62ECC    33FF      XOR EDI,EDI
下面的是被DLL改过后的汇编代码71B62EC2  8B1410     MOV EDX,DWORD PRT DS:[EAX+EDX]
71B62EC5  8401       TEST BYTE PTR DS:[ECX],AL
71B62EC7    FFEO     JMP EAX
71B62EC9    0056      ADD BYTE PTR DS:[ESI+57],DL
71B62ECC    33FF     EDI,EDI
////////////////////
求助下大家,我应该怎么改代码,``
才可以HOOK到send这个函数啊?

解决方案 »

  1.   


    ReadProcessMemory( INVALID_HANDLE_VALUE, ( void * )g_pSend, ( void * )g_dwOldBytes[0], sizeof( DWORD )*2, NULL );
    //将00400000改写为我们函数的地址
    *( DWORD* )( g_btNewBytes + 1 ) = ( DWORD )hook_send;
    WriteProcessMemory( INVALID_HANDLE_VALUE, ( void * )g_pSend, ( void * )g_btNewBytes, sizeof( DWORD )*2, NULL );  进程句柄竟然是INVALID_HANDLE_VALUE,不崩溃才怪。
      

  2.   


    看清楚点再回答,-1表示的就是当前进程,而且楼主的代码已经hook成功了。另外,一般的API hook应该是讲函数头修改成Jmp 0xXXXXXXXX这样的汇编代码,刚好占用5个自己,在自己Hook的函数末尾先PUSH EBP,再MOV EBP,ESP,再用Jmp跳转send+5的位置,而你hook后的代码完全不正确了,g_btNewBytes通常应该是5个字节码,第一个字节应该是0xEB,然后是NewSend的偏移地址,你再修改下应该差不多了,当然一定要同时使用OD或WinDbg附加到游戏进程调试。
      

  3.   

     HANDLE g_hInstance = NULL;
     //修改API入口为 mov eax, 00400000;jmp eax是程序能跳转到自己的函数
     BYTE g_btNewBytes[8] = { 0xB8, 0x0, 0x0, 0x40, 0x0, 0xFF, 0xE0, 0x0 };
     //保存原API入口的8个字节
     DWORD g_dwOldBytes[2][2] = { 0x0, 0x0, 0x0, 0x0 };
     //钩子句柄
     HHOOK   g_hOldHook = NULL;
     //API中send函数的地址
     DWORD g_pSend = 0;
     //事务,解决同步问题
     HANDLE g_hSendEvent = NULL;
     //自己的send函数地址,参数必须与API的send函数地址相同
    上面的是全局变量的定义!
    代码的作者说 BYTE g_btNewBytes[8] = { 0xB8, 0x0, 0x0, 0x40, 0x0, 0xFF, 0xE0, 0x0 };
    是修改API入口为 mov eax, 00400000;jmp eax是程序能跳转到自己的函数!
    在我HOOK 时候,是能成功地修改API入口的值的!但是,当被HOOK 的程序调用SEND 的时间,程序就卡死在被我修改的地方!
    而且修改到的代码这这样的
    71B62EC2 8B1410 MOV EDX,DWORD PRT DS:[EAX+EDX]
    71B62EC5 8401 TEST BYTE PTR DS:[ECX],AL
    71B62EC7 FFEO JMP EAX该代码的作者说,修改API入口为 mov eax, 00400000;jmp eax是程序能跳转到自己的函数
    为什么说00400000是自己的函数入口地址,是怎么计算出来呢?
    楼上的帮我解答下好吗?`
      

  4.   


    /*WINAPI不写,调用进程会挂掉滴*/
    int WINAPI mysend(SOCKET s, const char FAR *buf, int len, int flag)
    {
        char *pBuffer = new char[len+1];
        ZeroMemory(pBuffer, len+1);
        memcpy(pBuffer, buf, len);
        OutputDebugString(pBuffer);
        delete pBuffer;
        return real_send(s, buf, len, flag);   
    }
      

  5.   

    对不起```由于没把
    int _stdcall hook_send( SOCKET s, const char *buf, int len, int flags )
    {
    int nRet;
    WaitForSingleObject( g_hSendEvent, INFINITE );

    //恢复API头8个字节
    WriteProcessMemory( INVALID_HANDLE_VALUE, ( void* )g_pSend, ( void* )g_dwOldBytes[0], sizeof( DWORD )*2, NULL );  //这里把SEND入口地址改了回来``

    /*
    这里可以添加想要进行的处理过程
    */// AfxMessageBox("faewsd");
    //真正执行API函数
    nRet = send( s, buf, len, flags );////因为前面把SEND的入口地址改回来了```所以还是继续调用原来的SEND!!!
    AfxMessageBox("faewsd");
    //写入跳转语句,继续Hook
    // WriteProcessMemory( INVALID_HANDLE_VALUE, ( void* )g_pSend, 
    //( void* )g_btNewBytes, sizeof( DWORD )*2, NULL );

    // SetEvent( g_hSendEvent );

    return nRet;
    }
    发上来```导致楼上误解了``,
    其实mysend这个函数应该不用写的`,
    因为这分代码的作者原来的思路是先把真正的SNED入口改 了``跳到
    hook_send这里,然后在把SEND改回来,````在执行了加入的代码后,``接着调用真实的SEND发包``