System.Net.Sockets.Socket.Disconnect 如何断开与套接字的连接?
How does System.Net.Sockets.Socket.Disconnect disconnect from the socket?
我的 DLL 被注入程序,然后使用 Detours 挂钩到 connect
、send
、recv
和 closesocket
函数。重点是阻止程序连接到某个服务器,而是直接与我的 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
背后调用的是什么?我还需要挂钩什么其他功能来检测它?
我试过连接到 shutdown
、setsockopt
、WSACancelBlockingCall
、WSACleanup
、WSASend
、WSASendDisconnect
、WSASendMsg
、WSASendTo
、WSARecv
、WSARecvDisconnect
和 WSARecvFrom
。 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.
所以如果你想做我做的事,你必须:
- 挂钩到
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);
- return 函数的地址
*((LPFN_DISCONNECTEX*)lpvOutBuffer) = &Mine_DisconnectEx;
我的 DLL 被注入程序,然后使用 Detours 挂钩到 connect
、send
、recv
和 closesocket
函数。重点是阻止程序连接到某个服务器,而是直接与我的 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
背后调用的是什么?我还需要挂钩什么其他功能来检测它?
我试过连接到 shutdown
、setsockopt
、WSACancelBlockingCall
、WSACleanup
、WSASend
、WSASendDisconnect
、WSASendMsg
、WSASendTo
、WSARecv
、WSARecvDisconnect
和 WSARecvFrom
。 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.
所以如果你想做我做的事,你必须:
- 挂钩到
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);
- return 函数的地址
*((LPFN_DISCONNECTEX*)lpvOutBuffer) = &Mine_DisconnectEx;