Adresse von SysCallTable



  • Hallo,

    Arbeite an einem kleinen Projekt und sollte im Zuge dessen die Adresse der SysCallTable auslesen. Das Programm selber steht schon und läuft schon seit Jahren in meiner Firma jedoch steht jetzt ein Update von unserem Server Kernel (2.4) auf 2.6 bevor, und da hat sich doch die Exportation der Adresse geändert?

    Stehe im Moment auf der Leitung...



  • Seit 2.6 wird SysCallTable nur noch für direkt in den Kernel einkompilierten Code exportiert, für Module gibt es das Symbol nicht mehr (du könntest es aber mit einem schmutzigen Hack selbst zur Laufzeit finden).



  • wenn das mal nicht der bursche aus dem andern thread ist 😉



  • devkid schrieb:

    Seit 2.6 wird SysCallTable nur noch für direkt in den Kernel einkompilierten Code exportiert, für Module gibt es das Symbol nicht mehr (du könntest es aber mit einem schmutzigen Hack selbst zur Laufzeit finden).

    Also müsste ich entweder den Kernel selber abändern oder eben so einen "schmutzigen Hack" verwenden?

    Wenn ich Methode a verwende, ist mein Programm lediglich für DIESEN EINEN Kernel verfügbar. Methode b würde mir eine kompaktibilität zu dem 2.6 er Kernel erlauben?

    Wie sieht denn der Hack aus?
    Gibt es dazu offizielle Informationen oder ist das eher etwas nicht übliches für Kernelmodule?

    Wenn es nicht üblich ist, kann dann mein Programm auch stabil laufen, oder wird es zu Laufzeitproblemen führen?

    Danke dir schon einmal für das beantworten meiner Fragen 🙂



  • atomfish schrieb:

    wenn das mal nicht der bursche aus dem andern thread ist 😉

    genau dasselbe habe ich gedacht.

    @hobbycoder: wozu brauchst du das? Hier wird dir keiner bei so einem Hack helfen, woher sollen wir wissen, dass du nicht ein Cracker-Newbie bist, der ein Rootkit schreiben will?



  • hobbycoder schrieb:

    Also müsste ich entweder den Kernel selber abändern oder eben so einen "schmutzigen Hack" verwenden?

    Erfasst.

    hobbycoder schrieb:

    Wenn ich Methode a verwende, ist mein Programm lediglich für DIESEN EINEN Kernel verfügbar. Methode b würde mir eine kompaktibilität zu dem 2.6 er Kernel erlauben?

    Den Source-Code kannst du auch in jeden anderen Kernel einkompilieren (solange die verwendete API die gleiche geblieben ist), für eine Änderung musst du aber den ganzen Kernel neu bauen.

    hobbycoder schrieb:

    Wie sieht denn der Hack aus?

    Du durchwühlst den Arbeitsspeicher nach was brauchbarem.

    hobbycoder schrieb:

    Gibt es dazu offizielle Informationen

    Nein und das ist auch gut so.

    hobbycoder schrieb:

    ist das eher etwas nicht übliches für Kernelmodule?

    Für "gute" (Gegenteil von böse) Kernel-Module ist das mehr als nur unüblich. Die sollten nämlich mit Sys-Calls nix zu tun haben.

    hobbycoder schrieb:

    Wenn es nicht üblich ist, kann dann mein Programm auch stabil laufen, oder wird es zu Laufzeitproblemen führen?

    Wenn er die Tabelle findet und die Überprüfungen stimmen (man achte auf das wenn), sollte das laufen.

    PS: Lass es einfach sein. 😃



  • @hobbycoder: Schreib bitte im Forum. Wenn dus nicht lassen willst, dann such halt mit Google, da gibts genug Ergebnisse.



  • Also das soll kein Cracker Szenario werden.
    Mein Programm, welches für den 2.4 er kernel lauffähig ist, funktioniert ja auch für diesen Kernel.

    Ihr müsst mir nur erklären, wie ich beim 2.6er Kernel auf die Adresse der SysCallTable komme. Wäre ich ein böser Cracker - oder was weiß ich - würde ich sicherlich noch andere Sachen benötigen.



  • devkid schrieb:

    Wenn dus nicht lassen willst, dann such halt mit Google, da gibts genug Ergebnisse.

    Google ist dein Freund.



  • #include <stdio.h>
    #include <unistd.h>
    #include <netinet/in.h>
    #include <stdlib.h>
    #include <string.h>
    
    // kernel loaded at 1MB (0x00100000)
    // kernel ring starts at 0xC0000000
    // kernel itself is at 0xC0100000
    
    struct _idtr {
      uint16_t limit;
      unsigned long base;
    } __attribute__((packed));
    
    unsigned long idt_table;
    
    struct _idt_entry {
      uint16_t lo;
      uint16_t css;
      uint16_t flags;
      uint16_t hi;
    } __attribute__((packed));
    
    unsigned long syscall_handler;
    
    #define KERN_START 0xC0000000
    
    int is_kern_addr(unsigned long addr)
    {
      if(addr < KERN_START)
        return -1;
      return 0;
    }
    
    int read_virt(FILE *fp, unsigned long addr, void *buf, unsigned int len)
    {
      if(is_kern_addr(addr) < 0)
        return -1;
    
      addr = addr - KERN_START;
      fseek(fp, addr, SEEK_SET);
      return fread(buf, 1, len, fp);
    }
    
    int write_virt(FILE *fp, unsigned long addr, void *buf, unsigned int len)
    {
      if (is_kern_addr(addr) < 0)
        return -1;
    
      addr = addr - KERN_START;
      fseek(fp, addr, SEEK_SET);
      return fwrite(buf, 1, len, fp);
    }
    
    int main()
    {
      FILE *fpmem;
      struct _idtr idtr;
      struct _idt_entry idt;
      char buf[100];
      int i;
      char *ptr;
      unsigned long sys_call_table2 = 0x00;
    
      if (getuid() != 0)
        printf("[*] note: you are not root, trying to access /dev/mem anyway\n");
      else
        printf("[*] we are root!\n");
    
      fpmem = fopen("/dev/mem", "r+");
    
      if (fpmem == NULL)
      {
        printf("[-] access to /dev/mem denied!\n");
        exit(0);
      }
    
      printf("[*] syscall okay\n");
    
      __asm__("sidt %0" : "=m"(idtr));
      idt_table = idtr.base;
      printf("\n\n[*]interrupt descriptor table is at: 0x%x\n", (unsigned int)idt_table); // casting bitch
    
      printf("[*] trying to calculate address of int 0x80\n");
      if (read_virt(fpmem, idt_table + sizeof(struct _idt_entry)*0x80, &idt, sizeof(struct _idt_entry)) < 0)
      {
        printf("[-] failed!\n");
        exit(0);
      }
      syscall_handler = (idt.hi << 16) | idt.lo;
      printf("[*] syscall handler is at: 0x%x\n", (unsigned int)syscall_handler);
    
      printf("[debug] %lu < %u ?\n", syscall_handler, KERN_START);
      memset(buf, 0x00, 100);
      if(read_virt(fpmem, syscall_handler, buf, 100) < 0)
      {perror("error");
        printf("[-] failed to read the first 100 bytes of system_call()!\n");
        exit(0);
      }
    
      for(i=0, ptr=buf; i<100; i++, ptr++)
      {
        if ( (*ptr == 0xff) &&
             (*(ptr+1) == 0x14) &&
             (*(ptr+2) == 0x85))
        {
          sys_call_table2 = *((uint32_t *)(ptr+3));
          break;
        }
      }
    
      if (sys_call_table2 > 0)
        printf("[*] found sys_call_table: 0x%x\n", (unsigned int)sys_call_table2);
      else
        printf("[-] sys_call_table not found!\n");
    
      printf("\n");
      fclose(fpmem);
      exit(0);
    }
    

    Hab mir das mal so zusammengebastelt, doch das Ergebnis ist:

    [] we are root!
    [
    ] syscall okay

    []interrupt descriptor table is at: 0xc06e1000
    [
    ] trying to calculate address of int 0x80
    [*] syscall handler is at: 0xbfd2
    [debug] 49106 < 3221225472 ?
    error: Operation not permitted



  • Das, was du da zusammengebastelt hast, ist ein Userspace-Programm... (Und das ist dir nicht aufgefallen?)

    http://kerneltrap.org/node/5793#comment-193975...



  • // Verschrieben - Fehler



  • Verschrieben...

    // make -C /usr/src/linux-headers-2.6.28-11-generic M=`pwd` modules
    
    #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>
    
    MODULE_LICENSE("GPL");
    
    unsigned long **find_sys_call_table(void) 
    {
        	unsigned long **sctable;
        	unsigned long ptr;
        	//extern int loops_per_jiffy;	in einer header datei schon deklariert? extern fehler?
    
    	sctable = NULL;
        	for (ptr = (unsigned long)&loops_per_jiffy; ptr < (unsigned long)&boot_cpu_data; ptr += sizeof(void *))
    	{
        		unsigned long *p;
            	p = (unsigned long *)ptr;
    
            	if (p[__NR_close] == (unsigned long) sys_close)
    		{
                		sctable = (unsigned long **)p;
                		return &sctable[0];
            	}
        	}
    	return NULL;
    }
    
    static int __init readlog_init(void) 
    {
    	unsigned long **sys_call_table = find_sys_call_table();
    	printk(KERN_INFO "\nbla\n");
    	printk(KERN_ALERT "SysCallTable is located at: %lu", sys_call_table);
       	return 0;
    }
    
    static void __exit readlog_exit(void)
    {
    return;
    }
    
    module_init(readlog_init);
    module_exit(readlog_exit);
    

    Also loops_per_jiffy kann ich irgendwie nicht als extern int deklarieren, da es laut Compiler schon in einer Header Datei definiert ist. Wenn ichs auskommentiere, kompiliert das Teil auch 🙂

    Meine Frage ist bezüglich dem printk() Ich bin mir nicht sicher wie ich eine Variable vom Typ unsigned long ** ausgebe. %lu ist glaube ich nur für unsigned long.

    Wenn ich

    dmesg | tail

    mache, bekomme ich auch:

    [ 4650.670978] SysCallTable is located at: 0



  • Hab mir nochmals den kompletten Code durchgelesen und habe gesenden dass der Flag %p ausreicht:

    static int __init readlog_init(void) 
    {
    	unsigned long **sys_call_table = find_sys_call_table();
    	printk(KERN_ALERT "\nSysCallTable is located at: %p", sys_call_table);
       	return 0;
    }
    

    Leider funktioniert es immer noch nicht...

    [ 5804.215536] Loops per jiffy hat den Wert: 6383740<1>
    [ 5804.216292] SysCallTable is located at: 00000000<1>
    [ 5804.228201] Module unloaded

    Bitte um Hilfe



  • Stimmt der Code eigentlich von der Logik?


Anmelden zum Antworten