易语言消息机制分析(消息拦截原理)
我自己做了个易语言的sig签名,方便分析的时候用.易语言例子是静态编译的.版本 5.11易语言其实是基于mfc的,它依然需要mfc的消息派发机制,只不过,自己当了系统与
用户间的代理人.所有的消息都要经它转发而已.我在MFC的消息派发函数_AfxDispatchCmdMsg
下断点,总能断下所有事件,包括按钮事件.我按下按钮,断在如下:
0045C7E0 _ /$55 push ebp ; ewnd._AfxDispatchCmdMsg(CCmdTarget *,uint,int,void (CCmdTarget::*)(void),void *,uint,AFX_CMDHANDLERINFO *)(guessed Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7)
0045C7E1 |.8BEC mov ebp, esp
0045C7E3 |.8B45 20 mov eax, dword ptr ss:
0045C7E6 |.53 push ebx
0045C7E7 |.56 push esi
0045C7E8 |.6A 01 push 1
在下面不远处,消息转发到了:
只是这有点麻烦了.我才不想一步一步绕到用户事件处理的地方.
因此,我们要找到易语言给用户派发消息的地方.
往下追踪:
00411688 |.FFD0 call eax ; ewnd.ProcessNotifySys(int,ulong,ulong)
处理消息的其中一步,继续吧
004116B4 |.E8 77C7FF call CKrnlApp::Notify(int,ulong,ulong)
再继续:
0040E36D |> \8B4424 34 mov eax, dword ptr ss: ; Case 7D8 of switch ewnd.40DE4F
0040E371 |.8BCE mov ecx, esi
0040E373 |.50 push eax ; /Arg1 =>
0040E374 |.E8 67A600 call CKrnlApp::ProcessEvent(EVENT_NOTIFY *) ; \ewnd.CKrnlApp::ProcessEvent(EVENT_NOTIFY *) //处理派发消息
0040E379 |.E9 580700 jmp 0040EAD6
0040E37E |>8B4C24 34 mov ecx, dword ptr ss: ; Case 7EF of switch ewnd.40DE4F
0040E382 |.51 push ecx ; /Arg1 =>
0040E383 |.8BCE mov ecx, esi ; |
0040E385 |.E8 06A700 call CKrnlApp::ProcessEvent(EVENT_NOTIFY2 *); \ewnd.CKrnlApp::ProcessEvent(EVENT_NOTIFY2 *)
0040E38A |.E9 470700 jmp 0040EAD6
0040E38F |>8B86 4802 mov eax, dword ptr ds: ; Case 7DB of switch ewnd.40DE4F
来到派发事件的地方了呢!跟进:
CPU Disasm
Address Hex dump Command Comments
00418A06 |.51 push ecx ; |Arg1 = ASCII "p"I"
00418A07 |.8B4D E8 mov ecx, dword ptr ss: ; |
00418A0A |.E8 419AFF call CKrnlApp::BeginProcessEvent(ulong,ulong,int,int) ;获取用户定义的消息
00418A0F |.8945 FC mov dword ptr ss:, eax
00418A12 |.837D FC 0 cmp dword ptr ss:, 0;判断这次的消息是不是用户的.
00418A16 |.75 04 jne short 00418A1C
00418A18 |.33C0 xor eax, eax
00418A1A |.EB 67 jmp short 00418A83
00418A1C |>56 push esi;是用户定义的消息,那就来到这里处理了.
00418A1D |.57 push edi
00418A1E |.8B55 08 mov edx, dword ptr ss:
00418A21 |.8B42 0C mov eax, dword ptr ds:
00418A24 |.83E8 01 sub eax, 1
00418A27 |.8945 EC mov dword ptr ss:, eax
00418A2A |.EB 09 jmp short 00418A35
00418A2C |>8B4D EC /mov ecx, dword ptr ss:
00418A2F |.83E9 01 |sub ecx, 1
00418A32 |.894D EC |mov dword ptr ss:, ecx
00418A35 |>837D EC 0 |cmp dword ptr ss:, 0
00418A39 |.7C 12 |jl short 00418A4D
00418A3B |.8B55 EC |mov edx, dword ptr ss:
00418A3E |.8B45 08 |mov eax, dword ptr ss:
00418A41 |.8B4C90 10 |mov ecx, dword ptr ds:
00418A45 |.894D F0 |mov dword ptr ss:, ecx
00418A48 |.FF75 F0 |push dword ptr ss:
00418A4B |.^ EB DF \jmp short 00418A2C
00418A4D |>FF55 FC call dword ptr ss: //调用用户消息处理例程.这就是所谓的事件特征码.
00418A50 |.5F pop edi
00418A51 |.5E pop esi
00418A52 |.895D F4 mov dword ptr ss:, ebx
看到我的注释了没?就是这样简单.我忘记是在哪儿看到的了,前辈们总结的易语言事件特征码:FF55FC5F5E.
看来原理很简单嘛.
现在总结一下:
易语言其实是基于mfc的,它注册了所有的事件,
由MFC事件派发函数_AfxDispatchCmdMsg把所有发生的事件派发给易语言,
此时易语言相当于用户.然后易语言调用CKrnlApp::Notify(int,ulong,ulong),派发事件,
调用CKrnlApp::ProcessEvent(EVENT_NOTIFY *)进一步处理派发的事件.
然后CKrnlApp::BeginProcessEvent(ulong,ulong,int,int)获取用户事件,如果匹配了,
就调用用户事件处理例程.
完美断下按钮事件:
转自看雪
{:5_188:}论坛怎么没有代码高亮的功能,一堆灰代码在一起看得好难受
本帖最后由 LWJ一辈子 于 2015-1-11 09:34 编辑
原来这就是易语言的消息体制{:6_222:}
前排,感谢恒大分享教程
感谢恒大分享!
{:5_127:}对于易语言彻底文盲了
目测是在某论坛转载过来的、我记得我看过
恒大的教程啊。看看先。
给了一个启示 回头再去弄那个
这下又涨姿识了,谢谢恒大的教程