简体   繁体   English

C++ 挂钩 winsock

[英]C++ hooking winsock

I am trying to hook winsock send and recv in order to read all traffic of a process.我试图挂钩 winsock send 和 recv 以读取进程的所有流量。 I am injectin the following code as a dll inside the target process我将以下代码作为 dll 注入到目标进程中

#include "dll.h"
#include <windows.h>
#include <winsock2.h>
#include <iostream>
#include <fstream>

#pragma comment(lib, "ws2_32.lib")

using namespace std;

DllClass::DllClass()
{

}


DllClass::~DllClass ()
{

}

BYTE hook[6];
BYTE hook2[6];
BYTE jmp[6] = { 0xe9,0x00, 0x00, 0x00, 0x00 ,0xc3 };  
ofstream myfile;
ofstream myfile2;

DWORD HookFunction(LPCSTR lpModule, LPCSTR lpFuncName, LPVOID lpFunction, unsigned char *lpBackup)
{  
      DWORD dwAddr = (DWORD)GetProcAddress(GetModuleHandle(lpModule), lpFuncName);
      ReadProcessMemory(GetCurrentProcess(), (LPVOID)dwAddr, lpBackup, 6, 0);
      DWORD dwCalc = ((DWORD)lpFunction - dwAddr - 5);
      memcpy(&jmp[1], &dwCalc, 4);
      WriteProcessMemory(GetCurrentProcess(), (LPVOID)dwAddr, jmp, 6, 0);
      return dwAddr;
}    

BOOL UnHookFunction(LPCSTR lpModule, LPCSTR lpFuncName, unsigned char *lpBackup)
{
DWORD dwAddr = (DWORD)GetProcAddress(GetModuleHandle(lpModule), lpFuncName);
if (WriteProcessMemory(GetCurrentProcess(), (LPVOID)dwAddr, lpBackup, 6, 0))
        return TRUE;
return FALSE;  
}

int nSend(SOCKET s, const char *buf, int len,int flags){
UnHookFunction("ws2_32.dll", "send", hook);


int result = send(s,buf,len,flags);


  myfile.open ("C:\\tmp\\log.txt",ios::app | ios::binary);
  myfile << buf;
  myfile.close();




HookFunction("ws2_32.dll", "send", (LPVOID*) nSend, hook);
return result;
} 

