System.Net.Sockets.Socket.Disconnect 如何断开与套接字的连接?

How does System.Net.Sockets.Socket.Disconnect disconnect from the socket?

我的 DLL 被注入程序,然后使用 Detours 挂钩到 connectsendrecvclosesocket 函数。重点是阻止程序连接到某个服务器,而是直接与我的 DLL 通信。

我的recv函数使用了一个无限循环,只是等待任何数据发送给程序。当 closesocket 被调用时,循环被打破,一切正常。

但是有一个用 C# 编写的程序在我关闭它时挂起。它的错误日志说:

SocketException: A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied.

at System.Net.Sockets.Socket.Disconnect (Boolean reuseSocket) [0x00000] in :0

异常是预料之中的,因为套接字从未连接到任何东西。但是有什么解决方法吗? System.Net.Sockets.Socket.Disconnect 背后调用的是什么?我还需要挂钩什么其他功能来检测它?

我试过连接到 shutdownsetsockoptWSACancelBlockingCallWSACleanupWSASendWSASendDisconnectWSASendMsgWSASendToWSARecvWSARecvDisconnectWSARecvFrom。 None 他们被叫到。

System.Net.Sockets.Socket.Disconnect 呼叫 DisconnectEx。正如评论所说:

Note The function pointer for the DisconnectEx function must be obtained at run time by making a call to the WSAIoctl function with the SIO_GET_EXTENSION_FUNCTION_POINTER opcode specified. The input buffer passed to the WSAIoctl function must contain WSAID_DISCONNECTEX, a globally unique identifier (GUID) whose value identifies the DisconnectEx extension function. On success, the output returned by the WSAIoctl function contains a pointer to the DisconnectEx function. The WSAID_DISCONNECTEX GUID is defined in the Mswsock.h header file.

所以如果你想做我做的事,你必须:

  1. 挂钩到 WSAIoctl
  2. 检查 dwIoControlCode 是否为 SIO_GET_EXTENSION_FUNCTION_POINTER
  3. 检查 lpvInBuffer 是否为 WSAID_DISCONNECTEX:
IsEqualGUID(*((GUID*)lpvInBuffer), WSAID_DISCONNECTEX)
  1. 将地址存储到真实的DisconnectEx某处
LPFN_DISCONNECTEX Real_DisconnectEx = NULL;
(...)
Real_DisconnectEx = *((LPFN_DISCONNECTEX*)lpvOutBuffer);
  1. return 函数的地址
*((LPFN_DISCONNECTEX*)lpvOutBuffer) = &Mine_DisconnectEx;