谁知道如何截取网络封包?就像wpe一样的程序的delphi源码。
或者说明原理及方法。
我知道好像用api Hook但具体如何实现呢?
最好有现成的函数调用,做成后是这样的软件,就是不要什么都截取,只截取指定的进程。而且能显示出是从哪个IP到哪个IP以及端口号和数据包本身。别的多余的东西都不要。Email:[email protected]
或者说明原理及方法。
我知道好像用api Hook但具体如何实现呢?
最好有现成的函数调用,做成后是这样的软件,就是不要什么都截取,只截取指定的进程。而且能显示出是从哪个IP到哪个IP以及端口号和数据包本身。别的多余的东西都不要。Email:[email protected]
解决方案 »
- 大家帮忙看一下
- 动态生成的Combobox或edit 怎么限制输入的只能是数字???谢谢
- 有谁用过sncCurrencyEdit这个控件啊?用过的来看看!
- 这个错误是怎么回事?[Error] PrintInfo.pas(36): Statement expected, but expression of type 'TfrPreview' found
- 关于键盘精灵
- 怎么样取得在打印设置中设置的打印机名称?
- 怎样解决表中字段重复问题
- 關於dbgrid問題
- 哪位仁兄有《黑白棋》的算法或源代码,小弟苦于找不到算法,恳请指教!
- 有关sql的问题(paradox)
- 请教InputQuery与MulDiv
- 要做个加密的注册码生成机制,请问各位怎么实现啊?我没做过这方面的,请大家指教指教,谢谢!
利用HOOK拦截封包原理截获API是个很有用的东西,比如你想分析一下别人的程序是怎样工作的。这里我介绍一下一种我自己试验通过的方法。
首先,我们必须设法把自己的代码放到目标程序的进程空间里去。Windows Hook可以帮我们实现这一点。SetWindowsHookEx的声明如下:
HHOOK SetWindowsHookEx(
int idHook, // hook type
HOOKPROC lpfn, // hook procedure
HINSTANCE hMod, // handle to application instance
DWORD dwThreadId // thread identifier
);
具体的参数含义可以翻阅msdn,没有msdn可谓寸步难行。
这里Hook本身的功能并不重要,我们使用它的目的仅仅只是为了能够让Windows把我们的代码植入别的进程里去。hook Type我们任选一种即可,只要保证是目标程序肯定会调用到就行,这里我用的是WH_CALLWNDPROC。lpfn和hMod分别指向我们的钩子代码及其所在的dll,dwThreadId设为0,表示对所有系统内的线程都挂上这样一个hook,这样我们才能把代码放到别的进程里去。 之后,我们的代码就已经进入了系统内的所有进程空间了。必须注意的是,我们只需要截获我们所关心的目标程序的调用,因此还必须区分一下进程号。我们自己的钩子函数中,第一次运行将进行最重要的API重定向的工作。也就是通过将所需要截获的API的开头几个字节改为一个跳转指令,使其跳转到我们的API中来。这是最关键的部分。这里我想截三个调用,ws2_32.dll中的send和recv、user32.dll中的GetMessageA。 DWORD dwCurrentPID = 0;
HHOOK hOldHook = NULL;
DWORD pSend = 0;
DWORD pRecv = 0;
GETMESSAGE pGetMessage = NULL; BYTE btNewBytes[8] = { 0x0B8, 0x0, 0x0, 0x40, 0x0, 0x0FF, 0x0E0, 0 };
DWORD dwOldBytes[3][2]; HANDLE hDebug = INVALID_HANDLE_value; LRESULT CALLBACK CallWndProc( int nCode, WPARAM wParam, LPARAM lParam )
{
DWORD dwSize;
DWORD dwPIDWatched;
HMODULE hLib; if( dwCurrentPID == 0 )
{
dwCurrentPID = GetCurrentProcessId();
HWND hwndMainHook;
hwndMainHook = ::FindWindow( 0, "MainHook" );
dwPIDWatched = ::SendMessage( hwndMainHook, (WM_USER+100), 0, 0 );
hOldHook = (HHOOK)::SendMessage( hwndMainHook, (WM_USER+101), 0, 0 ); if( dwCurrentPID == dwPIDWatched )
{
hLib = LoadLibrary( "ws2_32.dll" );
pSend = (DWORD)GetProcAddress( hLib, "send" );
pRecv = (DWORD)GetProcAddress( hLib, "recv" ); ::ReadProcessMemory( INVALID_HANDLE_value, (void *)pSend, (void *)dwOldBytes[0], sizeof(DWORD)*2, &dwSize );
*(DWORD *)( btNewBytes + 1 ) = (DWORD)new_send;
::WriteProcessMemory( INVALID_HANDLE_value, (void *)pSend, (void *)btNewBytes, sizeof(DWORD)*2, &dwSize ); ::ReadProcessMemory( INVALID_HANDLE_value, (void *)pRecv, (void *)dwOldBytes[1], sizeof(DWORD)*2, &dwSize );
*(DWORD *)( btNewBytes + 1 ) = (DWORD)new_recv;
::WriteProcessMemory( INVALID_HANDLE_value, (void *)pRecv, (void *)btNewBytes, sizeof(DWORD)*2, &dwSize ); hLib = LoadLibrary( "user32.dll" );
pGetMessage = (GETMESSAGE)GetProcAddress( hLib, "GetMessageA" );
::ReadProcessMemory( INVALID_HANDLE_value, (void *)pGetMessage, (void *)dwOldBytes[2], sizeof(DWORD)*2, &dwSize );
*(DWORD *)( btNewBytes + 1 ) = (DWORD)new_GetMessage;
::WriteProcessMemory( INVALID_HANDLE_value, (void *)pGetMessage, (void *)btNewBytes, sizeof(DWORD)*2, &dwSize ); hDebug = ::CreateFile( "C:\\Trace.log", GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0 );
}
} if( hOldHook != NULL )
{
return CallNextHookEx( hOldHook, nCode, wParam, lParam );
} return 0;
} 上面的钩子函数,只有第一次运行时有用,就是把三个函数的首8字节修改一下(实际上只需要7个)。btNewBytes中的指令实际就是
mov eax, 0x400000
jmp eax
这里的0x400000就是新的函数的地址,比如new_recv/new_send/new_GetMessage,此时,偷梁换柱已经完成。再看看我们的函数中都干了些什么。以GetMessageA为例: BOOL _stdcall new_GetMessage( LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax )
{
DWORD dwSize;
char szTemp[256];
BOOL r = false; //Watch here before it's executed.
sprintf( szTemp, "Before GetMessage : HWND 0x%8.8X, msgMin 0x%8.8X, msgMax 0x%8.8x \r\n", hWnd, wMsgFilterMin, wMsgFilterMax );
::WriteFile( hDebug, szTemp, strlen(szTemp), &dwSize, 0 );
//Watch over // restore it at first
::WriteProcessMemory( INVALID_HANDLE_value, (void *)pGetMessage, (void *)dwOldBytes[2], sizeof(DWORD)*2, &dwSize ); // execute it
r = pGetMessage( lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax ); // hook it again
*(DWORD *)( btNewBytes + 1 ) = (DWORD)new_GetMessage;
::WriteProcessMemory( INVALID_HANDLE_value, (void *)pGetMessage, (void *)btNewBytes, sizeof(DWORD)*2, &dwSize ); //Watch here after it's executed
sprintf( szTemp, "Result of GetMessage is %d.\r\n", r );
::WriteFile( hDebug, szTemp, strlen( szTemp ), &dwSize, 0 );
if( r )
{
sprintf( szTemp, "Msg : HWND 0x%8.8X, MSG 0x%8.8x, wParam 0x%8.8X, lParam 0x%8.8X\r\nTime 0x%8.8X, X %d, Y %d\r\n",
lpMsg->hwnd, lpMsg->message,
lpMsg->wParam, lpMsg->lParam, lpMsg->time,
lpMsg->pt.x, lpMsg->pt.y );
::WriteFile( hDebug, szTemp, strlen( szTemp ), &dwSize, 0 );
}
strcpy( szTemp, "\r\n" );
::WriteFile( hDebug, szTemp, strlen( szTemp ), &dwSize, 0 ); //Watch over return r;
} 先将截获下来的参数,写入到一个log文件中,以便分析。然后恢复原先保留下来的GetMessageA的首8字节,然后执行真正的GetMessageA调用,完毕后再将执行结果也写入log文件,然后将GetMessageA的执行结果返回给调用者。
整个截获的过程就是这样。你可以把其中的写log部分改成你自己想要的操作。这里有个不足的地方是,截获动作是不能够并发进行的,如果目标进程是多线程的,就会有问题。解决办法是,可以在每次new_GetMessage中加入一个CriticalSection的锁和解锁,以使调用变为串行进行,但这个我没有试验过。
http://www.csdn.net/develop/Read_Article.asp?Id=22765问题是:
我很想知道,在我的程序中(就是调用这个dll的主程序),如何从dll中获取截取的数据包内容?
最好是实时的,就是一有数据立即读出并显示一个Memo中。我开始想在dll中再加入一个读取数据内容的函数,并导出这个函数,然后在主程序中调用这个函数。不过没成功,而且只能用一个timer中的定时事件定时读取,这样做也不行,会出现错误。var tmp:string; begin setlength(tmp,len); move(buf,tmp[1],len); showmessage(tmp); end;
这个方法好像行不通,我没有试验好!我读取的数据明显与实际不符。
还有如果数据是纯二进制的不是全文本的,用这方法也不太行。有没有什么好方法呢?