更改 Windows 7 屏幕键盘中的特定配置值

更改 Windows 7 屏幕键盘中的特定配置值

我必须使用 Windows 7 的屏幕键盘来输入:

(如果您尚未使用,您可以通过以下方式获取:所有项目->配件->四通八达的交通网络->屏幕键盘

或者直接搜索“osk.exe”)

屏幕键盘

它提供了“悬停”按钮的功能。微软对此的描述如下:

在悬停模式下,您可以使用鼠标或操纵杆指向某个键并持续预定的一段时间,然后会自动输入所选字符。

这是我的具体问题。预定义的时间段对我来说太长了。最短时间为 0.5 秒(最长 3 秒)。

有什么办法改变这个值<0.5?例如通过编辑注册表?

编辑:该条目HKEY_CURRENT_USER\Software\Microsoft\Osk\HoverPeriod不能设置为低于 500 毫秒。

编辑(2):我认为解决我的问题的唯一方法是反编译 .exe(我猜它是用 C 编写的,或者?)并更改最小时间。然后我必须再次编译它。这个过程可行吗?什么事情可能会失败?

任何有用的建议都棒极了!

答案1

它在代码的哪里找到我们的密钥?

使用进程监视器,深入研究 ETL 事件,读出该值堆栈跟踪给我们:

"Frame","Module","Location","Address","Path"
...
"3","ntdll.dll","NtQueryValueKey + 0xa","0x7fbce17344a","C:\Windows\SYSTEM32\ntdll.dll"
"4","KERNELBASE.dll","LocalBaseRegQueryValue + 0x15d","0x7fbcb1a3e1d","C:\Windows\system32\KERNELBASE.dll"
"5","KERNELBASE.dll","RegQueryValueExW + 0xe9","0x7fbcb1a3c19","C:\Windows\system32\KERNELBASE.dll"
"6","ADVAPI32.dll","RegQueryValueExWStub + 0x1e","0x7fbcba412fe","C:\Windows\system32\ADVAPI32.dll"
"7","osk.exe","OSKSettingsManager::GetOskSetting + 0xc7","0x7f72356057f","C:\Windows\System32\osk.exe"
"8","osk.exe","OSKSettingsManager::Initialize + 0x6e","0x7f72355ffe2","C:\Windows\System32\osk.exe"
"9","osk.exe","OSKSettingsManager::GetOSKSettingsManager + 0x64","0x7f72355fee4","C:\Windows\System32\osk.exe"
"10","osk.exe","COskNativeHWNDHost::DetermineOSKWindowSizeAndLimits + 0x5a","0x7f72355d4fa","C:\Windows\System32\osk.exe"
"11","osk.exe","COskNativeHWNDHost::Initialize + 0xaa","0x7f72355d28e","C:\Windows\System32\osk.exe"
"12","osk.exe","PresentOSK + 0x112","0x7f723557882","C:\Windows\System32\osk.exe"
"13","osk.exe","wWinMain + 0x356","0x7f723557f16","C:\Windows\System32\osk.exe"
"14","osk.exe","operator new[] + 0x37a","0x7f723564b12","C:\Windows\System32\osk.exe"
"15","KERNEL32.DLL","BaseThreadInitThunk + 0x1a","0x7fbcd24298e","C:\Windows\system32\KERNEL32.DLL"
"16","ntdll.dll","RtlUserThreadStart + 0x1d","0x7fbce19e229","C:\Windows\SYSTEM32\ntdll.dll"

我们可以看到OSKSettingsManager::GetOskSetting读出了值。

那么,这部分是什么样子的?我们可以调试它吗?

使用 WinDBG 查看该函数,它在之前访问该注册表项000007f7 23560517

