WSASend 缓冲区到字符串
WSASend Buffer to String
如何将 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);
}
正如@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;
}
Update:您的 send()
挂钩假设 buf
始终以 null 结尾,但事实并非如此。将 buf
数据复制到 `string:
时,您必须使用提供的 len
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"
本身在单次发送中完成。您真正需要做的是将出站数据按原样保存到每个套接字缓冲区,然后解析缓冲区以查找完整消息,仅将完整消息传递到您的管道并将它们从缓冲区中删除,将部分数据留在由后续发送完成的缓冲区。
如何将 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);
}
正如@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;
}
Update:您的 send()
挂钩假设 buf
始终以 null 结尾,但事实并非如此。将 buf
数据复制到 `string:
len
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"
本身在单次发送中完成。您真正需要做的是将出站数据按原样保存到每个套接字缓冲区,然后解析缓冲区以查找完整消息,仅将完整消息传递到您的管道并将它们从缓冲区中删除,将部分数据留在由后续发送完成的缓冲区。