Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
extra_recipe — Ian Beer의 CVE-2017-2370 익스플로잇 (iOS 10.2 커널 메모리 r/w) | Kitploit
도구/GitHubGitHub/ldebug/extra_recipe
iOS SecurityMemory ForensicsVulnerability AnalysisExploitationMobile SecurityBinary Exploitation
GitHubldebug/extra_recipe

extra_recipe

Ian Beer의 CVE-2017-2370 익스플로잇 (iOS 10.2 커널 메모리 r/w)

저장소 보기
49년 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유
웹사이트

// ianbeer

iOS 10.2용 CVE-2017-2370 커널 임의 읽기/쓰기 익스플로잇

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) 지점에서 userspace 포인터 recipe_size에서 sz로 4바이트가 읽힙니다.

(b) 지점에서 sz가 MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE(5120)보다 작고 MACH_VOUCHER_TRAP_STACK_LIMIT(256)보다 크면 sz를 사용하여 커널 힙 버퍼를 할당합니다.

(c) 지점에서 copyin이 다시 호출되어 방금 할당된 버퍼로 사용자 공간 메모리를 복사하는데, 할당된 검증 크기인 sz를 전달하는 대신 args->recipe_size가 크기로 전달됩니다. 이것은 크기를 가리키는 userspace 포인터이지 크기 자체가 아닙니다!

이로 인해 완전히 제어 가능한 커널 힙 오버플로가 발생합니다. 참고로 이 코드는 실제로는 제대로 동작할 수 없습니다 :)

*** 익스플로잇 ***

저는 kalloc으로 할당되는 사전 할당된 mach 메시지 버퍼를 대상으로 삼습니다. 처음 4바이트는 메시지를 버퍼의 어디에서 읽고 쓸지 결정하는 데 사용되는 크기 필드입니다. 이 필드를 변조하면 kmsg를 뒷받침하는 kalloc 할당 경계를 벗어나 mach 메시지를 읽고 쓸 수 있습니다.

한 가지 약간의 복잡한 점은 포트의 사전 할당된 kmsg가 커널의 실제 mach_msg 전송에만 사용된다는 것입니다(예를 들어 MIG 메서드에 대한 응답에는 사용되지 않음). 따라서 그 안에 충분한 제어된 콘텐츠를 넣기가 조금 더 까다로워집니다.

커널이 사용자 제어 데이터를 많이 포함하여 보내는 mach 메시지 유형 중 하나는 스레드가 크래시할 때 전송되는 예외 메시지입니다.

load_regs_and_crash.s 파일에는 ARM64 범용 레지스터에 버퍼의 내용을 로드하는 ARM64 어셈블리가 포함되어 있어, 크래시가 발생하면 예외 메시지에 해당 데이터 버퍼가 포함됩니다(약 0x70바이트가 제어됨).

포트의 ikm_size 필드를 다른 포트의 헤더를 가리키도록 덮어쓰면 다른 포트의 헤더를 읽고 쓸 수 있으며 메모리에서 그 위치를 알아낼 수 있습니다. 그런 다음 두 번째 포트를 해제하고 그 자리에 사용자 클라이언트를 재할당하여 역시 읽고 쓸 수 있습니다.

저는 userclients의 vtable 포인터를 읽은 다음, [https://info.lookout.com/rs/051-ESQ-475/images/pegasus-exploits-technical-details.pdf]에 자세히 설명된 OSSerializer::serialize 가젯 기법을 사용하여 두 개의 제어된 인자로 임의 함수를 호출합니다.

저는 uuid_copy를 호출하는데, 이 함수는 memmove(arg0, arg1, 0x10)를 호출합니다. arg0 또는 arg1을 userclient 자체를 가리키도록 지정하면(예외 메시지를 수신하여 읽을 수 있음) 16바이트 단위로 임의의 커널 메모리를 읽고 쓸 수 있습니다.

도구 다운로드