为什么这个键盘拦截内核扩展工作? [英] Why doesn't this keyboard intercepting kernel extension work?

查看:188
本文介绍了为什么这个键盘拦截内核扩展工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的同行开发者!我非常希望,至少有一些人不会害怕这个问题包含的文本量(我只是尽我所能描述人性化的可能性)。 :)

my fellow developers! I hope very much that at least some of you will not get frightened by the amount of text this question contains (I simply did my best to be as descriptive as humanely possible). :)

对于那些认为我已经提出这个问题来写恶意软件或其他东西的人。我想编写一个应用程序,允许用户选择要在操作系统完成启动后启动的应用程序。整个想法是允许用户在操作系统完成启动之前通过按下先前绑定到应用程序的热键来选择这些应用程序。例如,用户打开他的Mac,键入SMTV并消失,当系统完成启动我的应用程序恢复输入,并启动Safari,邮件,Tweetie和Vuze。我是新来的SO,但我尽力帮助他人回答他们的问题 - 我想我可以期待相同的回报。检查我的个人资料和我的活动,然后开始尖酸关于恶意软件。

To those who think I've asked this question to write malware or something. I want to write an application that will allow users to select applications to be launched after the OS will finish launching. The whole idea is to allow user to select these apps BEFORE the OS finished launching by pressing hotkeys previously binded to the apps. For example user turns on his Mac, types SMTV and goes away, when the system finishes launching my app recovers the input and launches Safari, Mail, Tweetie and Vuze. I'm new to SO but I do my best to help others by answering their questions - I think I can expect the same in return. Check my profile and my activity and after that start screaming about malware.

此问题是问题有可能恢复键盘输入完成,而Mac OS正在启动?

指导 Pekka的建议,我偶然发现了一个文章接受键盘活动,介绍了他和目标开发团队成功地将iBook的CDROM弹出键从F12重新分配到Shift + F12。主要部分是,他们实际上拦截键盘事件,这是我需要的。最后,Christian已经为像我这样的开发人员编写了这篇文章,以使用iJect作为类似功能的原型。

Guided by Pekka's advice, I've stumbled upon an article Intercepting Keyboard Events by Christian Starkjohann that describes how he and the Objective Development team succeeded in reassigning iBook's CDROM eject key from F12 to Shift+F12. The main part is that they actually intercepted keyboard events, which is what I need. In the end Christian has written this article exactly for developers like me to use the idea of iJect as a prototype for similar functionality.

首先,我决定创建一个简单的内核扩展只需将用户的键盘输入记录到 /var/log/kernel.log 。我在XCode中启动了一个新的通用内核扩展项目,并按照 Hello Kernel:使用Xcode创建内核扩展教程位于Mac Dev Center的内核扩展概念来创建一个Hello World项目,然后使用从iJect源代码中填充它。以下是结果:

To start with, I decided to create a simple kernel extension to simply log the user's keyboard input to /var/log/kernel.log. I've started a new Generic Kernel Extension project in XCode, followed the instructions of the Hello Kernel: Creating a Kernel Extension With Xcode tutorial found in Mac Dev Center's Kernel Extension Concepts to create a Hello World project and then stuffed it with code taken from iJect sources. Here are the results:

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程序成功加载/卸载,实际上不拦截任何键盘事件。我已经尝试了很多东西让它工作,但没有任何错误或其他问题,在我无法google的任何有用的方式,并要求您的帮助。

The resulting kernel extension gets successfully loaded/unloaded by kextload/kextunload programs, but doesn't actually intercept any of the keyboard events. I've tried doing lots of things to get it working, but without any errors or other problems with it in the way I can't google anything useful and ask your help.

推荐答案

问题不在于如何覆盖现有的IOHIDSystem实例。这很好。

The problem is not with how you are overriding the existing IOHIDSystem instance. That works just fine.

问题是当IOHIKeyboard打开时,它会传递一个回调函数到IOHIDSystem来处理事件。回调是IOHIDSystem的静态私有函数,称为_keyboardEvent:

The problem is that when IOHIKeyboard is opened, it is passed a callback function to the IOHIDSystem for processing events. The callback is a static private function of IOHIDSystem, called _keyboardEvent:

    success = ((IOHIKeyboard*)source)->open(this, kIOServiceSeize,0,
                (KeyboardEventCallback)        _keyboardEvent, 
                (KeyboardSpecialEventCallback) _keyboardSpecialEvent,
                (UpdateEventFlagsCallback)     _updateEventFlags);

然后回调函数在IOHIDSystem实例中调用keyboardEvent函数:

The callback then calls keyboardEvent function in the IOHIDSystem instance:

    self->keyboardEvent(eventType, flags, key, charCode, charSet,
                            origCharCode, origCharSet, keyboardType, repeat, ts, sender);

它不会调用十个参数,一个是虚拟的(你正在覆盖)。相反,被称为是11参数非虚拟的。所以即使你试图重写11参数,它不会工作,因为调用永远不通过vtable。

It does not call the ten parameter one, which is virtual (and which you are overriding). Instead, what is being called is the 11 parameter non-virtual one. So even if you tried to override the 11 parameter one, it would not work as the call never goes through the vtable.

这篇关于为什么这个键盘拦截内核扩展工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