如题,谢谢大家了,如果没有现成的代码能够指条路子也行。
解决方案 »
- 图和“去除”黑色背景(2D游戏中,将黑色背景特效图片改成透明通道的特效图片)
- 换个思路再来问
- 如何知道文件的目录
- vc通过com方式如何读取指定的Excel中的内容
- 一组.C文件和.h文件,再加一个makefile文件,大侠门知道怎么编译吗?
- 怎麼我的電腦沒有 net send 命令???
- 如何在对话框上加工具条样子的按钮
- 一个很菜的问题,初学的我想了好几天也没解决,大家来帮我一下吧
- Gina !!!在线等待....
- 如何改变对话框的标题栏的背景色?
- 请问大家,在新建的工程里面有个后面三个字母是App的类,比如CMydlgApp,这一般是干什么用的?
- 为什么在多线程中画三维动画,缓冲区没有交互,也就是没有动画效果
使用HOOK 将会降低系统效率,因为它增加了系统处量消息的工作量。建议在必要时才使用HOOK,并在消息处理完成后立即移去该HOOK。
HOOK链
WINDOWS提供了几种不同类型的HOOKS;不同的HOOK可以处理不同的消息。例如,WH_MOUSE HOOK用来监视鼠标消息。
WINDOWS为这几种HOOKS维护着各自的HOOK链。HOOK链是一个由应用程序定义的回调函数队列,当某种类型的消息发生时,WINDOWS向此种类型的HOOK链的第一个函数发送该消息,在第一函数处理完该消息后由该函数向链表中的下一个函数传递消息,依次向下。如果链中某个函数没有向下传送该消息,那么链表中后面的函数将得不到此消息。(对于某些类型的HOOK,不管HOOK链中的函数是否向下传递消息,与此类型HOOK联系的所有HOOK函数都会收到系统发送的消息)
HOOK过程
为了拦截特定的消息,你可以使用SetWindowsHookEx函数在该类型的HOOK链中安装你自己的HOOK函数。该函数语法如下:
public function MyHook(nCode,wParam,iParam) as long
‘加入代码
end function
其中MyHook可以随便命名,其它不能变。该函数必须放在模块段。nCode指定HOOK类型。wParam,iParam的取值随nCode不同而不同,它代表了某种类型的HOOK的某个特定的动作。
SetWindowsHookEx总是将你的HOOK函数放置在HOOK链的顶端。你可以使用CallNextHookEx函数将系统消息传递给HOOK链中的下一个函数。
[注释]对于某些类型的HOOK,系统将向该类的所有HOOK函数发送消息,这时,HOOK函数中的CallNextHookEx语句将被忽略。
全局HOOK函数可以拦截系统中所有线程的某个特定的消息(此时该HOOK函数必须放置在DLL中),局部HOOK函数可以拦截指定线程的某特定消息(此时该HOOK函数可以放置在DLL中,也可以放置在应用程序的模块段)。
[注释] 建议只在调试时使用全局HOOK函数。全局HOOK函数将降低系统效率,并且会同其它使用该类HOOK的应用程序产生冲突。HOOK类型
WH_CALLWNDPROC 和 WH_CALLWNDPROCRET HOOK
WH_CALLWNDPROC 和WH_CALLWNDPROCRET HOOK可以监视SendMessage发送的消息。系统在向窗体过程发送消息前,将调用WH_CALLWNDPROC;在窗体过程处理完该消息后系统将调用WH_CALLWNDPROCRET。
WH_CALLWNDPROCRET HOOK会向HOOK过程传送一个CWPRETSTRUCT结构的地址。该结构包含了窗体过程处理系统消息后的一些信息。
WH_CBT Hook
系统在激活,创建,消毁,最小化,最大化,移动,改变窗体前;在完成一条系统命令前;在从系统消息队列中移去鼠标或键盘事件前;在设置输入焦点前,或同步系统消息队列前,将调用WH_CBT HOOK。你可以在你的HOOK 过程拦截该类HOOK,并返回一个值,告诉系统,是否继续执行上面的操作。
WH_DEBUG HOOK
系统在调用与某种HOOK类型联系的HOOK过程前,将调用WH_DEBUG ,应用程序可以使用该HOOK决定是否让系统执行某种类型的HOOK。
WH_FOREGROUNDIDLE Hook
系统在空闲时调用该HOOK,在后台执行优先权较低的应用程序。
WH_GETMESSAGE Hook
WH_GETMESSAGE Hook使应用程序可以拦截GetMessage 或 PeekMessage的消息。应用程序使用WH_GETMESSAGE HOOK监视鼠标、键盘输入和发送到队列中的其它消息。
WH_JOURNALRECORD Hook
WH_JOURNALRECORD Hook使应用程序可以监视输入事件。典型地,应用程序使用该HOOK记录鼠标、键盘输入事件以供以后回放。该HOOK是全局HOOK,并且不能在指定线程中使用。
WH_JOURNALPLAYBACK Hook
` WH_JOURNALPLAYBACK Hook使应用程序可以向系统消息队列中插入消息。该HOOK可以回放以前由WH_JOURNALRECORD HOOK录制的鼠标、键盘输入事件。在WH_JOURNALPLAYBACK Hook安装到系统时,鼠标、键盘输入事件将被屏蔽。该HOOK同样是一个全局HOOK,不能在指定线程中使用。
WH_JOURNALPLAYBACK Hook返回一个时间暂停值,它告诉系统,在处理当前回放的消息时,系统等待百分之几秒。这使得此HOOK可以控制在回放时的时间事件。
WH_KEYBOARD Hook
WH_KEYBOARD Hook使应用程序可以监视由GetMessage和PeekMessage返回的WM_KEYDOWN 及WM_KEYUP消息。应用程序使用该HOOK监视发送到消息队列中的键盘输入。
WH_MOUSE Hook
WH_MOUSE Hook 使应用程序可以监视由GetMessage和PeekMessage返回的消息。应用程序使用该HOOK监视发送到消息队列中的鼠标输入。
WH_MSGFILTER and WH_SYSMSGFILTER Hooks
WH_MSGFILTER 和WH_SYSMSGFILTER Hooks使应用程序可以监视菜单、滚动条、消息框、对话框,当用户使用ALT+TAB或ALT+ESC来切换窗体时,该HOOK也可以拦截到消息。WH_MSGFILTER仅在应用程序内部监视菜单、滚动条、消息框、对话框,而WH_SYSMSGFILTER则可以在系统内监视所有应用程序的这些事件。
WH_SHELL Hook
一个SHELL程序可以使用WH_SHELL Hook来接收重要的信息。当一个SHELL程序被激活前或当前窗体被创建、消毁时,系统会调用WH_SHELL Hook过程。
使用HOOK
安装、消毁HOOK过程
监视系统事件安装、消毁HOOK过程
使用SetWindowsHookEx函数,指定一个HOOK类型,自己的HOOK过程是全局还是局部HOOK,同时给出HOOK过程的进入点,就可以轻松的安装你自己的HOOK过程。
为了安装一个全局HOOK过程,必须在应用程序外建立一个DLL,并将该HOOK函数封装到其中,应用程序在安装全局HOOK过程时必须先得到该DLL模块的句柄。将DLL名传递给LoadLibrary 函数,就会得到该DLL模块的句柄;得到该句柄 后,使用GetProcAddress函数可以得到HOOK过程的地址。最后,使用SetWindowsHookEx将HOOK过程的首址嵌入相应的HOOK链中,SetWindowsHookEx传递一个模块句柄,它为HOOK过程的进入点,线程标识符置为0,指出:该HOOK过程同系统中的所有线程关联。
以下是C写的例程,大家可以方便的转换为VB程序。
HOOKPROC hkprcSysMsg;
static HINSTANCE hinstDLL;
static HHOOK hhookSysMsg;
hinstDLL = LoadLibrary((LPCTSTR) "c:\\windows\\sysmsg.dll");
hkprcSysMsg = (HOOKPROC)GetProcAddress(hinstDLL, "SysMessageProc");
hhookSysMsg = SetWindowsHookEx(WH_SYSMSGFILTER,
hkprcSysMsg, hinstDLL, 0);
异常窗口的特征是指?
另,只能用hook就没有其他的办法了吗?
关掉异常弹出的窗口是可以的.
用消息钩子监控WM_SHOWWINDOW消息,如果符合条件,则post wm_close 消息
具体框架如下:
1.取得进程ID,Win98/2000下用ToolHelp函数Process32First,Process32Next,
NT4.0下用PSAPI,EnumProcess
2.用DebugAPI调试进程,这需要写一个线程来等待调试事件CREATE_PROCESS_DEBUG_INFO dbgProcInfo;DWORD WINAPI ThreadProc(LPVOID lParam){
if(!DebugActiveProcess(dwProcessID)){
MessageBox(NULL,"调试进程失败!",NULL,MB_OK);
return -1;
}
DEBUG_EVENT dbg;
while(WaitForDebugEvent(&dbg,INFINITE)){
//被调试进程触发退出事件
if(dbg.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT){
break;
}
//调试进程后将立刻触发的事件
//可以将结构CREATE_PROCESS_DEBUG_INFO保存,留作后用,
//结构具体定义参看msdn或Winbase.H
if(dbg.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT){
dbgProcInfo = dbg.u.CreateProcessInfo;
}
//被调试进程发生异常
//值得注意的是在上面的CREATE_PROCESS_DEBUG_EVENT触发后,
//紧接着就会触发一个int 3异常,中断被调试进程,只需简单的
//::ContinueDebugEvent(dbg.dwProcessId,dbg.dwThreadId,DBG_CONTINUE);
//就行了,被调试进程就会继续执行.
else if(dbg.dwDebugEventCode == EXCEPTION_DEBUG_EVENT){
//结构DEBUG_EVENT中就存储着异常代码
//dbg.u.Exception.ExceptionRecord.ExceptionCode [异常代码]
//可以在这里选择做出异常处理,常见异常有:
//EXCEPTION_ACCESS_VIOLATION = C0000005h 读写内存冲突
//EXCEPTION_INT_DIVIDE_BY_ZERO = C0000094h 非法除0
//EXCEPTION_STACK_OVERFLOW = C00000FDh 堆栈溢出或者越界
//EXCEPTION_GUARD_PAGE = 80000001h 由Virtual Alloc建立起来的属性页冲突
//EXCEPTION_NONCONTINUABLE_EXCEPTION = C0000025h
//不可持续异常,程序无法恢复执行,异常处理例程不应处理这个异常
//EXCEPTION_INVALID_DISPOSITION = C0000026h
//在异常处理过程中系统使用的代码
//EXCEPTION_BREAKPOINT = 80000003h 调试时因代码中int3中断
//EXCEPTION_SINGLE_STEP = 80000004h 处于被单步调试状态(int 1)
//还有一些我就不一一列出了,参看msdn
}
//下一句是将调试事件处理完之后的后续手段,dwContinueFlag 通常用DBG_CONTINUE
//也就是让被调试进程继续执行
//另外还可以用以下常数:(msdn中都有)
//DBG_TERMINATE_THREAD
//DBG_TERMINATE_PROCESS
//DBG_CONTROL_C
//DBG_CONTROL_BREAK
//DBG_EXCEPTION_NOT_HANDLED
::ContinueDebugEvent(dbg.dwProcessId,dbg.dwThreadId,dwContinueFlag);
}
}至于关闭windows 的异常窗体,说实在的没用,既然你的进程发生了未处理异常,
强制关闭windows 的提示窗口,进程也无法继续了。如果非要这么做的话,建议向进程的地址空间中插入一段异常处理代码.
windows 弹出异常窗体是因为发生未处理异常,如果你插入处理代码就不会了在插入的代码中作如下处理
//ExceptionFilterProc即异常处理函数
SetUnhandledExceptionFilter(ExceptionFilterProc);
异常处理函数定义如下
DWORD __stdcall ExceptionFilterProc(EXCEPTION_POINTERS *){
//如果你能处理该异常就处理,否则直接返回
//返回值有如下选择
//EXCEPTION_EXECUTE_HANDLER = 1 已经处理了异常,结束程序
//EXCEPTION_CONTINUE_SEARCH = 0 不处理异常,转交系统处理(将弹出windows的消息框)
//EXCEPTION_CONTINUE_EXECUTION = -1 修复错误,从异常发生处继续执行
}这些东西虽然不是什么新鲜玩艺,也并不复杂,但如果你是初次接触的话,
还是得花些功夫去研究的。建议学学Win32 ASM,看看在ASM中是怎样使用SEH的。
1.用户程序发生异常后,将被系统捕获
2.Windows内部采用了结构化异常处理(SEH)来处理捕获的异常
SEH有两种,一种是进程相关SEH,用API SetUnhandledExceptionFilter(ExpProc)
来设置处理函数,进程中的任意一个线程发生异常都会在这处理.
另一中是线程相关SEH,这是一个链式结构的DD,只处理指定相关线程中的异常,
如果你没有在这个链中插入自己的异常处理函数,系统将弹出错误框,然后结束进程。
3.在VC中,M$将SEH封装为
__try{
}__finally{
}
和
__try{
}__except(DWORD ExceptionProc()){
}两种
我采用你的方法基本上可以实现我的功能了,但现在有一个问题就是无论被调试程序有没有异常,只要我把调试程序关掉,被调试的程序也被关掉了,怎样才能使关掉调试程序时被调试程序(没有异常时)依然正常运行呢?
被DebuAPI挂接后的进程是无法摆脱挂接的,
即调试进程结束后,被调试进程必然被结束。一个小经验:如果你想杀掉任务器中的一个进程,但任务
管理器却告诉你“拒绝访问”,你可以选中进程,点鼠标
右键,选择“调试”(当然,机器里得有调试器,如VC),
就可以kill它了,对付某些恶心的病毒还是挺有用的.
或者把exe当一个module使用loadLibrary读取进取,GetProcAddress导出main函数,try执行。
当然,你的读取exe得exe得修改编译设置,不能把基地址指定0x400000