SysCalls



  • Spuckt:

    printk(KERN_INFO "SysCallTable is located at: %p\n", sctable);
    

    jetzt auch die dezimale Schreibweise aus? Deine erste dmesg Ausgabe scheint mir eher einen String auszugeben statt der Adresse des Pointers (sollte normalerweise bei hexadezimal mit 0x anfangen).



  • Also er spuckt genau das selbe aus:

    [ 205.723575] SysCallTable is located at: c0509940
    [ 205.723580] SysCallWrite is located at: c01bdbb0
    [ 205.723584] SysCallRead is located at: c01bdda0
    [ 205.723588] SysCallOpen is located at: c01bb790
    [ 205.723592] SysCallFork is located at: c01023f0

    Scheint eher an dem Überschreiben zu liegen, laut dmesg:

    [ 205.723612] BUG: unable to handle kernel paging request at c0509944

    Grüße



  • Das kann nicht funktionieren, wenn der Kernel die Adresse der sys_call_table weiterhin frei zugänglich machen würde, dann hätte man auch einfach das Symbol weiterhin exportieren können.

    Aber lies dir das hier mal durch http://www.kernelhacking.com/rodrigo/docs/StMichael/kernel-land-rootkits.pdf ob das in aktuellen Kernels (noch) geht kann ich dir nicht sagen, aber auf den ersten Blick scheint das ein guter Ansatzpunkt zu sein, evt. musst du es noch ein wenig modifizieren.



  • Ok, also du kannst die sys_call_table wie folgt bekommen:

    void *get_system_call(void);
    void *get_sys_call_table(void *system_call);
    
    /* Und so bekommt du die sys_call_table: */
    void* sys_call_table = get_sys_call_table( get_sytem_call() );
    
    /* Code von http://www.enye-sec.org */
    
    void *get_system_call(void)
    {
    unsigned char idtr[6];
    unsigned long base;
    struct idt_descriptor desc;
    
    asm ("sidt %0" : "=m" (idtr));
    base = *((unsigned long *) &idtr[2]);
    memcpy(&desc, (void *) (base + (0x80*8)), sizeof(desc));
    
    return((void *) ((desc.off_high << 16) + desc.off_low)); 
    
    }
    
    void *get_sys_call_table(void *system_call)
    {
    unsigned char *p;
    unsigned long s_c_t;
    
    p = (unsigned char *) system_call;
    
    while (!((*p == 0xff) && (*(p+1) == 0x14) && (*(p+2) == 0x85)))
    	p++;
    
    dire_call = (unsigned long) p;
    
    p += 3;
    s_c_t = *((unsigned long *) p);
    
    p += 4;
    after_call = (unsigned long) p;
    
    /* cli */
    while (*p != 0xfa)
    	p++;
    
    dire_exit = (unsigned long) p;
    
    return((void *) s_c_t);
    
    }
    

    Das Verfahren ist das aus dem PDF beschriebene, wenn du die Präsentation allerdings durchgelesen hast wirst du wissen, dass das Verfahren sehr leicht geblockt werden kann.



  • @Tippgeber: Die Adresse der Tabelle hat er doch schon und die stimmt ja auch.

    Genau so wie bestimmte Bereiche aus /dev/mem geblockt werden, wird dann hier auch der Speicherbereich geschützt sein (wie Tippgeber ja bereits gesagt hat). Unter einem älteren Kernel (aus Ubuntu 8.04 , wenn ich mich richtig erinnere) hat das ganze bei mir aber noch funktioniert. (BTW: Welche Distribution benutzt du?)

    @joboyjo: Kannst du den Kernel auch anpassen wie du willst oder muss dein Modul für jeden Kernel passen? Beim Kernel-Build lässt sich auch konfigurieren, dass er sys_call_table weiterhin an Module exportieren soll.



  • ich frag mich nur zu was das ganze gut sein soll vorhandene kernelfunktionen zu überschreiben. (evtl für einen rootkit?)



  • @tippgeber.

    Das ist kompletter Schwachsinn, sry:

    1. Hatte ich das selbe Script wie du, nur selber programmiert und leicht abgeändert. => Gibt genau die selbe Adresse zur SysCallTable aus

    2. /proc/kallsyms wird bei jedem reboot neu geschrieben und dort werden sämtliche symbole ausgelagert, damit auch die sys_call_adresse.

    @devkid
    Habe das aktuelle Ubuntu 9.04 kernel version
    2.6.28.11-generic

    das modul sollte eigentlich für sämtliche 2.6.x kernel funktionieren.



  • joboyy schrieb:

    @devkid
    Habe das aktuelle Ubuntu 9.04 kernel version
    2.6.28.11-generic

    Ich auch, und da funktioniert es bei mir auch nicht. Ich hab jetzt leider keinen andere Distro/Kernel installiert zum Testen.

    joboyy schrieb:

    das modul sollte eigentlich für sämtliche 2.6.x kernel funktionieren.

    Naja, source-kompatibel würde es bleiben, der Kernel müsste nur speziell konfiguriert sein...



  • joboyy schrieb:

    @tippgeber.

    Das ist kompletter Schwachsinn, sry:

    1. Hatte ich das selbe Script wie du, nur selber programmiert und leicht abgeändert. => Gibt genau die selbe Adresse zur SysCallTable aus

    2. /proc/kallsyms wird bei jedem reboot neu geschrieben und dort werden sämtliche symbole ausgelagert, damit auch die sys_call_adresse.

    Stimmt. Versuch mal bevor du auf die sys_call_table schreibst ihr die Schreibberechtigung zu geben, scheinbar ist die Seite ab 2.6.24 read-only.
    Das geht mit "set_memory_rw( sctable, 1);", diese Funktion ist in arch/x86/mm/pageattr.c zu finden.



  • @tippgeber
    Danke, ich dachte schon an eine WriteProtection.
    Werde mir das jetzt mal genauer ansehen und die Ergebnisse hier posten 🙂

    Grüße



  • /home/si/Desktop/kernel/hello11.c:51: Fehler: Implizite Deklaration der Funktion »set_memory_rw«

    ...
    Er scheint die Funktion nicht zu kennen. Die Includes sind:

    #include <linux/string.h>
    #include <linux/smp_lock.h>
    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/file.h>
    #include <linux/fs.h>
    #include <linux/sched.h>
    #include <linux/syscalls.h>
    #include <linux/time.h>
    #include <asm/unistd.h>
    #include <linux/version.h>
    #include <linux/errno.h>
    #include <linux/dcache.h>
    #include <linux/mm.h>
    #include <asm/uaccess.h>
    #include <asm/string.h>
    #define __KERNEL_SYSCALLS__
    #include <linux/dirent.h>
    #include <linux/fcntl.h>
    


  • Du musst halt die Funktionsdeklaration angeben: int set_memory_rw(unsigned long addr, int numpages);

    Aber du kannst dir die Mühe sparen, denn es funktioniert nicht, habe es eben getestet.

    Wenn du einfach nur auf deinem lokalen System das machen willst, dann kannst du auch ganz einfach im Kernel Sourcecode die Schreibberechtigung hinzufügen. Dummerweise finde ich gerade die entsprechende Datei nicht mehr 😞



  • Es muss doch ne Möglichkeit geben auf die syscalls schreiben zu können?



  • jojoboyj schrieb:

    Es muss doch ne Möglichkeit geben auf die syscalls schreiben zu können?

    Wenn es so einfach wäre, dann wäre die Sicherheit des Kernels enorm reduziert. Wenn du auf die Erstellung als Modul verzichten würdest wäre es auch gar kein Ding, dann hättest du ganz legitim Zugriff darauf, oder wenn du die Seite der sys_call_table beschreibbar machst. Aber in jedem Fall musst du den Kernel selbst patchen. Was für deine Übungszwecke doch in Ordnung sein sollte, oder nicht :)?



  • Wie schon oben erwähnt sollte es für jeden 2.6.x Kernel funktionieren.
    Und ich kann nicht anfangen auf privat System bzw. manchmal produktiv System immer erst den Kernel zu patchen. Das sollte eigentlich übers Modul laufen...



  • jojoboyj schrieb:

    Wie schon oben erwähnt sollte es für jeden 2.6.x Kernel funktionieren.
    Und ich kann nicht anfangen auf privat System bzw. manchmal produktiv System immer erst den Kernel zu patchen. Das sollte eigentlich übers Modul laufen...

    Auf Produktivsystemen musst du aber auch davon ausgehen, dass dort entsprechend geschützte Kernel laufen die Checksummen der sys_call_table anlegen und regelmäßig überprüfen (siehe das von mir verlinkte Paper). Und wie du siehst ändert sich hier ständig etwas, so sind verfahren aus dem 2.6.24er Kernel schon jetzt nicht mehr anwendbar.



  • Also gibt es im Moment wirklich keine Möglichkeit?



  • Ist jetzt schon dein dritter Thread zum Thema. Akzeptier halt mal wie's ist 😉


Anmelden zum Antworten