2010-01-11 24 views
5

các nhà phát triển đồng nghiệp của tôi! Tôi hy vọng rất nhiều rằng ít nhất một số bạn sẽ không sợ hãi bởi số lượng văn bản câu hỏi này chứa (tôi chỉ đơn giản là làm hết sức mình để được mô tả như nhân loại có thể). :)Tại sao bàn phím này không chặn công việc mở rộng hạt nhân?

Đối với những người nghĩ rằng tôi đã hỏi câu hỏi này để viết phần mềm độc hại hoặc nội dung nào đó. Tôi muốn viết một ứng dụng cho phép người dùng lựa chọn các ứng dụng được khởi chạy sau khi hệ điều hành kết thúc khởi chạy. Toàn bộ ý tưởng là cho phép người dùng chọn các ứng dụng này TRƯỚC KHI hệ điều hành đã hoàn thành việc khởi chạy bằng cách nhấn phím nóng trước đây được liên kết với các ứng dụng. Ví dụ người dùng bật máy Mac của mình, loại SMTV và biến mất, khi hệ thống kết thúc khởi chạy ứng dụng của tôi, khôi phục dữ liệu nhập và khởi chạy Safari, Mail, Tweetie và Vuze. Tôi là người mới đối với SO nhưng tôi cố hết sức để giúp đỡ người khác bằng cách trả lời câu hỏi của họ - tôi nghĩ tôi có thể trông đợi điều đó. Kiểm tra hồ sơ của tôi và hoạt động của tôi và sau đó bắt đầu la hét về phần mềm độc hại.

Câu hỏi này là câu hỏi tiếp theo cho câu hỏi Is it possible to recover keyboard input that was done while Mac OS was starting up?.

Được hướng dẫn bởi Pekka's advice, tôi đã stumbled khi một bài báo Intercepting Keyboard Events Christian Starkjohann mô tả cách ông và Objective Development team thành công trong việc giao lại chìa khóa đẩy CDROM iBook từ F12 để Shift + F12. Phần chính là họ thực sự chặn sự kiện bàn phím, đó là những gì tôi cần. Cuối cùng, Christian đã viết chính xác bài viết này cho các nhà phát triển như tôi để sử dụng ý tưởng về iJect làm nguyên mẫu cho chức năng tương tự.

Để bắt đầu, tôi quyết định tạo phần mở rộng hạt nhân đơn giản để chỉ cần đăng nhập đầu vào bàn phím của người dùng vào /var/log/kernel.log. Tôi đã bắt đầu một dự án mở rộng hạt nhân chung mới trong XCode, theo hướng dẫn của hướng dẫn Hello Kernel: Creating a Kernel Extension With Xcode được tìm thấy trong Mac Dev Center's Kernel Extension Concepts để tạo dự án Hello World và sau đó nhồi nó bằng mã lấy từ nguồn iJect. Dưới đây là kết quả:

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); 
} 

T kết quả mở rộng hạt nhân của anh ta được tải/nạp thành công bởi các chương trình kextload/kextunload, nhưng không thực sự chặn bất kỳ sự kiện bàn phím nào. Tôi đã thử làm rất nhiều thứ để làm cho nó hoạt động, nhưng không có bất kỳ lỗi hoặc các vấn đề khác với nó theo cách tôi không thể google bất cứ điều gì hữu ích và yêu cầu giúp đỡ của bạn.

+0

Hey Svante! Cảm ơn rất nhiều vì đã giúp tôi với ngữ pháp. Tôi không phải là người bản ngữ mặc dù tôi cố gắng hết sức để không gây khó chịu cho mọi người ...;) –

+1

Từ những gì tôi có thể thấy, các phần mềm độc hại đang khóc là không có cơ sở (mặc dù ai đó tìm cách viết phần mềm độc hại có thể hỏi các câu hỏi tương tự). Bất kỳ chương trình nào ở mức độ sâu * này có thể * là phần mềm độc hại, đó là lý do tại sao đó là công việc của hệ điều hành để hỏi người dùng trước bất kỳ thứ gì giống như nó được cài đặt. Tất nhiên, Ivan, nó * sẽ * có thể chặn các tổ hợp phím của một hộp thoại mật khẩu theo cách đó - không tự nghĩ về điều đó - đó có thể là lý do tại sao nó không hoạt động. Có lẽ hệ điều hành đủ thông minh để ngăn chặn việc chặn chính xác vì lý do đó. –

+0

Có lẽ bạn đã đúng ... Mặc dù theo như tôi đã hiểu toàn bộ lừa được dựa trên khả năng ngôn ngữ C++ để thay thế các bảng các lớp địa chỉ thành các phương thức, nó sẽ hoạt động trong mọi trường hợp. –

Trả lời

2

Sự cố không phải là cách bạn ghi đè trường hợp IOHIDSystem hiện có. Điều đó hoạt động tốt.

Vấn đề là khi IOHIKeyboard được mở, nó được chuyển một hàm gọi lại tới hệ thống IOHIDS để xử lý sự kiện.Gọi lại là một chức năng riêng tĩnh của IOHIDSystem, gọi _keyboardEvent:

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

gọi lại sau đó gọi KeyboardEvent chức năng trong trường hợp IOHIDSystem:

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

Nó không gọi mười một tham số, đó là ảo (và bạn đang ghi đè). Thay vào đó, những gì đang được gọi là tham số 11 không ảo. Vì vậy, ngay cả khi bạn đã cố gắng ghi đè tham số 11, nó sẽ không hoạt động khi cuộc gọi không bao giờ đi qua vtable.

Các vấn đề liên quan