lizhirui 发表于 2016-10-28 00:16

【VC】网络收发包HOOK

目前仅仅实现了网络发包拦截修改,原理如下:
首先主程序在被拦截进程中调用VirtualAllocEx分配内存,然后写入待注入的DLL文件名,并且使用CreateRemoteThread创建远程线程,远程调用LoadLibrary注入DLL,然后等待进程管道,被注入的DLL首先会创建进程管道并且等待主进程连接,当主进程连接后,主进程向被注入的DLL发送主进程的进程PID以及回调函数的地址,然后关闭进程管道,接下来,被注入的DLL找到注入进程中的ws2_32.dll的send函数,
申请一块内存,写入如下代码:
原API被替换的指令
mov eax,原API中被替换指令的下一条指令
jmp eax
并修改头部机器码,变成:
mov eax,DLL内部的拦截函数地址
jmp eax

拦截函数名称为MySocketsend 采用_stdcall方式调用
按照标准接口定义 BOOL WINAPI MySocketsend(SOCKET s,char *buf,int len,int flag)
一旦被注入进程发送数据,就会被拦截并进入这个函数,这个函数将会首先在主进程中创建一块内存,将待发送的数据写入主进程内存,然后使用远程线程调用的方法调用主进程的回调函数,待主进程处理完成后,将主进程的缓冲区数据读出,以call的方式传递主进程修改后的参数调用刚才申请的内存中的代码,调用完成后,为了欺骗原来的程序,如果发送成功,就返回原数据而不是被修改数据的长度,否则返回SOCKET_ERROR。

该接口实现如下:
BOOL WINAPI MySocketsend(SOCKET s,char *buf,int len,int flag)
{
        HANDLE hProcess = NULL;
        HANDLE hThread = NULL;
        LPVOID pRemoteBuf = NULL;
        LPVOID pRemoteStr = NULL;
        LPDWORD pData = NULL;
        DWORD x;
        LPVOID pRemote_Str = NULL;
        DWORD pRemote_Len = 0;
        LPVOID SendBuf;
        DWORD r;
        char strbuf;

        if((Func_callback == 0) || (PID_callback == 0))
        {
                error:
                //MessageBox(NULL,"Hello","Hello",MB_OK);
                return ((PFSOCKETSEND)mem_buf)(s,buf,len,flag);
        }
        else
        {
                if(!(hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,PID_callback)))
                {
                        goto error;
                }

                //sprintf_s(strbuf,100,"%x\r\n%x\r\n",(DWORD)PID_callback,(DWORD)Func_callback);
                //MessageBox(NULL,strbuf,"succ",MB_OK);
                pRemoteBuf = VirtualAllocEx(hProcess,NULL,8,MEM_COMMIT,PAGE_READWRITE);
                pRemoteStr = VirtualAllocEx(hProcess,NULL,len,MEM_COMMIT,PAGE_READWRITE);
                WriteProcessMemory(hProcess,pRemoteStr,buf,len,NULL);
                x = (DWORD)pRemoteStr;
                WriteProcessMemory(hProcess,pRemoteBuf,&x,4,NULL);
                WriteProcessMemory(hProcess,(LPVOID)((DWORD)pRemoteBuf + 4),&len,4,NULL);
                hThread = CreateRemoteThread(hProcess,NULL,0,(LPTHREAD_START_ROUTINE)Func_callback,pRemoteBuf,0,NULL);
                WaitForSingleObject(hThread,INFINITE);
                CloseHandle(hThread);
                ReadProcessMemory(hProcess,pRemoteBuf,&pRemote_Str,4,NULL);
                ReadProcessMemory(hProcess,(LPVOID)((DWORD)pRemoteBuf + 4),&pRemote_Len,4,NULL);
                VirtualFreeEx(hProcess,pRemoteBuf,8,MEM_DECOMMIT);
                VirtualFreeEx(hProcess,pRemoteStr,len,MEM_DECOMMIT);
                SendBuf = VirtualAlloc(NULL,pRemote_Len,MEM_COMMIT,PAGE_READWRITE);
                ReadProcessMemory(hProcess,pRemote_Str,SendBuf,pRemote_Len,NULL);
                CloseHandle(hProcess);
                r = ((PFSOCKETSEND)mem_buf)(s,(char *)SendBuf,pRemote_Len,flag);
                VirtualFree(SendBuf,pRemote_Len,MEM_DECOMMIT);
               
                if(r == SOCKET_ERROR)
                {
                        return SOCKET_ERROR;
                }
                else
                {
                        return len;
                }
        }
}

