Domanda

I miei colleghi sviluppatori! Spero molto che almeno alcuni di voi non si spaventino dalla quantità di testo che questa domanda contiene (ho semplicemente fatto del mio meglio per essere descrittivo il più possibile umanamente possibile). :)

A coloro che pensano di aver posto questa domanda per scrivere malware o qualcosa del genere. Voglio scrivere un'applicazione che consentirà agli utenti di selezionare le applicazioni di essere lanciata dopo l'avvio del sistema operativo. L'intera idea è consentire all'utente di selezionare queste app prima che il sistema operativo terminasse premendo i tasti di scelta rapida precedentemente associati alle app. Ad esempio, l'utente accende il suo Mac, tipi SMTV e scompare, quando il sistema finisce di lanciare la mia app recupera l'input e lancia Safari, Mail, Tweetie e Vuze. Sono nuovo di così, ma faccio del mio meglio per aiutare gli altri rispondendo alle loro domande - penso di potermi aspettare lo stesso in cambio. Controlla il mio profilo e la mia attività e dopo inizia a urlare sul malware.

Questa domanda è un seguito alla domanda È possibile recuperare l'input della tastiera che è stato fatto mentre Mac OS stava avviando?.

Guidato da Il consiglio di Pekka, Mi sono imbattuto in un articolo Intercettazione di eventi da tastiera da cristiano Starkjohann che descrive come lui e il Team di sviluppo oggettivo è riuscito a riassegnare la chiave di espulsione CDROM di IBook da F12 a Maiusc+F12. La parte principale è che in realtà intercettato Eventi della tastiera, che sono ciò di cui ho bisogno. Alla fine Christian ha scritto questo articolo esattamente per gli sviluppatori come me per usare l'idea di Iject come prototipo per funzionalità simili.

Per cominciare, ho deciso di creare una semplice estensione del kernel per registrare semplicemente l'input della tastiera dell'utente a /var/log/kernel.log. Ho avviato un nuovo progetto di estensione del kernel generico in Xcode, seguito le istruzioni del Hello Kernel: creazione di un'estensione del kernel con Xcode Tutorial trovato in Concetti di estensione del kernel di Mac Dev Center Per creare un progetto Hello World e poi l'ho riempito con codice tratto da fonti Iject. Ecco i risultati:

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

L'estensione del kernel risultante viene caricata/scaricata correttamente dai programmi Kextload/KextUnload, ma in realtà non intercetta nessuno degli eventi della tastiera. Ho provato a fare molte cose per farlo funzionare, ma senza errori o altri problemi nel modo in cui non posso Google nulla di utile e chiedere il tuo aiuto.

È stato utile?

Soluzione

Il problema non riguarda il modo in cui stai preparando all'istanza esistente di Iohidsystem. Funziona bene.

Il problema è che quando viene aperto iohikeyboard, viene passata una funzione di callback al sistema IOHid per elaborare eventi. Il callback è una funzione privata statica di iohidsystem, chiamata _KeyboardEvent:

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

Il callback chiama quindi la funzione tastieravent nell'istanza di Iohidsystem:

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

Non chiama il parametro Ten One, che è virtuale (e che stai prevalendo). Invece, quello che viene chiamato è quello di 11 parametri non virtuali. Quindi, anche se hai provato a sovrascrivere il parametro 11, non funzionerebbe in quanto la chiamata non passa mai attraverso il vtable.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top