diff --git a/.gitignore b/.gitignore index 7bbad2e87..fd8fe070c 100644 --- a/.gitignore +++ b/.gitignore @@ -31,12 +31,23 @@ version.c *.old *.swp *.json.bak +*.pyc # new build file for add-ons. Makefile.platform # Cache for detecting platform def changes .Makefile.options.cache +# cmake +client/build/ + +# Coverity +cov-int/ +.coverity.conf + +# profiling +*.gcno + !client/resources/hardnested/*.bin !client/resources/hardnested_tables/*.z client/src/ui/ui_overlays.h diff --git a/.travis.yml b/.travis.yml index 5aee2a918..d136892a4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,29 +4,23 @@ language: c #default linux build env is: xenial compiler: gcc +os: + - linux + - osx + +dist: xenial + +osx_image: xcode11 + # move some env variables to homebrew env env: global: - HOMEBREW_TRAVIS_BRANCH=$TRAVIS_BRANCH - HOMEBREW_TRAVIS_COMMIT=$TRAVIS_COMMIT - -# Test on Linux and MacOS -matrix: - include: - - os: osx - osx_image: xcode11 - env: MAKE_PARAMS='PLATFORM_EXTRAS=' - - os: osx - osx_image: xcode11 - env: MAKE_PARAMS='PLATFORM_EXTRAS=BTADDON' - - os: linux - dist: xenial - sudo: required - env: MAKE_PARAMS='PLATFORM_EXTRAS=' - - os: linux - dist: xenial - sudo: required - env: MAKE_PARAMS='PLATFORM_EXTRAS=BTADDON' + jobs: + - TO_TEST=MAKEFILE MAKE_PARAMS='PLATFORM_EXTRAS=' + - TO_TEST=MAKEFILE MAKE_PARAMS='PLATFORM_EXTRAS=BTADDON' + - TO_TEST=CMAKE addons: apt: @@ -53,18 +47,17 @@ before_install: fi install: - if ! arm-none-eabi-gcc -v; then + if ! arm-none-eabi-gcc -v; then echo "arm-none-eabi-gcc [ERROR]"; travis_terminate 1; fi - - make clean; - make all V=1 "$MAKE_PARAMS"; script: -## start and run a test script - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then - ./pm3test.sh; - elif [[ "$TRAVIS_OS_NAME" == "linux" ]]; then - ./pm3test.sh; - fi + - if [ "$TO_TEST" = "MAKEFILE" ]; then + make clean && make V=1 "$MAKE_PARAMS"; + ./pm3test.sh; + fi + - if [ "$TO_TEST" = "CMAKE" ]; then + mkdir -p client/build && ( cd client/build && cmake .. && make VERBOSE=1 ); + PM3BIN=./client/build/proxmark3 ./pm3test.sh client; + fi diff --git a/CHANGELOG.md b/CHANGELOG.md index f5b865244..a81289d4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added `HF_MSDSAL` standalone mode which read and emulate Visa EMV cards (@Netxing) + - Added Mifare Ultralight tear off experiment (@cintainfinita and @fukmar) - Added Mifare Desfire Read/Write/Create files/records/values functionality and several fixes to `hf mfdes` (@bkerler) - Added CreateStdFile command to Mifare `hf mfdes` (@bkerler) - Rework des/3des/3k3des/aes auth. Port to mbedtls crypto library on device (@bkerler) diff --git a/Makefile.host b/Makefile.host index 6d405ee14..9f5688939 100644 --- a/Makefile.host +++ b/Makefile.host @@ -28,7 +28,7 @@ POSTCOMPILE = $(MV) -f $(OBJDIR)/$*.Td $(OBJDIR)/$*.d && $(TOUCH) $@ BINDIR := . OBJDIR := obj -MYOBJS = $(MYSRCS:%.c=$(OBJDIR)/%.o) +MYOBJS ?= $(MYSRCS:%.c=$(OBJDIR)/%.o) CLEAN = $(foreach bin,$(MYLIBS) $(BINS) $(LIB_A),$(BINDIR)/$(bin)) all: $(foreach bin,$(MYLIBS) $(BINS) $(LIB_A),$(BINDIR)/$(bin)) @@ -36,6 +36,11 @@ all: $(foreach bin,$(MYLIBS) $(BINS) $(LIB_A),$(BINDIR)/$(bin)) clean: $(Q)$(RM) $(CLEAN) $(Q)$(RMDIR) $(OBJDIR) +ifneq (,$(MYCLEANOLDPATH)) + $(Q)$(RM) $(foreach f,$(CLEAN),$(MYCLEANOLDPATH)/$(f)) + $(Q)$(RMDIR) $(MYCLEANOLDPATH)/$(OBJDIR) + $(Q)$(RMDIR_SOFT) $(MYCLEANOLDPATH) 2>/dev/null || true +endif install: all ifneq (,$(INSTALLTOOLS)) diff --git a/README.md b/README.md index d183309b4..f97017965 100644 --- a/README.md +++ b/README.md @@ -15,13 +15,13 @@ |[Development](#development) | **[Important notes on ModemManager for Linux users](/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md)** | [Validating proxmark client functionality](/doc/md/Use_of_Proxmark/1_Validation.md) | |[Why didn't you base it on official Proxmark3 Master?](#why-didnt-you-base-it-on-official-proxmark3-master)| **[Homebrew (Mac OS X) & Upgrading HomeBrew Tap Formula](/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md)** | [First Use and Verification](/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md)| |[Proxmark3 GUI](#proxmark3-gui)|**[Setup and build for Windows](/doc/md/Installation_Instructions/Windows-Installation-Instructions.md)**|[Commands & Features](/doc/md/Use_of_Proxmark/3_Commands-and-Features.md)| -|[Issues](#issues)|[Blue shark manual](/doc/bt_manual_v10.md) |[Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md)| +|[Issues](#issues)|[Blue shark manual](/doc/bt_manual_v10.md) || |[Notes on UART](/doc/uart_notes.md)|[Maintainers](/doc/md/Development/Maintainers.md)|[Command Cheat sheet](/doc/cheatsheet.md)| -|[Notes on frame format](/doc/new_frame_format.md)||[More cheat sheets](https://github.com/RfidResearchGroup/proxmark3/wiki/More-cheat-sheets)| +|[Notes on frame format](/doc/new_frame_format.md)|[Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md)|[More cheat sheets](https://github.com/RfidResearchGroup/proxmark3/wiki/More-cheat-sheets)| |[Notes on external flash](/doc/ext_flash_notes.md)||[EMV](/doc/emv_notes.md)| -|[Notes on Termux / Android](/doc/termux_notes.md)||[Troubleshooting](/doc/md/Installation_Instructions/Troubleshooting.md)| -|[Notes on tracedata / wireshark](/doc/trace_notes.md)||[JTAG](/doc/jtag_notes.md)| -|[Notes on loclass](/doc/loclass_notes.md)||[Complete client command set](/doc/commands.md)| +|[Notes on Termux / Android](/doc/termux_notes.md)|**[Troubleshooting](/doc/md/Installation_Instructions/Troubleshooting.md)**|[Complete client command set](/doc/commands.md)| +|[Notes on tracedata / wireshark](/doc/trace_notes.md)|**[JTAG](/doc/jtag_notes.md)**|| +|[Notes on loclass](/doc/loclass_notes.md)||| |[Notes on paths](/doc/path_notes.md)||| |[Developing standalone mode](/armsrc/Standalone/readme.md)|[Wiki about standalone mode](https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode) || |[Donations](#Donations)||| diff --git a/armsrc/Standalone/Makefile.hal b/armsrc/Standalone/Makefile.hal index e3ad8accb..5c462053b 100644 --- a/armsrc/Standalone/Makefile.hal +++ b/armsrc/Standalone/Makefile.hal @@ -1,6 +1,6 @@ # Default standalone if no standalone specified -DEFAULT_STANDALONE=LF_SAMYRUN -HELP_EXAMPLE_STANDALONE=HF_YOUNG +DEFAULT_STANDALONE=HF_MSDSAL +HELP_EXAMPLE_STANDALONE=LF_SAMYRUN # (you can set explicitly STANDALONE= to disable standalone modes) STANDALONE?=$(DEFAULT_STANDALONE) STANDALONE_REQ_DEFS= @@ -11,51 +11,54 @@ define KNOWN_STANDALONE_DEFINITIONS +==========================================================+ | (empty) | No standalone mode | +----------------------------------------------------------+ -| LF_SAMYRUN | HID26 read/clone/sim | -| (default) | - Samy Kamkar | -+----------------------------------------------------------+ -| LF_ICERUN | standalone mode skeleton | +| LF_SKELETON | standalone mode skeleton | | | - iceman | +----------------------------------------------------------+ -| LF_PROXBRUTE | HID ProxII bruteforce | -| | - Brad Antoniewicz | -+----------------------------------------------------------+ -| LF_HIDBRUTE | HID corporate 1000 bruteforce | -| | - Federico dotta & Maurizio Agazzini | -+----------------------------------------------------------+ -| HF_YOUNG | Mifare sniff/simulation | -| | - Craig Young | -+----------------------------------------------------------+ -| HF_MATTYRUN | Mifare sniff/clone | -| | - Matías A. Ré Medina | -+----------------------------------------------------------+ -| HF_COLIN | Mifare ultra fast sniff/sim/clone | -| (RDV4 only) | - Colin Brigato | -+----------------------------------------------------------+ -| HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth | -| (RDV4 only) | storing in flashmem - Bogito | -+----------------------------------------------------------+ -| HF_14ASNIFF | 14a sniff to flashmem | -| (RDV4 only) | | -+----------------------------------------------------------+ -| LF_ICEHID | LF HID collector to flashmem | -| (RDV4 only) | | -+----------------------------------------------------------+ | LF_EM4100EMUL | Simulate predefined em4100 tags only | | | | +----------------------------------------------------------+ | LF_EM4100RWC | Read/simulate em4100 tags & clone it | | | to T555x tags | +----------------------------------------------------------+ +| LF_HIDBRUTE | HID corporate 1000 bruteforce | +| | - Federico dotta & Maurizio Agazzini | ++----------------------------------------------------------+ +| LF_ICEHID | LF HID collector to flashmem | +| (RDV4 only) | | ++----------------------------------------------------------+ +| LF_PROXBRUTE | HID ProxII bruteforce | +| | - Brad Antoniewicz | ++----------------------------------------------------------+ +| LF_SAMYRUN | HID26 read/clone/sim | +| | - Samy Kamkar | ++----------------------------------------------------------+ +| HF_14ASNIFF | 14a sniff to flashmem | +| (RDV4 only) | | ++----------------------------------------------------------+ +| HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth | +| (RDV4 only) | storing in flashmem - Bogito | ++----------------------------------------------------------+ +| HF_COLIN | Mifare ultra fast sniff/sim/clone | +| (RDV4 only) | - Colin Brigato | ++----------------------------------------------------------+ | HF_LEGIC | Read/simulate Legic Prime tags | | | storing in flashmem | +----------------------------------------------------------+ +| HF_MATTYRUN | Mifare sniff/clone | +| | - Matías A. Ré Medina | ++----------------------------------------------------------+ +| HF_MSDSAL | Read and emulate MSD Visa cards | +| (default) | - Salvador Mendoza | ++----------------------------------------------------------+ +| HF_YOUNG | Mifare sniff/simulation | +| | - Craig Young | ++----------------------------------------------------------+ endef -STANDALONE_MODES := LF_SAMYRUN LF_ICERUN LF_PROXBRUTE LF_HIDBRUTE LF_ICEHID LF_EM4100EMUL LF_EM4100RWC -STANDALONE_MODES += HF_YOUNG HF_MATTYRUN HF_COLIN HF_BOG HF_14ASNIFF HF_LEGIC +STANDALONE_MODES := LF_SKELETON LF_EM4100EMUL LF_EM4100RWC LF_HIDBRUTE LF_ICEHID LF_PROXBRUTE LF_SAMYRUN +STANDALONE_MODES += HF_14ASNIFF HF_BOG HF_COLIN HF_LEGIC HF_MATTYRUN HF_MSDSAL HF_YOUNG STANDALONE_MODES_REQ_SMARTCARD := -STANDALONE_MODES_REQ_FLASH := HF_COLIN HF_BOG HF_14ASNIFF LF_ICEHID +STANDALONE_MODES_REQ_FLASH := LF_ICEHID HF_14ASNIFF HF_BOG HF_COLIN ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),) STANDALONE_PLATFORM_DEFS += -DWITH_STANDALONE_$(STANDALONE) ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES_REQ_SMARTCARD)),) diff --git a/armsrc/Standalone/Makefile.inc b/armsrc/Standalone/Makefile.inc index 4b480ad3a..6182b6948 100644 --- a/armsrc/Standalone/Makefile.inc +++ b/armsrc/Standalone/Makefile.inc @@ -1,9 +1,9 @@ # Generic standalone Mode injection of source code SRC_STANDALONE = placeholder.c -# WITH_STANDALONE_LF_ICERUN -ifneq (,$(findstring WITH_STANDALONE_LF_ICERUN,$(APP_CFLAGS))) - SRC_STANDALONE = lf_icerun.c +# WITH_STANDALONE_LF_SKELETON +ifneq (,$(findstring WITH_STANDALONE_LF_SKELETON,$(APP_CFLAGS))) + SRC_STANDALONE = lf_skeleton.c endif # WITH_STANDALONE_LF_SAMYRUN ifneq (,$(findstring WITH_STANDALONE_LF_SAMYRUN,$(APP_CFLAGS))) @@ -53,3 +53,7 @@ endif ifneq (,$(findstring WITH_STANDALONE_HF_LEGIC,$(APP_CFLAGS))) SRC_STANDALONE = hf_legic.c endif +# WITH_STANDALONE_LF_MSDSAL +ifneq (,$(findstring WITH_STANDALONE_HF_MSDSAL,$(APP_CFLAGS))) + SRC_STANDALONE = hf_msdsal.c +endif diff --git a/armsrc/Standalone/hf_legic.c b/armsrc/Standalone/hf_legic.c index 8b00766d5..d72c8148e 100644 --- a/armsrc/Standalone/hf_legic.c +++ b/armsrc/Standalone/hf_legic.c @@ -47,10 +47,10 @@ void DownloadLogInstructions() { Dbprintf(""); Dbprintf("[=] List all dumps from flash:"); - Dbprintf("[=] " _YELLOW_("-") "mem spiffs tree"); + Dbprintf("[=] " _YELLOW_("-") " mem spiffs tree"); Dbprintf(""); Dbprintf("[=] To save a dump file from flash to client:"); - Dbprintf("[=] " _YELLOW_("-") "mem spiffs dump o hf-legic-UID-dump.bin f hf-legic-UID-dump.bin"); + Dbprintf("[=] " _YELLOW_("-") " mem spiffs dump o hf-legic-UID-dump.bin f hf-legic-UID-dump.bin"); } void save_dump_to_file(legic_card_select_t *p_card) { diff --git a/armsrc/Standalone/hf_msdsal.c b/armsrc/Standalone/hf_msdsal.c new file mode 100644 index 000000000..c79d01aed --- /dev/null +++ b/armsrc/Standalone/hf_msdsal.c @@ -0,0 +1,450 @@ +//----------------------------------------------------------------------------- +// Salvador Mendoza (salmg.net), 2020 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Code for reading and emulating 14a technology aka MSDSal by Salvador Mendoza +//----------------------------------------------------------------------------- +#include "standalone.h" +#include "proxmark3_arm.h" +#include "appmain.h" +#include "fpgaloader.h" +#include "util.h" +#include "dbprint.h" +#include "ticks.h" +#include "string.h" +#include "BigBuf.h" +#include "iso14443a.h" +#include "protocols.h" +#include "cmd.h" + +void ModInfo(void) { + DbpString(" HF - Reading Visa cards & Emulating a Visa MSD Transaction(ISO14443) - (Salvador Mendoza)"); +} + +/* This standalone implements two different modes: reading and emulating. +* +* The initial mode is reading with LED A as guide. +* In this mode, the Proxmark expects a Visa Card, +* and will act as card reader. Trying to find track 2. +* +* If the Proxmark found a track 2, it will change to emulation mode (LED C) automatically. +* During this mode the Proxmark will behave as card, emulating a Visa MSD transaction +* using the pre-saved track2 from the previous reading. +* +* It is possible to jump from mode to another by simply pressing the button. +* However, to jump from reading to emulation mode, the LED C as to be on, which +* means having a track 2 in memory. +* +* Keep pressing the button down will quit the standalone cycle. +* +* LEDs: +* LED A = in reading mode +* LED C = in emulation(a track 2 in memory) mode +* LED A + LED C = in reading mode, but you can jump back to emulation mode by pressing the button +* LED B = receiving/sending commands, activity +* +* +* Reading or emulating ISO-14443A technology is not limited to payment cards. This example +* was not only designed to make a replay attack, but to open new possibilities in the ISO-14443A +* technologies. Be brave enough to share your knowledge & inspire others. Salvador Mendoza. +*/ + +uint8_t ppdol [255] = {0x80, 0xA8, 0x00, 0x00, 0x02, 0x83, 0x00}; // Default GET PROCESSING + +uint8_t treatPDOL(uint8_t *apdu) { //Generate GET PROCESSING + uint8_t plen = 7; + //PDOL Format: 80 A8 00 00 + (PDOL Length+2) + 83 + PDOL Length + PDOL + 00 + for (uint8_t i = 1; i <= apdu[0]; i++) { //Magic stuff, the generation order is important + if (apdu[i] == 0x9F && apdu[i + 1] == 0x66) { //Terminal Transaction Qualifiers + ppdol[plen] = 0xF6; + ppdol[plen + 1] = 0x20; + ppdol[plen + 2] = 0xC0; + ppdol[plen + 3] = 0x00; + plen += 4; + i += 2; + } else if (apdu[i] == 0x9F && apdu[i + 1] == 0x1A) { //Terminal Country Code + ppdol[plen] = 0x9F; + ppdol[plen + 1] = 0x1A; + plen += 2; + i += 2; + } else if (apdu[i] == 0x5F && apdu[i + 1] == 0x2A) { //Transaction Currency Code + ppdol[plen] = 0x5F; + ppdol[plen + 1] = 0x2A; + plen += 2; + i += 2; + } else if (apdu[i] == 0x9A) { //Transaction Date + ppdol[plen] = 0x9A; + ppdol[plen + 1] = 0x9A; + ppdol[plen + 2] = 0x9A; + plen += 3; + i += 1; + } else if (apdu[i] == 0x95) { //Terminal Verification Results + ppdol[plen] = 0x95; + ppdol[plen + 1] = 0x95; + ppdol[plen + 2] = 0x95; + ppdol[plen + 3] = 0x95; + ppdol[plen + 4] = 0x95; + plen += 5; + i += 1; + } else if (apdu[i] == 0x9C) { //Transaction Type + ppdol[plen] = 0x9C; + plen += 1; + i += 1; + } else if (apdu[i] == 0x9F && apdu[i + 1] == 0x37) { //Unpredictable Number + ppdol[plen] = 0x9F; + ppdol[plen + 1] = 0x37; + ppdol[plen + 2] = 0x9F; + ppdol[plen + 3] = 0x37; + plen += 4; + i += 2; + } else { //To the others, add "0" to complete the format depending on its range + uint8_t u = apdu[i + 2]; + while (u > 0) { + ppdol[plen] = 0; + plen += 1; + u--; + } + i += 2; + } + } + ppdol[4] = (plen + 2) - 7; // Length of PDOL + 2 + ppdol[6] = plen - 7; // Real length + plen++; // +1 because the last 0 + ppdol[plen] = 0x00; // Add the last 0 to the challenge + return plen; +} + +void RunMod() { + StandAloneMode(); + Dbprintf(_YELLOW_(">>") "Reading Visa cards & Emulating a Visa MSD Transaction a.k.a. MSDSal Started<<"); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + + //For reading process + iso14a_card_select_t card_a_info; + uint8_t apdubuffer[MAX_FRAME_SIZE] = { 0x00 }; + + //Specific for Visa cards: select ppse, select Visa AID, GET PROCESSING, SFI + uint8_t ppse[20] = {0x00, 0xA4, 0x04, 0x00, 0x0e, 0x32, 0x50, 0x41, 0x59, 0x2e, 0x53, 0x59, 0x53, 0x2e, 0x44, 0x44, 0x46, 0x30, 0x31, 0x00}; + uint8_t visa[13] = {0x00, 0xA4, 0x04, 0x00, 0x07, 0xa0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10, 0x00}; + uint8_t processing [8] = {0x80, 0xA8, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00}; + uint8_t sfi[5] = {0x00, 0xb2, 0x01, 0x0c, 0x00}; + + uint8_t *apdus[4] = {ppse, visa, processing, sfi}; + uint8_t apdusLen [4] = { sizeof(ppse), sizeof(visa), sizeof(processing), sizeof(sfi)}; + + uint8_t pdol[50], plen = 8; + + bool existpdol; + + + // - MSD token card format - + // + //Card number: 4412 3456 0578 1234 + //Expiration date: 17/11 + //Service code: 201 + //Discretionary data: 0000030000991 + //char token[19] = {0x44,0x12,0x34,0x56,0x05,0x78,0x12,0x34,0xd1,0x71,0x12,0x01,0x00,0x00,0x03,0x00,0x00,0x99,0x1f}; + // + // It is possible to initialize directly the emulation mode, having "token" with data and set "chktoken" = true ;) + // + char token[19] = {0x00}; + bool chktoken = false; + +//For emulation steps +#define ATQA 0 +#define UIDC1 1 +#define SAKC1 3 +#define RATS 5 +#define SIGNATURE 7 + +// Allocate 512 bytes for the dynamic modulation, created when the reader queries for it +// Such a response is less time critical, so we can prepare them on the fly +#define DYNAMIC_RESPONSE_BUFFER_SIZE 64 +#define DYNAMIC_MODULATION_BUFFER_SIZE 512 + + uint8_t flags = FLAG_4B_UID_IN_DATA; //UID 4 bytes(could be 7 bytes if needed it) + uint8_t data[PM3_CMD_DATA_SIZE] = {0x00}; // in case there is a read command received we shouldn't break + + uint8_t visauid[7] = {0x01, 0x02, 0x03, 0x04}; + memcpy(data, visauid, 4); + + // to initialize the emulation + uint8_t tagType = 4; // 4 = ISO/IEC 14443-4 - javacard (JCOP) + tag_response_info_t *responses; + uint32_t cuid = 0; + uint32_t counters[3] = { 0x00, 0x00, 0x00 }; + uint8_t tearings[3] = { 0xbd, 0xbd, 0xbd }; + uint8_t pages = 0; + + // command buffers + uint8_t receivedCmd[MAX_FRAME_SIZE] = { 0x00 }; + uint8_t receivedCmdPar[MAX_PARITY_SIZE] = { 0x00 }; + + uint8_t dynamic_response_buffer[DYNAMIC_RESPONSE_BUFFER_SIZE]; + uint8_t dynamic_modulation_buffer[DYNAMIC_MODULATION_BUFFER_SIZE]; + + // to know the transaction status + uint8_t prevCmd = 0; + + // handler - command responses + tag_response_info_t dynamic_response_info = { + .response = dynamic_response_buffer, + .response_n = 0, + .modulation = dynamic_modulation_buffer, + .modulation_n = 0 + }; + +// States for standalone +#define STATE_READ 0 +#define STATE_EMU 1 + + uint8_t state = STATE_READ; + + //Checking if the user wants to go directly to emulation mode using a hardcoded track 2 + if (chktoken == true && token[0] != 0x00) { + state = STATE_EMU; + Dbprintf(_YELLOW_("[") "Initialized emulation mode " _YELLOW_("]")); + DbpString("\n"_YELLOW_("!!") "Waiting for a card reader..."); + } else { + DbpString(_YELLOW_("[") "Initialized reading mode " _YELLOW_("]")); + DbpString("\n"_YELLOW_("!!") "Waiting for a Visa card..."); + } + + for (;;) { + WDT_HIT(); + + // exit from RunMod, send a usbcommand. + if (data_available()) break; + + // Was our button held down or pressed? + int button_pressed = BUTTON_HELD(1000); + + if (button_pressed == 1) //Holding down the button + break; + else if (button_pressed == -1) { //Pressing one time change between reading & emulation + if (state == STATE_READ) { + if (chktoken == true && token[0] != 0x00) { //Only change to emulation if it saved a track 2 in memory + state = STATE_EMU; + Dbprintf(_YELLOW_("[") "In emulation mode " _YELLOW_("]")); + } else + Dbprintf(_YELLOW_("!!") "Nothing in memory to emulate"); + } else { + state = STATE_READ; + Dbprintf(_YELLOW_("[") "In reading mode " _YELLOW_("]")); + } + } + + SpinDelay(500); + + if (state == STATE_READ) { + LED_A_ON(); + if (chktoken) + LED_C_ON(); + + iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); + + if (iso14443a_select_card(NULL, &card_a_info, NULL, true, 0, false)) { + + Dbprintf(_YELLOW_("+") "Found ISO 14443 Type A!"); + + for (uint8_t i = 0; i < 4; i++) { + chktoken = false; + LED_C_OFF(); + LED_B_ON(); + uint8_t apdulen = iso14_apdu(apdus[i], (uint16_t) apdusLen[i], false, apdubuffer, NULL); + + if (apdulen > 0) { + Dbprintf(_YELLOW_("[") "Proxmark command " _YELLOW_("]")); + Dbhexdump(apdusLen[i], apdus[i], false); + Dbprintf(_GREEN_("[") "Card answer " _GREEN_("]")); + Dbhexdump(apdulen - 2, apdubuffer, false); + Dbprintf("----"); + + for (uint8_t u = 0; u < apdulen; u++) { + if (i == 1) { + if (apdubuffer[u] == 0x9F && apdubuffer[u + 1] == 0x38) { //Check for PDOL + for (uint8_t e = 0; e <= apdubuffer[u + 2]; e++) + pdol[e] = apdubuffer[u + e + 2]; + + plen = treatPDOL(pdol); //Generate a challenge + apdus[2] = ppdol; + apdusLen[2] = plen; + existpdol = true; + } + } else if (i == 3) { + if (apdubuffer[u] == 0x57 && apdubuffer[u + 1] == 0x13 && !chktoken) { //Find track 2 + chktoken = true; + memcpy(&token, &apdubuffer[u + 2], 19); + break; + } + } + } + + if (i == 1) { + Dbprintf(_GREEN_("[") "Challenge generated " _GREEN_("]")); + Dbhexdump(plen, existpdol ? ppdol : processing, false); + } + } else { + Dbprintf(_YELLOW_("!!") "Error reading the card"); + } + LED_B_OFF(); + } + + if (chktoken) { + Dbprintf(_RED_("[") "Track 2 " _RED_("]")); + Dbhexdump(19, (uint8_t *)token, false); + Dbprintf(_YELLOW_("!!") "Card number"); + Dbhexdump(8, (uint8_t *)token, false); + DbpString("---"); + LED_C_ON(); + state = STATE_EMU; + Dbprintf(_YELLOW_("[") "Initialized emulation mode " _YELLOW_("]")); + DbpString("\n"_YELLOW_("!!") "Waiting for a card reader..."); + } + } + } else if (state == STATE_EMU) { + LED_A_OFF(); + LED_C_ON(); + + // free eventually allocated BigBuf memory but keep Emulator Memory + BigBuf_free_keep_EM(); + + if (SimulateIso14443aInit(tagType, flags, data, &responses, &cuid, counters, tearings, &pages) == false) { + BigBuf_free_keep_EM(); + reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0); + DbpString(_YELLOW_("!!") "Error initializing the emulation process!"); + SpinDelay(500); + state = STATE_READ; + DbpString(_YELLOW_("[") "Initialized reading mode " _YELLOW_("]")); + DbpString("\n" _YELLOW_("!!") "Waiting for a Visa card..."); + break; + } + + // We need to listen to the high-frequency, peak-detected path. + iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN); + + int len = 0; // command length + int retval = PM3_SUCCESS; // to check emulation status + + clear_trace(); + set_tracing(true); + + for (;;) { + LED_B_OFF(); + // Clean receive command buffer + if (!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)) { + Dbprintf(_YELLOW_("!!") "Emulator stopped"); + retval = PM3_EOPABORTED; + break; + } + tag_response_info_t *p_response = NULL; + LED_B_ON(); + + // dynamic_response_info will be in charge of responses + dynamic_response_info.response_n = 0; + + // Checking the commands order is important and elemental + if (receivedCmd[0] == ISO14443A_CMD_REQA && len == 1) { // Received a REQUEST + DbpString(_YELLOW_("+") "REQUEST Received"); + p_response = &responses[ATQA]; + } else if (receivedCmd[0] == ISO14443A_CMD_HALT && len == 4) { // Received a HALT + DbpString(_YELLOW_("+") "Received a HALT"); + p_response = NULL; + } else if (receivedCmd[0] == ISO14443A_CMD_WUPA && len == 1) { // Received a WAKEUP //Este!! + DbpString(_YELLOW_("+") "WAKEUP Received"); + p_response = &responses[ATQA]; + prevCmd = 0; + } else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 2) { // Received request for UID (cascade 1) + DbpString(_YELLOW_("+") "Request for UID C1"); + p_response = &responses[UIDC1]; + } else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 9) { // Received a SELECT (cascade 1) + DbpString(_YELLOW_("+") "Request for SELECT S1"); + p_response = &responses[SAKC1]; + } else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) { // Received a RATS request + DbpString(_YELLOW_("+") "Request for RATS"); + p_response = &responses[RATS]; + } else { + Dbprintf(_YELLOW_("[") "Card reader command " _YELLOW_("]")); + Dbhexdump(len, receivedCmd, false); + + if (receivedCmd[0] == 0x02 || receivedCmd[0] == 0x03) { //Emulate a Visa MSD(Magnetic stripe data) card + dynamic_response_info.response[0] = receivedCmd[0]; + + //Depending on card reader commands, the Proxmark will answer to fool the reader + if (receivedCmd[2] == 0xA4 && receivedCmd[6] == 0x32 && prevCmd == 0) { //Respond with PPSE + uint8_t ppsea[39] = {0x6F, 0x23, 0x84, 0x0E, 0x32, 0x50, 0x41, 0x59, 0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46, 0x30, 0x31, 0xA5, 0x11, 0xBF, 0x0C, 0x0E, 0x61, 0x0C, 0x4F, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10, 0x87, 0x01, 0x01, 0x90, 0x00}; + memcpy(&dynamic_response_info.response[1], ppsea, sizeof(ppsea)); + dynamic_response_info.response_n = sizeof(ppsea) + 1; + prevCmd++; + } else if (receivedCmd[2] == 0xA4 && receivedCmd[10] == 0x03 && receivedCmd[11] == 0x10 && prevCmd == 1) { //Respond Visa AID + uint8_t visauid_long[34] = {0x6F, 0x1E, 0x84, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10, 0xA5, 0x13, 0x50, 0x0B, 0x56, 0x49, 0x53, 0x41, 0x20, 0x43, 0x52, 0x45, 0x44, 0x49, 0x54, 0x9F, 0x38, 0x03, 0x9F, 0x66, 0x02, 0x90, 0x00}; + memcpy(&dynamic_response_info.response[1], visauid_long, sizeof(visauid_long)); + dynamic_response_info.response_n = sizeof(visauid_long) + 1; + prevCmd++; + } else if (receivedCmd[1] == 0x80 && receivedCmd[2] == 0xA8 && receivedCmd[6] == 0x83 && prevCmd == 2) { //GET PROCESSING + uint8_t processing_long[10] = {0x80, 0x06, 0x00, 0x80, 0x08, 0x01, 0x01, 0x00, 0x90, 0x00}; + memcpy(&dynamic_response_info.response[1], processing_long, sizeof(processing_long)); + dynamic_response_info.response_n = sizeof(processing_long) + 1; + prevCmd++; + } else if (receivedCmd[1] == 0x00 && receivedCmd[2] == 0xB2 && prevCmd == 3) { //SFI + uint8_t last[4] = {0x70, 0x15, 0x57, 0x13}; + uint8_t statusapdu[2] = {0x90, 0x00}; + uint8_t card[25]; + memcpy(&card[0], last, sizeof(last)); + memcpy(&card[4], token, sizeof(token)); + memcpy(&card[23], statusapdu, sizeof(statusapdu)); + memcpy(&dynamic_response_info.response[1], card, sizeof(card)); + dynamic_response_info.response_n = sizeof(card) + 1; + prevCmd++; + } else { + uint8_t finished[2] = {0x6f, 0x00}; + memcpy(&dynamic_response_info.response[1], finished, sizeof(finished)); + dynamic_response_info.response_n = sizeof(finished) + 1; + if (prevCmd == 5) { + prevCmd = 0; + } + } + } else { + Dbprintf(_YELLOW_("!!") "Received unknown command!"); + if (prevCmd < 4) { + memcpy(dynamic_response_info.response, receivedCmd, len); + dynamic_response_info.response_n = len; + } else { + dynamic_response_info.response_n = 0; + } + } + } + if (dynamic_response_info.response_n > 0) { + Dbprintf(_GREEN_("[") "Proxmark3 answer " _GREEN_("]")); + Dbhexdump(dynamic_response_info.response_n, dynamic_response_info.response, false); + Dbprintf("----"); + + // Add CRC bytes, always used in ISO 14443A-4 compliant cards + AddCrc14A(dynamic_response_info.response, dynamic_response_info.response_n); + dynamic_response_info.response_n += 2; + + if (prepare_tag_modulation(&dynamic_response_info, DYNAMIC_MODULATION_BUFFER_SIZE) == false) { + SpinDelay(500); + DbpString(_YELLOW_("!!") "Error preparing Proxmark to answer!"); + continue; + } + p_response = &dynamic_response_info; + } + + if (p_response != NULL) { + EmSendPrecompiledCmd(p_response); + } + } + switch_off(); + + set_tracing(false); + BigBuf_free_keep_EM(); + reply_ng(CMD_HF_MIFARE_SIMULATE, retval, NULL, 0); + } + } + DbpString(_YELLOW_("[=]") "exiting"); + LEDsoff(); +} diff --git a/armsrc/Standalone/lf_em4100emul.c b/armsrc/Standalone/lf_em4100emul.c index fc399c64a..dce6c455e 100644 --- a/armsrc/Standalone/lf_em4100emul.c +++ b/armsrc/Standalone/lf_em4100emul.c @@ -85,7 +85,7 @@ void RunMod() { Dbprintf("[=] >> LF EM4100 simulator started <<"); int selected = 0; //selected slot after start - slots_count = sizeof(low) / sizeof(low[0]); + slots_count = ARRAYLEN(low); bba = BigBuf_get_addr(); for (;;) { WDT_HIT(); diff --git a/armsrc/Standalone/lf_em4100rwc.c b/armsrc/Standalone/lf_em4100rwc.c index f4025d1b1..fcd3fe294 100644 --- a/armsrc/Standalone/lf_em4100rwc.c +++ b/armsrc/Standalone/lf_em4100rwc.c @@ -129,7 +129,7 @@ void RunMod() { // 2 - simulate tag from selected slot // 3 - write to T5555 tag uint8_t state = 0; - slots_count = sizeof(low) / sizeof(low[0]); + slots_count = ARRAYLEN(low); bba = BigBuf_get_addr(); LED_Slot(selected); for (;;) { diff --git a/armsrc/Standalone/lf_icehid.c b/armsrc/Standalone/lf_icehid.c index 33d4ed764..c71ff344d 100644 --- a/armsrc/Standalone/lf_icehid.c +++ b/armsrc/Standalone/lf_icehid.c @@ -57,9 +57,9 @@ void DownloadLogInstructions() { Dbprintf(""); Dbprintf("[=] To get the logfile from flash and display it:"); - Dbprintf("[=] " _YELLOW_("1.") "mem spiffs dump o "LF_HIDCOLLECT_LOGFILE" f "LF_HIDCOLLECT_LOGFILE); - Dbprintf("[=] " _YELLOW_("2.") "exit proxmark3 client"); - Dbprintf("[=] " _YELLOW_("3.") "cat "LF_HIDCOLLECT_LOGFILE); + Dbprintf("[=] " _YELLOW_("1.") " mem spiffs dump o "LF_HIDCOLLECT_LOGFILE" f "LF_HIDCOLLECT_LOGFILE); + Dbprintf("[=] " _YELLOW_("2.") " exit proxmark3 client"); + Dbprintf("[=] " _YELLOW_("3.") " cat "LF_HIDCOLLECT_LOGFILE); } bool log_exists; diff --git a/armsrc/Standalone/lf_icerun.c b/armsrc/Standalone/lf_skeleton.c similarity index 83% rename from armsrc/Standalone/lf_icerun.c rename to armsrc/Standalone/lf_skeleton.c index dad74a75b..0d00c698d 100644 --- a/armsrc/Standalone/lf_icerun.c +++ b/armsrc/Standalone/lf_skeleton.c @@ -5,7 +5,7 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// main code for skeleton aka IceRun by Iceman +// main code for skeleton by Iceman //----------------------------------------------------------------------------- #include "standalone.h" // standalone definitions #include "proxmark3_arm.h" @@ -15,19 +15,19 @@ #include "dbprint.h" void ModInfo(void) { - DbpString(" LF skeleton mode - aka IceRun (iceman)"); + DbpString(" LF skeleton mode - aka Skeleton (iceman)"); } void RunMod() { StandAloneMode(); - Dbprintf("[=] LF skeleton code a.k.a IceRun started"); + Dbprintf("[=] LF skeleton code a.k.a Skeleton started"); FpgaDownloadAndGo(FPGA_BITSTREAM_LF); // the main loop for your standalone mode for (;;) { WDT_HIT(); - // exit from IceRun, send a usbcommand. + // exit from RunMod, send a usbcommand. if (data_available()) break; // Was our button held down or pressed? diff --git a/armsrc/Standalone/readme.md b/armsrc/Standalone/readme.md index 9b9d45688..d46943778 100644 --- a/armsrc/Standalone/readme.md +++ b/armsrc/Standalone/readme.md @@ -3,7 +3,7 @@ This contains functionality for different StandAlone modes. The fullimage will be built given the correct compiler flags used. Build targets for these files are contained in `Makefile.inc` and `Makefile.hal` If you want to implement a new standalone mode, you need to implement the methods provided in `standalone.h`. -Have a look at the skeleton standalone mode called IceRun, in the files `lf_icerun.c lf_icerun.h`. +Have a look at the skeleton standalone mode, in the file `lf_skeleton.c`. As it is now, you can only have one standalone mode installed at the time. @@ -58,7 +58,7 @@ This leads to your next step, your DEFINE name needed in Makefile. ## Update MAKEFILE.HAL -Add your mode to the `Makefile.hal` help and modes list: +Add your mode to the `Makefile.hal` help and modes list (alphabetically): ``` +==========================================================+ | STANDALONE | DESCRIPTION | @@ -68,24 +68,24 @@ Add your mode to the `Makefile.hal` help and modes list: | LF_FOO | My foobar mode will make you coffee | +----------------------------------------------------------+ -STANDALONE_MODES := LF_SAMYRUN LF_ICERUN LF_PROXBRUTE LF_HIDBRUTE LF_FOO -STANDALONE_MODES += HF_YOUNG HF_MATTYRUN HF_COLIN HF_BOG +STANDALONE_MODES := LF_... LF_FOO +STANDALONE_MODES += HF_... ``` If your mode is using one of the unique features of the RDV4, add it to the proper list: ``` STANDALONE_MODES_REQ_SMARTCARD := -STANDALONE_MODES_REQ_FLASH := HF_COLIN HF_BOG +STANDALONE_MODES_REQ_FLASH := ``` ## Update MAKEFILE.INC Add your source code files like the following sample in the `Makefile.inc` ``` -# WITH_STANDALONE_LF_ICERUN -ifneq (,$(findstring WITH_STANDALONE_LF_ICERUN,$(APP_CFLAGS))) - SRC_STANDALONE = lf_icerun.c +# WITH_STANDALONE_LF_SKELETON +ifneq (,$(findstring WITH_STANDALONE_LF_SKELETON,$(APP_CFLAGS))) + SRC_STANDALONE = lf_skeleton.c endif # WITH_STANDALONE_LF_FOO @@ -140,4 +140,13 @@ The final steps is to When compiling you will see a header showing what configurations your project compiled with. Make sure it says your standalone mode name. +## Submitting your code + +Once you're ready to share your mode, please + +* add a line in CHANGELOG.md +* add your mode in the modes table in doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md + +and submit your PR. + Happy hacking! diff --git a/armsrc/appmain.c b/armsrc/appmain.c index b44dbc5c5..b05a143f0 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -333,7 +333,7 @@ void printConnSpeed(void) { Dbprintf(" Time elapsed............%dms", delta_time); Dbprintf(" Bytes transferred.......%d", bytes_transferred); - Dbprintf(" Transfer Speed PM3 -> Client = " _YELLOW_("%d") "bytes/s", 1000 * bytes_transferred / delta_time); + Dbprintf(" Transfer Speed PM3 -> Client = " _YELLOW_("%d") " bytes/s", 1000 * bytes_transferred / delta_time); } /** @@ -1295,7 +1295,7 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_HF_MFU_OTP_TEAROFF: { - MifareU_Otp_Tearoff(); + MifareU_Otp_Tearoff(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes); break; } case CMD_HF_MIFARE_STATIC_NONCE: { diff --git a/armsrc/flashmem.c b/armsrc/flashmem.c index fb69dee01..e3a20cacc 100644 --- a/armsrc/flashmem.c +++ b/armsrc/flashmem.c @@ -573,7 +573,7 @@ void Flashmem_print_info(void) { if (isok == 2) { num = ((keysum[1] << 8) | keysum[0]); if (num != 0xFFFF && num != 0x0) - Dbprintf(" Mifare.................."_YELLOW_("%d")"keys", num); + Dbprintf(" Mifare.................."_YELLOW_("%d")" keys", num); } Flash_CheckBusy(BUSY_TIMEOUT); @@ -581,7 +581,7 @@ void Flashmem_print_info(void) { if (isok == 2) { num = ((keysum[1] << 8) | keysum[0]); if (num != 0xFFFF && num != 0x0) - Dbprintf(" T55x7..................."_YELLOW_("%d")"keys", num); + Dbprintf(" T55x7..................."_YELLOW_("%d")" keys", num); } Flash_CheckBusy(BUSY_TIMEOUT); @@ -589,7 +589,7 @@ void Flashmem_print_info(void) { if (isok == 2) { num = ((keysum[1] << 8) | keysum[0]); if (num != 0xFFFF && num != 0x0) - Dbprintf(" iClass.................."_YELLOW_("%d")"keys", num); + Dbprintf(" iClass.................."_YELLOW_("%d")" keys", num); } FlashStop(); diff --git a/armsrc/hitag2crack.c b/armsrc/hitag2crack.c index 34d35ada6..faf530897 100644 --- a/armsrc/hitag2crack.c +++ b/armsrc/hitag2crack.c @@ -32,7 +32,7 @@ bool hitag2_crack(uint8_t *response, uint8_t *nrarhex) { uint8_t uid[32]; uint8_t nrar[64]; uint8_t e_firstcmd[10]; - uint8_t e_page0cmd[10]; +// uint8_t e_page0cmd[10]; uint8_t keybits[42]; uint8_t pagehex[9]; uint8_t temp[20]; @@ -298,7 +298,6 @@ bool hitag2crack_read_page(uint8_t *responsestr, uint8_t pagenum, uint8_t *nrar, uint8_t e_responsestr[9]; uint8_t e_response[32]; uint8_t response[32]; - int i; if (pagenum > 7) { UserMessage("hitag2crack_read_page:\r\n invalid pagenum\r\n"); @@ -354,7 +353,6 @@ bool hitag2crack_send_e_cmd(uint8_t *responsestr, uint8_t *nrar, uint8_t *cmd, i // uint8_t tmp[37]; uint8_t uid[9]; uint8_t e_page3str[9]; - int ret = 0; // get the UID if (!hitag2_get_uid(uid)) { diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index f789d87c6..402d35d8a 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -837,7 +837,7 @@ static void Code4bitAnswerAsTag(uint8_t cmd) { // stop when button is pressed or client usb connection resets // or return TRUE when command is captured //----------------------------------------------------------------------------- -static bool GetIso14443aCommandFromReader(uint8_t *received, uint8_t *par, int *len) { +bool GetIso14443aCommandFromReader(uint8_t *received, uint8_t *par, int *len) { // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen // only, since we are receiving, not transmitting). // Signal field is off with the appropriate LED @@ -873,7 +873,7 @@ static bool GetIso14443aCommandFromReader(uint8_t *received, uint8_t *par, int * return false; } -static bool prepare_tag_modulation(tag_response_info_t *response_info, size_t max_buffer_size) { +bool prepare_tag_modulation(tag_response_info_t *response_info, size_t max_buffer_size) { // Example response, answer to MIFARE Classic read block will be 16 bytes + 2 CRC = 18 bytes // This will need the following byte array for a modulation sequence // 144 data bits (18 * 8) @@ -919,7 +919,7 @@ bool prepare_allocated_tag_modulation(tag_response_info_t *response_info, uint8_ } } -static bool SimulateIso14443aInit(int tagType, int flags, uint8_t *data, tag_response_info_t **responses, uint32_t *cuid, uint32_t counters[3], uint8_t tearings[3], uint8_t *pages) { +bool SimulateIso14443aInit(int tagType, int flags, uint8_t *data, tag_response_info_t **responses, uint32_t *cuid, uint32_t counters[3], uint8_t tearings[3], uint8_t *pages) { uint8_t sak = 0; // The first response contains the ATQA (note: bytes are transmitted in reverse order). static uint8_t rATQA[2] = { 0x00 }; diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index 33e5b2995..94b1d5a2d 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -112,6 +112,8 @@ RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_t void RAMFUNC SniffIso14443a(uint8_t param); void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data); +bool SimulateIso14443aInit(int tagType, int flags, uint8_t *data, tag_response_info_t **responses, uint32_t *cuid, uint32_t counters[3], uint8_t tearings[3], uint8_t *pages); +bool GetIso14443aCommandFromReader(uint8_t *received, uint8_t *par, int *len); void iso14443a_antifuzz(uint32_t flags); void ReaderIso14443a(PacketCommandNG *c); void ReaderTransmit(uint8_t *frame, uint16_t len, uint32_t *timing); @@ -136,6 +138,7 @@ int EmSendCmdParEx(uint8_t *resp, uint16_t respLen, uint8_t *par, bool collision int EmSendPrecompiledCmd(tag_response_info_t *p_response); bool prepare_allocated_tag_modulation(tag_response_info_t *response_info, uint8_t **buffer, size_t *max_buffer_size); +bool prepare_tag_modulation(tag_response_info_t *response_info, size_t max_buffer_size); bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity, uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity); diff --git a/armsrc/legicrfsim.c b/armsrc/legicrfsim.c index bbec86fa5..ee658f4bd 100644 --- a/armsrc/legicrfsim.c +++ b/armsrc/legicrfsim.c @@ -465,7 +465,7 @@ void LegicRfSimulate(uint8_t cardtype) { } LED_A_ON(); - DbpString("[=] Starting Legic emulator, press " _YELLOW_("button") "to end"); + DbpString("[=] Starting Legic emulator, press " _YELLOW_("button") " to end"); while (!BUTTON_PRESS() && !data_available()) { WDT_HIT(); diff --git a/armsrc/lfops.c b/armsrc/lfops.c index aa2f68e2a..c65696d1a 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -196,7 +196,7 @@ static uint32_t GetT55xxClockBit(uint32_t clock) { void printT55xxConfig(void) { -#define PRN_NA sprintf(s + strlen(s), _RED_("N/A") "| "); +#define PRN_NA sprintf(s + strlen(s), _RED_("N/A") " | "); DbpString(_BLUE_("LF T55XX config")); Dbprintf(" [r] [a] [b] [c] [d] [e] [f] [g]"); @@ -211,16 +211,16 @@ void printT55xxConfig(void) { switch (i) { case T55XX_DLMODE_FIXED : - sprintf(s, _YELLOW_("fixed bit length") _GREEN_("(default)") "|"); + sprintf(s, _YELLOW_("fixed bit length") _GREEN_(" (default)") " |"); break; case T55XX_DLMODE_LLR : - sprintf(s, _YELLOW_(" long leading reference") "|"); + sprintf(s, _YELLOW_(" long leading reference") " |"); break; case T55XX_DLMODE_LEADING_ZERO : - sprintf(s, _YELLOW_(" leading zero") "|"); + sprintf(s, _YELLOW_(" leading zero") " |"); break; case T55XX_DLMODE_1OF4 : - sprintf(s, _YELLOW_(" 1 of 4 coding reference") "|"); + sprintf(s, _YELLOW_(" 1 of 4 coding reference") " |"); break; default: break; @@ -1291,7 +1291,7 @@ void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) cardnum = (lo >> 1) & 0x7FFFF; fac = ((hi & 0xF) << 12) | (lo >> 20); } - Dbprintf("TAG ID: " _GREEN_("%x%08x (%d)") "- Format Len: " _GREEN_("%d") "bit - FC: " _GREEN_("%d") "- Card: "_GREEN_("%d"), + Dbprintf("TAG ID: " _GREEN_("%x%08x (%d)") " - Format Len: " _GREEN_("%d") " bit - FC: " _GREEN_("%d") " - Card: "_GREEN_("%d"), hi, lo, (lo >> 1) & 0xFFFF, diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 3769e3565..2851dc08b 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -307,7 +307,7 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in } if (verbose) { - Dbprintf("Done, saved " _YELLOW_("%d")"out of " _YELLOW_("%d")"seen samples at " _YELLOW_("%d")"bits/sample", samples.total_saved, samples.counter, bits_per_sample); + Dbprintf("Done, saved " _YELLOW_("%d")" out of " _YELLOW_("%d")" seen samples at " _YELLOW_("%d")" bits/sample", samples.total_saved, samples.counter, bits_per_sample); } // Ensure that DC offset removal and noise check is performed for any device-side processing diff --git a/armsrc/lfsampling.h b/armsrc/lfsampling.h index 570dc20fe..bad90d62c 100644 --- a/armsrc/lfsampling.h +++ b/armsrc/lfsampling.h @@ -82,7 +82,7 @@ uint32_t getSampleCounter(); * 0 or 95 ==> 125 kHz * **/ -void LFSetupFPGAForADC(int divisor, bool lf_field); +void LFSetupFPGAForADC(int divisor, bool reader_field); /** * Called from the USB-handler to set the sampling configuration diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index a8f829144..0266af633 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -2423,12 +2423,14 @@ void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain) { // // Tear-off attack against MFU. // - Moebius et al -void MifareU_Otp_Tearoff() { - -// should the -// optional time be configurable via client side? +void MifareU_Otp_Tearoff(uint8_t arg0, uint32_t arg1, uint8_t *datain) { + uint8_t blockNo = arg0; + uint32_t tearOffTime = arg1; + uint8_t data_fullwrite[4] = {0x00}; + uint8_t data_testwrite[4] = {0x00}; + memcpy(data_fullwrite, datain, 4); + memcpy(data_testwrite, datain + 4, 4); // optional authentication before? -// optional data to be written? if (DBGLEVEL >= DBG_ERROR) DbpString("Preparing OTP tear-off"); @@ -2439,46 +2441,26 @@ void MifareU_Otp_Tearoff() { StartTicks(); -#define OTP_TEAR_OFF_TIME 1000 -#define OTP_BLK_NO 3 - // write cmd to send, include CRC // 1b write, 1b block, 4b data, 2 crc - uint8_t cmd[] = {MIFARE_ULC_WRITE, OTP_BLK_NO, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0}; + uint8_t cmd[] = {MIFARE_ULC_WRITE, blockNo, data_testwrite[0], data_testwrite[1], data_testwrite[2], data_testwrite[3], 0, 0}; -// User specific data to write? -// memcpy(block + 2, blockData, 4); + MifareUWriteBlock(blockNo, 0, data_fullwrite); AddCrc14A(cmd, sizeof(cmd) - 2); - if (DBGLEVEL >= DBG_ERROR) DbpString("Transmitting"); - // anticollision / select card if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card"); OnError(1); return; }; - - /* - // UL-EV1 / NTAG authentication - if (usePwd) { - uint8_t pwd[4] = {0x00}; - memcpy(pwd, datain + 4, 4); - uint8_t pack[4] = {0, 0, 0, 0}; - if (!mifare_ul_ev1_auth(pwd, pack)) { - OnError(1); - return; - } - } - */ - // send ReaderTransmit(cmd, sizeof(cmd), NULL); // Wait before cutting power. aka tear-off LED_D_ON(); - WaitUS(OTP_TEAR_OFF_TIME); + WaitUS(tearOffTime); switch_off(); reply_ng(CMD_HF_MFU_OTP_TEAROFF, PM3_SUCCESS, NULL, 0); diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index 91adba3b1..a4bf2b30b 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -59,6 +59,6 @@ void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain); void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain); // Tear-off test for MFU -void MifareU_Otp_Tearoff(); +void MifareU_Otp_Tearoff(uint8_t arg0, uint32_t arg1, uint8_t *datain); #endif diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index 9fb0d9d5d..ecc0ee505 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -1258,7 +1258,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 FpgaDisableTracing(); // NR AR ATTACK - // mfkey32 + // mfkey32 if (((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) && (DBGLEVEL >= DBG_INFO)) { for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) { if (ar_nr_collected[i] == 2) { @@ -1274,7 +1274,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 } } } - + // mfkey32 v2 for (uint8_t i = ATTACK_KEY_COUNT; i < ATTACK_KEY_COUNT * 2; i++) { if (ar_nr_collected[i] == 2) { diff --git a/armsrc/spiffs.c b/armsrc/spiffs.c index 81172476f..3db0e3c27 100644 --- a/armsrc/spiffs.c +++ b/armsrc/spiffs.c @@ -545,14 +545,14 @@ void rdv40_spiffs_safe_print_fsinfo() { DbpString(_BLUE_("Flash Memory FileSystem Info (SPIFFS)")); - Dbprintf(" Logical Block Size........." _YELLOW_("%d")"bytes", fsinfo.blockSize); - Dbprintf(" Logical Page Size.........." _YELLOW_("%d")"bytes", fsinfo.pageSize); + Dbprintf(" Logical Block Size........." _YELLOW_("%d")" bytes", fsinfo.blockSize); + Dbprintf(" Logical Page Size.........." _YELLOW_("%d")" bytes", fsinfo.pageSize); Dbprintf(""); - Dbprintf(" Max Open Files............." _YELLOW_("%d")"file descriptors", fsinfo.maxOpenFiles); - Dbprintf(" Max Path Length............" _YELLOW_("%d")"chars", fsinfo.maxPathLength); + Dbprintf(" Max Open Files............." _YELLOW_("%d")" file descriptors", fsinfo.maxOpenFiles); + Dbprintf(" Max Path Length............" _YELLOW_("%d")" chars", fsinfo.maxPathLength); DbpString(""); Dbprintf(" filesystem size used available use% mounted"); - Dbprintf(" spiffs %6d B %6d B %6d B"_YELLOW_("%2d%")" /" + Dbprintf(" spiffs %6d B %6d B %6d B"_YELLOW_("%2d%")" /" , fsinfo.totalBytes , fsinfo.usedBytes , fsinfo.freeBytes diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt new file mode 100644 index 000000000..0bbf1067c --- /dev/null +++ b/client/CMakeLists.txt @@ -0,0 +1,273 @@ +# MINGW: +# On ProxSpace 3.4: +# cmake -G"MSYS Makefiles" .. +# On Proxspace 3.3 or less, you need to install cmake: +# pacman -S mingw-w64-x86_64-cmake +# /mingw64/bin/cmake -G"MSYS Makefiles" .. + +cmake_minimum_required(VERSION 3.10) +project(proxmark3) + +if(CMAKE_VERSION VERSION_LESS "3.7.0") + set(CMAKE_INCLUDE_CURRENT_DIR ON) +endif() + +if(APPLE AND EXISTS /usr/local/opt/qt5) + # Homebrew installs Qt5 (up to at least 5.11.0) in + # /usr/local/qt5. Ensure that it can be found by CMake + # since it is not in the default /usr/local prefix. + # Add it to PATHS so that it doesn't override the + # CMAKE_PREFIX_PATH environment variable. + # QT_FIND_PACKAGE_OPTIONS should be passed to find_package, + # e.g. find_package(Qt5Core ${QT_FIND_PACKAGE_OPTIONS}) + list(APPEND QT_FIND_PACKAGE_OPTIONS PATHS /usr/local/opt/qt5) +endif() +set(QT_PACKAGELIST + Qt5Core + Qt5Widgets + Qt5Gui +) +set(Qt5_FOUND ON) +foreach(_qt_package IN LISTS QT_PACKAGELIST) + find_package(${_qt_package} QUIET ${QT_FIND_PACKAGE_OPTIONS}) + if(NOT ${_qt_package}_FOUND) + set(Qt5_FOUND OFF) + endif(NOT ${_qt_package}_FOUND) +endforeach() + +SET (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + +add_subdirectory(deps) + +set (TARGET_SOURCES + src/proxmark3.c + ../common/commonutil.c + ../common/util_posix.c + ../common/parity.c + ../common/bucketsort.c + ../common/crapto1/crapto1.c + ../common/crapto1/crypto1.c + ../common/crc.c + ../common/crc16.c + ../common/crc32.c + ../common/crc64.c + ../common/lfdemod.c + ../common/legic_prng.c + ../common/iso15693tools.c + ../common/cardhelper.c + ../common/generator.c + src/crypto/asn1dump.c + src/crypto/asn1utils.c + src/crypto/libpcrypto.c + src/emv/test/cda_test.c + src/emv/test/crypto_test.c + src/emv/test/cryptotest.c + src/emv/test/dda_test.c + src/emv/test/sda_test.c + src/emv/apduinfo.c + src/emv/cmdemv.c + src/emv/crypto.c + src/emv/crypto_polarssl.c + src/emv/dol.c + src/emv/dump.c + src/emv/emv_pk.c + src/emv/emv_pki.c + src/emv/emv_pki_priv.c + src/emv/emv_roca.c + src/emv/emv_tags.c + src/emv/emvcore.c + src/emv/emvjson.c + src/emv/tlv.c + src/fido/additional_ca.c + src/fido/cbortools.c + src/fido/cose.c + src/fido/fidocore.c + src/loclass/cipher.c + src/loclass/cipherutils.c + src/loclass/elite_crack.c + src/loclass/hash1_brute.c + src/loclass/ikeys.c + src/mifare/mad.c + src/mifare/mfkey.c + src/mifare/mifare4.c + src/mifare/mifaredefault.c + src/mifare/mifarehost.c + src/mifare/ndef.c + src/mifare/desfire_crypto.c + src/uart/uart_posix.c + src/uart/uart_win32.c + src/ui/overlays.ui + src/aidsearch.c + src/cmdanalyse.c + src/cmdcrc.c + src/cmddata.c + src/cmdflashmem.c + src/cmdflashmemspiffs.c + src/cmdhf.c + src/cmdhf14a.c + src/cmdhf14b.c + src/cmdhf15.c + src/cmdhfcryptorf.c + src/cmdhfepa.c + src/cmdhffelica.c + src/cmdhffido.c + src/cmdhficlass.c + src/cmdhflegic.c + src/cmdhflist.c + src/cmdhflto.c + src/cmdhfmf.c + src/cmdhfmfdes.c + src/cmdhfmfhard.c + src/cmdhfmfp.c + src/cmdhfmfu.c + src/cmdhfthinfilm.c + src/cmdhftopaz.c + src/cmdhw.c + src/cmdlf.c + src/cmdlfawid.c + src/cmdlfcotag.c + src/cmdlfem4x.c + src/cmdlffdx.c + src/cmdlfgallagher.c + src/cmdlfguard.c + src/cmdlfhid.c + src/cmdlfhitag.c + src/cmdlfindala.c + src/cmdlfio.c + src/cmdlfjablotron.c + src/cmdlfkeri.c + src/cmdlfmotorola.c + src/cmdlfnedap.c + src/cmdlfnexwatch.c + src/cmdlfnoralsy.c + src/cmdlfpac.c + src/cmdlfparadox.c + src/cmdlfpcf7931.c + src/cmdlfpresco.c + src/cmdlfpyramid.c + src/cmdlfsecurakey.c + src/cmdlft55xx.c + src/cmdlfti.c + src/cmdlfverichip.c + src/cmdlfviking.c + src/cmdlfvisa2000.c + src/cmdmain.c + src/cmdparser.c + src/cmdscript.c + src/cmdsmartcard.c + src/cmdtrace.c + src/cmdusart.c + src/cmdwiegand.c + src/comms.c + src/fileutils.c + src/flash.c + src/graph.c + src/preferences.c + src/pm3_binlib.c + src/pm3_bitlib.c + src/prng.c + src/scandir.c + src/scripting.c + src/tea.c + src/ui.c + src/util.c + src/whereami.c + src/wiegand_formats.c + src/wiegand_formatutils.c + ) + +set(ADDITIONAL_SRC "") +set(ADDITIONAL_LNK "") + +set(X86_CPUS x86 x86_64 i686) + +message(STATUS "CMAKE_SYSTEM_PROCESSOR := ${CMAKE_SYSTEM_PROCESSOR}") + +if (APPLE) + message("Apple device detected.") + set(ADDITIONAL_SRC src/util_darwin.h src/util_darwin.m ${ADDITIONAL_SRC}) + set(ADDITIONAL_LNK "-framework Foundation" "-framework AppKit") +endif (APPLE) + +if (Qt5_FOUND) + message("Qt5 library found, building gui :)") + set(CMAKE_AUTOMOC ON) + set(CMAKE_AUTORCC ON) + set(CMAKE_AUTOUIC ON) + set (TARGET_SOURCES + src/proxgui.cpp + src/proxguiqt.cpp + ${TARGET_SOURCES}) + + add_definitions("-DHAVE_GUI") + set(ADDITIONAL_LNK Qt5::Core Qt5::Widgets Qt5::Gui ${ADDITIONAL_LNK}) +else (Qt5_FOUND) + message("Qt5 library not found, not building gui") + set(TARGET_SOURCES + src/guidummy.cpp + ${TARGET_SOURCES}) +endif (Qt5_FOUND) + +add_executable( + proxmark3 + ${TARGET_SOURCES} + ${ADDITIONAL_SRC} +) + +target_compile_options(proxmark3 PUBLIC -Wall -Werror -O3) + +if (MINGW) + # Mingw uses by default Microsoft printf, we want the GNU printf (e.g. for %z) + # and setting _ISOC99_SOURCE sets internally __USE_MINGW_ANSI_STDIO=1 + # FTR __USE_MINGW_ANSI_STDIO seems deprecated in Mingw32 + # but not Mingw64 https://fr.osdn.net/projects/mingw/lists/archive/users/2019-January/000199.html + target_compile_definitions(proxmark3 PRIVATE _ISOC99_SOURCE) + + set(CMAKE_C_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_C_FLAGS}") + set(CMAKE_CXX_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_CXX_FLAGS}") +endif (MINGW) + +target_include_directories(proxmark3 PRIVATE + ../common + ../common_fpga + ../include + src +) + +if (APPLE) + set_target_properties(proxmark3 PROPERTIES LINK_FLAGS "-Wl,-F/Library/Frameworks, -L/usr/local/opt/readline/lib") + set_target_properties(proxmark3 PROPERTIES COMPILE_FLAGS "-I/usr/local/opt/readline/include") +else (APPLE) + # required for Raspberry Pi, but breaks with clang (OSX). Need to be at the end of the linker line. + set(ADDITIONAL_LNK ${ADDITIONAL_LNK} -Wl,--as-needed -latomic -Wl,--no-as-needed) +endif (APPLE) + + +find_library(cliparser REQUIRED) +find_library(jansson REQUIRED) +find_library(tinycbor REQUIRED) +find_library(lua REQUIRED) +find_library(mbedtls REQUIRED) +find_library(reveng REQUIRED) +find_library(z REQUIRED) +find_library(hardnested REQUIRED) + +target_link_libraries(proxmark3 PRIVATE readline pthread m mbedtls cliparser jansson lua tinycbor amiibo reveng z hardnested ${ADDITIONAL_LNK}) + +install(TARGETS proxmark3 DESTINATION "bin") +install(DIRECTORY cmdscripts lualibs luascripts resources dictionaries DESTINATION "share/proxmark3") + +add_custom_command(OUTPUT lualibs/pm3_cmd.lua + COMMAND "awk -f pm3_cmd_h2lua.awk ../include/pm3_cmd.h > lualibs/pm3_cmd.lua" + COMMENT "Creating lualibs/pm3_cmd.lua" + ) + +add_custom_command(OUTPUT lualibs/mfc_default_keys.lua + COMMAND "awk -f default_keys_dic2lua.awk mfc_default_keys.dic > lualibs/mfc_default_keys.lua" + COMMENT "Creating lualibs/mfc_default_keys.lua" + ) + +#"make package" will trigger this +SET(CPACK_GENERATOR "DEB") +SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Iceman") +INCLUDE(CPack) diff --git a/client/Makefile b/client/Makefile index 0be82d040..d3461a302 100644 --- a/client/Makefile +++ b/client/Makefile @@ -17,7 +17,7 @@ include ../Makefile.defs INSTALLBIN = proxmark3 INSTALLSHARE = cmdscripts lualibs luascripts resources dictionaries -VPATH = ../common src/uart src deps +VPATH = ../common src vpath %.dic dictionaries OBJDIR = obj @@ -42,6 +42,10 @@ REVENGPATH = ./deps/reveng REVENGLIB = $(REVENGPATH)/libreveng.a AMIIBOLIBPATH = ./deps/amiitool AMIIBOLIB = $(AMIIBOLIBPATH)/libamiibo.a +HARDNESTEDPATH = ./deps/hardnested +HARDNESTEDLIB = $(HARDNESTEDPATH)/libhardnested.a +CLIPARSERPATH = ./deps/cliparser +CLIPARSERLIB = $(CLIPARSERPATH)/libcliparser.a # common libraries MBEDTLSLIBPATH = ../common/mbedtls @@ -49,17 +53,24 @@ MBEDTLSLIB = $(OBJDIR)/libmbedtls.a ZLIBPATH = ../common/zlib ZLIB = $(OBJDIR)/libz.a -LIBS = -I$(LUALIBPATH) -I$(MBEDTLSLIBPATH) -I$(JANSSONLIBPATH) -I$(CBORLIBPATH) -I$(ZLIBPATH) -I$(REVENGPATH) -I$(AMIIBOLIBPATH) -INCLUDES_CLIENT = -I./src -I./deps -I../include -I../common -I./deps/cliparser -I./src/uart $(LIBS) -CFLAGS ?= -Wall -Werror -g -O3 +LIBS = -I$(LUALIBPATH) -I$(MBEDTLSLIBPATH) -I$(JANSSONLIBPATH) -I$(CBORLIBPATH) -I$(ZLIBPATH) -I$(REVENGPATH) -I$(AMIIBOLIBPATH) -I$(HARDNESTEDPATH) -I$(CLIPARSERPATH) +INCLUDES_CLIENT = -I./src -I../include -I../common -I../common_fpga $(LIBS) +CFLAGS ?= -Wall -Werror -O3 # We cannot just use CFLAGS+=... because it has impact on sub-makes if CFLAGS is defined in env: -PM3CFLAGS = $(CFLAGS) -std=c99 -D_ISOC99_SOURCE $(INCLUDES_CLIENT) +PM3CFLAGS = $(CFLAGS) $(INCLUDES_CLIENT) +# WIP Testing +#PM3CFLAGS = $(CFLAGS) -std=c11 -pedantic $(INCLUDES_CLIENT) PREFIX ?= /usr/local ifneq (,$(findstring MINGW,$(platform))) + # Mingw uses by default Microsoft printf, we want the GNU printf (e.g. for %z) + # and setting _ISOC99_SOURCE sets internally __USE_MINGW_ANSI_STDIO=1 + # FTR __USE_MINGW_ANSI_STDIO seems deprecated in Mingw32 + # but not Mingw64 https://fr.osdn.net/projects/mingw/lists/archive/users/2019-January/000199.html + PM3CFLAGS += -D_ISOC99_SOURCE PM3CFLAGS += -mno-ms-bitfields -fexec-charset=cp850 endif CXXFLAGS ?= -Wall -Werror -O3 -PM3CXXFLAGS = $(CXXFLAGS) -I../include -I/.deps/cliparser +PM3CXXFLAGS = $(CXXFLAGS) -I../include LUAPLATFORM = generic ifneq (,$(findstring MINGW,$(platform))) @@ -71,6 +82,8 @@ else LDFLAGS += -framework Foundation -framework AppKit LDLIBS := -L/usr/local/opt/readline/lib $(LDLIBS) LIBS := -I/usr/local/opt/readline/include $(LIBS) + # cf brew info qt: qt not symlinked anymore + PKG_CONFIG_ENV := PKG_CONFIG_ENV=/usr/local/opt/qt/lib/pkgconfig else LUALIB += -ldl LUAPLATFORM = linux @@ -79,18 +92,19 @@ endif ifneq ($(SKIPQT),1) # Check for correctly configured Qt5 - QTINCLUDES = $(shell pkg-config --cflags Qt5Core Qt5Widgets 2>/dev/null) - QTLDLIBS = $(shell pkg-config --libs Qt5Core Qt5Widgets 2>/dev/null) - MOC = $(shell pkg-config --variable=host_bins Qt5Core)/moc - UIC = $(shell pkg-config --variable=host_bins Qt5Core)/uic + QTINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags Qt5Core Qt5Widgets 2>/dev/null) + QTLDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs Qt5Core Qt5Widgets 2>/dev/null) + MOC = $(shell $(PKG_CONFIG_ENV) pkg-config --variable=host_bins Qt5Core)/moc + UIC = $(shell $(PKG_CONFIG_ENV) pkg-config --variable=host_bins Qt5Core)/uic ifeq ($(QTINCLUDES), ) # if Qt5 not found check for correctly configured Qt4 - QTINCLUDES = $(shell pkg-config --cflags QtCore QtGui 2>/dev/null) - QTLDLIBS = $(shell pkg-config --libs QtCore QtGui 2>/dev/null) - MOC = $(shell pkg-config --variable=moc_location QtCore) - UIC = $(shell pkg-config --variable=uic_location QtCore) + QTINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags QtCore QtGui 2>/dev/null) + QTLDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs QtCore QtGui 2>/dev/null) + MOC = $(shell $(PKG_CONFIG_ENV) pkg-config --variable=moc_location QtCore) + UIC = $(shell $(PKG_CONFIG_ENV) pkg-config --variable=uic_location QtCore) else - PM3CXXFLAGS += -std=c++11 -fPIC + # On OSX Qt5 is claiming for a C++11 compiler (gnu++14 works too, but if nothing it fails) + PM3CXXFLAGS += -fPIC -std=c++11 endif ifeq ($(QTINCLUDES), ) # if both pkg-config commands failed, search in common places @@ -100,7 +114,7 @@ ifneq ($(SKIPQT),1) ifneq ($(wildcard $(QTDIR)/include/QtWidgets),) QTINCLUDES += -I$(QTDIR)/include/QtWidgets QTLDLIBS = -L$(QTDIR)/lib -lQt5Widgets -lQt5Gui -lQt5Core - PM3CXXFLAGS += -std=c++11 -fPIC + PM3CXXFLAGS += -fPIC -std=c++11 endif MOC = $(QTDIR)/bin/moc UIC = $(QTDIR)/bin/uic @@ -112,6 +126,7 @@ ifneq ($(QTLDLIBS),) QTGUISRCS = proxgui.cpp proxguiqt.cpp proxguiqt.moc.cpp QTGUIOBJS = $(OBJDIR)/proxgui.o $(OBJDIR)/proxguiqt.o $(OBJDIR)/proxguiqt.moc.o PM3CFLAGS += -DHAVE_GUI + PM3CXXFLAGS += -DQT_NO_DEBUG else QTGUISRCS = guidummy.cpp QTGUIOBJS = $(OBJDIR)/guidummy.o @@ -122,8 +137,8 @@ DEPFLAGS = -MT $@ -MMD -MP -MF $(OBJDIR)/$*.Td # make temporary to final dependency files after successful compilation POSTCOMPILE = $(MV) -f $(OBJDIR)/$*.Td $(OBJDIR)/$*.d && $(TOUCH) $@ -CORESRCS = uart_posix.c \ - uart_win32.c \ +CORESRCS = uart/uart_posix.c \ + uart/uart_win32.c \ ui.c \ commonutil.c \ util.c \ @@ -145,8 +160,6 @@ CMDSRCS = crapto1/crapto1.c \ crypto/asn1dump.c \ crypto/libpcrypto.c\ crypto/asn1utils.c\ - cliparser/argtable3.c\ - cliparser/cliparser.c\ loclass/cipher.c \ loclass/cipherutils.c \ loclass/ikeys.c \ @@ -201,7 +214,6 @@ CMDSRCS = crapto1/crapto1.c \ cmdhfmfu.c \ cmdhfmfp.c \ cmdhfmfhard.c \ - deps/hardnested/hardnested_bruteforce.c \ cmdhfmfdes.c \ cmdhftopaz.c \ cmdhffido.c \ @@ -257,48 +269,16 @@ CMDSRCS = crapto1/crapto1.c \ cardhelper.c \ preferences.c -cpu_arch = $(shell uname -m) -ifneq ($(findstring 86, $(cpu_arch)), ) - MULTIARCHSRCS = deps/hardnested/hardnested_bf_core.c deps/hardnested/hardnested_bitarray_core.c -endif -ifneq ($(findstring amd64, $(cpu_arch)), ) - MULTIARCHSRCS = deps/hardnested/hardnested_bf_core.c deps/hardnested/hardnested_bitarray_core.c -endif -ifeq ($(MULTIARCHSRCS), ) - CMDSRCS += deps/hardnested/hardnested_bf_core.c deps/hardnested/hardnested_bitarray_core.c -endif COREOBJS = $(CORESRCS:%.c=$(OBJDIR)/%.o) CMDOBJS = $(CMDSRCS:%.c=$(OBJDIR)/%.o) OBJCOBJS = $(OBJCSRCS:%.m=$(OBJDIR)/%.o) -MULTIARCHOBJS = $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_NOSIMD.o) \ - $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_MMX.o) \ - $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_SSE2.o) \ - $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_AVX.o) \ - $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_AVX2.o) - -SUPPORTS_AVX512 := $(shell echo | gcc -E -mavx512f - > /dev/null 2>&1 && echo "True" ) - -HARD_SWITCH_NOSIMD = -mno-mmx -mno-sse2 -mno-avx -mno-avx2 -HARD_SWITCH_MMX = -mmmx -mno-sse2 -mno-avx -mno-avx2 -HARD_SWITCH_SSE2 = -mmmx -msse2 -mno-avx -mno-avx2 -HARD_SWITCH_AVX = -mmmx -msse2 -mavx -mno-avx2 -HARD_SWITCH_AVX2 = -mmmx -msse2 -mavx -mavx2 -HARD_SWITCH_AVX512 = -mmmx -msse2 -mavx -mavx2 -mavx512f -ifeq "$(SUPPORTS_AVX512)" "True" - HARD_SWITCH_NOSIMD += -mno-avx512f - HARD_SWITCH_MMX += -mno-avx512f - HARD_SWITCH_SSE2 += -mno-avx512f - HARD_SWITCH_AVX += -mno-avx512f - HARD_SWITCH_AVX2 += -mno-avx512f - MULTIARCHOBJS += $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_AVX512.o) -endif BINS = proxmark3 -CLEAN = $(BINS) *.moc.cpp ui/ui_overlays.h lualibs/pm3_cmd.lua lualibs/mfc_default_keys.lua -# transition: make sure old flasher is gone too -CLEAN += flasher +CLEAN = $(BINS) src/*.moc.cpp src/ui/ui_overlays.h lualibs/pm3_cmd.lua lualibs/mfc_default_keys.lua +# transition: cleaning also old path stuff +CLEAN += flasher *.moc.cpp ui/ui_overlays.h # need to assign dependancies to build these first... all: $(BINS) @@ -306,10 +286,10 @@ all: $(BINS) all-static: LDLIBS:=-static $(LDLIBS) all-static: $(BINS) -proxmark3: LDLIBS+=$(LUALIB) $(JANSSONLIB) $(MBEDTLSLIB) $(CBORLIB) $(ZLIB) $(REVENGLIB) $(AMIIBOLIB) $(QTLDLIBS) -proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(LUALIB) $(JANSSONLIB) $(CBORLIB) $(REVENGLIB) $(MBEDTLSLIB) $(ZLIB) $(AMIIBOLIB) lualibs/pm3_cmd.lua lualibs/mfc_default_keys.lua +proxmark3: LDLIBS+=$(LUALIB) $(JANSSONLIB) $(MBEDTLSLIB) $(CBORLIB) $(ZLIB) $(REVENGLIB) $(AMIIBOLIB) $(HARDNESTEDLIB) $(CLIPARSERLIB) $(QTLDLIBS) +proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(LUALIB) $(JANSSONLIB) $(CBORLIB) $(REVENGLIB) $(MBEDTLSLIB) $(ZLIB) $(AMIIBOLIB) $(HARDNESTEDLIB) $(CLIPARSERLIB) lualibs/pm3_cmd.lua lualibs/mfc_default_keys.lua $(info [=] LD $@) - $(Q)$(LD) $(LDFLAGS) $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(LDLIBS) -o $@ + $(Q)$(LD) $(LDFLAGS) $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(LDLIBS) -o $@ src/proxgui.cpp: src/ui/ui_overlays.h @@ -337,6 +317,8 @@ clean: $(Q)$(MAKE) --no-print-directory -C $(CBORLIBPATH) clean $(Q)$(MAKE) --no-print-directory -C $(REVENGPATH) clean $(Q)$(MAKE) --no-print-directory -C $(AMIIBOLIBPATH) clean + $(Q)$(MAKE) --no-print-directory -C $(HARDNESTEDPATH) clean + $(Q)$(MAKE) --no-print-directory -C $(CLIPARSERPATH) clean install: all $(info [@] Installing client to $(DESTDIR)$(PREFIX)...) @@ -381,10 +363,18 @@ $(REVENGLIB): $(info [*] MAKE reveng) $(Q)$(MAKE) --no-print-directory -C $(REVENGPATH) all +$(HARDNESTEDLIB): + $(info [*] MAKE hardnested) + $(Q)$(MAKE) --no-print-directory -C $(HARDNESTEDPATH) all + $(AMIIBOLIB): $(info [*] MAKE amiibo) $(Q)$(MAKE) --no-print-directory -C $(AMIIBOLIBPATH) all +$(CLIPARSERLIB): + $(info [*] MAKE cliparser) + $(Q)$(MAKE) --no-print-directory -C $(CLIPARSERPATH) all + # common libraries: $(MBEDTLSLIB): $(info [*] MAKE mbedtls) @@ -399,42 +389,6 @@ $(ZLIB): # easy printing of MAKE VARIABLES print-%: ; @echo $* = $($*) -$(OBJDIR)/%_NOSIMD.o : %.c $(OBJDIR)/%_NOSIMD.d - $(info [-] CC(NOSIMD) $<) - $(Q)$(MKDIR) $(dir $@) - $(Q)$(CC) $(DEPFLAGS:%.Td=%_NOSIMD.Td) $(PM3CFLAGS) $(HARD_SWITCH_NOSIMD) -c -o $@ $< - $(Q)$(MV) -f $(OBJDIR)/$*_NOSIMD.Td $(OBJDIR)/$*_NOSIMD.d && $(TOUCH) $@ - -$(OBJDIR)/%_MMX.o : %.c $(OBJDIR)/%_MMX.d - $(info [-] CC(MMX) $<) - $(Q)$(MKDIR) $(dir $@) - $(Q)$(CC) $(DEPFLAGS:%.Td=%_MMX.Td) $(PM3CFLAGS) $(HARD_SWITCH_MMX) -c -o $@ $< - $(Q)$(MV) -f $(OBJDIR)/$*_MMX.Td $(OBJDIR)/$*_MMX.d && $(TOUCH) $@ - -$(OBJDIR)/%_SSE2.o : %.c $(OBJDIR)/%_SSE2.d - $(info [-] CC(SSE2) $<) - $(Q)$(MKDIR) $(dir $@) - $(Q)$(CC) $(DEPFLAGS:%.Td=%_SSE2.Td) $(PM3CFLAGS) $(HARD_SWITCH_SSE2) -c -o $@ $< - $(Q)$(MV) -f $(OBJDIR)/$*_SSE2.Td $(OBJDIR)/$*_SSE2.d && $(TOUCH) $@ - -$(OBJDIR)/%_AVX.o : %.c $(OBJDIR)/%_AVX.d - $(info [-] CC(AVX) $<) - $(Q)$(MKDIR) $(dir $@) - $(Q)$(CC) $(DEPFLAGS:%.Td=%_AVX.Td) $(PM3CFLAGS) $(HARD_SWITCH_AVX) -c -o $@ $< - $(Q)$(MV) -f $(OBJDIR)/$*_AVX.Td $(OBJDIR)/$*_AVX.d && $(TOUCH) $@ - -$(OBJDIR)/%_AVX2.o : %.c $(OBJDIR)/%_AVX2.d - $(info [-] CC(AVX2) $<) - $(Q)$(MKDIR) $(dir $@) - $(Q)$(CC) $(DEPFLAGS:%.Td=%_AVX2.Td) $(PM3CFLAGS) $(HARD_SWITCH_AVX2) -c -o $@ $< - $(Q)$(MV) -f $(OBJDIR)/$*_AVX2.Td $(OBJDIR)/$*_AVX2.d && $(TOUCH) $@ - -$(OBJDIR)/%_AVX512.o : %.c $(OBJDIR)/%_AVX512.d - $(info [-] CC(AVX512) $<) - $(Q)$(MKDIR) $(dir $@) - $(Q)$(CC) $(DEPFLAGS:%.Td=%_AVX512.Td) $(PM3CFLAGS) $(HARD_SWITCH_AVX512) -c -o $@ $< - $(Q)$(MV) -f $(OBJDIR)/$*_AVX512.Td $(OBJDIR)/$*_AVX512.d && $(TOUCH) $@ - %.o: %.c $(OBJDIR)/%.o : %.c $(OBJDIR)/%.d $(info [-] CC $<) @@ -456,8 +410,7 @@ $(OBJDIR)/%.o : %.m $(OBJDIR)/%.d $(Q)$(CC) $(DEPFLAGS) $(PM3CFLAGS) -c -o $@ $< $(Q)$(POSTCOMPILE) -DEPENDENCY_FILES = $(patsubst %.c, $(OBJDIR)/%.d, $(CORESRCS) $(CMDSRCS) $(REVENGSRCS)) \ - $(patsubst %.o, %.d, $(MULTIARCHOBJS)) \ +DEPENDENCY_FILES = $(patsubst %.c, $(OBJDIR)/%.d, $(CORESRCS) $(CMDSRCS)) \ $(patsubst %.cpp, $(OBJDIR)/%.d, $(QTGUISRCS)) \ $(patsubst %.m, $(OBJDIR)/%.d, $(OBJCSRCS)) \ $(OBJDIR)/proxmark3.d diff --git a/client/deps/CMakeLists.txt b/client/deps/CMakeLists.txt new file mode 100644 index 000000000..6b577d438 --- /dev/null +++ b/client/deps/CMakeLists.txt @@ -0,0 +1,9 @@ +include(cliparser.cmake) +include(tinycbor.cmake) +include(jansson.cmake) +include(lua.cmake) +include(mbedtls.cmake) +include(amiibo.cmake) +include(reveng.cmake) +include(zlib.cmake) +include(hardnested.cmake) \ No newline at end of file diff --git a/client/deps/amiibo.cmake b/client/deps/amiibo.cmake new file mode 100644 index 000000000..857074f9e --- /dev/null +++ b/client/deps/amiibo.cmake @@ -0,0 +1,16 @@ +# just for testing amiitool before complete migration into a lib: + +#amiitool: +#gcc $(CFLAGS) \ +#amiitool.c $(MYSRCS) ../../../../common/../../commonutil.c ../ui.c -lreadline -lm ../../../../common/mbedtls/libmbedtls.a \ +#-o amiitool + +add_library(amiibo STATIC + amiitool/amiibo.c + amiitool/drbg.c + amiitool/keygen.c +) + +target_include_directories(amiibo PRIVATE ../../include ../../common) +target_include_directories(amiibo INTERFACE amiitool) +target_compile_options(amiibo PRIVATE -Wall -Werror -O3) diff --git a/client/deps/amiitool/Makefile b/client/deps/amiitool/Makefile index 6926c12c6..7fe532878 100644 --- a/client/deps/amiitool/Makefile +++ b/client/deps/amiitool/Makefile @@ -1,6 +1,6 @@ MYSRCPATHS = MYINCLUDES = -I. -I.. -I../jansson -I../../../common -I../../../include -MYCFLAGS = -std=c99 -D_ISOC99_SOURCE +MYCFLAGS = MYDEFS = MYSRCS = \ amiibo.c \ @@ -9,6 +9,9 @@ MYSRCS = \ LIB_A = libamiibo.a +# Transition: remove old directories and objects +MYCLEANOLDPATH = ../../amiitool + include ../../../Makefile.host # just for testing amiitool before complete migration into a lib: diff --git a/client/deps/amiitool/amiitool.c b/client/deps/amiitool/amiitool.c index 2c5c4ddc2..b63222d50 100644 --- a/client/deps/amiitool/amiitool.c +++ b/client/deps/amiitool/amiitool.c @@ -86,7 +86,7 @@ int main(int argc, char **argv) { return 1; } - nfc3d_amiibo_keys amiiboKeys; + nfc3d_amiibo_keys amiiboKeys = {0}; if (! LoadAmiikey(amiiboKeys, keyfile)) return 5; @@ -136,7 +136,7 @@ int main(int argc, char **argv) { return 3; } } - size_t readPages = fread(original, 4, NTAG215_SIZE / 4, f); + readPages = fread(original, 4, NTAG215_SIZE / 4, f); if (readPages < NFC3D_AMIIBO_SIZE / 4) { fprintf(stderr, "Could not read from save\n"); fclose(f); diff --git a/client/deps/cliparser.cmake b/client/deps/cliparser.cmake new file mode 100644 index 000000000..890fd39c5 --- /dev/null +++ b/client/deps/cliparser.cmake @@ -0,0 +1,11 @@ +add_library(cliparser STATIC + cliparser/argtable3.c + cliparser/cliparser.c +) + +target_include_directories(cliparser PRIVATE + ../../common + ../../include + ../src) +target_include_directories(cliparser INTERFACE cliparser) +target_compile_options(cliparser PRIVATE -Wall -Werror -O3) diff --git a/client/deps/cliparser/Makefile b/client/deps/cliparser/Makefile new file mode 100644 index 000000000..7f4409de0 --- /dev/null +++ b/client/deps/cliparser/Makefile @@ -0,0 +1,11 @@ +MYSRCPATHS = +MYINCLUDES = -I../../../common -I../../../include -I../../src +MYCFLAGS = +MYDEFS = +MYSRCS = \ + argtable3.c \ + cliparser.c + +LIB_A = libcliparser.a + +include ../../../Makefile.host diff --git a/client/deps/hardnested.cmake b/client/deps/hardnested.cmake new file mode 100644 index 000000000..8945d68a8 --- /dev/null +++ b/client/deps/hardnested.cmake @@ -0,0 +1,109 @@ +add_library(hardnested_nosimd OBJECT + hardnested/hardnested_bf_core.c + hardnested/hardnested_bitarray_core.c) + +target_compile_options(hardnested_nosimd PRIVATE -Wall -Werror -O3) + +target_include_directories(hardnested_nosimd PRIVATE + ../../common + ../../include) + +## CPU-specific code +## These are mostly for x86-based architectures, which is not useful for many Android devices. +## Mingw platforms: AMD64 +set(X86_CPUS x86 x86_64 i686 AMD64) + +message(STATUS "CMAKE_SYSTEM_PROCESSOR := ${CMAKE_SYSTEM_PROCESSOR}") + +if ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST X86_CPUS) + message(STATUS "Building optimised x86/x86_64 binaries") + + target_compile_options(hardnested_nosimd BEFORE PRIVATE + -mno-mmx -mno-sse2 -mno-avx -mno-avx2 -mno-avx512f) + + ## x86 / MMX + add_library(hardnested_mmx OBJECT + hardnested/hardnested_bf_core.c + hardnested/hardnested_bitarray_core.c) + + target_compile_options(hardnested_mmx PRIVATE -Wall -Werror -O3) + target_compile_options(hardnested_mmx BEFORE PRIVATE + -mmmx -mno-sse2 -mno-avx -mno-avx2 -mno-avx512f) + + target_include_directories(hardnested_mmx PRIVATE + ../../common + ../../include) + + ## x86 / SSE2 + add_library(hardnested_sse2 OBJECT + hardnested/hardnested_bf_core.c + hardnested/hardnested_bitarray_core.c) + + target_compile_options(hardnested_sse2 PRIVATE -Wall -Werror -O3) + target_compile_options(hardnested_sse2 BEFORE PRIVATE + -mmmx -msse2 -mno-avx -mno-avx2 -mno-avx512f) + + target_include_directories(hardnested_sse2 PRIVATE + ../../common + ../../include) + + ## x86 / AVX + add_library(hardnested_avx OBJECT + hardnested/hardnested_bf_core.c + hardnested/hardnested_bitarray_core.c) + + target_compile_options(hardnested_avx PRIVATE -Wall -Werror -O3) + target_compile_options(hardnested_avx BEFORE PRIVATE + -mmmx -msse2 -mavx -mno-avx2 -mno-avx512f) + + target_include_directories(hardnested_avx PRIVATE + ../../common + ../../include) + + ## x86 / AVX2 + add_library(hardnested_avx2 OBJECT + hardnested/hardnested_bf_core.c + hardnested/hardnested_bitarray_core.c) + + target_compile_options(hardnested_avx2 PRIVATE -Wall -Werror -O3) + target_compile_options(hardnested_avx2 BEFORE PRIVATE + -mmmx -msse2 -mavx -mavx2 -mno-avx512f) + + target_include_directories(hardnested_avx2 PRIVATE + ../../common + ../../include) + + ## x86 / AVX512 + add_library(hardnested_avx512 OBJECT + hardnested/hardnested_bf_core.c + hardnested/hardnested_bitarray_core.c) + + target_compile_options(hardnested_avx512 PRIVATE -Wall -Werror -O3) + target_compile_options(hardnested_avx512 BEFORE PRIVATE + -mmmx -msse2 -mavx -mavx2 -mavx512f) + + target_include_directories(hardnested_avx512 PRIVATE + ../../common + ../../include) + + set(SIMD_TARGETS + $ + $ + $ + $ + $) +else () + message(STATUS "Not building optimised targets") + set(SIMD_TARGETS) +endif () + +add_library(hardnested STATIC + hardnested/hardnested_bruteforce.c + $ + ${SIMD_TARGETS}) +target_include_directories(hardnested PRIVATE + ../../common + ../../include + ../src + jansson) +target_include_directories(hardnested INTERFACE hardnested) diff --git a/client/deps/hardnested/Makefile b/client/deps/hardnested/Makefile new file mode 100644 index 000000000..079516977 --- /dev/null +++ b/client/deps/hardnested/Makefile @@ -0,0 +1,83 @@ +MYSRCPATHS = +MYINCLUDES = -I../../../common -I../../../include -I../../src -I../jansson +MYCFLAGS = +MYDEFS = +MYSRCS = hardnested_bruteforce.c + +cpu_arch = $(shell uname -m) +ifneq ($(findstring 86, $(cpu_arch)), ) + MULTIARCHSRCS = hardnested_bf_core.c hardnested_bitarray_core.c +endif +ifneq ($(findstring amd64, $(cpu_arch)), ) + MULTIARCHSRCS = hardnested_bf_core.c hardnested_bitarray_core.c +endif +ifeq ($(MULTIARCHSRCS), ) + MYSRCS += hardnested_bf_core.c hardnested_bitarray_core.c +endif + +LIB_A = libhardnested.a + +MYOBJS = $(MYSRCS:%.c=$(OBJDIR)/%.o) +MYOBJS += $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_NOSIMD.o) \ + $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_MMX.o) \ + $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_SSE2.o) \ + $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_AVX.o) \ + $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_AVX2.o) + +SUPPORTS_AVX512 := $(shell echo | $(CC) -E -mavx512f - > /dev/null 2>&1 && echo "True" ) + +HARD_SWITCH_NOSIMD = -mno-mmx -mno-sse2 -mno-avx -mno-avx2 +HARD_SWITCH_MMX = -mmmx -mno-sse2 -mno-avx -mno-avx2 +HARD_SWITCH_SSE2 = -mmmx -msse2 -mno-avx -mno-avx2 +HARD_SWITCH_AVX = -mmmx -msse2 -mavx -mno-avx2 +HARD_SWITCH_AVX2 = -mmmx -msse2 -mavx -mavx2 +HARD_SWITCH_AVX512 = -mmmx -msse2 -mavx -mavx2 -mavx512f +ifeq "$(SUPPORTS_AVX512)" "True" + HARD_SWITCH_NOSIMD += -mno-avx512f + HARD_SWITCH_MMX += -mno-avx512f + HARD_SWITCH_SSE2 += -mno-avx512f + HARD_SWITCH_AVX += -mno-avx512f + HARD_SWITCH_AVX2 += -mno-avx512f + MYOBJS += $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_AVX512.o) +endif + +include ../../../Makefile.host + +$(OBJDIR)/%_NOSIMD.o : %.c $(OBJDIR)/%_NOSIMD.d + $(info DEBUG $<) + +$(OBJDIR)/%_NOSIMD.o : %.c $(OBJDIR)/%_NOSIMD.d + $(info [-] CC(NOSIMD) $<) + $(Q)$(MKDIR) $(dir $@) + $(Q)$(CC) $(DEPFLAGS:%.Td=%_NOSIMD.Td) $(CFLAGS) $(HARD_SWITCH_NOSIMD) -c -o $@ $< + $(Q)$(MV) -f $(OBJDIR)/$*_NOSIMD.Td $(OBJDIR)/$*_NOSIMD.d && $(TOUCH) $@ + +$(OBJDIR)/%_MMX.o : %.c $(OBJDIR)/%_MMX.d + $(info [-] CC(MMX) $<) + $(Q)$(MKDIR) $(dir $@) + $(Q)$(CC) $(DEPFLAGS:%.Td=%_MMX.Td) $(CFLAGS) $(HARD_SWITCH_MMX) -c -o $@ $< + $(Q)$(MV) -f $(OBJDIR)/$*_MMX.Td $(OBJDIR)/$*_MMX.d && $(TOUCH) $@ + +$(OBJDIR)/%_SSE2.o : %.c $(OBJDIR)/%_SSE2.d + $(info [-] CC(SSE2) $<) + $(Q)$(MKDIR) $(dir $@) + $(Q)$(CC) $(DEPFLAGS:%.Td=%_SSE2.Td) $(CFLAGS) $(HARD_SWITCH_SSE2) -c -o $@ $< + $(Q)$(MV) -f $(OBJDIR)/$*_SSE2.Td $(OBJDIR)/$*_SSE2.d && $(TOUCH) $@ + +$(OBJDIR)/%_AVX.o : %.c $(OBJDIR)/%_AVX.d + $(info [-] CC(AVX) $<) + $(Q)$(MKDIR) $(dir $@) + $(Q)$(CC) $(DEPFLAGS:%.Td=%_AVX.Td) $(CFLAGS) $(HARD_SWITCH_AVX) -c -o $@ $< + $(Q)$(MV) -f $(OBJDIR)/$*_AVX.Td $(OBJDIR)/$*_AVX.d && $(TOUCH) $@ + +$(OBJDIR)/%_AVX2.o : %.c $(OBJDIR)/%_AVX2.d + $(info [-] CC(AVX2) $<) + $(Q)$(MKDIR) $(dir $@) + $(Q)$(CC) $(DEPFLAGS:%.Td=%_AVX2.Td) $(CFLAGS) $(HARD_SWITCH_AVX2) -c -o $@ $< + $(Q)$(MV) -f $(OBJDIR)/$*_AVX2.Td $(OBJDIR)/$*_AVX2.d && $(TOUCH) $@ + +$(OBJDIR)/%_AVX512.o : %.c $(OBJDIR)/%_AVX512.d + $(info [-] CC(AVX512) $<) + $(Q)$(MKDIR) $(dir $@) + $(Q)$(CC) $(DEPFLAGS:%.Td=%_AVX512.Td) $(CFLAGS) $(HARD_SWITCH_AVX512) -c -o $@ $< + $(Q)$(MV) -f $(OBJDIR)/$*_AVX512.Td $(OBJDIR)/$*_AVX512.d && $(TOUCH) $@ diff --git a/client/deps/hardnested/hardnested_tables.c b/client/deps/hardnested/hardnested_tables.c index 91e3b3cd3..d3c620fe5 100644 --- a/client/deps/hardnested/hardnested_tables.c +++ b/client/deps/hardnested/hardnested_tables.c @@ -20,7 +20,7 @@ //----------------------------------------------------------------------------- // To compile it: -// gcc -std=c99 -I ../../common -o hardnested_tables hardnested_tables.c +// gcc -I../../../common -I../../../include -o hardnested_tables hardnested_tables.c #include #include diff --git a/client/deps/jansson.cmake b/client/deps/jansson.cmake new file mode 100644 index 000000000..216f7a830 --- /dev/null +++ b/client/deps/jansson.cmake @@ -0,0 +1,18 @@ +add_library(jansson STATIC + jansson/dump.c + jansson/error.c + jansson/hashtable.c + jansson/hashtable_seed.c + jansson/load.c + jansson/memory.c + jansson/pack_unpack.c + jansson/strbuffer.c + jansson/strconv.c + jansson/utf.c + jansson/path.c + jansson/value.c +) + +target_compile_definitions(jansson PRIVATE HAVE_STDINT_H) +target_include_directories(jansson INTERFACE jansson) +target_compile_options(jansson PRIVATE -Wall -Werror -Wno-unused-function -O3) diff --git a/client/deps/jansson/Makefile b/client/deps/jansson/Makefile index 1ef283bab..152e8bcb9 100644 --- a/client/deps/jansson/Makefile +++ b/client/deps/jansson/Makefile @@ -1,6 +1,6 @@ MYSRCPATHS = MYINCLUDES = -I. -MYCFLAGS = -std=c99 -D_ISOC99_SOURCE -Wno-unused-function +MYCFLAGS = -Wno-unused-function MYDEFS = -DHAVE_STDINT_H MYSRCS = \ dump.c \ @@ -18,4 +18,7 @@ MYSRCS = \ LIB_A = libjansson.a +# Transition: remove old directories and objects +MYCLEANOLDPATH = ../../jansson + include ../../../Makefile.host diff --git a/client/deps/jansson/pack_unpack.c b/client/deps/jansson/pack_unpack.c index 651e1c56b..279499ebd 100644 --- a/client/deps/jansson/pack_unpack.c +++ b/client/deps/jansson/pack_unpack.c @@ -185,7 +185,7 @@ static char *read_string(scanner_t *s, va_list *ap, length = va_arg(*ap, size_t); } else { prev_token(s); - length = s->has_error ? 0 : strlen(str); + length = s->has_error == 1 ? 0 : strlen(str); } if (!s->has_error && strbuffer_append_bytes(&strbuff, str, length) == -1) { diff --git a/client/deps/liblua/Makefile b/client/deps/liblua/Makefile index d4b31be0a..54e45185b 100644 --- a/client/deps/liblua/Makefile +++ b/client/deps/liblua/Makefile @@ -1,7 +1,6 @@ MYSRCPATHS = MYINCLUDES = -I. -# Lua lib is not ready for C99 style... -#MYCFLAGS = -std=c99 -D_ISOC99_SOURCE +# Lua lib requires GNU extensions (implicit declarations of functions): -std=gnu99 or -std=gnu11 MYCFLAGS = MYDEFS = -DLUA_COMPAT_ALL $(SYSCFLAGS) MYSRCS = lapi.c lcode.c lctype.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c \ @@ -14,6 +13,9 @@ SYSCFLAGS= LIB_A= liblua.a +# Transition: remove old directories and objects +MYCLEANOLDPATH = ../../liblua + # Your platform. See PLATS for possible values. PLAT= none diff --git a/client/deps/lua.cmake b/client/deps/lua.cmake new file mode 100644 index 000000000..3850863b5 --- /dev/null +++ b/client/deps/lua.cmake @@ -0,0 +1,48 @@ +add_library(lua STATIC + liblua/lapi.c + liblua/lcode.c + liblua/lctype.c + liblua/ldebug.c + liblua/ldo.c + liblua/ldump.c + liblua/lfunc.c + liblua/lgc.c + liblua/llex.c + liblua/lmem.c + liblua/lobject.c + liblua/lopcodes.c + liblua/lparser.c + liblua/lstate.c + liblua/lstring.c + liblua/ltable.c + liblua/ltm.c + liblua/lundump.c + liblua/lvm.c + liblua/lzio.c + liblua/lauxlib.c + liblua/lbaselib.c + liblua/lbitlib.c + liblua/lcorolib.c + liblua/ldblib.c + liblua/liolib.c + liblua/lmathlib.c + liblua/loslib.c + liblua/lstrlib.c + liblua/ltablib.c + liblua/loadlib.c + liblua/linit.c +) + +target_compile_definitions(lua PRIVATE LUA_COMPAT_ALL) + +if (NOT MINGW) + if (APPLE) + target_compile_definitions(lua PRIVATE LUA_USE_MACOSX) + else (APPLE) + target_compile_definitions(lua PRIVATE LUA_USE_LINUX) + target_link_libraries(lua INTERFACE dl) + endif (APPLE) +endif (NOT MINGW) + +target_include_directories(lua INTERFACE liblua) +target_compile_options(lua PRIVATE -Wall -Werror -O3) diff --git a/client/deps/mbedtls.cmake b/client/deps/mbedtls.cmake new file mode 100644 index 000000000..932c1757c --- /dev/null +++ b/client/deps/mbedtls.cmake @@ -0,0 +1,48 @@ +add_library(mbedtls STATIC + ../../common/mbedtls/aes.c + ../../common/mbedtls/asn1parse.c + ../../common/mbedtls/asn1write.c + ../../common/mbedtls/base64.c + ../../common/mbedtls/bignum.c + ../../common/mbedtls/ctr_drbg.c + ../../common/mbedtls/entropy_poll.c + ../../common/mbedtls/entropy.c + ../../common/mbedtls/error.c + ../../common/mbedtls/timing.c + ../../common/mbedtls/ecp.c + ../../common/mbedtls/ecp_curves.c + ../../common/mbedtls/certs.c + ../../common/mbedtls/camellia.c + ../../common/mbedtls/blowfish.c + ../../common/mbedtls/cipher_wrap.c + ../../common/mbedtls/cipher.c + ../../common/mbedtls/cmac.c + ../../common/mbedtls/des.c + ../../common/mbedtls/ecdsa.c + ../../common/mbedtls/md.c + ../../common/mbedtls/md_wrap.c + ../../common/mbedtls/md5.c + ../../common/mbedtls/oid.c + ../../common/mbedtls/pem.c + ../../common/mbedtls/arc4.c + ../../common/mbedtls/pk.c + ../../common/mbedtls/pk_wrap.c + ../../common/mbedtls/pkwrite.c + ../../common/mbedtls/pkcs5.c + ../../common/mbedtls/pkcs12.c + ../../common/mbedtls/pkparse.c + ../../common/mbedtls/platform.c + ../../common/mbedtls/platform_util.c + ../../common/mbedtls/rsa.c + ../../common/mbedtls/rsa_internal.c + ../../common/mbedtls/sha1.c + ../../common/mbedtls/sha256.c + ../../common/mbedtls/sha512.c + ../../common/mbedtls/threading.c + ../../common/mbedtls/x509.c + ../../common/mbedtls/x509_crl.c + ../../common/mbedtls/x509_crt.c + ) + +target_include_directories(mbedtls PRIVATE ../../common) +target_compile_options(mbedtls PRIVATE -Wall -Werror -O3) diff --git a/client/deps/reveng.cmake b/client/deps/reveng.cmake new file mode 100644 index 000000000..0d24c9d49 --- /dev/null +++ b/client/deps/reveng.cmake @@ -0,0 +1,13 @@ +add_library(reveng STATIC + reveng/bmpbit.c + reveng/cli.c + reveng/model.c + reveng/poly.c + reveng/preset.c + reveng/reveng.c +) + +target_compile_definitions(reveng PRIVATE PRESETS) +target_include_directories(reveng PRIVATE ../cliparser) +target_include_directories(reveng INTERFACE reveng) +target_compile_options(reveng PRIVATE -Wall -Werror -O3) diff --git a/client/deps/reveng/Makefile b/client/deps/reveng/Makefile index 17d63a4f9..1794b0bdb 100644 --- a/client/deps/reveng/Makefile +++ b/client/deps/reveng/Makefile @@ -4,13 +4,12 @@ # Add -DPRESETS to compile with preset models (edit config.h) MYSRCPATHS = -MYINCLUDES = -I. -I.. -MYCFLAGS = -std=c99 -D_ISOC99_SOURCE +MYINCLUDES = -I../cliparser +MYCFLAGS = MYDEFS = -DPRESETS MYSRCS = \ bmpbit.c \ cli.c \ - getopt.c \ model.c \ poly.c \ preset.c \ @@ -18,6 +17,9 @@ MYSRCS = \ LIB_A = libreveng.a +# Transition: remove old directories and objects +MYCLEANOLDPATH = ../../reveng + include ../../../Makefile.host CLEAN += bmptst diff --git a/client/deps/reveng/cli.c b/client/deps/reveng/cli.c index b8de74961..9d849dfc3 100644 --- a/client/deps/reveng/cli.c +++ b/client/deps/reveng/cli.c @@ -53,7 +53,7 @@ #include #include -#include "cliparser/getopt.h" +#include "getopt.h" #ifdef _WIN32 # include # include diff --git a/client/deps/reveng/getopt.c b/client/deps/reveng/getopt.c deleted file mode 100644 index 2c384e6be..000000000 --- a/client/deps/reveng/getopt.c +++ /dev/null @@ -1,80 +0,0 @@ -/*---------------------------------------------------------------------- - - Replacement for Unix "getopt()", for DOS/Windows/etc. - - getopt.c 1.3 2003/09/17 16:17:59 - - Copyright (C) 1998, 2003 by David A. Hinds -- All Rights Reserved - - This file is part of ASPEX. - - ASPEX 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; either version 2 of the License, or - (at your option) any later version. - - ASPEX 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 ASPEX; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -----------------------------------------------------------------------*/ - -#include -#include -#include "getopt.h" - -char *optarg; -int optind = 1, opterr, optopt; -int pos = 0; -int getopt(int argc, char *argv[], const char *optstring) { - //static int pos = 0; - char *str; - - if (pos == 0) { - if ((optind >= argc) || (*argv[optind] != '-')) - return EOF; - pos = 1; - if (argv[optind][pos] == '\0') - return EOF; - } - - str = strchr(optstring, argv[optind][pos]); - if (str == NULL) { - optopt = argv[optind][pos]; - if (opterr) - fprintf(stderr, "%s: illegal option -- %c\n", argv[0], - optopt); - return '?'; - } - - if (str[1] == ':') { - if (argv[optind][pos + 1] != '\0') { - optarg = &argv[optind][pos + 1]; - return *str; - } - optind++; - if (optind >= argc) { - optopt = *str; - if (opterr) - fprintf(stderr, "%s: option requires an argument -- %c\n", - argv[0], optopt); - return '?'; - } - optarg = argv[optind]; - optind++; - pos = 0; - return *str; - } else { - pos++; - if (argv[optind][pos] == '\0') { - optind++; - pos = 0; - } - return *str; - } -} diff --git a/client/deps/reveng/getopt.h b/client/deps/reveng/getopt.h deleted file mode 100644 index c4b77d31e..000000000 --- a/client/deps/reveng/getopt.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - getopt.h 1.2 2003/09/17 16:17:59 - - Copyright (C) 1998, 2003 by David A. Hinds -- All Rights Reserved - - This file is part of ASPEX. - - ASPEX 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; either version 2 of the License, or - (at your option) any later version. - - ASPEX 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 ASPEX; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef __GETOPT_H -#define __GETOPT_H - -extern char *optarg; -extern int optind, opterr, optopt, pos; -int getopt(int argc, char *argv[], const char *optstring); - -#endif diff --git a/client/deps/tinycbor.cmake b/client/deps/tinycbor.cmake new file mode 100644 index 000000000..14ebb5326 --- /dev/null +++ b/client/deps/tinycbor.cmake @@ -0,0 +1,14 @@ +add_library(tinycbor STATIC + tinycbor/cborencoder.c + tinycbor/cborencoder_close_container_checked.c + tinycbor/cborerrorstrings.c + tinycbor/cborparser.c + tinycbor/cborparser_dup_string.c + tinycbor/cborpretty.c + tinycbor/cbortojson.c + tinycbor/cborvalidation.c + ) + +target_include_directories(tinycbor INTERFACE tinycbor) +# Strange errors on Mingw when compiling with -O3 +target_compile_options(tinycbor PRIVATE -Wall -Werror -O2) diff --git a/client/deps/tinycbor/Makefile b/client/deps/tinycbor/Makefile index 376e2b641..99039ac98 100644 --- a/client/deps/tinycbor/Makefile +++ b/client/deps/tinycbor/Makefile @@ -1,7 +1,6 @@ MYSRCPATHS = MYINCLUDES = # Strange errors on Mingw when compiling with C99 -#MYCFLAGS = -std=c99 -D_ISOC99_SOURCE MYCFLAGS = MYDEFS = MYSRCS = \ @@ -16,6 +15,9 @@ MYSRCS = \ LIB_A = tinycbor.a +# Transition: remove old directories and objects +MYCLEANOLDPATH = ../../tinycbor + # Strange errors on Mingw when compiling with -O3 CFLAGS ?= -Wall -Werror -O2 diff --git a/client/deps/zlib.cmake b/client/deps/zlib.cmake new file mode 100644 index 000000000..dc6044f80 --- /dev/null +++ b/client/deps/zlib.cmake @@ -0,0 +1,12 @@ +add_library(z STATIC + ../../common/zlib/deflate.c + ../../common/zlib/adler32.c + ../../common/zlib/trees.c + ../../common/zlib/zutil.c + ../../common/zlib/inflate.c + ../../common/zlib/inffast.c + ../../common/zlib/inftrees.c +) + +target_compile_definitions(z PRIVATE Z_SOLO NO_GZIP ZLIB_PM3_TUNED) +target_compile_options(z PRIVATE -Wall -Werror -O3) diff --git a/client/dictionaries/mfdes_default_keys.dic b/client/dictionaries/mfdes_default_keys.dic new file mode 100644 index 000000000..dac73fa04 --- /dev/null +++ b/client/dictionaries/mfdes_default_keys.dic @@ -0,0 +1,44 @@ +0000000000000000 #NXP Default DES +7544d1652bc9bd43 +00000000000000000000000000000000 #NXP Default 3DES/AES +000000000000000000000000000000000000000000000000 #NXP Default 3K3DES +00112233445566778899AABBCCDDEEFF #TI TRF7970A sloa213 +79702553797025537970255379702553 #TI TRF7970A sloa213 +4E617468616E2E4C6920546564647920 +43464F494D48504E4C4359454E528841 #NHIF +6AC292FAA1315B4D858AB3A3D7D5933A +404142434445464748494a4b4c4d4e4f +00112233445566778899aabbccddeeff +2b7e151628aed2a6abf7158809cf4f3c +fbeed618357133667c85e08f7236a8de +f7ddac306ae266ccf90bc11ee46d513b +54686973206973206D79206B65792020 +ffffffffffffffffffffffffffffffff +a0a1a2a3a4a5a6a7a0a1a2a3a4a5a6a7 +b0b1b2b3b4b5b6b7b0b1b2b3b4b5b6b7 +b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7 +11111111111111111111111111111111 +22222222222222222222222222222222 +33333333333333333333333333333333 +44444444444444444444444444444444 +55555555555555555555555555555555 +66666666666666666666666666666666 +77777777777777777777777777777777 +88888888888888888888888888888888 +99999999999999999999999999999999 +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +cccccccccccccccccccccccccccccccc +dddddddddddddddddddddddddddddddd +eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee +000102030405060708090a0b0c0d0e0f +0102030405060708090a0b0c0d0e0f10 +00010203040506070809101112131415 +01020304050607080910111213141516 +16151413121110090807060504030201 +15141312111009080706050403020100 +0f0e0d0c0b0a09080706050403020100 +100f0e0d0c0b0a090807060504030201 +404142434445464748494a4b4c4d4e4f +303132333435363738393a3b3c3d3e3f diff --git a/client/luascripts/hf_writer.lua b/client/luascripts/hf_writer.lua deleted file mode 100644 index ef7c3969b..000000000 --- a/client/luascripts/hf_writer.lua +++ /dev/null @@ -1,231 +0,0 @@ -local utils = require('utils') -local getopt = require('getopt') -local read14a = require('read14a') - ---[[ ----Suggestions of improvement: ---- Add support another types of dumps: BIN, JSON ---- Maybe it will be not only as `mfc_gen3_writer`, like a universal dump manager. ---- Add undependence from the operation system. At the moment code not working in Linux. ---- Add more chinesse backdoors RAW commands for UID changing (find RAW for the 4 byte familiar chinese card, from native it soft: http://bit.ly/39VIDsU) ---- Hide system messages when you writing a dumps, replace it to some of like [#####----------] 40% - --- iceman notes: --- doesn't take consideration filepaths for dump files. --- doesn't allow A keys for authenticating when writing --- doesn't verify that card is magic gen3. --- doesn't take several versions of same dump ( -1, -2, -3 ) styles. ---]] - -copyright = '' -author = 'Winds' -version = 'v1.0.0' -desc = [[ - The script gives you a easy way to write your *.eml dumps onto normal MFC and magic Gen3 cards. - - Works with both 4 and 7 bytes NXP MIFARE Classic 1K cards. - The script also has the possibility to change UID and permanent lock uid on magic Gen3 cards. - - It supports the following functionality. - - 1. Write it to the same of current card UID. - 2. Write it to magic Gen3 card. - 3. Change uid to match dump on magic Gen3 card. - 4. Permanent lock UID on magic Gen3 card. - 5. Erase all data at the card and set the FF FF FF FF FF FF keys, and Access Conditions to 78778800. - - Script works in a wizard styled way. -]] -example = [[ - 1. script run mfc_gen3_writer -]] -usage = [[ - Select your *.eml dump from list to write to the card. -]] - --- Some globals -local DEBUG = false -- the debug flag - -------------------------------- --- Some utilities -------------------------------- - ---- --- A debug printout-function -local function dbg(args) - if not DEBUG then return end - if type(args) == 'table' then - local i = 1 - while args[i] do - dbg(args[i]) - i = i+1 - end - else - print('###', args) - end -end ---- --- This is only meant to be used when errors occur -local function oops(err) - print('ERROR:', err) - core.clearCommandBuffer() - return nil, err -end ---- --- Usage help -local function help() - print(copyright) - print(author) - print(version) - print(desc) - print('Example usage') - print(example) - print(usage) -end ---- --- GetUID -local function GetUID() - return read14a.read(true, true).uid -end ---- --- -local function dropfield() - read14a.disconnect() - core.clearCommandBuffer() -end ---- --- Wait for tag (MFC) -local function wait() - read14a.waitFor14443a() -end ---- --- -local function main(args) - - -- Arguments for the script - for o, a in getopt.getopt(args, 'hd') do - if o == 'h' then return help() end - if o == 'd' then DEBUG = true end - end - - local files = {} -- Array for eml files - local b_keys = {} -- Array for B keys - local eml = {} -- Array for data in block 32 - local num_dumps = 0 -- num of found eml dump files - - local tab = string.rep('-', 64) - -- - wait() - print(tab) - - local length = 25 - local e = 16 - -- Detect 7 byte card - if string.len(GetUID()) == 14 then - length = 31 - e = 22 - end - dropfield() - - ---List all EML files in /client - local dumpEML = "find '.' -iname '*dump.eml' -type f" - local p = assert(io.popen(dumpEML)) - for _ in p:lines() do - - -- The length of eml file - if string.len(_) == length then - num_dumps = num_dumps + 1 - -- cut UID from eml file - files[num_dumps] = string.sub(_, 9, e) - print(' '..num_dumps..' | '..files[num_dumps]) - end - end - p.close() - - if num_dumps == 0 then return oops("Didn't find any dump files") end - - print(tab) - print(' Your card has UID '..GetUID()) - print('') - print(' Select which dump to write (1 until '..num_dumps..')') - print(tab) - io.write(' --> ') - - local no = tonumber(io.read()) - print(tab) - print(' You have been selected card dump ' .. no .. ', with UID : '..files[no]) - - --- Load eml file - local dumpfile = assert(io.open('./hf-mf-' .. files[no] .. '-dump.eml', 'r')) - for _ in dumpfile:lines() do table.insert(eml, _); end - dumpfile.close() - - --- Extract B key from EML file - local b = 0 - for i = 1, #eml do - if (i % 4 == 0) then - repeat - b = b + 1 - -- Cut key from block - b_keys[b] = string.sub(eml[i], (#eml[i] - 11), #eml[i]) - until b % 4 == 0 - end - end - print(tab) - dbg(b_keys) - dbg(eml) - - --- Change UID on certain version of magic Gen3 card. - if (utils.confirm(' Change UID ?') == true) then - wait() - --core.console('hf 14a raw -s -c -t 2000 90f0cccc10'..tostring(eml[1])) - print('hf 14a raw -s -c -t 2000 90f0cccc10'..tostring(eml[1])) - print(tab) - print(' The new card UID : ' .. GetUID()) - end - print(tab) - - --- Lock UID - if (utils.confirm(' Permanent lock UID ? (card can never change uid again) ') == true) then - wait() - core.console('hf 14a raw -s -c -t 2000 90fd111100') - end - print(tab) - - --- Writing blocks - local default_key = 'FFFFFFFFFFFF' - local default_key_blk = 'FFFFFFFFFFFF78778800FFFFFFFFFFFF' - local empty = string.rep('0', 32) - local cmd_wrbl = 'hf mf wrbl %d B %s %s' - - if (utils.confirm(' Are you using a empty card with default key?') == true) then - wait() - for i = 1, #eml do - core.console(string.format(cmd_wrbl, (i-1), default_key, eml[i])) - end - else - print(tab) - if (utils.confirm(' Delete ALL data and write all keys to 0x'..default_key..' ?') == true) then - wait() - for i = 1, #eml do - if (i % 4 == 0) then - core.console(string.format(cmd_wrbl, (i-1), b_keys[i], default_key_blk)) - else - core.console(string.format(cmd_wrbl, (i-1), b_keys[i], empty)) - end - end - else - print(tab) - print('Writing to card') - wait() - for i = 1, #eml do - core.console(string.format(cmd_wrbl, (i-1), b_keys[i], eml[i])) - end - end - end - dropfield() - print(tab) - print('Done') -end - -main(args) diff --git a/client/resources/aid_desfire.json b/client/resources/aid_desfire.json index 4a9798067..206e003a0 100644 --- a/client/resources/aid_desfire.json +++ b/client/resources/aid_desfire.json @@ -122,17 +122,17 @@ FFFFFF General Issuer Information (FIDs 00: MAD Version; 01: Card Holder; 02: Ca }, { "AID": "F518F0", - "Vendor": "TELENOT", + "Vendor": "Telenot Electronic GmbH", "Country": "DE", - "Name": "TELENOT Tag", + "Name": "Telenot Tag", "Description": "", "Type": "alarm system" }, { "AID": "F38091", - "Vendor": "MICROTRONIC", + "Vendor": "Microtronic AG", "Country": "CH", - "Name": "MICROTRONIC Tag", + "Name": "Microtronic Tag", "Description": "", "Type": "payment system" }, @@ -256,5 +256,69 @@ FFFFFF General Issuer Information (FIDs 00: MAD Version; 01: Card Holder; 02: Ca "Name": "BAT", "Description": "", "Type": "transport" - }, -} + }, + { + "AID": "05845F", + "Vendor": "InterCard GmbH Kartensysteme", + "Country": "DE", + "Name": "InterCard", + "Description": "Campus Card", + "Type": "student" + }, + { + "AID": "15845F", + "Vendor": "InterCard GmbH Kartensysteme", + "Country": "DE", + "Name": "InterCard", + "Description": "Campus Card", + "Type": "student" + }, + { + "AID": "25845F", + "Vendor": "InterCard GmbH Kartensysteme", + "Country": "DE", + "Name": "InterCard", + "Description": "Campus Card", + "Type": "student" + }, + { + "AID": "35845F", + "Vendor": "InterCard GmbH Kartensysteme", + "Country": "DE", + "Name": "InterCard", + "Description": "Campus Card", + "Type": "student" + }, + { + "AID": "55845F", + "Vendor": "InterCard GmbH Kartensysteme", + "Country": "DE", + "Name": "InterCard", + "Description": "Campus Card", + "Type": "student" + }, + { + "AID": "65845F", + "Vendor": "InterCard GmbH Kartensysteme", + "Country": "DE", + "Name": "InterCard", + "Description": "Campus Card", + "Type": "student" + }, + { + "AID": "75845F", + "Vendor": "InterCard GmbH Kartensysteme", + "Country": "DE", + "Name": "InterCard", + "Description": "Campus Card", + "Type": "student" + }, + { + "AID": "C26001", + "Vendor": "CAR2GO", + "Country": "DE", + "Name": "MemberCard", + "Description": "CAR2GO - Member Card", + "Type": "carsharing" + } +] diff --git a/client/src/cmdcrc.c b/client/src/cmdcrc.c index d51e18021..8830f5530 100644 --- a/client/src/cmdcrc.c +++ b/client/src/cmdcrc.c @@ -22,7 +22,7 @@ # endif /* STDIN_FILENO */ #endif /* _WIN32 */ -#include "reveng/reveng.h" +#include "reveng.h" #include "ui.h" #include "util.h" diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 86cc91dfd..9a809f603 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -21,11 +21,11 @@ #include "graph.h" // for graph data #include "comms.h" #include "lfdemod.h" // for demod code -#include "../loclass/cipherutils.h" // for decimating samples in getsamples +#include "loclass/cipherutils.h" // for decimating samples in getsamples #include "cmdlfem4x.h" // askem410xdecode #include "fileutils.h" // searchFile #include "mifare/ndef.h" -#include "cliparser/cliparser.h" +#include "cliparser.h" uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN]; size_t DemodBufferLen = 0; @@ -101,13 +101,13 @@ static int usage_data_biphaserawdecode(void) { static int usage_data_rawdemod(void) { PrintAndLogEx(NORMAL, "Usage: data rawdemod [modulation] |"); PrintAndLogEx(NORMAL, " [modulation] as 2 char,"); - PrintAndLogEx(NORMAL, " "_YELLOW_("ab")"- ask/biphase"); - PrintAndLogEx(NORMAL, " "_YELLOW_("am")"- ask/manchester"); - PrintAndLogEx(NORMAL, " "_YELLOW_("ar")"- ask/raw"); - PrintAndLogEx(NORMAL, " "_YELLOW_("fs")"- fsk"); - PrintAndLogEx(NORMAL, " "_YELLOW_("nr")"- nrz/direct"); - PrintAndLogEx(NORMAL, " "_YELLOW_("p1")"- psk1"); - PrintAndLogEx(NORMAL, " "_YELLOW_("p2")"- psk2"); + PrintAndLogEx(NORMAL, " "_YELLOW_("ab")" - ask/biphase"); + PrintAndLogEx(NORMAL, " "_YELLOW_("am")" - ask/manchester"); + PrintAndLogEx(NORMAL, " "_YELLOW_("ar")" - ask/raw"); + PrintAndLogEx(NORMAL, " "_YELLOW_("fs")" - fsk"); + PrintAndLogEx(NORMAL, " "_YELLOW_("nr")" - nrz/direct"); + PrintAndLogEx(NORMAL, " "_YELLOW_("p1")" - psk1"); + PrintAndLogEx(NORMAL, " "_YELLOW_("p2")" - psk2"); PrintAndLogEx(NORMAL, " as 'h', prints the help for the specific modulation"); PrintAndLogEx(NORMAL, " see specific modulation help for optional parameters"); PrintAndLogEx(NORMAL, ""); @@ -843,7 +843,7 @@ int AutoCorrelate(const int *in, int *out, size_t len, size_t window, bool SaveG // sanity check if (window > len) window = len; - if (verbose) PrintAndLogEx(INFO, "performing " _YELLOW_("%zu") "correlations", GraphTraceLen - window); + if (verbose) PrintAndLogEx(INFO, "performing " _YELLOW_("%zu") " correlations", GraphTraceLen - window); //test double autocv = 0.0; // Autocovariance value @@ -899,9 +899,9 @@ int AutoCorrelate(const int *in, int *out, size_t len, size_t window, bool SaveG if (verbose && foo < bar) { distance = idx_1 - idx; - PrintAndLogEx(SUCCESS, "possible visible correlation "_YELLOW_("%4d") "samples", distance); + PrintAndLogEx(SUCCESS, "possible visible correlation "_YELLOW_("%4d") " samples", distance); } else if (verbose && (correlation > 1)) { - PrintAndLogEx(SUCCESS, "possible correlation " _YELLOW_("%4zu") "samples", correlation); + PrintAndLogEx(SUCCESS, "possible correlation " _YELLOW_("%4zu") " samples", correlation); } else { PrintAndLogEx(FAILED, "no repeating pattern found, try increasing window size"); } @@ -1599,7 +1599,7 @@ int getSamples(uint32_t n, bool verbose) { if (n == 0 || n > sizeof(got)) n = sizeof(got); - if (verbose) PrintAndLogEx(INFO, "Reading " _YELLOW_("%u") "bytes from device memory", n); + if (verbose) PrintAndLogEx(INFO, "Reading " _YELLOW_("%u") " bytes from device memory", n); PacketResponseNG response; if (!GetFromDevice(BIG_BUF, got, n, 0, NULL, 0, &response, 10000, true)) { @@ -1614,7 +1614,7 @@ int getSamples(uint32_t n, bool verbose) { //Old devices without this feature would send 0 at arg[0] if (response.oldarg[0] > 0) { sample_config *sc = (sample_config *) response.data.asBytes; - if (verbose) PrintAndLogEx(INFO, "Samples @ " _YELLOW_("%d") "bits/smpl, decimation 1:%d ", sc->bits_per_sample, sc->decimation); + if (verbose) PrintAndLogEx(INFO, "Samples @ " _YELLOW_("%d") " bits/smpl, decimation 1:%d ", sc->bits_per_sample, sc->decimation); bits_per_sample = sc->bits_per_sample; } diff --git a/client/src/cmdflashmem.c b/client/src/cmdflashmem.c index ab104276d..8d19c3888 100644 --- a/client/src/cmdflashmem.c +++ b/client/src/cmdflashmem.c @@ -266,7 +266,7 @@ static int CmdFlashMemLoad(const char *Cmd) { conn.block_after_ACK = false; free(data); - PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu")"bytes to offset "_GREEN_("%u"), datalen, start_index); + PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu")" bytes to offset "_GREEN_("%u"), datalen, start_index); return PM3_SUCCESS; } static int CmdFlashMemDump(const char *Cmd) { @@ -321,7 +321,7 @@ static int CmdFlashMemDump(const char *Cmd) { return PM3_EMALLOC; } - PrintAndLogEx(INFO, "downloading "_YELLOW_("%u")"bytes from flashmem", len); + PrintAndLogEx(INFO, "downloading "_YELLOW_("%u")" bytes from flashmem", len); if (!GetFromDevice(FLASH_MEM, dump, len, start_index, NULL, 0, NULL, -1, true)) { PrintAndLogEx(FAILED, "ERROR; downloading from flashmemory"); free(dump); diff --git a/client/src/cmdflashmemspiffs.c b/client/src/cmdflashmemspiffs.c index 8ec0fe8e1..b994ea56c 100644 --- a/client/src/cmdflashmemspiffs.c +++ b/client/src/cmdflashmemspiffs.c @@ -308,7 +308,7 @@ static int CmdFlashMemSpiFFSDump(const char *Cmd) { return PM3_EMALLOC; } - PrintAndLogEx(INFO, "downloading "_YELLOW_("%u") "bytes from spiffs (flashmem)", len); + PrintAndLogEx(INFO, "downloading "_YELLOW_("%u") " bytes from spiffs (flashmem)", len); if (!GetFromDevice(SPIFFS, dump, len, start_index, (uint8_t *)destfilename, 32, NULL, -1, true)) { PrintAndLogEx(FAILED, "ERROR; downloading from spiffs(flashmemory)"); free(dump); @@ -449,7 +449,7 @@ static int CmdFlashMemSpiFFSLoad(const char *Cmd) { free(data); if (res == PM3_SUCCESS) - PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu") "bytes to file "_GREEN_("%s"), datalen, destfilename); + PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu") " bytes to file "_GREEN_("%s"), datalen, destfilename); return res; } diff --git a/client/src/cmdhf.c b/client/src/cmdhf.c index 9ea34420a..fbc99dbd5 100644 --- a/client/src/cmdhf.c +++ b/client/src/cmdhf.c @@ -16,7 +16,7 @@ #include // tolower #include "cmdparser.h" // command_t -#include "cliparser/cliparser.h" // parse +#include "cliparser.h" // parse #include "comms.h" // clearCommandBuffer #include "lfdemod.h" // computeSignalProperties #include "cmdhf14a.h" // ISO14443-A @@ -39,7 +39,7 @@ #include "ui.h" #include "cmddata.h" #include "graph.h" -#include "../../common_fpga/fpga.h" +#include "fpga.h" static int CmdHelp(const char *Cmd); @@ -92,7 +92,7 @@ int CmdHFSearch(const char *Cmd) { PrintAndLogEx(INPLACE, "Searching for ThinFilm tag..."); if (IfPm3NfcBarcode()) { if (infoThinFilm(false) == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Thinfilm tag") "found\n"); + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Thinfilm tag") " found\n"); res = PM3_SUCCESS; } } @@ -101,7 +101,7 @@ int CmdHFSearch(const char *Cmd) { PrintAndLogEx(INPLACE, "Searching for LTO-CM tag..."); if (IfPm3Iso14443a()) { if (infoLTO(false) == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("LTO-CM tag") "found\n"); + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("LTO-CM tag") " found\n"); res = PM3_SUCCESS; } } @@ -110,7 +110,7 @@ int CmdHFSearch(const char *Cmd) { PrintAndLogEx(INPLACE, "Searching for ISO14443-A tag..."); if (IfPm3Iso14443a()) { if (infoHF14A(false, false, false) > 0) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO14443-A tag") "found\n"); + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO14443-A tag") " found\n"); res = PM3_SUCCESS; } } @@ -119,7 +119,7 @@ int CmdHFSearch(const char *Cmd) { PrintAndLogEx(INPLACE, "Searching for ISO15693 tag..."); if (IfPm3Iso15693()) { if (readHF15Uid(false)) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO15693 tag") "found\n"); + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO15693 tag") " found\n"); res = PM3_SUCCESS; } } @@ -128,7 +128,7 @@ int CmdHFSearch(const char *Cmd) { PrintAndLogEx(INPLACE, "Searching for LEGIC tag..."); if (IfPm3Legicrf()) { if (readLegicUid(false) == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("LEGIC Prime tag") "found\n"); + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("LEGIC Prime tag") " found\n"); res = PM3_SUCCESS; } } @@ -137,7 +137,7 @@ int CmdHFSearch(const char *Cmd) { PrintAndLogEx(INPLACE, "Searching for Topaz tag..."); if (IfPm3Iso14443a()) { if (readTopazUid(false) == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Topaz tag") "found\n"); + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Topaz tag") " found\n"); res = PM3_SUCCESS; } } @@ -146,7 +146,7 @@ int CmdHFSearch(const char *Cmd) { PrintAndLogEx(INPLACE, "Searching for FeliCa tag..."); if (IfPm3Felica()) { if (readFelicaUid(false) == PM3_SUCCESS) { - PrintAndLogEx(NORMAL, "\nValid " _GREEN_("ISO18092 / FeliCa tag") "found\n"); + PrintAndLogEx(NORMAL, "\nValid " _GREEN_("ISO18092 / FeliCa tag") " found\n"); res = PM3_SUCCESS; } } @@ -156,7 +156,7 @@ int CmdHFSearch(const char *Cmd) { PrintAndLogEx(INPLACE, "Searching for CryptoRF tag..."); if (IfPm3Iso14443b()) { if (readHFCryptoRF(false) == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("CryptoRF tag") "found\n"); + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("CryptoRF tag") " found\n"); res = PM3_SUCCESS; } } @@ -167,7 +167,7 @@ int CmdHFSearch(const char *Cmd) { PrintAndLogEx(INPLACE, "Searching for ISO14443-B tag..."); if (IfPm3Iso14443b()) { if (readHF14B(false) == 1) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO14443-B tag") "found\n"); + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO14443-B tag") " found\n"); res = PM3_SUCCESS; } } @@ -176,7 +176,7 @@ int CmdHFSearch(const char *Cmd) { PrintAndLogEx(INPLACE, "Searching for iClass / PicoPass tag..."); if (IfPm3Iclass()) { if (readIclass(false, false) == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("iClass tag / PicoPass tag") "found\n"); + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("iClass tag / PicoPass tag") " found\n"); res = PM3_SUCCESS; } } @@ -196,7 +196,7 @@ int CmdHFTune(const char *Cmd) { if (cmdp == 'h') return usage_hf_tune(); int iter = param_get32ex(Cmd, 0, 0, 10); - PrintAndLogEx(INFO, "Measuring HF antenna, click " _GREEN_("pm3 button") "or press " _GREEN_("Enter") "to exit"); + PrintAndLogEx(INFO, "Measuring HF antenna, click " _GREEN_("pm3 button") " or press " _GREEN_("Enter") " to exit"); PacketResponseNG resp; clearCommandBuffer(); diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 029b354d2..262e879f4 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -19,7 +19,7 @@ #include "commonutil.h" // ARRAYLEN #include "comms.h" // clearCommandBuffer #include "cmdtrace.h" -#include "cliparser/cliparser.h" +#include "cliparser.h" #include "cmdhfmf.h" #include "cmdhfmfu.h" #include "emv/emvcore.h" @@ -466,7 +466,7 @@ int CmdHF14ASim(const char *Cmd) { break; } if (!errors) { - PrintAndLogEx(SUCCESS, "Emulating " _YELLOW_("ISO/IEC 14443 type A tag")"with " _GREEN_("%d byte UID (%s)"), uidlen, sprint_hex(uid, uidlen)); + PrintAndLogEx(SUCCESS, "Emulating " _YELLOW_("ISO/IEC 14443 type A tag")" with " _GREEN_("%d byte UID (%s)"), uidlen, sprint_hex(uid, uidlen)); useUIDfromEML = false; } cmdp += 2; @@ -1024,7 +1024,7 @@ static int CmdHF14ACmdRaw(const char *Cmd) { active_select = true; break; case 'b': - sscanf(Cmd + i + 2, "%d", &temp); + sscanf(Cmd + i + 2, "%u", &temp); numbits = temp & 0xFFFF; i += 3; while (Cmd[i] != ' ' && Cmd[i] != '\0') { i++; } @@ -1032,7 +1032,7 @@ static int CmdHF14ACmdRaw(const char *Cmd) { break; case 't': bTimeout = true; - sscanf(Cmd + i + 2, "%d", &temp); + sscanf(Cmd + i + 2, "%u", &temp); timeout = temp; i += 3; while (Cmd[i] != ' ' && Cmd[i] != '\0') { i++; } diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index 9762ba498..620a75bd7 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -29,7 +29,7 @@ #include "comms.h" // clearCommandBuffer #include "cmdtrace.h" #include "iso15693tools.h" -#include "../crypto/libpcrypto.h" +#include "crypto/libpcrypto.h" #include "graph.h" #include "crc16.h" // iso15 crc #include "cmddata.h" // getsamples @@ -928,7 +928,7 @@ static int CmdHF15Info(const char *Cmd) { memcpy(uid, recv + 2, sizeof(uid)); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") "---------"); + PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------"); PrintAndLogEx(INFO, "-------------------------------------------------------------"); PrintAndLogEx(SUCCESS, " TYPE: " _YELLOW_("%s"), getTagInfo_15(recv + 2)); PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); diff --git a/client/src/cmdhffido.c b/client/src/cmdhffido.c index e6f89790a..e35479db9 100644 --- a/client/src/cmdhffido.c +++ b/client/src/cmdhffido.c @@ -30,9 +30,9 @@ #include "proxmark3.h" #include "emv/emvcore.h" #include "emv/emvjson.h" -#include "cliparser/cliparser.h" -#include "../crypto/asn1utils.h" -#include "../crypto/libpcrypto.h" +#include "cliparser.h" +#include "crypto/asn1utils.h" +#include "crypto/libpcrypto.h" #include "fido/cbortools.h" #include "fido/fidocore.h" #include "emv/dump.h" diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 73163e1ea..c687e316d 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -19,10 +19,10 @@ #include "util_posix.h" #include "comms.h" #include "mbedtls/des.h" -#include "../loclass/cipherutils.h" -#include "../loclass/cipher.h" -#include "../loclass/ikeys.h" -#include "../loclass/elite_crack.h" +#include "loclass/cipherutils.h" +#include "loclass/cipher.h" +#include "loclass/ikeys.h" +#include "loclass/elite_crack.h" #include "fileutils.h" #include "protocols.h" #include "cardhelper.h" @@ -927,7 +927,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) { uint32_t limit = MIN(applimit, decryptedlen / 8); if (decryptedlen / 8 != applimit) { - PrintAndLogEx(WARNING, "Actual file len " _YELLOW_("%zu") "vs HID app-limit len " _YELLOW_("%u"), decryptedlen, applimit * 8); + PrintAndLogEx(WARNING, "Actual file len " _YELLOW_("%zu") " vs HID app-limit len " _YELLOW_("%u"), decryptedlen, applimit * 8); PrintAndLogEx(INFO, "Setting limit to " _GREEN_("%u"), limit * 8); } uint8_t numblocks4userid = GetNumberBlocksForUserId(decrypted + (6 * 8)); @@ -1415,7 +1415,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) { // print the dump PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "------+--+-------------------------+----------"); - PrintAndLogEx(INFO, " CSN |00| " _GREEN_("%s") "|", sprint_hex(tag_data, 8)); + PrintAndLogEx(INFO, " CSN |00| " _GREEN_("%s") " |", sprint_hex(tag_data, 8)); printIclassDumpContents(tag_data, 1, (gotBytes / 8), gotBytes); if (filename[0] == 0) { @@ -2052,11 +2052,11 @@ static int CmdHFiClassReadTagFile(const char *Cmd) { PrintAndLogEx(INFO, "File: " _YELLOW_("%s"), filename); PrintAndLogEx(INFO, "File size %zu bytes, file blocks %d (0x%x)", bytes_read, (uint16_t)(bytes_read >> 3), (uint16_t)(bytes_read >> 3)); PrintAndLogEx(INFO, "Printing blocks from"); - PrintAndLogEx(INFO, "start " _YELLOW_("0x%02x") "end " _YELLOW_("0x%02x"), (startblock == 0) ? 6 : startblock, endblock); + PrintAndLogEx(INFO, "start " _YELLOW_("0x%02x") " end " _YELLOW_("0x%02x"), (startblock == 0) ? 6 : startblock, endblock); } uint8_t *csn = dump; PrintAndLogEx(INFO, "------+--+-------------------------+----------"); - PrintAndLogEx(INFO, " CSN |00| " _GREEN_("%s") "|", sprint_hex(csn, 8)); + PrintAndLogEx(INFO, " CSN |00| " _GREEN_("%s") " |", sprint_hex(csn, 8)); printIclassDumpContents(dump, startblock, endblock, bytes_read); free(dump); return PM3_SUCCESS; @@ -2223,7 +2223,7 @@ static int loadKeys(char *filename) { memcpy(iClass_Key_Table[i], dump + (i * 8), 8); free(dump); - PrintAndLogEx(SUCCESS, "Loaded " _GREEN_("%2d") "keys from %s", i, filename); + PrintAndLogEx(SUCCESS, "Loaded " _GREEN_("%2d") " keys from %s", i, filename); return PM3_SUCCESS; } @@ -2440,7 +2440,7 @@ static int CmdHFiClassCheckKeys(const char *Cmd) { if (use_raw) PrintAndLogEx(SUCCESS, "Using " _YELLOW_(" raw mode")); - PrintAndLogEx(SUCCESS, "Searching for " _YELLOW_("%s") "key", (use_credit_key) ? "CREDIT" : "DEBIT"); + PrintAndLogEx(SUCCESS, "Searching for " _YELLOW_("%s") " key", (use_credit_key) ? "CREDIT" : "DEBIT"); PrintAndLogEx(SUCCESS, "Tag info"); PrintAndLogEx(SUCCESS, "CSN | %s", sprint_hex(CSN, sizeof(CSN))); PrintAndLogEx(SUCCESS, "CCNR | %s", sprint_hex(CCNR, sizeof(CCNR))); @@ -2714,7 +2714,7 @@ static int CmdHFiClassLookUp(const char *Cmd) { if (memcmp(iClass_Key_Table[i], "\x00\x00\x00\x00\x00\x00\x00\x00", 8) == 0) { memcpy(iClass_Key_Table[i], item->key, 8); - PrintAndLogEx(SUCCESS, "Added key to keyslot [%d] - "_YELLOW_("`hf iclass managekeys p`")"to view", i); + PrintAndLogEx(SUCCESS, "Added key to keyslot [%d] - "_YELLOW_("`hf iclass managekeys p`")" to view", i); break; } } diff --git a/client/src/cmdhflegic.c b/client/src/cmdhflegic.c index 04bd692aa..7507e326b 100644 --- a/client/src/cmdhflegic.c +++ b/client/src/cmdhflegic.c @@ -55,7 +55,7 @@ static int usage_legic_rdbl(void) { } static int usage_legic_sim(void) { PrintAndLogEx(NORMAL, "Simulates a LEGIC Prime tag. MIM22, MIM256, MIM1024 types can be emulated"); - PrintAndLogEx(NORMAL, "Use " _YELLOW_("`hf legic eload`") "to upload a dump into emulator memory\n"); + PrintAndLogEx(NORMAL, "Use " _YELLOW_("`hf legic eload`") " to upload a dump into emulator memory\n"); PrintAndLogEx(NORMAL, "Usage: hf legic sim [h] \n"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h : this help"); @@ -217,7 +217,7 @@ static int CmdLegicInfo(const char *Cmd) { return PM3_ESOFT; } - PrintAndLogEx(SUCCESS, "Reading full tag memory of " _YELLOW_("%d") "bytes...", card.cardsize); + PrintAndLogEx(SUCCESS, "Reading full tag memory of " _YELLOW_("%d") " bytes...", card.cardsize); // allocate receiver buffer uint8_t *data = calloc(card.cardsize, sizeof(uint8_t)); @@ -239,7 +239,7 @@ static int CmdLegicInfo(const char *Cmd) { PrintAndLogEx(SUCCESS, " " _CYAN_("CDF: System Area")); PrintAndLogEx(NORMAL, "------------------------------------------------------"); - PrintAndLogEx(SUCCESS, "MCD: " _GREEN_("%02X") " MSN: " _GREEN_("%s") " MCC: " _GREEN_("%02X") " ( %s)", + PrintAndLogEx(SUCCESS, "MCD: " _GREEN_("%02X") " MSN: " _GREEN_("%s") " MCC: " _GREEN_("%02X") " (%s)", data[0], sprint_hex(data + 1, 3), data[4], @@ -394,7 +394,7 @@ static int CmdLegicInfo(const char *Cmd) { (segment_flag & 0x4) >> 2, (segment_flag & 0x8) >> 3 ); - PrintAndLogEx(SUCCESS, " | WRP: %02u, WRC: %02u, RD: %01u, CRC: 0x%02X ( %s)", + PrintAndLogEx(SUCCESS, " | WRP: %02u, WRC: %02u, RD: %01u, CRC: 0x%02X (%s)", wrp, wrc, ((data[i + 3] ^ crc) & 0x80) >> 7, diff --git a/client/src/cmdhflto.c b/client/src/cmdhflto.c index c5b73c0c6..6434a9e88 100644 --- a/client/src/cmdhflto.c +++ b/client/src/cmdhflto.c @@ -616,7 +616,7 @@ static int CmdHfLTRestore(const char *Cmd) { is_data_loaded = loadFileEML(filename, (uint8_t *)dump_data, &dump_datalen); } else - PrintAndLogEx(WARNING, "\nWarning: invalid dump filename "_YELLOW_("%s")"to restore!\n", filename); + PrintAndLogEx(WARNING, "\nWarning: invalid dump filename "_YELLOW_("%s")" to restore!\n", filename); } if (is_data_loaded == PM3_SUCCESS) { diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 44e56351b..8c6247614 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -19,8 +19,8 @@ #include "cmdtrace.h" #include "emv/dump.h" #include "mifare/mifaredefault.h" // mifare default key array -#include "cliparser/cliparser.h" // argtable -#include "hardnested/hardnested_bf_core.h" // SetSIMDInstr +#include "cliparser.h" // argtable +#include "hardnested_bf_core.h" // SetSIMDInstr #include "mifare/mad.h" #include "mifare/ndef.h" #include "protocols.h" @@ -249,10 +249,10 @@ static int usage_hf14_chk(void) { PrintAndLogEx(NORMAL, " t write keys to emulator memory\n"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf chk 0 A 1234567890ab")" -- target block 0, Key A using key 1234567890ab"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf chk 0 A mfc_default_keys.dic")" -- target block 0, Key A using default dictionary file"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf chk *1 ? t")" -- target all blocks, all keys, 1K, write to emulator memory"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf chk *1 ? d")" -- target all blocks, all keys, 1K, write to file"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf chk 0 A 1234567890ab")" -- target block 0, Key A using key 1234567890ab"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf chk 0 A mfc_default_keys.dic")" -- target block 0, Key A using default dictionary file"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf chk *1 ? t")" -- target all blocks, all keys, 1K, write to emulator memory"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf chk *1 ? d")" -- target all blocks, all keys, 1K, write to file"); return PM3_SUCCESS; } static int usage_hf14_chk_fast(void) { @@ -270,12 +270,12 @@ static int usage_hf14_chk_fast(void) { PrintAndLogEx(NORMAL, " m use dictionary from flashmemory\n"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf fchk 1 1234567890ab")" -- target 1K using key 1234567890ab"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf fchk 1 mfc_default_keys.dic")" -- target 1K using default dictionary file"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf fchk 1 t")" -- target 1K, write to emulator memory"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf fchk 1 d")" -- target 1K, write to file"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf fchk 1 1234567890ab")" -- target 1K using key 1234567890ab"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf fchk 1 mfc_default_keys.dic")" -- target 1K using default dictionary file"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf fchk 1 t")" -- target 1K, write to emulator memory"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf fchk 1 d")" -- target 1K, write to file"); if (IfPm3Flash()) - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf fchk 1 m")" -- target 1K, use dictionary from flashmemory"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf fchk 1 m")" -- target 1K, use dictionary from flashmemory"); return PM3_SUCCESS; } /* @@ -1361,7 +1361,7 @@ static int CmdHF14AMfNested(const char *Cmd) { } uint64_t t2 = msclock() - t1; - PrintAndLogEx(SUCCESS, "Time to check " _YELLOW_("%zu") "known keys: %.0f seconds\n", ARRAYLEN(g_mifare_default_keys), (float)t2 / 1000.0); + PrintAndLogEx(SUCCESS, "Time to check " _YELLOW_("%zu") " known keys: %.0f seconds\n", ARRAYLEN(g_mifare_default_keys), (float)t2 / 1000.0); PrintAndLogEx(SUCCESS, "enter nested key recovery"); // nested sectors @@ -1408,7 +1408,7 @@ static int CmdHF14AMfNested(const char *Cmd) { } t1 = msclock() - t1; - PrintAndLogEx(SUCCESS, "time in nested: " _YELLOW_("%.0f") "seconds\n", (float)t1 / 1000.0); + PrintAndLogEx(SUCCESS, "time in nested: " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0); // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag? @@ -1576,7 +1576,7 @@ static int CmdHF14AMfNestedStatic(const char *Cmd) { } uint64_t t2 = msclock() - t1; - PrintAndLogEx(SUCCESS, "Time to check "_YELLOW_("%zu") "known keys: %.0f seconds\n", ARRAYLEN(g_mifare_default_keys), (float)t2 / 1000.0); + PrintAndLogEx(SUCCESS, "Time to check "_YELLOW_("%zu") " known keys: %.0f seconds\n", ARRAYLEN(g_mifare_default_keys), (float)t2 / 1000.0); PrintAndLogEx(SUCCESS, "enter static nested key recovery"); // nested sectors @@ -1613,7 +1613,7 @@ static int CmdHF14AMfNestedStatic(const char *Cmd) { } t1 = msclock() - t1; - PrintAndLogEx(SUCCESS, "time in static nested: " _YELLOW_("%.0f") "seconds\n", (float)t1 / 1000.0); + PrintAndLogEx(SUCCESS, "time in static nested: " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0); // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag? @@ -2060,7 +2060,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { PrintAndLogEx(INFO, _YELLOW_("======================= START KNOWN KEY ATTACK =======================")); } if (mfCheckKeys(FirstBlockOfSector(blockNo), keyType, true, 1, key, &key64) == PM3_SUCCESS) { - PrintAndLogEx(INFO, "target sector:%3u key type: %c -- using valid key [ " _YELLOW_("%s") "] (used for nested / hardnested attack)", + PrintAndLogEx(INFO, "target sector:%3u key type: %c -- using valid key [" _YELLOW_("%s") "] (used for nested / hardnested attack)", blockNo, keyType ? 'B' : 'A', sprint_hex(key, sizeof(key)) @@ -2095,13 +2095,13 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { know_target_key = true; blockNo = i; keyType = j; - PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "] (used for nested / hardnested attack)", + PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key ["_YELLOW_("%s") "] (used for nested / hardnested attack)", i, j ? 'B' : 'A', sprint_hex(key, sizeof(key)) ); } else { - PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]", + PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key ["_YELLOW_("%s") "]", i, j ? 'B' : 'A', sprint_hex(key, sizeof(key)) @@ -2141,7 +2141,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { num_to_bytes(g_mifare_default_keys[cnt], 6, keyBlock + cnt * 6); } key_cnt = ARRAYLEN(g_mifare_default_keys); - PrintAndLogEx(SUCCESS, "loaded " _GREEN_("%2d") "keys from hardcoded default array", key_cnt); + PrintAndLogEx(SUCCESS, "loaded " _GREEN_("%2d") " keys from hardcoded default array", key_cnt); } // Use the dictionary to find sector keys on the card @@ -2219,13 +2219,13 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { know_target_key = true; blockNo = i; keyType = j; - PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "] (used for nested / hardnested attack)", + PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [" _YELLOW_("%s") "] (used for nested / hardnested attack)", i, j ? 'B' : 'A', sprint_hex(tmp_key, sizeof(tmp_key)) ); } else { - PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]", + PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [" _YELLOW_("%s") "]", i, j ? 'B' : 'A', sprint_hex(tmp_key, sizeof(tmp_key)) @@ -2267,7 +2267,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { // Store the keys e_sector[blockNo].Key[keyType] = key64; e_sector[blockNo].foundKey[keyType] = 'S'; - PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "] (used for nested / hardnested attack)", + PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [" _YELLOW_("%s") "] (used for nested / hardnested attack)", blockNo, keyType ? 'B' : 'A', sprint_hex(key, sizeof(key)) @@ -2307,7 +2307,7 @@ noValidKeyFound: if (mfCheckKeys(FirstBlockOfSector(i), j, true, 1, tmp_key, &key64) == PM3_SUCCESS) { e_sector[i].Key[j] = bytes_to_num(tmp_key, 6); e_sector[i].foundKey[j] = 'R'; - PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]", + PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [" _YELLOW_("%s") "]", i, j ? 'B' : 'A', sprint_hex(tmp_key, sizeof(tmp_key)) @@ -2349,7 +2349,7 @@ noValidKeyFound: e_sector[current_sector_i].foundKey[current_key_type_i] = 'A'; e_sector[current_sector_i].Key[current_key_type_i] = key64; num_to_bytes(key64, 6, tmp_key); - PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]", + PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [" _YELLOW_("%s") "]", current_sector_i, current_key_type_i ? 'B' : 'A', sprint_hex(tmp_key, sizeof(tmp_key)) @@ -2449,7 +2449,7 @@ tryHardnested: // If the nested attack fails then we try the hardnested attack } // Check if the key was found if (e_sector[current_sector_i].foundKey[current_key_type_i]) { - PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]", + PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [" _YELLOW_("%s") "]", current_sector_i, current_key_type_i ? 'B' : 'A', sprint_hex(tmp_key, sizeof(tmp_key)) @@ -2522,7 +2522,7 @@ all_found: // Generate and show statistics t1 = msclock() - t1; - PrintAndLogEx(INFO, "autopwn execution time: " _YELLOW_("%.0f") "seconds", (float)t1 / 1000.0); + PrintAndLogEx(INFO, "autopwn execution time: " _YELLOW_("%.0f") " seconds", (float)t1 / 1000.0); free(dump); free(e_sector); @@ -3565,7 +3565,7 @@ void printKeyTableEx(uint8_t sectorscnt, sector_t *e_sector, uint8_t start_secto snprintf(strB, sizeof(strB), "%012" PRIx64, e_sector[i].Key[1]); if (e_sector[i].foundKey[0] > 1) { - PrintAndLogEx(SUCCESS, "| "_YELLOW_("%03d")"| " _GREEN_("%s")" | " _YELLOW_("%c")"| " _GREEN_("%s")" | " _YELLOW_("%c")"|" + PrintAndLogEx(SUCCESS, "| "_YELLOW_("%03d")" | " _GREEN_("%s")" | " _YELLOW_("%c")" | " _GREEN_("%s")" | " _YELLOW_("%c")" |" , i , strA, e_sector[i].foundKey[0] , strB, e_sector[i].foundKey[1] @@ -3577,7 +3577,7 @@ void printKeyTableEx(uint8_t sectorscnt, sector_t *e_sector, uint8_t start_secto if (start_sector == 0) s = i; - PrintAndLogEx(SUCCESS, "| "_YELLOW_("%03d")"| " _GREEN_("%s")" | " _YELLOW_("%d")"| " _GREEN_("%s")" | " _YELLOW_("%d")"|" + PrintAndLogEx(SUCCESS, "| "_YELLOW_("%03d")" | " _GREEN_("%s")" | " _YELLOW_("%d")" | " _GREEN_("%s")" | " _YELLOW_("%d")" |" , s , strA, e_sector[i].foundKey[0] , strB, e_sector[i].foundKey[1] @@ -4520,7 +4520,7 @@ static int CmdHF14AMfice(const char *Cmd) { strcpy(filename, fptr); } - PrintAndLogEx(NORMAL, "Collecting "_YELLOW_("%u")"nonces \n", limit); + PrintAndLogEx(NORMAL, "Collecting "_YELLOW_("%u")" nonces \n", limit); if ((fnonces = fopen(filename, "wb")) == NULL) { PrintAndLogEx(WARNING, "Could not create file " _YELLOW_("%s"), filename); diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index d02c1ddfa..287b13523 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -16,21 +16,21 @@ #include "cmdparser.h" // command_t #include "comms.h" #include "ui.h" -#include "cmdhw.h" #include "cmdhf14a.h" -#include "mbedtls/des.h" #include "mbedtls/aes.h" -#include "../crypto/libpcrypto.h" +#include "crypto/libpcrypto.h" #include "protocols.h" -#include "mifare.h" // desfire raw command options #include "cmdtrace.h" -#include "cliparser/cliparser.h" +#include "cliparser.h" #include "emv/apduinfo.h" // APDU manipulation / errorcodes #include "emv/emvcore.h" // APDU logging #include "util_posix.h" // msleep -#include "mifare/mifare4.h" // MIFARE Authenticate / MAC #include "mifare/desfire_crypto.h" #include "crapto1/crapto1.h" +#include "fileutils.h" + +#define MAX_KEY_LEN 24 +#define MAX_KEYS_LIST_LEN 1024 struct desfire_key defaultkey = {0}; static desfirekey_t sessionkey = &defaultkey; @@ -175,17 +175,11 @@ static char *cluster_to_text(uint8_t cluster) { case CL_ADMIN: return "card administration"; case CL_MISC1: - return "miscellaneous applications"; case CL_MISC2: - return "miscellaneous applications"; case CL_MISC3: - return "miscellaneous applications"; case CL_MISC4: - return "miscellaneous applications"; case CL_MISC5: - return "miscellaneous applications"; case CL_MISC6: - return "miscellaneous applications"; case CL_MISC7: return "miscellaneous applications"; case CL_AIRLINES: @@ -219,7 +213,6 @@ static char *cluster_to_text(uint8_t cluster) { case CL_CITYCARD: return "city card services"; case CL_ACCESS_CONTROL_1: - return "access control & security"; case CL_ACCESS_CONTROL_2: return "access control & security"; case CL_VIGIK: @@ -289,19 +282,12 @@ static char *cluster_to_text(uint8_t cluster) { case CL_MAIL: return "mail"; case CL_AMISC: - return "miscellaneous applications"; case CL_AMISC1: - return "miscellaneous applications"; case CL_AMISC2: - return "miscellaneous applications"; case CL_AMISC3: - return "miscellaneous applications"; case CL_AMISC4: - return "miscellaneous applications"; case CL_AMISC5: - return "miscellaneous applications"; case CL_AMISC6: - return "miscellaneous applications"; case CL_AMISC7: return "miscellaneous applications"; default: @@ -311,7 +297,7 @@ static char *cluster_to_text(uint8_t cluster) { } typedef enum { - UNKNOWN = 0, + DESFIRE_UNKNOWN = 0, DESFIRE_MF3ICD40, DESFIRE_EV1, DESFIRE_EV2, @@ -344,9 +330,9 @@ static char *getCardSizeStr(uint8_t fsize) { // is LSB set? if (fsize & 1) - sprintf(retStr, "0x%02X ( " _YELLOW_("%d - %d bytes") ")", fsize, usize, lsize); + sprintf(retStr, "0x%02X (" _YELLOW_("%d - %d bytes") ")", fsize, usize, lsize); else - sprintf(retStr, "0x%02X ( " _YELLOW_("%d bytes") ")", fsize, lsize); + sprintf(retStr, "0x%02X (" _YELLOW_("%d bytes") ")", fsize, lsize); return buf; } @@ -356,14 +342,14 @@ static char *getProtocolStr(uint8_t id, bool hw) { char *retStr = buf; if (id == 0x04) { - sprintf(retStr, "0x%02X ( " _YELLOW_("ISO 14443-3 MIFARE, 14443-4") ")", id); + sprintf(retStr, "0x%02X (" _YELLOW_("ISO 14443-3 MIFARE, 14443-4") ")", id); } else if (id == 0x05) { if (hw) - sprintf(retStr, "0x%02X ( " _YELLOW_("ISO 14443-2, 14443-3") ")", id); + sprintf(retStr, "0x%02X (" _YELLOW_("ISO 14443-2, 14443-3") ")", id); else - sprintf(retStr, "0x%02X ( " _YELLOW_("ISO 14443-3, 14443-4") ")", id); + sprintf(retStr, "0x%02X (" _YELLOW_("ISO 14443-3, 14443-4") ")", id); } else { - sprintf(retStr, "0x%02X ( " _YELLOW_("Unknown") ")", id); + sprintf(retStr, "0x%02X (" _YELLOW_("Unknown") ")", id); } return buf; } @@ -374,17 +360,17 @@ static char *getVersionStr(uint8_t major, uint8_t minor) { char *retStr = buf; if (major == 0x00) - sprintf(retStr, "%x.%x ( " _YELLOW_("DESFire MF3ICD40") ")", major, minor); + sprintf(retStr, "%x.%x (" _YELLOW_("DESFire MF3ICD40") ")", major, minor); else if (major == 0x01 && minor == 0x00) - sprintf(retStr, "%x.%x ( " _YELLOW_("DESFire EV1") ")", major, minor); + sprintf(retStr, "%x.%x (" _YELLOW_("DESFire EV1") ")", major, minor); else if (major == 0x12 && minor == 0x00) - sprintf(retStr, "%x.%x ( " _YELLOW_("DESFire EV2") ")", major, minor); + sprintf(retStr, "%x.%x (" _YELLOW_("DESFire EV2") ")", major, minor); // else if (major == 0x13 && minor == 0x00) -// sprintf(retStr, "%x.%x ( " _YELLOW_("DESFire EV3") ")", major, minor); +// sprintf(retStr, "%x.%x (" _YELLOW_("DESFire EV3") ")", major, minor); else if (major == 0x30 && minor == 0x00) - sprintf(retStr, "%x.%x ( " _YELLOW_("DESFire Light") ")", major, minor); + sprintf(retStr, "%x.%x (" _YELLOW_("DESFire Light") ")", major, minor); else - sprintf(retStr, "%x.%x ( " _YELLOW_("Unknown") ")", major, minor); + sprintf(retStr, "%x.%x (" _YELLOW_("Unknown") ")", major, minor); return buf; } @@ -653,7 +639,7 @@ static nxp_cardtype_t getCardType(uint8_t major, uint8_t minor) { if (major == 0x11 && minor == 0x00) return PLUS_EV1; - return UNKNOWN; + return DESFIRE_UNKNOWN; } int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload, bool defaultkey) { @@ -736,8 +722,7 @@ int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload, sAPDU apdu = {0x90, subcommand, 0x00, 0x00, 0x01, data}; int res = send_desfire_cmd(&apdu, false, recv_data, &recv_len, &sw, 0, false); if (res != PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "Sending auth command %02X " _RED_("failed"), subcommand); - return PM3_ESOFT; + return 1; } } else if (payload->mode == MFDES_AUTH_PICC) { /*cmd[0] = AUTHENTICATE; @@ -747,13 +732,11 @@ int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload, } if (!recv_len) { - PrintAndLogEx(ERR, "Authentication failed. Card timeout."); - return PM3_ESOFT; + return 2; } if (sw != status(MFDES_ADDITIONAL_FRAME)) { - PrintAndLogEx(ERR, "Authentication failed. Invalid key number."); - return PM3_ESOFT; + return 3; } int expectedlen = 8; @@ -762,8 +745,7 @@ int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload, } if (recv_len != expectedlen) { - PrintAndLogEx(ERR, "Authentication failed. Length of answer %d doesn't match algo length %d.", recv_len, expectedlen); - return PM3_ESOFT; + return 4; } int rndlen = recv_len; @@ -778,8 +760,7 @@ int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload, // Part 3 if (payload->algo == MFDES_ALGO_AES) { if (mbedtls_aes_setkey_dec(&ctx, key->data, 128) != 0) { - PrintAndLogEx(ERR, "mbedtls_aes_setkey_dec failed"); - return PM3_ESOFT; + return 5; } mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, rndlen, IV, encRndB, RndB); } else if (payload->algo == MFDES_ALGO_DES) @@ -848,8 +829,7 @@ int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload, } if (payload->algo == MFDES_ALGO_AES) { if (mbedtls_aes_setkey_enc(&ctx, key->data, 128) != 0) { - PrintAndLogEx(ERR, "mbedtls_aes_setkey_enc failed"); - return PM3_ESOFT; + return 6; } mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, 32, IV, tmp, both); if (g_debugMode > 1) { @@ -866,8 +846,7 @@ int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload, sAPDU apdu = {0x90, MFDES_ADDITIONAL_FRAME, 0x00, 0x00, bothlen, both}; int res = send_desfire_cmd(&apdu, false, recv_data, &recv_len, &sw, 0, false); if (res != PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "Sending auth command %02X " _RED_("failed"), subcommand); - return PM3_ESOFT; + return 7; } } else { /*cmd[0] = ADDITIONAL_FRAME; @@ -881,14 +860,12 @@ int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload, } if (!recv_len) { - PrintAndLogEx(ERR, "Authentication failed. Card timeout."); - return PM3_ESOFT; + return 8; } if (payload->mode != MFDES_AUTH_PICC) { if (sw != status(MFDES_S_OPERATION_OK)) { - PrintAndLogEx(ERR, "Authentication failed."); - return PM3_ESOFT; + return 9; } } else { /*if (resp[1] != 0x00) { @@ -915,8 +892,7 @@ int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload, tdes_nxp_receive(encRndA, encRndA, rndlen, key->data, IV, 3); } else if (payload->mode == MFDES_AUTH_AES) { if (mbedtls_aes_setkey_dec(&ctx, key->data, 128) != 0) { - PrintAndLogEx(ERR, "mbedtls_aes_setkey_dec failed"); - return PM3_ESOFT; + return 10; } mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, rndlen, IV, encRndA, encRndA); } @@ -924,12 +900,11 @@ int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload, rol(RndA, rndlen); for (int x = 0; x < rndlen; x++) { if (RndA[x] != encRndA[x]) { - PrintAndLogEx(ERR, "Authentication failed. Cannot verify Session Key."); if (g_debugMode > 1) { PrintAndLogEx(INFO, "Expected_RndA : %s", sprint_hex(RndA, rndlen)); PrintAndLogEx(INFO, "Generated_RndA : %s", sprint_hex(encRndA, rndlen)); } - return PM3_ESOFT; + return 11; } } @@ -938,6 +913,45 @@ int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload, return PM3_SUCCESS; } +void AuthToError(int error) { + switch (error) { + case 1: + PrintAndLogEx(SUCCESS, "Sending auth command failed"); + break; + case 2: + PrintAndLogEx(ERR, "Authentication failed. No data received"); + break; + case 3: + PrintAndLogEx(ERR, "Authentication failed. Invalid key number."); + break; + case 4: + PrintAndLogEx(ERR, "Authentication failed. Length of answer %d doesn't match algo length %d."); + break; + case 5: + PrintAndLogEx(ERR, "mbedtls_aes_setkey_dec failed"); + break; + case 6: + PrintAndLogEx(ERR, "mbedtls_aes_setkey_enc failed"); + break; + case 7: + PrintAndLogEx(SUCCESS, "Sending auth command failed"); + break; + case 8: + PrintAndLogEx(ERR, "Authentication failed. Card timeout."); + break; + case 9: + PrintAndLogEx(ERR, "Authentication failed."); + break; + case 10: + PrintAndLogEx(ERR, "mbedtls_aes_setkey_dec failed"); + break; + case 11: + PrintAndLogEx(ERR, "Authentication failed. Cannot verify Session Key."); + break; + default: + break; + } +} // -- test if card supports 0x0A static int test_desfire_authenticate() { uint8_t data[] = {0x00}; @@ -1464,7 +1478,7 @@ static int handler_desfire_writedata(mfdes_data_t *data, MFDES_FILE_TYPE_T type) if (data->fileno > 0x1F) return PM3_EINVARG; int datatowrite = le24toh(data->length); int offset = le24toh(data->offset); - int datasize = 0; + int datasize; int pos = 0; int recvlen = 0; int res = PM3_SUCCESS; @@ -1477,8 +1491,10 @@ static int handler_desfire_writedata(mfdes_data_t *data, MFDES_FILE_TYPE_T type) if (type == MFDES_RECORD_FILE) apdu.INS = MFDES_WRITE_RECORD; while (datatowrite > 0) { - if (datatowrite > 52) datasize = 52; - else datasize = datatowrite; + if (datatowrite > 52) + datasize = 52; + else + datasize = datatowrite; tmp[1] = offset & 0xFF; tmp[2] = (offset >> 8) & 0xFF; @@ -1676,7 +1692,7 @@ int getKeySettings(uint8_t *aid) { } // Authentication tests - int res = test_desfire_authenticate(); + res = test_desfire_authenticate(); if (res == PM3_ETIMEOUT) return res; PrintAndLogEx(SUCCESS, " [0x0A] Authenticate : %s", (res == PM3_SUCCESS) ? _YELLOW_("YES") : "NO"); @@ -1824,29 +1840,29 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { swap16(fid); if (aidlength != 3) { - PrintAndLogEx(ERR, "AID must have 3 bytes length."); + PrintAndLogEx(ERR, "AID must have 3 bytes length"); return PM3_EINVARG; } if (fidlength != 2) { - PrintAndLogEx(ERR, "FID must have 2 bytes length."); - return PM3_EINVARG; - } - bool usefid = true; - if (fidlength == 0) usefid = false; - - if (keylen1 != 1) { - PrintAndLogEx(ERR, "Keysetting1 must have 1 byte length."); + PrintAndLogEx(ERR, "FID must have 2 bytes length"); return PM3_EINVARG; } + bool usefid = (fidlength != 0); + if (keylen1 != 1) { - PrintAndLogEx(ERR, "Keysetting2 must have 1 byte length."); + PrintAndLogEx(ERR, "Keysetting1 must have 1 byte length"); + return PM3_EINVARG; + } + + if (keylen2 != 1) { + PrintAndLogEx(ERR, "Keysetting2 must have 1 byte length"); return PM3_EINVARG; } if (namelen > 16) { - PrintAndLogEx(ERR, "Name has a max. of 16 bytes length."); + PrintAndLogEx(ERR, "Name has a max. of 16 bytes length"); return PM3_EINVARG; } bool usename = true; @@ -1860,7 +1876,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { uint8_t keysetting2=0xEE;*/ if (memcmp(aid, "\x00\x00\x00", 3) == 0) { - PrintAndLogEx(WARNING, _RED_(" Creating root aid 000000 is forbidden.")); + PrintAndLogEx(WARNING, _RED_(" Creating root aid 000000 is forbidden")); return PM3_ESOFT; } @@ -1868,12 +1884,17 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { memcpy(aidhdr.aid, aid, sizeof(aid)); aidhdr.keysetting1 = keysetting1; aidhdr.keysetting2 = keysetting2; + if (usefid) memcpy(aidhdr.fid, fid, sizeof(fid)); + if (usename) memcpy(aidhdr.name, name, sizeof(name)); uint8_t rootaid[3] = {0x00, 0x00, 0x00}; int res = handler_desfire_select_application(rootaid); - if (res != PM3_SUCCESS) { DropField(); return res; } + if (res != PM3_SUCCESS) { + DropField(); + return res; + } res = handler_desfire_createapp(&aidhdr, usename, usefid); DropField(); @@ -1931,12 +1952,14 @@ static int CmdHF14ADesClearRecordFile(const char *Cmd) { arg_param_end }; CLIExecWithReturn(Cmd, argtable, false); - uint8_t fileno; int aidlength = 0; uint8_t aid[3] = {0}; CLIGetHexWithReturn(1, aid, &aidlength); + int filenolen = 0; - CLIGetHexWithReturn(2, &fileno, &filenolen); + uint8_t fileno[1] = {0}; + CLIGetHexWithReturn(2, fileno, &filenolen); + int fidlength = 0; uint8_t fid[2] = {0}; CLIParamHexToBuf(arg_get_str(3), fid, 2, &fidlength); @@ -1947,7 +1970,7 @@ static int CmdHF14ADesClearRecordFile(const char *Cmd) { return PM3_EINVARG; } - if (fileno > 0x1F) { + if (fileno[0] > 0x1F) { PrintAndLogEx(ERR, "Fileno must be lower 0x1F."); return PM3_EINVARG; } @@ -1965,10 +1988,12 @@ static int CmdHF14ADesClearRecordFile(const char *Cmd) { return res; } - res = handler_desfire_clearrecordfile(fileno); + res = handler_desfire_clearrecordfile(fileno[0]); if (res == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "Successfully cleared record file."); - } else PrintAndLogEx(ERR, "Error on deleting file : %d", res); + } else { + PrintAndLogEx(ERR, "Error on deleting file : %d", res); + } DropField(); return res; } @@ -1987,12 +2012,14 @@ static int CmdHF14ADesDeleteFile(const char *Cmd) { arg_param_end }; CLIExecWithReturn(Cmd, argtable, false); - uint8_t fileno; int aidlength = 0; uint8_t aid[3] = {0}; CLIGetHexWithReturn(1, aid, &aidlength); + int filenolen = 0; - CLIGetHexWithReturn(2, &fileno, &filenolen); + uint8_t fileno[1] = {0}; + CLIGetHexWithReturn(2, fileno, &filenolen); + int fidlength = 0; uint8_t fid[2] = {0}; CLIParamHexToBuf(arg_get_str(3), fid, 2, &fidlength); @@ -2003,7 +2030,7 @@ static int CmdHF14ADesDeleteFile(const char *Cmd) { return PM3_EINVARG; } - if (fileno > 0x1F) { + if (fileno[0] > 0x1F) { PrintAndLogEx(ERR, "Fileno must be lower 0x1F."); return PM3_EINVARG; } @@ -2021,10 +2048,12 @@ static int CmdHF14ADesDeleteFile(const char *Cmd) { return res; } - res = handler_desfire_deletefile(fileno); + res = handler_desfire_deletefile(fileno[0]); if (res == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "Successfully deleted file.."); - } else PrintAndLogEx(ERR, "Error on deleting file : %d", res); + } else { + PrintAndLogEx(ERR, "Error on deleting file : %d", res); + } DropField(); return res; } @@ -2048,22 +2077,27 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { arg_param_end }; CLIExecWithReturn(Cmd, argtable, false); - uint8_t fileno; int aidlength = 0; uint8_t aid[3] = {0}; CLIGetHexWithReturn(1, aid, &aidlength); + int filenolen = 0; - CLIGetHexWithReturn(2, &fileno, &filenolen); + uint8_t fileno[1] = {0}; + CLIGetHexWithReturn(2, fileno, &filenolen); + int fidlength = 0; uint8_t fid[2] = {0}; CLIParamHexToBuf(arg_get_str(3), fid, 2, &fidlength); + uint8_t comset = arg_get_int(4); int arlength = 0; uint8_t ar[2] = {0}; CLIGetHexWithReturn(5, ar, &arlength); + int fsizelen = 0; uint8_t filesize[3] = {0}; CLIGetHexWithReturn(6, filesize, &fsizelen); + bool isbackup = arg_get_lit(7); CLIParserFree(); @@ -2076,7 +2110,7 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { return PM3_EINVARG; } - if (fileno > 0x1F) { + if (fileno[0] > 0x1F) { PrintAndLogEx(ERR, "File number range is invalid (0x00-0x1F)."); return PM3_EINVARG; } @@ -2116,7 +2150,7 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { mfdes_file_t ft; memcpy(ft.fid, fid, 2); memcpy(ft.filesize, filesize, 3); - ft.fileno = fileno; + ft.fileno = fileno[0]; ft.comset = comset; memcpy(ft.access_rights, ar, 2); @@ -2146,21 +2180,23 @@ static int CmdHF14ADesGetValueData(const char *Cmd) { arg_param_end }; CLIExecWithReturn(Cmd, argtable, false); - uint8_t fileno; + int aidlength = 0; uint8_t aid[3] = {0}; CLIGetHexWithReturn(1, aid, &aidlength); + int filenolen = 0; - CLIGetHexWithReturn(2, &fileno, &filenolen); + uint8_t fileno[1] = {0}; + CLIGetHexWithReturn(2, fileno, &filenolen); CLIParserFree(); if (filenolen != 1) { - PrintAndLogEx(ERR, "File number is missing."); + PrintAndLogEx(ERR, "File number is missing"); return PM3_EINVARG; } - if (fileno > 0x1F) { - PrintAndLogEx(ERR, "File number range is invalid (0x00-0x1F)."); + if (fileno[0] > 0x1F) { + PrintAndLogEx(ERR, "File number range is invalid (0x00-0x1F)"); return PM3_EINVARG; } @@ -2179,11 +2215,12 @@ static int CmdHF14ADesGetValueData(const char *Cmd) { return res; } mfdes_value_t value; - value.fileno = fileno; + value.fileno = fileno[0]; + int len = 0; res = handler_desfire_getvalue(&value, &len); if (res == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "Successfully read value from File %d:", fileno); + PrintAndLogEx(SUCCESS, "Successfully read value from File %u:", fileno); PrintAndLogEx(NORMAL, "\nOffset | Data | Ascii"); PrintAndLogEx(NORMAL, "----------------------------------------------------------------------------"); for (int i = 0; i < len; i += 16) { @@ -2214,38 +2251,42 @@ static int CmdHF14ADesReadData(const char *Cmd) { arg_param_end }; CLIExecWithReturn(Cmd, argtable, false); - uint8_t fileno; int aidlength = 0; uint8_t aid[3] = {0}; CLIGetHexWithReturn(1, aid, &aidlength); + int filenolen = 0; - CLIGetHexWithReturn(2, &fileno, &filenolen); + uint8_t fileno[1] = {0}; + CLIGetHexWithReturn(2, fileno, &filenolen); + int offsetlength = 0; uint8_t offset[3] = {0}; CLIParamHexToBuf(arg_get_str(3), offset, 3, &offsetlength); + int flength = 0; uint8_t filesize[3] = {0}; CLIParamHexToBuf(arg_get_str(4), filesize, 3, &flength); + int type = arg_get_int(5); CLIParserFree(); if (type > 1) { - PrintAndLogEx(ERR, "Invalid file type (0=Standard/Backup, 1=Record)."); + PrintAndLogEx(ERR, "Invalid file type (0=Standard/Backup, 1=Record)"); return PM3_EINVARG; } if (offsetlength != 3 && offsetlength != 0) { - PrintAndLogEx(ERR, "Offset needs 3 hex bytes."); + PrintAndLogEx(ERR, "Offset needs 3 hex bytes"); return PM3_EINVARG; } if (filenolen != 1) { - PrintAndLogEx(ERR, "File number is missing."); + PrintAndLogEx(ERR, "File number is missing"); return PM3_EINVARG; } - if (fileno > 0x1F) { - PrintAndLogEx(ERR, "File number range is invalid (0x00-0x1F)."); + if (fileno[0] > 0x1F) { + PrintAndLogEx(ERR, "File number range is invalid (0x00-0x1F)"); return PM3_EINVARG; } @@ -2269,15 +2310,18 @@ static int CmdHF14ADesReadData(const char *Cmd) { mfdes_data_t ft; memcpy(ft.offset, offset, 3); memcpy(ft.length, filesize, 3); - ft.fileno = fileno; + ft.fileno = fileno[0]; + int bytestoread = le24toh(filesize); + if (bytestoread == 0) bytestoread = 0xFFFFFF; - uint8_t *data = (uint8_t *)malloc(bytestoread); + + uint8_t *data = (uint8_t *)calloc(bytestoread, sizeof(uint8_t)); if (data != NULL) { ft.data = data; res = handler_desfire_readdata(&ft, type); if (res == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "Successfully read data from File %d:", ft.fileno); + PrintAndLogEx(SUCCESS, "Successfully read data from file %d:", ft.fileno); PrintAndLogEx(NORMAL, "\nOffset | Data | Ascii"); PrintAndLogEx(NORMAL, "----------------------------------------------------------------------------"); int len = le24toh(ft.length); @@ -2308,15 +2352,22 @@ static int CmdHF14ADesChangeValue(const char *Cmd) { arg_int0("mM", "mode", "", "Mode (0=Credit, 1=LimitedCredit, 2=Debit)"), arg_param_end }; + mfdes_value_t value; CLIExecWithReturn(Cmd, argtable, false); + int aidlength = 0; uint8_t aid[3] = {0}; CLIGetHexWithReturn(1, aid, &aidlength); + int filenolen = 0; - CLIGetHexWithReturn(2, &value.fileno, &filenolen); + uint8_t fileno[1] = {0}; + CLIGetHexWithReturn(2, fileno, &filenolen); + value.fileno = fileno[0]; + int vlength = 0x0; CLIParamHexToBuf(arg_get_str(3), value.value, 4, &vlength); + int mode = arg_get_int(4); CLIParserFree(); swap24(aid); @@ -2378,6 +2429,7 @@ static int CmdHF14ADesChangeValue(const char *Cmd) { static int CmdHF14ADesWriteData(const char *Cmd) { + CLIParserInit("hf mfdes writedata", "Write data to File", "Usage:" @@ -2389,56 +2441,66 @@ static int CmdHF14ADesWriteData(const char *Cmd) { arg_strx0("aA", "aid", "", "AID for file (3 hex bytes, big endian)"), arg_strx0("nN", "fileno", "", "File Number (1 hex byte, 0x00 - 0x1F)"), arg_strx0("oO", "offset", "", "File Offset (3 hex bytes, big endian), optional"), - arg_strx0("dD", "data", "", "Data to write (hex bytes, 0xFFFFFF bytes max.)"), + arg_strx0("dD", "data", "", "Data to write (hex bytes, 0xFFFF bytes max.)"), arg_int0("type", "type", "", "File Type (0=Standard/Backup, 1=Record)"), arg_param_end }; + CLIExecWithReturn(Cmd, argtable, false); - uint8_t fileno; + int aidlength = 0; uint8_t aid[3] = {0}; CLIGetHexWithReturn(1, aid, &aidlength); + int filenolen = 0; - CLIGetHexWithReturn(2, &fileno, &filenolen); + uint8_t fileno[1] = {0}; + CLIGetHexWithReturn(2, fileno, &filenolen); + int offsetlength = 0; uint8_t offset[3] = {0}; CLIParamHexToBuf(arg_get_str(3), offset, 3, &offsetlength); - int dlength = 0xFFFFFF; - uint8_t *data = (uint8_t *)malloc(0xFFFFFF); - memset(data, 0x0, 0xFFFFFF); - CLIParamHexToBuf(arg_get_str(4), data, 0xFFFFFF, &dlength); + + int dlength = 0xFFFF; + uint8_t *data = (uint8_t *)calloc(0xFFFF, sizeof(uint8_t)); + if (data == NULL) { + PrintAndLogEx(ERR, "failed to allocate memory"); + return PM3_EMALLOC; + } + CLIParamHexToBuf(arg_get_str(4), data, 0xFFFF, &dlength); + int type = arg_get_int(5); + CLIParserFree(); swap24(aid); swap24(offset); - if (type > 1) { - PrintAndLogEx(ERR, "Unknown type (0=Standard/Backup, 1=Record)."); + if (type < 0 || type > 1) { + PrintAndLogEx(ERR, "Unknown type (0=Standard/Backup, 1=Record)"); if (data) free(data); return PM3_EINVARG; } if (dlength == 0) { - PrintAndLogEx(ERR, "Data needs some hex bytes to write."); + PrintAndLogEx(ERR, "Data needs some hex bytes to write"); if (data) free(data); return PM3_EINVARG; } if (offsetlength != 3 && offsetlength != 0) { - PrintAndLogEx(ERR, "Offset needs 3 hex bytes."); + PrintAndLogEx(ERR, "Offset needs 3 hex bytes"); if (data) free(data); return PM3_EINVARG; } if (filenolen != 1) { - PrintAndLogEx(ERR, "File number is missing."); + PrintAndLogEx(ERR, "File number is missing"); if (data) free(data); return PM3_EINVARG; } - if (fileno > 0x1F) { - PrintAndLogEx(ERR, "File number range is invalid (0x00-0x1F)."); + if (fileno[0] > 0x1F) { + PrintAndLogEx(ERR, "File number range is invalid (0x00-0x1F)"); if (data) free(data); return PM3_EINVARG; } @@ -2452,21 +2514,23 @@ static int CmdHF14ADesWriteData(const char *Cmd) { int res = handler_desfire_select_application(aid); if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Couldn't select aid."); + PrintAndLogEx(ERR, "Couldn't select aid"); DropField(); if (data) free(data); return res; } mfdes_data_t ft; + memcpy(ft.offset, offset, 3); htole24(dlength, ft.length); - ft.fileno = fileno; + ft.fileno = fileno[0]; + if (data != NULL) { ft.data = data; res = handler_desfire_writedata(&ft, type); if (res == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "Successfully wrote data."); + PrintAndLogEx(SUCCESS, "Successfully wrote data"); } else { PrintAndLogEx(ERR, "Couldn't read data. Error %d", res); } @@ -2497,25 +2561,31 @@ static int CmdHF14ADesCreateRecordFile(const char *Cmd) { arg_param_end }; CLIExecWithReturn(Cmd, argtable, false); - uint8_t fileno; int aidlength = 0; uint8_t aid[3] = {0}; CLIGetHexWithReturn(1, aid, &aidlength); + int filenolen = 0; - CLIGetHexWithReturn(2, &fileno, &filenolen); + uint8_t fileno[1] = {0}; + CLIGetHexWithReturn(2, fileno, &filenolen); + int fidlength = 0; uint8_t fid[2] = {0}; CLIParamHexToBuf(arg_get_str(3), fid, 2, &fidlength); + uint8_t comset = arg_get_int(4); int arlength = 0; uint8_t ar[2] = {0}; CLIGetHexWithReturn(5, ar, &arlength); + int rsizelen = 0; uint8_t recordsize[3] = {0}; CLIGetHexWithReturn(6, recordsize, &rsizelen); + int msizelen = 0; uint8_t maxnumrecords[3] = {0}; CLIGetHexWithReturn(7, maxnumrecords, &msizelen); + bool cyclic = arg_get_lit(8); CLIParserFree(); @@ -2539,7 +2609,7 @@ static int CmdHF14ADesCreateRecordFile(const char *Cmd) { return PM3_EINVARG; } - if (fileno > 0x1F) { + if (fileno[0] > 0x1F) { PrintAndLogEx(ERR, "File number range is invalid (0x00-0x1F)."); return PM3_EINVARG; } @@ -2578,7 +2648,7 @@ static int CmdHF14ADesCreateRecordFile(const char *Cmd) { } mfdes_linear_t ft; - ft.fileno = fileno; + ft.fileno = fileno[0]; memcpy(ft.fid, fid, 2); ft.comset = comset; memcpy(ft.access_rights, ar, 2); @@ -2616,25 +2686,31 @@ static int CmdHF14ADesCreateValueFile(const char *Cmd) { arg_param_end }; CLIExecWithReturn(Cmd, argtable, false); - uint8_t fileno; int aidlength = 0; uint8_t aid[3] = {0}; CLIGetHexWithReturn(1, aid, &aidlength); + int filenolen = 0; - CLIGetHexWithReturn(2, &fileno, &filenolen); + uint8_t fileno[1] = {0}; + CLIGetHexWithReturn(2, fileno, &filenolen); + uint8_t comset = arg_get_int(3); int arlength = 0; uint8_t ar[2] = {0}; CLIGetHexWithReturn(4, ar, &arlength); + int lllen = 0; uint8_t lowerlimit[4] = {0}; CLIGetHexWithReturn(5, lowerlimit, &lllen); + int ullen = 0; uint8_t upperlimit[4] = {0}; CLIGetHexWithReturn(6, upperlimit, &ullen); + int vllen = 0; uint8_t value[4] = {0}; CLIGetHexWithReturn(7, value, &vllen); + int limitedlen = 0; uint8_t limited = 0; CLIGetHexWithReturn(8, &limited, &limitedlen); @@ -2647,37 +2723,37 @@ static int CmdHF14ADesCreateValueFile(const char *Cmd) { swap32(value); if (filenolen != 1) { - PrintAndLogEx(ERR, "File number is missing."); + PrintAndLogEx(ERR, "File number is missing"); return PM3_EINVARG; } - if (fileno > 0x1F) { - PrintAndLogEx(ERR, "File number range is invalid (0x00-0x1F)."); + if (fileno[0] > 0x1F) { + PrintAndLogEx(ERR, "File number range is invalid (0x00-0x1F)"); return PM3_EINVARG; } if (comset != 0 && comset != 1 && comset != 3) { - PrintAndLogEx(ERR, "Communication setting must be either 0=Plain, 1=Plain+MAC or 3=Encrypt."); + PrintAndLogEx(ERR, "Communication setting must be either 0=Plain, 1=Plain+MAC or 3=Encrypt"); return PM3_EINVARG; } if (arlength != 2) { - PrintAndLogEx(ERR, "Access rights must have 2 hex bytes length."); + PrintAndLogEx(ERR, "Access rights must have 2 hex bytes length"); return PM3_EINVARG; } if (lllen != 4) { - PrintAndLogEx(ERR, "Lower limit must have 4 hex bytes length."); + PrintAndLogEx(ERR, "Lower limit must have 4 hex bytes length"); return PM3_EINVARG; } if (ullen != 4) { - PrintAndLogEx(ERR, "Upper limit must have 4 hex bytes length."); + PrintAndLogEx(ERR, "Upper limit must have 4 hex bytes length"); return PM3_EINVARG; } if (vllen != 4) { - PrintAndLogEx(ERR, "Value must have 4 hex bytes length."); + PrintAndLogEx(ERR, "Value must have 4 hex bytes length"); return PM3_EINVARG; } @@ -2699,7 +2775,7 @@ static int CmdHF14ADesCreateValueFile(const char *Cmd) { } mfdes_value_file_t ft; - ft.fileno = fileno; + ft.fileno = fileno[0]; ft.comset = comset; memcpy(ft.access_rights, ar, 2); memcpy(ft.lowerlimit, lowerlimit, 4); @@ -2737,7 +2813,7 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { CLIParserFree(); if ((keylen < 8) || (keylen > 8)) { - PrintAndLogEx(ERR, "Specified key must have 8 bytes length."); + PrintAndLogEx(ERR, "Specified key must have 8 bytes length"); return PM3_EINVARG; } @@ -2752,6 +2828,7 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { payload.mode = MFDES_AUTH_PICC; payload.algo = MFDES_ALGO_DES; payload.keyno = 0; + SendCommandNG(CMD_HF_DESFIRE_AUTH1, (uint8_t *)&payload, sizeof(payload)); PacketResponseNG resp; @@ -2767,11 +2844,14 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { uint8_t flags; uint8_t datalen; uint8_t datain[FRAME_PAYLOAD_SIZE]; - } PACKED payload; - payload.datain[0] = 0xFC; - payload.flags = NONE; - payload.datalen = 1; - SendCommandNG(CMD_HF_DESFIRE_COMMAND, (uint8_t *)&payload, sizeof(payload)); + } PACKED payload_raw; + + payload_raw.datain[0] = 0xFC; + payload_raw.flags = NONE; + payload_raw.datalen = 1; + + SendCommandNG(CMD_HF_DESFIRE_COMMAND, (uint8_t *)&payload_raw, sizeof(payload_raw)); + if (!WaitForResponseTimeout(CMD_HF_DESFIRE_COMMAND, &resp, 3000)) { PrintAndLogEx(WARNING, "Client reset command execute timeout"); DropField(); @@ -2787,7 +2867,7 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { return PM3_SUCCESS; } } else { - PrintAndLogEx(WARNING, _RED_("Auth command failed.")); + PrintAndLogEx(WARNING, _RED_("Auth command failed")); } DropField(); return PM3_SUCCESS; @@ -2839,11 +2919,11 @@ static int CmdHF14ADesInfo(const char *Cmd) { } PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") "---------------------------"); + PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------"); PrintAndLogEx(INFO, "-------------------------------------------------------------"); PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(package->uid, sizeof(package->uid))); PrintAndLogEx(SUCCESS, " Batch number: " _GREEN_("%s"), sprint_hex(package->details + 7, 5)); - PrintAndLogEx(SUCCESS, " Production date: week " _GREEN_("%02x") "/ " _GREEN_("20%02x"), package->details[12], package->details[13]); + PrintAndLogEx(SUCCESS, " Production date: week " _GREEN_("%02x") " / " _GREEN_("20%02x"), package->details[12], package->details[13]); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--- " _CYAN_("Hardware Information")); PrintAndLogEx(INFO, " Vendor Id: " _YELLOW_("%s"), getTagInfo(package->versionHW[0])); @@ -3051,6 +3131,151 @@ static int DecodeFileSettings(uint8_t *src, int src_len, int maclen) { return PM3_ESOFT; } +static int CmdHF14ADesDump(const char *Cmd) { + (void)Cmd; // Cmd is not used so far + DropField(); + uint8_t aid[3] = {0}; + uint8_t app_ids[78] = {0}; + uint8_t app_ids_len = 0; + + uint8_t file_ids[33] = {0}; + uint8_t file_ids_len = 0; + + dfname_t dfnames[255]; + uint8_t dfname_count = 0; + + int res = 0; + + if (handler_desfire_appids(app_ids, &app_ids_len) != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Can't get list of applications on tag"); + DropField(); + return PM3_ESOFT; + } + + if (handler_desfire_dfnames(dfnames, &dfname_count) != PM3_SUCCESS) { + PrintAndLogEx(WARNING, _RED_("Can't get DF Names")); + DropField(); + return PM3_ESOFT; + } + + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "-- Mifare DESFire Dump ----------------------"); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); + + for (int i = 0; i < app_ids_len; i += 3) { + + aid[0] = app_ids[i]; + aid[1] = app_ids[i + 1]; + aid[2] = app_ids[i + 2]; + + PrintAndLogEx(SUCCESS, " AID : " _GREEN_("%02X%02X%02X"), aid[2], aid[1], aid[0]); + PrintAndLogEx(SUCCESS, " AID Function Cluster 0x%02X: " _YELLOW_("%s"), aid[2], cluster_to_text(aid[2])); + + for (int m = 0; m < dfname_count; m++) { + if (dfnames[m].aid[0] == aid[0] && dfnames[m].aid[1] == aid[1] && dfnames[m].aid[2] == aid[2]) { + PrintAndLogEx(SUCCESS, " - DF " _YELLOW_("%02X%02X") " Name : " _YELLOW_("%s"), dfnames[m].fid[1], dfnames[m].fid[0], dfnames[m].name); + } + } + + uint8_t num_keys = 0; + uint8_t key_setting = 0; + res = handler_desfire_keysettings(&key_setting, &num_keys); + if (res != PM3_SUCCESS) return res; + + res = handler_desfire_select_application(aid); + + if (handler_desfire_fileids(file_ids, &file_ids_len) == PM3_SUCCESS) { + for (int j = file_ids_len - 1; j >= 0; j--) { + PrintAndLogEx(SUCCESS, "\n\n Fileid %d (0x%02x)", file_ids[j], file_ids[j]); + + uint8_t filesettings[20] = {0}; + int fileset_len = 0; + + res = handler_desfire_filesettings(file_ids[j], filesettings, &fileset_len); + int maclen = 0; // To be implemented + + if (res == PM3_SUCCESS) { + //if (DecodeFileSettings(filesettings, fileset_len, maclen) != PM3_SUCCESS) { + if (fileset_len == 1 + 1 + 2 + 3 + maclen) { + int filesize = (filesettings[6] << 16) + (filesettings[5] << 8) + filesettings[4]; + mfdes_data_t fdata; + fdata.fileno = file_ids[j]; + memset(fdata.offset, 0, 3); + //memcpy(fdata.length,&filesettings[4],3); + memset(fdata.length, 0, 3); + uint8_t *data = (uint8_t *)malloc(filesize); + fdata.data = data; + if (data) { + res = handler_desfire_readdata(&fdata, MFDES_DATA_FILE); + if (res == PM3_SUCCESS) { + PrintAndLogEx(NORMAL, "\nOffset | Data | Ascii"); + PrintAndLogEx(NORMAL, "----------------------------------------------------------------------------"); + int len = le24toh(fdata.length); + for (int n = 0; n < len; n += 16) { + PrintAndLogEx(NORMAL, "%02d/0x%02X | %s| %s", n, n, sprint_hex(&fdata.data[n], len > 16 ? 16 : len), sprint_ascii(&fdata.data[n], len > 16 ? 16 : len)); + } + free(data); + } else { + PrintAndLogEx(ERR, "Couldn't read value. Error %d", res); + res = handler_desfire_select_application(aid); + } + } + } else if (fileset_len == 1 + 1 + 2 + 4 + 4 + 4 + 1 + maclen) { + PrintAndLogEx(NORMAL, "\n\nValue file: 0x%0x", file_ids[j]); + mfdes_value_t value; + value.fileno = file_ids[j]; + int len = 0; + res = handler_desfire_getvalue(&value, &len); + if (res == PM3_SUCCESS) { + PrintAndLogEx(NORMAL, "\nOffset | Value | Ascii"); + PrintAndLogEx(NORMAL, "----------------------------------------------------------------------------"); + for (int n = 0; n < len; n += 16) { + PrintAndLogEx(NORMAL, "%02d/0x%02X | %s| %s", n, n, sprint_hex(&value.value[n], len > 16 ? 16 : len), sprint_ascii(&value.value[n], len > 16 ? 16 : len)); + } + } else { + PrintAndLogEx(ERR, "Couldn't read value. Error %d", res); + res = handler_desfire_select_application(aid); + } + } else if (fileset_len == 1 + 1 + 2 + 3 + 3 + 3 + maclen) { + int maxrecords = (filesettings[9] << 16) + (filesettings[8] << 8) + filesettings[7]; + int filesize = (filesettings[6] << 16) + (filesettings[5] << 8) + filesettings[4]; + mfdes_data_t fdata; + fdata.fileno = file_ids[j]; + memset(fdata.length, 0, 3); + //memcpy(fdata.length,&filesettings[4],3); + uint8_t *data = (uint8_t *)malloc(filesize); + fdata.data = data; + if (data) { + for (int offset = 0; offset < maxrecords; offset++) { + PrintAndLogEx(NORMAL, "\n\nRecord offset: %024x", offset); + memset(data, 0, filesize); + fdata.offset[0] = offset & 0xFF; + fdata.offset[1] = (offset >> 8) & 0xFF; + fdata.offset[2] = (offset >> 16) & 0xFF; + res = handler_desfire_readdata(&fdata, MFDES_RECORD_FILE); + if (res == PM3_SUCCESS) { + PrintAndLogEx(NORMAL, "\nOffset | Data | Ascii"); + PrintAndLogEx(NORMAL, "----------------------------------------------------------------------------"); + int len = le24toh(fdata.length); + for (int n = 0; n < len; n += 16) { + PrintAndLogEx(NORMAL, "%02d/0x%02X | %s| %s", n, n, sprint_hex(&fdata.data[n], len > 16 ? 16 : len), sprint_ascii(&fdata.data[n], len > 16 ? 16 : len)); + } + } else { + res = handler_desfire_select_application(aid); + } + } + free(data); + } + } + } + } + } + } + PrintAndLogEx(INFO, "-------------------------------------------------------------"); + DropField(); + return PM3_SUCCESS; +} + static int CmdHF14ADesEnumApplications(const char *Cmd) { (void)Cmd; // Cmd is not used so far DropField(); @@ -3082,7 +3307,7 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "-- Mifare DESFire Enumerate applications --------------------"); PrintAndLogEx(INFO, "-------------------------------------------------------------"); - PrintAndLogEx(SUCCESS, " Tag report " _GREEN_("%d") "application%c", app_ids_len / 3, (app_ids_len == 3) ? ' ' : 's'); + PrintAndLogEx(SUCCESS, " Tag report " _GREEN_("%d") " application%c", app_ids_len / 3, (app_ids_len == 3) ? ' ' : 's'); for (int i = 0; i < app_ids_len; i += 3) { @@ -3116,7 +3341,7 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { // Get File IDs if (handler_desfire_fileids(file_ids, &file_ids_len) == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, " Tag report " _GREEN_("%d") "file%c", file_ids_len, (file_ids_len == 1) ? ' ' : 's'); + PrintAndLogEx(SUCCESS, " Tag report " _GREEN_("%d") " file%c", file_ids_len, (file_ids_len == 1) ? ' ' : 's'); for (int j = file_ids_len - 1; j >= 0; j--) { PrintAndLogEx(SUCCESS, " Fileid %d (0x%02x)", file_ids[j], file_ids[j]); @@ -3305,17 +3530,523 @@ static int CmdHF14ADesAuth(const char *Cmd) { } */ mfdes_auth_res_t rpayload; - if (handler_desfire_auth(&payload, &rpayload, usedefaultkey) == PM3_SUCCESS) { + int error = handler_desfire_auth(&payload, &rpayload, usedefaultkey); + if (error == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, " Key : " _GREEN_("%s"), sprint_hex(key, keylength)); PrintAndLogEx(SUCCESS, " SESSION : " _GREEN_("%s"), sprint_hex(rpayload.sessionkey, keylength)); PrintAndLogEx(INFO, "-------------------------------------------------------------"); } else { + AuthToError(error); return PM3_ESOFT; } PrintAndLogEx(INFO, "-------------------------------------------------------------"); return PM3_SUCCESS; } +void DesFill2bPattern(uint8_t deskeyList[MAX_KEYS_LIST_LEN][8], size_t *deskeyListLen, uint8_t aeskeyList[MAX_KEYS_LIST_LEN][16], size_t *aeskeyListLen, uint8_t k3kkeyList[MAX_KEYS_LIST_LEN][24], size_t *k3kkeyListLen, uint32_t *startPattern) { + for (uint32_t pt = *startPattern; pt < 0x10000; pt++) { + if (*deskeyListLen != MAX_KEYS_LIST_LEN) { + deskeyList[*deskeyListLen][0] = (pt >> 8) & 0xff; + deskeyList[*deskeyListLen][1] = pt & 0xff; + memcpy(&deskeyList[*deskeyListLen][2], &deskeyList[*deskeyListLen][0], 2); + memcpy(&deskeyList[*deskeyListLen][4], &deskeyList[*deskeyListLen][0], 4); + (*deskeyListLen)++; + } + if (*aeskeyListLen != MAX_KEYS_LIST_LEN) { + aeskeyList[*aeskeyListLen][0] = (pt >> 8) & 0xff; + aeskeyList[*aeskeyListLen][1] = pt & 0xff; + memcpy(&aeskeyList[*aeskeyListLen][2], &aeskeyList[*aeskeyListLen][0], 2); + memcpy(&aeskeyList[*aeskeyListLen][4], &aeskeyList[*aeskeyListLen][0], 4); + memcpy(&aeskeyList[*aeskeyListLen][8], &aeskeyList[*aeskeyListLen][0], 8); + (*aeskeyListLen)++; + } + if (*k3kkeyListLen != MAX_KEYS_LIST_LEN) { + k3kkeyList[*k3kkeyListLen][0] = (pt >> 8) & 0xff; + k3kkeyList[*k3kkeyListLen][1] = pt & 0xff; + memcpy(&k3kkeyList[*k3kkeyListLen][2], &k3kkeyList[*k3kkeyListLen][0], 2); + memcpy(&k3kkeyList[*k3kkeyListLen][4], &k3kkeyList[*k3kkeyListLen][0], 4); + memcpy(&k3kkeyList[*k3kkeyListLen][8], &k3kkeyList[*k3kkeyListLen][0], 8); + memcpy(&k3kkeyList[*k3kkeyListLen][16], &k3kkeyList[*k3kkeyListLen][0], 4); + (*k3kkeyListLen)++; + } + + *startPattern = pt; + if ((*deskeyListLen == MAX_KEYS_LIST_LEN) && (*aeskeyListLen == MAX_KEYS_LIST_LEN) && (*k3kkeyListLen == MAX_KEYS_LIST_LEN)) + break; + } + (*startPattern)++; +} + +static int AuthCheckDesfire(uint8_t *aid, uint8_t deskeyList[MAX_KEYS_LIST_LEN][8], size_t deskeyListLen, uint8_t aeskeyList[MAX_KEYS_LIST_LEN][16], size_t aeskeyListLen, uint8_t k3kkeyList[MAX_KEYS_LIST_LEN][24], size_t k3kkeyListLen, uint8_t foundKeys[4][0xE][24 + 1], bool *result) { + int res = handler_desfire_select_application(aid); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "AID %X does not exist."); + return res; + } + + int usedkeys[0xF] = {0}; + bool des = false; + bool tdes = false; + bool aes = false; + bool k3kdes = false; + + if (memcmp(aid, "\x00\x00\x00", 3) != 0) { + uint8_t file_ids[33] = {0}; + uint8_t file_ids_len = 0; + // Get File IDs + if (handler_desfire_fileids(file_ids, &file_ids_len) == PM3_SUCCESS) { + for (int j = file_ids_len - 1; j >= 0; j--) { + uint8_t filesettings[20] = {0}; + int fileset_len = 0; + res = handler_desfire_filesettings(file_ids[j], filesettings, &fileset_len); + if (res == PM3_SUCCESS) { + uint16_t accrights = (filesettings[3] << 8) + filesettings[2]; + int change_access_rights = accrights & 0xF; + int read_write_access = (accrights >> 4) & 0xF; + int write_access = (accrights >> 8) & 0xF; + int read_access = (accrights >> 12) & 0xF; + if (change_access_rights == 0xE) change_access_rights = 0x0; + if (read_write_access == 0xE) read_write_access = 0x0; + if (write_access == 0xE) write_access = 0x0; + if (read_access == 0xE) read_access = 0x0; + usedkeys[change_access_rights] = 1; + usedkeys[read_write_access] = 1; + usedkeys[write_access] = 1; + usedkeys[read_access] = 1; + if (res == PM3_SUCCESS) { + switch (fileset_len >> 6) { + case 0: + des = true; + tdes = true; + break; + case 1: + k3kdes = true; + break; + case 2: + aes = true; + break; + default: + break; + } + } + } + } + if (file_ids_len == 0) { + for (int z = 0; z < 0xE; z++) { + usedkeys[z] = 1; + des = true; + tdes = true; + aes = true; + k3kdes = true; + } + } + } + } else des = true; + int error = PM3_SUCCESS; + bool badlen = false; + mfdes_authinput_t payload; + uint32_t curaid = (aid[0] & 0xFF) + ((aid[1] & 0xFF) << 8) + ((aid[2] & 0xFF) << 16); + if (des) { + for (int keyno = 0; keyno < 0xE; keyno++) + if (usedkeys[keyno] == 1 && foundKeys[0][keyno][0] == 0) { + for (int curkey = 0; curkey < deskeyListLen; curkey++) { + payload.keylen = 8; + memcpy(payload.key, deskeyList[curkey], 8); + payload.mode = MFDES_AUTH_DES; + payload.algo = MFDES_ALGO_DES; + payload.keyno = keyno; + mfdes_auth_res_t rpayload; + error = handler_desfire_auth(&payload, &rpayload, false); + if (error == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "AID 0x%06X, Found DES Key %d : " _GREEN_("%s"), curaid, keyno, sprint_hex(deskeyList[curkey], 8)); + foundKeys[0][keyno][0] = 0x01; + *result = true; + memcpy(&foundKeys[0][keyno][1], deskeyList[curkey], 8); + break; + } else if (error < 7) { + badlen = true; + DropField(); + res = handler_desfire_select_application(aid); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "AID %X does not exist."); + return res; + } + break; + } + } + if (badlen == true) { + badlen = false; + break; + } + } + } + if (tdes) { + for (int keyno = 0; keyno < 0xE; keyno++) + if (usedkeys[keyno] == 1 && foundKeys[1][keyno][0] == 0) { + for (int curkey = 0; curkey < aeskeyListLen; curkey++) { + payload.keylen = 16; + memcpy(payload.key, aeskeyList[curkey], 16); + payload.mode = MFDES_AUTH_DES; + payload.algo = MFDES_ALGO_3DES; + payload.keyno = keyno; + mfdes_auth_res_t rpayload; + error = handler_desfire_auth(&payload, &rpayload, false); + if (error == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "AID 0x%06X, Found 3DES Key %d : " _GREEN_("%s"), curaid, keyno, sprint_hex(aeskeyList[curkey], 16)); + foundKeys[1][keyno][0] = 0x01; + *result = true; + memcpy(&foundKeys[1][keyno][1], aeskeyList[curkey], 16); + break; + } else if (error < 7) { + badlen = true; + DropField(); + res = handler_desfire_select_application(aid); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "AID %X does not exist."); + return res; + } + break; + } + } + if (badlen == true) { + badlen = false; + break; + } + } + } + + if (aes) { + for (int keyno = 0; keyno < 0xE; keyno++) + if (usedkeys[keyno] == 1 && foundKeys[2][keyno][0] == 0) { + for (int curkey = 0; curkey < aeskeyListLen; curkey++) { + payload.keylen = 16; + memcpy(payload.key, aeskeyList[curkey], 16); + payload.mode = MFDES_AUTH_AES; + payload.algo = MFDES_ALGO_AES; + payload.keyno = keyno; + mfdes_auth_res_t rpayload; + error = handler_desfire_auth(&payload, &rpayload, false); + if (error == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "AID 0x%06X, Found AES Key %d : " _GREEN_("%s"), curaid, keyno, sprint_hex(aeskeyList[curkey], 16)); + foundKeys[2][keyno][0] = 0x01; + *result = true; + memcpy(&foundKeys[2][keyno][1], aeskeyList[curkey], 16); + break; + } else if (error < 7) { + badlen = true; + DropField(); + res = handler_desfire_select_application(aid); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "AID %X does not exist."); + return res; + } + break; + } + } + if (badlen == true) { + badlen = false; + break; + } + } + } + + if (k3kdes) { + for (int keyno = 0; keyno < 0xE; keyno++) + if (usedkeys[keyno] == 1 && foundKeys[3][keyno][0] == 0) { + for (int curkey = 0; curkey < k3kkeyListLen; curkey++) { + payload.keylen = 24; + memcpy(payload.key, k3kkeyList[curkey], 24); + payload.mode = MFDES_AUTH_ISO; + payload.algo = MFDES_ALGO_3K3DES; + payload.keyno = keyno; + mfdes_auth_res_t rpayload; + error = handler_desfire_auth(&payload, &rpayload, false); + if (error == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "AID 0x%06X, Found 3K3 Key %d : " _GREEN_("%s"), curaid, keyno, sprint_hex(k3kkeyList[curkey], 24)); + foundKeys[3][keyno][0] = 0x01; + *result = true; + memcpy(&foundKeys[3][keyno][1], k3kkeyList[curkey], 16); + break; + } else if (error < 7) { + badlen = true; + DropField(); + res = handler_desfire_select_application(aid); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "AID %X does not exist."); + return res; + } + break; + } + } + if (badlen == true) { + badlen = false; + break; + } + } + } + DropField(); + return PM3_SUCCESS; +} + +static int CmdHF14aDesChk(const char *Cmd) { + int res; + uint8_t deskeyList[MAX_KEYS_LIST_LEN][8] = {{0}}; + uint8_t aeskeyList[MAX_KEYS_LIST_LEN][16] = {{0}}; + uint8_t k3kkeyList[MAX_KEYS_LIST_LEN][MAX_KEY_LEN] = {{0}}; + size_t deskeyListLen = 0; + size_t aeskeyListLen = 0; + size_t k3kkeyListLen = 0; + uint8_t foundKeys[4][0xE][24 + 1] = {{{0}}}; + + CLIParserInit("hf mfdes chk", + "Checks keys with Mifare Desfire card.", + "Usage:\n" + " hf mfdes chk -a 123456 -k 000102030405060708090a0b0c0d0e0f -> check key on aid 0x123456\n" + " hf mfdes chk -d mfdes_default_keys -> check keys from dictionary against all existing aid on card\n" + " hf mfdes chk -d mfdes_default_keys -a 123456 -> check keys from dictionary against aid 0x123456\n" + " hf mfdes chk -a 123456 --pattern1b -j keys -> check all 1-byte keys pattern on aid 0x123456 and save found keys to json\n" + " hf mfdes chk -a 123456 --pattern2b --startp2b FA00 -> check all 2-byte keys pattern on aid 0x123456. Start from key FA00FA00...FA00\n"); + + void *argtable[] = { + arg_param_begin, + arg_strx0("aA", "aid", "", "Use specific AID (3 hex bytes, big endian)"), + arg_str0("kK", "key", "", "Key for checking (HEX 16 bytes)"), + arg_str0("dD", "dict", "", "File with keys dictionary"), + arg_lit0(NULL, "pattern1b", "Check all 1-byte combinations of key (0000...0000, 0101...0101, 0202...0202, ...)"), + arg_lit0(NULL, "pattern2b", "Check all 2-byte combinations of key (0000...0000, 0001...0001, 0002...0002, ...)"), + arg_str0(NULL, "startp2b", "", "Start key (2-byte HEX) for 2-byte search (use with `--pattern2b`)"), + arg_str0("jJ", "json", "", "Json file to save keys"), + arg_lit0("vV", "verbose", "Verbose mode."), + arg_param_end + }; + CLIExecWithReturn(Cmd, argtable, false); + + int aidlength = 0; + uint8_t aid[3] = {0}; + CLIGetHexWithReturn(1, aid, &aidlength); + swap24(aid); + uint8_t vkey[16] = {0}; + int vkeylen = 0; + CLIGetHexWithReturn(2, vkey, &vkeylen); + + if (vkeylen > 0) { + if (vkeylen == 8) { + memcpy(&deskeyList[deskeyListLen], vkey, 8); + deskeyListLen++; + } else if (vkeylen == 16) { + memcpy(&aeskeyList[aeskeyListLen], vkey, 16); + aeskeyListLen++; + } else if (vkeylen == 24) { + memcpy(&k3kkeyList[k3kkeyListLen], vkey, 16); + k3kkeyListLen++; + } else { + PrintAndLogEx(ERR, "Specified key must have 8, 16 or 24 bytes length."); + CLIParserFree(); + return PM3_EINVARG; + } + } + + uint8_t dict_filename[FILE_PATH_SIZE + 2] = {0}; + int dict_filenamelen = 0; + if (CLIParamStrToBuf(arg_get_str(3), dict_filename, FILE_PATH_SIZE, &dict_filenamelen)) { + PrintAndLogEx(FAILED, "File name too long or invalid."); + CLIParserFree(); + return PM3_EINVARG; + } + + bool pattern1b = arg_get_lit(4); + bool pattern2b = arg_get_lit(5); + + if (pattern1b && pattern2b) { + PrintAndLogEx(ERR, "Pattern search mode must be 2-byte or 1-byte only."); + CLIParserFree(); + return PM3_EINVARG; + } + + if (dict_filenamelen && (pattern1b || pattern2b)) { + PrintAndLogEx(ERR, "Pattern search mode and dictionary mode can't be used in one command."); + CLIParserFree(); + return PM3_EINVARG; + } + + uint32_t startPattern = 0x0000; + uint8_t vpattern[2]; + int vpatternlen = 0; + CLIGetHexWithReturn(6, vpattern, &vpatternlen); + if (vpatternlen > 0) { + if (vpatternlen > 0 && vpatternlen <= 2) { + startPattern = (vpattern[0] << 8) + vpattern[1]; + } else { + PrintAndLogEx(ERR, "Pattern must be 2-byte length."); + CLIParserFree(); + return PM3_EINVARG; + } + if (!pattern2b) + PrintAndLogEx(WARNING, "Pattern entered, but search mode not is 2-byte search."); + } + + uint8_t jsonname[250] = {0}; + int jsonnamelen = 0; + if (CLIParamStrToBuf(arg_get_str(7), jsonname, sizeof(jsonname), &jsonnamelen)) { + PrintAndLogEx(ERR, "Invalid json name."); + CLIParserFree(); + return PM3_EINVARG; + } + jsonname[jsonnamelen] = 0; + + bool verbose = arg_get_lit(8); + + CLIParserFree(); + + // 1-byte pattern search mode + if (pattern1b) { + for (int i = 0; i < 0x100; i++) + memset(aeskeyList[i], i, 16); + for (int i = 0; i < 0x100; i++) + memset(deskeyList[i], i, 8); + for (int i = 0; i < 0x100; i++) + memset(k3kkeyList[i], i, 24); + aeskeyListLen = 0x100; + deskeyListLen = 0x100; + k3kkeyListLen = 0x100; + } + + // 2-byte pattern search mode + if (pattern2b) { + DesFill2bPattern(deskeyList, &deskeyListLen, aeskeyList, &aeskeyListLen, k3kkeyList, &k3kkeyListLen, &startPattern); + } + + // dictionary mode + size_t endFilePosition = 0; + if (dict_filenamelen) { + uint16_t keycnt = 0; + res = loadFileDICTIONARYEx((char *)dict_filename, deskeyList, sizeof(deskeyList), NULL, 8, &keycnt, 0, &endFilePosition, true); + deskeyListLen = keycnt; + if (endFilePosition) + PrintAndLogEx(SUCCESS, "First part of des dictionary successfully loaded."); + endFilePosition = 0; + res = loadFileDICTIONARYEx((char *)dict_filename, aeskeyList, sizeof(aeskeyList), NULL, 16, &keycnt, 0, &endFilePosition, true); + aeskeyListLen = keycnt; + if (endFilePosition) + PrintAndLogEx(SUCCESS, "First part of aes dictionary successfully loaded."); + endFilePosition = 0; + res = loadFileDICTIONARYEx((char *)dict_filename, k3kkeyList, sizeof(k3kkeyList), NULL, 24, &keycnt, 0, &endFilePosition, true); + k3kkeyListLen = keycnt; + if (endFilePosition) + PrintAndLogEx(SUCCESS, "First part of k3kdes dictionary successfully loaded."); + endFilePosition = 0; + + if (endFilePosition) + PrintAndLogEx(SUCCESS, "First part of dictionary successfully loaded."); + } + + if (aeskeyListLen == 0) { + PrintAndLogEx(ERR, "Aes key list is empty. Nothing to check."); + return PM3_EINVARG; + } else { + PrintAndLogEx(INFO, "Loaded " _YELLOW_("%zu") " aes keys", aeskeyListLen); + } + + if (deskeyListLen == 0) { + PrintAndLogEx(ERR, "Des key list is empty. Nothing to check."); + return PM3_EINVARG; + } else { + PrintAndLogEx(INFO, "Loaded " _YELLOW_("%zu") " des keys", deskeyListLen); + } + + if (k3kkeyListLen == 0) { + PrintAndLogEx(ERR, "K3k key list is empty. Nothing to check."); + return PM3_EINVARG; + } else { + PrintAndLogEx(INFO, "Loaded " _YELLOW_("%zu") " k3kdes keys", k3kkeyListLen); + } + + if (!verbose) + printf("Search keys:\n"); + + bool result = false; + uint8_t app_ids[78] = {0}; + uint8_t app_ids_len = 0; + + if (handler_desfire_appids(app_ids, &app_ids_len) != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Can't get list of applications on tag"); + DropField(); + return PM3_ESOFT; + } + + if (aidlength != 0) { + memcpy(&app_ids[0], aid, 3); + app_ids_len = 1; + } + + for (int x = 0; x < app_ids_len / 3; x++) { + uint32_t curaid = (app_ids[x * 3] & 0xFF) + ((app_ids[(x * 3) + 1] & 0xFF) << 8) + ((app_ids[(x * 3) + 2] & 0xFF) << 16); + PrintAndLogEx(ERR, "Checking aid 0x%06X...", curaid); + res = AuthCheckDesfire(&app_ids[x * 3], deskeyList, deskeyListLen, aeskeyList, aeskeyListLen, k3kkeyList, k3kkeyListLen, foundKeys, &result); + if (res == PM3_EOPABORTED) { + break; + } + + if (pattern2b && startPattern < 0x10000) { + if (!verbose) + printf("p"); + aeskeyListLen = 0; + deskeyListLen = 0; + k3kkeyListLen = 0; + DesFill2bPattern(deskeyList, &deskeyListLen, aeskeyList, &aeskeyListLen, k3kkeyList, &k3kkeyListLen, &startPattern); + continue; + } + if (dict_filenamelen && endFilePosition) { + if (!verbose) + printf("d"); + uint16_t keycnt = 0; + res = loadFileDICTIONARYEx((char *)dict_filename, deskeyList, sizeof(deskeyList), NULL, 16, &keycnt, endFilePosition, &endFilePosition, false); + deskeyListLen = keycnt; + keycnt = 0; + res = loadFileDICTIONARYEx((char *)dict_filename, aeskeyList, sizeof(aeskeyList), NULL, 16, &keycnt, endFilePosition, &endFilePosition, false); + aeskeyListLen = keycnt; + keycnt = 0; + res = loadFileDICTIONARYEx((char *)dict_filename, k3kkeyList, sizeof(k3kkeyList), NULL, 16, &keycnt, endFilePosition, &endFilePosition, false); + k3kkeyListLen = keycnt; + continue; + } + } + if (!verbose) + printf("\n"); + + // save keys to json + if ((jsonnamelen > 0) && result) { + // Mifare Desfire info + SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0); + + PacketResponseNG resp; + WaitForResponse(CMD_ACK, &resp); + + iso14a_card_select_t card; + memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t)); + + uint64_t select_status = resp.oldarg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision + + uint8_t data[10 + 1 + 2 + 1 + 256 + (4 * 0xE * (24 + 1))] = {0}; + uint8_t atslen = 0; + if (select_status == 1 || select_status == 2) { + memcpy(data, card.uid, card.uidlen); + data[10] = card.sak; + data[11] = card.atqa[1]; + data[12] = card.atqa[0]; + atslen = card.ats_len; + data[13] = atslen; + memcpy(&data[14], card.ats, atslen); + } + + // length: UID(10b)+SAK(1b)+ATQA(2b)+ATSlen(1b)+ATS(atslen)+foundKeys[2][64][AES_KEY_LEN + 1] + memcpy(&data[14 + atslen], foundKeys, 4 * 0xE * (24 + 1)); + saveFileJSON((char *)jsonname, jsfMfDesfireKeys, data, 0xE); + } + + return PM3_SUCCESS; +} + static int CmdHF14ADesList(const char *Cmd) { (void)Cmd; // Cmd is not used so far return CmdTraceList("des"); @@ -3364,6 +4095,8 @@ static command_t CommandTable[] = { {"getvalue", CmdHF14ADesGetValueData, IfPm3Iso14443a, "Get value of file"}, {"changevalue", CmdHF14ADesChangeValue, IfPm3Iso14443a, "Write value of a value file (credit/debit/clear)"}, {"formatpicc", CmdHF14ADesFormatPICC, IfPm3Iso14443a, "Format PICC"}, + {"dump", CmdHF14ADesDump, IfPm3Iso14443a, "Dump all files"}, + {"chk", CmdHF14aDesChk, IfPm3Iso14443a, "Check keys"}, /* ToDo: diff --git a/client/src/cmdhfmfhard.c b/client/src/cmdhfmfhard.c index 85e91ac64..6fc146164 100644 --- a/client/src/cmdhfmfhard.c +++ b/client/src/cmdhfmfhard.c @@ -32,10 +32,10 @@ #include "util_posix.h" #include "crapto1/crapto1.h" #include "parity.h" -#include "hardnested/hardnested_bruteforce.h" -#include "hardnested/hardnested_bf_core.h" -#include "hardnested/hardnested_bitarray_core.h" -#include "zlib.h" +#include "hardnested_bruteforce.h" +#include "hardnested_bf_core.h" +#include "hardnested_bitarray_core.h" +#include "zlib/zlib.h" #include "fileutils.h" #define NUM_CHECK_BITFLIPS_THREADS (num_CPUs()) diff --git a/client/src/cmdhfmfp.c b/client/src/cmdhfmfp.c index 91418b191..728101ce7 100644 --- a/client/src/cmdhfmfp.c +++ b/client/src/cmdhfmfp.c @@ -19,13 +19,13 @@ #include "mifare/mifare4.h" #include "mifare/mad.h" #include "mifare/ndef.h" -#include "cliparser/cliparser.h" +#include "cliparser.h" #include "emv/dump.h" #include "mifare/mifaredefault.h" #include "util_posix.h" #include "fileutils.h" #include "protocols.h" -#include "../crypto/libpcrypto.h" +#include "crypto/libpcrypto.h" static const uint8_t DefaultKey[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; uint16_t CardAddresses[] = {0x9000, 0x9001, 0x9002, 0x9003, 0x9004, 0xA000, 0xA001, 0xA080, 0xA081, 0xC000, 0xC001}; @@ -58,9 +58,9 @@ static char *getCardSizeStr(uint8_t fsize) { // is LSB set? if (fsize & 1) - sprintf(retStr, "0x%02X ( " _YELLOW_("%d - %d bytes") ")", fsize, usize, lsize); + sprintf(retStr, "0x%02X (" _YELLOW_("%d - %d bytes") ")", fsize, usize, lsize); else - sprintf(retStr, "0x%02X ( " _YELLOW_("%d bytes") ")", fsize, lsize); + sprintf(retStr, "0x%02X (" _YELLOW_("%d bytes") ")", fsize, lsize); return buf; } @@ -70,14 +70,14 @@ static char *getProtocolStr(uint8_t id, bool hw) { char *retStr = buf; if (id == 0x04) { - sprintf(retStr, "0x%02X ( " _YELLOW_("ISO 14443-3 MIFARE, 14443-4") ")", id); + sprintf(retStr, "0x%02X (" _YELLOW_("ISO 14443-3 MIFARE, 14443-4") ")", id); } else if (id == 0x05) { if (hw) - sprintf(retStr, "0x%02X ( " _YELLOW_("ISO 14443-2, 14443-3") ")", id); + sprintf(retStr, "0x%02X (" _YELLOW_("ISO 14443-2, 14443-3") ")", id); else - sprintf(retStr, "0x%02X ( " _YELLOW_("ISO 14443-3, 14443-4") ")", id); + sprintf(retStr, "0x%02X (" _YELLOW_("ISO 14443-3, 14443-4") ")", id); } else { - sprintf(retStr, "0x%02X ( " _YELLOW_("Unknown") ")", id); + sprintf(retStr, "0x%02X (" _YELLOW_("Unknown") ")", id); } return buf; } @@ -88,20 +88,20 @@ static char *getVersionStr(uint8_t major, uint8_t minor) { char *retStr = buf; if (major == 0x00) - sprintf(retStr, "%x.%x ( " _YELLOW_("DESFire MF3ICD40") ")", major, minor); + sprintf(retStr, "%x.%x (" _YELLOW_("DESFire MF3ICD40") ")", major, minor); else if (major == 0x01 && minor == 0x00) - sprintf(retStr, "%x.%x ( " _YELLOW_("DESFire EV1") ")", major, minor); + sprintf(retStr, "%x.%x (" _YELLOW_("DESFire EV1") ")", major, minor); else if (major == 0x12 && minor == 0x00) - sprintf(retStr, "%x.%x ( " _YELLOW_("DESFire EV2") ")", major, minor); + sprintf(retStr, "%x.%x (" _YELLOW_("DESFire EV2") ")", major, minor); // else if (major == 0x13 && minor == 0x00) -// sprintf(retStr, "%x.%x ( " _YELLOW_("DESFire EV3") ")", major, minor); +// sprintf(retStr, "%x.%x (" _YELLOW_("DESFire EV3") ")", major, minor); else if (major == 0x30 && minor == 0x00) - sprintf(retStr, "%x.%x ( " _YELLOW_("DESFire Light") ")", major, minor); + sprintf(retStr, "%x.%x (" _YELLOW_("DESFire Light") ")", major, minor); else if (major == 0x11 && minor == 0x00) - sprintf(retStr, "%x.%x ( " _YELLOW_("Plus EV1") ")", major, minor); + sprintf(retStr, "%x.%x (" _YELLOW_("Plus EV1") ")", major, minor); else - sprintf(retStr, "%x.%x ( " _YELLOW_("Unknown") ")", major, minor); + sprintf(retStr, "%x.%x (" _YELLOW_("Unknown") ")", major, minor); return buf; } @@ -112,16 +112,16 @@ static char *getTypeStr(uint8_t type) { switch (type) { case 1: - sprintf(retStr, "0x%02X ( " _YELLOW_("DESFire") ")", type); + sprintf(retStr, "0x%02X (" _YELLOW_("DESFire") ")", type); break; case 2: - sprintf(retStr, "0x%02X ( " _YELLOW_("Plus") ")", type); + sprintf(retStr, "0x%02X (" _YELLOW_("Plus") ")", type); break; case 3: - sprintf(retStr, "0x%02X ( " _YELLOW_("Ultralight") ")", type); + sprintf(retStr, "0x%02X (" _YELLOW_("Ultralight") ")", type); break; case 4: - sprintf(retStr, "0x%02X ( " _YELLOW_("NTAG") ")", type); + sprintf(retStr, "0x%02X (" _YELLOW_("NTAG") ")", type); break; default: break; @@ -227,7 +227,7 @@ static int get_plus_signature(uint8_t *signature, int *signature_len) { static int plus_print_version(uint8_t *version) { PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(version + 14, 7)); PrintAndLogEx(SUCCESS, " Batch number: " _GREEN_("%s"), sprint_hex(version + 21, 5)); - PrintAndLogEx(SUCCESS, " Production date: week " _GREEN_("%02x") "/ " _GREEN_("20%02x"), version[7 + 7 + 7 + 5], version[7 + 7 + 7 + 5 + 1]); + PrintAndLogEx(SUCCESS, " Production date: week " _GREEN_("%02x") " / " _GREEN_("20%02x"), version[7 + 7 + 7 + 5], version[7 + 7 + 7 + 5 + 1]); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--- " _CYAN_("Hardware Information")); PrintAndLogEx(INFO, " Vendor Id: " _YELLOW_("%s"), getTagInfo(version[0])); @@ -266,7 +266,7 @@ static int CmdHFMFPInfo(const char *Cmd) { PrintAndLogEx(WARNING, "command don't have any parameters.\n"); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") "---------------------------"); + PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------"); PrintAndLogEx(INFO, "-------------------------------------------------------------"); bool supportVersion = false; @@ -328,11 +328,11 @@ static int CmdHFMFPInfo(const char *Cmd) { uint16_t ATQA = card.atqa[0] + (card.atqa[1] << 8); if (ATQA & 0x0004) { - PrintAndLogEx(INFO, " SIZE: " _GREEN_("2K") "(%s UID)", (ATQA & 0x0040) ? "7" : "4"); + PrintAndLogEx(INFO, " SIZE: " _GREEN_("2K") " (%s UID)", (ATQA & 0x0040) ? "7" : "4"); isPlus = true; } if (ATQA & 0x0002) { - PrintAndLogEx(INFO, " SIZE: " _GREEN_("4K") "(%s UID)", (ATQA & 0x0040) ? "7" : "4"); + PrintAndLogEx(INFO, " SIZE: " _GREEN_("4K") " (%s UID)", (ATQA & 0x0040) ? "7" : "4"); isPlus = true; } @@ -357,7 +357,7 @@ static int CmdHFMFPInfo(const char *Cmd) { } if (card.sak == 0x20) { - PrintAndLogEx(INFO, " SAK: " _GREEN_("MIFARE Plus SL0/SL3") "or " _GREEN_("MIFARE DESFire")); + PrintAndLogEx(INFO, " SAK: " _GREEN_("MIFARE Plus SL0/SL3") " or " _GREEN_("MIFARE DESFire")); if (card.ats_len > 0) { @@ -1190,7 +1190,7 @@ static int CmdHFMFPChk(const char *Cmd) { PrintAndLogEx(ERR, "Key list is empty. Nothing to check."); return PM3_EINVARG; } else { - PrintAndLogEx(INFO, "Loaded " _YELLOW_("%zu") "keys", keyListLen); + PrintAndLogEx(INFO, "Loaded " _YELLOW_("%zu") " keys", keyListLen); } if (!verbose) diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index fcac8d137..f70c3887e 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -11,7 +11,7 @@ #include #include "cmdparser.h" #include "commonutil.h" -#include "../crypto/libpcrypto.h" +#include "crypto/libpcrypto.h" #include "mbedtls/des.h" #include "cmdhfmf.h" #include "cmdhf14a.h" @@ -20,7 +20,7 @@ #include "protocols.h" #include "generator.h" #include "mifare/ndef.h" -#include "cliparser/cliparser.h" +#include "cliparser.h" #define MAX_UL_BLOCKS 0x0F @@ -64,13 +64,13 @@ static int usage_hf_mfu_info(void) { static int usage_hf_mfu_dump(void) { PrintAndLogEx(NORMAL, "Reads all pages from Ultralight, Ultralight-C, Ultralight EV1"); PrintAndLogEx(NORMAL, "NTAG 203, NTAG 210, NTAG 212, NTAG 213, NTAG 215, NTAG 216"); - PrintAndLogEx(NORMAL, "and saves binary dump into the file " _YELLOW_("`filename.bin`") "or " _YELLOW_("`cardUID.bin`")); + PrintAndLogEx(NORMAL, "and saves binary dump into the file " _YELLOW_("`filename.bin`") " or " _YELLOW_("`cardUID.bin`")); PrintAndLogEx(NORMAL, "It autodetects card type.\n"); PrintAndLogEx(NORMAL, "Usage: hf mfu dump k l f p q <#pages>"); PrintAndLogEx(NORMAL, " Options :"); PrintAndLogEx(NORMAL, " k : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]"); PrintAndLogEx(NORMAL, " l : (optional) swap entered key's endianness"); - PrintAndLogEx(NORMAL, " f : " _YELLOW_("filename w/o .bin") "to save the dump as"); + PrintAndLogEx(NORMAL, " f : " _YELLOW_("filename w/o .bin") " to save the dump as"); PrintAndLogEx(NORMAL, " p : starting Page number to manually set a page to start the dump at"); PrintAndLogEx(NORMAL, " q : number of Pages to manually set how many pages to dump"); PrintAndLogEx(NORMAL, ""); @@ -91,8 +91,8 @@ static int usage_hf_mfu_restore(void) { PrintAndLogEx(NORMAL, " l : (optional) swap entered key's endianness"); PrintAndLogEx(NORMAL, " s : (optional) enable special write UID " _BLUE_("-MAGIC TAG ONLY-")); PrintAndLogEx(NORMAL, " e : (optional) enable special write version/signature " _BLUE_("-MAGIC NTAG 21* ONLY-")); - PrintAndLogEx(NORMAL, " r : (optional) use the password found in dumpfile to configure tag. requires " _YELLOW_("'e'") "parameter to work"); - PrintAndLogEx(NORMAL, " f : " _YELLOW_("filename w .bin") "to restore"); + PrintAndLogEx(NORMAL, " r : (optional) use the password found in dumpfile to configure tag. requires " _YELLOW_("'e'") " parameter to work"); + PrintAndLogEx(NORMAL, " f : " _YELLOW_("filename w .bin") " to restore"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu restore s f myfile")); @@ -136,7 +136,7 @@ static int usage_hf_mfu_wrbl(void) { static int usage_hf_mfu_eload(void) { PrintAndLogEx(NORMAL, "It loads emul dump from the file " _YELLOW_("`filename.eml`")); - PrintAndLogEx(NORMAL, "Hint: See " _YELLOW_("`script run dumptoemul-mfu`") "to convert the .bin to the eml"); + PrintAndLogEx(NORMAL, "Hint: See " _YELLOW_("`script run dumptoemul-mfu`") " to convert the .bin to the eml"); PrintAndLogEx(NORMAL, "Usage: hf mfu eload u [numblocks]"); PrintAndLogEx(NORMAL, " Options:"); PrintAndLogEx(NORMAL, " h : this help"); @@ -198,7 +198,7 @@ static int usage_hf_mfu_ucsetuid(void) { PrintAndLogEx(NORMAL, "Usage: hf mfu setuid "); PrintAndLogEx(NORMAL, " [uid] - (14 hex symbols)"); PrintAndLogEx(NORMAL, "\n"); - PrintAndLogEx(NORMAL, "This only works for " _BLUE_("Magic Ultralight") "tags."); + PrintAndLogEx(NORMAL, "This only works for " _BLUE_("Magic Ultralight") " tags."); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu setuid 11223344556677")); @@ -235,13 +235,21 @@ static int usage_hf_mfu_pwdgen(void) { } static int usage_hf_mfu_otp_tearoff(void) { - PrintAndLogEx(NORMAL, "Tear-off test against OTP block on MFU tags."); - PrintAndLogEx(NORMAL, "Usage: hf mfu otptear [h]"); + PrintAndLogEx(NORMAL, "Tear-off test against OTP block (no 3) on MFU tags - More help sooner or later\n"); + PrintAndLogEx(NORMAL, "Usage: hf mfu otptear b i l s d t \n"); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : this help"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu otptear")); + PrintAndLogEx(NORMAL, " b : (optional) block to run the test - default block: 8 (not OTP for safety)"); + PrintAndLogEx(NORMAL, " i