使用不同版本的 Winsock
Winsock working with different versions
我写了一个数据包拦截器来从 winsock 的 send/recv 函数中转储信息,据我所知,这两个函数都位于 ws2_32.dll;挂钩是通过将 jmp 写入记录我需要的信息然后调用原始函数的函数来完成的,挂钩本身工作正常。
真正奇怪的是,我开始注意到我无法记录任何 RECV 调用,而 SEND 调用却被截获了。
写hook的函数如下:
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 接收,这有意义吗?这种行为在任何方面都是正常的吗?
在不同的模块中编写钩子相当容易,但由于它们应该是不同的,这让我相信出了点问题,而且,我计算机中的其他一些应用程序(如 firefox 本身)也有同样的行为.
我添加这张图片是为了更好地解释这种情况,看起来程序链接到 wsock32 并以一些 ws2_32 的功能结束。
wsock32.dll
适用于 Winsock 1.x,ws2_32.dll
适用于 Winsock 2.x。大多数应用 link 到 ws2_32.dll
,但旧版应用(和配置错误的应用)可能仍然 link 到 wsock32.dll
。在现代系统中,wsock32.dll
在内部将其 大多数 函数重定向到 ws2_32.dll
或 mswsock.dll
.
您的目标应用 link 正在 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-specific 扩展函数可用,如好吧(WSASend()
、WSARecv()
等),Winsock 2.x 套接字也可以支持重叠 I/O 和 I/O 完成端口。因此,如果您真的想在任何给定应用程序中挂接所有可能的数据交换途径,您可能必须挂接 BSD 函数、Winsock 扩展函数和 I/O 函数。但是,如果您只针对一个特定的应用程序,则只需挂钩它实际调用的函数(在本例中为 send()
和 WSARecv()
)。
我写了一个数据包拦截器来从 winsock 的 send/recv 函数中转储信息,据我所知,这两个函数都位于 ws2_32.dll;挂钩是通过将 jmp 写入记录我需要的信息然后调用原始函数的函数来完成的,挂钩本身工作正常。
真正奇怪的是,我开始注意到我无法记录任何 RECV 调用,而 SEND 调用却被截获了。
写hook的函数如下:
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 接收,这有意义吗?这种行为在任何方面都是正常的吗?
在不同的模块中编写钩子相当容易,但由于它们应该是不同的,这让我相信出了点问题,而且,我计算机中的其他一些应用程序(如 firefox 本身)也有同样的行为.
我添加这张图片是为了更好地解释这种情况,看起来程序链接到 wsock32 并以一些 ws2_32 的功能结束。
wsock32.dll
适用于 Winsock 1.x,ws2_32.dll
适用于 Winsock 2.x。大多数应用 link 到 ws2_32.dll
,但旧版应用(和配置错误的应用)可能仍然 link 到 wsock32.dll
。在现代系统中,wsock32.dll
在内部将其 大多数 函数重定向到 ws2_32.dll
或 mswsock.dll
.
您的目标应用 link 正在 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-specific 扩展函数可用,如好吧(WSASend()
、WSARecv()
等),Winsock 2.x 套接字也可以支持重叠 I/O 和 I/O 完成端口。因此,如果您真的想在任何给定应用程序中挂接所有可能的数据交换途径,您可能必须挂接 BSD 函数、Winsock 扩展函数和 I/O 函数。但是,如果您只针对一个特定的应用程序,则只需挂钩它实际调用的函数(在本例中为 send()
和 WSARecv()
)。