我写了一个钩子的类,用bc6编译和调用的时候遇到点问题,用bc2010编译变成了局部钩子,大家帮忙看下,谢谢!
这是在头文件声明的THOOK类
class THOOK
{
FARPROC fp;
FARPROC newfp;
HMODULE hModule;
BYTE OldCode[5];
BYTE NewCode[5];
DWORD OldFnID;
DWORD NewFnID;
public:
int flag;
bool bHook;
THOOK *next;
THOOK();
void HookOn();
void HookOff();
bool init(char *dllname,char *prname,FARPROC MyP);
~THOOK();
};
THOOK::THOOK()
{
flag=-1;
bHook=false;
for(int i=0;i<5;i++)
{
OldCode[i]=0xe9;
NewCode[i]=0;
}
fp=NULL;
newfp=NULL;
hModule=NULL;
OldFnID=0;
NewFnID=0;
next=NULL;
}
THOOK::~THOOK()
{
flag=-1;
if(bHook) HookOff();
delete(OldCode);
delete(NewCode);
fp=NULL;
newfp=NULL;
hModule=NULL;
//用BC6编译时如果调用出错在这里或是构造函数里任意地方添加空行再编译,调用就会成功
//这也就是我的第一个问题,用BC2010编译就不会出现调用错误;
OldFnID=0;
NewFnID=0;
if(next)
{
delete(next);
next=NULL;
}
}
bool THOOK::init(char *dllname,char *prname,FARPROC MyP)
{
hModule=GetModuleHandle(dllname);
fp=GetProcAddress(hModule,prname);
if(fp==NULL) return false;
Move(fp,OldCode,5);
newfp=MyP;
NewCode[0]=0Xe9;
DWORD *addr;
addr=(DWORD *)(NewCode+1);
*addr=DWORD(newfp)-DWORD(fp)-5;
NewFnID=GetCurrentProcessId();
OldFnID=NewFnID;
HookOn();
return true;
}
void THOOK::HookOn()
{
OldFnID=NewFnID;
HANDLE hProc=OpenProcess(PROCESS_ALL_ACCESS,0,OldFnID);
VirtualProtectEx(hProc,fp,5,PAGE_READWRITE,&OldFnID);
WriteProcessMemory(hProc,fp,NewCode,5,0);
VirtualProtectEx(hProc,fp,5,OldFnID,&OldFnID);
bHook=true;
}
void THOOK::HookOff()
{
OldFnID=NewFnID;
HANDLE hProc=OpenProcess(PROCESS_ALL_ACCESS,0,OldFnID);
VirtualProtectEx(hProc,fp,5,PAGE_READWRITE,&OldFnID);
WriteProcessMemory(hProc,fp,OldCode,5,0);
VirtualProtectEx(hProc,fp,5,OldFnID,&OldFnID);
bHook=false;
}
//---------------------------------------
#include <vcl.h>
#include <stdio.h>
#include <windows.h>
#include <winsock2.h>
#include "THOOK.h"
#pragma hdrstop
#pragma argsused
HHOOK g_hHook;
HINSTANCE g_hinstDll;
THOOK *THookHandle;
bool bHooked=false;
//--------------------------添加函数需修改部分一------------------------------------
const int countP=4;
int WINAPI MyRecv(SOCKET s, char FAR* buf, int len, int flags); //---1
int WINAPI MySend(SOCKET s, char FAR* buf, int len, int flags); //---2
int WINAPI MyConnect( SOCKET s, const struct sockaddr FAR* name, int namelen); //---3
int WINAPI MyBind( SOCKET s, const struct sockaddr FAR* name, int namelen); //---4
//--------------------------------------------
LRESULT WINAPI HookProc(int nCode,WPARAM wParam,LPARAM lParam)
{
return (CallNextHookEx(g_hHook,nCode,wParam,lParam));
}
extern "C" bool _declspec(dllexport) _stdcall InstallHook(HWND hWnd)
{
if(!g_hHook)
g_hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)HookProc,g_hinstDll,0);
if(!g_hHook) return false;
THOOK *p;
p=THookHandle;
while(p)
{
if(!p->bHook)
{
p->HookOn();
}
p=p->next;
}
bHooked=true;
return true;
}
extern "C" bool _declspec(dllexport) _stdcall UninstallHook()
{
bool result=false;
if(g_hHook)
{
result=UnhookWindowsHookEx(g_hHook);
if(bHooked)
{
THOOK *p;
p=THookHandle;
while(p)
{
if(p->bHook) p->HookOff();
p=p->next;
}
bHooked=false;
}
SendMessage(HWND_BROADCAST,WM_SETTINGCHANGE,0,0);
}
g_hHook=NULL;
return result;
}
void WINAPI checksum(char FAR* buf )
{
int size=20;
unsigned long cksum=0;
while(size >1)
{
cksum+=*buf++;
size -=sizeof(USHORT);
}
if(size ) cksum += *(UCHAR*)buf;
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16);
cksum=~cksum;
buf[10]=char(cksum&0x00ff);
buf[11]=char(cksum>>8);
}
//--------------------------添加函数需修改部分二------------------------------------
int WINAPI MyRecv(SOCKET s, char FAR* buf, int len, int flags)
{
int res;
THOOK *p;
p=THookHandle;
while(p&&p->flag!=1)
{
p=p->next;
}
p->HookOff();
res=recv(s,buf,len,flags);
p->HookOn();
return res;
}
int WINAPI MySend(SOCKET s, char FAR* buf, int len, int flags)
{
int res;
THOOK *p;
p=THookHandle;
while(p&&p->flag!=2)
{
p=p->next;
}
p->HookOff();
res=send(s,buf,len,flags);
p->HookOn();
return res;
}
int WINAPI MyConnect( SOCKET s, const struct sockaddr FAR* name,int namelen)
{
int res;
THOOK *p;
p=THookHandle;
while(p&&p->flag!=3)
{
p=p->next;
}
SOCKADDR_IN Newsin;
memcpy(&Newsin,name,namelen);
Newsin.sin_family=AF_INET;
sendiphdr.destIP=0x0701a8c0;
Newsin.sin_port=htons(10026);
//for(int i=0;i<8;i++) Newsin.sin_zero[i]=0;这里如果用0填充,端口就会变成10791,ip修改没问题
p->HookOff();
res=connect(s,(LPSOCKADDR)&Newsin, namelen);
p->HookOn();
if(res<0)
{
int err=WSAGetLastError();
String rlt=IntToStr(err);
MessageBoxA(NULL,rlt.c_str(),"ERRO",MB_OK);
}
return res;
}
int WINAPI MyBind( SOCKET s, const struct sockaddr FAR* name, int namelen)
{
int res;
THOOK *p;
p=THookHandle;
while(p&&p->flag!=4)
{
p=p->next;
}
p->HookOff();
res=MyBind(s,name,namelen);
p->HookOn();
MessageBoxA(NULL,"挂钩bind成功!","OK",MB_OK);
return res;
}
//-------------------------------------------
#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
g_hinstDll=hinst;
THOOK *p;
switch(reason)
{
case DLL_PROCESS_ATTACH:
{
bool hooked[countP];
p=THookHandle;
int countnow=0;
while(!p&&countnow<countP)
{
countnow++;
if(!THookHandle)
{
THookHandle=new(THOOK);
p=THookHandle;
}
else
{
p=THookHandle;
while(p->next)
{
p=p->next;
}
p->next=new(THOOK);
p=p->next;
}
switch(countnow)
{
//--------------------------添加函数需修改部分三------------------------------------
case 1:
hooked[countnow-1]=p->init("ws2_32.dll","recv",(FARPROC )MyRecv);
break;
case 2:
hooked[countnow-1]=p->init("ws2_32.dll","send",(FARPROC )MySend);
break;
case 3:
hooked[countnow-1]=p->init("ws2_32.dll","connect",(FARPROC )MyConnect);
break;
case 4:
hooked[countnow-1]=p->init("ws2_32.dll","bind",(FARPROC )MyBind);
break;
//-----------------------------------------------
}
if(hooked[countnow-1])
{
p->flag=countnow;
}
if(p->flag<countP) p=p->next;
//MessageBoxA(NULL,"成功!","OK",MB_OK);
}
for(int i=0;i<countP;i++)
{
hooked[0]=hooked[0]&&hooked[i];
hooked[countP-1]=hooked[countP-1]|hooked[i];
}
if(!hooked[countP-1])
{
MessageBoxA(NULL,"初始化函数错误!","ERROR",MB_OK);
return (false);
}
if(!hooked[0])
{
MessageBoxA(NULL,"部分函数无法初始化!","ERROR",MB_OK);
return (false);
}
}
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
if(bHooked&&THookHandle)
{
delete(THookHandle);
}
break;
}
return true;
}
//---------------------------------------
也不是一个线程安全的操作。 想想: 两个线程, 第一个发现 bHook 为 false, 那么它就会去执行一些操作, 然后设置 bHook 为 true. 关键是, 在它执行操作的过程中, bHook 仍然为 false , 此时另一个线程发现是 false 也会去执行相关的操作。