如何将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);
}
答案 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"
本身在单个发送中也是完整的。你真正需要做的是将出站数据按原样保存到每个套接字缓冲区,然后解析缓冲区以查找完整的消息,只将完整的消息传递给管道并将其从缓冲区中删除,留下部分数据缓冲区由后续发送完成。