C++ 为什么这个键盘拦截内核扩展不起作用?
我的开发伙伴们!我非常希望,至少你们中的一些人不会被这个问题所包含的大量文本吓到。我只是尽了最大的努力,尽可能地进行描述 对于那些认为我问这个问题是为了写恶意软件或其他东西的人。我想编写一个应用程序,允许用户在操作系统完成启动后选择要启动的应用程序。整个想法是允许用户在操作系统完成启动之前通过按下先前绑定到应用程序的热键来选择这些应用程序。例如,用户打开Mac电脑,键入SMTV,然后离开,当系统完成启动my app时,恢复输入并启动Safari、Mail、Tweetie和Vuze。我是个新手,但我尽我所能帮助别人回答他们的问题——我想我也可以期待同样的回报。检查我的个人资料和我的活动,然后开始对恶意软件大喊大叫 这是问题的后续问题 在我的指导下,我偶然发现了Christian Starkjohann的一篇文章,其中描述了他如何成功地将iBook的CDROM弹出键从F12重新分配到Shift+F12。主要部分是他们实际上截获了键盘事件,这正是我所需要的。最后Christian写这篇文章正是为了让像我这样的开发人员使用iJet的思想作为类似功能的原型 首先,我决定创建一个简单的内核扩展,将用户的键盘输入记录到/var/log/kernel.log。我已经在XCode中启动了一个新的通用内核扩展项目,按照中的教程中的说明创建了一个Hello World项目,然后用取自iJet源代码的代码填充它。结果如下: TestKEXT.cC++ 为什么这个键盘拦截内核扩展不起作用?,c++,macos,keyboard,kernel-extension,C++,Macos,Keyboard,Kernel Extension,我的开发伙伴们!我非常希望,至少你们中的一些人不会被这个问题所包含的大量文本吓到。我只是尽了最大的努力,尽可能地进行描述 对于那些认为我问这个问题是为了写恶意软件或其他东西的人。我想编写一个应用程序,允许用户在操作系统完成启动后选择要启动的应用程序。整个想法是允许用户在操作系统完成启动之前通过按下先前绑定到应用程序的热键来选择这些应用程序。例如,用户打开Mac电脑,键入SMTV,然后离开,当系统完成启动my app时,恢复输入并启动Safari、Mail、Tweetie和Vuze。我是个新手,但
生成的内核扩展由kextload/kextunload程序成功加载/卸载,但实际上没有截获任何键盘事件。我尝试过做很多事情来让它工作,但是没有任何错误或其他问题,我无法在谷歌上搜索任何有用的东西并请求您的帮助。问题不在于您如何覆盖现有的IOHIDSystem实例。那很好用 问题是,当IOHIKeyboard打开时,它被传递一个回调函数到IOHIDSystem以处理事件。回调是IOHIDSystem的静态私有函数,称为_keyboardEvent:
success = ((IOHIKeyboard*)source)->open(this, kIOServiceSeize,0,
(KeyboardEventCallback) _keyboardEvent,
(KeyboardSpecialEventCallback) _keyboardSpecialEvent,
(UpdateEventFlagsCallback) _updateEventFlags);
然后回调调用IOHIDSystem实例中的keyboardEvent函数:
self->keyboardEvent(eventType, flags, key, charCode, charSet,
origCharCode, origCharSet, keyboardType, repeat, ts, sender);
它不调用10个参数1,这是虚拟的,并且您正在覆盖它。相反,所调用的是11个参数的非虚拟参数。因此,即使您试图覆盖11参数1,它也无法工作,因为调用从未通过vtable。嘿,斯万特!非常感谢你帮我学习语法。我不是以英语为母语的人,尽管我尽了最大的努力不让别人太生气;从我所看到的,恶意软件的呼声是没有根据的,即使有人想写恶意软件可能会问类似的问题。任何程序都有可能是恶意软件,这就是为什么在安装类似程序之前,操作系统的工作就是询问用户。当然,伊万,有可能以这种方式截获密码对话框的击键-我自己没有想到-这可能是它不起作用的原因。也许操作系统足够聪明,可以阻止截获,也许你是对的。。。虽然我已经了解了整个技巧是基于C++语言的能力来取代类的地址表到方法,这应该在任何情况下工作。
#include "HIDHack.h"
static void *oldVtable = NULL;
static void *myVtable = NULL;
int HidHackLoad(void) {
IOHIDSystem *p;
HIDHack *sub;
if (oldVtable != NULL) {
printf("###0 KEXT is already loaded\n");
return 1;
}
if (myVtable == NULL) {
sub = new HIDHack();
myVtable = *(void **)sub;
sub->free();
}
p = IOHIDSystem::instance();
oldVtable = *(void **)p;
*(void **)p = myVtable;
printf("###1 KEXT has been successfully loaded\n");
return 0;
}
int HidHackUnload(void) {
IOHIDSystem *p;
if (oldVtable != NULL) {
p = IOHIDSystem::instance();
if (*(void **)p != myVtable) {
printf("###2 KEXT is not loaded\n");
return 1;
}
*(void **)p = oldVtable;
oldVtable = NULL;
}
printf("###3 KEXT has been successfully unloaded\n");
return 0;
}
void HIDHack::keyboardEvent(unsigned eventType, unsigned flags, unsigned key, unsigned charCode, unsigned charSet, unsigned origCharCode, unsigned origCharSet, unsigned keyboardType, bool repeat,
AbsoluteTime ts) {
printf("###4 hid event type %d flags 0x%x key %d kbdType %d\n", eventType, flags, key, keyboardType);
IOHIDSystem::keyboardEvent(eventType, flags, key, charCode, charSet, origCharCode, origCharSet, keyboardType, repeat, ts);
}
void HIDHack::keyboardSpecialEvent( unsigned eventType,
/* flags */ unsigned flags,
/* keyCode */ unsigned key,
/* specialty */ unsigned flavor,
/* guid */ UInt64 guid,
/* repeat */ bool repeat,
/* atTime */ AbsoluteTime ts) {
printf("###5 special event type %d flags 0x%x key %d flavor %d\n", eventType, flags, key, flavor);
IOHIDSystem::keyboardSpecialEvent(eventType, flags, key, flavor, guid, repeat, ts);
}
success = ((IOHIKeyboard*)source)->open(this, kIOServiceSeize,0,
(KeyboardEventCallback) _keyboardEvent,
(KeyboardSpecialEventCallback) _keyboardSpecialEvent,
(UpdateEventFlagsCallback) _updateEventFlags);
self->keyboardEvent(eventType, flags, key, charCode, charSet,
origCharCode, origCharSet, keyboardType, repeat, ts, sender);