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

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

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

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

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

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
CVE-2017-2370 — Mac 10.12.2 पर | Kitploit
उपकरण/GitHubGitHub/peterpan0927/cve-2017-2370
विशेषाधिकार वृद्धिआईओएस सुरक्षामेमोरी फोरेंसिकशोषणजानकारी एकत्र करनाबाइनरी शोषण
GitHubpeterpan0927/cve-2017-2370

CVE-2017-2370

Mac 10.12.2 पर

रिपॉजिटरी देखें
203158 साल पहलेKitploit द्वारा समीक्षित

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

सभी देखें →

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

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

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

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

0x00. प्रस्तावना

इस बार privilege escalation के लिए mach_voucher_extract_attr_recipe_trap में मौजूद एक भेद्यता का उपयोग किया गया है, और शोषण विधि का मूल MACH_MSG_OOL_PORTS_DESCRIPTOR संदेश के माध्यम से है।

mach_msg ool के बारे में सीधे शब्दों में कहें तो, जब एक msg जिसमें ool descriptor होता है, भेजा जाता है, तो कर्नेल निर्दिष्ट डेटा को user space से kernel space में कॉपी करता है, और कर्नेल इस डेटा को तब तक बनाए रखता है जब तक लक्ष्य task संदेश को संसाधित नहीं कर लेता। इसी तरह, जब लक्ष्य प्रक्रिया एक ऐसा संदेश प्राप्त करती है जिसमें ool descriptor होता है, तो कर्नेल डेटा को kernel space से user space में कॉपी करता है (जरूरी नहीं कि वास्तविक कॉपी हो)। इसलिए इस तकनीकी बिंदु का उपयोग kernel heap में डेटा लिखने या कर्नेल से डेटा पढ़ने के लिए किया जा सकता है।

चूँकि इस भेद्यता का शोषण Trident की तुलना में कहीं अधिक जटिल है, इसलिए मैंने इसे चरण-दर-चरण धीरे-धीरे विश्लेषित किया है, भेद्यता के उत्पत्ति बिंदु से लेकर कदम-दर-कदम शोषण तक। कोड मेरे github पर देखा जा सकता है।

0x01. भेद्यता का उत्पत्ति बिंदु

iOS 10 और macOS 10.12 में जोड़ी गई नई सुविधाओं में mach_voucher_extract_attr_recipe_trap नामक एक फ़ंक्शन है, जो एक Mach trap है जिसे sandbox के अंदर कॉल किया जा सकता है। इस फ़ंक्शन का स्रोत कोड नीचे दिया गया है:

kern_return_t
  mach_voucher_extract_attr_recipe_trap(struct mach_voucher_extract_attr_recipe_args *args)
  {
    ipc_voucher_t voucher = IV_NULL;
    kern_return_t kr = KERN_SUCCESS;
    mach_msg_type_number_t sz = 0;
	//将recipe_size的地址拷贝到sz中,此时sz存放的就是kalloc_size的值了
    if (copyin(args->recipe_size, (void *)&sz, sizeof(sz)))     <---------- (a)
      return KERN_MEMORY_ERROR;

    if (sz > MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE)
      return MIG_ARRAY_TOO_LARGE;

    voucher = convert_port_name_to_voucher(args->voucher_name);
    if (voucher == IV_NULL)
      return MACH_SEND_INVALID_DEST;

    mach_msg_type_number_t __assert_only max_sz = sz;

    if (sz < MACH_VOUCHER_TRAP_STACK_LIMIT) {
      /* keep small recipes on the stack for speed */
      uint8_t krecipe[sz];
      if (copyin(args->recipe, (void *)krecipe, sz)) {
        kr = KERN_MEMORY_ERROR;
        goto done;
      }
      kr = mach_voucher_extract_attr_recipe(voucher, args->key,
                                            (mach_voucher_attr_raw_recipe_t)krecipe, &sz);
      assert(sz <= max_sz);

      if (kr == KERN_SUCCESS && sz > 0)
        kr = copyout(krecipe, (void *)args->recipe, sz);
    } else {
      uint8_t *krecipe = kalloc((vm_size_t)sz);                 <---------- (b)
      if (!krecipe) {
        kr = KERN_RESOURCE_SHORTAGE;
        goto done;
      }

      if (copyin(args->recipe, (void *)krecipe, args->recipe_size)) {         <----------- (c)
        kfree(krecipe, (vm_size_t)sz);
        kr = KERN_MEMORY_ERROR;
        goto done;
      }

      kr = mach_voucher_extract_attr_recipe(voucher, args->key,
                                            (mach_voucher_attr_raw_recipe_t)krecipe, &sz);
      assert(sz <= max_sz);

      if (kr == KERN_SUCCESS && sz > 0)
        kr = copyout(krecipe, (void *)args->recipe, sz);
      kfree(krecipe, (vm_size_t)sz);
    }

    kr = copyout(&sz, args->recipe_size, sizeof(sz));

  done:
    ipc_voucher_release(voucher);
    return kr;
  }
  1. विश्लेषण से हम जान सकते हैं कि बिंदु a पर 4-बाइट user space पॉइंटर args->recipe_size को sz में लिखा जाता है।
  2. बिंदु b पर, यदि sz का आकार MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE (5120) और MACH_VOUCHER_TRAP_STACK_LIMIT (256) के बीच है, तो sz के मान के अनुसार एक kernel heap बफर आवंटित किया जाता है।
  3. बिंदु c पर user space की मेमोरी को अभी आवंटित क्षेत्र में कॉपी किया जाता है, लेकिन कॉपी के लिए पारित आकार वह sz नहीं है जिसका उपयोग kernel heap आवंटित करने के लिए किया गया था, बल्कि एक user space पॉइंटर है, जिससे heap overflow उत्पन्न होता है। हम इसी बिंदु का उपयोग हमला करने के लिए करते हैं, और copyin फ़ंक्शन की एक विशेषता यह है कि unmap किए गए पृष्ठों का सामना करने पर कॉपी रुक जाती है। यह विशेषता हमारे poc में उपयोग की जाएगी:

