Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
extra_recipe — CVE-2017-2370 用の Ian Beer のエクスプロイト(iOS 10.2 におけるカーネルメモリの読み書き) | Kitploit
ツール/GitHubGitHub/ldebug/extra_recipe
iOSセキュリティメモリフォレンジック脆弱性分析エクスプロイトモバイルセキュリティバイナリエクスプロイト
GitHubldebug/extra_recipe

extra_recipe

CVE-2017-2370 用の Ian Beer のエクスプロイト(iOS 10.2 におけるカーネルメモリの読み書き)

リポジトリを見る
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) では、ユーザー空間のポインター recipe_size から 4 バイトが 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 です。これはサイズそのものではなく、サイズへのユーザー空間ポインターです!

これにより、完全に制御可能なカーネルヒープオーバーフローが発生します。ちなみに、このコードは実際には正しく動作しません :)

*** エクスプロイト ***

私は kalloc によって割り当てられる、事前割り当て済みの mach メッセージバッファーを標的にします。先頭の 4 バイトはサイズフィールドで、バッファー内のどこでメッセージを読み書きするかを決定するために使われます。このフィールドを破壊することで、kmsg を支える kalloc の割り当て範囲外で mach メッセージが読み書きされるようにできます。

少し厄介な点として、ポートの事前割り当て済み kmsg は、カーネルによる実際の mach_msg 送信にのみ使用されます(たとえば MIG メソッドへの応答には使用されません)。そのため、kmsg に十分な制御されたコンテンツを入れるのが少し難しくなります。

カーネルがユーザー制御データを大量に含めて送信するメッセージの一種に、スレッドがクラッシュしたときに送信される例外メッセージがあります。

load_regs_and_crash.s というファイルには、ARM64 の汎用レジスターにバッファーの内容をロードする ARM64 アセンブリが含まれており、クラッシュ時に例外メッセージにそのデータバッファー(約 0x70 バイトを制御可能)が含まれるようにしています。

ポートの ikm_size フィールドを別のポートのヘッダーを指すように上書きすることで、別のポートのヘッダーを読み書きし、そのメモリー上の位置を知ることができます。その後、その 2 番目のポートを解放し、同じ場所にユーザークライアントを再割り当てして、それも読み書きできるようにします。

私は userclient の vtable ポインターを読み取り、[https://info.lookout.com/rs/051-ESQ-475/images/pegasus-exploits-technical-details.pdf] で詳述されている OSSerializer::serialize ガジェット手法を使って、2 つの制御された引数で任意の関数を呼び出します。

私は uuid_copy を呼び出します。これは memmove(arg0, arg1, 0x10) を呼び出します。arg0 または arg1 のいずれかを userclient 自体(例外メッセージを受信することで読み取れる)に向けることで、任意のカーネルメモリーを 16 バイト単位で読み書きできます。

ツールをダウンロード