Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
extra_recipe — Ian Beers Exploit für CVE-2017-2370 (Kernel-Speicher r/w auf iOS 10.2) | Kitploit
Tools/GitHubGitHub/ldebug/extra_recipe
iOS-SicherheitSpeicherforensikSchwachstellenanalyseExploitationMobile SicherheitBinary-Exploitation
GitHubldebug/extra_recipe

extra_recipe

Ian Beers Exploit für CVE-2017-2370 (Kernel-Speicher r/w auf iOS 10.2)

Repository anzeigen
4vor 9 JahrenNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen
Webseite

// ianbeer

Kernel-Exploit für beliebiges Lesen und Schreiben (CVE-2017-2370) für iOS 10.2

Nur auf iPod Touch 6G 14C92 getestet – andere Geräte/Firmwares funktionieren nicht ohne Weiteres!

*** der Bug *** mach_voucher_extract_attr_recipe_trap ist ein Mach-Trap, der aus jedem Kontext aufgerufen werden kann. Es handelt sich um brandneuen Code, der in iOS 10 hinzugefügt wurde.

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;

}

Hier ist die Argumentstruktur (vom Userspace aus kontrolliert):

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 und recipe_size sind Userspace-Zeiger.

An Punkt (a) werden vier Bytes vom Userspace-Zeiger recipe_size in sz gelesen.

An Punkt (b) wird, wenn sz kleiner als MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE (5120) und größer als MACH_VOUCHER_TRAP_STACK_LIMIT (256) ist, sz verwendet, um einen Kernel-Heap-Puffer zu allokieren.

An Punkt (c) wird copyin erneut aufgerufen, um Userspace-Speicher in den gerade allokierten Puffer zu kopieren, aber anstatt sz (die validierte Größe, die allokiert wurde) zu übergeben, wird args->recipe_size als Größe übergeben. Das ist der Userspace-Zeiger auf die Größe, nicht die Größe selbst!

Dies führt zu einem vollständig kontrollierten Kernel-Heap-Overflow. Beachte, dass der Code eigentlich gar nicht korrekt funktionieren kann :)

*** der Exploit *** Ich ziele auf vorab allokierte Mach-Message-Puffer, die über kalloc allokiert werden. Die ersten 4 Bytes sind ein Größenfeld, das verwendet wird, um zu bestimmen, wo im Puffer eine Nachricht gelesen und geschrieben wird. Durch Korrumpieren dieses Feldes können wir bewirken, dass Mach-Messages außerhalb der Grenzen der kalloc-Allokation, die den kmsg stützt, gelesen und geschrieben werden.

Es gibt eine kleine Komplikation: Der vorab allokierte kmsg eines Ports wird nur für tatsächliche mach_msg-Sendungen durch den Kernel verwendet (nicht zum Beispiel für Antworten auf MIG-Methoden). Das macht es etwas kniffliger, genügend kontrollierten Inhalt in sie zu bekommen.

Ein Typ von Mach-Message, die der Kernel mit vielen benutzerkontrollierten Daten sendet, ist eine Exception-Message, die gesendet wird, wenn ein Thread abstürzt.

Die Datei load_regs_and_crash.s enthält ARM64-Assembly, die die ARM64-Allzweckregister mit dem Inhalt eines Puffers lädt, sodass die Exception-Message beim Absturz diesen Datenpuffer enthält (etwa 0x70 Bytes sind kontrolliert).

Indem wir das ikm_size-Feld des Ports überschreiben, sodass es auf den Header eines anderen Ports zeigt, können wir den Header eines anderen Ports lesen und schreiben und herausfinden, wo er sich im Speicher befindet. Wir können diesen zweiten Port dann freigeben und an seiner Stelle einen User-Client neu allokieren, den wir ebenfalls lesen und schreiben können.

Ich lese den vtable-Zeiger des User-Clients und verwende dann die OSSerializer::serialize-Gadget-Technik, wie in [https://info.lookout.com/rs/051-ESQ-475/images/pegasus-exploits-technical-details.pdf] beschrieben, um eine beliebige Funktion mit zwei kontrollierten Argumenten aufzurufen.

Ich rufe uuid_copy auf, das memmove(arg0, arg1, 0x10) aufruft. Indem wir entweder arg0 oder arg1 in den User-Client selbst zeigen lassen (den wir durch Empfangen der Exception-Message lesen können), können wir beliebigen Kernel-Speicher in 16-Byte-Blöcken lesen und schreiben.

Tool herunterladen