在上一篇文章中,我们了解了如何使用 Flipper Zero 实现透明阅读器。如果我们采用相同的概念,但这次实现一个透明的卡模拟器呢?我们可以像大炮一样使用 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 及其要发回的长度。
Flipper 提供了函数 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) 检索该响应。这部分有点棘手,因为在 shell 命令中,通常不会进行来回交换。所以,我使用函数 cli_getc(cli) 来读取一个字符。
最后,我们使用 unhexify(tmp, (uint8_t*)bit_buffer_get_data(rx_data), len); 将十六进制字符串转换为 uint8_t 数组。
如有必要,我们使用 add_crc 添加 CRC。
最后,我们可以使用以下方式将回复发送给读者:
FuriHalNfcError r = furi_hal_nfc_listener_tx(rx_data, bit_buffer_get_size(rx_cmd));.
现在,我们如何验证这一切?
好吧,我们可以使用上一篇文章中的透明阅读器来验证我们的模拟器。所以,我们需要两个脚蹼零点……但我没有。不过,我有 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 |
它非常实用,因为它允许我们一一发送命令来验证一切:
然而,实际上,沟通要复杂一些。因此,我使用 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-block、r-block、s-block),但这将在以后的博客文章中介绍。
FuriHalNfcEvent event = furi_hal_nfc_listener_wait_event(100);
这样就很好用了,仿真也极其稳定。我可以将 Flipper 从读卡器上放置或移除,并多次发送命令,而且每次都有效。 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 对于调试嗅探模式下的通信非常有用:我将其放置在读卡器和卡(可以是正品卡或 Flipper)之间,并且我能够检查数据交换。
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 黑客攻击 - cannon fooder的详细内容。更多信息请关注PHP中文网其他相关文章!