【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原版代码):
下载地址:
这方面我也有研究 直接注入在某些程序会导致崩溃 用LSP来进行拦截就稳定很多了但会丢失一些数据 毕竟协议方面我做的不是很好
沙发站起 下一次我试试LSP拦截方法,感谢楼上 可以用于服务器验证的修改吗 看不懂啊,,,,, 嗯又来学习来了 收藏了谢谢了 看不懂,随便顶顶吧 看到代码就支持一下……表示暂时是只会用成品的菜鸟
hook劫持,有时候会引起崩溃啊
页:
[1]
2