From f51cb7e0b47a966bd882edf68e93ae7249b992c5 Mon Sep 17 00:00:00 2001 From: andreock Date: Thu, 28 Nov 2024 23:10:36 +0100 Subject: [PATCH] Add NFC write support for ultralight/NTAG and FlipperZero file format --- .../flipper_zero_nfc_file_parser.cpp | 92 +++++++++++++++++++ .../flipper_zero_nfc_file_parser.hpp | 21 +++++ lib/nfc_attacks/nfc_attacks.cpp | 12 +++ lib/nfc_attacks/nfc_attacks.hpp | 1 + lib/nfc_attacks/nfc_tasks.cpp | 12 ++- 5 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 lib/nfc_attacks/flipper_zero_nfc_file_parser.cpp create mode 100644 lib/nfc_attacks/flipper_zero_nfc_file_parser.hpp diff --git a/lib/nfc_attacks/flipper_zero_nfc_file_parser.cpp b/lib/nfc_attacks/flipper_zero_nfc_file_parser.cpp new file mode 100644 index 0000000..91a2b71 --- /dev/null +++ b/lib/nfc_attacks/flipper_zero_nfc_file_parser.cpp @@ -0,0 +1,92 @@ +/* + * This file is part of the Capibara zero (https://github.com/CapibaraZero/fw or + * https://capibarazero.github.io/). Copyright (c) 2024 Andrea Canale. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "../UI/navigation/NFC/NFCNavigation.hpp" +#include "nfc_attacks.hpp" + +static int count_chars_in_line(const char *str, int pos) { + int end_pos = pos; + while (str[end_pos] != '\n') { + end_pos++; + } + return end_pos; +} + +static std::vector split(std::string &s, + const std::string &delimiter) { + std::vector tokens; + size_t pos = 0; + std::string token; + while ((pos = s.find(delimiter)) != std::string::npos) { + token = s.substr(0, pos); + tokens.push_back(token); + s.erase(0, pos + delimiter.length()); + } + tokens.push_back(s); + + return tokens; +} + +void flipper_zero_nfc_parser(std::string file, NFCAttacks *attacks) { + int start_position = file.find("Device type:"); + start_position += std::string("Device type: ").size(); + int end_position = count_chars_in_line(file.c_str(), start_position); + int type = 0; + std::string nfc_type = + file.substr(start_position, end_position - start_position); + if (nfc_type == "Mifare Classic") { + type = 0; + } else if (nfc_type.find("NTAG") != std::string::npos) { + type = 1; + } + start_position = type == 0 ? file.find("Block 0:") : file.find("Page 0:"); + std::string blocks_str = file.substr(start_position); + size_t i = 0; + std::vector blocks = split(blocks_str, "\n"); + uint8_t key[6] = {0xFF, 0xFF, 0XFF, 0XFF, 0XFF, 0XFF}; + size_t wrote_sectors = 0; + size_t unwritable_sectors = 0; + for (std::string block : blocks) { + if (block.find("Failed") == std::string::npos && block != "") { + uint8_t data[type == 0 ? 16 : 4]; + size_t substr_space = i < 10 ? 9 : 10; + if(type != 0) { + substr_space--; + } + std::string parsed_blocks = block.substr(substr_space); + std::vector values = split(parsed_blocks, " "); + size_t j = 0; + for (std::string val : values) { + data[j++] = val != "??" ? strtol(val.c_str(), NULL, 16) : 0xFF; + } + bool success = false; + if (type == 0) { + success = attacks->write_sector(i++, data, 0, key); + } else { + success = attacks->write_ntag(i++, data); + } + if (success) { + set_wrote_sectors(++wrote_sectors); + } else { + set_unwritable_sectors(++unwritable_sectors); + } + } + } +} \ No newline at end of file diff --git a/lib/nfc_attacks/flipper_zero_nfc_file_parser.hpp b/lib/nfc_attacks/flipper_zero_nfc_file_parser.hpp new file mode 100644 index 0000000..f966a49 --- /dev/null +++ b/lib/nfc_attacks/flipper_zero_nfc_file_parser.hpp @@ -0,0 +1,21 @@ +/* + * This file is part of the Capibara zero (https://github.com/CapibaraZero/fw or + * https://capibarazero.github.io/). Copyright (c) 2024 Andrea Canale. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "nfc_attacks.hpp" +#include + +void flipper_zero_nfc_parser(std::string file, NFCAttacks *attacks); \ No newline at end of file diff --git a/lib/nfc_attacks/nfc_attacks.cpp b/lib/nfc_attacks/nfc_attacks.cpp index c94a720..ea07c5f 100644 --- a/lib/nfc_attacks/nfc_attacks.cpp +++ b/lib/nfc_attacks/nfc_attacks.cpp @@ -340,6 +340,18 @@ uint8_t NFCAttacks::write_ntag(NFCTag *tag) { return unwritable; } +bool NFCAttacks::write_ntag(uint8_t page, uint8_t *data) { + uint8_t uid[7]; + uint8_t uid_length; + bool success = false; + + if (nfc_framework.get_tag_uid(uid, uid_length)) { + success = nfc_framework.write_ntag2xx_page(page, data); + } + + return success; +} + uint8_t NFCAttacks::format_ntag(int pages) { LOG_INFO("Formatting ntag..."); uint8_t empty_tag_data[pages * NTAG_PAGE_SIZE] = {0}; diff --git a/lib/nfc_attacks/nfc_attacks.hpp b/lib/nfc_attacks/nfc_attacks.hpp index d012c02..69ba727 100644 --- a/lib/nfc_attacks/nfc_attacks.hpp +++ b/lib/nfc_attacks/nfc_attacks.hpp @@ -59,6 +59,7 @@ class NFCAttacks { bool write_sector(uint8_t block_number, uint8_t *data, uint8_t key_type, uint8_t *key); uint8_t write_ntag(NFCTag *tag); + bool write_ntag(uint8_t page, uint8_t *data); uint8_t format_ntag(int pages); void format_tag(); bool detect_felica(uint8_t *idm, uint8_t *pmm, uint16_t *sys_code); diff --git a/lib/nfc_attacks/nfc_tasks.cpp b/lib/nfc_attacks/nfc_tasks.cpp index 60d8694..70a71dc 100644 --- a/lib/nfc_attacks/nfc_tasks.cpp +++ b/lib/nfc_attacks/nfc_tasks.cpp @@ -216,14 +216,19 @@ void write_nfc_sectors(void *pv) { key[i++] = key_byte; } - uint8_t data[16]; + uint8_t data[type == "0" ? 16 : 4]; i = 0; for (uint8_t data_byte : block.value()["data"].as()) { data[i++] = data_byte; } - if (params->attacks->write_sector(block_key, data, block_value_key_type, - key)) { + bool success = false; + if (type == "0") { + success = params->attacks->write_sector(i++, data, 0, key); + } else { + success = params->attacks->write_ntag(i++, data); + } + if (success) { set_wrote_sectors(++wrote_sectors); } else { set_unwritable_sectors(++unwritable_sectors); @@ -233,6 +238,7 @@ void write_nfc_sectors(void *pv) { } else { flipper_zero_nfc_parser(std::string(nfc_dump.readString().c_str()), params->attacks); } + delay(6000); goto_home_nfc(params); free(pv); vTaskDelete(NULL);