从应用层到MCU,看Windows处理键盘输入 [1.在应用层调试Notepad.exe (按键消费者)]

这篇具有很好参考价值的文章主要介绍了从应用层到MCU,看Windows处理键盘输入 [1.在应用层调试Notepad.exe (按键消费者)]。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

文本编辑器/文本编辑框是应用层常见的键盘处理程序。微软泄露的WinXP源码下有文本编辑器Notepad的实现:

Microsoft_leaked_source_code\nt5src\Source\XPSP1\NT\shell\osshell\accesory\notepad
从应用层到MCU,看Windows处理键盘输入 [1.在应用层调试Notepad.exe (按键消费者)]

文本编辑器的实现并不复杂,微软又(被迫)提供了Sample,因此本文就不重复造轮子了。本文从调试器的角度观察Notepad.exe如何消费键盘按键.

  1. Notepad接收WM_CHAR

首先评估一下调试Notepad.exe的难易程度(虽然有源码,我还是装作没有):

从应用层到MCU,看Windows处理键盘输入 [1.在应用层调试Notepad.exe (按键消费者)]

无壳且看着像是C++编译器生成

从应用层到MCU,看Windows处理键盘输入 [1.在应用层调试Notepad.exe (按键消费者)]

Notepad.exe属于标准的Windows窗口程序

既然猜测Notepad.exe是标准的窗口程序,那它一定按窗口程序的模板(如下)处理窗口消息,而作为键盘按键的消费者,WM_CHAR等按键消息亦包含其中:

    while (GetMessage((LPMSG)&msg, (HWND)NULL, 0, 0))
    {
        if (TranslateAccelerator(hwndNP, hAccel, (LPMSG)&msg) == 0)
        {
           TranslateMessage ((LPMSG)&msg);
           DispatchMessage ((LPMSG)&msg);
        }
    }

在跟踪消费者WM_CHAR的行为前,先要从茫茫众消息(窗体消息中有大量的鼠标移动的消息干扰分析)中筛选出WM_CHAR,思路如下:

  1. 定位GetMessage API;

  1. 分析GetMessage返回的消息,筛选出WM_CHAR消息;

下面看我分步实现上述思路:

  1. 定位GetMessage API。

先用IDA和windbg查找并定位Notepad.exe调用GetMessage API的身影:

从应用层到MCU,看Windows处理键盘输入 [1.在应用层调试Notepad.exe (按键消费者)]

根据IDA分析,Notepad.exe在WinMain中进行消息循环

0:001> x notepad!*main* ;先找符号winMain,再找GetMessage调用处
00007ff7`e4d0ad6c NOTEPAD!wWinMain (<no parameter info>)

0:001> uf NOTEPAD!wWinMain 
00007ff7`e4d0b010 488d4d0f        lea     rcx,[rbp+0Fh] ;<--获得窗体消息msg变量的地址
00007ff7`e4d0b014 4533c0          xor     r8d,r8d
00007ff7`e4d0b017 33d2            xor     edx,edx
00007ff7`e4d0b019 48ff1500bc0100  call    qword ptr [NOTEPAD!_imp_GetMessageW (00007ff7`e4d26c20)]
00007ff7`e4d0b020 0f1f440000      nop     dword ptr [rax+rax]
00007ff7`e4d0b025 85c0            test    eax,eax

简单说明上面windbg的输出:

L5处:GetMessage需要4个参数,参数1传入窗体消息MSG msg的地址。而我的OS是64位系统,所以Notepad.exe也是64位程序。64位程序依次通过rcx/rdx/r8/r9传入函数的前4个参数;

L9处:GetMessage已经返回,在此处下断点,查看MSG msg栈变量就可以获得窗体消息。

  1. 分析GetMessage返回的消息消息,筛选出WM_CHAR消息

为了使windbg能正确解析各个成员变量,需要明确告知windbg从GetMessage返回的窗体消息是个MSG结构体。MSG定义在combase.dll中:

0:001> dt combase!MSG
   +0x000 hwnd             : Ptr64 HWND__
   +0x008 message          : Uint4B
   +0x010 wParam           : Uint8B
   +0x018 lParam           : Int8B
   +0x020 time             : Uint4B
   +0x024 pt               : tagPOINT

在GetMessage返回处下断点,windbg停下后解析MSG内容:

0:001> bp 00007ff7`e4d0b020
0:001> g
Breakpoint 0 hit

0:000> dt combase!MSG [rbp+f]
   +0x000 hwnd             : 0x00000000`001001fe HWND__
   +0x008 message          : 0xf
   +0x010 wParam           : 0
   +0x018 lParam           : 0n0
   +0x020 time             : 0xaa1dbe
   +0x024 pt               : tagPOINT

其中:

L6处为窗口句柄,这和前面Spy++获得的窗口句柄值一致

L7处为消息类型,值0x0f对应WM_PAINT

