尊敬的开发者们!我非常希望至少有一些人不会被这个问题所吓倒(我尽力用最详细的描述方式)。:)
对于那些认为我是在问如何编写恶意软件的人。我想编写一个应用程序,允许用户选择在操作系统启动完成后要启动的应用程序。整个想法是允许用户通过预先绑定到应用程序的热键在操作系统启动之前选择这些应用程序。例如,用户打开他的Mac电脑,输入SMTV并离开,当系统启动完成后,我的应用程序恢复输入并启动Safari、Mail、Tweetie和Vuze。我是SO的新手,但我尽力通过回答他们的问题来帮助别人-我认为我可以期待得到同样的帮助。请查看我的个人资料和活动记录,然后再开始大喊大叫关于恶意软件的事情。
这个问题是是否可能在Mac OS启动时恢复键盘输入?的后续问题。
对于那些认为我是在问如何编写恶意软件的人。我想编写一个应用程序,允许用户选择在操作系统启动完成后要启动的应用程序。整个想法是允许用户通过预先绑定到应用程序的热键在操作系统启动之前选择这些应用程序。例如,用户打开他的Mac电脑,输入SMTV并离开,当系统启动完成后,我的应用程序恢复输入并启动Safari、Mail、Tweetie和Vuze。我是SO的新手,但我尽力通过回答他们的问题来帮助别人-我认为我可以期待得到同样的帮助。请查看我的个人资料和活动记录,然后再开始大喊大叫关于恶意软件的事情。
这个问题是是否可能在Mac OS启动时恢复键盘输入?的后续问题。
在Pekka的建议的指导下,我偶然发现了Christian Starkjohann的一篇文章截取键盘事件, 文章描述了他和Objective Development团队是如何成功地将iBook的CDROM弹出键从F12重新分配到Shift + F12的。主要部分是他们实际上截取了键盘事件,这正是我所需要的。最后,Christian撰写了这篇文章,正是为了像我这样的开发人员能够将iJect的想法作为类似功能的原型。
首先,我决定创建一个简单的内核扩展程序,将用户的键盘输入记录到/var/log/kernel.log
。我在XCode中开始了一个新的通用内核扩展项目,并按照Hello Kernel: Creating a Kernel Extension With Xcode教程中在Mac Dev Center's Kernel Extension Concepts找到的指示创建了一个Hello World项目,然后用iJect源代码填充它。以下是结果:
TestKEXT.c
#include <sys/systm.h>
#include <mach/mach_types.h>
extern int HidHackLoad(void);
extern int HidHackUnload(void);
kern_return_t MacOSSCKEXT_start (kmod_info_t * ki, void * d) {
return HidHackLoad() == 0 ? KERN_SUCCESS : KERN_FAILURE;
}
kern_return_t MacOSSCKEXT_stop (kmod_info_t * ki, void * d) {
return HidHackUnload() == 0 ? KERN_SUCCESS : KERN_FAILURE;
}
HIDHack.h
#ifdef __cplusplus
extern "C" {
#endif
#include <mach/mach_types.h>
#include <sys/systm.h>
extern int HidHackLoad(void);
extern int HidHackUnload(void);
#ifdef __cplusplus
}
#endif
#include <IOKit/system.h>
#include <IOKit/assert.h>
#include <IOKit/hidsystem/IOHIDSystem.h>
class HIDHack : public IOHIDSystem {
public:
virtual void keyboardEvent(unsigned eventType,
/* flags */ unsigned flags,
/* keyCode */ unsigned key,
/* charCode */ unsigned charCode,
/* charSet */ unsigned charSet,
/* originalCharCode */ unsigned origCharCode,
/* originalCharSet */ unsigned origCharSet,
/* keyboardType */ unsigned keyboardType,
/* repeat */ bool repeat,
/* atTime */ AbsoluteTime ts);
virtual void keyboardSpecialEvent(unsigned eventType,
/* flags */ unsigned flags,
/* keyCode */ unsigned key,
/* specialty */ unsigned flavor,
/* guid */ UInt64 guid,
/* repeat */ bool repeat,
/* atTime */ AbsoluteTime ts);
};
HIDHack.cpp
#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);
}
生成的内核扩展可以被kextload/kextunload程序成功加载/卸载,但实际上没有拦截任何键盘事件。我尝试了很多方法来让它工作,但由于没有错误或其他问题,我无法在谷歌上找到任何有用的信息,所以需要您的帮助。