WSARecv 钩子:防止数据包被可执行文件接收

Posted

技术标签:

【中文标题】WSARecv 钩子:防止数据包被可执行文件接收【英文标题】:WSARecv hook: prevent packet from being recieved by the executable 【发布时间】:2014-08-06 22:34:29 【问题描述】:

我正在使用 C++ 和绕道来开发挂钩 winsock2 函数的 dll。我的目标是修改进出原始可执行文件的 TCP 流量。在某些时候,我需要停止某些数据包传递(以便原始可执行文件根本不知道该数据包,但仍保持连接)。

使用 WSASend 挂钩,很清楚(您只是不调用原始 WSASend 并返回 0)。 但我不知道如何使用 WSAOVERLAPPED 结构在 WSARecv 钩子中制作它。

我希望下面的代码能说明我想要什么:

__declspec(dllexport) int WINAPI WSARecv_hook(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)

    // Recieve real data
    int ret = WSARecv_real(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpOverlapped, lpCompletionRoutine);

    // Loop over lpBuffers and analyze it
    for(int i=0; i < dwBufferCount; i++)
    
        // analyze it
        if(packet_should_be_blocked(lpBuffers[i].buf, lpBuffers[i].len))
        
            // Do or return what?
         else 
            // Otherwise, just process as usual
        
    
    return ret;

我如何假装什么​​都没发生,也没有收到任何数据包(比如假的 WSA_IO_PENDING)?有什么想法/想法吗?

附:据我所知,可执行文件不使用完成例程(lpCompletionRoutine 始终为 NULL),仅使用重叠结构。

【问题讨论】:

嗯。我以为我写了一条评论,询问当您“丢弃”数据包时您希望应用程序实际做什么?相信这是超时,还是网络出现故障? 不,我只是想让它继续等待其他数据包,就像什么都没发生一样。 请注意,packet_should_be_blocked 不能工作,因为 TCP 不是面向消息的。您必须缓冲数据,直到有足够的数据进行分析,然后可能仅删除您在单个调用中收到的部分数据。这也适用于阻止接收呼叫。 @BenVoigt 我熟悉我正在修改的协议(每个数据包/消息的前两个字节定义数据包/消息类型,每个数据包类型都有固定长度),所以这根本不是问题。还是谢谢你。 @splattru:这是一个问题,因为您假设标头和有效负载在单个缓冲区中一起到达。这种假设对于 TCP 来说是错误的。 【参考方案1】:

主要的障碍是重叠操作意味着在调用函数以挂起状态退出后在后台执行。如果调用者要求WSARecv() 执行重叠读取,则它期望数据到达后台,并且您将无法直接验证钩子内部的数据,因为它尚未收到。您必须使用自己的私有WSAOVERLAPPED 来执行您自己的重叠读取,使用线程或完成回调来检测读取何时完成,以便您可以分析数据。如果数据是可接受的,则将其复制到调用者的缓冲区并通知调用者的WSAOVERLAPPED。否则,发布另一个读取并等待该数据到达,根据需要重复,直到您最终收到一些您想要提供给调用者的数据。

【讨论】:

不是这样的问题。如果您收到不想传递给原始程序的消息,则在再次调用WSARecv() 时将原始请求保持等待状态,从而为下一个传入数据包提供完成请求的机会.【参考方案2】:

修改 TCP 流量的一种更简单的方法是仅挂钩 connect 系列函数,并使应用程序连接到您控制下的透明代理,该代理执行实际的流修改。

虽然应用程序可以在流中写入自己的端口号,以便远程端与数据包源地址进行比较,但这在实践中不是问题,因为

    这也会破坏住宅互联网连接中非常常见的 NAT-PAT 网关 您可以重写内容并发送代理地址,因此检查通过

事实上,FTP 代理必须重写此命令,因为它们会产生从属连接以进行文件传输。但大多数现代应用程序都被编写为与 PAT 兼容。

【讨论】:

重写数据包内容以将客户端的 IP 替换为代理的 IP 如果您不小心,可能会很危险。仅对您熟悉的协议执行此操作,例如 FTP。如果代理盲目地更改恰好看起来像客户端 IP 的任意数据,则代理可能会损坏与 IP 无关的数据。已知一些代理会表现出这个问题。 @Remy:我很确定这个问题中的协议是已知的;否则流修改将不起作用。 @Remy:感谢您发现错字,我确实在最后一段中打算使用“FTP”。

以上是关于WSARecv 钩子:防止数据包被可执行文件接收的主要内容,如果未能解决你的问题,请参考以下文章

在组件外部使用 redux 钩子来实现代码的可重用性

使用 React 的 useState 钩子时输入可空状态的正确方法

创建组策略,防止误点程序

使用 Java 代码操作 MFC 对话框可执行文件

如何在单个可执行文件中将数据重定向到标准输入?

赫斯基需要为每个新分支都设置可执行文件