From 496b673453e77acd5477b260ee74d080f04999c7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 26 Jan 2017 14:23:48 +0100 Subject: [PATCH 01/16] Added some comments --- fpga/hi_simulate.v | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/fpga/hi_simulate.v b/fpga/hi_simulate.v index 0768c29d..6139cfad 100644 --- a/fpga/hi_simulate.v +++ b/fpga/hi_simulate.v @@ -53,6 +53,11 @@ end // Divide 13.56 MHz by 32 to produce the SSP_CLK // The register is bigger to allow higher division factors of up to /128 +// FPGA_HF_SIMULATOR_NO_MODULATION (0<<0) // 0000 +// FPGA_HF_SIMULATOR_MODULATE_BPSK (1<<0) // 0001 +// FPGA_HF_SIMULATOR_MODULATE_212K (2<<0) // 0010 +// FPGA_HF_SIMULATOR_MODULATE_424K (4<<0) // 0100 +// FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 0x5 // 0101 reg [10:0] ssp_clk_divider; always @(posedge adc_clk) @@ -86,8 +91,8 @@ end // Divide SSP_CLK by 8 to produce the byte framing signal; the phase of // this is arbitrary, because it's just a bitstream. // One nasty issue, though: I can't make it work with both rx and tx at -// once. The phase wrt ssp_clk must be changed. TODO to find out why -// that is and make a better fix. +// once. The phase wrt ssp_clk must be changed. +// TODO to find out why that is and make a better fix. reg [2:0] ssp_frame_divider_to_arm; always @(posedge ssp_clk) ssp_frame_divider_to_arm <= (ssp_frame_divider_to_arm + 1); -- 2.39.5 From fbed30e8c99de3c4301264cd4ca6e82c709533c4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 26 Jan 2017 15:54:12 +0100 Subject: [PATCH 02/16] chg: lets not have it static, since I get the same nonce in the same session over again. --- common/random.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/common/random.c b/common/random.c index 62d0cbeb..df549968 100644 --- a/common/random.c +++ b/common/random.c @@ -1,6 +1,6 @@ #include "random.h" -static uint64_t next_random = 1; + uint64_t next_random = 1; /* Generates a (non-cryptographically secure) 32-bit random number. * @@ -13,7 +13,9 @@ uint32_t prand() { if (next_random == 1) next_random = GetTickCount(); - next_random = next_random * 6364136223846793005 + 1; + next_random *= 6364136223846793005; + next_random += 1; + return (uint32_t)(next_random >> 32) % 0xffffffff; } -- 2.39.5 From 2e78fbaa1d62a89689fd12048db7e0b6be696a5e Mon Sep 17 00:00:00 2001 From: Iceman Date: Thu, 26 Jan 2017 17:53:35 +0100 Subject: [PATCH 03/16] chg: link to strawberry perl was dead Thanks to @Marshmellow42 for pointing it out --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 92abdac8..ad88932f 100644 --- a/README.md +++ b/README.md @@ -226,7 +226,7 @@ You only need devkitARM, nothing more (no extra lib or anything else) to compile `export PATH=$PATH:$DEVKITARM/bin` ### 6. Install Strawberry Perl -Download and install: http://strawberry-perl.googlecode.com/files/strawberry-perl-5.10.1.1.msi +Download and install: https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/strawberry-perl/strawberry-perl-5.10.1.3.msi ### 7. Build and run Download and install Git for Windows: https://git-scm.com/download/win -- 2.39.5 From beb2ce1f2dd06501d2bc914d8b19a3ea65c02e8f Mon Sep 17 00:00:00 2001 From: Iceman Date: Thu, 26 Jan 2017 17:55:24 +0100 Subject: [PATCH 04/16] Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index ad88932f..d2c2e0ca 100644 --- a/README.md +++ b/README.md @@ -183,8 +183,7 @@ Follow those instructions to get it up and running. No need for the old proxspa [1.6.0] How to connect: https://youtu.be/0ZS2t5C-caI [1.6.1] How to flash: https://www.youtube.com/watch?v=WXouhuGYEiw -Recommendations: -Use only container tag [1.6.4] +Recommendations: Use only latest container. ## Building on Windows -- 2.39.5 From 74dde713b14123ed67d563f59f9329f3dbd91384 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 26 Jan 2017 21:13:17 +0100 Subject: [PATCH 05/16] CHG: should remove the OSX linker warning: ld: warning: directory not found for option '-L/opt/local/lib' --- armsrc/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/armsrc/Makefile b/armsrc/Makefile index 08252565..17a5a0ed 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -54,8 +54,7 @@ THUMBSRC = start.c \ string.c \ BigBuf.c \ ticks.c \ - hfsnoop.c \ - random.c + hfsnoop.c # These are to be compiled in ARM mode ARMSRC = fpgaloader.c \ @@ -66,7 +65,8 @@ ARMSRC = fpgaloader.c \ $(SRC_ICLASS) \ usb_cdc.c \ cmd.c \ - parity.c + parity.c \ + random.c # $(SRC_EMV) \ #BigBuf.c \ -- 2.39.5 From 7dae65ce9919e65c0d6ccd7c2c669c55ef4c8ee3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 26 Jan 2017 21:34:01 +0100 Subject: [PATCH 06/16] chg: TravisCI should also use perl --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 14ce9b38..ea0a545c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,6 +30,7 @@ before_script: - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install -y gcc-arm-none-eabi; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then git fetch --all; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install perl; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew tap iceman1001/proxmark3; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install proxmark3; fi -- 2.39.5 From bdebc8dbab9ca3867faf32532c4db32966fce56a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 26 Jan 2017 23:49:05 +0100 Subject: [PATCH 07/16] CHG: removed a -L path for OSX --- client/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/Makefile b/client/Makefile index db33d77a..7da69d73 100644 --- a/client/Makefile +++ b/client/Makefile @@ -54,11 +54,11 @@ else ifeq ($(platform),Darwin) ifneq (, $(findstring moc 5,$(qtplatform))) # use this if you have QT5 installed. CFLAGS += -I/usr/include/malloc/ -I/usr/local/opt/readline/include -I/usr/local/opt/qt5/include - LDLIBS = -L/opt/local/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/qt5/lib -lreadline -lpthread -lm + LDLIBS = -L/usr/local/opt/readline/lib -L/usr/local/opt/qt5/lib -lreadline -lpthread -lm else # Assuming you have QT4 installed. CFLAGS += -I/usr/include/malloc/ -I/usr/local/opt/readline/include - LDLIBS = -L/opt/local/lib -L/usr/local/opt/readline/lib -lreadline -lpthread -lm + LDLIBS = -L/usr/local/opt/readline/lib -lreadline -lpthread -lm endif LUAPLATFORM = macosx -- 2.39.5 From 4653da43318d7b0ac4de7d313ee7c017af4914cb Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 27 Jan 2017 10:49:34 +0100 Subject: [PATCH 08/16] ADD: `lf cotag` - added first try at basic functionality to read samples from Cotag. In lfops.c is the startup sequence that needs to be tested out. --- armsrc/appmain.c | 3 +++ armsrc/apps.h | 1 + armsrc/lfops.c | 46 ++++++++++++++++++++++++++++++++++++ client/Makefile | 1 + client/cmdlf.c | 1 + client/cmdlf.h | 1 + client/cmdlfcotag.c | 41 ++++++++++++++++++++++++++++++++ client/cmdlfcotag.h | 22 +++++++++++++++++ client/hid-flasher/usb_cmd.h | 3 ++- client/lualibs/commands.lua | 1 + include/usb_cmd.h | 1 + 11 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 client/cmdlfcotag.c create mode 100644 client/cmdlfcotag.h diff --git a/armsrc/appmain.c b/armsrc/appmain.c index d4b22465..905fd320 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1009,6 +1009,9 @@ void UsbPacketReceived(uint8_t *packet, int len) case CMD_VIKING_CLONE_TAG: CopyVikingtoT55xx(c->arg[0], c->arg[1], c->arg[2]); break; + case CMD_COTAG: + Cotag(); + break; #endif #ifdef WITH_HITAG diff --git a/armsrc/apps.h b/armsrc/apps.h index 6289223b..6ea9d5ea 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -98,6 +98,7 @@ void T55xxWakeUp(uint32_t Pwd); void TurnReadLFOn(uint32_t delay); void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode); void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode); +void Cotag(); /// iso14443b.h void SimulateIso14443bTag(uint32_t pupi); diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 71d9ba95..28927c33 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1737,3 +1737,49 @@ void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off LED_D_OFF(); } + +void Cotag() { + +#define WAIT2200 { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(2200); } + + LED_A_ON(); + + //clear buffer now so it does not interfere with timing later + BigBuf_Clear_keep_EM(); + + // Set up FPGA, 132kHz to power up the tag + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 89); + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); + + // Connect the A/D to the peak-detected low-frequency path. + SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + + // 50ms for the resonant antenna to settle. + SpinDelay(50); + + // Now set up the SSC to get the ADC samples that are now streaming at us. + FpgaSetupSsc(); + // start a 1.5ticks is 1us + StartTicks(); + + //send start pulse + TurnReadLFOn(800); + WAIT2200 + TurnReadLFOn(3600); + WAIT2200 + TurnReadLFOn(800); + WAIT2200 + TurnReadLFOn(3600); + + // Turn field on to read the response + TurnReadLFOn(READ_GAP); + + // Acquisition + doT55x7Acquisition(20000); + + // Turn the field off + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off + cmd_send(CMD_ACK,0,0,0,0,0); + LED_A_OFF(); +} diff --git a/client/Makefile b/client/Makefile index 7da69d73..0191ff25 100644 --- a/client/Makefile +++ b/client/Makefile @@ -143,6 +143,7 @@ CMDSRCS = mifarehost.c \ cmdlfvisa2000.c \ cmdlfnoralsy.c \ cmdlffdx.c \ + cmdlfcotag.c \ pm3_binlib.c \ scripting.c \ cmdscript.c \ diff --git a/client/cmdlf.c b/client/cmdlf.c index 43131428..2daa46ab 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -1192,6 +1192,7 @@ static command_t CommandTable[] = {"help", CmdHelp, 1, "This help"}, {"animal", CmdLFFdx, 1, "{ Animal RFIDs... }"}, {"awid", CmdLFAWID, 1, "{ AWID RFIDs... }"}, + {"cotag", CmdLFCOTAG, 1, "{ COTAG RFIDs... }"}, {"em4x", CmdLFEM4X, 1, "{ EM4X RFIDs... }"}, {"guard", CmdLFGuard, 1, "{ Guardall RFIDs... }"}, {"hid", CmdLFHID, 1, "{ HID RFIDs... }"}, diff --git a/client/cmdlf.h b/client/cmdlf.h index f8f048a1..80297532 100644 --- a/client/cmdlf.h +++ b/client/cmdlf.h @@ -40,6 +40,7 @@ #include "cmdlfvisa2000.h" // for VISA2000 menu #include "cmdlfnoralsy.h" // for NORALSY meny #include "cmdlffdx.h" // for FDX-B meny +#include "cmdlfcotag.h" // for COTAG meny #define T55XX_WRITE_TIMEOUT 1500 diff --git a/client/cmdlfcotag.c b/client/cmdlfcotag.c new file mode 100644 index 00000000..e200e834 --- /dev/null +++ b/client/cmdlfcotag.c @@ -0,0 +1,41 @@ +//----------------------------------------------------------------------------- +// Authored by Iceman +// +// 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. +//----------------------------------------------------------------------------- +// Low frequency COTAG commands +//----------------------------------------------------------------------------- +#include "cmdlfcotag.h" // COTAG function declarations + +static int CmdHelp(const char *Cmd); + +int CmdCOTAGRead(const char *Cmd) { + +// if (Cmd[0] == 'h' || Cmd[0] == 'H') return usage_lf_cotag_read(); + + UsbCommand c = {CMD_COTAG, {0, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + + getSamples("20000", TRUE); + return CmdFSKdemodAWID(Cmd); +} + +static command_t CommandTable[] = { + {"help", CmdHelp, 1, "This help"}, + {"read", CmdCOTAGRead, 0, "Attempt to read and extract tag data"}, + {NULL, NULL, 0, NULL} +}; + +int CmdLFCOTAG(const char *Cmd) { + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) { + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdlfcotag.h b/client/cmdlfcotag.h new file mode 100644 index 00000000..9bf7407e --- /dev/null +++ b/client/cmdlfcotag.h @@ -0,0 +1,22 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2010 iZsh +// +// 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. +//----------------------------------------------------------------------------- +// Low frequency AWID commands +//----------------------------------------------------------------------------- + +#ifndef CMDLFCOTAG_H__ +#define CMDLFCOTAG_H__ + +#include "proxmark3.h" // Definitions, USB controls, etc +#include "cmddata.h" // getSamples +#include "cmdparser.h" // CmdsParse, CmdsHelp +#include "cmdmain.h" + +int CmdLFCOTAG(const char *Cmd); +int CmdCOTAGRead(const char *Cmd); + +#endif diff --git a/client/hid-flasher/usb_cmd.h b/client/hid-flasher/usb_cmd.h index 82e4cecb..4d0f5e8e 100644 --- a/client/hid-flasher/usb_cmd.h +++ b/client/hid-flasher/usb_cmd.h @@ -95,7 +95,8 @@ typedef struct { #define CMD_PSK_SIM_TAG 0x0220 #define CMD_AWID_DEMOD_FSK 0x0221 #define CMD_VIKING_CLONE_TAG 0x0222 - +#define CMD_T55XX_WAKEUP 0x0224 +#define CMD_COTAG 0x0225 /* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ diff --git a/client/lualibs/commands.lua b/client/lualibs/commands.lua index 2347ffe5..7aaa1745 100644 --- a/client/lualibs/commands.lua +++ b/client/lualibs/commands.lua @@ -62,6 +62,7 @@ local _commands = { CMD_AWID_DEMOD_FSK = 0x0221, CMD_VIKING_CLONE_TAG = 0x0222, CMD_T55XX_WAKEUP = 0x0224, + CMD_COTAG = 0x0225, --/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ diff --git a/include/usb_cmd.h b/include/usb_cmd.h index 53ac18e7..e312f93a 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -105,6 +105,7 @@ typedef struct{ #define CMD_AWID_DEMOD_FSK 0x0221 #define CMD_VIKING_CLONE_TAG 0x0222 #define CMD_T55XX_WAKEUP 0x0224 +#define CMD_COTAG 0x0225 /* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ -- 2.39.5 From 76c0ec0ba867308c26a882bb69087fac78d2ea2f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 27 Jan 2017 10:56:14 +0100 Subject: [PATCH 09/16] FIX: missed include. for boolean defines --- client/cmdlfcotag.h | 1 + 1 file changed, 1 insertion(+) diff --git a/client/cmdlfcotag.h b/client/cmdlfcotag.h index 9bf7407e..106d2eb9 100644 --- a/client/cmdlfcotag.h +++ b/client/cmdlfcotag.h @@ -11,6 +11,7 @@ #ifndef CMDLFCOTAG_H__ #define CMDLFCOTAG_H__ +#include "util.h" // FALSE / TRUE #include "proxmark3.h" // Definitions, USB controls, etc #include "cmddata.h" // getSamples #include "cmdparser.h" // CmdsParse, CmdsHelp -- 2.39.5 From e99acd00cc0ef24aa685b86eb4623c397e082368 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 29 Jan 2017 10:41:48 +0100 Subject: [PATCH 10/16] CHG: the mifare Auth command can make use of a random nonce aswell. CHG: since sim commands are timing critical, I'm testing a smaller prand prng function from Intel --- armsrc/iso14443a.c | 110 +++++++++++++++++++++++--------------------- armsrc/mifareutil.c | 5 +- armsrc/mifareutil.h | 1 + common/random.c | 25 ++++++---- common/random.h | 4 +- 5 files changed, 81 insertions(+), 64 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index d0695501..2b4f9ea1 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -850,6 +850,8 @@ bool prepare_allocated_tag_modulation(tag_response_info_t* response_info) { void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { #define ATTACK_KEY_COUNT 8 // keep same as define in cmdhfmf.c -> readerAttack() + // init pseudorand + fast_prand(); uint8_t sak = 0; uint32_t cuid = 0; @@ -869,7 +871,7 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { uint8_t cardAUTHKEY = 0xff; // no authentication // allow collecting up to 8 sets of nonces to allow recovery of up to 8 keys - nonces_t ar_nr_resp[ATTACK_KEY_COUNT*2]; // for 2 separate attack types (nml, moebius) + nonces_t ar_nr_resp[ATTACK_KEY_COUNT*2]; // for 2 separate attack types (std, moebius) memset(ar_nr_resp, 0x00, sizeof(ar_nr_resp)); uint8_t ar_nr_collected[ATTACK_KEY_COUNT*2]; // for 2nd attack type (moebius) @@ -976,8 +978,6 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { // Tag NONCE. uint8_t response5[4]; - nonce = prand(); - num_to_bytes(nonce, 4, response5); uint8_t response6[] = { 0x04, 0x58, 0x80, 0x02, 0x00, 0x00 }; // dummy ATS (pseudo-ATR), answer to RATS: // Format byte = 0x58: FSCI=0x08 (FSC=256), TA(1) and TC(1) present, @@ -1187,57 +1187,53 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { ) { // if first auth for sector, or matches sector and keytype of previous auth - if (ar_nr_collected[i+mM] < 2) { - // if we haven't already collected 2 nonces for this sector - if (ar_nr_resp[ar_nr_collected[i+mM]].ar != ar) { - // Avoid duplicates... probably not necessary, ar should vary. - if (ar_nr_collected[i+mM]==0) { - // first nonce collect - ar_nr_resp[i+mM].cuid = cuid; - ar_nr_resp[i+mM].sector = cardAUTHSC; - ar_nr_resp[i+mM].keytype = cardAUTHKEY; - ar_nr_resp[i+mM].nonce = nonce; - ar_nr_resp[i+mM].nr = nr; - ar_nr_resp[i+mM].ar = ar; - nonce1_count++; - // add this nonce to first moebius nonce - ar_nr_resp[i+ATTACK_KEY_COUNT].cuid = cuid; - ar_nr_resp[i+ATTACK_KEY_COUNT].sector = cardAUTHSC; - ar_nr_resp[i+ATTACK_KEY_COUNT].keytype = cardAUTHKEY; - ar_nr_resp[i+ATTACK_KEY_COUNT].nonce = nonce; - ar_nr_resp[i+ATTACK_KEY_COUNT].nr = nr; - ar_nr_resp[i+ATTACK_KEY_COUNT].ar = ar; - ar_nr_collected[i+ATTACK_KEY_COUNT]++; - } else { // second nonce collect (std and moebius) - ar_nr_resp[i+mM].nonce2 = nonce; - ar_nr_resp[i+mM].nr2 = nr; - ar_nr_resp[i+mM].ar2 = ar; - if (!gettingMoebius) { - nonce2_count++; - // check if this was the last second nonce we need for std attack - if ( nonce2_count == nonce1_count ) { - // done collecting std test switch to moebius - // first finish incrementing last sample - ar_nr_collected[i+mM]++; - // switch to moebius collection - gettingMoebius = true; - mM = ATTACK_KEY_COUNT; - break; - } - } else { - moebius_n_count++; - // if we've collected all the nonces we need - finish. - if (nonce1_count == moebius_n_count) { - cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,0,0,&ar_nr_resp,sizeof(ar_nr_resp)); - nonce1_count = 0; - nonce2_count = 0; - moebius_n_count = 0; - gettingMoebius = false; - } + if (ar_nr_collected[i+mM] > 1) continue; + + // if we haven't already collected 2 nonces for this sector + if (ar_nr_resp[ar_nr_collected[i+mM]].ar != ar) { + // Avoid duplicates... probably not necessary, ar should vary. + if (ar_nr_collected[i+mM]==0) { + // first nonce collect + nonce1_count++; + // add this nonce to first moebius nonce + ar_nr_resp[i+ATTACK_KEY_COUNT].cuid = cuid; + ar_nr_resp[i+ATTACK_KEY_COUNT].sector = cardAUTHSC; + ar_nr_resp[i+ATTACK_KEY_COUNT].keytype = cardAUTHKEY; + ar_nr_resp[i+ATTACK_KEY_COUNT].nonce = nonce; + ar_nr_resp[i+ATTACK_KEY_COUNT].nr = nr; + ar_nr_resp[i+ATTACK_KEY_COUNT].ar = ar; + ar_nr_collected[i+ATTACK_KEY_COUNT]++; + } else { + // second nonce collect (std and moebius) + ar_nr_resp[i+mM].nonce2 = nonce; + ar_nr_resp[i+mM].nr2 = nr; + ar_nr_resp[i+mM].ar2 = ar; + + if (!gettingMoebius) { + nonce2_count++; + // check if this was the last second nonce we need for std attack + if ( nonce2_count == nonce1_count ) { + // done collecting std test switch to moebius + // first finish incrementing last sample + ar_nr_collected[i+mM]++; + // switch to moebius collection + gettingMoebius = true; + mM = ATTACK_KEY_COUNT; + break; + } + } else { + moebius_n_count++; + // if we've collected all the nonces we need - finish. + if (nonce1_count == moebius_n_count) { + cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,0,0,&ar_nr_resp,sizeof(ar_nr_resp)); + nonce1_count = 0; + nonce2_count = 0; + moebius_n_count = 0; + gettingMoebius = false; } } - ar_nr_collected[i+mM]++; } + ar_nr_collected[i+mM]++; } // we found right spot for this nonce stop looking break; @@ -1372,6 +1368,7 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { LED_A_OFF(); if(flags & FLAG_NR_AR_ATTACK && MF_DBGLEVEL >= 1) { + /* for ( uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) { if (ar_nr_collected[i] == 2) { Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i= 4) Dbprintf("Re-read after previous NR_AR_ATTACK, resetting buffer"); memset(ar_nr_resp, 0x00, sizeof(ar_nr_resp)); memset(ar_nr_collected, 0x00, sizeof(ar_nr_collected)); mM = 0; @@ -3116,7 +3120,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * if (MF_DBGLEVEL >= 1) Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", tracing, BigBuf_get_traceLen()); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + cmd_send(CMD_ACK,1,0,0,0,0); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); set_tracing(FALSE); } diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index 4795a7ec..4100ef54 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -121,7 +121,10 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN // "random" reader nonce: //byte_t nr[4] = {0x55, 0x41, 0x49, 0x92}; - byte_t nr[4] = {0x01, 0x01, 0x01, 0x01}; + fast_prand(); + byte_t nr[4]; + num_to_bytes(prand(), 4, nr); + //byte_t nr[4] = {0x01, 0x01, 0x01, 0x01}; uint32_t nt, ntpp; // Supplied tag nonce diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index 041da212..c07bc579 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -21,6 +21,7 @@ #include "iso14443a.h" #include "crapto1.h" #include "des.h" +#include "random.h" // fast_prand, prand // mifare authentication #define CRYPT_NONE 0 diff --git a/common/random.c b/common/random.c index df549968..5658683d 100644 --- a/common/random.c +++ b/common/random.c @@ -1,6 +1,6 @@ #include "random.h" - uint64_t next_random = 1; +static uint32_t g_nextrandom; /* Generates a (non-cryptographically secure) 32-bit random number. * @@ -8,14 +8,23 @@ * method of seeding with the time it took to call "autoseed" from first run. * * https://github.com/Proxmark/proxmark3/pull/209/commits/f9c1dcd9f6e68a8c07cffed697a9c4c8caed6015 + * + * Iceman, rand needs to be fast. + * https://software.intel.com/en-us/articles/fast-random-number-generator-on-the-intel-pentiumr-4-processor/ */ + +inline void fast_prand(){ + fast_prandEx(GetTickCount()); +} +inline void fast_prandEx(uint32_t seed) { + g_nextrandom = seed; +} + uint32_t prand() { - if (next_random == 1) - next_random = GetTickCount(); - - next_random *= 6364136223846793005; - next_random += 1; - - return (uint32_t)(next_random >> 32) % 0xffffffff; +// g_nextrandom *= 6364136223846793005; +// g_nextrandom += 1; +//return (uint32_t)(g_nextrandom >> 32) % 0xffffffff; + g_nextrandom = (214013 * g_nextrandom + 2531011); + return (g_nextrandom>>16) & 0xFFFF; } diff --git a/common/random.h b/common/random.h index 45f176d3..800ad810 100644 --- a/common/random.h +++ b/common/random.h @@ -15,7 +15,7 @@ #include "common.h" #include "ticks.h" - +void fast_prand(); +void fast_prandEx(uint32_t seed); uint32_t prand(); - #endif \ No newline at end of file -- 2.39.5 From 7e735c1398b9c3643d292614db10c7e58c58db85 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 29 Jan 2017 11:29:15 +0100 Subject: [PATCH 11/16] FIX: 'hf 14a sim x' - this fixes the error with using moebius attack and sim. Updating the nonce variable doesn't change the premodulated response. And it should update everytime it gets a command. One concering issue is that this takes time. Successfully works with two PM3. One acting reader, another sim. --- armsrc/iso14443a.c | 33 ++++++----- client/cmdhfmf.c | 104 ++++++++++++++++++----------------- client/nonce2key/nonce2key.c | 5 +- 3 files changed, 74 insertions(+), 68 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 2b4f9ea1..d49e6ae1 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1058,12 +1058,7 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { if(!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)) { DbpString("Button press"); break; - } - - // incease nonce at every command recieved - nonce = prand(); - num_to_bytes(nonce, 4, response5); - + } p_response = NULL; // Okay, look at the command now. @@ -1158,6 +1153,12 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { EmSendCmdEx(emdata, sizeof(emdata), false); p_response = NULL; } else { + + // incease nonce at every command recieved. this is time consuming. + nonce = prand(); + num_to_bytes(nonce, 4, response5); + prepare_tag_modulation(&responses[5], DYNAMIC_MODULATION_BUFFER_SIZE); + cardAUTHSC = receivedCmd[1] / 4; // received block num cardAUTHKEY = receivedCmd[0] - 0x60; p_response = &responses[5]; order = 7; @@ -1173,7 +1174,7 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); uint32_t nr = bytes_to_num(receivedCmd,4); uint32_t ar = bytes_to_num(receivedCmd+4,4); - + // Collect AR/NR per keytype & sector if ( (flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK ) { @@ -1279,8 +1280,8 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { dynamic_response_info.response_n = 2; } break; - case 0xaa: - case 0xbb: { + case 0xAA: + case 0xBB: { dynamic_response_info.response[0] = receivedCmd[0] ^ 0x11; dynamic_response_info.response_n = 2; } break; @@ -1313,7 +1314,7 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { dynamic_response_info.response[1] = receivedCmd[1]; // Add CRC bytes, always used in ISO 14443A-4 compliant cards - AppendCrc14443a(dynamic_response_info.response,dynamic_response_info.response_n); + AppendCrc14443a(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) { @@ -1333,7 +1334,7 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { // comment this limit if you want to simulation longer if (!tracing) { - Dbprintf("Trace Full. Simulation stopped."); + DbpString("Trace Full. Simulation stopped."); break; } // comment this limit if you want to simulation longer @@ -1366,9 +1367,10 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { set_tracing(FALSE); BigBuf_free_keep_EM(); LED_A_OFF(); - + + /* if(flags & FLAG_NR_AR_ATTACK && MF_DBGLEVEL >= 1) { - /* + for ( uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) { if (ar_nr_collected[i] == 2) { Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i= 4){ Dbprintf("-[ Wake ups after halt [%d]", happened); Dbprintf("-[ Messages after halt [%d]", happened2); diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 0ea171af..6b944df3 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1383,62 +1383,64 @@ void readerAttack(nonces_t data[], bool setEmulatorMem, bool verbose) { printf("enter reader attack\n"); for (uint8_t i = 0; i < ATTACK_KEY_COUNT; ++i) { - if (data[i].ar2 > 0) { + + // if no-collected data + if (data[i].ar2 == 0) continue; - // We can probably skip this, mfkey32v2 is more reliable. + // We can probably skip this, mfkey32v2 is more reliable. #ifdef HFMF_TRYMFK32 - if (tryMfk32(data[i], &key, verbose)) { - PrintAndLog("Found Key%s for sector %02d: [%012"llx"]" - , (data[i].keytype) ? "B" : "A" - , data[i].sector - , key - ); - - k_sector[i].Key[data[i].keytype] = key; - k_sector[i].foundKey[data[i].keytype] = TRUE; - - //set emulator memory for keys - if (setEmulatorMem) { - uint8_t memBlock[16] = {0,0,0,0,0,0, 0xff, 0x0F, 0x80, 0x69, 0,0,0,0,0,0}; - num_to_bytes( k_sector[i].Key[0], 6, memBlock); - num_to_bytes( k_sector[i].Key[1], 6, memBlock+10); - PrintAndLog("Setting Emulator Memory Block %02d: [%s]" - , ((data[i].sector)*4) + 3 - , sprint_hex( memBlock, sizeof(memBlock)) - ); - mfEmlSetMem( memBlock, ((data[i].sector)*4) + 3, 1); - } - continue; + if (tryMfk32(data[i], &key, verbose)) { + PrintAndLog("Found Key%s for sector %02d: [%012"llx"]" + , (data[i].keytype) ? "B" : "A" + , data[i].sector + , key + ); + + k_sector[i].Key[data[i].keytype] = key; + k_sector[i].foundKey[data[i].keytype] = TRUE; + + //set emulator memory for keys + if (setEmulatorMem) { + uint8_t memBlock[16] = {0,0,0,0,0,0, 0xff, 0x0F, 0x80, 0x69, 0,0,0,0,0,0}; + num_to_bytes( k_sector[i].Key[0], 6, memBlock); + num_to_bytes( k_sector[i].Key[1], 6, memBlock+10); + PrintAndLog("Setting Emulator Memory Block %02d: [%s]" + , ((data[i].sector)*4) + 3 + , sprint_hex( memBlock, sizeof(memBlock)) + ); + mfEmlSetMem( memBlock, ((data[i].sector)*4) + 3, 1); } + continue; + } #endif - //moebius attack - if (tryMfk32_moebius(data[i+ATTACK_KEY_COUNT], &key, verbose)) { - uint8_t sectorNum = data[i+ATTACK_KEY_COUNT].sector; - uint8_t keyType = data[i+ATTACK_KEY_COUNT].keytype; - - PrintAndLog("M-Found Key%s for sector %02d: [%012"llx"]" - , keyType ? "B" : "A" - , sectorNum - , key - ); - - k_sector[sectorNum].Key[keyType] = key; - k_sector[sectorNum].foundKey[keyType] = TRUE; - - //set emulator memory for keys - if (setEmulatorMem) { - uint8_t memBlock[16] = {0,0,0,0,0,0, 0xff, 0x0F, 0x80, 0x69, 0,0,0,0,0,0}; - num_to_bytes( k_sector[sectorNum].Key[0], 6, memBlock); - num_to_bytes( k_sector[sectorNum].Key[1], 6, memBlock+10); - PrintAndLog("Setting Emulator Memory Block %02d: [%s]" - , (sectorNum*4) + 3 - , sprint_hex( memBlock, sizeof(memBlock)) - ); - mfEmlSetMem( memBlock, (sectorNum*4) + 3, 1); - } - continue; + + //moebius attack + if (tryMfk32_moebius(data[i+ATTACK_KEY_COUNT], &key, verbose)) { + uint8_t sectorNum = data[i+ATTACK_KEY_COUNT].sector; + uint8_t keyType = data[i+ATTACK_KEY_COUNT].keytype; + + PrintAndLog("Found Key%s for sector %02d: [%012"llx"]" + , keyType ? "B" : "A" + , sectorNum + , key + ); + + k_sector[sectorNum].Key[keyType] = key; + k_sector[sectorNum].foundKey[keyType] = TRUE; + + //set emulator memory for keys + if (setEmulatorMem) { + uint8_t memBlock[16] = {0,0,0,0,0,0, 0xff, 0x0F, 0x80, 0x69, 0,0,0,0,0,0}; + num_to_bytes( k_sector[sectorNum].Key[0], 6, memBlock); + num_to_bytes( k_sector[sectorNum].Key[1], 6, memBlock+10); + //iceman, guessing this will not work so well for 4K tags. + PrintAndLog("Setting Emulator Memory Block %02d: [%s]" + , (sectorNum*4) + 3 + , sprint_hex( memBlock, sizeof(memBlock)) + ); + mfEmlSetMem( memBlock, (sectorNum*4) + 3, 1); } - + continue; } } } diff --git a/client/nonce2key/nonce2key.c b/client/nonce2key/nonce2key.c index fa734144..64d35873 100644 --- a/client/nonce2key/nonce2key.c +++ b/client/nonce2key/nonce2key.c @@ -280,8 +280,9 @@ bool tryMfk32_moebius(nonces_t data, uint64_t *outputkey, bool verbose) { } isSuccess = (counter > 0); t1 = clock() - t1; - if ( t1 > 0 ) PrintAndLog("Time in mfkey32_moebius: %.0f ticks - possible keys %d", (float)t1, counter); - + if (verbose) { + if ( t1 > 0 ) PrintAndLog("Time in mfkey32_moebius: %.0f ticks - possible keys %d", (float)t1, counter); + } *outputkey = ( isSuccess ) ? outkey : 0; crypto1_destroy(s); return isSuccess; -- 2.39.5 From 2ce218042d2aebdfa4c5a58f19e6550f367c5d81 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 29 Jan 2017 13:21:17 +0100 Subject: [PATCH 12/16] CHG: 'hf 14a sim e' - it now has a parameter for setfoundkeys to emulator memory. CHG: textual changes. --- client/cmdhf14a.c | 38 ++++++++++++++++++++++---------------- client/cmdhfmf.c | 17 +++++++++-------- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 6411a919..ca8b8c1d 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -130,9 +130,9 @@ char* getTagInfo(uint8_t uid) { int usage_hf_14a_sim(void) { // PrintAndLog("\n Emulating ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n"); PrintAndLog("\n Emulating ISO/IEC 14443 type A tag with 4,7 byte UID\n"); - PrintAndLog("Usage: hf 14a sim t u x"); - PrintAndLog(" Options : "); - PrintAndLog(" h : this help"); + PrintAndLog("usage: hf 14a sim [h] t u [x] [e] [v]"); + PrintAndLog("options: "); + PrintAndLog(" h : This help"); PrintAndLog(" t : 1 = MIFARE Classic"); PrintAndLog(" 2 = MIFARE Ultralight"); PrintAndLog(" 3 = MIFARE Desfire"); @@ -142,12 +142,14 @@ int usage_hf_14a_sim(void) { PrintAndLog(" 7 = AMIIBO (NTAG 215), pack 0x8080"); // PrintAndLog(" u : 4, 7 or 10 byte UID"); PrintAndLog(" u : 4, 7 byte UID"); - PrintAndLog(" x : (Optional) performs the 'reader attack', nr/ar attack against a legitimate reader"); - PrintAndLog(" v : (Optional) show maths used for cracking reader. Useful for debugging."); - PrintAndLog("\n sample : hf 14a sim t 1 u 11223344 x"); - PrintAndLog(" : hf 14a sim t 1 u 11223344"); - PrintAndLog(" : hf 14a sim t 1 u 11223344556677"); -// PrintAndLog(" : hf 14a sim t 1 u 11223445566778899AA\n"); + PrintAndLog(" x : (Optional) Performs the 'reader attack', nr/ar attack against a reader"); + PrintAndLog(" e : (Optional) Fill simulator keys from found keys"); + PrintAndLog(" v : (Optional) Verbose"); + PrintAndLog("samples:"); + PrintAndLog(" hf 14a sim t 1 u 11223344 x"); + PrintAndLog(" hf 14a sim t 1 u 11223344"); + PrintAndLog(" hf 14a sim t 1 u 11223344556677"); +// PrintAndLog(" hf 14a sim t 1 u 11223445566778899AA\n"); return 0; } int usage_hf_14a_sniff(void){ @@ -447,7 +449,8 @@ int CmdHF14ASim(const char *Cmd) { uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0}; int uidlen = 0; bool useUIDfromEML = TRUE; - bool verbose = false; + bool setEmulatorMem = FALSE; + bool verbose = FALSE; while(param_getchar(Cmd, cmdp) != 0x00) { switch(param_getchar(Cmd, cmdp)) { @@ -459,7 +462,7 @@ int CmdHF14ASim(const char *Cmd) { // Retrieve the tag type tagtype = param_get8ex(Cmd, cmdp+1, 0, 10); if (tagtype == 0) - errors = true; + errors = TRUE; cmdp += 2; break; case 'u': @@ -488,6 +491,11 @@ int CmdHF14ASim(const char *Cmd) { flags |= FLAG_NR_AR_ATTACK; cmdp++; break; + case 'e': + case 'E': + setEmulatorMem = TRUE; + cmdp++; + break; default: PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; @@ -502,8 +510,6 @@ int CmdHF14ASim(const char *Cmd) { if ( useUIDfromEML ) flags |= FLAG_UID_IN_EMUL; - PrintAndLog("Press pm3-button to abort simulation"); - UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,{ tagtype, flags, 0 }}; memcpy(c.d.asBytes, uid, uidlen>>1); clearCommandBuffer(); @@ -511,15 +517,15 @@ int CmdHF14ASim(const char *Cmd) { nonces_t data[ATTACK_KEY_COUNT*2]; UsbCommand resp; - + + PrintAndLog("Press pm3-button to abort simulation"); while( !ukbhit() ){ if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) continue; - if ( !(flags & FLAG_NR_AR_ATTACK) ) break; if ( (resp.arg[0] & 0xffff) != CMD_SIMULATE_MIFARE_CARD ) break; memcpy( data, resp.d.asBytes, sizeof(data) ); - readerAttack(data, TRUE, verbose); + readerAttack(data, setEmulatorMem, verbose); } return 0; } diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 6b944df3..36438d7f 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -24,19 +24,20 @@ int usage_hf14_mifare(void){ return 0; } int usage_hf14_mf1ksim(void){ - PrintAndLog("Usage: hf mf sim [h] u n i x"); + PrintAndLog("Usage: hf mf sim [h] u n [i] [x] [e] [v]"); PrintAndLog("options:"); PrintAndLog(" h this help"); PrintAndLog(" u (Optional) UID 4,7 or 10bytes. If not specified, the UID 4b from emulator memory will be used"); PrintAndLog(" n (Optional) Automatically exit simulation after blocks have been read by reader. 0 = infinite"); PrintAndLog(" i (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted"); - PrintAndLog(" x (Optional) Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s)"); - PrintAndLog(" e (Optional) Fill simulator keys from what we crack"); - PrintAndLog(" v (Optional) Show maths used for cracking reader. Useful for debugging."); + PrintAndLog(" x (Optional) Crack, performs the 'reader attack', nr/ar attack against a reader"); + PrintAndLog(" e (Optional) Fill simulator keys from found keys"); + PrintAndLog(" v (Optional) Verbose"); PrintAndLog("samples:"); PrintAndLog(" hf mf sim u 0a0a0a0a"); PrintAndLog(" hf mf sim u 11223344556677"); PrintAndLog(" hf mf sim u 112233445566778899AA"); + PrintAndLog(" hf mf sim u 11223344 i x"); return 0; } int usage_hf14_dbg(void){ @@ -1381,7 +1382,8 @@ void readerAttack(nonces_t data[], bool setEmulatorMem, bool verbose) { k_sector[i].foundKey[1] = FALSE; } - printf("enter reader attack\n"); + if (verbose) printf("enter Moebius attack (mfkey32v2) \n"); + for (uint8_t i = 0; i < ATTACK_KEY_COUNT; ++i) { // if no-collected data @@ -1419,7 +1421,7 @@ void readerAttack(nonces_t data[], bool setEmulatorMem, bool verbose) { uint8_t sectorNum = data[i+ATTACK_KEY_COUNT].sector; uint8_t keyType = data[i+ATTACK_KEY_COUNT].keytype; - PrintAndLog("Found Key%s for sector %02d: [%012"llx"]" + PrintAndLog("Reader is trying authenticate with: Key %s, sector %02d: [%012"llx"]" , keyType ? "B" : "A" , sectorNum , key @@ -1528,7 +1530,6 @@ int CmdHF14AMf1kSim(const char *Cmd) { while( !ukbhit() ){ if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) continue; - if ( !(flags & FLAG_NR_AR_ATTACK) ) break; if ( (resp.arg[0] & 0xffff) != CMD_SIMULATE_MIFARE_CARD ) break; @@ -1537,7 +1538,7 @@ int CmdHF14AMf1kSim(const char *Cmd) { } if (k_sector != NULL) { - printKeyTable(k_sectorsCount, k_sector ); + printKeyTable(k_sectorsCount, k_sector); free(k_sector); k_sector = NULL; } -- 2.39.5 From 84bdbc19174eaf54db337ef0470e35cf45dc8e9d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 29 Jan 2017 23:09:23 +0100 Subject: [PATCH 13/16] FIX: 'hf 14a sim x' - adjusted and shows messages when verbose. FIX: 'hf mf sim x i' - same as above. In general we only use Moebius attack for "sim x", that means a clean up on device side code. simpler to understand. It still tries to gather 8 different collections of nonces combo. When one is complete, it get sent to client which runs moebius direct. --- armsrc/iso14443a.c | 348 ++++++++++++++++----------------------------- client/cmdhf14a.c | 16 +-- client/cmdhfmf.c | 141 +++++++----------- client/cmdhfmf.h | 3 +- include/mifare.h | 5 + 5 files changed, 196 insertions(+), 317 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index d49e6ae1..39604874 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -871,17 +871,9 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { uint8_t cardAUTHKEY = 0xff; // no authentication // allow collecting up to 8 sets of nonces to allow recovery of up to 8 keys - nonces_t ar_nr_resp[ATTACK_KEY_COUNT*2]; // for 2 separate attack types (std, moebius) - memset(ar_nr_resp, 0x00, sizeof(ar_nr_resp)); - - uint8_t ar_nr_collected[ATTACK_KEY_COUNT*2]; // for 2nd attack type (moebius) - memset(ar_nr_collected, 0x00, sizeof(ar_nr_collected)); - uint8_t nonce1_count = 0; - uint8_t nonce2_count = 0; - uint8_t moebius_n_count = 0; - bool gettingMoebius = false; - uint8_t mM = 0; // moebius_modifier for collection storage - + nonces_t ar_nr_nonces[ATTACK_KEY_COUNT]; // for attack types moebius + memset(ar_nr_nonces, 0x00, sizeof(ar_nr_nonces)); + uint8_t moebius_count = 0; switch (tagType) { case 1: { // MIFARE Classic 1k @@ -1056,7 +1048,7 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { // Clean receive command buffer if(!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)) { - DbpString("Button press"); + Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", tracing, BigBuf_get_traceLen()); break; } p_response = NULL; @@ -1153,15 +1145,21 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { EmSendCmdEx(emdata, sizeof(emdata), false); p_response = NULL; } else { + + cardAUTHKEY = receivedCmd[0] - 0x60; + cardAUTHSC = receivedCmd[1] / 4; // received block num - // incease nonce at every command recieved. this is time consuming. + // incease nonce at AUTH requests. this is time consuming. nonce = prand(); - num_to_bytes(nonce, 4, response5); - prepare_tag_modulation(&responses[5], DYNAMIC_MODULATION_BUFFER_SIZE); - - cardAUTHSC = receivedCmd[1] / 4; // received block num - cardAUTHKEY = receivedCmd[0] - 0x60; - p_response = &responses[5]; order = 7; + //num_to_bytes(nonce, 4, response5); + num_to_bytes(nonce, 4, dynamic_response_info.response); + dynamic_response_info.response_n = 4; + + //prepare_tag_modulation(&responses[5], DYNAMIC_MODULATION_BUFFER_SIZE); + prepare_tag_modulation(&dynamic_response_info, DYNAMIC_MODULATION_BUFFER_SIZE); + p_response = &dynamic_response_info; + //p_response = &responses[5]; + order = 7; } } else if(receivedCmd[0] == ISO14443A_CMD_RATS) { // Received a RATS request if (tagType == 1 || tagType == 2) { // RATS not supported @@ -1178,69 +1176,60 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { // Collect AR/NR per keytype & sector if ( (flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK ) { - for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) { + int8_t index = -1; + int8_t empty = -1; + for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) { + // find which index to use + if ( (cardAUTHSC == ar_nr_nonces[i].sector) && (cardAUTHKEY == ar_nr_nonces[i].keytype)) + index = i; + + // keep track of empty slots. + if ( ar_nr_nonces[i].state == EMPTY) + empty = i; + } + // if no empty slots. Choose first and overwrite. + if ( index == -1 ) { + if ( empty == -1 ) { + index = 0; + ar_nr_nonces[index].state = EMPTY; + } else { + index = empty; + } + } + + switch(ar_nr_nonces[index].state) { + case EMPTY: { + // first nonce collect + ar_nr_nonces[index].cuid = cuid; + ar_nr_nonces[index].sector = cardAUTHSC; + ar_nr_nonces[index].keytype = cardAUTHKEY; + ar_nr_nonces[index].nonce = nonce; + ar_nr_nonces[index].nr = nr; + ar_nr_nonces[index].ar = ar; + ar_nr_nonces[index].state = FIRST; + break; + } + case FIRST : { + // second nonce collect + ar_nr_nonces[index].nonce2 = nonce; + ar_nr_nonces[index].nr2 = nr; + ar_nr_nonces[index].ar2 = ar; + ar_nr_nonces[index].state = SECOND; + + // send to client + cmd_send(CMD_ACK, CMD_SIMULATE_MIFARE_CARD, 0, 0, &ar_nr_nonces[index], sizeof(nonces_t)); - if ( ar_nr_collected[i+mM] == 0 || ( - (cardAUTHSC == ar_nr_resp[i+mM].sector) && - (cardAUTHKEY == ar_nr_resp[i+mM].keytype) && - (ar_nr_collected[i+mM] > 0) - ) - ) { - - // if first auth for sector, or matches sector and keytype of previous auth - if (ar_nr_collected[i+mM] > 1) continue; - - // if we haven't already collected 2 nonces for this sector - if (ar_nr_resp[ar_nr_collected[i+mM]].ar != ar) { - // Avoid duplicates... probably not necessary, ar should vary. - if (ar_nr_collected[i+mM]==0) { - // first nonce collect - nonce1_count++; - // add this nonce to first moebius nonce - ar_nr_resp[i+ATTACK_KEY_COUNT].cuid = cuid; - ar_nr_resp[i+ATTACK_KEY_COUNT].sector = cardAUTHSC; - ar_nr_resp[i+ATTACK_KEY_COUNT].keytype = cardAUTHKEY; - ar_nr_resp[i+ATTACK_KEY_COUNT].nonce = nonce; - ar_nr_resp[i+ATTACK_KEY_COUNT].nr = nr; - ar_nr_resp[i+ATTACK_KEY_COUNT].ar = ar; - ar_nr_collected[i+ATTACK_KEY_COUNT]++; - } else { - // second nonce collect (std and moebius) - ar_nr_resp[i+mM].nonce2 = nonce; - ar_nr_resp[i+mM].nr2 = nr; - ar_nr_resp[i+mM].ar2 = ar; - - if (!gettingMoebius) { - nonce2_count++; - // check if this was the last second nonce we need for std attack - if ( nonce2_count == nonce1_count ) { - // done collecting std test switch to moebius - // first finish incrementing last sample - ar_nr_collected[i+mM]++; - // switch to moebius collection - gettingMoebius = true; - mM = ATTACK_KEY_COUNT; - break; - } - } else { - moebius_n_count++; - // if we've collected all the nonces we need - finish. - if (nonce1_count == moebius_n_count) { - cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,0,0,&ar_nr_resp,sizeof(ar_nr_resp)); - nonce1_count = 0; - nonce2_count = 0; - moebius_n_count = 0; - gettingMoebius = false; - } - } - } - ar_nr_collected[i+mM]++; - } - // we found right spot for this nonce stop looking - break; - } + ar_nr_nonces[index].state = EMPTY; + ar_nr_nonces[index].sector = 0; + ar_nr_nonces[index].keytype = 0; + + moebius_count++; + break; } + default: break; } + } + p_response = NULL; } else if (receivedCmd[0] == MIFARE_ULC_AUTH_1 ) { // ULC authentication, or Desfire Authentication } else if (receivedCmd[0] == MIFARE_ULEV1_AUTH) { // NTAG / EV-1 authentication @@ -1318,7 +1307,7 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { dynamic_response_info.response_n += 2; if (prepare_tag_modulation(&dynamic_response_info,DYNAMIC_MODULATION_BUFFER_SIZE) == false) { - Dbprintf("Error preparing tag response"); + DbpString("Error preparing tag response"); LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); break; } @@ -1403,9 +1392,10 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { */ if (MF_DBGLEVEL >= 4){ - Dbprintf("-[ Wake ups after halt [%d]", happened); - Dbprintf("-[ Messages after halt [%d]", happened2); - Dbprintf("-[ Num of received cmd [%d]", cmdsRecvd); + Dbprintf("-[ Wake ups after halt [%d]", happened); + Dbprintf("-[ Messages after halt [%d]", happened2); + Dbprintf("-[ Num of received cmd [%d]", cmdsRecvd); + Dbprintf("-[ Num of moebius tries [%d]", moebius_count); } cmd_send(CMD_ACK,1,0,0,0,0); @@ -2500,17 +2490,8 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * // Here, we collect CUID, NT, NR, AR, CUID2, NT2, NR2, AR2 // This can be used in a reader-only attack. - nonces_t ar_nr_resp[ATTACK_KEY_COUNT*2]; // for 2 separate attack types (nml, moebius) - memset(ar_nr_resp, 0x00, sizeof(ar_nr_resp)); - - uint8_t ar_nr_collected[ATTACK_KEY_COUNT*2]; // for 2nd attack type (moebius) - memset(ar_nr_collected, 0x00, sizeof(ar_nr_collected)); - uint8_t nonce1_count = 0; - uint8_t nonce2_count = 0; - uint8_t moebius_n_count = 0; - bool gettingMoebius = false; - uint8_t mM = 0; // moebius_modifier for collection storage - bool doBufResetNext = false; + nonces_t ar_nr_nonces[ATTACK_KEY_COUNT]; + memset(ar_nr_nonces, 0x00, sizeof(ar_nr_nonces)); // -- Determine the UID // Can be set from emulator memory or incoming data @@ -2752,101 +2733,63 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * uint32_t nr = bytes_to_num(receivedCmd, 4); uint32_t ar = bytes_to_num(&receivedCmd[4], 4); - if (doBufResetNext) { - // Reset, lets try again! - if (MF_DBGLEVEL >= 4) Dbprintf("Re-read after previous NR_AR_ATTACK, resetting buffer"); - memset(ar_nr_resp, 0x00, sizeof(ar_nr_resp)); - memset(ar_nr_collected, 0x00, sizeof(ar_nr_collected)); - mM = 0; - doBufResetNext = false; - } - - for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) { + // Collect AR/NR per keytype & sector + if ( (flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK ) { - if ( ar_nr_collected[i+mM] == 0 || ( - (cardAUTHSC == ar_nr_resp[i+mM].sector) && - (cardAUTHKEY == ar_nr_resp[i+mM].keytype) && - (ar_nr_collected[i+mM] > 0) - ) - ) { - - // if first auth for sector, or matches sector and keytype of previous auth - if (ar_nr_collected[i+mM] < 2) { - // if we haven't already collected 2 nonces for this sector - if (ar_nr_resp[ar_nr_collected[i+mM]].ar != ar) { - // Avoid duplicates... probably not necessary, ar should vary. - if (ar_nr_collected[i+mM]==0) { - // first nonce collect - ar_nr_resp[i+mM].cuid = cuid; - ar_nr_resp[i+mM].sector = cardAUTHSC; - ar_nr_resp[i+mM].keytype = cardAUTHKEY; - ar_nr_resp[i+mM].nonce = nonce; - ar_nr_resp[i+mM].nr = nr; - ar_nr_resp[i+mM].ar = ar; - nonce1_count++; - // add this nonce to first moebius nonce - ar_nr_resp[i+ATTACK_KEY_COUNT].cuid = cuid; - ar_nr_resp[i+ATTACK_KEY_COUNT].sector = cardAUTHSC; - ar_nr_resp[i+ATTACK_KEY_COUNT].keytype = cardAUTHKEY; - ar_nr_resp[i+ATTACK_KEY_COUNT].nonce = nonce; - ar_nr_resp[i+ATTACK_KEY_COUNT].nr = nr; - ar_nr_resp[i+ATTACK_KEY_COUNT].ar = ar; - ar_nr_collected[i+ATTACK_KEY_COUNT]++; - } else { // second nonce collect (std and moebius) - ar_nr_resp[i+mM].nonce2 = nonce; - ar_nr_resp[i+mM].nr2 = nr; - ar_nr_resp[i+mM].ar2 = ar; - if (!gettingMoebius) { - nonce2_count++; - // check if this was the last second nonce we need for std attack - if ( nonce2_count == nonce1_count ) { - // done collecting std test switch to moebius - // first finish incrementing last sample - ar_nr_collected[i+mM]++; - // switch to moebius collection - gettingMoebius = true; - mM = ATTACK_KEY_COUNT; - break; - } - } else { - moebius_n_count++; - // if we've collected all the nonces we need - finish. - - if (nonce1_count == moebius_n_count) { - cmd_send(CMD_ACK, CMD_SIMULATE_MIFARE_CARD, 0, 0, &ar_nr_resp, sizeof(ar_nr_resp)); - nonce1_count = 0; - nonce2_count = 0; - moebius_n_count = 0; - gettingMoebius = false; - doBufResetNext = true; - finished = ( ((flags & FLAG_INTERACTIVE) == FLAG_INTERACTIVE)); - } - } - } - ar_nr_collected[i+mM]++; - } + int8_t index = -1; + int8_t empty = -1; + for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) { + // find which index to use + if ( (cardAUTHSC == ar_nr_nonces[i].sector) && (cardAUTHKEY == ar_nr_nonces[i].keytype)) + index = i; + + // keep track of empty slots. + if ( ar_nr_nonces[i].state == EMPTY) + empty = i; + } + // if no empty slots. Choose first and overwrite. + if ( index == -1 ) { + if ( empty == -1 ) { + index = 0; + ar_nr_nonces[index].state = EMPTY; + } else { + index = empty; } - // we found right spot for this nonce stop looking - break; } - } + switch(ar_nr_nonces[index].state) { + case EMPTY: { + // first nonce collect + ar_nr_nonces[index].cuid = cuid; + ar_nr_nonces[index].sector = cardAUTHSC; + ar_nr_nonces[index].keytype = cardAUTHKEY; + ar_nr_nonces[index].nonce = nonce; + ar_nr_nonces[index].nr = nr; + ar_nr_nonces[index].ar = ar; + ar_nr_nonces[index].state = FIRST; + break; + } + case FIRST : { + // second nonce collect + ar_nr_nonces[index].nonce2 = nonce; + ar_nr_nonces[index].nr2 = nr; + ar_nr_nonces[index].ar2 = ar; + ar_nr_nonces[index].state = SECOND; + + // send to client + cmd_send(CMD_ACK, CMD_SIMULATE_MIFARE_CARD, 0, 0, &ar_nr_nonces[index], sizeof(nonces_t)); + + ar_nr_nonces[index].state = EMPTY; + ar_nr_nonces[index].sector = 0; + ar_nr_nonces[index].keytype = 0; + break; + } + default: break; + } + } /* - // Collect AR/NR - // if(ar_nr_collected < 2 && cardAUTHSC == 2){ - if(ar_nr_collected < 2) { - // if(ar_nr_responses[2] != nr) { - ar_nr_responses[ar_nr_collected*4] = cuid; - ar_nr_responses[ar_nr_collected*4+1] = nonce; - ar_nr_responses[ar_nr_collected*4+2] = nr; - ar_nr_responses[ar_nr_collected*4+3] = ar; - ar_nr_collected++; - // } - - // Interactive mode flag, means we need to send ACK - finished = ( ((flags & FLAG_INTERACTIVE) == FLAG_INTERACTIVE)&& ar_nr_collected == 2); - } + // Interactive mode flag, means we need to send ACK crypto1_word(pcs, ar , 1); cardRr = nr ^ crypto1_word(pcs, 0, 0); @@ -3081,45 +3024,6 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * } } - // Interactive mode flag, means we need to send ACK - /* - if((flags & FLAG_INTERACTIVE) == FLAG_INTERACTIVE && flags & FLAG_NR_AR_ATTACK == FLAG_NR_AR_ATTACK) { - // May just aswell send the collected ar_nr in the response aswell - uint8_t len = ar_nr_collected * 4 * 4; - cmd_send(CMD_ACK, CMD_SIMULATE_MIFARE_CARD, len, 0, &ar_nr_responses, len); - } - */ - - if( ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK ) && MF_DBGLEVEL >= 1 ) { - for ( uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) { - if (ar_nr_collected[i] == 2) { - Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i= 1) Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", tracing, BigBuf_get_traceLen()); diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index ca8b8c1d..b6c8b3c9 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -441,7 +441,6 @@ int CmdHF14ACUIDs(const char *Cmd) { // ## simulate iso14443a tag // ## greg - added ability to specify tag UID int CmdHF14ASim(const char *Cmd) { - #define ATTACK_KEY_COUNT 8 bool errors = FALSE; uint8_t flags = 0; uint8_t tagtype = 1; @@ -451,7 +450,8 @@ int CmdHF14ASim(const char *Cmd) { bool useUIDfromEML = TRUE; bool setEmulatorMem = FALSE; bool verbose = FALSE; - + nonces_t data[1]; + while(param_getchar(Cmd, cmdp) != 0x00) { switch(param_getchar(Cmd, cmdp)) { case 'h': @@ -483,7 +483,7 @@ int CmdHF14ASim(const char *Cmd) { break; case 'v': case 'V': - verbose = true; + verbose = TRUE; cmdp++; break; case 'x': @@ -498,7 +498,7 @@ int CmdHF14ASim(const char *Cmd) { break; default: PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; + errors = TRUE; break; } if(errors) break; @@ -514,19 +514,19 @@ int CmdHF14ASim(const char *Cmd) { memcpy(c.d.asBytes, uid, uidlen>>1); clearCommandBuffer(); SendCommand(&c); - - nonces_t data[ATTACK_KEY_COUNT*2]; UsbCommand resp; PrintAndLog("Press pm3-button to abort simulation"); + while( !ukbhit() ){ if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) continue; if ( !(flags & FLAG_NR_AR_ATTACK) ) break; if ( (resp.arg[0] & 0xffff) != CMD_SIMULATE_MIFARE_CARD ) break; - memcpy( data, resp.d.asBytes, sizeof(data) ); - readerAttack(data, setEmulatorMem, verbose); + memcpy(data, resp.d.asBytes, sizeof(data) ); + readerAttack(data[0], setEmulatorMem, verbose); } + showSectorTable(); return 0; } diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 36438d7f..e6568f59 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1361,18 +1361,16 @@ int CmdHF14AMfChk(const char *Cmd) { PrintAndLog(""); return 0; } -#define ATTACK_KEY_COUNT 8 + sector *k_sector = NULL; uint8_t k_sectorsCount = 16; -void readerAttack(nonces_t data[], bool setEmulatorMem, bool verbose) { +static void emptySectorTable(){ // initialize storage for found keys if (k_sector == NULL) k_sector = calloc(k_sectorsCount, sizeof(sector)); if (k_sector == NULL) return; - - uint64_t key = 0; // empty e_sector for(int i = 0; i < k_sectorsCount; ++i){ @@ -1381,68 +1379,47 @@ void readerAttack(nonces_t data[], bool setEmulatorMem, bool verbose) { k_sector[i].foundKey[0] = FALSE; k_sector[i].foundKey[1] = FALSE; } +} +void showSectorTable(){ + if (k_sector != NULL) { + printKeyTable(k_sectorsCount, k_sector); + free(k_sector); + k_sector = NULL; + } +} +void readerAttack(nonces_t data, bool setEmulatorMem, bool verbose) { - if (verbose) printf("enter Moebius attack (mfkey32v2) \n"); + uint64_t key = 0; + bool success = FALSE; - for (uint8_t i = 0; i < ATTACK_KEY_COUNT; ++i) { - - // if no-collected data - if (data[i].ar2 == 0) continue; - - // We can probably skip this, mfkey32v2 is more reliable. -#ifdef HFMF_TRYMFK32 - if (tryMfk32(data[i], &key, verbose)) { - PrintAndLog("Found Key%s for sector %02d: [%012"llx"]" - , (data[i].keytype) ? "B" : "A" - , data[i].sector - , key - ); - - k_sector[i].Key[data[i].keytype] = key; - k_sector[i].foundKey[data[i].keytype] = TRUE; - - //set emulator memory for keys - if (setEmulatorMem) { - uint8_t memBlock[16] = {0,0,0,0,0,0, 0xff, 0x0F, 0x80, 0x69, 0,0,0,0,0,0}; - num_to_bytes( k_sector[i].Key[0], 6, memBlock); - num_to_bytes( k_sector[i].Key[1], 6, memBlock+10); - PrintAndLog("Setting Emulator Memory Block %02d: [%s]" - , ((data[i].sector)*4) + 3 - , sprint_hex( memBlock, sizeof(memBlock)) - ); - mfEmlSetMem( memBlock, ((data[i].sector)*4) + 3, 1); - } - continue; - } -#endif - - //moebius attack - if (tryMfk32_moebius(data[i+ATTACK_KEY_COUNT], &key, verbose)) { - uint8_t sectorNum = data[i+ATTACK_KEY_COUNT].sector; - uint8_t keyType = data[i+ATTACK_KEY_COUNT].keytype; - - PrintAndLog("Reader is trying authenticate with: Key %s, sector %02d: [%012"llx"]" - , keyType ? "B" : "A" - , sectorNum - , key - ); - - k_sector[sectorNum].Key[keyType] = key; - k_sector[sectorNum].foundKey[keyType] = TRUE; - - //set emulator memory for keys - if (setEmulatorMem) { - uint8_t memBlock[16] = {0,0,0,0,0,0, 0xff, 0x0F, 0x80, 0x69, 0,0,0,0,0,0}; - num_to_bytes( k_sector[sectorNum].Key[0], 6, memBlock); - num_to_bytes( k_sector[sectorNum].Key[1], 6, memBlock+10); - //iceman, guessing this will not work so well for 4K tags. - PrintAndLog("Setting Emulator Memory Block %02d: [%s]" - , (sectorNum*4) + 3 - , sprint_hex( memBlock, sizeof(memBlock)) - ); - mfEmlSetMem( memBlock, (sectorNum*4) + 3, 1); - } - continue; + if (k_sector == NULL) + emptySectorTable(); + + success = tryMfk32_moebius(data, &key, verbose); + if (success) { + uint8_t sector = data.sector; + uint8_t keytype = data.keytype; + + PrintAndLog("Reader is trying authenticate with: Key %s, sector %02d: [%012"llx"]" + , keytype ? "B" : "A" + , sector + , key + ); + + k_sector[sector].Key[keytype] = key; + k_sector[sector].foundKey[keytype] = TRUE; + + //set emulator memory for keys + if (setEmulatorMem) { + uint8_t memBlock[16] = {0,0,0,0,0,0, 0xff, 0x0F, 0x80, 0x69, 0,0,0,0,0,0}; + num_to_bytes( k_sector[sector].Key[0], 6, memBlock); + num_to_bytes( k_sector[sector].Key[1], 6, memBlock+10); + //iceman, guessing this will not work so well for 4K tags. + PrintAndLog("Setting Emulator Memory Block %02d: [%s]" + , (sector*4) + 3 + , sprint_hex( memBlock, sizeof(memBlock)) + ); + mfEmlSetMem( memBlock, (sector*4) + 3, 1); } } } @@ -1453,18 +1430,17 @@ int CmdHF14AMf1kSim(const char *Cmd) { uint8_t exitAfterNReads = 0; uint8_t flags = (FLAG_UID_IN_EMUL | FLAG_4B_UID_IN_DATA); int uidlen = 0; - bool setEmulatorMem = false; uint8_t cmdp = 0; - bool errors = false; - - // If set to true, we should show our workings when doing NR_AR_ATTACK. - bool verbose = false; - + bool errors = FALSE; + bool verbose = FALSE; + bool setEmulatorMem = FALSE; + nonces_t data[1]; + while(param_getchar(Cmd, cmdp) != 0x00) { switch(param_getchar(Cmd, cmdp)) { case 'e': case 'E': - setEmulatorMem = true; + setEmulatorMem = TRUE; cmdp++; break; case 'h': @@ -1489,11 +1465,11 @@ int CmdHF14AMf1kSim(const char *Cmd) { case 8: flags = FLAG_4B_UID_IN_DATA; break; default: return usage_hf14_mf1ksim(); } - cmdp +=2; + cmdp += 2; break; case 'v': case 'V': - verbose = true; + verbose = TRUE; cmdp++; break; case 'x': @@ -1503,7 +1479,7 @@ int CmdHF14AMf1kSim(const char *Cmd) { break; default: PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; + errors = TRUE; break; } if(errors) break; @@ -1521,27 +1497,20 @@ int CmdHF14AMf1kSim(const char *Cmd) { memcpy(c.d.asBytes, uid, sizeof(uid)); clearCommandBuffer(); SendCommand(&c); + UsbCommand resp; - if(flags & FLAG_INTERACTIVE) { + if(flags & FLAG_INTERACTIVE) { PrintAndLog("Press pm3-button or send another cmd to abort simulation"); - nonces_t data[ATTACK_KEY_COUNT*2]; - UsbCommand resp; - while( !ukbhit() ){ if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) continue; if ( !(flags & FLAG_NR_AR_ATTACK) ) break; if ( (resp.arg[0] & 0xffff) != CMD_SIMULATE_MIFARE_CARD ) break; - memcpy( data, resp.d.asBytes, sizeof(data) ); - readerAttack(data, setEmulatorMem, verbose); - } - - if (k_sector != NULL) { - printKeyTable(k_sectorsCount, k_sector); - free(k_sector); - k_sector = NULL; + memcpy(data, resp.d.asBytes, sizeof(data)); + readerAttack(data[0], setEmulatorMem, verbose); } + showSectorTable(); } return 0; } diff --git a/client/cmdhfmf.h b/client/cmdhfmf.h index a2f9328a..26df2df4 100644 --- a/client/cmdhfmf.h +++ b/client/cmdhfmf.h @@ -61,6 +61,7 @@ int CmdHF14AMfCLoad(const char* cmd); int CmdHF14AMfCSave(const char* cmd); int CmdHf14MfDecryptBytes(const char *Cmd); -void readerAttack(nonces_t data[], bool setEmulatorMem, bool verbose); +void showSectorTable(void); +void readerAttack(nonces_t data, bool setEmulatorMem, bool verbose); void printKeyTable( uint8_t sectorscnt, sector *e_sector ); #endif diff --git a/include/mifare.h b/include/mifare.h index 11c977d5..e6643f5f 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -74,6 +74,11 @@ typedef struct { uint32_t nr2; uint8_t sector; uint8_t keytype; + enum { + EMPTY, + FIRST, + SECOND, + } state; } nonces_t; #endif // _MIFARE_H_ -- 2.39.5 From 1cec48cc0e608397288ebbdc68768b02b8dcacab Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Jan 2017 16:51:07 +0100 Subject: [PATCH 14/16] ADD: added the writedumpfile function from "14araw.lua" into utils.lua ADD: `ufodump.lua` - added the Aztek dump script. Since its an unknown tag hence the name. --- client/lualibs/utils.lua | 37 +++++++- client/scripts/ufodump.lua | 181 +++++++++++++++++++++++++++++++++++++ 2 files changed, 217 insertions(+), 1 deletion(-) create mode 100644 client/scripts/ufodump.lua diff --git a/client/lualibs/utils.lua b/client/lualibs/utils.lua index 39f8bca2..9dcb49c7 100644 --- a/client/lualibs/utils.lua +++ b/client/lualibs/utils.lua @@ -53,6 +53,34 @@ local Utils = return hex end, + ------------ FILE WRITING (EML) + --- Writes an eml-file. + -- @param uid - the uid of the tag. Used in filename + -- @param blockData. Assumed to be on the format {'\0\1\2\3,'\b\e\e\f' ..., + -- that is, blockData[row] contains a string with the actual data, not ascii hex representation + -- return filename if all went well, + -- @reurn nil, error message if unsuccessfulls + WriteDumpFile = function(uid, blockData) + local destination = string.format("%s.eml", uid) + local file = io.open(destination, "w") + if file == nil then + return nil, string.format("Could not write to file %s", destination) + end + local rowlen = string.len(blockData[1]) + + for i,block in ipairs(blockData) do + if rowlen ~= string.len(block) then + prlog(string.format("WARNING: Dumpdata seems corrupted, line %d was not the same length as line 1",i)) + end + + local formatString = string.format("H%d", string.len(block)) + local _,hex = bin.unpack(formatString,block) + file:write(hex.."\n") + end + file:close() + return destination + end, + ------------ string split function Split = function( inSplitPattern, outResults ) if not outResults then @@ -262,7 +290,14 @@ local Utils = if #s == 0 then return '' end local t={} for k in s:gmatch"(%x%x)" do - table.insert(t, string.char(tonumber(k,16))) + local n = tonumber(k,16) + local c + if (n < 32) or (n == 127) then + c = '.'; + else + c = string.char(n) + end + table.insert(t,c) end return table.concat(t) end, diff --git a/client/scripts/ufodump.lua b/client/scripts/ufodump.lua new file mode 100644 index 00000000..f1e4be1e --- /dev/null +++ b/client/scripts/ufodump.lua @@ -0,0 +1,181 @@ +local cmds = require('commands') +local getopt = require('getopt') +local lib14a = require('read14a') +local utils = require('utils') +example = [[ + script run ufodump + script run ufodump -b 10 +]] +author = "Iceman" +desc = +[[ +This is a script that reads AZTEK iso14443a tags. +It starts from block 0, and ends at default block 20. Use 'b' to say different endblock. + +xor: the first three block (0,1,2) is not XORED. The rest seems to be xored. + +Arguments: + h this helptext + b endblock in decimal (1-255, default 20) +]] + +-- Some globals +local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds +local DEBUG = false -- the debug flag +--- +-- A debug printout-function +function dbg(args) + if DEBUG then + print("###", args) + end +end +--- +-- This is only meant to be used when errors occur +function oops(err) + print("ERROR: ",err) + core.clearCommandBuffer() +end +--- +-- Usage help +function help() + print(desc) + print("Example usage") + print(example) +end +-- +-- writes data to ascii textfile. +function writeDumpFile(uid, blockData) + local destination = string.format("%s.eml", uid) + local file = io.open(destination, "w") + if file == nil then + return nil, string.format("Could not write to file %s", destination) + end + local rowlen = string.len(blockData[1]) + + for i,block in ipairs(blockData) do + if rowlen ~= string.len(block) then + print(string.format("WARNING: Dumpdata seems corrupted, line %d was not the same length as line 1",i)) + end + file:write(block.."\n") + end + file:close() + return destination +end +-- +--- Picks out and displays the data read from a tag +-- Specifically, takes a usb packet, converts to a Command +-- (as in commands.lua), takes the data-array and +-- reads the number of bytes specified in arg1 (arg0 in c-struct) +-- and displays the data +-- @blockno just to print which block the data belong to +-- @param usbpacket the data received from the device +function showdata(blockno, data) + local xorkey = '55AA55AA55AA55AA6262' + --local s = data.." | "..utils.ConvertHexToAscii(data).." | " + local s = data.." | " + local dex = '' + local rs + for i = 1, 20-4, 4 do + local item = string.sub(data, i, i+3) + local xor = string.sub(xorkey, i, i+3) + + if blockno > 2 then + rs = bit32.bxor(tonumber(item,16) , tonumber(xor,16)) + else + rs = tonumber(item, 16) + end + dex = (dex..'%04X'):format(rs) + end + --s = s..dex.." | "..utils.ConvertHexToAscii(dex) + s = s..dex.." | " + print( (" %02d | %s"):format(blockno,s)) +end +-- +-- Send a "raw" iso14443a package, ie "hf 14a raw" command +function sendRaw(rawdata, options) + --print(">> ", rawdata) + local flags = lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT + lib14a.ISO14A_COMMAND.ISO14A_RAW + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC + local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, + arg1 = flags, -- Send raw + -- arg2 contains the length, which is half the length + -- of the ASCII-string rawdata + arg2 = string.len(rawdata)/2, + data = rawdata} + return lib14a.sendToDevice(command, options.ignore_response) +end +-- +-- Sends an instruction to do nothing, only disconnect +function disconnect() + local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, arg1 = 0, } + -- We can ignore the response here, no ACK is returned for this command + -- Check /armsrc/iso14443a.c, ReaderIso14443a() for details + return lib14a.sendToDevice(command, true) + --core.console("hf 14a raw -r") +end +--- +-- The main entry point +function main(args) + + local ignore_response = false + local endblock = 20 + + -- Read the parameters + for o, a in getopt.getopt(args, 'hb:') do + if o == "h" then return help() end + if o == "b" then endblock = a end + end + endblock = endblock or 20 + + -- First of all, connect + info, err = lib14a.read1443a(true) + if err then disconnect() return oops(err) end + core.clearCommandBuffer() + + local blockData = {} + + -- Show tag info + print(("\nFound Card UID [%s]\n"):format(info.uid)) + + print("blk | data | xored") + print("----+------------------+-------------------") + for block = 00, endblock do + local cmd = string.format("10%02x00", block) + res, err = sendRaw(cmd , {ignore_response = ignore_response}) + if err then disconnect() return oops(err) end + + local cmd_response = Command.parse(res) + local len = tonumber(cmd_response.arg1) * 2 + local data = string.sub(tostring(cmd_response.data), 0, len-4) + + showdata(block, data) + table.insert(blockData, data) + end + print("----+------------------+-------------------") + disconnect() + + local filename, err = writeDumpFile(info.uid, blockData) + if err then return oops(err) end + + print(string.format("\nDumped data into %s", filename)) +end + + + + +------------------------- +-- Testing +------------------------- +function selftest() + DEBUG = true + dbg("Performing test") + main() + dbg("Tests done") +end +-- Flip the switch here to perform a sanity check. +-- It read a nonce in two different ways, as specified in the usage-section +if "--test"==args then + selftest() +else + -- Call the main + main(args) +end \ No newline at end of file -- 2.39.5 From 71aa1ff8245ddcfdaebdbd5313be596d374949b2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 31 Jan 2017 05:33:24 +0100 Subject: [PATCH 15/16] FIX: fixes warning for "%zu" string formatspecifier on MINGW systems. (Thanks to @marshmellow42 for this one) --- client/Makefile | 2 +- client/proxmark3.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/client/Makefile b/client/Makefile index 0191ff25..0053d8e5 100644 --- a/client/Makefile +++ b/client/Makefile @@ -19,7 +19,7 @@ LUAPLATFORM = generic ifneq (,$(findstring MINGW,$(platform))) LDLIBS += -L/mingw/lib -lgdi32 - CFLAGS += -I/mingw/include + CFLAGS += -I/mingw/include -D__USE_MINGW_ANSI_STDIO=1 CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui MOC = $(QTDIR)/bin/moc LUAPLATFORM = mingw diff --git a/client/proxmark3.h b/client/proxmark3.h index 2c881042..9b10af1a 100644 --- a/client/proxmark3.h +++ b/client/proxmark3.h @@ -15,7 +15,9 @@ // Handle platform specific includes #ifdef _WIN32 // for MINGW32 environments - #define _USE_32BIT_TIME_T 1 + #ifndef _USE_32BIT_TIME_T + #define _USE_32BIT_TIME_T 1 + #endif #include #include #else -- 2.39.5 From b828a4e16818697605d57f2600cbb815c5ce5e7e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 31 Jan 2017 16:11:57 +0100 Subject: [PATCH 16/16] CHG: 'lf snoop' - now automatically downloads samples after finished. (annoying step to do over and over) FIX: 'lf snoop' - now turns of LF antenna after snoop. FIX: 'lf cotag read' - now waits until the ACK cmd arrives before downloading samples. --- armsrc/lfops.c | 35 +++++++++++++++++++++-------------- armsrc/lfsampling.c | 12 +++++++++--- client/cmdlf.c | 12 ++++++------ client/cmdlfcotag.c | 10 +++++++--- 4 files changed, 43 insertions(+), 26 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 28927c33..0dc5bcf9 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -78,6 +78,8 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t periods, uint3 // now do the read DoAcquisition_config(false); + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); } /* blank r/w tag data stream @@ -1740,12 +1742,12 @@ void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode void Cotag() { +//#define WAIT2200 { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(2035); } #define WAIT2200 { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(2200); } - LED_A_ON(); //clear buffer now so it does not interfere with timing later - BigBuf_Clear_keep_EM(); + BigBuf_Clear_ext(false); // Set up FPGA, 132kHz to power up the tag FpgaDownloadAndGo(FPGA_BITSTREAM_LF); @@ -1755,28 +1757,33 @@ void Cotag() { // Connect the A/D to the peak-detected low-frequency path. SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - // 50ms for the resonant antenna to settle. - SpinDelay(50); - // Now set up the SSC to get the ADC samples that are now streaming at us. FpgaSetupSsc(); + // start a 1.5ticks is 1us StartTicks(); //send start pulse - TurnReadLFOn(800); - WAIT2200 - TurnReadLFOn(3600); - WAIT2200 - TurnReadLFOn(800); - WAIT2200 + TurnReadLFOn(800); WAIT2200 + TurnReadLFOn(3600); WAIT2200 + TurnReadLFOn(800); WAIT2200 TurnReadLFOn(3600); - // Turn field on to read the response - TurnReadLFOn(READ_GAP); +/* + TurnReadLFOn(740); WAIT2200 + TurnReadLFOn(3330); WAIT2200 + TurnReadLFOn(740); WAIT2200 + TurnReadLFOn(3330); + + +burst 800 us, gap 2.2 msecs +burst 3.6 msecs gap 2.2 msecs +burst 800 us gap 2.2 msecs +pulse 3.6 msecs +*/ // Acquisition - doT55x7Acquisition(20000); + DoAcquisition_default(-1, true); // Turn the field off FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 02c0cd4a..d726ba20 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -110,7 +110,7 @@ void LFSetupFPGAForADC(int divisor, bool lf_field) { * @param silent - is true, now outputs are made. If false, dbprints the status * @return the number of bits occupied by the samples. */ -uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold,bool silent) { +uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold, bool silent) { //bigbuf, to hold the aquired raw data signal uint8_t *dest = BigBuf_get_addr(); uint16_t bufsize = BigBuf_max_traceLen(); @@ -224,14 +224,20 @@ uint32_t ReadLF(bool activeField, bool silent) { * @return number of bits sampled **/ uint32_t SampleLF(bool printCfg) { - return ReadLF(true, printCfg); + BigBuf_Clear_ext(false); + uint32_t ret = ReadLF(true, printCfg); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + return ret; } /** * Initializes the FPGA for snoop-mode (field off), and acquires the samples. * @return number of bits sampled **/ uint32_t SnoopLF() { - return ReadLF(false, true); + BigBuf_Clear_ext(false); + uint32_t ret = ReadLF(false, true); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + return ret; } /** diff --git a/client/cmdlf.c b/client/cmdlf.c index 2daa46ab..eb2f7cde 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -36,11 +36,10 @@ int usage_lf_read(void){ return 0; } int usage_lf_snoop(void) { - PrintAndLog("Usage: lf snoop"); + PrintAndLog("Snoop low frequence signal. Use 'lf config' to set parameters."); + PrintAndLog("Usage: lf snoop [h]"); PrintAndLog("Options:"); - PrintAndLog(" h This help"); - PrintAndLog("This function takes no arguments. "); - PrintAndLog("Use 'lf config' to set parameters."); + PrintAndLog(" h This help"); return 0; } int usage_lf_config(void) { @@ -568,10 +567,11 @@ int CmdLFSnoop(const char *Cmd) { uint8_t cmdp = param_getchar(Cmd, 0); if(cmdp == 'h' || cmdp == 'H') return usage_lf_snoop(); - UsbCommand c = {CMD_LF_SNOOP_RAW_ADC_SAMPLES}; + UsbCommand c = {CMD_LF_SNOOP_RAW_ADC_SAMPLES,{0,0,0}}; clearCommandBuffer(); SendCommand(&c); WaitForResponse(CMD_ACK,NULL); + getSamples("", false); return 0; } @@ -1221,7 +1221,7 @@ static command_t CommandTable[] = {"simfsk", CmdLFfskSim, 0, "[c ] [i] [H ] [L ] [d ] \n\t\t-- Simulate LF FSK tag from demodbuffer or input"}, {"simpsk", CmdLFpskSim, 0, "[1|2|3] [c ] [i] [r ] [d ] \n\t\t-- Simulate LF PSK tag from demodbuffer or input"}, {"simbidir", CmdLFSimBidir, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"}, - {"snoop", CmdLFSnoop, 0, "['l'|'h'|] [trigger threshold]-- Snoop LF (l:125khz, h:134khz)"}, + {"snoop", CmdLFSnoop, 0, "Snoop LF"}, {"vchdemod", CmdVchDemod, 1, "['clone'] -- Demodulate samples for VeriChip"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdlfcotag.c b/client/cmdlfcotag.c index e200e834..11be2db8 100644 --- a/client/cmdlfcotag.c +++ b/client/cmdlfcotag.c @@ -18,9 +18,13 @@ int CmdCOTAGRead(const char *Cmd) { UsbCommand c = {CMD_COTAG, {0, 0, 0}}; clearCommandBuffer(); SendCommand(&c); - - getSamples("20000", TRUE); - return CmdFSKdemodAWID(Cmd); + if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2500) ) { + //PrintAndLog("command execution time out"); + return 1; + } + getSamples("", true); + //return CmdFSKdemodAWID(Cmd); + return 0; } static command_t CommandTable[] = { -- 2.39.5