DLL中的HOOK代码实现如下:
void hook()
{
        char *cmd = (char *)Func_send;
        LPDWORD addr;
        DWORD x;

        mem_buf = (char *)VirtualAlloc(NULL,100,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
        VirtualProtect((LPVOID)Func_send,255,PAGE_EXECUTE_READWRITE,&x);
        cmd = (char)0x68;
        addr = (LPDWORD)(cmd + 1);
        cmd = (char)0xC3;
        *addr = (DWORD)&MySocketsend;
        mem_buf = (char)0x8B;
        mem_buf = (char)0xFF;
        mem_buf = (char)0x55;
        mem_buf = (char)0x8B;
        mem_buf = (char)0xEC;
        mem_buf = (char)0x83;
        mem_buf = (char)0xEC;
        mem_buf = (char)0x10;
        mem_buf = (char)0x68;
        addr = (LPDWORD)(mem_buf + 9);
        mem_buf = (char)0xC3;
        *addr = (DWORD)Func_send + 8;
}


主程序中的HOOK代码实现如下(参考了一小部分《逆向工程核心原理》):
BOOL InjectDll(DWORD dwPID,LPCSTR szDllPath)
{
        HANDLE hProcess = NULL;
        HANDLE hThread = NULL;
        HMODULE hMod = NULL;
        LPVOID pRemoteBuf = NULL;
        DWORD dwBufSize = (DWORD)(strlen(szDllPath) + 1) * sizeof(CHAR);
        LPTHREAD_START_ROUTINE pThreadProc;
        HANDLE hPipe = NULL;
        DWORD x;

        if(!(hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwPID)))
        {
                printf("OpenProcess(%d) failed!!! [%d]\n",dwPID,GetLastError());
                return FALSE;
        }

       
        pRemoteBuf = VirtualAllocEx(hProcess,NULL,dwBufSize,MEM_COMMIT,PAGE_READWRITE);
        WriteProcessMemory(hProcess,pRemoteBuf,(LPVOID)szDllPath,dwBufSize,NULL);

        hMod = GetModuleHandle("kernel32.dll");
        pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod,"LoadLibraryA");
        hThread = CreateRemoteThread(hProcess,NULL,0,pThreadProc,pRemoteBuf,0,NULL);
        //WaitForSingleObject(hThread,INFINITE);
        CloseHandle(hThread);
        CloseHandle(hProcess);

        while(WaitNamedPipe("\\\\.\\pipe\\ajks8NJKS9sjkaj",NMPWAIT_WAIT_FOREVER) == FALSE)
        {
                /*printf("Wait NamedPipe Fail!\n");
                return FALSE;*/
        }

        if((hPipe = CreateFile("\\\\.\\pipe\\ajks8NJKS9sjkaj",GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL)) == INVALID_HANDLE_VALUE)
        {
                printf("Open NamedPipe Fail!\n");
                return FALSE;
        }

        *((DWORD *)datbuf) = GetCurrentProcessId();
        *((DWORD *)(datbuf + 4)) = (DWORD)&send_callback;

        if(WriteFile(hPipe,datbuf,8,&x,NULL) == FALSE)
        {
                printf("Write Namedpipe Fail!\n");
                return FALSE;
        }

        CloseHandle(hPipe);
        printf("Connect OK!\n");
        return TRUE;
}


易语言程序的测试截图(这个代码在VS2012用VC写成,但是应某人要求,将主进程的代码翻译成了易语言代码,但是没有VC原版代码好用,建议使用VC原版代码):


下载地址:

你与明日 发表于 2016-10-28 00:34

这方面我也有研究   直接注入在某些程序会导致崩溃    用LSP来进行拦截就稳定很多了但会丢失一些数据   毕竟协议方面我做的不是很好

我来看看看 发表于 2016-10-28 00:24

沙发站起

lizhirui 发表于 2016-10-28 00:39

下一次我试试LSP拦截方法,感谢楼上

a6718589 发表于 2016-10-28 00:46

可以用于服务器验证的修改吗

17000009682 发表于 2016-10-28 00:49

看不懂啊,,,,,

旧爱 发表于 2016-10-28 02:09

嗯又来学习来了 收藏了谢谢了

ke845560452 发表于 2016-10-28 04:47

看不懂,随便顶顶吧

仁二 发表于 2016-10-28 05:19

看到代码就支持一下……表示暂时是只会用成品的菜鸟

mancong122 发表于 2016-10-28 08:38

hook劫持,有时候会引起崩溃啊
页: [1] 2
查看完整版本: 【VC】网络收发包HOOK