Skip to content
KitploitKITPLOIT
उपकरणएक्सप्लॉइटब्लॉग
Log in
जमा करें
उपकरणएक्सप्लॉइटब्लॉग
जमा करें

हैकिंग, पेनटेस्ट और साइबर सुरक्षा उपकरण आपके सुरक्षा शस्त्रागार के लिए!

Kitploit हैकिंग, साइबर सुरक्षा और पेंटेस्टिंग टूल्स की एक निर्देशिका है। कमजोरियों को खोजने, सिस्टम का विश्लेषण करने, परीक्षण को स्वचालित करने और अपनी सुरक्षा को मजबूत करने के लिए नवीनतम प्रोजेक्ट अपडेट खोजें।

फ़ीडसंपर्कगोपनीयता© 2026 Kitploit

टूल निर्देशिका

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
n_gsm_exploit — Linux kernel n_gsm TTY ioctl use-after-free एक्सप्लॉइट PoC: रेस कंडीशन विश्लेषण, kernel base leak, heap spray, RIP hijack, arbitrary write, और modprobe_path विशेषाधिकार उन्नयन। | Kitploit
उपकरण/GitHubGitHub/gmh5225/n_gsm_exploit
विशेषाधिकार वृद्धिमेमोरी फोरेंसिकभेद्यता विश्लेषणशोषणबाइनरी शोषण
GitHubgmh5225/n_gsm_exploit

n_gsm_exploit

Linux kernel n_gsm TTY ioctl use-after-free एक्सप्लॉइट PoC: रेस कंडीशन विश्लेषण, kernel base leak, heap spray, RIP hijack, arbitrary write, और modprobe_path विशेषाधिकार उन्नयन।

रिपॉजिटरी देखें
12 साल पहलेअभी तक समीक्षित नहीं

सबसे लोकप्रिय

सभी देखें →

हमारे समुदाय द्वारा सबसे अधिक उपयोग किए जाने वाले उपकरण खोजें।

सभी उपकरण खोजें

हमारे उपकरणों का संग्रह ब्राउज़ करें

सभी उपकरण देखें →
साझा करें

यह अभी भी 0-day प्रतीत होता है। vulnerability patch होने से पहले मेरा यह exploit प्रकाशित करने का कोई इरादा नहीं था, लेकिन एक अन्य researcher ने, जिसने वही vulnerability खोजी थी, एक 0-day exploit प्रकाशित कर दिया, इसलिए मैंने भी अपना code प्रकाशित कर दिया। कृपया इसका उपयोग केवल research उद्देश्यों के लिए करें।

RCA

  • Linux kernel का TTY GSM 07.10 multiplexing protocol का समर्थन करता है।
    • https://docs.kernel.org/driver-api/tty/n_gsm.html
    • https://github.com/torvalds/linux/blob/master/drivers/tty/n_gsm.c
  • जब GSM के लिए ioctl का अनुरोध किया जाता है, तो kernel में निम्नलिखित functions निष्पादित होते हैं:

[1] GSMIOC_SETCONF: GSM की configuration को reset करता है।

[2] GSMIOC_GETCONF_DLCI: GSM से संबद्ध DLCI configuration प्राप्त करता है।

[3] GSMIOC_SETCONF_DLCI: GSM से संबद्ध DLCI configuration को बदलता है।

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);
	}
}
  • आइए पहले GSMIOC_SETCONF की जाँच करें, जो GSM के कॉन्फ़िगरेशन को बदलता है।

  • [1] यदि GSM का वर्तमान कॉन्फ़िगरेशन नए कॉन्फ़िगरेशन से भिन्न है, तो need_restart को true के रूप में चिह्नित किया जाता है।

    [2] यदि need_restart true है, तो वर्तमान GSM को gsm_cleanup_mux के माध्यम से समाप्त किया जाता है।

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] GSM के स्वामित्व वाले सभी DLCI, gsm_dlci_release के माध्यम से जारी किए जाते हैं।

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]
		}

...
}
  • इसके बाद, फ़ंक्शन निम्नलिखित क्रम में कॉल किए जाते हैं:

    • gsm_dlci_release → dlci_put → gsm_dlci_free

    [1] Use-After-Free (UAF) को रोकने के लिए gsm->dlci[addr] में NULL असाइन किया जाता है।

    [2] इसके बाद, kfree का उपयोग करके gsm->dlci[addr] को मुक्त किया जाता है।

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

  • आइए GSMIOC_SETCONF_DLCI की जाँच करें, जो GSM के स्वामित्व वाले DLCI के कॉन्फ़िगरेशन मानों को बदलता है।

  • [1] उपयोगकर्ता से पता (addr) सहित DLCI कॉन्फ़िगरेशन पढ़ता है।

    [2] gsm->dlci[addr] का संदर्भ लेता है।

    [3] DLCI के कॉन्फ़िगरेशन को बदलने के लिए gsm_dlci_config को कॉल करता है।

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] उपयोगकर्ता द्वारा पास किए गए विकल्पों के आधार पर need_open को true पर सेट करता है।

[2] तब तक प्रतीक्षा करता है जब तक dlci->state DLCI_CLOSED न हो जाए।

[3] यदि केवल gsm->initiator true है, तो DLCI को पुनः आरंभ करने के लिए gsm_dlci_begin_open फ़ंक्शन को कॉल किया जाता है।

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;
}

vulnerability

[1] लॉक के बिना gsm->dlci तक पहुँचता है।

[1] gsm_dlci_config dlci तक पहुँचता है। यदि GSMIOC_SETCONF के कारण gsm_cleanup_mux को कॉल किया गया है, तो रेस कंडीशन Use-After-Free (UAF) का कारण बन सकती है।

  • सामान्य परिस्थितियों में, यह शर्त बहुत कम समय में पूरी हो जाती है, और wakeup को कॉल किया जाता है।
  • यदि UAF होता है, तो जब तक उपयोगकर्ता स्तर से wakeup रूटीन को कॉल करने के लिए कोई भिन्न IOCTL का अनुरोध नहीं किया जाता, तब तक यह अनंत प्रतीक्षा में प्रवेश कर जाता है।
  • इसलिए, एक हमलावर IOCTL पूरा होने तक की अवधि को मापकर यह निर्धारित कर सकता है कि UAF ट्रिगर हुआ है या नहीं।
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;
		}
	...
  • wait_event_interruptible में प्रतीक्षा के दौरान, GSM को threadFunction2 द्वारा पुनः आरंभ किया जाता है।
    • GSM द्वारा संदर्भित DLCI को kfree किया जाता है, और wait_event_interruptible द्वारा संदर्भित DLCI को भी kfree किया जाता है।
    • ऐसी स्थिति में, चूँकि IOCTL को पूरा होने में लंबा समय लगता है, उपयोगकर्ता स्थान (user space) से यह पहचानना आसान है कि Use-After-Free (UAF) हो चुका है।

कर्नेल बेस लीक करना

  • कर्नेल के hypercall_page का पता /sys/kernel/notes में लिखा होता है, जिसे सामान्य उपयोगकर्ता पढ़ सकते हैं। इसलिए, एक हमलावर कर्नेल बेस लीक करने के लिए इस फ़ाइल को पढ़ सकता है।
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;
टूल डाउनलोड करें