以前CSDN上有过另一个HookApi的办法, 我贴在下面, 看完后请大家帮忙回答这样的问题:
为什么必须有一个Dll才行呢? 我曾试图将Dll和测试程序中的诸函数写到同一个程序中, 发现只是在这一个程序中HookApi起作用, 其它的MessageBox照旧, 这是什么原因呢? 难道User32.dll在内存中不仅有一个实例? 我查看内存发现在我的程序中MessageBoxA的入口处被修改了, 而在别的程序中仍是原来的, 这让我不明所以.
请各位不吝键盘, up有分.
为什么必须有一个Dll才行呢? 我曾试图将Dll和测试程序中的诸函数写到同一个程序中, 发现只是在这一个程序中HookApi起作用, 其它的MessageBox照旧, 这是什么原因呢? 难道User32.dll在内存中不仅有一个实例? 我查看内存发现在我的程序中MessageBoxA的入口处被修改了, 而在别的程序中仍是原来的, 这让我不明所以.
请各位不吝键盘, up有分.
解决方案 »
- 微软的截网络包库
- #pragma warning(enable:怎么用?
- 如何讲ACCESS里文本型的日期取出来放到日期控件里啊??
- 为什么下面的代码不能实现拷贝功能??出现"无法读取源文件或者磁盘"的错误
- 我在我的程序里使用directshow,在任何的对话框中加入#include <dshow.h>,都出现如下错误,是为什么,谢谢
- 请高手指教
- vc++中从屏幕输入指定字符,再在.txt文件中查找它,如果找到则删除。
- 在vc中用DirectShow做播放器,要怎样连接哪些库?
- 诚聘英才!模仿VC设断点的方法,很容易吗?我不觉得!
- 如何做一个真正的dll
- 如何改变标题栏字体的样式,比如说改成粗体,还有改颜色
- 这个函数是什么意思:(这里没msdn) InvokeHelper(0x66, DISPATCH_METHOD, VT_EMPTY, NULL, NULL);
-----------------------------------------------------
smhpnuaa(2002-7-18 14:56:13) 这么多高手在这里,哎,小弟愿意向各位高手学习
Api拦截并不是一个新的技术,很多商业软件都采用这种技术。对windows的Api函数的拦截,不外乎两种方法,第一种是Mr. Jeffrey Richter 的修改exe文件的模块输入节,种方法,很安全,但很复杂,而且有些exe文件,没有Dll的输入符号的列表,有可能出现拦截不到的情况。第二种方法就是常用的JMP XXX的方法,虽然很古老,却很简单实用。
本文一介绍第二种方法在Win2k下的使用。第二种方法,Win98/me 下因为进入Ring0级的方法很多,有LDT,IDT,Vxd等方法,很容易在内存中动态修改代码,但在Win2k下,这些方法都不能用,写WDM太过复杂,表面上看来很难实现,
其实不然。Win2k为我们提供了一个强大的内存Api操作函数---VirtualProtectEx,WriteProcessMemeory,ReadProcessMemeory,有了它们我们就能在内存中动态修改代码了,其原型为:
BOOL VirtualProtectEx(
HANDLE hProcess, // 要修改内存的进程句柄
LPVOID lpAddress, // 要修改内存的起始地址
DWORD dwSize, // 修改内存的字节
DWORD flNewProtect, // 修改后的内存属性
PDWORD lpflOldProtect // 修改前的内存属性的地址
);
BOOL WriteProcessMemory(
HANDLE hProcess, // 要写进程的句柄
LPVOID lpBaseAddress, // 写内存的起始地址
LPVOID lpBuffer, // 写入数据的地址
DWORD nSize, // 要写的字节数
LPDWORD lpNumberOfBytesWritten // 实际写入的子节数
);
BOOL ReadProcessMemory(
HANDLE hProcess, // 要读进程的句柄
LPCVOID lpBaseAddress, // 读内存的起始地址
LPVOID lpBuffer, // 读入数据的地址
DWORD nSize, // 要读入的字节数
LPDWORD lpNumberOfBytesRead // 实际读入的子节数
);
具体的参数请参看MSDN帮助。在Win2k下因为Dll和所属进程在同一地址空间,这点又和Win9x/me存在所有进程存在共享的地址空间不同,
因此,必须通过钩子函数和远程注入进程的方法,现以一个简单采用钩子函数对MessageBoxA进行拦截例子来说明:
其中Dll文件为:
HHOOK g_hHook;
HINSTANCE g_hinstDll;
FARPROC pfMessageBoxA;
int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);
BYTE OldMessageBoxACode[5],NewMessageBoxACode[5];
HMODULE hModule ;
DWORD dwIdOld,dwIdNew;
BOOL bHook=false;
void HookOn();
void HookOff();
BOOL init();
LRESULT WINAPI MousHook(int nCode,WPARAM wParam,LPARAM lParam);
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
if(!init())
{
MessageBoxA(NULL,"Init","ERROR",MB_OK);
return(false);
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
if(bHook) UnintallHook();
break;
}
return TRUE;
}
LRESULT WINAPI Hook(int nCode,WPARAM wParam,LPARAM lParam)//空的钩子函数
{
return(CallNextHookEx(g_hHook,nCode,wParam,lParam));
}
HOOKAPI2_API BOOL InstallHook()//输出安装空的钩子函数
{
g_hinstDll=LoadLibrary("HookApi2.dll");
g_hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)Hook,g_hinstDll,0);
if (!g_hHook)
{
MessageBoxA(NULL,"SET ERROR","ERROR",MB_OK);
return(false);
}
return(true);
}
HOOKAPI2_API BOOL UninstallHook()//输出御在钩子函数
{
return(UnhookWindowsHookEx(g_hHook));
} BOOL init()//初始化得到MessageBoxA的地址,并生成Jmp XXX(MyMessageBoxA)的跳转指令
{
hModule=LoadLibrary("user32.dll");
pfMessageBoxA=GetProcAddress(hModule,"MessageBoxA");
if(pfMessageBoxA==NULL)
return false;
_asm
{
lea edi,OldMessageBoxACode
mov esi,pfMessageBoxA
cld
movsd
movsb
}
NewMessageBoxACode[0]=0xe9;//jmp MyMessageBoxA的相对地址的指令
_asm
{
lea eax,MyMessageBoxA
mov ebx,pfMessageBoxA
sub eax,ebx
sub eax,5
mov dword ptr [NewMessageBoxACode+1],eax
}
dwIdNew=GetCurrentProcessId(); //得到所属进程的ID
dwIdOld=dwIdNew;
HookOn();//开始拦截
return(true);
} int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption, UINT uType )//首先关闭拦截,然后才能调用被拦截的Api 函数
{
int nReturn=0;
HookOff();
nReturn=MessageBoxA(hWnd,"Hook",lpCaption,uType);
HookOn();
return(nReturn);
}
void HookOn()
{
HANDLE hProc;
dwIdOld=dwIdNew;
hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);//得到所属进程的句柄
VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为可写
WriteProcessMemory(hProc,pfMessageBoxA,NewMessageBoxACode,5,0);//将所属进程中MessageBoxA的前5个字节改为JMP 到MyMessageBoxA
VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为原来的属性
bHook=true;
}
void HookOff()//将所属进程中JMP MyMessageBoxA的代码改为Jmp MessageBoxA
{
HANDLE hProc;
dwIdOld=dwIdNew;
hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);
VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);
WriteProcessMemory(hProc,pfMessageBoxA,OldMessageBoxACode,5,0);
VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);
bHook=false;
}
//测试文件:
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
if(!InstallHook())
{
MessageBoxA(NULL,"Hook Error!","Hook",MB_OK);
return 1;
}
MessageBoxA(NULL,"TEST","TEST",MB_OK);//可以看见Test变成了Hook,也可以在其他进程中看见
if(!UninstallHook())
{
MessageBoxA(NULL,"Uninstall Error!","Hook",MB_OK);
return 1;
}
return 0;
}
另外,在我的程序中看起来的确是将代码注入到User32.dll中了,为什么rujor(rujor)说“你的和序不可能注入其它进程德空间吧”呢?dll和我的程序有什么区别呢?
================================================================我是anothervip
================================================================
好好学习,天天向上
================================================================
dll可以的阿~
1、建立对话框程序
2、添加两个按钮BtnInit和Button1
3、加入以下代码:
FARPROC pfMessageBoxA;
int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);
BYTE OldMessageBoxACode[5],NewMessageBoxACode[5];
HMODULE hModule ;
DWORD dwIdOld,dwIdNew;
BOOL bHook=false; void HookOn();
void HookOff();
BOOL init();
int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption, UINT uType );BOOL init()//初始化得到MessageBoxA的地址,并生成Jmp XXX(MyMessageBoxA)的跳转指令
{
hModule=LoadLibrary("user32.dll");
pfMessageBoxA=GetProcAddress(hModule,"MessageBoxA");
if(pfMessageBoxA==NULL)
return false;
_asm
{
lea edi,OldMessageBoxACode
mov esi,pfMessageBoxA
cld
movsd
movsb
}
NewMessageBoxACode[0]=0xe9;//jmp MyMessageBoxA的相对地址的指令
_asm
{
lea eax,MyMessageBoxA
mov ebx,pfMessageBoxA
sub eax,ebx
sub eax,5
mov dword ptr [NewMessageBoxACode+1],eax
}
//dwIdNew=GetCurrentProcessId(); //得到所属进程的ID
//dwIdOld=dwIdNew;
dwIdOld=GetCurrentProcessId(); //得到所属进程的ID
HookOn();//开始拦截
return(true);
} int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption, UINT uType )//首先关闭拦截,然后才能调用被拦截的Api 函数
{
int nReturn=0;
HookOff();
// nReturn=MessageBoxA(hWnd,"Hook",lpCaption,uType);
nReturn=MessageBoxA(hWnd,"HHHHHHHHook","Hahahaha",uType);
HookOn();
return(nReturn);
}
void HookOn()
{
HANDLE hProc;
DWORD dwOldProtect;
//dwIdOld=dwIdNew;
hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);//得到所属进程的句柄
VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwOldProtect);//修改所属进程中MessageBoxA的前5个字节的属性为可写
WriteProcessMemory(hProc,pfMessageBoxA,NewMessageBoxACode,5,0);//将所属进程中MessageBoxA的前5个字节改为JMP 到MyMessageBoxA
VirtualProtectEx(hProc,pfMessageBoxA,5,dwOldProtect,&dwOldProtect);//修改所属进程中MessageBoxA的前5个字节的属性为原来的属性
bHook=true;
}
void HookOff()//将所属进程中JMP MyMessageBoxA的代码改为Jmp MessageBoxA
{
HANDLE hProc;
DWORD dwOldProtect;
//dwIdOld=dwIdNew;
hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);
VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwOldProtect);
WriteProcessMemory(hProc,pfMessageBoxA,OldMessageBoxACode,5,0);
VirtualProtectEx(hProc,pfMessageBoxA,5,dwOldProtect,&dwOldProtect);
bHook=false;
} void CXXXDlg::OnButton1()
{
::MessageBoxA(NULL,"TEST","TEST",MB_OK);
}void CXXXDlg::OnBtnInit()
{
init();
}
4、运行。点BtnInit来初始化,然后点Button1可以看到对话框变了。
5、运行别的程序(含有对话框的),发现对话框没变。
别的程序即使不能jmp到我的程序中,至少函数入口处我是修改了的呀,可是我在调试别的程序时观察内存,发现函数入口处根本不是我的E9XXXXXXXX,仍然是原来的代码。这是为什么呢?
刚刚看到你的回复,好像明白了许多。但是,如你所说,做成DLL去修改内存内容也应该是修改的一份拷贝呀,为什么却能起到作用呢?
你没有修改别的程序的代码~
你只是改了自己程序的代码~
而做成dll使用了Hook就不一样了~
把你的修改程序注入到各个进程的地址空间~
就可以随心所欲的修改了~
在98下由于机制不一样~
就不一定了~
Copy on Write Page Protection for Windows NT(Q103858)WriteProcessMemory所修改的pfMessageBoxA页面不是原始的DLL页面,而是原始页面的拷贝。这个拷贝映射到了本进程的pfMessageBoxA地址上,而其他的进程pfMessageBoxA的地址还是映射的原始页面。
以上只是我对于hook的看法(再Win 2k中),小弟也是初学者, 如有什么地方说错了,还希望各位大虾纠正,先谢谢了.