osk!OSKSettingsManager::GetOskSetting:
...
000007f7`2356050e ff15440bfeff    call    qword ptr [osk!_imp_RegOpenKeyExW (000007f7`23541058)]
000007f7`23560514 448bd8          mov     r11d,eax
000007f7`23560517 85c0            test    eax,eax
000007f7`23560519 751f            jne     osk!OSKSettingsManager::GetOskSetting+0x82 (000007f7`2356053a)
000007f7`2356051b 488b0b          mov     rcx,qword ptr [rbx]
...

现在,这里的问题是,当我尝试在该位置设置断点时,我无法再输入任何内容,因为它会将其自身添加到输入驱动程序中。通过按住键盘上的修饰键(这会在 中点亮)osk.exe可以轻松看到这一点。Altosk.exe

查看加法或减法的代码,我只看到40十六进制发生了一些事情,也就是64十进制。所以这也与数字无关。

它可能出现在四条cmp(比较)指令之一中,但这需要调试信息。或者它可能出现在更高级的函数中,这需要更多调查。但如果没有在不失去输入能力的情况下对其进行调试的能力,这将是一件非常困难的事情……

似乎找到正确的位置需要调试电缆,因为调试的计算机会失去输入功能,或者由于调试开销而运行得太慢。由于我目前没有带 1943 端口的笔记本电脑,我无法自己进行调试。它可以做到这一点,是的,它会真正冻结你的操作系统。调试操作系统而不是应用程序很有趣……^^

等一下,我们已经访问了符号!我们能找到有问题的代码吗?

OSKSettingsManager::ClearTransferKey(void)
OSKSettingsManager::GetOSKSettingsManager(OSKSettingsManager * *)
OSKSettingsManager::GetOskSetting(ulong,ulong *)
OSKSettingsManager::GetOskSetting(ulong,ulong *,int)
OSKSettingsManager::Initialize(void)
OSKSettingsManager::NotifyListeners(ulong,ulong)
OSKSettingsManager::RegisterListener(void (*)(ulong,ulong))
OSKSettingsManager::SQMStartupSettings(void)
OSKSettingsManager::SetOskSetting(ulong,ulong)
OSKSettingsManager::SetOskSetting(ulong,ulong,int)
OSKSettingsManager::_HandleUpdateAllListeners(void)
OSKSettingsManager::_KeepSettingValueInBounds(ulong,ulong *,int)
OSKSettingsManager::`scalar deleting destructor'(uint)

仔细观察,你会注意到有问题的功能:

OSKSettingsManager::_KeepSettingValueInBounds(ulong,ulong *,int)

如果我们浏览该函数,我们首先会看到:

mov     edi, edi
push    ebp
mov     ebp, esp
mov     eax, [ebp+arg_4]
imul    eax, 14h
cmp     dword_4B7598[eax], 0
jz      short loc_41BC36        

好的,这会比较某些内容,然后跳转到另一个位置。那里有什么?

pop     ebp
retn    8

因此,如果条件决定必须跳转,它就会离开该函数而不会改变任何东西。

那么,我们如何让它始终离开该函数呢?

jz将指令改为jmp总是执行跳转的指令,你可以在相对偏移量处找到它41BC10。如果你的程序计算的偏移量不同,你需要知道它使用什么401000作为基础,这样减去就可以得到绝对偏移量1AC10

请注意,在十六进制编辑器中将74( JZ) 更改为E9( JMP) 不起作用。您无法在十六进制编辑器中执行此操作,您需要某种可以反汇编和重新汇编代码的工具,但这种工具不一定容易找到(例如,人们实际付费购买的 IDA Professional 无法生成正确的 c 代码或可执行文件。补丁社区中常用的 OllyDBG 甚至无法打开可执行文件。)。甚至,Microsoft 可能正在保护其可执行文件免遭篡改,因为这可能被视为违反 EULA;所以,祝你好运!

哎!这很难,我只想用鼠标/眼睛/快速打字……

你一定要看看达舍尔这比屏幕键盘快得多。它只需将鼠标移向字母即可;水平移动决定速度,垂直移动选择字母。它内置字典,甚至可以将最有可能的字母放大,它还会尝试从您的移动中学习,以便速度和字母真正适应您的使用。

一张图片胜过千言万语......

当然,这只是一个示例,它相当小,速度也不算快,但您可以调整其大小,使其位于屏幕右侧,这样它就不会干扰您的屏幕。这样您就可以尽可能快地打字……

这是一个很好的例子,说明预测如何帮助您更快地输入任何语言:

还要注意的是,右侧的字母是按特定顺序排列的,这样主要方向(上、中或下)会在不同的类型(小写、大写、数字和标点)之间进行选择;然后在这个主要方向内,您的次要方向会在 AZ、az、0-9 等之间进行选择。我过去曾使用过这个,与其他竞争对手相比,它的流畅程度确实让我感到惊讶……

还要注意,Dasher 有一些配置,因此您可能能够调整一些您不喜欢的东西。

答案2

我担心大多数反编译器无法产生足够好的结果以供重新编译。

反编译只能帮助精确定位所HKEY_CURRENT_USER\Software\Microsoft\Osk\HoverPeriod使用的区域,从而找出读取该值的位置以及强制执行 500 毫秒限制的位置。

一旦找到,您应该修补二进制代码以禁用测试并强制 HoverPeriod 更小。修补二进制文件比重新编译更可行。

如果 osk.exe 被 Windows Update 取代(我并不期望发生这种情况),您可能需要重复这一努力。

[编辑]

为了给您提供更多帮助,这里有一些关于实用程序及其用法的词语。

您可以使用 C 反编译器或反汇编器。后一种类型可能更有用,尽管它需要一些 Intel 指令集方面的知识。您还需要一个好的十六进制编辑器,有些编辑器宣传具有反汇编器功能(见下面的链接)。

芬里斯计划宣称自己是“适用于代码分析、调试、协议分析、逆向工程、取证、诊断、安全审计、漏洞研究和许多其他用途的工具套件”。听起来不错,许多人推荐,但我没有用过。

REC Studio 反编译器尝试生成用于构建可执行文件的代码和数据的类似 C 的表示形式。

回旋镖是一个通用的、开源的、可重定向的机器代码程序反编译器。

通过谷歌搜索或在以下位置可以找到更多此类实用程序:

wikibooks x86 反汇编/分析工具
wikibooks x86 反汇编/反汇编器和反编译器
开放目录:反汇编程序

第一步是反汇编 osk。结果列表可能很长,需要一个好的文本编辑器(通常 notepad++ 就足够了)。

搜索字符串“HoverPeriod”(不区分大小写)。如果幸运的话,反汇编程序会将其识别为字符串,您可以按原样找到它。如果不幸运,则需要逐字节搜索。作为 Unicode 字符串,它看起来像H,0,o,0,v,0...字母应该被其数字代码替换的地方。

一旦找到“HoverPeriod”字符串,反汇编程序应该在它前面的某个地方放置一个标签。使用这个生成的标签的名称来搜索它在哪里使用,以确定它从注册表中检索到的位置以及结果存储在哪个全局变量中。

找到保存计数的变量后,搜索它被使用的位置。您要做什么取决于您找到的代码的格式。然后您可以决定所需的补丁。

例如,您可能想要使用十六进制编辑器在 osk.exe 中替换如下命令:

move AX,<HoverPeriod milliseconds count variable>

进入

mov AX,200       (your count of 200 milliseconds)

注意不同的命令长度,如果新命令较短,则需要用单字节 NOP 指令(无操作)填充到旧指令的长度。

如果反汇编程序给出的偏移量在代码中而不是在 exe 文件中,则可能需要搜索 osk.exe 中要修补的命令。如果十六进制编辑器不支持汇编程序搜索,请在列出原始指令字节的同时进行反汇编,这样您就会知道要搜索哪些二进制字节。避免搜索包含地址的指令,因为地址可能会在 exe 中重新定位,因此最好搜索靠近此类指令的字节序列。

如果十六进制编辑器支持汇编程序,您可以直接在十六进制编辑器中创建新的补丁字节。如果十六进制编辑器不支持汇编程序,而您又不熟悉英特尔机器代码,请找到一个汇编程序来编译您的新代码,然后使用其列表获取用于修补的已编译字节。

答案3

我可以建议使用自动识别自动点击?

这个想法是当光标位于屏幕窗口内时监视鼠标空闲情况(例如在控制循环中,定期检查光标是否改变了位置)并在 100 毫秒不活动后自动点击(调用函数 SendClick)。

击败逆向工程.exe。

答案4

也许您不必重新编译所有内容。在游戏世界中,通常使用训练器,它在程序运行时操纵内存中的值。如果您找到内存中的最小值(0.5)并编写类似加载器的程序来使该数字更小,它可能会起作用。

相关内容