int nRecv(SOCKET s, char* buf, int len, int flags)
{
    UnHookFunction("ws2_32.dll", "recv", hook2);
    DWORD tmp;

    len = recv(s, buf, len, flags);

    if (len > 0)
    {

        myfile2.open ("C:\\tmp\\log.txt",ios::app | ios::binary);
        myfile2 << buf;
        myfile2.close();
    }
   HookFunction("ws2_32.dll", "recv", (LPVOID*) nRecv, hook2);
    return len;
}
void fun(){ // <-- this is called after the DLL has been injected
HookFunction("ws2_32.dll", "send", (LPVOID*) nSend, hook);
HookFunction("ws2_32.dll", "recv", (LPVOID*) nRecv, hook2);
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:

case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

This works in some cases and in some it doesnt.这在某些情况下有效,而在某些情况下则无效。 If i inject it into filezilla ftp it works like a charm and writes everything that is send or recieved to a file.如果我将它注入到 filezilla ftp 中,它就像一个魅力,并将发送或接收的所有内容写入文件。

But on nearly all other programms (internet explorer, firefox usw.) it just writes some bytes to the file and then the process crashes...但是在几乎所有其他程序(Internet Explorer,firefox usw)上,它只是将一些字节写入文件,然后进程崩溃......

Has anyone an idea what is going wrong?有谁知道出了什么问题?

Ok.行。 Its working now, even with DataExecutionPrevention enabled.它现在可以工作,即使启用了 DataExecutionPrevention。 In case someone has a similar problem in future, here is the working code:如果将来有人遇到类似问题,这里是工作代码:

dllmain.cpp: dllmain.cpp:

#include "dll.h"
#include <windows.h>
#include <winsock2.h>
#include <iostream>
#include <fstream>

#pragma comment(lib, "ws2_32.lib")

using namespace std;

DllClass::DllClass()
{

}


DllClass::~DllClass ()
{

}

BYTE hook[6];
BYTE hook2[6];
BYTE jmp[6] = { 0xe9,0x00, 0x00, 0x00, 0x00 ,0xc3 };  
ofstream myfile;
ofstream myfile2;
DWORD pPrevious;

DWORD HookFunction(LPCSTR lpModule, LPCSTR lpFuncName, LPVOID lpFunction, unsigned char *lpBackup)
{  
      DWORD dwAddr = (DWORD)GetProcAddress(GetModuleHandle(lpModule), lpFuncName);
      ReadProcessMemory(GetCurrentProcess(), (LPVOID)dwAddr, lpBackup, 6, 0);
      DWORD dwCalc = ((DWORD)lpFunction - dwAddr - 5);
      VirtualProtect((void*) dwAddr, 6, PAGE_EXECUTE_READWRITE, &pPrevious);
      memcpy(&jmp[1], &dwCalc, 4);
      WriteProcessMemory(GetCurrentProcess(), (LPVOID)dwAddr, jmp, 6, 0);
      VirtualProtect((void*) dwAddr, 6, pPrevious, &pPrevious);
      FlushInstructionCache(GetCurrentProcess(),0,0);
      return dwAddr;
}    

BOOL UnHookFunction(LPCSTR lpModule, LPCSTR lpFuncName, unsigned char *lpBackup)
{
DWORD dwAddr = (DWORD)GetProcAddress(GetModuleHandle(lpModule), lpFuncName);

if (WriteProcessMemory(GetCurrentProcess(), (LPVOID)dwAddr, lpBackup, 6, 0))
        return TRUE;
        FlushInstructionCache(GetCurrentProcess(),0,0);

return FALSE;  
}

int __stdcall nSend(SOCKET s, const char *buf, int len,int flags){
UnHookFunction("ws2_32.dll", "send", hook);


int result = send(s,buf,len,flags);


  myfile.open ("C:\\tmp\\log.txt",ios::app | ios::binary);
  myfile << buf;
  myfile.close();




HookFunction("ws2_32.dll", "send", (LPVOID*) nSend, hook);
return result;
} 

int __stdcall nRecv(SOCKET s, char* buf, int len, int flags)
{
    UnHookFunction("ws2_32.dll", "recv", hook2);
    DWORD tmp;

    len = recv(s, buf, len, flags);

    if (len > 0)
    {

        myfile2.open ("C:\\tmp\\log.txt",ios::app | ios::binary);
        myfile2 << buf;
        myfile2.close();
    }
   HookFunction("ws2_32.dll", "recv", (LPVOID*) nRecv, hook2);
    return len;
}
void fun(){
HookFunction("ws2_32.dll", "send", (LPVOID*) nSend, hook);
HookFunction("ws2_32.dll", "recv", (LPVOID*) nRecv, hook2);
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
HookFunction("ws2_32.dll", "send", (LPVOID*) nSend, hook);
HookFunction("ws2_32.dll", "recv", (LPVOID*) nRecv, hook2);
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

dll.h dll文件

#ifndef _DLL_H_
#define _DLL_H_

#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllimport)
#endif /* Not BUILDING_DLL */


class DLLIMPORT DllClass
{
  public:
    DllClass();
    virtual ~DllClass(void);

  private:

};
extern "C" __declspec(dllexport) void fun();

#endif /* _DLL_H_ */

Tested and working with nearly all programs on Win XP 32bit and some programs on Win 7 x64在 Win XP 32 位上测试并使用几乎所有程序以及在 Win 7 x64 上的一些程序

Be sure to use the correct calling convention on your hooked functions.确保在您的挂钩函数上使用正确的调用约定。 The default calling convention is usually __cdecl.默认调用约定通常是 __cdecl。 However 'send', and 'recv' use __stdcall ( #define WINAPI __stdcall )但是“发送”和“接收”使用 __stdcall ( #define WINAPI __stdcall )

The main difference between the two are:两者的主要区别在于:

When a function uses __cdecl the caller is responsible for stack cleanup.当函数使用 __cdecl 时,调用者负责堆栈清理。 However when a function uses __stdcall the called function is responsible for stack cleanup.然而,当一个函数使用 __stdcall 时,被调用的函数负责堆栈清理。

int WINAPI nSend(SOCKET s, const char *buf, int len,int flags);
int WINAPI nRecv(SOCKET s, char* buf, int len, int flags)

See here for more information.请参阅此处了解更多信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM