博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Win32k(3) R0 to R3,键盘鼠标输入
阅读量:5235 次
发布时间:2019-06-14

本文共 3806 字,大约阅读时间需要 12 分钟。

第三部分 R0 to R3

 

这部分有教主非常精彩和实用的分析,我就不瞎说了。

 

r3 to r0 是常规系统调用倒过来

中断或者sysenter的东西:

 

NTSTATUS

KeUserModeCallback (

INULONGApiNumber,

INPVOIDInputBuffer,

INULONGInputLength,

OUTPVOID *OutputBuffer,

INPULONGOutputLength

)

这个函数设置好栈的布局后调用KiCallUserMode

KiCallUserMode调用_KiServiceExit

返回到ring3的_KeUserCallbackDispatcher

KeUserCallbackDispatcher从_PEB.KernelCallbackTable取得函数,执行,NtCallbackReturn返回

 

_PEB.KernelCallbackTable是函数表,ApiNumber是服务调用号

 

这些函数传递的参数可以参考windows_2000_source_code\win2k\private\ntos\w32\ntuser\inc\ntcb.h

 

不同版本不一定一样~

kd>dds 0x77d12970

77d12970 77d27f3c USER32!__fnCOPYDATA

77d12974  77d587b3USER32!__fnCOPYGLOBALDATA

77d12978 77d28ec8 USER32!__fnDWORD

77d1297c 77d2b149 USER32!__fnNCDESTROY

77d12980 77d5876c USER32!__fnDWORDOPTINLPMSG

77d12984 77d5896d USER32!__fnINOUTDRAG

77d12988 77d3b84d USER32!__fnGETTEXTLENGTHS

等等。。。

 

这个地方可以hook,XT也提供了检测这个位置的功能,不过hook这里的样本倒是没见过~这个字段在应用层是只读的~~

 

Hook wndproc的话倒是可以直接hook __fnINOUTLPPOINT5。不过太麻烦了,只是参数过滤的话就在KeUserModeCallback过滤了。

 

我看到过直接替换windows object里面wndproc参数的东东。

kd> k

ChildEBP RetAddr 

0012f738 77d18734 4may!WndProc+0x18[C:\Users\shendi\Desktop\梅亚飞监视u盘拷贝ppt_src\4may_src\4may.cpp @167]

0012f764 77d18816USER32!InternalCallWinProc+0x28

0012f7cc 77d28ea0USER32!UserCallWinProcCheckWow+0x150

0012f820 77d2d08aUSER32!DispatchClientMessage+0xa3

0012f848 7c92e453 USER32!__fnINOUTLPPOINT5+0x27

0012f848 805026fcntdll!KiUserCallbackDispatcher+0x13

b162b920 805a2d55 nt!KiCallUserMode+0x4

b162b97c bf83b414 nt!KeUserModeCallback+0x87

b162ba2c bf813f04 win32k!SfnINOUTLPPOINT5+0xbf

b162ba74 bf8140f6win32k!xxxSendMessageToClient+0x176

b162bac0 bf80ec99 win32k!xxxSendMessageTimeout+0x1a6

b162bae4 bf83b194 win32k!xxxSendMessage+0x1b

b162bb44 bf826c4cwin32k!xxxInitSendValidateMinMaxInfo+0x1b9

b162bb88 bf83a93c win32k!xxxAdjustSize+0x22

b162bc6c bf83967e win32k!xxxCreateWindowEx+0x8fe

b162bd20 8054267c win32k!NtUserCreateWindowEx+0x1c1

b162bd20 7c92e4f4 nt!KiFastCallEntry+0xfc

0012f848 7c92e453 ntdll!KiFastSystemCallRet

0012f890 77d2e389ntdll!KiUserCallbackDispatcher+0x13

0012fd34 77d2e442USER32!NtUserCreateWindowEx+0xc

0012fde0 77d2e4dc USER32!_CreateWindowEx+0x1ed

0012fe1c 00401451 USER32!CreateWindowExA+0x33

0012fea4 004010e8 4may!InitInstance+0x51[C:\Users\shendi\Desktop\梅亚飞监视u盘拷贝ppt_src\4may_src\4may.cpp @142]

0012ff20 00401fe3 4may!WinMain+0x58[C:\Users\shendi\Desktop\梅亚飞监视u盘拷贝ppt_src\4may_src\4may.cpp @48]

0012ffc0 7c817077 4may!WinMainCRTStartup+0x1b3[crtexe.c @ 330]

0012fff0 00000000 kernel32!BaseProcessStart+0x23

 

第四部分 键盘鼠标输入

中断服务把键盘码发给键盘驱动,csrss开一个线程win32k!RawInput循环read  irp给键盘驱动~

 

ROS最新的0.3.14  csrss调用NtUserCallOneParam,进入内核线程RawInputThreadMain,应该说这是更接近于windows的

 

看一下这个线程做了什么,键盘按键操作中的时候会pending,等待pending的操作没贴出来

 

for(;;)

    {

        Status =OpenInputDevice(&ghMouseDevice, &pMouDevice, L"\\Device\\PointerClass0");

        Status =OpenInputDevice(&ghKeyboardDevice, &pKbdDevice, L"\\Device\\KeyboardClass0");

 

MouStatus= ZwReadFile(ghMouseDevice,

                                       NULL,

                                       NULL,

                                       NULL,

&MouIosb,

&MouseInput,

sizeof(MOUSE_INPUT_DATA),

&ByteOffset,

                                       NULL);

 

 

KbdStatus= ZwReadFile(ghKeyboardDevice,

                                      NULL,

                                       NULL,

                                       NULL,

&KbdIosb,

&KeyInput,

sizeof(KEYBOARD_INPUT_DATA),

&ByteOffset,

                                       NULL);

 

 

UserProcessMouseInput(&MouseInput);

 

UserProcessKeyboardInput(&KeyInput);

}

KEYBOARD_INPUT_DATA这个结构是键盘驱动上传数据标准结构

 

UserProcessKeyboardInput这个函数

 

//得到目前的焦点,这个实在desktop的结构里

pFocusQueue= IntGetFocusMessageQueue();

 

if (pFocusQueue)

    {

pFocusThread= pFocusQueue->Thread;

if(pFocusThread&&pFocusThread->Tcb.Win32Thread)

pKl= ((PTHREADINFO)pFocusThread->Tcb.Win32Thread)->KeyboardLayout;

    }

//键盘布局

if (!pKl)

pKl= W32kGetDefaultKeyLayout();

 

将扫描码转换成虚拟按键,最后调用

 

UserSendKeyboardInput(&KbdInput,FALSE);

 

最终ProcessKeyEvent在处理完hook以及其他特殊情况以后

 

MsqPostMessage(pFocusQueue,&Msg, TRUE, QS_KEY);发送给焦点窗口

 

所以说要拦截键盘消息太底层就要自己处理扫描码了~~当然也不是不行

 

软件可以模拟键盘输入,就是NtUserSendInput啦

类别:  

转载于:https://www.cnblogs.com/retme/archive/2012/03/26/2494891.html

你可能感兴趣的文章
enote笔记法使用范例(1)——自己总结的一些编写代码的常识 (a)
查看>>
backgroundWorker 的callback和主线程的调度
查看>>
jsp页面中添加 enctype="multipart-formdata'无法提交到后台得解决思路
查看>>
Python连接SQLite数据库
查看>>
JS网页播放声音实现代码兼容各种浏览器
查看>>
RSA加密通信小结(二)-新版本APP与后台通信交互内容修改方案
查看>>
(二十五)、强引用 、软引用、 弱引用、虚引用
查看>>
redisTemplate实现轻量级消息队列, 异步处理excel并实现腾讯云cos文件上传下载
查看>>
USACO 1.5 Prime Palindromes
查看>>
FOI 2019 游记
查看>>
javascript 之作用域链-07
查看>>
3.20上午
查看>>
windows安装redis
查看>>
[LeetCode] Count and Say
查看>>
【代码片段】HTML5基本结构及常用默认模版
查看>>
Maven:Generating Project in Batch mode 卡住问题
查看>>
IBinder在进程之间传递一个对象的形式(一)
查看>>
过滤器与拦截器的区别(转)
查看>>
关于521
查看>>
浅谈XXE攻击
查看>>