copyin

0x01. शोषण के चरण

  1. सबसे पहले हमें हीप स्पेस को नियंत्रित करना होगा। यहाँ हम जिस तकनीक का उपयोग करते हैं वह heap feng shui है, क्योंकि freelist randomisation के बाद हमें पता नहीं होता कि पुनः आवंटित मेमोरी ब्लॉक कहाँ स्थित है।

सबसे पहले mach msg में MACH_MSG_OOL_PORTS_DESCRIPTOR के प्रसंस्करण को समझना आवश्यक है। जब कर्नेल को एक जटिल संदेश प्राप्त होता है और वह पाता है कि यह ports descriptor है, तो वह इसे (ipc_kmsg_copyin द्वारा कॉल किए गए) ipc_kmsg_copyin_ool_ports_descriptor फ़ंक्शन को सौंपता है, जो सभी port ऑब्जेक्ट्स को पढ़ता है। यह फ़ंक्शन आवश्यक मेमोरी आवंटित करने के लिए kalloc को कॉल करता है (64-बिट में आवंटित मेमोरी इनपुट का 2 गुना होती है, name की लंबाई 4 बाइट्स होती है), फिर वैध port के name को वास्तविक ipc_port ऑब्जेक्ट पते में बदलकर संग्रहीत करता है। इनपुट में MACH_PORT_NULL或者MACH_PORT_DEAD वाले name के लिए, इसे अपरिवर्तित रखा जाता है।

/* calculate length of data in bytes, rounding up */
if (os_mul_overflow(count, sizeof(mach_port_t), &ports_length)) { 
	*mr = MACH_SEND_TOO_LARGE; 
	return NULL; 
} 

if (os_mul_overflow(count, sizeof(mach_port_name_t), &names_length)) { 
    *mr = MACH_SEND_TOO_LARGE;
	return NULL; 
} 

if(ports_length == 0){
    return user_desc;
}

data = kalloc(ports_length); // 分配空间 
... 
objects = (ipc_object_t *) data; 

dsc->address = data; 

for ( i = 0; i < count; i++) { 
    mach_port_name_t name = names[i]; 
    ipc_object_t object;
    if (!MACH_PORT_VALID(name)) {
        objects[i] = (ipc_object_t)CAST_MACH_NAME_TO_PORT(name);// IPC_PORT_DEAD continue; 
    } 
...
}

इसलिए हमला करते समय हम बड़ी मात्रा में MACH_PORT_DEAD भेजते हैं, मेमोरी क्षेत्र को 0xFFFFFFFFFFFFFFFF (MACH_PORT_DEAD) से भर देते हैं, फिर भेद्यता को ट्रिगर करके एक IPC_PORT_DEAD को हमलावर द्वारा व्यवस्थित मेमोरी क्षेत्र में बदल देते हैं। यदि इंगित किया गया क्षेत्र एक वैध ipc port संरचना है, तो OOL PORTS संदेश प्राप्त करने के बाद, user space में इस ipc_port के अनुरूप port name प्राप्त किया जा सकता है, और अगला हमला किया जा सकता है।

堆风水

  1. ipc_object ऑब्जेक्ट का निर्माण

सबसे पहले हमें यह fake port प्राप्त हो चुका है। आगे जानकारी लीक (information leak) करने के लिए यह जानना आवश्यक है कि कर्नेल किन मापदंडों के आधार पर इसके साथ अलग-अलग व्यवहार करता है। पहले ipc_port की संरचना देखें:

struct ipc_port {
	//ipc_object的指针就在前八个字节,是我们溢出攻击的对象
	struct ipc_object ip_object; // port对象的类型 struct ipc_mqueue,ip_messages;
	struct ipc_mqueue ip_messages; //消息队列
	union {
               struct ipc_space *receiver;
               struct ipc_port *destination;
               ipc_port_timestamp_t timestamp;
    }data;
	union {
    	ipc_importance_task_t imp_task;
    	ipc_kobject_t kobject; // port对应的内核对象
    	uintptr_t alias;
	}kdata;
	...
} __attribute__((__packed__));

इसमें एक port के अनुरूप kernel object होता है, और यह कि यह ipc_port किस प्रकार के kernel object के अनुरूप है, यह ipc_object के गुणों द्वारा निर्धारित होता है। इसलिए हम वास्तव में ipc_object को निर्मित (craft) कर रहे हैं।

fakeport->io_bits = IO_BITS_ACTIVE | IKOT_CLOCK; //设置为IKOT_CLOCK对象,并处于激活状态
fakeport->io_lock_data[12] = 0x11;	//设置port锁处于活动状态,防止死锁

कर्नेल इस ipc_port को IKOT_CLOCK ऑब्जेक्ट के साथ संचार के लिए उपयोग होने वाला port मान लेगा। अगला उद्देश्य kernel base address लीक करना है:

टूल डाउनलोड करें