作者:任岩松中学阮赢毅
如果转载,请署名作者。
猜想1:通过窗口子类化操作
验证:不可行,因为子类化操作还是需要窗口接收消息,仍会被断,被断后函数代码也会导向处理消息代码,所以没有达到绕过消息断点的作用。
猜想2:通过钩子操作
初步设想:先用SetWindowsHookEx截获消息,然后将截获的消息分发到原来要去发到的目的窗口,修改msg参数(即窗口处理函数第二个函数,比如:SetWindowsHookEX一下键盘,然后通过SendMessage(hwnd,Msg,键盘码,0)来进行操作,再通过在窗口函数上设置对自定义的Msg的处理,实际等同于对WM_KEYDOWN或WM_KEYUP的处理。
问题:但是OLLBGY消息断点是如何实现的呢?如果消息断点也是通过建立钩子而得以实现,根据钩子的安装特点:先安装的在后,后安装的在前,那么调试器的消息断点在我执行自己的钩子函数之前,那么仍然会被断掉
验证:通过自己创建一个窗口,按上面所说的钩子操作,结果不会被断,说明消息断点不是通过建立钩子而实现的
示例程序://C++编写
#include <windows.h>
HWND HookHwnd; //挂钩的窗口
UINT HookMsg; //子定义的窗口Msg
int HookBool; //窗口是自建的还是调用的
WNDPROC HookProc; //老地址
HHOOK HookID; //钩子标示符
char StoreString[50]; //返回输入的字符
LRESULT CALLBACK AvoidProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam){//逃脱钩子的函数
if(lParam&0x80000000){//按一个键会产生两个事件:WM_KEYDOWN和WM_KEYUP,所以去掉一个
if(Msg== HookMsg){//如果消息MSG等于自定义Msg,则进行下面的代码,可以通过在这里填入代码,来进行处理
static int n; //
static char HideString[50];
HideString[n]='*';
StoreString[n]=wParam;
n=n+1; //索引加一
SetWindowText(hwnd,HideString); //是输入的字符显示成字符串“*”
return 1;
}
}
return CallWindowProc ((WNDPROC)HookProc,hwnd,Msg,wParam,lParam);//调用旧窗口
}
LRESULT CALLBACK MessageHook(int nCode,WPARAM wParam,LPARAM lParam){//钩子的回调函数
if (GetFocus()==HookHwnd){//判断输入焦点是不是想逃脱断点的窗口
if (HookBool==1){
static int Count;//判断是否已进行过GetWindowLong
if (Count==0){
HookProc=(WNDPROC)GetWindowLong(HookHwnd,GWL_WNDPROC); //得到以前的窗口
HookProc = (WNDPROC)SetWindowLong(HookHwnd, GWL_WNDPROC, (LONG)AvoidProc);//窗口子类化
Count=1;
}
}
PostMessage(HookHwnd,HookMsg,wParam,lParam);//传递消息
}
return 1;
}
int MessageBreakAvoid(HWND hwnd,UINT msg,int Bool){//挂钩的函数,并进行一些初始化
HookHwnd=hwnd; //初始化
HookMsg=msg;
HookBool=Bool;
HookID=SetWindowsHookEx(WH_KEYBOARD,MessageHook,GetModuleHandle(NULL),GetCurrentThreadId());//进行挂钩
return 0;
}
int UnMessageBreakAvoid(){//删除钩子
UnhookWindowsHookEx(HookID);
return 0;
}
本来是想把这个编写成一个类的,然后让AvoidProc函数成为虚函数,但是编成类后,总会出现错误,好像是调用约定什么的,于是就弄成这个样子了,大家有兴趣的话,可以编写个MessageBreakAvoid类,然后把AvoidProc函数弄成虚函数,这样就是一个比较标准的接口了,
后面的代码是紧接着上面的写的,是示范如何使用的,
int PASCAL WinMain(HINSTANCE MyHinst,HINSTANCE hPrev,LPSTR CmdLine,int ShowNumber){
HWND hwndB=CreateWindow("edit","个人简介",WS_VISIBLE,20,130,950,950,NULL,NULL,MyHinst,NULL);
ShowWindow(hwndB,1);
UpdateWindow(hwndB);
MSG MyMsg;
MessageBreakAvoid(hwndB,1101,1); ///注意这里
while (GetMessage(&MyMsg, NULL, 0, 0))
{
TranslateMessage(&MyMsg);
DispatchMessage(&MyMsg);
}
UnMessageBreakAvoid;
return TRUE;
}
先创建个窗口,然后MessageBreakAvoid一下,就可以逃过消息断点了,MessageBreakAvoid的第二个参数是把WM_KEYDOWN或WM_KEYUP转换成的自定义消息,我这里设成1101,大家设的时候,尽量设大点,不然和windows的自己的消息码冲突就不好了,
第三个参数是用来判断是不是自建的窗口函数,如果是自建的,你可以在自己的窗口函数代码处写入对1101的处理,如果不是,你可以在AvoidProc里写入对1101的处理,我这里是调用自带"edit"所以是1..
调试结果:成功绕过OllyDbg的消息跟踪
- 标 题:关于如何绕过消息断点的一篇文章(软件保护)
- 作 者:RYYMike
- 时 间:2008-10-11 22:14
- 链 接:http://bbs.pediy.com/showthread.php?t=74472