私の仲間の開発者!少なくとも一部の皆さんが、この質問に含まれるテキストの量に恐れを感じないことを願っています(私は、人道的に可能な限り説明的になるように最善を尽くしました)。:)
マルウェアか何かを書くために私がこの質問をしたと思う人たちへ。OSの起動終了後に起動するアプリケーションをユーザーが選択できるアプリケーションを作成したいと思います。全体的なアイデアは、ユーザーが以前にアプリにバインドされたホットキーを押して、OSの起動が完了する前にこれらのアプリを選択できるようにすることです。たとえば、ユーザーはMacの電源を入れ、SMTVと入力して消えます。システムの起動が完了すると、アプリが入力を復元し、Safari、Mail、Tweetie、Vuzeを起動します。私はSOに不慣れですが、他の人の質問に答えることで他の人を助けるために最善を尽くします-見返りに同じことを期待できると思います。私のプロフィールと活動を確認し、その後マルウェアについて叫び始めます。
この質問は、 Mac OSの起動中に行われたキーボード入力を回復することは可能ですか?という質問のフォローアップです。。
Pekkaのアドバイスに導かれて、ChristianStarkjohannによるInterceptingKeyboard Eventsの記事に出くわしました。彼と、 ObjectiveDevelopmentチームがiBookのCDROMイジェクトキーをF12からShift+F12に再割り当てすることに成功した方法を説明しています。主な部分は、彼らが実際にキーボードイベントを傍受したことです。これが私が必要としていることです。結局、Christianは、私のような開発者がiJectのアイデアを同様の機能のプロトタイプとして使用できるように、この記事を正確に作成しました。
まず、ユーザーのキーボード入力をに記録するだけの単純なカーネル拡張機能を作成することにしました/var/log/kernel.log
。XCodeで新しいGenericKernelExtensionプロジェクトを開始し、Hello Kernel:Mac DevCenterのKernelExtensionConceptsにあるXcodeを使用したカーネル拡張の作成チュートリアルの指示に従ってHelloWorldプロジェクトを作成し、そこから取得したコードを詰め込みました。 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プログラムによって正常にロード/アンロードされますが、実際にはキーボードイベントをインターセプトしません。私はそれを機能させるためにたくさんのことを試みましたが、エラーやその他の問題がなければ、有用なものをグーグルで検索してあなたの助けを求めることはできません。