WSASend缓冲区到字符串

时间:2015-05-14 15:04:42

标签: c++ winsock2 packet-capture

如何将Winsock2 WSASend()缓冲区转换为字符串?

这是我目前的代码,它只写了很多I个字符。

int WINAPI Hook_WSASend(SOCKET a0, LPWSABUF a1, DWORD a2, LPDWORD a3, DWORD a4, LPWSAOVERLAPPED a5, LPWSAOVERLAPPED_COMPLETION_ROUTINE a6)
{
    int rv = 0;
    char * buf = "";
    WSABUF * wb = a1;

    for(int i = 0; i == a2; i++){
        strcpy_s(buf, wb[i].len, wb[i].buf);
    }

    fopen_s(&pWSASendLogFile, "C:\\WSASendLog.txt", "a+");
    fprintf(pWSASendLogFile, "%s\n", buf);
    fclose(pWSASendLogFile);
    rv = Real_WSASend(a0,a1,a2,a3,a4,a5,a6);
    return rv;
}

正如Remy Lebeau所说,我正在添加更多关于我需要实现的信息。

我需要在字符串中包含缓冲区,因为:

  • 我必须在缓冲区内搜索特定字符串,特别是在执行任何操作之前,字符串必须以<TalkMsg开头。

  • 然后,我必须通过NamedPipe发送缓冲区,我已经有我的函数处理它。

为了更好地解释我正在做什么,这是我目前为Winsock send()提供的代码。我必须对WSASend()做同样的事情。

int WINAPI Hook_Send(SOCKET s, const char* buf, int len, int flags)
{
    /*
    fopen_s(&pSendLogFile, "C:\\SendLog.txt", "a+");
    fprintf(pSendLogFile, "%s\n", buf);
    fclose(pSendLogFile);
    */
    curSocket = s;
    if(Filtering){
        PipeHeader ph;
        string p(buf);
        if(p.find("<TalkMsg") == 0){
            ph.command = 5;
            ph.sockid = s;
            ph.datasize = len;
            if(SendPipeHeader((char*)&ph, sizeof(ph))){
                if(SendPipeData(buf, len)){
                    return len;
                }
            }
        }
    }

    return Real_Send(s, buf, len, flags);
}

1 个答案:

答案 0 :(得分:0)

正如@enhzflep在评论中所说,您没有正确管理buf变量。你甚至根本不需要它。只需将源缓冲区直接写入文件:

int WINAPI Hook_WSASend(SOCKET a0, LPWSABUF a1, DWORD a2, LPDWORD a3, DWORD a4, LPWSAOVERLAPPED a5, LPWSAOVERLAPPED_COMPLETION_ROUTINE a6)
{
    fopen_s(&pWSASendLogFile, "C:\\WSASendLog.txt", "a+");
    for(DWORD i = 0; i < a2; i++)
        fwrite(a1[i].buf, 1, a1[i].len, pWSASendLogFile);
    fprintf(pWSASendLogFile, "\n");
    fclose(pWSASendLogFile);

    int rv = Real_WSASend(a0,a1,a2,a3,a4,a5,a6);
    return rv;
}

更新:您的send()挂钩假设buf始终以空值终止,但事实并非如此。将len数据复制到`string:

时,必须使用提供的buf
int WINAPI Hook_Send(SOCKET s, const char* buf, int len, int flags)
{
    /*
    fopen_s(&pSendLogFile, "C:\\SendLog.txt", "a+");
    fwrite(buf, 1, len, pSendLogFile);
    fprintf(pSendLogFile, "\n");
    fclose(pSendLogFile);
    */
    curSocket = s;
    if(Filtering){
        PipeHeader ph;
        string p(buf, len); // <-- here
        if(p.find("<TalkMsg") == 0){
            ph.command = 5;
            ph.sockid = s;
            ph.datasize = len;
            if(SendPipeHeader((char*)&ph, sizeof(ph))){
                if(SendPipeData(buf, len)){
                    return len;
                }
            }
        }
    }

    return Real_Send(s, buf, len, flags);
}

您需要在WSASend()挂钩中执行类似操作,并考虑所有WSABUF缓冲区的总长度:

int WINAPI Hook_WSASend(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesSent, DWORD dwFlags, LPWSAOVERLAPPED                    lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
    /*
    fopen_s(&pWSASendLogFile, "C:\\WSASendLog.txt", "a+");
    for(DWORD i = 0; i < dwBufferCount; i++)
        fwrite(lpBuffers[i].buf, 1, lpBuffers[i].len, pWSASendLogFile);
    fprintf(pWSASendLogFile, "\n");
    fclose(pWSASendLogFile);
    */
    curSocket = s;
    if(Filtering){
        PipeHeader ph;
        string p;
        size_t len = 0;
        for(DWORD i = 0; i < dwBufferCount; i++) {
            len += lpBuffers[i].len;
        }
        p.reserve(len);
        for(DWORD i = 0; i < dwBufferCount; i++) {
            p.append(lpBuffers[i].buf, lpBuffers[i].len);
        }
        if(p.find("<TalkMsg") == 0){
            ph.command = 5;
            ph.sockid = s;
            ph.datasize = len;
            if(SendPipeHeader((char*)&ph, sizeof(ph))){
                if(SendPipeData(p.c_str(), len)){
                    if (lpNumberOfBytesSent){
                        *lpNumberOfBytesSent = len;
                    }
                    if (lpCompletionRoutine) {
                        lpCompletionRoutine(0, len, lpOverlapped, 0);
                    }
                    return 0;
                }
            }
        }
    }

    return Real_WSASend(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine);
}

话虽这么说,由于TCP的流媒体特性,这种过滤代码不是很可靠。当"<TalkMsg"存在时,无法保证输入数据在单个发送中表示完整的消息,或者即使"<TalkMsg"本身在单个发送中也是完整的。你真正需要做的是将出站数据按原样保存到每个套接字缓冲区,然后解析缓冲区以查找完整的消息,只将完整的消息传递给管道并将其从缓冲区中删除,留下部分数据缓冲区由后续发送完成。

相关问题