Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
extra_recipe — Эксплойт Иана Бира для CVE-2017-2370 (чтение/запись памяти ядра на iOS 10.2) | Kitploit
Инструменты/GitHubGitHub/ldebug/extra_recipe
Безопасность iOSКриминалистика памятиАнализ уязвимостейЭксплуатацияМобильная безопасностьЭксплуатация Бинарных Файлов
GitHubldebug/extra_recipe

extra_recipe

Эксплойт Иана Бира для CVE-2017-2370 (чтение/запись памяти ядра на iOS 10.2)

Репозиторий
49 лет назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться
Сайт

// ianbeer

Эксплойт для произвольного чтения/записи в ядре для CVE-2017-2370 на iOS 10.2

Протестировано только на iPod Touch 6G 14C92 — другие устройства/прошивки не будут работать «из коробки»!

*** баг *** mach_voucher_extract_attr_recipe_trap — это mach-ловушка, которая может быть вызвана из любого контекста. Это совершенно новый код, добавленный в iOS 10.

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;

root@kitploit:~
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;

}

Вот структура аргументов (контролируется из пространства пользователя)

struct mach_voucher_extract_attr_recipe_args { PAD_ARG_(mach_port_name_t, voucher_name); PAD_ARG_(mach_voucher_attr_key_t, key); PAD_ARG_(mach_voucher_attr_raw_recipe_t, recipe); PAD_ARG_(user_addr_t, recipe_size); };

recipe и recipe_size — это указатели на пространство пользователя.

В точке (a) из указателя recipe_size (пространство пользователя) читаются четыре байта в переменную sz.

В точке (b), если sz было меньше MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE (5120) и больше MACH_VOUCHER_TRAP_STACK_LIMIT (256), sz используется для выделения буфера в куче ядра.

В точке (c) copyin вызывается снова, чтобы скопировать память из пространства пользователя в только что выделенный буфер, но вместо того, чтобы передавать sz (валидированный размер, который был выделен), в качестве размера передаётся args->recipe_size. Это указатель на размер из пространства пользователя, а не сам размер!

Это приводит к полностью контролируемому переполнению кучи ядра. Обратите внимание, что код на самом деле не может работать корректно :)

*** эксплойт ***

Я нацеливаюсь на предварительно выделенные буферы mach-сообщений, которые выделяются через kalloc. Первые 4 байта — это поле размера, которое используется для определения того, где в буфере читать и писать сообщение. Повреждая это поле, мы можем заставить mach-сообщения читаться и записываться за пределами выделения kalloc, лежащего в основе kmsg.

Есть небольшое осложнение: предварительно выделенный kmsg порта будет использоваться ядром только для фактических отправок mach_msg (не для ответов на методы MIG, например). Это делает немного сложнее поместить в них достаточное количество контролируемого содержимого.

Один из типов mach-сообщений, которые ядро отправляет с большим количеством контролируемых пользователем данных, — это сообщение об исключении, отправляемое при сбое потока.

Файл load_regs_and_crash.s содержит код ARM64, который загружает регистры общего назначения ARM64 содержимым буфера таким образом, что при сбое сообщение об исключении содержит этот буфер данных (контролируется около 0x70 байт).

Перезаписывая поле ikm_size порта так, чтобы оно указывало на заголовок другого порта, мы можем читать и записывать заголовок другого порта и узнавать его расположение в памяти. Затем мы можем освободить этот второй порт и перераспределить на его месте user client, который мы также можем читать и записывать.

Я читаю указатель vtable user client'а, а затем использую технику OSSerializer::serialize, как подробно описано в [https://info.lookout.com/rs/051-ESQ-475/images/pegasus-exploits-technical-details.pdf], чтобы вызвать произвольную функцию с двумя контролируемыми аргументами.

Я вызываю uuid_copy, которая вызывает memmove(arg0, arg1, 0x10). Указывая arg0 или arg1 на сам user client (который мы можем прочитать, получив сообщение об исключении), мы можем читать и записывать произвольную память ядра блоками по 16 байт.

Скачать инструмент