Das Modul wurde im Rahmen meiner Masterarbeit im Jahr 2010 erstellt. Das Thema der Masterarbeit ist Keylogging im Linux-Kernel . Die Hauptidee war, einen Weg zu finden, um Systemaufrufe für den x64 arch Linux-Kernel abzufangen, insbesondere für den Kernel 2.6.34.7-61.fc13.x86_64.
Einführung
Es gab viele verschiedene Artikel über das Abfangen von Systemaufrufen für x32 arch. Im Rahmen einer Recherche stellte ich mich der Frage, wie Systemaufrufe für x86_64 arch über ein Linux-Kernel-Modul abgefangen werden können.
Wie können wir einen Systemaufruf abfangen?
- Finden Sie die Adresse der Syscall-Tabelle heraus.
- Ersetzen Sie den ursprünglichen Systemaufruf durch den neuen.
Syscall-Tabellenadresse
IDT (Interrupt D escription Table) begrenzt den Interrupt-Handler und den Interrupt-Code . Im geschützten Modus ist IDT ein Array von Deskriptoren, die im Speicher gespeichert sind. Jeder Prozessor hat ein spezielles IDTR- Register. Das Register besteht aus der physischen IDT-Adresse und der IDT-Länge. Die erste Annahme war, die IDT-Adresse aus dem IDTR-Register abzurufen und anschließend die Adresse der Syscall-Tabellen zu berechnen. Die Annahme war jedoch falsch, da wir in diesem Fall die x32-Handleradresse erhalten haben.
Die zweite Annahme war interessanter. Bevor ich fortfahre, möchte ich MSR (Macodell Specific R egister) beschreiben. Ein MSR ist eines von verschiedenen Steuerregistern im x86-Befehlssatz, die zum Debuggen, Verfolgen der Programmausführung, Überwachen der Computerleistung und Umschalten bestimmter CPU-Funktionen verwendet werden. Lassen Sie uns über MSR_LSTAR
- 0xc0000082
(Langmodus-SYSCALL-Ziel) sprechen. Die vollständige Liste finden Sie unter /usr/include/asm/msr-index.h
.
Der MSR_LSTAR
speichert den Systemaufrufeintrag für die x86-64-Architektur. Sie können die Adresse erhalten:
int i, lo, hi; asm volatile("rdmsr" : "=a" (lo), "=d" (hi) : "c" (MSR_LSTAR)); system_call = (void*)(((long)hi<<32) | lo);
Gehen wir weiter. Ich hatte die Adresse und suchte \xff\x14\xc5
. \xff\x14\xc5
ist eine magische Zahl. Wenn Sie den Code von Kernel 2.6.34.7-61.fc13.x86_64 durchsehen, insbesondere die Funktion system_call
, werden Sie feststellen, dass die nächsten 4 Bytes die Adresse syscall_table sind.
Wir kannten die Syscall-Tabellenadresse, was bedeutete, dass wir eine Syscall-Handler-Adresse erhalten und diese ersetzen / abfangen konnten.
Der Quellcode:
unsigned char *ptr; for (ptr=system_call, i=0; i<500; i++) { if (ptr[0] == 0xff && ptr[1] == 0x14 && ptr[2] == 0xc5) return (void*)(0xffffffff00000000 | *((unsigned int*)(ptr+3))); ptr++; }
Abfangen von Systemaufrufen
Ich stand vor einem Problem. Beim Ändern einer Adresse in der Systemaufruftabelle ist ein Fehler aufgetreten. Zum Glück war es ganz einfach:
- Speicherschutz deaktivieren.
- Schreiben Sie eine Syscall-Handler-Adresse neu.
- Aktivieren Sie den Speicherschutz.
Wenn Sie den Speicherschutz deaktivieren möchten, sollten Sie CR0
wissen: Das Register CR0
besteht aus Flags. Die Flags verwalten das Prozessorverhalten. Das Flag WP ist Write Protect
, es ist das 48. Bit bei CR0
.
Speicherschutz deaktivieren:
asm("pushq %rax"); asm("movq %cr0, %rax"); asm("andq $0xfffffffffffeffff, %rax"); asm("movq %rax, %cr0"); asm("popq %rax");
Speicherschutz aktivieren:
asm("pushq %rax"); asm("movq %cr0, %rax"); asm("xorq $0x0000000000001000, %rax"); asm("movq %rax, %cr0"); asm("popq %rax");
Fazit
Einerseits sollte es ausreichen, um das Abfangen von Systemaufrufen zu behandeln, andererseits bin ich mir nicht sicher, ob sich seit 2010 nichts geändert hat. Verwenden Sie es also so, wie es ist. Der Quellcode befindet sich unter github.com/ultral/linux-keylogger .
PS