问题描述
我的 DLL 被注入到程序中,然后使用 Detours 挂钩到 connect
、send
、recv
和 closesocket
函数。关键是阻止程序连接到某个服务器,而是直接与我的 DLL 通信。
我的 recv
函数使用无限循环,只是等待任何数据发送到程序。当调用 closesocket
时,循环被破坏,一切正常。
但是有一个用 C# 编写的程序在我关闭它时会挂起。它的错误日志说:
SocketException:由于套接字未连接并且(使用 sendto 调用在数据报套接字上发送时)未提供地址,因此不允许发送或接收数据的请求。
在 System.Net.sockets.socket.disconnect(布尔重用套接字)[0x00000] 中:0
异常是意料之中的,因为套接字从未连接到任何东西。但是有什么解决方法吗? System.Net.sockets.socket.disconnect
在幕后叫什么?我还需要挂钩什么其他功能来检测它?
我试过挂钩 shutdown
、setsockopt
、WSACancelBlockingCall
、WSACleanup
、WSASend
、WSASenddisconnect
、WSASendMsg
、WSASendTo
、WSARecv
、WSARecvdisconnect
和 WSARecvFrom
。他们都没有接到电话。
解决方法
System.Net.Sockets.Socket.Disconnect
调用 DisconnectEx
。正如评论所说:
注意DisconnectEx 函数的函数指针必须在运行时通过使用 SIO_GET_EXTENSION_FUNCTION_POINTERWSAIoctl 函数获得/strong> 指定的操作码。传递给 WSAIoctl 函数的输入缓冲区必须包含 WSAID_DISCONNECTEX,这是一个全局唯一标识符 (GUID),其值标识 DisconnectEx 扩展函数。成功时,WSAIoctl 函数返回的输出包含一个指向 DisconnectEx 函数的指针。 WSAID_DISCONNECTEX GUID 在 Mswsock.h 头文件中定义。
所以如果你想做我所做的,你必须:
- 连接到
WSAIoctl
- 检查
dwIoControlCode
是否为SIO_GET_EXTENSION_FUNCTION_POINTER
- 检查
lpvInBuffer
是否为WSAID_DISCONNECTEX
:
IsEqualGUID(*((GUID*)lpvInBuffer),WSAID_DISCONNECTEX)
- 将地址存储到真实的
DisconnectEx
某处
LPFN_DISCONNECTEX Real_DisconnectEx = NULL;
(...)
Real_DisconnectEx = *((LPFN_DISCONNECTEX*)lpvOutBuffer);
- 返回函数的地址
*((LPFN_DISCONNECTEX*)lpvOutBuffer) = &Mine_DisconnectEx;