Winsock使用不同版本
我写了一个数据包拦截器来从winsock的send/recv函数转储信息,并且据我所知,这两个函数都位于ws2_32.dll中;挂钩是通过将jmp写入一个函数来完成的,该函数记录我需要的信息,然后调用原始函数,挂钩本身工作得很好。Winsock使用不同版本
真奇怪的是我开始注意到我无法记录任何RECV呼叫,而SEND呼叫被截获得很好。
写入钩子函数如下:
procedure Setup;
var
lModuleHandle : dword;
lPlaceHolder : dword;
begin
lModuleHandle := LoadLibrary(MODULE_NAME);
OriginalSend := Dword(GetProcAddress(lModuleHandle, FUNCTION_SEND));
OriginalRecv := Dword(GetProcAddress(lModuleHandle, FUNCTION_RECV));
VirtualProtect(Ptr(OriginalSend), 5, PAGE_EXECUTE_READWRITE, lPlaceHolder);
VirtualProtect(Ptr(OriginalRecv), 5, PAGE_EXECUTE_READWRITE, lPlaceHolder);
PByte(OriginalRecv)^ := $E9;
PDword(OriginalRecv + 1)^ := Dword(@Hook_Recv) - OriginalRecv - 5;
PByte(OriginalSend)^ := $E9;
PDword(OriginalSend + 1)^ := Dword(@Hook_Send) - OriginalSend - 5;
Inc(OriginalSend, 5);
Inc(OriginalRecv, 5);
end;
程序我的工作(一被拦截)使用WinSock 2和一些调试后,我注意到,我不得不装的wsock32.dll并决定在它的RECV上放置一个断点,而我在ws2_32.dll的SEND中又有一个断点;两个断点都被击中。
这意味着该程序使用ws2_32.dll发送和wsock32.dll recv,这是否有任何意义?这种行为在任何方面都是正常的吗?
在不同模块中编写钩子相当容易,但由于它们应该是不同的,所以我相信有些东西是错误的,而且我的电脑中的其他一些应用程序(如Firefox本身)也具有相同的行为。
我添加此图片来更好地解释情况,看起来像程序链接到wsock32,并最终得到一些ws2_32的功能。
wsock32.dll
是的Winsock 1.x中,ws2_32.dll
如果Winsock的2.x的大多数应用链接到ws2_32.dll
,但传统应用(和错误配置的应用)可能仍然链接到wsock32.dll
。在现代系统上,wsock32.dll
在其内部重定向大多数其功能为ws2_32.dll
或mswsock.dll
。
您的目标应用连接到wsock32.dll
。相反,您正在使用ws2_32.dll
连接功能。
在内部,wsock32.send()
直接映射到ws2_32.send()
,这就是为什么您的send()
挂钩工作。但是,wsock32.recv()
不是映射到ws2_32.recv()
,这就是为什么您的recv()
挂钩不起作用。代替wsock32.recv()
实际上调用ws2_32.WSARecv()
。
在的WinSock 2.x的,标准的BSD套接字功能仍然可用(send()
,recv()
等),但也有Winsock的具体可用的扩展功能,以及(WSASend()
,WSARecv()
,等),和Winsock 2。 x套接字也可以支持重叠I/O和I/O完成端口。因此,如果您真的想要在任何给定的应用程序中挂接所有可能的数据交换途径,您可能需要挂钩BSD功能,Winsock扩展功能和I/O功能。但是,如果你只是针对一个特定的应用程序,你只需要钩住它实际调用的函数(在这种情况下,它是send()
和WSARecv()
)。
'send()'和'recv()'不是可用于发送/读取数据的唯一函数。试着钩住'WSASend()'和'WSARecv()'。如果套接字通信使用重叠I/O,则可能还需要钩住其他函数,如'WriteFile()'和'ReadFile()',甚至GetOverlappedResult()和GetQueuedCompletionStatus()。 –
'wsock32.dll'用于Winsock 1.x,'ws2_32.dll'用于Winsock 2.x. 'wsock32.dll'只是一个将命令重定向到'ws2_32.dll'的thunk,以便与旧应用程序兼容。一切都应该最终通过'ws2_32.dll'。但是这并不一定保证'wsock32.dll'中的'recv()'映射到'ws2_32.dll'中的'recv()'。它实际上做的是'wsock32.dll'的私有实现。 –
@RemyLebeau但如果应用程序使用ws2_32的SEND发送信息,它不应该使用来自同一模块的RECV来接收数据吗? –