#define WM_SETTEXT                      0x000C
#define WM_GETTEXT                      0x000D
#define WM_GETTEXTLENGTH                0x000E
#define WM_PAINT                        0x000F
#define WM_CLOSE                        0x0010

修改一下前面的断点,让它变为条件断点(条件断点略复杂,请移步windbg设置条件断点),每当Notepad.exe中按键,windbg打印WM_CHAR:

0:001> bp 00007ff7`e4d0b020 ".block{r @$t0=poi(rbp+0xf+0x08);.if(@$t0==0x102){.printf @\"WM_CHAR enter\";gc;};.else{gc;}}"
0:000> g
WM_CHAR enterWM_CHAR enter
从应用层到MCU,看Windows处理键盘输入 [1.在应用层调试Notepad.exe (按键消费者)]

随手在Notepad上输入几个字母,windbg艰难的吐出几个日志。效果挺好,就是挺卡的

  1. Notepad处理WM_CHAR/显示输出

Notepad.exe以文件映射的方式实现文本读写,它会将收到的按键内容暂存在所映射内存中,通过某种机制将这段内存内容显示在文本(文本编辑框)上。提一个问题,如果修改这段内存,是否导致最终文本内容被修改?以下面文本为例:

从应用层到MCU,看Windows处理键盘输入 [1.在应用层调试Notepad.exe (按键消费者)]

测试文本内容

  1. 验证Notepad是以文件映射的方式更新文本内容:

用Cheat Engine附加到Notepad进程,"Memory view"--Search--"Find memory"--在Find对话框中输入要查找的文本,同时勾选Unicode复选框输,即可在Cheat Engine中找到acpi.h中部分内容:

从应用层到MCU,看Windows处理键盘输入 [1.在应用层调试Notepad.exe (按键消费者)]
从应用层到MCU,看Windows处理键盘输入 [1.在应用层调试Notepad.exe (按键消费者)]
从应用层到MCU,看Windows处理键盘输入 [1.在应用层调试Notepad.exe (按键消费者)]

左框为文本的部分内容;右框为相应的内存映射的内容

至此,可以确定Notepad.exe的内容被映射的内存块。

(PS:其实用windbg在内存映射中搜索指定字符串,也可以取得相同结果。然而第一次尝试搜索时我以ansi字符串的方式搜索,没有找到该字符,疑惑中改用Cheat Engine)

0:003> s -u 0x20181900000 L?100000 "State" #windbg 搜索指定Unicode string
从应用层到MCU,看Windows处理键盘输入 [1.在应用层调试Notepad.exe (按键消费者)]

windbg的搜索结果

借用前面搜索指定字符串的输出结果,可以确定文本内容被映射到内存地址:0000020181967050。

#搜索acpi.h文件中第一行文字,确定所在的内存起始地址:
0:001> s -u 0x20181900000 L?100000 "typedef struct _GAS_20 {"
00000201`81967050  0074 0079 0070 0065 0064 0065 0066 0020  t.y.p.e.d.e.f. .
#以Unicode字符串形式打印起始地址的内容:
0:001> du 00000201`81967050
00000201`81967050  "typedef struct _GAS_20 {..    UI"
00000201`81967090  "NT8...AddrSpcID;          //The "
00000201`819670d0  "address space where the data str"
00000201`81967110  "ucture or register exists...    "
00000201`81967150  "                                "
00000201`81967190  "//Defined values are above      "
00000201`819671d0  "                                "
00000201`81967210  "      ..    UINT8...RegBitWidth;"
00000201`81967250  "..//The size in bits of the give"
00000201`81967290  "n register. ...........//When ad"
00000201`819672d0  "dressing a data structure, this "
00000201`81967310  "field must be zero...    UINT8.."

我们尝试修改该内存块,如果修改内存后直接会反应到文本上,那么可以证明Notepad确实通过内存映射的方式访问文件。

修改前我们再核对一下acpi.h的面貌,因为待会马上要整容了:

从应用层到MCU,看Windows处理键盘输入 [1.在应用层调试Notepad.exe (按键消费者)]

测试文本原始内容

#以Unicode string方式修改内存
0:004> eu 0x20181967050    "I don't know what to write"
#查看修改结果
0:004> du 0x20181967050    
00000201`81967050  "I don't know what to write    UI"
00000201`81967090  "NT8...AddrSpcID;          //The "
00000201`819670d0  "address space where the data str"
00000201`81967110  "ucture or register exists...    "
从应用层到MCU,看Windows处理键盘输入 [1.在应用层调试Notepad.exe (按键消费者)]

测试文本修改后的内容

由此,证明了我的猜想。

  1. 链接键盘输入和显示输出过程

上一节提出了一个问题:Notepad通过某种机制将这段内存内容显示在文本(文本编辑框)上。这一节简单的回答这个问题。

a.输入端:Notepad接收到WM_CHAR消息后,通过DispatchMessage,将消息传给文本编辑框句柄hwndEdit(为什么hwndEdit就是文本编辑框的句柄?这个可以参考张银奎老师的《格蠹汇编》一书);

b.hwndEdit所在窗体的Callback处理WM_CHAR,将键盘消息插入到内存映射所对应的Unicode String的恰当位置;

c.输出端:由hwndEdit调用SetDlgItemText将Unicode String显示到Notepad.exe对应的文本编辑框。Notepad源码通过下列方式,从hwndEdit窗口句柄获得文本内容:

    hEText= (HANDLE) SendMessage( hwndEdit, EM_GETHANDLE, 0, 0 ); //获得文本句柄
    if( !hEText )  // silently return if we can't get it
    {
        return( bStatus );
    }
    pStart= LocalLock( hEText ); //获得文本

本文完,下一篇将从应用层进入驱动层,看下i8042.sys怎么处理键盘按键文章来源地址https://www.toymoban.com/news/detail-479391.html

到了这里,关于从应用层到MCU,看Windows处理键盘输入 [1.在应用层调试Notepad.exe (按键消费者)]的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【网络】-- 应用层

    目录 TCP协议通讯流程 三次握手的过程 四次挥手的过程 TCP 和 UDP 对比 应用层 \\\"协议\\\" 网络版计算器 认识TCP 守护进程 铺垫讲解 守护进程讲解 setsid 总结         下图是基于TCP 协议的客户端 / 服务器程序的一般流程: TCP是面向连接的通讯协议,在通讯之前,需要进行 3次握

    2023年04月09日
    浏览(61)
  • 应用层与传输层~

    应用层是负责应用程序之间沟通的一层。由于不同的网络应用的应用进程之间,有着不同的通信规则,因此自然就需要应用层协议来解决这些问题,这就构成了应用层的主要内容即:精确定义这些通信规则。 应用层有不少应用广泛的协议,像域名系统(DNS)、文件传输协议(

    2023年04月08日
    浏览(43)
  • 第6章:应用层

    2023年09月10日
    浏览(42)
  • 应用层协议 HTTP

    我们已经学过 TCP/IP , 已然知道数据能从客户端进程经过路径选择跨网络传送到服务器端进程。 我们还需要知道的是,我们把数据从 A 端传送到 B 端, TCP/IP 解决的是顺丰的功能,而两端还要对数据进行加工处理或者使用,所以我们还需要一层协议,不关心通信细节,关心应用

    2024年02月06日
    浏览(45)
  • 应用层协议——http

    虽然我们说,应用层协议是我们自己定的,但实际上,已经有一些现成的,又非常好用的应用层协议,供我们直接参考使用。HTTP(超文本传输协议)就是其中之一。 平时我们俗称的 “网址” 其实就是说的 URL: 这里的登录信息现在已经隐藏起来,改成例如手机登录、微信登录

    2024年02月15日
    浏览(39)
  • 应用层协议——https

    HTTP 协议内容都是按照⽂本的⽅式明⽂传输的,这就导致在传输过程中出现⼀些被篡改的情况。HTTPS 也是⼀个应⽤层协议,是在 HTTP 协议的基础上引⼊了⼀个加密层。HTTPS的端口号是443。 它是在应用层和传输层间加了一个软件层,当进行网络传输时,从上而下就是在加密,从

    2024年02月12日
    浏览(45)
  • 计网 应用层 电子邮件

                         

    2024年02月13日
    浏览(56)
  • 【网络】应用层——HTTPS协议

    🐱作者:一只大喵咪1201 🐱专栏:《网络》 🔥格言: 你只管努力,剩下的交给时间! 前面本喵讲解并演示了HTTP协议,在比较 POST 和 GET 方法的时候,本喵说这两个方法都不安全,虽然 POST 的提交的表单内容在请求正文中,无法在地址的 url 中看到,但是它仍然是不安全的。

    2024年02月14日
    浏览(45)
  • 应用层 curl 用法指南

    curl 是常用的命令行工具,用来请求 Web 服务器。它的名字就是客户端(client)的 URL 工具的意思。 它的功能非常强大,命令行参数多达几十种。如果熟练的话,完全可以取代 Postman 这一类的图形界面工具。 本文介绍它的主要命令行参数,作为日常的参考,方便查阅。内容主

    2024年02月06日
    浏览(72)
  • 应用层:域名系统DNS

    笔记来源: 湖科大教书匠:应用层概述 湖科大教书匠:域名系统DNS 声明:该学习笔记来自湖科大教书匠,笔记仅做学习参考 DNS报文使用运输层的UDP协议进行封装,运输层端口号53 域名系统DNS的作用 域名(www.×××.com)- DNS - IP地址 - ARP - MAC地址 因特网不能只使用一台DNS服务

    2024年02月13日
    浏览(59)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包