[FL-2759], [FL-2766] NFC collect params for mfkey32 attack (#1643)
* nfc: start nfc over rpc * nfc: add detect reader state * nfc: add reader analyzer * nfc: rework reader analyzer * reader_analyzer: print collected nonces to debug * reader analyzer: add save on SD card * reader_analyzer: separate mfkey related part to different file * mfkey32: add logic for collecting parameters * nfc: rework pcap with reader analyzer * nfc: add logger for reader * nfc: clean up * nfc: add detect reader view * nfc: add detect reader and mfkey nonces scenes * nfc: add mfkey comlplete scene * nfc: add new assets * nfc: fix gui * nfc: fix iso14443-4 UID emulation * nfc: add no sd card notification * nfc: fix grammar Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
#include "nfc_debug_pcap.h"
|
||||
|
||||
#include <storage/storage.h>
|
||||
#include <stream/buffered_file_stream.h>
|
||||
#include <furi_hal_nfc.h>
|
||||
#include <furi_hal_rtc.h>
|
||||
#include <stream_buffer.h>
|
||||
|
||||
#define TAG "NfcDebugPcap"
|
||||
|
||||
@@ -16,48 +18,94 @@
|
||||
#define DATA_PCD_TO_PICC_CRC_DROPPED 0xFA
|
||||
|
||||
#define NFC_DEBUG_PCAP_FILENAME EXT_PATH("nfc/debug.pcap")
|
||||
#define NFC_DEBUG_PCAP_BUFFER_SIZE 64
|
||||
|
||||
struct NfcDebugPcapWorker {
|
||||
bool alive;
|
||||
Storage* storage;
|
||||
File* file;
|
||||
StreamBufferHandle_t stream;
|
||||
FuriThread* thread;
|
||||
struct NfcDebugPcap {
|
||||
Stream* file_stream;
|
||||
};
|
||||
|
||||
static File* nfc_debug_pcap_open(Storage* storage) {
|
||||
File* file = storage_file_alloc(storage);
|
||||
if(!storage_file_open(file, NFC_DEBUG_PCAP_FILENAME, FSAM_WRITE, FSOM_OPEN_APPEND)) {
|
||||
storage_file_free(file);
|
||||
return NULL;
|
||||
}
|
||||
if(!storage_file_tell(file)) {
|
||||
struct {
|
||||
uint32_t magic;
|
||||
uint16_t major, minor;
|
||||
uint32_t reserved[2];
|
||||
uint32_t snaplen;
|
||||
uint32_t link_type;
|
||||
} __attribute__((__packed__)) pcap_hdr = {
|
||||
.magic = PCAP_MAGIC,
|
||||
.major = PCAP_MAJOR,
|
||||
.minor = PCAP_MINOR,
|
||||
.snaplen = FURI_HAL_NFC_DATA_BUFF_SIZE,
|
||||
.link_type = DLT_ISO_14443,
|
||||
};
|
||||
if(storage_file_write(file, &pcap_hdr, sizeof(pcap_hdr)) != sizeof(pcap_hdr)) {
|
||||
FURI_LOG_E(TAG, "Failed to write pcap header");
|
||||
static Stream* nfc_debug_pcap_open(Storage* storage) {
|
||||
Stream* stream = NULL;
|
||||
stream = buffered_file_stream_alloc(storage);
|
||||
if(!buffered_file_stream_open(stream, NFC_DEBUG_PCAP_FILENAME, FSAM_WRITE, FSOM_OPEN_APPEND)) {
|
||||
buffered_file_stream_close(stream);
|
||||
stream_free(stream);
|
||||
stream = NULL;
|
||||
} else {
|
||||
if(!stream_tell(stream)) {
|
||||
struct {
|
||||
uint32_t magic;
|
||||
uint16_t major, minor;
|
||||
uint32_t reserved[2];
|
||||
uint32_t snaplen;
|
||||
uint32_t link_type;
|
||||
} __attribute__((__packed__)) pcap_hdr = {
|
||||
.magic = PCAP_MAGIC,
|
||||
.major = PCAP_MAJOR,
|
||||
.minor = PCAP_MINOR,
|
||||
.snaplen = FURI_HAL_NFC_DATA_BUFF_SIZE,
|
||||
.link_type = DLT_ISO_14443,
|
||||
};
|
||||
if(stream_write(stream, (uint8_t*)&pcap_hdr, sizeof(pcap_hdr)) != sizeof(pcap_hdr)) {
|
||||
FURI_LOG_E(TAG, "Failed to write pcap header");
|
||||
buffered_file_stream_close(stream);
|
||||
stream_free(stream);
|
||||
stream = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return file;
|
||||
return stream;
|
||||
}
|
||||
|
||||
static void
|
||||
nfc_debug_pcap_write(NfcDebugPcapWorker* instance, uint8_t event, uint8_t* data, uint16_t len) {
|
||||
NfcDebugPcap* nfc_debug_pcap_alloc() {
|
||||
NfcDebugPcap* instance = malloc(sizeof(NfcDebugPcap));
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
instance->file_stream = nfc_debug_pcap_open(storage);
|
||||
if(!instance->file_stream) {
|
||||
free(instance);
|
||||
instance = NULL;
|
||||
}
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void nfc_debug_pcap_free(NfcDebugPcap* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->file_stream);
|
||||
|
||||
buffered_file_stream_close(instance->file_stream);
|
||||
stream_free(instance->file_stream);
|
||||
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void nfc_debug_pcap_process_data(
|
||||
NfcDebugPcap* instance,
|
||||
uint8_t* data,
|
||||
uint16_t len,
|
||||
bool reader_to_tag,
|
||||
bool crc_dropped) {
|
||||
furi_assert(instance);
|
||||
furi_assert(data);
|
||||
FuriHalRtcDateTime datetime;
|
||||
furi_hal_rtc_get_datetime(&datetime);
|
||||
|
||||
uint8_t event = 0;
|
||||
if(reader_to_tag) {
|
||||
if(crc_dropped) {
|
||||
event = DATA_PCD_TO_PICC_CRC_DROPPED;
|
||||
} else {
|
||||
event = DATA_PCD_TO_PICC;
|
||||
}
|
||||
} else {
|
||||
if(crc_dropped) {
|
||||
event = DATA_PICC_TO_PCD_CRC_DROPPED;
|
||||
} else {
|
||||
event = DATA_PICC_TO_PCD;
|
||||
}
|
||||
}
|
||||
|
||||
struct {
|
||||
// https://wiki.wireshark.org/Development/LibpcapFileFormat#record-packet-header
|
||||
uint32_t ts_sec;
|
||||
@@ -77,90 +125,6 @@ static void
|
||||
.event = event,
|
||||
.len = len << 8 | len >> 8,
|
||||
};
|
||||
xStreamBufferSend(instance->stream, &pkt_hdr, sizeof(pkt_hdr), FuriWaitForever);
|
||||
xStreamBufferSend(instance->stream, data, len, FuriWaitForever);
|
||||
}
|
||||
|
||||
static void
|
||||
nfc_debug_pcap_write_tx(uint8_t* data, uint16_t bits, bool crc_dropped, void* context) {
|
||||
NfcDebugPcapWorker* instance = context;
|
||||
uint8_t event = crc_dropped ? DATA_PCD_TO_PICC_CRC_DROPPED : DATA_PCD_TO_PICC;
|
||||
nfc_debug_pcap_write(instance, event, data, bits / 8);
|
||||
}
|
||||
|
||||
static void
|
||||
nfc_debug_pcap_write_rx(uint8_t* data, uint16_t bits, bool crc_dropped, void* context) {
|
||||
NfcDebugPcapWorker* instance = context;
|
||||
uint8_t event = crc_dropped ? DATA_PICC_TO_PCD_CRC_DROPPED : DATA_PICC_TO_PCD;
|
||||
nfc_debug_pcap_write(instance, event, data, bits / 8);
|
||||
}
|
||||
|
||||
int32_t nfc_debug_pcap_thread(void* context) {
|
||||
NfcDebugPcapWorker* instance = context;
|
||||
uint8_t buffer[NFC_DEBUG_PCAP_BUFFER_SIZE];
|
||||
|
||||
while(instance->alive) {
|
||||
size_t ret =
|
||||
xStreamBufferReceive(instance->stream, buffer, NFC_DEBUG_PCAP_BUFFER_SIZE, 50);
|
||||
if(storage_file_write(instance->file, buffer, ret) != ret) {
|
||||
FURI_LOG_E(TAG, "Failed to write pcap data");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NfcDebugPcapWorker* nfc_debug_pcap_alloc(Storage* storage) {
|
||||
NfcDebugPcapWorker* instance = malloc(sizeof(NfcDebugPcapWorker));
|
||||
|
||||
instance->alive = true;
|
||||
|
||||
instance->storage = storage;
|
||||
|
||||
instance->file = nfc_debug_pcap_open(storage);
|
||||
|
||||
instance->stream = xStreamBufferCreate(4096, 1);
|
||||
|
||||
instance->thread = furi_thread_alloc();
|
||||
furi_thread_set_name(instance->thread, "PcapWorker");
|
||||
furi_thread_set_stack_size(instance->thread, 1024);
|
||||
furi_thread_set_callback(instance->thread, nfc_debug_pcap_thread);
|
||||
furi_thread_set_context(instance->thread, instance);
|
||||
furi_thread_start(instance->thread);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void nfc_debug_pcap_free(NfcDebugPcapWorker* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
instance->alive = false;
|
||||
|
||||
furi_thread_join(instance->thread);
|
||||
furi_thread_free(instance->thread);
|
||||
|
||||
vStreamBufferDelete(instance->stream);
|
||||
|
||||
if(instance->file) storage_file_free(instance->file);
|
||||
|
||||
instance->storage = NULL;
|
||||
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void nfc_debug_pcap_prepare_tx_rx(
|
||||
NfcDebugPcapWorker* instance,
|
||||
FuriHalNfcTxRxContext* tx_rx,
|
||||
bool is_picc) {
|
||||
if(!instance || !instance->file) return;
|
||||
|
||||
if(is_picc) {
|
||||
tx_rx->sniff_tx = nfc_debug_pcap_write_rx;
|
||||
tx_rx->sniff_rx = nfc_debug_pcap_write_tx;
|
||||
} else {
|
||||
tx_rx->sniff_tx = nfc_debug_pcap_write_tx;
|
||||
tx_rx->sniff_rx = nfc_debug_pcap_write_rx;
|
||||
}
|
||||
|
||||
tx_rx->sniff_context = instance;
|
||||
stream_write(instance->file_stream, (uint8_t*)&pkt_hdr, sizeof(pkt_hdr));
|
||||
stream_write(instance->file_stream, data, len);
|
||||
}
|
||||
|
Reference in New Issue
Block a user