如何在不“消耗”的情况下读取键盘输入它在 x86 DOS 汇编中吗?
我需要编写一种可以从 C 代码调用的键盘记录器函数。 这意味着 ac 程序将调用一个名为 startlog 的汇编函数,该函数指示开始记录按下的按键,直到调用一个名为 endlog 的函数为止。日志记录应该像这样工作:写入按下的任何键的 ascii 值,而不会干扰 startlog 和 endlog 之间的 C 代码,这意味着如果 C 代码也需要读取输入(假设通过 scanf,它会正常工作)。
我设法通过将中断向量第 9 个条目(键盘按下中断)更改为我编写的将值写入文件的函数来编写记录器,并且它工作正常。但是 C 代码没有获取输入。 基本上我所做的是使用 int 21h 读取按下的按键,但是在读取 ascii 值后,它被“消耗”,所以我需要一种方法来再次模拟按键或读取该值而不“消耗”它,所以下次按键时被读取它读取相同的密钥。 (我用英文描述了代码,因为它是又长又笨拙的汇编代码)
I need to write a sort of key-logger function that can be called from C code.
what it means is a c program would call an assembly function called startlog that would indicate to start logging the keys pressed until a function called endlog is called. the logging should work like this: write the ascii value of any key pressed without disturbing the C code between startlog and endlog, meaning that if the C code also needs to read the input (let's say by scanf, it would work ok).
I managed to write the logger by changing the interrupt vector 9th entry (interrupt for keyboard press) to a function I wrote that writes the values to a file, and it works fine. however the C code does not get the input.
Basically what i did is read the key pressed using int 21h, however after reading the ascii value it is "consumed" so I need a way to either simulate the key press again or read the value without "consuming" it so next time a key is read it reads the same key.
(I described the code in english because it is long and clumsy assembly code)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
执行方法如下:
输出(在 Windows XP 上运行):
KEYLOG.TXT:
这里有一些问题。繁忙时无法使用某些 DOS 功能。这就是我检查
InDos
标志的原因。同时,InDos 可以指示 DOS 正忙,即使它正在等待键盘输入等简单的事情(例如在gets()
中)。这就是为什么有一个用于扫描代码的循环缓冲区来累积它们,而程序却无法安全地调用 DOS 文件 I/O 例程。
EndLog()
等待缓冲区耗尽。您可能还需要提前强制排水。我还尝试挂钩 int 28h 作为 int 1Ch 的替代品,但我的 int 28h ISR 从未被调用,不知道为什么。
我避免使用 C 的
fopen()
和fwrite()
/fprintf()
来记录日志文件,以免干扰主程序不知道后台发生的事情。出于同样的原因,ISR 中只使用最简单的标准 C 函数。Here's how you can do it:
Output (run on Windows XP):
KEYLOG.TXT:
There're a few problems here. You can't use some DOS functions when it's busy. This is why I'm checking the
InDos
flag. At the same time InDos can indicate that DOS is busy even when it's waiting for such simple things as keyboard input (e.g. ingets()
).This is why there's a circular buffer for the scan codes that accumulates them while the program can't safely call DOS file I/O routines.
EndLog()
waits until the buffer is drained. You may need to force draining earlier as well.I've also tried hooking int 28h as an alternative to int 1Ch, but my ISR for int 28h got never invoked, not sure why.
I'm avoiding the use of C's
fopen()
andfwrite()
/fprintf()
for the log file so as not to interfere with the main program that's unaware of the things happening in the background. Only the most trivial standard C functions are used in the ISRs for the same reason.如果 INT 9 是键盘中断,并且您要更改此向量以指向您自己的代码来拦截字符,那么为什么您不能只存储旧向量并在挂钩代码末尾跳转到它呢?
If INT 9 is the keyboard interrupt and you are changing this vector to point at you own code to intercept chars, why can you not just store the old vector and jump to it at the end of your hook code?