我试图挂钩Winsock发送和Recv,以读取进程的所有流量。我将以下代码作为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;
}
Run Code Online (Sandbox Code Playgroud)
这在某些情况下有效,在某些情况下则无效。如果我将其注入到filezilla ftp中,它的工作原理就像一个超级按钮,并将发送或接收的所有内容写入文件。
但是几乎在所有其他程序(Internet Explorer,firefox usw)上,它只向文件中写入了一些字节,然后进程崩溃了……
有谁知道出什么问题了吗?
好的。即使启用了 DataExecutionPrevention,它现在也可以正常工作。如果将来有人遇到类似的问题,这里是工作代码:
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;
}
Run Code Online (Sandbox Code Playgroud)
动态链接库
#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_ */
Run Code Online (Sandbox Code Playgroud)
经过测试并适用于 Win XP 32 位上的几乎所有程序以及 Win 7 x64 上的一些程序
确保对挂钩函数使用正确的调用约定。默认调用约定通常是 __cdecl。但是“send”和“recv”使用 __stdcall ( #define WINAPI __stdcall)
两者之间的主要区别是:
当函数使用 __cdecl 时,调用者负责堆栈清理。但是,当函数使用 __stdcall 时,被调用函数负责堆栈清理。
int WINAPI nSend(SOCKET s, const char *buf, int len,int flags);
int WINAPI nRecv(SOCKET s, char* buf, int len, int flags)
Run Code Online (Sandbox Code Playgroud)
浏览此处获取更多信息。
| 归档时间: |
|
| 查看次数: |
13231 次 |
| 最近记录: |