偷换windows窗口过程
来源:互联网 发布:淘宝联盟用了红包丢单 编辑:程序博客网 时间:2024/05/21 06:25
Window user32子动态库控件封装和消息分发浅析 这篇文章提到窗口程序在分发消息时会依次调用:UserCallWinProcCheckWow--->_InternalCallWinProc-->各个窗口程序的WndProc。各类控件的窗口程序不同,比如Button控件用的是Button_WndProc,程序通过_InternalCallWinProc最终进入Button_WndProc对Button事件处理。受到这篇文章的启示,我尝试用windbg修改calc.exe的窗口程序,并记录于此。
网上一些文章提及万能消息断点时,无不例外的都会带到_InternalCallWinProc这个函数,综合各家所言和自己调试的过程,我得到如下结论:
1._InternalCallWinProc的函数接口可能为:
_InternalCallWinProc(WndProc*,Hwnd,UINT,WPARAM,LPARAM);参数1是程序在调用RegisterClass(Ex)时注册的窗口过程,参数2是接收消息的窗口的句柄,参数3是消息号。从参数2到参数5,类似于传递给WndProc接口的参数。
2.在_InternalCallWinProc函数中会以参数1传入的函数指针作为消息的窗口过程,将参数2-5压栈传给它并跳转到该窗口过程。可能的实现如下(xp):
_InternalCallWinProc(){ (*WndProc)(Hwnd,UINT,WPARAM,LPARAM);}(win7)
_InternalCallWinProc(){ push LPARAM push WPARAM push UINT push Hwnd jmp WndProc}回到我的正题上,我要做的是偷换窗口过程。xp到win7都没有检测函数指针WndProc的合法性(至少在windbg中是这样),所以,我们可以把这个指针值偷换为其他代码(可以通过注入代码的形式实现)。作为演示的目的,我把calc.exe按键7的WndProc替换为ExitProcess函数,以下为实现步骤:
1.用spy++定位按键7的句柄:
2.windbg attach到calc.exe,设置符号并查找符号_InternalCallWinProc
0:001> x *!*internalcall* @查找符号InternalCallWinProc地址77d1870c USER32!InternalCallWinProc = <no type information>0:001> x *!Button_* @查找Button控件符号地址771a7725 comctl32!Button_CalcRect = <no type information>0:001> bp USER32!InternalCallWinProc0:001> gBreakpoint 0 hitUSER32!InternalCallWinProc:77d1870c 55 push ebp0:000> kbChildEBP RetAddr Args to Child 00>0007fd30 77d18816 7365912a 000101b2 00000219 USER32!InternalCallWinProc01>0007fd98 77d189cd 00000000 7365912a 000101b2 USER32!UserCallWinProcCheckWow+0x15002>0007fdf8 77d18a10 0007fee8 00000000 0007ff1c USER32!DispatchMessageWorker+0x30603>0007fe08 010021a7 0007fee8 7c80b731 000a2348 USER32!DispatchMessageW+0xf...0007fff0 00000000 01012475 00000000 78746341 kernel32!BaseProcessStart+0x23@栈回溯00>处的0x7365912a是计算机窗口过程的函数指针0:000> ln 7365912a (7365912a) msctfime!UIWndProc | (7365913a) msctfime!CtfImeDestroyInputContextExact matches: msctfime!UIWndProc (<no parameter info>)@查看地址0x7365912a附近的符号是msctfime!UIWndProc,有点像一个窗口过程3.准备下条件断点。来分析一下断点要满足的需求:如果我们在Button控件(Button控件的窗口过程为comctl32!Button_CalcRect)"7"(spy++显示句柄值0x001016A判断)上按下左键(消息值为0x201)时,使windbg中断。把这段话转变为windbg能理解的命令:
0:000> bp comctl32!Button_WndProc ".if(dwo(esp+4)==0001016A&dwo(esp+8)==201){.echo Button7Down;}.else{gc;}"0:000> g其中dwo(esp+4)用于判断按键7的窗口句柄值,dwo(esp+8)用于判断消息值是否为左键按下。我们看下断点的效果:
当我按下7,windbg在输出窗口输出"Button7Down",看来断点生效了~再来看下调用堆栈:
0:000> kbChildEBP RetAddr Args to Child 00> 0007fd04 77d18734 0001016a 00000201 00000001 comctl32!Button_WndProc01> 0007fd30 77d18816 771a8eb4 0001016a 00000201 USER32!InternalCallWinProc+0x2802> 0007fd98 77d189cd 00000000 771a8eb4 0001016a USER32!UserCallWinProcCheckWow+0x15003> 0007fdf8 77d18a10 0007fee8 00000000 0007ff1c USER32!DispatchMessageWorker+0x30604> 0007fe08 010021a7 0007fee8 7c80b731 000a2348 USER32!DispatchMessageW+0xf...0007ffc0 7c817067 00330039 00360037 7ffd3000 calc+0x125e90007fff0 00000000 01012475 00000000 78746341 kernel32!BaseProcessStart+0x23按调用栈可以看到是USER32!InternalCallWinProc调用了comctl32!Button_WndProc,现在我们回过头来看下前面我得到的结论对不对----USER32!InternalCallWinProc的参数1存放了处理消息的窗口过程:
0:000> ln 771a8eb4 (771a8eb4) comctl32!Button_WndProc | (771a99c9) comctl32!InitButtonClassExact matches: comctl32!Button_WndProc = <no type information>果不其然,0x771a8eb4是Button控件的消息处理函数!
既然USER32!InternalCallWinProc对参数1传入的值不加甄别,我完全可以对USER32!InternalCallWinProc下同样的条件断点,触发断点后在函数入口处修改参数1的值,把他指向进程空间中其他一段可执行代码,那就ExitProcess了:
0:000> x *!*ExitProcess*7c81cafa kernel32!ExitProcess = <no type information>0:000> bp USER32!InternalCallWinProc ".if(dwo(esp+8)==0001016A&dwo(esp+c)==201){.echo Button7Down;}.else{gc;}"0:000> gButton7Downeax=c0000000 ebx=00000000 ecx=40000000 edx=00000040 esi=771a8eb4 edi=0007fd6ceip=77d1870c esp=0007fd34 ebp=0007fd98 iopl=0 ov up ei ng nz na pe cycs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000a87USER32!InternalCallWinProc:77d1870c 55 push ebp0:000> kbChildEBP RetAddr Args to Child 0007fd30 77d18816 771a8eb4 0001016a 00000201 USER32!InternalCallWinProc0007fd98 77d189cd 00000000 771a8eb4 0001016a USER32!UserCallWinProcCheckWow+0x150@注意传入给InternalCallWinProc的函数指针位于参数2,所以要修改的是esp+80:000> ed 0007fd30+8 7c81cafa 0:000> geax=000000c0 ebx=00000102 ecx=77d2b401 edx=0007f720 esi=000000d4 edi=00000000eip=7c92e4f4 esp=00bfff24 ebp=00bfff88 iopl=0 nv up ei pl zr na pe nccs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246ntdll!KiFastSystemCallRet: <--------------进程退出7c92e4f4 c3 ret修改参数2后,继续执行windbg马上就能看到进程退出,有意思吧?来看下任务栏的截图:
calc.exe已经不复存在,偷换成功~
本篇完~
- 偷换windows窗口过程
- windows窗口创建过程
- Windows窗口的实现过程
- windows程序设计 窗口过程函数
- Windows窗口程序运行过程
- 窗口破坏过程与Windows消息循环
- 窗口破坏过程与Windows消息循环
- 窗口破坏过程与Windows消息循环
- 一个简单的Windows窗口过程
- 《Windows核心编程》の窗口过程的使用
- windows 消息机制、窗口过程与线程间消息传递
- 从Windows消息的角度看窗口应用程序运行过程
- windows编程学习笔记(2)窗口过程函数
- windows 消息机制、窗口过程与线程间消息传递
- Windows程序设计(SDK)窗口过程---程序 的关闭
- 利用Windows绘制界面并且编写窗口过程函数
- Windows,C++编程创建窗口的过程详解
- Windows编程——实现创建一个窗口过程
- kafka教程-基本概念
- HDU
- Java三大框架搭建
- boost库简单读写xml
- 山东省第八届ACM省赛 J 题(company)
- 偷换windows窗口过程
- Linux 存储管理 缺页中断和页面换入
- [LeetCode
- HDU 1059 Dividing (多重背包二进制优化)
- 数据结构-C++ 迷宫
- [算法]n阶台阶,一次走一步或两步,有多少种走法?
- K-means KNN AND KD-tree
- [C++]图的邻接矩阵、邻接表及其相互转化和邻接表的广度遍历、深度遍历
- JVM(1):Java 类的加载机制