前の投稿では、Flipper Zero を使用して透明リーダーを実装する方法を説明しました。同じコンセプトを採用して、今度は透過的なカード エミュレータを実装したらどうなるでしょうか?フリッパー ゼロを大砲のように使用して、誤ったリクエストを送信することで、リーダーやスマートフォンなどのデジタル要塞を攻撃することができます。不正なコマンド、ライフサイクルで予期されないコマンド、ファジング、バッファ オーバーフローなど、限界はありません!
透明カード リーダーと同様に、コンピューターからシリアル CLI を使用して Flipper と通信したいと考えています。コンピューターはすべてのロジックを処理します。つまり、Python スクリプトなどを使用して、コマンドに応じてどのような応答を返すかを決定します。
次に、カード エミュレータ コマンドの実装についてですが、これは本質的に、リーダーと比較して一種のミラー モードです。
ただし、物事を複雑にする小さな点があります。カードとリーダーの通信中、リーダーがマスターとして機能すること、つまり、通信を開始してコマンドを送信するのはリーダーであることに注意してください。
つまり、カード エミュレータを作成している場合、リーダーからのイベントを待機している必要があります。リーダーがクライアントとして機能するサーバーのように考えることができます。これを Flipper Zero にコーディングする必要があります。
それでは、まず、ISO 14443-A を使用したリーダーとカード間の通信交換について簡単にまとめてみましょう。
これは、ISO 14443-A を介して通信するリーダーとカード間の主なやり取りをまとめた図です。
+----------------+ +----------------+ | Reader | | Card | +----------------+ +----------------+ | | Field activation | | | | --- REQA (Request Command Type A) -------------> | | 26 | | | | <------------ ATQA (Answer to Request Type A) ---| | 04 00 | | | --- ANTICOLLISION Command ---------------------->| | | | <------------ UID (Unique Identifier) -----------| | | | --- SELECT [UID] Command ----------------------->| | | | <------------ SAK (Select Acknowledge) ----------| | | | --- RATS (Request for Answer To Select) -------->| | E0 50 BC A5 | | | | <------------ ATS (Answer To Select) ------------| | 0A 78 80 82 02 20 63 CB A3 A0 92 43 | | | | ---- [Opt] PPS (Proto and Parameter Selection) ->| | D0 73 87 | | | | <------------ [PPS Response] --------------------| | D0 73 87 | | | | --- TPDU [Encapsulated APDU Command] ----------->| | 0200A404000E325041592E5359532E444446303100E042 | | | | <------------ TPDU [Encapsulated APDU Response] -| | 00a404000e325041592e5359532e444446303100 |
ここで問題は、「Flipper でこれらすべてをどのように実装するか?」です。
前の記事と同様に、applications/main/nfc/nfc_cli.c ファイルの展開を続けます (ブランチにあるファイルを参照してください)。
まず、ハードウェアについて簡単に説明します。 NFC 管理には、Flipper Zero は ST25R3916 チップを使用します。これは、非接触リーダーとカード エミュレーターの両方を作成できるため、非常に優れています。チップは、フィールドのアクティブ化から衝突防止まで、関連するコマンドの送信を自動的に処理します。必要なのは、送り返す ATQA、SAK、UID、およびその長さを指定することだけです。
フリッパーは、これらすべてを処理する関数 furi_hal_nfc_iso14443a_listener_set_col_res_data を提供します。
そのため、Flipper の NFC CLI に 3 つのコマンドを追加して、これらの要素を設定しました。
エミュレーションを開始する直前に、これらのパラメータを指定して furi_hal_nfc_iso14443a_listener_set_col_res_data を呼び出します。
+----------------+ +----------------+ | Reader | | Card | +----------------+ +----------------+ | | Field activation | | | | --- REQA (Request Command Type A) -------------> | | 26 | | | | <------------ ATQA (Answer to Request Type A) ---| | 04 00 | | | --- ANTICOLLISION Command ---------------------->| | | | <------------ UID (Unique Identifier) -----------| | | | --- SELECT [UID] Command ----------------------->| | | | <------------ SAK (Select Acknowledge) ----------| | | | --- RATS (Request for Answer To Select) -------->| | E0 50 BC A5 | | | | <------------ ATS (Answer To Select) ------------| | 0A 78 80 82 02 20 63 CB A3 A0 92 43 | | | | ---- [Opt] PPS (Proto and Parameter Selection) ->| | D0 73 87 | | | | <------------ [PPS Response] --------------------| | D0 73 87 | | | | --- TPDU [Encapsulated APDU Command] ----------->| | 0200A404000E325041592E5359532E444446303100E042 | | | | <------------ TPDU [Encapsulated APDU Response] -| | 00a404000e325041592e5359532e444446303100 |
次に、関数 furi_hal_nfc_set_mode を使用して、Flipper Zero をカード エミュレータ モードに設定します。今回はモード FuriHalNfcModeListener を指定し、テクノロジーは標準値 FuriHalNfcTechIso14443a、FuriHalNfcTechIso14443b、FuriHalNfcTechIso15693 を使用します。
最後に、エミュレーションを開始するために、近くのリーダーを待機する無限ループを開始するコマンド run_emu を実装しました。イベント監視は関数 furi_hal_nfc_listener_wait_event によって処理されます。
if(g_NfcTech == FuriHalNfcTechIso14443a) { furi_hal_nfc_iso14443a_listener_set_col_res_data(g_uid, g_uid_len, g_atqa, g_sak); fdt = ISO14443_3A_FDT_LISTEN_FC; }
次に、イベントは、検出された内容に応じて複数の値を取ることができます。
FuriHalNfcEvent event = furi_hal_nfc_listener_wait_event(100);
次に、コマンドの受信と応答の送信を処理する方法を見てみましょう。
while(true) { FuriHalNfcEvent event = furi_hal_nfc_listener_wait_event(100); if(event == FuriHalNfcEventTimeout) { if(cli_cmd_interrupt_received(cli)) { break; } } if(event & FuriHalNfcEventAbortRequest) { break; } if(event & FuriHalNfcEventFieldOn) { printf("on\r\n"); } if(event & FuriHalNfcEventFieldOff) { furi_hal_nfc_listener_idle(); printf("off\r\n"); } if(event & FuriHalNfcEventListenerActive) { // Nothing } if(event & FuriHalNfcEventRxEnd) {
次に、端末は関数 nfc_emu_get_resp(cli, rx_cmd) を使用して取得した応答を送信します。シェル コマンドでは通常、やり取りが行われないため、この部分は少し注意が必要です。そこで、関数 cli_getc(cli) を使用して文字を読み取ります。
最後に、unhexify(tmp, (uint8_t*)bit_buffer_get_data(rx_data), len); を使用して 16 進文字列を uint8_t 配列に変換します。
必要に応じて、add_crc を使用して CRC を追加します。
最後に、次を使用してリーダーに応答を送信できます:
FuriHalNfcError r = furi_hal_nfc_listener_tx(rx_data, bit_buffer_get_size(rx_cmd));.
では、これらすべてをどのように検証すればよいでしょうか?
前回の投稿の透過リーダーを使用して、エミュレータを検証できます。したがって、フリッパー ゼロが 2 つ必要になります...私は持っていません。ただし、私は Hydra NFC v2 を持っているので、透過的なリーダーのセットアップが可能です。
pynfc のスクリプトを使用する必要があるだけです。
+----------------+ +----------------+ | Reader | | Card | +----------------+ +----------------+ | | Field activation | | | | --- REQA (Request Command Type A) -------------> | | 26 | | | | <------------ ATQA (Answer to Request Type A) ---| | 04 00 | | | --- ANTICOLLISION Command ---------------------->| | | | <------------ UID (Unique Identifier) -----------| | | | --- SELECT [UID] Command ----------------------->| | | | <------------ SAK (Select Acknowledge) ----------| | | | --- RATS (Request for Answer To Select) -------->| | E0 50 BC A5 | | | | <------------ ATS (Answer To Select) ------------| | 0A 78 80 82 02 20 63 CB A3 A0 92 43 | | | | ---- [Opt] PPS (Proto and Parameter Selection) ->| | D0 73 87 | | | | <------------ [PPS Response] --------------------| | D0 73 87 | | | | --- TPDU [Encapsulated APDU Command] ----------->| | 0200A404000E325041592E5359532E444446303100E042 | | | | <------------ TPDU [Encapsulated APDU Response] -| | 00a404000e325041592e5359532e444446303100 |
コマンドを 1 つずつ送信してすべてを検証できるため、非常に実用的です。
しかし、実際には、コミュニケーションはもう少し複雑です。そこで、PC/SC リーダーである ACR122U を使用して完全な APDU コマンドを送受信し、Python スクリプト ( pyscard を使用) と組み合わせて実際のテストを行いました。
私の場合は、単純に PPSE アプリケーションを選択します。
if(g_NfcTech == FuriHalNfcTechIso14443a) { furi_hal_nfc_iso14443a_listener_set_col_res_data(g_uid, g_uid_len, g_atqa, g_sak); fdt = ISO14443_3A_FDT_LISTEN_FC; }
したがって、カード エミュレータはさらに多くのイベントを処理する必要があります。したがって、このケースに対処するために、以下の Python スクリプトを作成しました。さまざまなタイプの TPDU (i ブロック、r ブロック、s ブロック) など、説明すべきことはたくさんありますが、それについては今後のブログ投稿で説明します。
FuriHalNfcEvent event = furi_hal_nfc_listener_wait_event(100);
これにより、非常にうまく動作し、エミュレーションは非常に安定しました。フリッパーをリーダーに配置したり、リーダーから取り外したりしてコマンドを複数回送信することができ、毎回機能します。もう一度言いますが、Flipper は NFC レイヤーの優れた実装を備えており、その API により最小限の実装労力で多くの機能が可能になります。
以下に、Python スクリプトからの出力のサンプルを示します。
+----------------+ +----------------+ | Reader | | Card | +----------------+ +----------------+ | | Field activation | | | | --- REQA (Request Command Type A) -------------> | | 26 | | | | <------------ ATQA (Answer to Request Type A) ---| | 04 00 | | | --- ANTICOLLISION Command ---------------------->| | | | <------------ UID (Unique Identifier) -----------| | | | --- SELECT [UID] Command ----------------------->| | | | <------------ SAK (Select Acknowledge) ----------| | | | --- RATS (Request for Answer To Select) -------->| | E0 50 BC A5 | | | | <------------ ATS (Answer To Select) ------------| | 0A 78 80 82 02 20 63 CB A3 A0 92 43 | | | | ---- [Opt] PPS (Proto and Parameter Selection) ->| | D0 73 87 | | | | <------------ [PPS Response] --------------------| | D0 73 87 | | | | --- TPDU [Encapsulated APDU Command] ----------->| | 0200A404000E325041592E5359532E444446303100E042 | | | | <------------ TPDU [Encapsulated APDU Response] -| | 00a404000e325041592e5359532e444446303100 |
Proxmark 3 の使用は、スニッフィング モードでの通信のデバッグに役立ちました。Proxmark 3 をリーダーとカード (本物のカードまたはフリッパー) の間に置き、データ交換を確認することができました。
if(g_NfcTech == FuriHalNfcTechIso14443a) { furi_hal_nfc_iso14443a_listener_set_col_res_data(g_uid, g_uid_len, g_atqa, g_sak); fdt = ISO14443_3A_FDT_LISTEN_FC; }
よし、次は何だ?
以上がFlipper Zero NFC ハッキング - 大砲の食べ物屋の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。