Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
extra_recipe — Exploit de Ian Beer para CVE-2017-2370 (r/w de memória do kernel no iOS 10.2) | Kitploit
Ferramentas/GitHubGitHub/ldebug/extra_recipe
Segurança iOSForensia de MemóriaAnálise de VulnerabilidadesExploraçãoSegurança MóvelExploração de Binários
GitHubldebug/extra_recipe

extra_recipe

Exploit de Ian Beer para CVE-2017-2370 (r/w de memória do kernel no iOS 10.2)

Ver Repositório
4há 9 anosAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar
Site

// ianbeer

exploit de leitura/escrita arbitrária no kernel para CVE-2017-2370 no iOS 10.2

Testado apenas em iPod Touch 6G 14C92 - outros dispositivos/firmwares não funcionarão imediatamente!

*** o bug *** mach_voucher_extract_attr_recipe_trap é uma armadilha mach que pode ser chamada de qualquer contexto. É um código totalmente novo, adicionado no 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;

}

Aqui está a estrutura de argumentos (controlada a partir do espaço do utilizador)

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 e recipe_size são ponteiros do espaço do utilizador.

No ponto (a) quatro bytes são lidos do ponteiro recipe_size (espaço do utilizador) para sz.

No ponto (b), se sz for menor que MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE (5120) e maior que MACH_VOUCHER_TRAP_STACK_LIMIT (256), sz é usado para alocar um buffer no heap do kernel.

No ponto (c), copyin é chamado novamente para copiar memória do espaço do utilizador para aquele buffer que foi alocado agora, mas em vez de passar sz (o tamanho validado que foi alocado) args->recipe_size é passado como o tamanho. Isto é o ponteiro do espaço do utilizador para o tamanho, não o tamanho!

Isto leva a um overflow do heap do kernel completamente controlado. Note que o código na verdade não pode funcionar corretamente :)

*** o exploit ***

Eu miro buffers de mensagens mach pré-alocados que são alocados via kalloc. Os primeiros 4 bytes são um campo de tamanho que é usado para determinar onde no buffer ler e escrever uma mensagem. Ao corromper este campo podemos fazer com que mensagens mach sejam lidas e escritas fora dos limites da alocação kalloc que sustenta o kmsg.

Há uma pequena complicação: o kmsg pré-alocado de uma porta só será usado para envios reais de mach_msg pelo kernel (não para respostas a métodos MIG, por exemplo). Isto torna um pouco mais complicado obter conteúdo controlado suficiente dentro deles.

Um tipo de mensagem mach que o kernel envia com muitos dados controlados pelo utilizador é uma mensagem de exceção, enviada quando uma thread crasha.

O ficheiro load_regs_and_crash.s contém assembly ARM64 que carrega os registos de propósito geral ARM64 com o conteúdo de um buffer de modo que, quando crasha, a mensagem de exceção contém esse buffer de dados (cerca de 0x70 bytes são controlados).

Ao sobrescrever o campo ikm_size da porta para apontar para o cabeçalho de outra porta, podemos ler e escrever o cabeçalho de outra porta e descobrir onde ela está na memória. Podemos então libertar essa segunda porta e realocar um user client no seu lugar, que também podemos ler e escrever.

Leio o ponteiro vtable do user client e uso a técnica do gadget OSSerializer::serialize conforme detalhado em [https://info.lookout.com/rs/051-ESQ-475/images/pegasus-exploits-technical-details.pdf] para chamar uma função arbitrária com dois argumentos controlados.

Eu chamo uuid_copy que chama memmove(arg0, arg1, 0x10). Ao apontar arg0 ou arg1 para dentro do próprio user client (que podemos ler recebendo a mensagem de exceção), podemos ler e escrever memória arbitrária do kernel em blocos de 16 bytes.

Baixar ferramenta