我写了一个钩子的类,用bc6编译和调用的时候遇到点问题,用bc2010编译变成了局部钩子,大家帮忙看下,谢谢!

shLeon 2012-05-03 02:45:18
这是在头文件声明的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;
}
//---------------------------------------------------------------------------



遇到的问题主要有几点:
1、用BC6编译,钩子是全局的,用BC2010编译钩子是局部的;
2、用BC2010编译调用时不会出错,用BC6编译调用时经常会出错,但是头文件里加减一空行再编译错误就消除了;
3、在钩子卸掉后会导致一些程序出错,比如IE,卸载的时候复原工作也没看出什么问题啊;
4、SOCKADDR_IN结构中的sin_zero[8]在修改ip和port后填0,修改的ip正常,但是port却还是原来的
重点还是第2、3个问题,我想了很久没想明白,是我的编译器有问题还是在哪里疏漏了什么,,哪位大侠能指导下,谢谢!
...全文
108 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
shLeon 2012-05-05
  • 打赏
  • 举报
回复
写错了,应该是while(!p->bHook){}

可能误导了你,结构里面的bHook只有在成员函数hookoff()和hookon()里面被修改,
而while(!p->bHook){}只有等到另一个进程hookon()以后才能往下执行而不会去执行其他,应该可以的
shLeon 2012-05-04
  • 打赏
  • 举报
回复
就是为了每次函数的重入才构造个类重入应该是没问题了,,刚又遇到个问题依旧是BC2010编译没问题,BC6编译出错率达30%以上,,代码很简单,,是不是我的BC6真的有问题了?
HINSTANCE hin=ShellExecute(NULL,"open",".\\fsload.exe",NULL,NULL,SW_SHOWNORMAL);
Sleep(500);
if(hin)
{
HWND hwndHandle = FindWindow("TForm_Client","封神啸天辅助工具 Ver:1.9.0");
unsigned long int PID;
GetWindowThreadProcessId(hwndHandle,&PID);
char *title="啸天";
bool q=SetWindowText(hwndHandle,title);

}
CCED136 2012-05-04
  • 打赏
  • 举报
回复
这个判断语句 while(!bHook){}

也不是一个线程安全的操作。 想想: 两个线程, 第一个发现 bHook 为 false, 那么它就会去执行一些操作, 然后设置 bHook 为 true. 关键是, 在它执行操作的过程中, bHook 仍然为 false , 此时另一个线程发现是 false 也会去执行相关的操作。
CCED136 2012-05-04
  • 打赏
  • 举报
回复
也不对, 应该创建一个同步区段来控制, HookOff 中加锁, 其他线程调用 HookOff 会阻塞, 直到前一个线程调用 HookOn 解锁之后, 其他线程被阻塞的 HookOff 才能继续
shLeon 2012-05-04
  • 打赏
  • 举报
回复
嗯嗯,是的,调用HookOff()前应该先检查一下bHook加一句
while(!bHook){}
这样或许能够解决第3个问题,试试看
CCED136 2012-05-04
  • 打赏
  • 举报
回复
感觉不对哦, 你 HookOff HookOn 函数实际上并没有执行同步保护。

想想, 目标程序多线程调用 Socket 函数, 假如现在一个线程刚进入你的 MyRecv 函数,你在函数中调用了 HookOff , 然后调用实际的 recv 功能, 由于 recv 功能耗时, 在recv 函数还没有返回的时候,

注意,这个时候第二个线程也开始调用你的 MyRecv 函数, 也执行 HookOff 功能了, 想想是否混乱了?
CCED136 2012-05-03
  • 打赏
  • 举报
回复
修改函数首 4 字节数据的 API HOOK 方式, 特别需要注意函数重入问题。一般,最好加个同步区段,把并行变成串行操作。

1,316

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder 网络及通讯开发
社区管理员
  • 网络及通讯开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