mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 13:53:55 -07:00
commit
5f9aa3801b
98 changed files with 3284 additions and 1341 deletions
47
.github/ISSUE_TEMPLATE/checklist-for-release.md
vendored
Normal file
47
.github/ISSUE_TEMPLATE/checklist-for-release.md
vendored
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
---
|
||||||
|
name: Checklist for release
|
||||||
|
about: A template when making a release (usage reserved to repo maintainers)
|
||||||
|
title: "[RELEASE 4.x] Checklist"
|
||||||
|
labels: Release
|
||||||
|
assignees: doegox, iceman1001
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Checklist
|
||||||
|
|
||||||
|
- [ ] CHANGELOG.md
|
||||||
|
- [ ] `make style`
|
||||||
|
- [ ] `make clean; make client CC=clang CXX=clang++ LD=clang++` on recent Debian or Ubuntu
|
||||||
|
- [ ] `mymanualchecks.sh`
|
||||||
|
- [ ] `mycppcheck.sh` no alarming warning?
|
||||||
|
- [ ] `mymakeclang.sh` no alarming error/warning ?
|
||||||
|
- [ ] `mystandalone_makes.sh` compile all standalone modes (linux only)
|
||||||
|
- [ ] [Travis](https://travis-ci.org/github/RfidResearchGroup/proxmark3/builds) green (linux noqt / osx+qt ; with makefile (w/wo bt) / with cmake)
|
||||||
|
- [ ] [Appveyor](https://ci.appveyor.com/project/RfidResearchGroup/proxmark3/history) green (PS)
|
||||||
|
|
||||||
|
# OS compilation and tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make clean && make -j PLATFORM=PM3OTHER && tools/pm3test.sh
|
||||||
|
make clean && make -j PLATFORM=PM3RDV4 && tools/pm3test.sh
|
||||||
|
make clean && make -j PLATFORM=PM3RDV4 PLATFORM_EXTRAS=BTADDON && tools/pm3test.sh
|
||||||
|
make install; pushd /tmp; proxmark3 -c 'data load em4x05.pm3;lf search 1'; popd; make uninstall
|
||||||
|
|
||||||
|
( cd client; rm -rf build; mkdir build;cd build;cmake .. && make -j PLATFORM=PM3OTHER && PM3BIN=./proxmark3 ../../tools/pm3test.sh client )
|
||||||
|
( cd client; rm -rf build; mkdir build;cd build;cmake .. && make -j PLATFORM=PM3RDV4 && PM3BIN=./proxmark3 ../../tools/pm3test.sh client )
|
||||||
|
( cd client; rm -rf build; mkdir build;cd build;cmake .. && make -j PLATFORM=PM3RDV4 PLATFORM_EXTRAS=BTADDON && PM3BIN=./proxmark3 ../../tools/pm3test.sh client )
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] RPI Zero
|
||||||
|
- [ ] WSL
|
||||||
|
- [ ] PSv3.3
|
||||||
|
- [ ] Kali
|
||||||
|
- [ ] Debian
|
||||||
|
- [ ] Ubuntu20
|
||||||
|
- [ ] ParrotOS
|
||||||
|
- [ ] Fedora
|
||||||
|
- [ ] OpenSuse
|
||||||
|
- [ ] OSX
|
||||||
|
- [ ] Android
|
||||||
|
- [ ] Termux
|
||||||
|
|
|
@ -3,6 +3,11 @@ 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...
|
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]
|
## [unreleased][unreleased]
|
||||||
|
- Add `hf 14a config` to deal with badly configured cards: invalid ATQA/BCC/SAK (@doegox)"
|
||||||
|
- Mikron JSC Russia Ultralight EV1 41 pages tag type support (@McEloff)
|
||||||
|
- Add test for Ultralight gen2 magic 'hf search' (@McEloff)
|
||||||
|
- Add test for Ultralight EV1 gen2 magic 'hf search' (@McEloff)
|
||||||
|
- Added `hf mf gen3*`magic gen 3 card operations (@McEloff)
|
||||||
- Readded verichip command which seems missing (@iceman1001)
|
- Readded verichip command which seems missing (@iceman1001)
|
||||||
- Fix missing t55x7 config block detection (@iceman1001)
|
- Fix missing t55x7 config block detection (@iceman1001)
|
||||||
- Fix missing define on proxspace (@mwalker33)
|
- Fix missing define on proxspace (@mwalker33)
|
||||||
|
|
|
@ -38,6 +38,9 @@ define KNOWN_STANDALONE_DEFINITIONS
|
||||||
| HF_14ASNIFF | 14a sniff to flashmem |
|
| HF_14ASNIFF | 14a sniff to flashmem |
|
||||||
| (RDV4 only) | |
|
| (RDV4 only) | |
|
||||||
+----------------------------------------------------------+
|
+----------------------------------------------------------+
|
||||||
|
| HF_AVEFUL | Mifare ultralight read/simulation |
|
||||||
|
| | - Ave Ozkal |
|
||||||
|
+----------------------------------------------------------+
|
||||||
| HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth |
|
| HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth |
|
||||||
| (RDV4 only) | storing in flashmem - Bogito |
|
| (RDV4 only) | storing in flashmem - Bogito |
|
||||||
+----------------------------------------------------------+
|
+----------------------------------------------------------+
|
||||||
|
@ -62,7 +65,7 @@ define KNOWN_STANDALONE_DEFINITIONS
|
||||||
endef
|
endef
|
||||||
|
|
||||||
STANDALONE_MODES := LF_SKELETON LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RWC LF_HIDBRUTE LF_ICEHID LF_PROXBRUTE LF_SAMYRUN
|
STANDALONE_MODES := LF_SKELETON LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RWC LF_HIDBRUTE LF_ICEHID LF_PROXBRUTE LF_SAMYRUN
|
||||||
STANDALONE_MODES += HF_14ASNIFF HF_BOG HF_COLIN HF_ICECLASS HF_LEGIC HF_MATTYRUN HF_MSDSAL HF_YOUNG
|
STANDALONE_MODES += HF_14ASNIFF HF_AVEFUL HF_BOG HF_COLIN HF_ICECLASS HF_LEGIC HF_MATTYRUN HF_MSDSAL HF_YOUNG
|
||||||
STANDALONE_MODES_REQ_SMARTCARD :=
|
STANDALONE_MODES_REQ_SMARTCARD :=
|
||||||
STANDALONE_MODES_REQ_FLASH := LF_ICEHID HF_14ASNIFF HF_BOG HF_COLIN HF_ICECLASS
|
STANDALONE_MODES_REQ_FLASH := LF_ICEHID HF_14ASNIFF HF_BOG HF_COLIN HF_ICECLASS
|
||||||
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),)
|
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),)
|
||||||
|
|
|
@ -37,6 +37,10 @@ endif
|
||||||
ifneq (,$(findstring WITH_STANDALONE_HF_14ASNIFF,$(APP_CFLAGS)))
|
ifneq (,$(findstring WITH_STANDALONE_HF_14ASNIFF,$(APP_CFLAGS)))
|
||||||
SRC_STANDALONE = hf_14asniff.c
|
SRC_STANDALONE = hf_14asniff.c
|
||||||
endif
|
endif
|
||||||
|
# WITH_STANDALONE_HF_AVEFUL
|
||||||
|
ifneq (,$(findstring WITH_STANDALONE_HF_AVEFUL,$(APP_CFLAGS)))
|
||||||
|
SRC_STANDALONE = hf_aveful.c
|
||||||
|
endif
|
||||||
# WITH_STANDALONE_LF_ICEHID
|
# WITH_STANDALONE_LF_ICEHID
|
||||||
ifneq (,$(findstring WITH_STANDALONE_LF_ICEHID,$(APP_CFLAGS)))
|
ifneq (,$(findstring WITH_STANDALONE_LF_ICEHID,$(APP_CFLAGS)))
|
||||||
SRC_STANDALONE = lf_icehid.c
|
SRC_STANDALONE = lf_icehid.c
|
||||||
|
|
127
armsrc/Standalone/hf_aveful.c
Normal file
127
armsrc/Standalone/hf_aveful.c
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// A. Ozkal, 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.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// main code for HF Mifare Ultralight read/simulation by Ave Ozkal
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Several parts of this code is based on code by Craig Young from HF_YOUNG
|
||||||
|
|
||||||
|
// This code does not:
|
||||||
|
// - Account for cards with authentication (MFU EV1 etc)
|
||||||
|
// - Determine if cards have block count that's not the same as the BLOCKS def
|
||||||
|
|
||||||
|
#include "standalone.h" // standalone definitions
|
||||||
|
#include "proxmark3_arm.h"
|
||||||
|
#include "appmain.h"
|
||||||
|
#include "fpgaloader.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
|
||||||
|
#include "ticks.h" // SpinDelay
|
||||||
|
#include "mifareutil.h"
|
||||||
|
#include "iso14443a.h"
|
||||||
|
|
||||||
|
#define BLOCKS 16
|
||||||
|
#define SAK 0x00
|
||||||
|
#define ATQA0 0x44
|
||||||
|
#define ATQA1 0x00
|
||||||
|
|
||||||
|
#define STATE_SEARCH 0
|
||||||
|
#define STATE_READ 1
|
||||||
|
#define STATE_EMUL 2
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t uid[10];
|
||||||
|
uint8_t uidlen;
|
||||||
|
uint8_t atqa[2];
|
||||||
|
uint8_t sak;
|
||||||
|
} PACKED card_clone_t;
|
||||||
|
|
||||||
|
void ModInfo(void) {
|
||||||
|
DbpString(" HF Mifare Ultralight read/simulation by Ave Ozkal");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunMod(void) {
|
||||||
|
StandAloneMode();
|
||||||
|
Dbprintf("AveFUL (MF Ultralight read/emul) started");
|
||||||
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
|
|
||||||
|
// the main loop for your standalone mode
|
||||||
|
for (;;) {
|
||||||
|
WDT_HIT();
|
||||||
|
|
||||||
|
// exit from RunMod, send a usbcommand.
|
||||||
|
if (data_available()) break;
|
||||||
|
|
||||||
|
iso14a_card_select_t card;
|
||||||
|
|
||||||
|
SpinDelay(500);
|
||||||
|
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
|
||||||
|
|
||||||
|
// 0 = search, 1 = read, 2 = emul
|
||||||
|
int state = STATE_SEARCH;
|
||||||
|
|
||||||
|
DbpString("Scanning...");
|
||||||
|
for (;;) {
|
||||||
|
// Was our button held down or pressed?
|
||||||
|
int button_pressed = BUTTON_HELD(1000);
|
||||||
|
|
||||||
|
if (button_pressed != BUTTON_NO_CLICK || data_available())
|
||||||
|
break;
|
||||||
|
else if (state == STATE_SEARCH) {
|
||||||
|
if (!iso14443a_select_card(NULL, &card, NULL, true, 0, true)) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
if (card.sak == SAK && card.atqa[0] == ATQA0 && card.atqa[1] == ATQA1 && card.uidlen == 7) {
|
||||||
|
DbpString("Found ultralight with UID: ");
|
||||||
|
Dbhexdump(card.uidlen, card.uid, 0);
|
||||||
|
state = STATE_READ;
|
||||||
|
} else {
|
||||||
|
DbpString("Found non-ultralight card, ignoring.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (state == STATE_READ) {
|
||||||
|
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||||
|
iso14443a_select_card(NULL, NULL, NULL, true, 0, true);
|
||||||
|
bool read_successful = true;
|
||||||
|
Dbprintf("Contents:");
|
||||||
|
|
||||||
|
for (int i = 0; i < BLOCKS; i++) {
|
||||||
|
uint8_t dataout[4] = {0x00};
|
||||||
|
if (mifare_ultra_readblock(i, dataout)) {
|
||||||
|
// If there's an error reading, go back to search state
|
||||||
|
read_successful = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// We're skipping 14 blocks (56 bytes) here, as that "[...] has version/signature/counter data here" according to comments on dumptoemul-mfu
|
||||||
|
// When converting a bin, it's almost all 0 other than one 0x0F byte, and functionality seems to be unaffected if that byte is set to 0x00.
|
||||||
|
emlSetMem_xt(dataout, 14 + i, 1, 4);
|
||||||
|
Dbhexdump(4, dataout, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read_successful) {
|
||||||
|
Dbprintf("Successfully loaded into emulator memory...");
|
||||||
|
state = STATE_EMUL;
|
||||||
|
} else {
|
||||||
|
Dbprintf("Read failure, going back to search state.");
|
||||||
|
state = STATE_SEARCH;
|
||||||
|
}
|
||||||
|
} else if (state == 2) {
|
||||||
|
uint8_t flags = FLAG_7B_UID_IN_DATA;
|
||||||
|
|
||||||
|
Dbprintf("Starting simulation, press pm3-button to stop and go back to search state.");
|
||||||
|
SimulateIso14443aTag(2, flags, card.uid);
|
||||||
|
|
||||||
|
// Go back to search state if user presses pm3-button
|
||||||
|
state = STATE_SEARCH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DbpString("exiting");
|
||||||
|
LEDsoff();
|
||||||
|
}
|
|
@ -7,6 +7,15 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// main code for hf_iceclass by Iceman
|
// main code for hf_iceclass by Iceman
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Created for the live streamed talk 'DEFCON 28 Wireless Village-Omikron and Iceman - Ghosting the PACS-man: New Tools and Techniques'
|
||||||
|
// https://www.youtube.com/watch?v=ghiHXK4GEzE
|
||||||
|
//
|
||||||
|
// I created a youtube video demostrating the HF_ICECLASS standalone mode
|
||||||
|
// https://youtu.be/w_1GnAscNIU
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
#include "standalone.h" // standalone definitions
|
#include "standalone.h" // standalone definitions
|
||||||
#include "proxmark3_arm.h"
|
#include "proxmark3_arm.h"
|
||||||
#include "appmain.h"
|
#include "appmain.h"
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
#include "legic.h" // legic_card_select_t struct
|
#include "legic.h" // legic_card_select_t struct
|
||||||
#include "spiffs.h" // flashmem
|
#include "spiffs.h" // flashmem
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* To list all dump files from flash:
|
* To list all dump files from flash:
|
||||||
*
|
*
|
||||||
|
@ -106,6 +105,7 @@ void RunMod(void) {
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
Dbprintf("[=] >> HF Legic Prime Read/Simulate Started <<");
|
Dbprintf("[=] >> HF Legic Prime Read/Simulate Started <<");
|
||||||
DbpString("[=] press and HOLD button to exit standalone mode");
|
DbpString("[=] press and HOLD button to exit standalone mode");
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ void RunMod(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// The read data is migrated to a MIM1024 card
|
// The read data is migrated to a MIM1024 card
|
||||||
LegicRfSimulate(ct);
|
LegicRfSimulate(ct, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -355,8 +355,11 @@ static void SendStatus(void) {
|
||||||
I2C_print_status();
|
I2C_print_status();
|
||||||
#endif
|
#endif
|
||||||
#ifdef WITH_LF
|
#ifdef WITH_LF
|
||||||
printConfig(); // LF Sampling config
|
printLFConfig(); // LF Sampling config
|
||||||
printT55xxConfig(); // LF T55XX Config
|
printT55xxConfig(); // LF T55XX Config
|
||||||
|
#endif
|
||||||
|
#ifdef WITH_ISO14443a
|
||||||
|
printHf14aConfig(); // HF 14a config
|
||||||
#endif
|
#endif
|
||||||
printConnSpeed();
|
printConnSpeed();
|
||||||
DbpString(_CYAN_("Various"));
|
DbpString(_CYAN_("Various"));
|
||||||
|
@ -739,7 +742,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_LF_SAMPLING_PRINT_CONFIG: {
|
case CMD_LF_SAMPLING_PRINT_CONFIG: {
|
||||||
printConfig();
|
printLFConfig();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_LF_SAMPLING_GET_CONFIG: {
|
case CMD_LF_SAMPLING_GET_CONFIG: {
|
||||||
|
@ -756,7 +759,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
}
|
}
|
||||||
case CMD_LF_ACQ_RAW_ADC: {
|
case CMD_LF_ACQ_RAW_ADC: {
|
||||||
struct p {
|
struct p {
|
||||||
uint8_t verbose;
|
bool verbose;
|
||||||
uint32_t samples;
|
uint32_t samples;
|
||||||
} PACKED;
|
} PACKED;
|
||||||
struct p *payload = (struct p *)packet->data.asBytes;
|
struct p *payload = (struct p *)packet->data.asBytes;
|
||||||
|
@ -1058,14 +1061,19 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
uint8_t uid[8];
|
uint8_t uid[8];
|
||||||
} PACKED;
|
} PACKED;
|
||||||
struct p *payload = (struct p *) packet->data.asBytes;
|
struct p *payload = (struct p *) packet->data.asBytes;
|
||||||
SetTag15693Uid(payload->uid);
|
SetTag15693Uid(payload->uid);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_LEGICRF
|
#ifdef WITH_LEGICRF
|
||||||
case CMD_HF_LEGIC_SIMULATE: {
|
case CMD_HF_LEGIC_SIMULATE: {
|
||||||
LegicRfSimulate(packet->oldarg[0]);
|
struct p {
|
||||||
|
uint8_t tagtype;
|
||||||
|
bool send_reply;
|
||||||
|
} PACKED;
|
||||||
|
struct p *payload = (struct p *) packet->data.asBytes;
|
||||||
|
LegicRfSimulate(payload->tagtype, payload->send_reply);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_HF_LEGIC_WRITER: {
|
case CMD_HF_LEGIC_WRITER: {
|
||||||
|
@ -1140,6 +1148,21 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_ISO14443a
|
#ifdef WITH_ISO14443a
|
||||||
|
case CMD_HF_ISO14443A_PRINT_CONFIG: {
|
||||||
|
printHf14aConfig();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CMD_HF_ISO14443A_GET_CONFIG: {
|
||||||
|
hf14a_config *hf14aconfig = getHf14aConfig();
|
||||||
|
reply_ng(CMD_HF_ISO14443A_GET_CONFIG, PM3_SUCCESS, (uint8_t *)hf14aconfig, sizeof(hf14a_config));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CMD_HF_ISO14443A_SET_CONFIG: {
|
||||||
|
hf14a_config c;
|
||||||
|
memcpy(&c, packet->data.asBytes, sizeof(hf14a_config));
|
||||||
|
setHf14aConfig(&c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case CMD_HF_ISO14443A_SNIFF: {
|
case CMD_HF_ISO14443A_SNIFF: {
|
||||||
SniffIso14443a(packet->data.asBytes[0]);
|
SniffIso14443a(packet->data.asBytes[0]);
|
||||||
reply_ng(CMD_HF_ISO14443A_SNIFF, PM3_SUCCESS, NULL, 0);
|
reply_ng(CMD_HF_ISO14443A_SNIFF, PM3_SUCCESS, NULL, 0);
|
||||||
|
@ -1214,6 +1237,10 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
MifareUWriteBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
|
MifareUWriteBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case CMD_HF_MIFAREU_WRITEBL_COMPAT: {
|
||||||
|
MifareUWriteBlockCompat(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case CMD_HF_MIFARE_ACQ_ENCRYPTED_NONCES: {
|
case CMD_HF_MIFARE_ACQ_ENCRYPTED_NONCES: {
|
||||||
MifareAcquireEncryptedNonces(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes);
|
MifareAcquireEncryptedNonces(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes);
|
||||||
break;
|
break;
|
||||||
|
@ -1248,7 +1275,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_HF_MIFARE_CHKKEYS: {
|
case CMD_HF_MIFARE_CHKKEYS: {
|
||||||
MifareChkKeys(packet->data.asBytes);
|
MifareChkKeys(packet->data.asBytes, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_HF_MIFARE_CHKKEYS_FAST: {
|
case CMD_HF_MIFARE_CHKKEYS_FAST: {
|
||||||
|
@ -1318,6 +1345,19 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
MifareCIdent();
|
MifareCIdent();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// Gen 3 magic cards
|
||||||
|
case CMD_HF_MIFARE_GEN3UID: {
|
||||||
|
MifareGen3UID(packet->oldarg[0], packet->data.asBytes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CMD_HF_MIFARE_GEN3BLK: {
|
||||||
|
MifareGen3Blk(packet->oldarg[0], packet->data.asBytes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CMD_HF_MIFARE_GEN3FREEZ: {
|
||||||
|
MifareGen3Freez();
|
||||||
|
break;
|
||||||
|
}
|
||||||
// mifare sniffer
|
// mifare sniffer
|
||||||
// case CMD_HF_MIFARE_SNIFF: {
|
// case CMD_HF_MIFARE_SNIFF: {
|
||||||
// SniffMifare(packet->oldarg[0]);
|
// SniffMifare(packet->oldarg[0]);
|
||||||
|
@ -1806,12 +1846,9 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
uint8_t filename[32];
|
uint8_t filename[32];
|
||||||
uint8_t *pfilename = packet->data.asBytes;
|
uint8_t *pfilename = packet->data.asBytes;
|
||||||
memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN);
|
memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN);
|
||||||
if (DBGLEVEL > 1) Dbprintf("> Filename received for spiffs dump : %s", filename);
|
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Filename received for spiffs dump : %s", filename);
|
||||||
|
|
||||||
//uint32_t size = 0;
|
|
||||||
//rdv40_spiffs_stat((char *)filename, (uint32_t *)size,RDV40_SPIFFS_SAFETY_SAFE);
|
|
||||||
uint32_t size = packet->oldarg[1];
|
uint32_t size = packet->oldarg[1];
|
||||||
//uint8_t buff[size];
|
|
||||||
|
|
||||||
uint8_t *buff = BigBuf_malloc(size);
|
uint8_t *buff = BigBuf_malloc(size);
|
||||||
rdv40_spiffs_read_as_filetype((char *)filename, (uint8_t *)buff, size, RDV40_SPIFFS_SAFETY_SAFE);
|
rdv40_spiffs_read_as_filetype((char *)filename, (uint8_t *)buff, size, RDV40_SPIFFS_SAFETY_SAFE);
|
||||||
|
@ -1836,7 +1873,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
uint8_t filename[32];
|
uint8_t filename[32];
|
||||||
uint8_t *pfilename = packet->data.asBytes;
|
uint8_t *pfilename = packet->data.asBytes;
|
||||||
memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN);
|
memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN);
|
||||||
if (DBGLEVEL > 1) Dbprintf("> Filename received for spiffs STAT : %s", filename);
|
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Filename received for spiffs STAT : %s", filename);
|
||||||
int changed = rdv40_spiffs_lazy_mount();
|
int changed = rdv40_spiffs_lazy_mount();
|
||||||
uint32_t size = size_in_spiffs((char *)filename);
|
uint32_t size = size_in_spiffs((char *)filename);
|
||||||
if (changed) rdv40_spiffs_lazy_unmount();
|
if (changed) rdv40_spiffs_lazy_unmount();
|
||||||
|
@ -1849,7 +1886,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
uint8_t filename[32];
|
uint8_t filename[32];
|
||||||
uint8_t *pfilename = packet->data.asBytes;
|
uint8_t *pfilename = packet->data.asBytes;
|
||||||
memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN);
|
memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN);
|
||||||
if (DBGLEVEL > 1) Dbprintf("> Filename received for spiffs REMOVE : %s", filename);
|
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Filename received for spiffs REMOVE : %s", filename);
|
||||||
rdv40_spiffs_remove((char *) filename, RDV40_SPIFFS_SAFETY_SAFE);
|
rdv40_spiffs_remove((char *) filename, RDV40_SPIFFS_SAFETY_SAFE);
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
break;
|
break;
|
||||||
|
@ -1864,9 +1901,9 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
strncpy((char *)src, token, sizeof(src) - 1);
|
strncpy((char *)src, token, sizeof(src) - 1);
|
||||||
token = strtok(NULL, ",");
|
token = strtok(NULL, ",");
|
||||||
strncpy((char *)dest, token, sizeof(dest) - 1);
|
strncpy((char *)dest, token, sizeof(dest) - 1);
|
||||||
if (DBGLEVEL > 1) {
|
if (DBGLEVEL >= DBG_DEBUG) {
|
||||||
Dbprintf("> Filename received as source for spiffs RENAME : %s", src);
|
Dbprintf("Filename received as source for spiffs RENAME : %s", src);
|
||||||
Dbprintf("> Filename received as destination for spiffs RENAME : %s", dest);
|
Dbprintf("Filename received as destination for spiffs RENAME : %s", dest);
|
||||||
}
|
}
|
||||||
rdv40_spiffs_rename((char *) src, (char *)dest, RDV40_SPIFFS_SAFETY_SAFE);
|
rdv40_spiffs_rename((char *) src, (char *)dest, RDV40_SPIFFS_SAFETY_SAFE);
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
@ -1882,9 +1919,9 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
strncpy((char *)src, token, sizeof(src) - 1);
|
strncpy((char *)src, token, sizeof(src) - 1);
|
||||||
token = strtok(NULL, ",");
|
token = strtok(NULL, ",");
|
||||||
strncpy((char *)dest, token, sizeof(dest) - 1);
|
strncpy((char *)dest, token, sizeof(dest) - 1);
|
||||||
if (DBGLEVEL > 1) {
|
if (DBGLEVEL >= DBG_DEBUG) {
|
||||||
Dbprintf("> Filename received as source for spiffs COPY : %s", src);
|
Dbprintf("Filename received as source for spiffs COPY : %s", src);
|
||||||
Dbprintf("> Filename received as destination for spiffs COPY : %s", dest);
|
Dbprintf("Filename received as destination for spiffs COPY : %s", dest);
|
||||||
}
|
}
|
||||||
rdv40_spiffs_copy((char *) src, (char *)dest, RDV40_SPIFFS_SAFETY_SAFE);
|
rdv40_spiffs_copy((char *) src, (char *)dest, RDV40_SPIFFS_SAFETY_SAFE);
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
@ -1896,14 +1933,12 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
uint32_t append = packet->oldarg[0];
|
uint32_t append = packet->oldarg[0];
|
||||||
uint32_t size = packet->oldarg[1];
|
uint32_t size = packet->oldarg[1];
|
||||||
uint8_t *data = packet->data.asBytes;
|
uint8_t *data = packet->data.asBytes;
|
||||||
|
|
||||||
//rdv40_spiffs_lazy_mount();
|
|
||||||
|
|
||||||
uint8_t *pfilename = packet->data.asBytes;
|
uint8_t *pfilename = packet->data.asBytes;
|
||||||
memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN);
|
memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN);
|
||||||
data += SPIFFS_OBJ_NAME_LEN;
|
data += SPIFFS_OBJ_NAME_LEN;
|
||||||
|
|
||||||
if (DBGLEVEL > 1) Dbprintf("> Filename received for spiffs WRITE : %s with APPEND SET TO : %d", filename, append);
|
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("> Filename received for spiffs WRITE : %s with APPEND SET TO : %d", filename, append);
|
||||||
|
|
||||||
if (!append) {
|
if (!append) {
|
||||||
rdv40_spiffs_write((char *) filename, (uint8_t *)data, size, RDV40_SPIFFS_SAFETY_SAFE);
|
rdv40_spiffs_write((char *) filename, (uint8_t *)data, size, RDV40_SPIFFS_SAFETY_SAFE);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -90,6 +90,7 @@ static em4x50_tag_t tag = {
|
||||||
#define EM4X50_COMMAND_WRITE_PASSWORD 0x11
|
#define EM4X50_COMMAND_WRITE_PASSWORD 0x11
|
||||||
#define EM4X50_COMMAND_SELECTIVE_READ 0x0A
|
#define EM4X50_COMMAND_SELECTIVE_READ 0x0A
|
||||||
|
|
||||||
|
#define EM4X50_COMMAND_TIMEOUT 5000
|
||||||
#define FPGA_TIMER_0 0
|
#define FPGA_TIMER_0 0
|
||||||
|
|
||||||
int gHigh = 0;
|
int gHigh = 0;
|
||||||
|
@ -99,6 +100,8 @@ int gLow = 0;
|
||||||
|
|
||||||
static void init_tag(void) {
|
static void init_tag(void) {
|
||||||
|
|
||||||
|
// iceman: memset(tag.sectors, 0x00, sizeof));
|
||||||
|
|
||||||
// initialize global tag structure
|
// initialize global tag structure
|
||||||
for (int i = 0; i < 34; i++)
|
for (int i = 0; i < 34; i++)
|
||||||
for (int j = 0; j < 7; j++)
|
for (int j = 0; j < 7; j++)
|
||||||
|
@ -185,10 +188,9 @@ static void em4x50_setup_read(void) {
|
||||||
|
|
||||||
// 50ms for the resonant antenna to settle.
|
// 50ms for the resonant antenna to settle.
|
||||||
SpinDelay(50);
|
SpinDelay(50);
|
||||||
|
|
||||||
// Now set up the SSC to get the ADC samples that are now streaming at us.
|
// Now set up the SSC to get the ADC samples that are now streaming at us.
|
||||||
FpgaSetupSsc(FPGA_MAJOR_MODE_LF_READER);
|
FpgaSetupSsc(FPGA_MAJOR_MODE_LF_READER);
|
||||||
// start a 1.5ticks is 1us
|
|
||||||
StartTicks();
|
|
||||||
|
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_125);
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_125);
|
||||||
|
|
||||||
|
@ -255,10 +257,9 @@ static bool get_signalproperties(void) {
|
||||||
signal_found = true;
|
signal_found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!signal_found)
|
if (signal_found == false)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// calculate mean maximum value of 32 periods, each period has a length of
|
// calculate mean maximum value of 32 periods, each period has a length of
|
||||||
|
@ -312,35 +313,46 @@ static int get_next_bit(void) {
|
||||||
|
|
||||||
static uint32_t get_pulse_length(void) {
|
static uint32_t get_pulse_length(void) {
|
||||||
|
|
||||||
|
// Dbprintf( _CYAN_("4x50 get_pulse_length A") );
|
||||||
|
|
||||||
|
int32_t timeout = (T0 * 3 * EM4X50_T_TAG_FULL_PERIOD);
|
||||||
|
|
||||||
// iterates pulse length (low -> high -> low)
|
// iterates pulse length (low -> high -> low)
|
||||||
|
|
||||||
uint8_t sample = 0;
|
volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
|
|
||||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
while (sample > gLow && (timeout--)) {
|
||||||
|
|
||||||
while (sample > gLow)
|
|
||||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeout == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
|
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
|
||||||
|
timeout = (T0 * 3 * EM4X50_T_TAG_FULL_PERIOD);
|
||||||
|
|
||||||
while (sample < gHigh)
|
while (sample < gHigh && (timeout--)) {
|
||||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
|
}
|
||||||
|
|
||||||
while (sample > gLow)
|
if (timeout == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
timeout = (T0 * 3 * EM4X50_T_TAG_FULL_PERIOD);
|
||||||
|
while (sample > gLow && (timeout--)) {
|
||||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeout == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
return (uint32_t)AT91C_BASE_TC1->TC_CV;
|
return (uint32_t)AT91C_BASE_TC1->TC_CV;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool check_pulse_length(uint32_t pl, int length) {
|
static bool check_pulse_length(uint32_t pl, int length) {
|
||||||
|
|
||||||
// check if pulse length <pl> corresponds to given length <length>
|
// check if pulse length <pl> corresponds to given length <length>
|
||||||
|
return ((pl >= T0 * (length - EM4X50_TAG_TOLERANCE)) & (pl <= T0 * (length + EM4X50_TAG_TOLERANCE)));
|
||||||
if ((pl >= T0 * (length - EM4X50_TAG_TOLERANCE)) &
|
|
||||||
(pl <= T0 * (length + EM4X50_TAG_TOLERANCE)))
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void em4x50_send_bit(int bit) {
|
static void em4x50_send_bit(int bit) {
|
||||||
|
@ -428,13 +440,9 @@ static bool find_single_listen_window(void) {
|
||||||
|
|
||||||
// listen window found
|
// listen window found
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
|
|
||||||
cnt_pulses++;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
cnt_pulses++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -494,7 +502,6 @@ static bool find_double_listen_window(bool bcommand) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
cnt_pulses++;
|
cnt_pulses++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -506,9 +513,7 @@ static bool find_em4x50_tag(void) {
|
||||||
|
|
||||||
// function is used to check wether a tag on the proxmark is an
|
// function is used to check wether a tag on the proxmark is an
|
||||||
// EM4x50 tag or not -> speed up "lf search" process
|
// EM4x50 tag or not -> speed up "lf search" process
|
||||||
|
return find_single_listen_window();
|
||||||
return (find_single_listen_window());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool request_receive_mode(void) {
|
static bool request_receive_mode(void) {
|
||||||
|
@ -516,9 +521,7 @@ static bool request_receive_mode(void) {
|
||||||
// To issue a command we have to find a listen window first.
|
// To issue a command we have to find a listen window first.
|
||||||
// Because identification and sychronization at the same time is not
|
// Because identification and sychronization at the same time is not
|
||||||
// possible when using pulse lengths a double listen window is used.
|
// possible when using pulse lengths a double listen window is used.
|
||||||
|
|
||||||
bool bcommand = true;
|
bool bcommand = true;
|
||||||
|
|
||||||
return find_double_listen_window(bcommand);
|
return find_double_listen_window(bcommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
16
armsrc/epa.c
16
armsrc/epa.c
|
@ -229,7 +229,7 @@ int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length) {
|
||||||
sizeof(apdu_select_binary_cardaccess),
|
sizeof(apdu_select_binary_cardaccess),
|
||||||
response_apdu,
|
response_apdu,
|
||||||
sizeof(response_apdu)
|
sizeof(response_apdu)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (rapdu_length < 6
|
if (rapdu_length < 6
|
||||||
|| response_apdu[rapdu_length - 4] != 0x90
|
|| response_apdu[rapdu_length - 4] != 0x90
|
||||||
|
@ -243,7 +243,7 @@ int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length) {
|
||||||
sizeof(apdu_read_binary),
|
sizeof(apdu_read_binary),
|
||||||
response_apdu,
|
response_apdu,
|
||||||
sizeof(response_apdu)
|
sizeof(response_apdu)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (rapdu_length <= 6
|
if (rapdu_length <= 6
|
||||||
|| response_apdu[rapdu_length - 4] != 0x90
|
|| response_apdu[rapdu_length - 4] != 0x90
|
||||||
|
@ -325,11 +325,11 @@ void EPA_PACE_Collect_Nonce(PacketCommandNG *c) {
|
||||||
|
|
||||||
// now get the nonce
|
// now get the nonce
|
||||||
uint8_t nonce[256] = {0};
|
uint8_t nonce[256] = {0};
|
||||||
|
|
||||||
struct p {
|
struct p {
|
||||||
uint32_t m;
|
uint32_t m;
|
||||||
} PACKED;
|
} PACKED;
|
||||||
struct p *packet = (struct p*)c->data.asBytes;
|
struct p *packet = (struct p *)c->data.asBytes;
|
||||||
|
|
||||||
func_return = EPA_PACE_Get_Nonce(packet->m, nonce);
|
func_return = EPA_PACE_Get_Nonce(packet->m, nonce);
|
||||||
// check if the command succeeded
|
// check if the command succeeded
|
||||||
|
@ -359,7 +359,7 @@ int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce) {
|
||||||
|
|
||||||
// copy the constant part
|
// copy the constant part
|
||||||
memcpy(apdu, apdu_general_authenticate_pace_get_nonce, sizeof(apdu_general_authenticate_pace_get_nonce));
|
memcpy(apdu, apdu_general_authenticate_pace_get_nonce, sizeof(apdu_general_authenticate_pace_get_nonce));
|
||||||
|
|
||||||
// append Le (requested length + 2 due to tag/length taking 2 bytes) in RAPDU
|
// append Le (requested length + 2 due to tag/length taking 2 bytes) in RAPDU
|
||||||
apdu[sizeof(apdu_general_authenticate_pace_get_nonce)] = requested_length + 4;
|
apdu[sizeof(apdu_general_authenticate_pace_get_nonce)] = requested_length + 4;
|
||||||
|
|
||||||
|
@ -444,8 +444,8 @@ int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password)
|
||||||
// check if the command succeeded
|
// check if the command succeeded
|
||||||
if (send_return != 6)
|
if (send_return != 6)
|
||||||
// && response_apdu[send_return - 4] != 0x90
|
// && response_apdu[send_return - 4] != 0x90
|
||||||
// || response_apdu[send_return - 3] != 0x00)
|
// || response_apdu[send_return - 3] != 0x00)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -500,7 +500,7 @@ void EPA_PACE_Replay(PacketCommandNG *c) {
|
||||||
apdu_lengths_replay[i],
|
apdu_lengths_replay[i],
|
||||||
response_apdu,
|
response_apdu,
|
||||||
sizeof(response_apdu)
|
sizeof(response_apdu)
|
||||||
);
|
);
|
||||||
timings[i] = GetCountUS();
|
timings[i] = GetCountUS();
|
||||||
// every step but the last one should succeed
|
// every step but the last one should succeed
|
||||||
if (i < ARRAYLEN(apdu_lengths_replay) - 1
|
if (i < ARRAYLEN(apdu_lengths_replay) - 1
|
||||||
|
|
|
@ -122,6 +122,51 @@ static uint32_t LastProxToAirDuration;
|
||||||
#define SEC_Y 0x00
|
#define SEC_Y 0x00
|
||||||
#define SEC_Z 0xc0
|
#define SEC_Z 0xc0
|
||||||
|
|
||||||
|
/*
|
||||||
|
Default HF 14a config is set to:
|
||||||
|
forceanticol = 0 (auto)
|
||||||
|
forcebcc = 0 (expect valid BCC)
|
||||||
|
forcecl2 = 0 (auto)
|
||||||
|
forcecl3 = 0 (auto)
|
||||||
|
forcerats = 0 (auto)
|
||||||
|
*/
|
||||||
|
static hf14a_config hf14aconfig = { 0, 0, 0, 0, 0 } ;
|
||||||
|
|
||||||
|
void printHf14aConfig(void) {
|
||||||
|
DbpString(_CYAN_("HF 14a config"));
|
||||||
|
Dbprintf("[a] Anticol override......%s%s%s", (hf14aconfig.forceanticol == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forceanticol == 1) ? _RED_("Yes: Always do anticol") : "", (hf14aconfig.forceanticol == 2) ? _RED_("Yes: Always skip anticol") : "");
|
||||||
|
Dbprintf("[b] BCC override..........%s%s%s", (hf14aconfig.forcebcc == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcebcc == 1) ? _RED_("Yes: Always do CL2") : "", (hf14aconfig.forcebcc == 2) ? _RED_("Yes: Always use card BCC") : "");
|
||||||
|
Dbprintf("[2] CL2 override..........%s%s%s", (hf14aconfig.forcecl2 == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcecl2 == 1) ? _RED_("Yes: Always do CL2") : "", (hf14aconfig.forcecl2 == 2) ? _RED_("Yes: Always skip CL2") : "");
|
||||||
|
Dbprintf("[3] CL3 override..........%s%s%s", (hf14aconfig.forcecl3 == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcecl3 == 1) ? _RED_("Yes: Always do CL3") : "", (hf14aconfig.forcecl3 == 2) ? _RED_("Yes: Always skip CL3") : "");
|
||||||
|
Dbprintf("[r] RATS override.........%s%s%s", (hf14aconfig.forcerats == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcerats == 1) ? _RED_("Yes: Always do RATS") : "", (hf14aconfig.forcerats == 2) ? _RED_("Yes: Always skip RATS") : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called from the USB-handler to set the 14a configuration
|
||||||
|
* The 14a config is used for card selection sequence.
|
||||||
|
*
|
||||||
|
* Values set to '-1' implies no change
|
||||||
|
* @brief setSamplingConfig
|
||||||
|
* @param sc
|
||||||
|
*/
|
||||||
|
void setHf14aConfig(hf14a_config *hc) {
|
||||||
|
|
||||||
|
if ((hc->forceanticol >= 0) && (hc->forceanticol <= 2))
|
||||||
|
hf14aconfig.forceanticol = hc->forceanticol;
|
||||||
|
if ((hc->forcebcc >= 0) && (hc->forcebcc <= 2))
|
||||||
|
hf14aconfig.forcebcc = hc->forcebcc;
|
||||||
|
if ((hc->forcecl2 >= 0) && (hc->forcecl2 <= 2))
|
||||||
|
hf14aconfig.forcecl2 = hc->forcecl2;
|
||||||
|
if ((hc->forcecl3 >= 0) && (hc->forcecl3 <= 2))
|
||||||
|
hf14aconfig.forcecl3 = hc->forcecl3;
|
||||||
|
if ((hc->forcerats >= 0) && (hc->forcerats <= 2))
|
||||||
|
hf14aconfig.forcerats = hc->forcerats;
|
||||||
|
}
|
||||||
|
|
||||||
|
hf14a_config *getHf14aConfig(void) {
|
||||||
|
return &hf14aconfig;
|
||||||
|
}
|
||||||
|
|
||||||
void iso14a_set_trigger(bool enable) {
|
void iso14a_set_trigger(bool enable) {
|
||||||
g_trigger = enable;
|
g_trigger = enable;
|
||||||
}
|
}
|
||||||
|
@ -1832,8 +1877,8 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
if (check == 1000) {
|
if (check == 2000) {
|
||||||
if (BUTTON_PRESS() || data_available())
|
if (BUTTON_PRESS())
|
||||||
return 1;
|
return 1;
|
||||||
check = 0;
|
check = 0;
|
||||||
}
|
}
|
||||||
|
@ -1959,7 +2004,6 @@ int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen) {
|
||||||
b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR);
|
b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR);
|
||||||
(void)b;
|
(void)b;
|
||||||
}
|
}
|
||||||
if (BUTTON_PRESS()) break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that the FPGA Delay Queue is empty before we switch to TAGSIM_LISTEN again:
|
// Ensure that the FPGA Delay Queue is empty before we switch to TAGSIM_LISTEN again:
|
||||||
|
@ -2336,7 +2380,8 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
|
||||||
uint8_t resp[MAX_FRAME_SIZE] = {0}; // theoretically. A usual RATS will be much smaller
|
uint8_t resp[MAX_FRAME_SIZE] = {0}; // theoretically. A usual RATS will be much smaller
|
||||||
uint8_t resp_par[MAX_PARITY_SIZE] = {0};
|
uint8_t resp_par[MAX_PARITY_SIZE] = {0};
|
||||||
|
|
||||||
uint8_t sak = 0x04; // cascade uid
|
uint8_t sak; // cascade uid
|
||||||
|
bool do_cascade = 1;
|
||||||
int cascade_level = 0;
|
int cascade_level = 0;
|
||||||
|
|
||||||
if (p_card) {
|
if (p_card) {
|
||||||
|
@ -2360,26 +2405,32 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
|
||||||
memset(uid_ptr, 0, 10);
|
memset(uid_ptr, 0, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for proprietary anticollision:
|
if (hf14aconfig.forceanticol == 0) {
|
||||||
if ((resp[0] & 0x1F) == 0) return 3;
|
// check for proprietary anticollision:
|
||||||
|
if ((resp[0] & 0x1F) == 0) return 3;
|
||||||
|
} else if (hf14aconfig.forceanticol == 2) {
|
||||||
|
return 3; // force skipping anticol
|
||||||
|
} // else force executing
|
||||||
|
|
||||||
// OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in
|
// OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in
|
||||||
// which case we need to make a cascade 2 request and select - this is a long UID
|
// which case we need to make a cascade 2 request and select - this is a long UID
|
||||||
// While the UID is not complete, the 3nd bit (from the right) is set in the SAK.
|
// While the UID is not complete, the 3nd bit (from the right) is set in the SAK.
|
||||||
for (; sak & 0x04; cascade_level++) {
|
for (; do_cascade; cascade_level++) {
|
||||||
// SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97)
|
// SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97)
|
||||||
uint8_t sel_all[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x20 };
|
uint8_t sel_all[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x20 };
|
||||||
uint8_t sel_uid[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
uint8_t sel_uid[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
uint8_t uid_resp[4] = {0};
|
uint8_t uid_resp[5] = {0}; // UID + original BCC
|
||||||
sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2;
|
sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2;
|
||||||
|
|
||||||
if (anticollision) {
|
if (anticollision) {
|
||||||
// SELECT_ALL
|
// SELECT_ALL
|
||||||
ReaderTransmit(sel_all, sizeof(sel_all), NULL);
|
ReaderTransmit(sel_all, sizeof(sel_all), NULL);
|
||||||
if (!ReaderReceive(resp, resp_par)) return 0;
|
if (!ReaderReceive(resp, resp_par)) {
|
||||||
|
Dbprintf("Card didn't answer to CL%i select all", cascade_level + 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (Demod.collisionPos) { // we had a collision and need to construct the UID bit by bit
|
if (Demod.collisionPos) { // we had a collision and need to construct the UID bit by bit
|
||||||
memset(uid_resp, 0, 4);
|
memset(uid_resp, 0, 5);
|
||||||
uint16_t uid_resp_bits = 0;
|
uint16_t uid_resp_bits = 0;
|
||||||
uint16_t collision_answer_offset = 0;
|
uint16_t collision_answer_offset = 0;
|
||||||
// anti-collision-loop:
|
// anti-collision-loop:
|
||||||
|
@ -2391,7 +2442,7 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
|
||||||
}
|
}
|
||||||
uid_resp[uid_resp_bits / 8] |= 1 << (uid_resp_bits % 8); // next time select the card(s) with a 1 in the collision position
|
uid_resp[uid_resp_bits / 8] |= 1 << (uid_resp_bits % 8); // next time select the card(s) with a 1 in the collision position
|
||||||
uid_resp_bits++;
|
uid_resp_bits++;
|
||||||
// construct anticollosion command:
|
// construct anticollision command:
|
||||||
sel_uid[1] = ((2 + uid_resp_bits / 8) << 4) | (uid_resp_bits & 0x07); // length of data in bytes and bits
|
sel_uid[1] = ((2 + uid_resp_bits / 8) << 4) | (uid_resp_bits & 0x07); // length of data in bytes and bits
|
||||||
for (uint16_t i = 0; i <= uid_resp_bits / 8; i++) {
|
for (uint16_t i = 0; i <= uid_resp_bits / 8; i++) {
|
||||||
sel_uid[2 + i] = uid_resp[i];
|
sel_uid[2 + i] = uid_resp[i];
|
||||||
|
@ -2407,7 +2458,7 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
} else { // no collision, use the response to SELECT_ALL as current uid
|
} else { // no collision, use the response to SELECT_ALL as current uid
|
||||||
memcpy(uid_resp, resp, 4);
|
memcpy(uid_resp, resp, 5); // UID + original BCC
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -2426,18 +2477,51 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
|
||||||
|
|
||||||
// Construct SELECT UID command
|
// Construct SELECT UID command
|
||||||
sel_uid[1] = 0x70; // transmitting a full UID (1 Byte cmd, 1 Byte NVB, 4 Byte UID, 1 Byte BCC, 2 Bytes CRC)
|
sel_uid[1] = 0x70; // transmitting a full UID (1 Byte cmd, 1 Byte NVB, 4 Byte UID, 1 Byte BCC, 2 Bytes CRC)
|
||||||
memcpy(sel_uid + 2, uid_resp, 4); // the UID received during anticollision, or the provided UID
|
|
||||||
sel_uid[6] = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate and add BCC
|
if (anticollision) {
|
||||||
|
memcpy(sel_uid + 2, uid_resp, 5); // the UID received during anticollision with original BCC
|
||||||
|
uint8_t bcc = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate BCC
|
||||||
|
if (sel_uid[6] != bcc) {
|
||||||
|
Dbprintf("BCC%d incorrect, got 0x%02x, expected 0x%02x", cascade_level, sel_uid[6], bcc);
|
||||||
|
if (hf14aconfig.forcebcc == 0) {
|
||||||
|
Dbprintf("Aborting");
|
||||||
|
return 0;
|
||||||
|
} else if (hf14aconfig.forcebcc == 1) {
|
||||||
|
sel_uid[6] = bcc;
|
||||||
|
} // else use card BCC
|
||||||
|
Dbprintf("Using BCC=" _YELLOW_("0x%02x") " to perform anticollision", sel_uid[6]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
memcpy(sel_uid + 2, uid_resp, 4); // the provided UID
|
||||||
|
sel_uid[6] = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate and add BCC
|
||||||
|
}
|
||||||
|
|
||||||
AddCrc14A(sel_uid, 7); // calculate and add CRC
|
AddCrc14A(sel_uid, 7); // calculate and add CRC
|
||||||
ReaderTransmit(sel_uid, sizeof(sel_uid), NULL);
|
ReaderTransmit(sel_uid, sizeof(sel_uid), NULL);
|
||||||
|
|
||||||
// Receive the SAK
|
// Receive the SAK
|
||||||
if (!ReaderReceive(resp, resp_par)) return 0;
|
if (!ReaderReceive(resp, resp_par)) {
|
||||||
|
Dbprintf("Card didn't answer to select");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
sak = resp[0];
|
sak = resp[0];
|
||||||
|
|
||||||
// Test if more parts of the uid are coming
|
// Test if more parts of the uid are coming
|
||||||
if ((sak & 0x04) /* && uid_resp[0] == 0x88 */) {
|
do_cascade = (((sak & 0x04) /* && uid_resp[0] == 0x88 */) > 0);
|
||||||
|
if (cascade_level == 0) {
|
||||||
|
if (hf14aconfig.forcecl2 == 2) {
|
||||||
|
do_cascade = false;
|
||||||
|
} else if (hf14aconfig.forcecl2 == 1) {
|
||||||
|
do_cascade = true;
|
||||||
|
} // else 0==auto
|
||||||
|
} else if (cascade_level == 1) {
|
||||||
|
if (hf14aconfig.forcecl3 == 2) {
|
||||||
|
do_cascade = false;
|
||||||
|
} else if (hf14aconfig.forcecl3 == 1) {
|
||||||
|
do_cascade = true;
|
||||||
|
} // else 0==auto
|
||||||
|
}
|
||||||
|
if (do_cascade) {
|
||||||
// Remove first byte, 0x88 is not an UID byte, it CT, see page 3 of:
|
// Remove first byte, 0x88 is not an UID byte, it CT, see page 3 of:
|
||||||
// http://www.nxp.com/documents/application_note/AN10927.pdf
|
// http://www.nxp.com/documents/application_note/AN10927.pdf
|
||||||
uid_resp[0] = uid_resp[1];
|
uid_resp[0] = uid_resp[1];
|
||||||
|
@ -2459,8 +2543,12 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
|
||||||
p_card->sak = sak;
|
p_card->sak = sak;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PICC compilant with iso14443a-4 ---> (SAK & 0x20 != 0)
|
if (hf14aconfig.forcerats == 0) {
|
||||||
if ((sak & 0x20) == 0) return 2;
|
// PICC compliant with iso14443a-4 ---> (SAK & 0x20 != 0)
|
||||||
|
if ((sak & 0x20) == 0) return 2;
|
||||||
|
} else if (hf14aconfig.forcerats == 2) {
|
||||||
|
return 2;
|
||||||
|
} // else force RATS
|
||||||
|
|
||||||
// RATS, Request for answer to select
|
// RATS, Request for answer to select
|
||||||
if (!no_rats) {
|
if (!no_rats) {
|
||||||
|
|
|
@ -96,6 +96,9 @@ typedef struct {
|
||||||
# define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len))
|
# define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void printHf14aConfig(void);
|
||||||
|
void setHf14aConfig(hf14a_config *hc);
|
||||||
|
hf14a_config *getHf14aConfig(void);
|
||||||
void iso14a_set_timeout(uint32_t timeout);
|
void iso14a_set_timeout(uint32_t timeout);
|
||||||
uint32_t iso14a_get_timeout(void);
|
uint32_t iso14a_get_timeout(void);
|
||||||
|
|
||||||
|
|
|
@ -44,12 +44,12 @@
|
||||||
# define FWT_TIMEOUT_14B 35312
|
# define FWT_TIMEOUT_14B 35312
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// 330/848kHz = 1558us / 4 == 400us,
|
// 330/848kHz = 1558us / 4 == 400us,
|
||||||
#define ISO14443B_READER_TIMEOUT 1700 //330
|
#define ISO14443B_READER_TIMEOUT 1700 //330
|
||||||
|
|
||||||
// 1024/3.39MHz = 302.1us between end of tag response and next reader cmd
|
// 1024/3.39MHz = 302.1us between end of tag response and next reader cmd
|
||||||
#define DELAY_ISO14443B_VICC_TO_VCD_READER 600 // 1024
|
#define DELAY_ISO14443B_VICC_TO_VCD_READER 600 // 1024
|
||||||
#define DELAY_ISO14443B_VCD_TO_VICC_READER 600// 1056
|
#define DELAY_ISO14443B_VCD_TO_VICC_READER 600// 1056
|
||||||
|
|
||||||
#ifndef RECEIVE_MASK
|
#ifndef RECEIVE_MASK
|
||||||
# define RECEIVE_MASK (DMA_BUFFER_SIZE - 1)
|
# define RECEIVE_MASK (DMA_BUFFER_SIZE - 1)
|
||||||
|
@ -740,7 +740,7 @@ void SimulateIso14443bTag(uint32_t pupi) {
|
||||||
*/
|
*/
|
||||||
static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
|
static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
|
||||||
|
|
||||||
int v;
|
int v;
|
||||||
|
|
||||||
// The soft decision on the bit uses an estimate of just the
|
// The soft decision on the bit uses an estimate of just the
|
||||||
// quadrant of the reference angle, not the exact angle.
|
// quadrant of the reference angle, not the exact angle.
|
||||||
|
@ -761,137 +761,137 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
|
||||||
// Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by max(abs(ci),abs(cq)) + 1/2*min(abs(ci),abs(cq)))
|
// Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by max(abs(ci),abs(cq)) + 1/2*min(abs(ci),abs(cq)))
|
||||||
#define AMPLITUDE(ci,cq) (MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2))
|
#define AMPLITUDE(ci,cq) (MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2))
|
||||||
|
|
||||||
switch(Demod.state) {
|
switch (Demod.state) {
|
||||||
|
|
||||||
case DEMOD_UNSYNCD: {
|
case DEMOD_UNSYNCD: {
|
||||||
if (AMPLITUDE(ci, cq) > SUBCARRIER_DETECT_THRESHOLD) { // subcarrier detected
|
if (AMPLITUDE(ci, cq) > SUBCARRIER_DETECT_THRESHOLD) { // subcarrier detected
|
||||||
Demod.state = DEMOD_PHASE_REF_TRAINING;
|
Demod.state = DEMOD_PHASE_REF_TRAINING;
|
||||||
Demod.sumI = ci;
|
Demod.sumI = ci;
|
||||||
Demod.sumQ = cq;
|
Demod.sumQ = cq;
|
||||||
Demod.posCount = 1;
|
Demod.posCount = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DEMOD_PHASE_REF_TRAINING: {
|
case DEMOD_PHASE_REF_TRAINING: {
|
||||||
if (Demod.posCount < 8) {
|
if (Demod.posCount < 8) {
|
||||||
if (AMPLITUDE(ci, cq) > SUBCARRIER_DETECT_THRESHOLD) {
|
if (AMPLITUDE(ci, cq) > SUBCARRIER_DETECT_THRESHOLD) {
|
||||||
// set the reference phase (will code a logic '1') by averaging over 32 1/fs.
|
// set the reference phase (will code a logic '1') by averaging over 32 1/fs.
|
||||||
// note: synchronization time > 80 1/fs
|
// note: synchronization time > 80 1/fs
|
||||||
Demod.sumI += ci;
|
Demod.sumI += ci;
|
||||||
Demod.sumQ += cq;
|
Demod.sumQ += cq;
|
||||||
Demod.posCount++;
|
Demod.posCount++;
|
||||||
} else {
|
} else {
|
||||||
// subcarrier lost
|
// subcarrier lost
|
||||||
Demod.state = DEMOD_UNSYNCD;
|
Demod.state = DEMOD_UNSYNCD;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF;
|
Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DEMOD_AWAITING_FALLING_EDGE_OF_SOF: {
|
case DEMOD_AWAITING_FALLING_EDGE_OF_SOF: {
|
||||||
|
|
||||||
MAKE_SOFT_DECISION();
|
MAKE_SOFT_DECISION();
|
||||||
|
|
||||||
if (v < 0) { // logic '0' detected
|
if (v < 0) { // logic '0' detected
|
||||||
Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF;
|
Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF;
|
||||||
Demod.posCount = 0; // start of SOF sequence
|
Demod.posCount = 0; // start of SOF sequence
|
||||||
} else {
|
} else {
|
||||||
if (Demod.posCount > 200 / 4) { // maximum length of TR1 = 200 1/fs
|
if (Demod.posCount > 200 / 4) { // maximum length of TR1 = 200 1/fs
|
||||||
Demod.state = DEMOD_UNSYNCD;
|
Demod.state = DEMOD_UNSYNCD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Demod.posCount++;
|
Demod.posCount++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DEMOD_GOT_FALLING_EDGE_OF_SOF: {
|
case DEMOD_GOT_FALLING_EDGE_OF_SOF: {
|
||||||
|
|
||||||
Demod.posCount++;
|
Demod.posCount++;
|
||||||
MAKE_SOFT_DECISION();
|
MAKE_SOFT_DECISION();
|
||||||
|
|
||||||
if (v > 0) {
|
if (v > 0) {
|
||||||
if (Demod.posCount < 9 * 2) { // low phase of SOF too short (< 9 etu). Note: spec is >= 10, but FPGA tends to "smear" edges
|
if (Demod.posCount < 9 * 2) { // low phase of SOF too short (< 9 etu). Note: spec is >= 10, but FPGA tends to "smear" edges
|
||||||
Demod.state = DEMOD_UNSYNCD;
|
Demod.state = DEMOD_UNSYNCD;
|
||||||
} else {
|
} else {
|
||||||
LED_C_ON(); // Got SOF
|
LED_C_ON(); // Got SOF
|
||||||
Demod.posCount = 0;
|
Demod.posCount = 0;
|
||||||
Demod.bitCount = 0;
|
Demod.bitCount = 0;
|
||||||
Demod.len = 0;
|
Demod.len = 0;
|
||||||
Demod.state = DEMOD_AWAITING_START_BIT;
|
Demod.state = DEMOD_AWAITING_START_BIT;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Demod.posCount > 14 * 2) { // low phase of SOF too long (> 12 etu)
|
if (Demod.posCount > 14 * 2) { // low phase of SOF too long (> 12 etu)
|
||||||
Demod.state = DEMOD_UNSYNCD;
|
Demod.state = DEMOD_UNSYNCD;
|
||||||
LED_C_OFF();
|
LED_C_OFF();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DEMOD_AWAITING_START_BIT: {
|
case DEMOD_AWAITING_START_BIT: {
|
||||||
Demod.posCount++;
|
Demod.posCount++;
|
||||||
MAKE_SOFT_DECISION();
|
MAKE_SOFT_DECISION();
|
||||||
if (v > 0) {
|
if (v > 0) {
|
||||||
if (Demod.posCount > 6 * 2) { // max 19us between characters = 16 1/fs, max 3 etu after low phase of SOF = 24 1/fs
|
if (Demod.posCount > 6 * 2) { // max 19us between characters = 16 1/fs, max 3 etu after low phase of SOF = 24 1/fs
|
||||||
LED_C_OFF();
|
LED_C_OFF();
|
||||||
if (Demod.bitCount == 0 && Demod.len == 0) { // received SOF only, this is valid for iClass/Picopass
|
if (Demod.bitCount == 0 && Demod.len == 0) { // received SOF only, this is valid for iClass/Picopass
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
Demod.state = DEMOD_UNSYNCD;
|
Demod.state = DEMOD_UNSYNCD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // start bit detected
|
} else { // start bit detected
|
||||||
Demod.posCount = 1; // this was the first half
|
Demod.posCount = 1; // this was the first half
|
||||||
Demod.thisBit = v;
|
Demod.thisBit = v;
|
||||||
Demod.shiftReg = 0;
|
Demod.shiftReg = 0;
|
||||||
Demod.state = DEMOD_RECEIVING_DATA;
|
Demod.state = DEMOD_RECEIVING_DATA;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DEMOD_RECEIVING_DATA: {
|
case DEMOD_RECEIVING_DATA: {
|
||||||
|
|
||||||
MAKE_SOFT_DECISION();
|
MAKE_SOFT_DECISION();
|
||||||
|
|
||||||
if (Demod.posCount == 0) { // first half of bit
|
if (Demod.posCount == 0) { // first half of bit
|
||||||
Demod.thisBit = v;
|
Demod.thisBit = v;
|
||||||
Demod.posCount = 1;
|
Demod.posCount = 1;
|
||||||
} else { // second half of bit
|
} else { // second half of bit
|
||||||
Demod.thisBit += v;
|
Demod.thisBit += v;
|
||||||
|
|
||||||
Demod.shiftReg >>= 1;
|
Demod.shiftReg >>= 1;
|
||||||
if (Demod.thisBit > 0) { // logic '1'
|
if (Demod.thisBit > 0) { // logic '1'
|
||||||
Demod.shiftReg |= 0x200;
|
Demod.shiftReg |= 0x200;
|
||||||
}
|
}
|
||||||
|
|
||||||
Demod.bitCount++;
|
Demod.bitCount++;
|
||||||
if (Demod.bitCount == 10) {
|
if (Demod.bitCount == 10) {
|
||||||
|
|
||||||
uint16_t s = Demod.shiftReg;
|
uint16_t s = Demod.shiftReg;
|
||||||
|
|
||||||
if ((s & 0x200) && !(s & 0x001)) { // stop bit == '1', start bit == '0'
|
if ((s & 0x200) && !(s & 0x001)) { // stop bit == '1', start bit == '0'
|
||||||
Demod.output[Demod.len] = (s >> 1);
|
Demod.output[Demod.len] = (s >> 1);
|
||||||
Demod.len++;
|
Demod.len++;
|
||||||
Demod.bitCount = 0;
|
Demod.bitCount = 0;
|
||||||
Demod.state = DEMOD_AWAITING_START_BIT;
|
Demod.state = DEMOD_AWAITING_START_BIT;
|
||||||
} else {
|
} else {
|
||||||
Demod.state = DEMOD_UNSYNCD;
|
Demod.state = DEMOD_UNSYNCD;
|
||||||
LED_C_OFF();
|
LED_C_OFF();
|
||||||
if (s == 0x000) {
|
if (s == 0x000) {
|
||||||
// This is EOF (start, stop and all data bits == '0'
|
// This is EOF (start, stop and all data bits == '0'
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Demod.posCount = 0;
|
Demod.posCount = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
Demod.state = DEMOD_UNSYNCD;
|
Demod.state = DEMOD_UNSYNCD;
|
||||||
LED_C_OFF();
|
LED_C_OFF();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -938,9 +938,9 @@ static int Get14443bAnswerFromTag(uint8_t *response, uint16_t max_len, int timeo
|
||||||
}
|
}
|
||||||
|
|
||||||
volatile int8_t ci = *upTo >> 8;
|
volatile int8_t ci = *upTo >> 8;
|
||||||
volatile int8_t cq = *upTo;
|
volatile int8_t cq = *upTo;
|
||||||
upTo++;
|
upTo++;
|
||||||
|
|
||||||
// we have read all of the DMA buffer content.
|
// we have read all of the DMA buffer content.
|
||||||
if (upTo >= dma->buf + DMA_BUFFER_SIZE) {
|
if (upTo >= dma->buf + DMA_BUFFER_SIZE) {
|
||||||
|
|
||||||
|
@ -960,7 +960,7 @@ static int Get14443bAnswerFromTag(uint8_t *response, uint16_t max_len, int timeo
|
||||||
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dma->buf;
|
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dma->buf;
|
||||||
AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
|
AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
if (BUTTON_PRESS()) {
|
if (BUTTON_PRESS()) {
|
||||||
DbpString("stopped");
|
DbpString("stopped");
|
||||||
|
@ -993,9 +993,9 @@ static int Get14443bAnswerFromTag(uint8_t *response, uint16_t max_len, int timeo
|
||||||
|
|
||||||
if (Demod.len > 0) {
|
if (Demod.len > 0) {
|
||||||
uint32_t sof_time = *eof_time
|
uint32_t sof_time = *eof_time
|
||||||
- (Demod.len * 8 * 8 * 16) // time for byte transfers
|
- (Demod.len * 8 * 8 * 16) // time for byte transfers
|
||||||
- (32 * 16) // time for SOF transfer
|
- (32 * 16) // time for SOF transfer
|
||||||
- 0; // time for EOF transfer
|
- 0; // time for EOF transfer
|
||||||
LogTrace(Demod.output, Demod.len, (sof_time * 4), (*eof_time * 4), NULL, false);
|
LogTrace(Demod.output, Demod.len, (sof_time * 4), (*eof_time * 4), NULL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1006,9 +1006,9 @@ static int Get14443bAnswerFromTag(uint8_t *response, uint16_t max_len, int timeo
|
||||||
// Transmit the command (to the tag) that was placed in ToSend[].
|
// Transmit the command (to the tag) that was placed in ToSend[].
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
static void TransmitFor14443b_AsReader(uint32_t *start_time) {
|
static void TransmitFor14443b_AsReader(uint32_t *start_time) {
|
||||||
|
|
||||||
tosend_t *ts = get_tosend();
|
tosend_t *ts = get_tosend();
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_SHALLOW_MOD);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_SHALLOW_MOD);
|
||||||
|
|
||||||
if (*start_time < DELAY_ARM_TO_TAG) {
|
if (*start_time < DELAY_ARM_TO_TAG) {
|
||||||
|
@ -1016,7 +1016,7 @@ static void TransmitFor14443b_AsReader(uint32_t *start_time) {
|
||||||
}
|
}
|
||||||
|
|
||||||
*start_time = (*start_time - DELAY_ARM_TO_TAG) & 0xfffffff0;
|
*start_time = (*start_time - DELAY_ARM_TO_TAG) & 0xfffffff0;
|
||||||
|
|
||||||
if (GetCountSspClk() > *start_time) { // we may miss the intended time
|
if (GetCountSspClk() > *start_time) { // we may miss the intended time
|
||||||
*start_time = (GetCountSspClk() + 16) & 0xfffffff0; // next possible time
|
*start_time = (GetCountSspClk() + 16) & 0xfffffff0; // next possible time
|
||||||
}
|
}
|
||||||
|
@ -1132,7 +1132,7 @@ static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len, uint32_t
|
||||||
tosend_t *ts = get_tosend();
|
tosend_t *ts = get_tosend();
|
||||||
CodeIso14443bAsReader(cmd, len);
|
CodeIso14443bAsReader(cmd, len);
|
||||||
TransmitFor14443b_AsReader(start_time);
|
TransmitFor14443b_AsReader(start_time);
|
||||||
*eof_time = *start_time + (32 * (8 * ts->max));
|
*eof_time = *start_time + (32 * (8 * ts->max));
|
||||||
LogTrace(cmd, len, *start_time, *eof_time, NULL, true);
|
LogTrace(cmd, len, *start_time, *eof_time, NULL, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1152,12 +1152,12 @@ uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *r
|
||||||
memcpy(message_frame + 2, message, message_length);
|
memcpy(message_frame + 2, message, message_length);
|
||||||
// EDC (CRC)
|
// EDC (CRC)
|
||||||
AddCrc14B(message_frame, message_length + 2);
|
AddCrc14B(message_frame, message_length + 2);
|
||||||
|
|
||||||
// send
|
// send
|
||||||
uint32_t start_time = 0;
|
uint32_t start_time = 0;
|
||||||
uint32_t eof_time = 0;
|
uint32_t eof_time = 0;
|
||||||
CodeAndTransmit14443bAsReader(message_frame, sizeof(message_frame), &start_time, &eof_time);
|
CodeAndTransmit14443bAsReader(message_frame, sizeof(message_frame), &start_time, &eof_time);
|
||||||
|
|
||||||
// get response
|
// get response
|
||||||
if (response == NULL) {
|
if (response == NULL) {
|
||||||
LED_A_OFF();
|
LED_A_OFF();
|
||||||
|
@ -1191,7 +1191,7 @@ static uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card) {
|
||||||
uint8_t r_init[3] = {0x0};
|
uint8_t r_init[3] = {0x0};
|
||||||
uint8_t r_select[3] = {0x0};
|
uint8_t r_select[3] = {0x0};
|
||||||
uint8_t r_papid[10] = {0x0};
|
uint8_t r_papid[10] = {0x0};
|
||||||
|
|
||||||
uint32_t start_time = 0;
|
uint32_t start_time = 0;
|
||||||
uint32_t eof_time = 0;
|
uint32_t eof_time = 0;
|
||||||
CodeAndTransmit14443bAsReader(init_srx, sizeof(init_srx), &start_time, &eof_time);
|
CodeAndTransmit14443bAsReader(init_srx, sizeof(init_srx), &start_time, &eof_time);
|
||||||
|
@ -1211,7 +1211,7 @@ static uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card) {
|
||||||
// SELECT command (with space for CRC)
|
// SELECT command (with space for CRC)
|
||||||
uint8_t select_srx[] = { ISO14443B_SELECT, 0x00, 0x00, 0x00};
|
uint8_t select_srx[] = { ISO14443B_SELECT, 0x00, 0x00, 0x00};
|
||||||
select_srx[1] = r_init[0];
|
select_srx[1] = r_init[0];
|
||||||
|
|
||||||
AddCrc14B(select_srx, 2);
|
AddCrc14B(select_srx, 2);
|
||||||
|
|
||||||
start_time = eof_time + DELAY_ISO14443B_VICC_TO_VCD_READER;
|
start_time = eof_time + DELAY_ISO14443B_VICC_TO_VCD_READER;
|
||||||
|
@ -1242,7 +1242,7 @@ static uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card) {
|
||||||
|
|
||||||
start_time = eof_time + DELAY_ISO14443B_VICC_TO_VCD_READER;
|
start_time = eof_time + DELAY_ISO14443B_VICC_TO_VCD_READER;
|
||||||
CodeAndTransmit14443bAsReader(select_srx, 3, &start_time, &eof_time); // Only first three bytes for this one
|
CodeAndTransmit14443bAsReader(select_srx, 3, &start_time, &eof_time); // Only first three bytes for this one
|
||||||
|
|
||||||
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
|
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
|
||||||
retlen = Get14443bAnswerFromTag(r_papid, sizeof(r_papid), ISO14443B_READER_TIMEOUT, &eof_time);
|
retlen = Get14443bAnswerFromTag(r_papid, sizeof(r_papid), ISO14443B_READER_TIMEOUT, &eof_time);
|
||||||
FpgaDisableTracing();
|
FpgaDisableTracing();
|
||||||
|
@ -1255,7 +1255,7 @@ static uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card) {
|
||||||
if (!check_crc(CRC_14443_B, r_papid, retlen)) {
|
if (!check_crc(CRC_14443_B, r_papid, retlen)) {
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (card) {
|
if (card) {
|
||||||
card->uidlen = 8;
|
card->uidlen = 8;
|
||||||
memcpy(card->uid, r_papid, 8);
|
memcpy(card->uid, r_papid, 8);
|
||||||
|
@ -1312,7 +1312,7 @@ int iso14443b_select_card(iso14b_card_select_t *card) {
|
||||||
AddCrc14B(attrib, 9);
|
AddCrc14B(attrib, 9);
|
||||||
start_time = eof_time + DELAY_ISO14443B_VICC_TO_VCD_READER;
|
start_time = eof_time + DELAY_ISO14443B_VICC_TO_VCD_READER;
|
||||||
CodeAndTransmit14443bAsReader(attrib, sizeof(attrib), &start_time, &eof_time);
|
CodeAndTransmit14443bAsReader(attrib, sizeof(attrib), &start_time, &eof_time);
|
||||||
|
|
||||||
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
|
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
|
||||||
retlen = Get14443bAnswerFromTag(r_attrib, sizeof(r_attrib), ISO14443B_READER_TIMEOUT, &eof_time);
|
retlen = Get14443bAnswerFromTag(r_attrib, sizeof(r_attrib), ISO14443B_READER_TIMEOUT, &eof_time);
|
||||||
FpgaDisableTracing();
|
FpgaDisableTracing();
|
||||||
|
@ -1423,10 +1423,10 @@ static bool ReadSTBlock(uint8_t blocknr, uint8_t *block) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Dbprintf("Address=%02x, Contents=%08x, CRC=%04x",
|
Dbprintf("Address=%02x, Contents=%08x, CRC=%04x",
|
||||||
blocknr,
|
blocknr,
|
||||||
(r_block[3] << 24) + (r_block[2] << 16) + (r_block[1] << 8) + r_block[0],
|
(r_block[3] << 24) + (r_block[2] << 16) + (r_block[1] << 8) + r_block[0],
|
||||||
(r_block[4] << 8) + r_block[5]);
|
(r_block[4] << 8) + r_block[5]);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1434,7 +1434,7 @@ void ReadSTMemoryIso14443b(uint16_t numofblocks) {
|
||||||
|
|
||||||
iso14443b_setup();
|
iso14443b_setup();
|
||||||
|
|
||||||
uint8_t *mem = BigBuf_malloc((numofblocks + 1) * 4 );
|
uint8_t *mem = BigBuf_malloc((numofblocks + 1) * 4);
|
||||||
|
|
||||||
iso14b_card_select_t card;
|
iso14b_card_select_t card;
|
||||||
uint8_t res = iso14443b_select_srx_card(&card);
|
uint8_t res = iso14443b_select_srx_card(&card);
|
||||||
|
@ -1450,15 +1450,15 @@ void ReadSTMemoryIso14443b(uint16_t numofblocks) {
|
||||||
|
|
||||||
for (uint8_t i = 0; i < numofblocks; i++) {
|
for (uint8_t i = 0; i < numofblocks; i++) {
|
||||||
|
|
||||||
if (ReadSTBlock(i, mem + ( i * 4)) == false) {
|
if (ReadSTBlock(i, mem + (i * 4)) == false) {
|
||||||
isOK = PM3_ETIMEOUT;
|
isOK = PM3_ETIMEOUT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// System area block (0xFF)
|
// System area block (0xFF)
|
||||||
if (ReadSTBlock(0xFF, mem + (numofblocks * 4)) == false)
|
if (ReadSTBlock(0xFF, mem + (numofblocks * 4)) == false)
|
||||||
isOK = PM3_ETIMEOUT;
|
isOK = PM3_ETIMEOUT;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
|
||||||
|
@ -1535,7 +1535,7 @@ void SniffIso14443b(void) {
|
||||||
bool reader_is_active = false;
|
bool reader_is_active = false;
|
||||||
bool expect_tag_answer = false;
|
bool expect_tag_answer = false;
|
||||||
int dma_start_time = 0;
|
int dma_start_time = 0;
|
||||||
|
|
||||||
// Count of samples received so far, so that we can include timing
|
// Count of samples received so far, so that we can include timing
|
||||||
int samples = 0;
|
int samples = 0;
|
||||||
|
|
||||||
|
@ -1544,7 +1544,7 @@ void SniffIso14443b(void) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
||||||
volatile int behind_by = ((uint16_t *)AT91C_BASE_PDC_SSC->PDC_RPR - upTo) & (DMA_BUFFER_SIZE - 1);
|
volatile int behind_by = ((uint16_t *)AT91C_BASE_PDC_SSC->PDC_RPR - upTo) & (DMA_BUFFER_SIZE - 1);
|
||||||
if (behind_by < 1) continue;
|
if (behind_by < 1) continue;
|
||||||
|
|
||||||
samples++;
|
samples++;
|
||||||
if (samples == 1) {
|
if (samples == 1) {
|
||||||
|
@ -1554,7 +1554,7 @@ void SniffIso14443b(void) {
|
||||||
|
|
||||||
volatile int8_t ci = *upTo >> 8;
|
volatile int8_t ci = *upTo >> 8;
|
||||||
volatile int8_t cq = *upTo;
|
volatile int8_t cq = *upTo;
|
||||||
upTo++;
|
upTo++;
|
||||||
|
|
||||||
// we have read all of the DMA buffer content.
|
// we have read all of the DMA buffer content.
|
||||||
if (upTo >= dma->buf + DMA_BUFFER_SIZE) {
|
if (upTo >= dma->buf + DMA_BUFFER_SIZE) {
|
||||||
|
@ -1575,7 +1575,7 @@ void SniffIso14443b(void) {
|
||||||
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dma->buf;
|
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dma->buf;
|
||||||
AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
|
AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
if (BUTTON_PRESS()) {
|
if (BUTTON_PRESS()) {
|
||||||
DbpString("Sniff stopped");
|
DbpString("Sniff stopped");
|
||||||
|
@ -1600,7 +1600,7 @@ void SniffIso14443b(void) {
|
||||||
Uart14bReset();
|
Uart14bReset();
|
||||||
Demod14bReset();
|
Demod14bReset();
|
||||||
reader_is_active = false;
|
reader_is_active = false;
|
||||||
expect_tag_answer = true;
|
expect_tag_answer = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Handle14443bSampleFromReader(cq & 0x01)) {
|
if (Handle14443bSampleFromReader(cq & 0x01)) {
|
||||||
|
@ -1619,20 +1619,20 @@ void SniffIso14443b(void) {
|
||||||
reader_is_active = false;
|
reader_is_active = false;
|
||||||
expect_tag_answer = true;
|
expect_tag_answer = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
reader_is_active = (Uart.state > STATE_14B_GOT_FALLING_EDGE_OF_SOF);
|
reader_is_active = (Uart.state > STATE_14B_GOT_FALLING_EDGE_OF_SOF);
|
||||||
}
|
}
|
||||||
|
|
||||||
// no need to try decoding tag data if the reader is sending - and we cannot afford the time
|
// no need to try decoding tag data if the reader is sending - and we cannot afford the time
|
||||||
if (reader_is_active == false && expect_tag_answer) {
|
if (reader_is_active == false && expect_tag_answer) {
|
||||||
|
|
||||||
if (Handle14443bSamplesFromTag((ci >> 1), (cq >> 1))) {
|
if (Handle14443bSamplesFromTag((ci >> 1), (cq >> 1))) {
|
||||||
|
|
||||||
uint32_t eof_time = dma_start_time + (samples * 16); // - DELAY_TAG_TO_ARM_SNIFF; // end of EOF
|
uint32_t eof_time = dma_start_time + (samples * 16); // - DELAY_TAG_TO_ARM_SNIFF; // end of EOF
|
||||||
uint32_t sof_time = eof_time
|
uint32_t sof_time = eof_time
|
||||||
- Demod.len * 8 * 8 * 16 // time for byte transfers
|
- Demod.len * 8 * 8 * 16 // time for byte transfers
|
||||||
- (32 * 16) // time for SOF transfer
|
- (32 * 16) // time for SOF transfer
|
||||||
- 0; // time for EOF transfer
|
- 0; // time for EOF transfer
|
||||||
|
|
||||||
LogTrace(Demod.output, Demod.len, (sof_time * 4), (eof_time * 4), NULL, false);
|
LogTrace(Demod.output, Demod.len, (sof_time * 4), (eof_time * 4), NULL, false);
|
||||||
// And ready to receive another response.
|
// And ready to receive another response.
|
||||||
|
@ -1657,7 +1657,7 @@ void SniffIso14443b(void) {
|
||||||
Dbprintf(" DecodeTag posCount.....%d", Demod.posCount);
|
Dbprintf(" DecodeTag posCount.....%d", Demod.posCount);
|
||||||
Dbprintf(" DecodeReader State.....%d", Uart.state);
|
Dbprintf(" DecodeReader State.....%d", Uart.state);
|
||||||
Dbprintf(" DecodeReader byteCnt...%d", Uart.byteCnt);
|
Dbprintf(" DecodeReader byteCnt...%d", Uart.byteCnt);
|
||||||
Dbprintf(" DecodeReader posCount..%d", Uart.posCnt);
|
Dbprintf(" DecodeReader posCount..%d", Uart.posCnt);
|
||||||
Dbprintf(" Trace length..........." _YELLOW_("%d"), BigBuf_get_traceLen());
|
Dbprintf(" Trace length..........." _YELLOW_("%d"), BigBuf_get_traceLen());
|
||||||
DbpString("");
|
DbpString("");
|
||||||
}
|
}
|
||||||
|
@ -1703,17 +1703,17 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) {
|
||||||
int status;
|
int status;
|
||||||
uint32_t sendlen = sizeof(iso14b_card_select_t);
|
uint32_t sendlen = sizeof(iso14b_card_select_t);
|
||||||
iso14b_card_select_t card;
|
iso14b_card_select_t card;
|
||||||
|
|
||||||
if ((param & ISO14B_SELECT_STD) == ISO14B_SELECT_STD) {
|
if ((param & ISO14B_SELECT_STD) == ISO14B_SELECT_STD) {
|
||||||
status = iso14443b_select_card(&card);
|
status = iso14443b_select_card(&card);
|
||||||
reply_mix(CMD_HF_ISO14443B_COMMAND, status, sendlen, 0, (uint8_t*)&card, sendlen);
|
reply_mix(CMD_HF_ISO14443B_COMMAND, status, sendlen, 0, (uint8_t *)&card, sendlen);
|
||||||
// 0: OK -1: attrib fail, -2:crc fail,
|
// 0: OK -1: attrib fail, -2:crc fail,
|
||||||
if (status != 0) goto out;
|
if (status != 0) goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((param & ISO14B_SELECT_SR) == ISO14B_SELECT_SR) {
|
if ((param & ISO14B_SELECT_SR) == ISO14B_SELECT_SR) {
|
||||||
status = iso14443b_select_srx_card(&card);
|
status = iso14443b_select_srx_card(&card);
|
||||||
reply_mix(CMD_HF_ISO14443B_COMMAND, status, sendlen, 0, (uint8_t*)&card, sendlen);
|
reply_mix(CMD_HF_ISO14443B_COMMAND, status, sendlen, 0, (uint8_t *)&card, sendlen);
|
||||||
// 0: OK 2: demod fail, 3:crc fail,
|
// 0: OK 2: demod fail, 3:crc fail,
|
||||||
if (status > 0) goto out;
|
if (status > 0) goto out;
|
||||||
}
|
}
|
||||||
|
@ -1730,10 +1730,10 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) {
|
||||||
len += 2;
|
len += 2;
|
||||||
}
|
}
|
||||||
uint8_t buf[100] = {0};
|
uint8_t buf[100] = {0};
|
||||||
|
|
||||||
uint32_t start_time = 0;
|
uint32_t start_time = 0;
|
||||||
uint32_t eof_time = 0;
|
uint32_t eof_time = 0;
|
||||||
CodeAndTransmit14443bAsReader(cmd, len, &start_time, &eof_time);
|
CodeAndTransmit14443bAsReader(cmd, len, &start_time, &eof_time);
|
||||||
|
|
||||||
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
|
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
|
||||||
status = Get14443bAnswerFromTag(buf, sizeof(buf), 5 * ISO14443B_READER_TIMEOUT, &eof_time); // raw
|
status = Get14443bAnswerFromTag(buf, sizeof(buf), 5 * ISO14443B_READER_TIMEOUT, &eof_time); // raw
|
||||||
|
|
|
@ -84,7 +84,7 @@
|
||||||
#define ISO15693_READER_TIMEOUT 330 // 330/212kHz = 1558us
|
#define ISO15693_READER_TIMEOUT 330 // 330/212kHz = 1558us
|
||||||
#define ISO15693_READER_TIMEOUT_WRITE 4700 // 4700/212kHz = 22ms, nominal 20ms
|
#define ISO15693_READER_TIMEOUT_WRITE 4700 // 4700/212kHz = 22ms, nominal 20ms
|
||||||
|
|
||||||
// iceman: This defines below exists in the header file, just here for my easy reading
|
// iceman: This defines below exists in the header file, just here for my easy reading
|
||||||
// Delays in SSP_CLK ticks.
|
// Delays in SSP_CLK ticks.
|
||||||
// SSP_CLK runs at 13,56MHz / 32 = 423.75kHz when simulating a tag
|
// SSP_CLK runs at 13,56MHz / 32 = 423.75kHz when simulating a tag
|
||||||
//#define DELAY_ISO15693_VCD_TO_VICC_SIM 132 // 132/423.75kHz = 311.5us from end of command EOF to start of tag response
|
//#define DELAY_ISO15693_VCD_TO_VICC_SIM 132 // 132/423.75kHz = 311.5us from end of command EOF to start of tag response
|
||||||
|
@ -700,7 +700,7 @@ int GetIso15693AnswerFromTag(uint8_t *response, uint16_t max_len, uint16_t timeo
|
||||||
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dma->buf;
|
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dma->buf;
|
||||||
AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
|
AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
if (BUTTON_PRESS()) {
|
if (BUTTON_PRESS()) {
|
||||||
DbpString("stopped");
|
DbpString("stopped");
|
||||||
|
@ -725,7 +725,7 @@ int GetIso15693AnswerFromTag(uint8_t *response, uint16_t max_len, uint16_t timeo
|
||||||
|
|
||||||
// timeout
|
// timeout
|
||||||
if (samples > timeout && dt->state < STATE_TAG_RECEIVING_DATA) {
|
if (samples > timeout && dt->state < STATE_TAG_RECEIVING_DATA) {
|
||||||
ret = -3;
|
ret = -3;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1715,7 +1715,6 @@ void SimTagIso15693(uint8_t *uid) {
|
||||||
uint32_t reader_eof_time = 0;
|
uint32_t reader_eof_time = 0;
|
||||||
int cmd_len = GetIso15693CommandFromReader(cmd, sizeof(cmd), &reader_eof_time);
|
int cmd_len = GetIso15693CommandFromReader(cmd, sizeof(cmd), &reader_eof_time);
|
||||||
if (cmd_len < 0) {
|
if (cmd_len < 0) {
|
||||||
Dbprintf("button pressed, exiting");
|
|
||||||
button_pressed = true;
|
button_pressed = true;
|
||||||
exit_loop = true;
|
exit_loop = true;
|
||||||
break;
|
break;
|
||||||
|
@ -1736,7 +1735,7 @@ void SimTagIso15693(uint8_t *uid) {
|
||||||
|
|
||||||
if (button_pressed)
|
if (button_pressed)
|
||||||
DbpString("button pressed");
|
DbpString("button pressed");
|
||||||
|
|
||||||
reply_ng(CMD_HF_ISO15693_SIMULATE, PM3_SUCCESS, NULL, 0);
|
reply_ng(CMD_HF_ISO15693_SIMULATE, PM3_SUCCESS, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1881,7 +1880,7 @@ SLIx functions from official master forks.
|
||||||
void LockPassSlixIso15693(uint32_t pass_id, uint32_t password) {
|
void LockPassSlixIso15693(uint32_t pass_id, uint32_t password) {
|
||||||
|
|
||||||
LED_A_ON();
|
LED_A_ON();
|
||||||
|
|
||||||
uint8_t cmd_inventory[] = {ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_INVENTORY | ISO15693_REQINV_SLOT1, 0x01, 0x00, 0x00, 0x00 };
|
uint8_t cmd_inventory[] = {ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_INVENTORY | ISO15693_REQINV_SLOT1, 0x01, 0x00, 0x00, 0x00 };
|
||||||
uint8_t cmd_get_rnd[] = {ISO15693_REQ_DATARATE_HIGH, 0xB2, 0x04, 0x00, 0x00 };
|
uint8_t cmd_get_rnd[] = {ISO15693_REQ_DATARATE_HIGH, 0xB2, 0x04, 0x00, 0x00 };
|
||||||
uint8_t cmd_set_pass[] = {ISO15693_REQ_DATARATE_HIGH, 0xB3, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
uint8_t cmd_set_pass[] = {ISO15693_REQ_DATARATE_HIGH, 0xB3, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
|
@ -1893,7 +1892,7 @@ void LockPassSlixIso15693(uint32_t pass_id, uint32_t password) {
|
||||||
uint32_t start_time = 0;
|
uint32_t start_time = 0;
|
||||||
bool done = false;
|
bool done = false;
|
||||||
|
|
||||||
// setup 'get random number' command
|
// setup 'get random number' command
|
||||||
crc = Iso15693Crc(cmd_get_rnd, 3);
|
crc = Iso15693Crc(cmd_get_rnd, 3);
|
||||||
cmd_get_rnd[3] = crc & 0xff;
|
cmd_get_rnd[3] = crc & 0xff;
|
||||||
cmd_get_rnd[4] = crc >> 8;
|
cmd_get_rnd[4] = crc >> 8;
|
||||||
|
@ -1901,7 +1900,7 @@ void LockPassSlixIso15693(uint32_t pass_id, uint32_t password) {
|
||||||
Dbprintf("LockPass: Press button lock password, long-press to terminate.");
|
Dbprintf("LockPass: Press button lock password, long-press to terminate.");
|
||||||
|
|
||||||
while (!done) {
|
while (!done) {
|
||||||
|
|
||||||
LED_D_ON();
|
LED_D_ON();
|
||||||
switch(BUTTON_HELD(1000)) {
|
switch(BUTTON_HELD(1000)) {
|
||||||
case BUTTON_SINGLE_CLICK:
|
case BUTTON_SINGLE_CLICK:
|
||||||
|
@ -2033,7 +2032,7 @@ void SetTag15693Uid(uint8_t *uid) {
|
||||||
SendDataTag(cmd[i], sizeof(cmd[i]), i == 0 ? true : false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, &eof_time);
|
SendDataTag(cmd[i], sizeof(cmd[i]), i == 0 ? true : false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, &eof_time);
|
||||||
start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
|
start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
|
||||||
}
|
}
|
||||||
|
|
||||||
reply_ng(CMD_HF_ISO15693_CSETUID, PM3_SUCCESS, NULL, 0);
|
reply_ng(CMD_HF_ISO15693_CSETUID, PM3_SUCCESS, NULL, 0);
|
||||||
switch_off();
|
switch_off();
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,11 +64,11 @@ static uint32_t last_frame_end; /* ts of last bit of previews rx or tx frame */
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// I/O interface abstraction (FPGA -> ARM)
|
// I/O interface abstraction (FPGA -> ARM)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
static uint8_t rx_byte_from_fpga(void) {
|
static uint16_t rx_frame_from_fpga(void) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
// wait for byte be become available in rx holding register
|
// wait for frame be become available in rx holding register
|
||||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||||
return AT91C_BASE_SSC->SSC_RHR;
|
return AT91C_BASE_SSC->SSC_RHR;
|
||||||
}
|
}
|
||||||
|
@ -76,48 +76,53 @@ static uint8_t rx_byte_from_fpga(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Demodulation
|
// Demodulation (Reader)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
// Returns am aproximated power measurement
|
// Returns a demedulated bit
|
||||||
//
|
//
|
||||||
// The FPGA running on the xcorrelation kernel samples the subcarrier at ~3 MHz.
|
// The FPGA running xcorrelation samples the subcarrier at ~13.56 MHz. The mode
|
||||||
// The kernel was initialy designed to receive BSPK/2-PSK. Hance, it reports an
|
// was initialy designed to receive BSPK/2-PSK. Hance, it reports an I/Q pair
|
||||||
// I/Q pair every 18.9us (8 bits i and 8 bits q).
|
// every 4.7us (8 bits i and 8 bits q).
|
||||||
//
|
//
|
||||||
// The subcarrier amplitude can be calculated using Pythagoras sqrt(i^2 + q^2).
|
// The subcarrier amplitude can be calculated using Pythagoras sqrt(i^2 + q^2).
|
||||||
// To reduce CPU time the amplitude is approximated by using linear functions:
|
// To reduce CPU time the amplitude is approximated by using linear functions:
|
||||||
// am = MAX(ABS(i),ABS(q)) + 1/2*MIN(ABS(i),ABSq))
|
// am = MAX(ABS(i),ABS(q)) + 1/2*MIN(ABS(i),ABSq))
|
||||||
//
|
//
|
||||||
// Note: The SSC receiver is never synchronized the calculation may be performed
|
// The bit time is 99.1us (21 I/Q pairs). The receiver skips the first 5 samples
|
||||||
// on a i/q pair from two subsequent correlations, but does not matter.
|
// and averages the next (most stable) 8 samples. The final 8 samples are dropped
|
||||||
// Note: inlining this function would fail with -Os
|
// also.
|
||||||
static int32_t sample_power(void) {
|
|
||||||
int32_t q = (int8_t)rx_byte_from_fpga();
|
|
||||||
q = ABS(q);
|
|
||||||
int32_t i = (int8_t)rx_byte_from_fpga();
|
|
||||||
i = ABS(i);
|
|
||||||
|
|
||||||
return MAX(i, q) + (MIN(i, q) >> 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a demedulated bit
|
|
||||||
//
|
//
|
||||||
// An aproximated power measurement is available every 18.9us. The bit time
|
// The demodulated should be alligned to the bit period by the caller. This is
|
||||||
// is 100us. The code samples 5 times and uses the last (most stable) sample.
|
// done in rx_bit and rx_ack.
|
||||||
//
|
//
|
||||||
// Note: The demodulator would be drifting (18.9us * 5 != 100us), rx_frame
|
// Note: The demodulator would be drifting (18.9us * 5 != 100us), rx_frame
|
||||||
// has a delay loop that aligns rx_bit calls to the TAG tx timeslots.
|
// has a delay loop that aligns rx_bit calls to the TAG tx timeslots.
|
||||||
|
//
|
||||||
// Note: inlining this function would fail with -Os
|
// Note: inlining this function would fail with -Os
|
||||||
static bool rx_bit(void) {
|
static bool rx_bit(void) {
|
||||||
int32_t power;
|
int32_t sum_cq = 0;
|
||||||
|
int32_t sum_ci = 0;
|
||||||
|
|
||||||
|
// skip first 5 I/Q pairs
|
||||||
for (size_t i = 0; i < 5; ++i) {
|
for (size_t i = 0; i < 5; ++i) {
|
||||||
power = sample_power();
|
(void)rx_frame_from_fpga();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (power > INPUT_THRESHOLD);
|
// sample next 8 I/Q pairs
|
||||||
|
for (uint8_t i = 0; i < 8; ++i) {
|
||||||
|
uint16_t iq = rx_frame_from_fpga();
|
||||||
|
int8_t ci = (int8_t)(iq >> 8);
|
||||||
|
int8_t cq = (int8_t)(iq & 0xff);
|
||||||
|
sum_ci += ci;
|
||||||
|
sum_cq += cq;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate power
|
||||||
|
int32_t power = (MAX(ABS(sum_ci), ABS(sum_cq)) + (MIN(ABS(sum_ci), ABS(sum_cq)) >> 1));
|
||||||
|
|
||||||
|
// compare average (power / 8) to threshold
|
||||||
|
return ((power >> 3) > INPUT_THRESHOLD);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -131,18 +136,18 @@ static bool rx_bit(void) {
|
||||||
|
|
||||||
static void tx_bit(bool bit) {
|
static void tx_bit(bool bit) {
|
||||||
// insert pause
|
// insert pause
|
||||||
LOW(GPIO_SSC_DOUT);
|
HIGH(GPIO_SSC_DOUT);
|
||||||
last_frame_end += RWD_TIME_PAUSE;
|
last_frame_end += RWD_TIME_PAUSE;
|
||||||
while (GET_TICKS < last_frame_end) { };
|
while (GET_TICKS < last_frame_end) { };
|
||||||
HIGH(GPIO_SSC_DOUT);
|
|
||||||
|
|
||||||
// return to high, wait for bit periode to end
|
// return to carrier on, wait for bit periode to end
|
||||||
|
LOW(GPIO_SSC_DOUT);
|
||||||
last_frame_end += (bit ? RWD_TIME_1 : RWD_TIME_0) - RWD_TIME_PAUSE;
|
last_frame_end += (bit ? RWD_TIME_1 : RWD_TIME_0) - RWD_TIME_PAUSE;
|
||||||
while (GET_TICKS < last_frame_end) { };
|
while (GET_TICKS < last_frame_end) { };
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Frame Handling
|
// Frame Handling (Reader)
|
||||||
//
|
//
|
||||||
// The LEGIC RF protocol from card to reader does not include explicit frame
|
// The LEGIC RF protocol from card to reader does not include explicit frame
|
||||||
// start/stop information or length information. The reader must know beforehand
|
// start/stop information or length information. The reader must know beforehand
|
||||||
|
@ -169,10 +174,10 @@ static void tx_frame(uint32_t frame, uint8_t len) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// add pause to mark end of the frame
|
// add pause to mark end of the frame
|
||||||
LOW(GPIO_SSC_DOUT);
|
HIGH(GPIO_SSC_DOUT);
|
||||||
last_frame_end += RWD_TIME_PAUSE;
|
last_frame_end += RWD_TIME_PAUSE;
|
||||||
while (GET_TICKS < last_frame_end) { };
|
while (GET_TICKS < last_frame_end) { };
|
||||||
HIGH(GPIO_SSC_DOUT);
|
LOW(GPIO_SSC_DOUT);
|
||||||
|
|
||||||
// log
|
// log
|
||||||
uint8_t cmdbytes[] = {len, BYTEx(frame, 0), BYTEx(frame, 1), BYTEx(frame, 2)};
|
uint8_t cmdbytes[] = {len, BYTEx(frame, 0), BYTEx(frame, 1), BYTEx(frame, 2)};
|
||||||
|
@ -267,12 +272,12 @@ static int init_card(uint8_t cardtype, legic_card_select_t *p_card) {
|
||||||
p_card->cmdsize = 0;
|
p_card->cmdsize = 0;
|
||||||
p_card->addrsize = 0;
|
p_card->addrsize = 0;
|
||||||
p_card->cardsize = 0;
|
p_card->cardsize = 0;
|
||||||
return 2;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_reader(bool clear_mem) {
|
static void init_reader(void) {
|
||||||
// configure FPGA
|
// configure FPGA
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_SUBCARRIER_212_KHZ | FPGA_HF_READER_MODE_RECEIVE_IQ);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_SUBCARRIER_212_KHZ | FPGA_HF_READER_MODE_RECEIVE_IQ);
|
||||||
|
@ -285,7 +290,7 @@ static void init_reader(bool clear_mem) {
|
||||||
// re-claim GPIO_SSC_DOUT as GPIO and enable output
|
// re-claim GPIO_SSC_DOUT as GPIO and enable output
|
||||||
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
|
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
|
||||||
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
|
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
|
||||||
HIGH(GPIO_SSC_DOUT);
|
LOW(GPIO_SSC_DOUT);
|
||||||
|
|
||||||
// reserve a cardmem, meaning we can use the tracelog function in bigbuff easier.
|
// reserve a cardmem, meaning we can use the tracelog function in bigbuff easier.
|
||||||
legic_mem = BigBuf_get_EM_addr();
|
legic_mem = BigBuf_get_EM_addr();
|
||||||
|
@ -406,11 +411,11 @@ legic_card_select_t *getLegicCardInfo(void) {
|
||||||
|
|
||||||
void LegicRfInfo(void) {
|
void LegicRfInfo(void) {
|
||||||
// configure ARM and FPGA
|
// configure ARM and FPGA
|
||||||
init_reader(false);
|
init_reader();
|
||||||
|
|
||||||
// establish shared secret and detect card type
|
// establish shared secret and detect card type
|
||||||
uint8_t card_type = setup_phase(0x01);
|
uint8_t card_type = setup_phase(0x01);
|
||||||
if (init_card(card_type, &card) != 0) {
|
if (init_card(card_type, &card) != PM3_SUCCESS) {
|
||||||
reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
|
reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
|
||||||
goto OUT;
|
goto OUT;
|
||||||
}
|
}
|
||||||
|
@ -446,11 +451,11 @@ int LegicRfReaderEx(uint16_t offset, uint16_t len, uint8_t iv) {
|
||||||
int res = PM3_SUCCESS;
|
int res = PM3_SUCCESS;
|
||||||
|
|
||||||
// configure ARM and FPGA
|
// configure ARM and FPGA
|
||||||
init_reader(false);
|
init_reader();
|
||||||
|
|
||||||
// establish shared secret and detect card type
|
// establish shared secret and detect card type
|
||||||
uint8_t card_type = setup_phase(iv);
|
uint8_t card_type = setup_phase(iv);
|
||||||
if (init_card(card_type, &card) != 0) {
|
if (init_card(card_type, &card) != PM3_SUCCESS) {
|
||||||
res = PM3_ESOFT;
|
res = PM3_ESOFT;
|
||||||
goto OUT;
|
goto OUT;
|
||||||
}
|
}
|
||||||
|
@ -481,11 +486,11 @@ OUT:
|
||||||
|
|
||||||
void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) {
|
void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) {
|
||||||
// configure ARM and FPGA
|
// configure ARM and FPGA
|
||||||
init_reader(false);
|
init_reader();
|
||||||
|
|
||||||
// establish shared secret and detect card type
|
// establish shared secret and detect card type
|
||||||
uint8_t card_type = setup_phase(iv);
|
uint8_t card_type = setup_phase(iv);
|
||||||
if (init_card(card_type, &card) != 0) {
|
if (init_card(card_type, &card) != PM3_SUCCESS) {
|
||||||
reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
|
reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
|
||||||
goto OUT;
|
goto OUT;
|
||||||
}
|
}
|
||||||
|
@ -518,7 +523,7 @@ OUT:
|
||||||
|
|
||||||
void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data) {
|
void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data) {
|
||||||
// configure ARM and FPGA
|
// configure ARM and FPGA
|
||||||
init_reader(false);
|
init_reader();
|
||||||
|
|
||||||
// uid is not writeable
|
// uid is not writeable
|
||||||
if (offset <= WRITE_LOWERLIMIT) {
|
if (offset <= WRITE_LOWERLIMIT) {
|
||||||
|
@ -528,7 +533,7 @@ void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data) {
|
||||||
|
|
||||||
// establish shared secret and detect card type
|
// establish shared secret and detect card type
|
||||||
uint8_t card_type = setup_phase(iv);
|
uint8_t card_type = setup_phase(iv);
|
||||||
if (init_card(card_type, &card) != 0) {
|
if (init_card(card_type, &card) != PM3_SUCCESS) {
|
||||||
reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
|
reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
|
||||||
goto OUT;
|
goto OUT;
|
||||||
}
|
}
|
||||||
|
@ -539,8 +544,8 @@ void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// write in reverse order, only then is DCF (decremental field) writable
|
// write in reverse order, only then is DCF (decremental field) writable
|
||||||
while (len-- > 0 && !BUTTON_PRESS()) {
|
while (len-- > 0 && BUTTON_PRESS() == false) {
|
||||||
if (!write_byte(len + offset, data[len], card.addrsize)) {
|
if (write_byte(len + offset, data[len], card.addrsize) == false) {
|
||||||
Dbprintf("operation failed | %02X | %02X | %02X", len + offset, len, data[len]);
|
Dbprintf("operation failed | %02X | %02X | %02X", len + offset, len, data[len]);
|
||||||
reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
|
reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
|
||||||
goto OUT;
|
goto OUT;
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#include "crc.h" /* legic crc-4 */
|
#include "crc.h" /* legic crc-4 */
|
||||||
#include "legic_prng.h" /* legic PRNG impl */
|
#include "legic_prng.h" /* legic PRNG impl */
|
||||||
#include "legic.h" /* legic_card_select_t struct */
|
#include "legic.h" /* legic_card_select_t struct */
|
||||||
|
#include "cmd.h"
|
||||||
#include "proxmark3_arm.h"
|
#include "proxmark3_arm.h"
|
||||||
#include "BigBuf.h"
|
#include "BigBuf.h"
|
||||||
#include "fpgaloader.h"
|
#include "fpgaloader.h"
|
||||||
|
@ -295,9 +295,9 @@ static int32_t init_card(uint8_t cardtype, legic_card_select_t *p_card) {
|
||||||
p_card->cmdsize = 0;
|
p_card->cmdsize = 0;
|
||||||
p_card->addrsize = 0;
|
p_card->addrsize = 0;
|
||||||
p_card->cardsize = 0;
|
p_card->cardsize = 0;
|
||||||
return 2;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_tag(void) {
|
static void init_tag(void) {
|
||||||
|
@ -455,23 +455,37 @@ static int32_t connected_phase(legic_card_select_t *p_card) {
|
||||||
// Only this function is public / called from appmain.c
|
// Only this function is public / called from appmain.c
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void LegicRfSimulate(uint8_t cardtype) {
|
void LegicRfSimulate(uint8_t tagtype, bool send_reply) {
|
||||||
// configure ARM and FPGA
|
// configure ARM and FPGA
|
||||||
init_tag();
|
init_tag();
|
||||||
|
|
||||||
|
int res = PM3_SUCCESS;
|
||||||
// verify command line input
|
// verify command line input
|
||||||
if (init_card(cardtype, &card) != 0) {
|
if (init_card(tagtype, &card) != PM3_SUCCESS) {
|
||||||
DbpString("[!] Unknown tagtype.");
|
DbpString("Unknown tagtype to simulate");
|
||||||
|
res = PM3_ESOFT;
|
||||||
goto OUT;
|
goto OUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t counter = 0;
|
||||||
LED_A_ON();
|
LED_A_ON();
|
||||||
DbpString("[=] Starting Legic emulator, press " _YELLOW_("button") " to end");
|
|
||||||
while (!BUTTON_PRESS() && !data_available()) {
|
Dbprintf("Legic Prime, simulating uid: %02X%02X%02X%02X", legic_mem[0], legic_mem[1], legic_mem[2], legic_mem[3]);
|
||||||
|
|
||||||
|
while (BUTTON_PRESS() == false) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
|
if (counter >= 2000) {
|
||||||
|
if (data_available()) {
|
||||||
|
res = PM3_EOPABORTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
counter = 0;
|
||||||
|
}
|
||||||
|
counter++;
|
||||||
|
|
||||||
// wait for carrier, restart after timeout
|
// wait for carrier, restart after timeout
|
||||||
if (!wait_for(RWD_PULSE, GetCountSspClk() + TAG_BIT_PERIOD)) {
|
if (wait_for(RWD_PULSE, GetCountSspClk() + TAG_BIT_PERIOD) == false) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -481,13 +495,25 @@ void LegicRfSimulate(uint8_t cardtype) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// conection is established, process commands until one fails
|
// conection is established, process commands until one fails
|
||||||
while (!connected_phase(&card)) {
|
while (connected_phase(&card) == false) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OUT:
|
OUT:
|
||||||
DbpString("[=] Sim stopped");
|
|
||||||
|
if (DBGLEVEL >= DBG_ERROR) {
|
||||||
|
Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", get_tracing(), BigBuf_get_traceLen());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res == PM3_EOPABORTED)
|
||||||
|
DbpString("aborted by user");
|
||||||
|
|
||||||
switch_off();
|
switch_off();
|
||||||
StopTicks();
|
StopTicks();
|
||||||
|
|
||||||
|
if (send_reply)
|
||||||
|
reply_ng(CMD_HF_LEGIC_SIMULATE, res, NULL, 0);
|
||||||
|
|
||||||
|
BigBuf_free_keep_EM();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// (c) 2009 Henryk Plötz <henryk@ploetzli.ch>
|
// (c) 2009 Henryk Plötz <henryk@ploetzli.ch>
|
||||||
// 2018 AntiCat
|
// 2018 AntiCat
|
||||||
//
|
// 2019 Piwi
|
||||||
|
// 2020 Iceman
|
||||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
// 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
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
// the license.
|
// the license.
|
||||||
|
@ -14,6 +15,6 @@
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
void LegicRfSimulate(uint8_t cardtype);
|
void LegicRfSimulate(uint8_t tagtype, bool send_reply);
|
||||||
|
|
||||||
#endif /* __LEGICRFSIM_H */
|
#endif /* __LEGICRFSIM_H */
|
||||||
|
|
|
@ -2041,7 +2041,7 @@ void T55xxReadBlock(uint8_t page, bool pwd_mode, bool brute_mem, uint8_t block,
|
||||||
|
|
||||||
// Acquisition
|
// Acquisition
|
||||||
// Now do the acquisition
|
// Now do the acquisition
|
||||||
DoPartialAcquisition(0, false, samples, 0);
|
DoPartialAcquisition(0, false, samples, 1000);
|
||||||
|
|
||||||
// Turn the field off
|
// Turn the field off
|
||||||
if (brute_mem == false) {
|
if (brute_mem == false) {
|
||||||
|
@ -2084,7 +2084,7 @@ void T55xx_ChkPwds(uint8_t flags) {
|
||||||
baseline_faulty >>= 5;
|
baseline_faulty >>= 5;
|
||||||
|
|
||||||
if (DBGLEVEL >= DBG_DEBUG)
|
if (DBGLEVEL >= DBG_DEBUG)
|
||||||
Dbprintf("Baseline " _YELLOW_("%llu"), baseline_faulty);
|
Dbprintf("Baseline " _YELLOW_("%llu"), baseline_faulty);
|
||||||
|
|
||||||
uint8_t *pwds = BigBuf_get_EM_addr();
|
uint8_t *pwds = BigBuf_get_EM_addr();
|
||||||
uint16_t pwd_count = 0;
|
uint16_t pwd_count = 0;
|
||||||
|
@ -2147,7 +2147,7 @@ void T55xx_ChkPwds(uint8_t flags) {
|
||||||
|
|
||||||
if (DBGLEVEL >= DBG_DEBUG)
|
if (DBGLEVEL >= DBG_DEBUG)
|
||||||
Dbprintf("%08x has distance " _YELLOW_("%llu"), pwd, curr);
|
Dbprintf("%08x has distance " _YELLOW_("%llu"), pwd, curr);
|
||||||
|
|
||||||
if (curr > prev) {
|
if (curr > prev) {
|
||||||
idx = i;
|
idx = i;
|
||||||
prev = curr;
|
prev = curr;
|
||||||
|
@ -2165,7 +2165,7 @@ OUT:
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
reply_ng(CMD_LF_T55XX_CHK_PWDS, PM3_SUCCESS, (uint8_t*)&payload, sizeof(payload));
|
reply_ng(CMD_LF_T55XX_CHK_PWDS, PM3_SUCCESS, (uint8_t *)&payload, sizeof(payload));
|
||||||
BigBuf_free();
|
BigBuf_free();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2492,36 +2492,37 @@ static void SendForward(uint8_t fwd_bit_count) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void EM4xLogin(uint32_t pwd) {
|
static void EM4xLogin(uint32_t pwd) {
|
||||||
uint8_t len;
|
|
||||||
forward_ptr = forwardLink_data;
|
forward_ptr = forwardLink_data;
|
||||||
len = Prepare_Cmd(FWD_CMD_LOGIN);
|
uint8_t len = Prepare_Cmd(FWD_CMD_LOGIN);
|
||||||
len += Prepare_Data(pwd & 0xFFFF, pwd >> 16);
|
len += Prepare_Data(pwd & 0xFFFF, pwd >> 16);
|
||||||
SendForward(len);
|
SendForward(len);
|
||||||
//WaitUS(20); // no wait for login command.
|
//WaitUS(20); // no wait for login command.
|
||||||
// should receive
|
// should receive
|
||||||
// 0000 1010 ok.
|
// 0000 1010 ok
|
||||||
// 0000 0001 fail
|
// 0000 0001 fail
|
||||||
}
|
}
|
||||||
|
|
||||||
void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) {
|
void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) {
|
||||||
|
|
||||||
LED_A_ON();
|
StartTicks();
|
||||||
uint8_t len;
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
WaitMS(20);
|
||||||
|
|
||||||
//clear buffer now so it does not interfere with timing later
|
LED_A_ON();
|
||||||
|
|
||||||
|
// clear buffer now so it does not interfere with timing later
|
||||||
BigBuf_Clear_ext(false);
|
BigBuf_Clear_ext(false);
|
||||||
|
|
||||||
StartTicks();
|
|
||||||
/* should we read answer from Logincommand?
|
/* should we read answer from Logincommand?
|
||||||
*
|
*
|
||||||
* should receive
|
* should receive
|
||||||
* 0000 1010 ok.
|
* 0000 1010 ok
|
||||||
* 0000 0001 fail
|
* 0000 0001 fail
|
||||||
**/
|
**/
|
||||||
if (usepwd) EM4xLogin(pwd);
|
if (usepwd) EM4xLogin(pwd);
|
||||||
|
|
||||||
forward_ptr = forwardLink_data;
|
forward_ptr = forwardLink_data;
|
||||||
len = Prepare_Cmd(FWD_CMD_READ);
|
uint8_t len = Prepare_Cmd(FWD_CMD_READ);
|
||||||
len += Prepare_Addr(addr);
|
len += Prepare_Addr(addr);
|
||||||
|
|
||||||
SendForward(len);
|
SendForward(len);
|
||||||
|
@ -2530,19 +2531,23 @@ void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) {
|
||||||
|
|
||||||
DoPartialAcquisition(20, false, 6000, 1000);
|
DoPartialAcquisition(20, false, 6000, 1000);
|
||||||
|
|
||||||
|
StopTicks();
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
reply_ng(CMD_LF_EM4X_READWORD, PM3_SUCCESS, NULL, 0);
|
reply_ng(CMD_LF_EM4X_READWORD, PM3_SUCCESS, NULL, 0);
|
||||||
LED_A_OFF();
|
LEDsoff();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd) {
|
void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd) {
|
||||||
|
|
||||||
LED_A_ON();
|
|
||||||
uint8_t len;
|
|
||||||
|
|
||||||
//clear buffer now so it does not interfere with timing later
|
|
||||||
BigBuf_Clear_ext(false);
|
|
||||||
StartTicks();
|
StartTicks();
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
WaitMS(50);
|
||||||
|
|
||||||
|
LED_A_ON();
|
||||||
|
|
||||||
|
// clear buffer now so it does not interfere with timing later
|
||||||
|
BigBuf_Clear_ext(false);
|
||||||
|
|
||||||
/* should we read answer from Logincommand?
|
/* should we read answer from Logincommand?
|
||||||
*
|
*
|
||||||
* should receive
|
* should receive
|
||||||
|
@ -2552,20 +2557,21 @@ void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd) {
|
||||||
if (usepwd) EM4xLogin(pwd);
|
if (usepwd) EM4xLogin(pwd);
|
||||||
|
|
||||||
forward_ptr = forwardLink_data;
|
forward_ptr = forwardLink_data;
|
||||||
len = Prepare_Cmd(FWD_CMD_WRITE);
|
uint8_t len = Prepare_Cmd(FWD_CMD_WRITE);
|
||||||
len += Prepare_Addr(addr);
|
len += Prepare_Addr(addr);
|
||||||
len += Prepare_Data(data & 0xFFFF, data >> 16);
|
len += Prepare_Data(data & 0xFFFF, data >> 16);
|
||||||
|
|
||||||
SendForward(len);
|
SendForward(len);
|
||||||
|
|
||||||
//Wait 20ms for write to complete?
|
// Wait 20ms for write to complete?
|
||||||
WaitMS(7);
|
WaitMS(7);
|
||||||
|
|
||||||
DoPartialAcquisition(20, false, 6000, 1000);
|
DoPartialAcquisition(20, false, 6000, 1000);
|
||||||
|
|
||||||
|
StopTicks();
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
reply_ng(CMD_LF_EM4X_WRITEWORD, PM3_SUCCESS, NULL, 0);
|
reply_ng(CMD_LF_EM4X_WRITEWORD, PM3_SUCCESS, NULL, 0);
|
||||||
LED_A_OFF();
|
LEDsoff();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2612,25 +2618,27 @@ void Cotag(uint32_t arg0) {
|
||||||
|
|
||||||
LED_A_ON();
|
LED_A_ON();
|
||||||
|
|
||||||
LFSetupFPGAForADC(LF_DIVISOR_125, true);
|
LFSetupFPGAForADC(LF_FREQ2DIV(132), true); //132
|
||||||
|
|
||||||
//clear buffer now so it does not interfere with timing later
|
//clear buffer now so it does not interfere with timing later
|
||||||
BigBuf_free();
|
BigBuf_free();
|
||||||
BigBuf_Clear_ext(false);
|
BigBuf_Clear_ext(false);
|
||||||
|
|
||||||
//send COTAG start pulse
|
// send COTAG start pulse
|
||||||
ON(740) OFF(2035)
|
// http://www.proxmark.org/forum/viewtopic.php?id=4455
|
||||||
ON(3330) OFF(2035)
|
/*
|
||||||
ON(740) OFF(2035)
|
ON(740) OFF(2035)
|
||||||
ON(1000)
|
ON(3330) OFF(2035)
|
||||||
|
ON(740) OFF(2035)
|
||||||
|
ON(2000)
|
||||||
/*
|
*/
|
||||||
ON(800) OFF(2200)
|
ON(800) OFF(2200)
|
||||||
ON(3600) OFF(2200)
|
ON(3600) OFF(2200)
|
||||||
ON(800) OFF(2200)
|
ON(800) OFF(2200)
|
||||||
ON(3400)
|
ON(2000) // ON(3400)
|
||||||
*/
|
|
||||||
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_FREQ2DIV(66)); // 66kHz
|
||||||
|
|
||||||
switch (rawsignal) {
|
switch (rawsignal) {
|
||||||
case 0: {
|
case 0: {
|
||||||
doCotagAcquisition();
|
doCotagAcquisition();
|
||||||
|
@ -2658,7 +2666,6 @@ void Cotag(uint32_t arg0) {
|
||||||
// Turn the field off
|
// Turn the field off
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -36,7 +36,7 @@ static BitstreamOut data = {0, 0, 0};
|
||||||
// internal struct to keep track of samples gathered
|
// internal struct to keep track of samples gathered
|
||||||
static sampling_t samples = {0, 0, 0, 0};
|
static sampling_t samples = {0, 0, 0, 0};
|
||||||
|
|
||||||
void printConfig(void) {
|
void printLFConfig(void) {
|
||||||
uint32_t d = config.divisor;
|
uint32_t d = config.divisor;
|
||||||
DbpString(_CYAN_("LF Sampling config"));
|
DbpString(_CYAN_("LF Sampling config"));
|
||||||
Dbprintf(" [q] divisor.............%d ( "_GREEN_("%d.%02d kHz")" )", d, 12000 / (d + 1), ((1200000 + (d + 1) / 2) / (d + 1)) - ((12000 / (d + 1)) * 100));
|
Dbprintf(" [q] divisor.............%d ( "_GREEN_("%d.%02d kHz")" )", d, 12000 / (d + 1), ((1200000 + (d + 1) / 2) / (d + 1)) - ((12000 / (d + 1)) * 100));
|
||||||
|
@ -97,7 +97,7 @@ void setSamplingConfig(sample_config *sc) {
|
||||||
config.samples_to_skip = sc->samples_to_skip;
|
config.samples_to_skip = sc->samples_to_skip;
|
||||||
|
|
||||||
if (sc->verbose)
|
if (sc->verbose)
|
||||||
printConfig();
|
printLFConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
sample_config *getSamplingConfig(void) {
|
sample_config *getSamplingConfig(void) {
|
||||||
|
@ -268,10 +268,10 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in
|
||||||
initSampleBuffer(&sample_size);
|
initSampleBuffer(&sample_size);
|
||||||
|
|
||||||
if (DBGLEVEL >= DBG_DEBUG) {
|
if (DBGLEVEL >= DBG_DEBUG) {
|
||||||
Dbprintf("lf sampling - after init");
|
|
||||||
printSamples();
|
printSamples();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool trigger_hit = false;
|
||||||
uint32_t cancel_counter = 0;
|
uint32_t cancel_counter = 0;
|
||||||
int16_t checked = 0;
|
int16_t checked = 0;
|
||||||
|
|
||||||
|
@ -279,7 +279,7 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in
|
||||||
|
|
||||||
// only every 4000th times, in order to save time when collecting samples.
|
// only every 4000th times, in order to save time when collecting samples.
|
||||||
// interruptible only when logging not yet triggered
|
// interruptible only when logging not yet triggered
|
||||||
if ((checked >= 4000) && (trigger_threshold > 0)) {
|
if ((checked >= 4000) && trigger_hit == false) {
|
||||||
if (data_available()) {
|
if (data_available()) {
|
||||||
checked = -1;
|
checked = -1;
|
||||||
break;
|
break;
|
||||||
|
@ -298,20 +298,22 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in
|
||||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
||||||
volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
|
|
||||||
// Testpoint 8 (TP8) can be used to trigger oscilliscope
|
// Test point 8 (TP8) can be used to trigger oscilloscope
|
||||||
LED_D_OFF();
|
LED_D_OFF();
|
||||||
|
|
||||||
// threshold either high or low values 128 = center 0. if trigger = 178
|
// threshold either high or low values 128 = center 0. if trigger = 178
|
||||||
if ((trigger_threshold > 0) && (sample < (trigger_threshold + 128)) && (sample > (128 - trigger_threshold))) {
|
if (trigger_hit == false) {
|
||||||
if (cancel_after > 0) {
|
if ((trigger_threshold > 0) && (sample < (trigger_threshold + 128)) && (sample > (128 - trigger_threshold))) {
|
||||||
cancel_counter++;
|
if (cancel_after > 0) {
|
||||||
if (cancel_after == cancel_counter)
|
cancel_counter++;
|
||||||
break;
|
if (cancel_after == cancel_counter)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trigger_threshold = 0;
|
trigger_hit = true;
|
||||||
|
|
||||||
if (samples_to_skip > 0) {
|
if (samples_to_skip > 0) {
|
||||||
samples_to_skip--;
|
samples_to_skip--;
|
||||||
|
@ -324,18 +326,19 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checked == -1 && verbose) {
|
|
||||||
Dbprintf("lf sampling aborted");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
|
if (checked == -1) {
|
||||||
|
Dbprintf("lf sampling aborted");
|
||||||
|
} else if (cancel_counter == cancel_after) {
|
||||||
|
Dbprintf("lf sampling cancelled after %u", cancel_counter);
|
||||||
|
}
|
||||||
|
|
||||||
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
|
// Ensure that DC offset removal and noise check is performed for any device-side processing
|
||||||
removeSignalOffset(data.buffer, samples.total_saved);
|
removeSignalOffset(data.buffer, samples.total_saved);
|
||||||
computeSignalProperties(data.buffer, samples.total_saved);
|
computeSignalProperties(data.buffer, samples.total_saved);
|
||||||
|
|
||||||
return data.numbits;
|
return data.numbits;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -356,20 +359,28 @@ uint32_t DoAcquisition_config(bool verbose, uint32_t sample_size) {
|
||||||
, config.trigger_threshold
|
, config.trigger_threshold
|
||||||
, verbose
|
, verbose
|
||||||
, sample_size
|
, sample_size
|
||||||
, 0
|
, 0 // cancel_after
|
||||||
, config.samples_to_skip);
|
, config.samples_to_skip);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t DoPartialAcquisition(int trigger_threshold, bool verbose, uint32_t sample_size, uint32_t cancel_after) {
|
uint32_t DoPartialAcquisition(int trigger_threshold, bool verbose, uint32_t sample_size, uint32_t cancel_after) {
|
||||||
return DoAcquisition(1, 8, 0, trigger_threshold, verbose, sample_size, cancel_after, 0);
|
return DoAcquisition(config.decimation
|
||||||
|
, config.bits_per_sample
|
||||||
|
, config.averaging
|
||||||
|
, trigger_threshold
|
||||||
|
, verbose
|
||||||
|
, sample_size
|
||||||
|
, cancel_after
|
||||||
|
, 0); // samples to skip
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t ReadLF(bool reader_field, bool verbose, uint32_t sample_size) {
|
static uint32_t ReadLF(bool reader_field, bool verbose, uint32_t sample_size) {
|
||||||
if (verbose)
|
if (verbose)
|
||||||
printConfig();
|
printLFConfig();
|
||||||
|
|
||||||
LFSetupFPGAForADC(config.divisor, reader_field);
|
LFSetupFPGAForADC(config.divisor, reader_field);
|
||||||
uint32_t ret = DoAcquisition_config(verbose, sample_size);
|
uint32_t ret = DoAcquisition_config(verbose, sample_size);
|
||||||
|
StopTicks();
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -495,7 +506,7 @@ void doCotagAcquisition(void) {
|
||||||
bool firsthigh = false, firstlow = false;
|
bool firsthigh = false, firstlow = false;
|
||||||
uint16_t i = 0, noise_counter = 0;
|
uint16_t i = 0, noise_counter = 0;
|
||||||
|
|
||||||
while ((i < bufsize) && (noise_counter < COTAG_T1 << 1)) {
|
while ((i < bufsize - 1) && (noise_counter < COTAG_T1 << 1)) {
|
||||||
|
|
||||||
if (BUTTON_PRESS())
|
if (BUTTON_PRESS())
|
||||||
break;
|
break;
|
||||||
|
@ -527,14 +538,13 @@ void doCotagAcquisition(void) {
|
||||||
firstlow = true;
|
firstlow = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (++i < bufsize) {
|
++i;
|
||||||
if (sample > COTAG_ONE_THRESHOLD) {
|
if (sample > COTAG_ONE_THRESHOLD) {
|
||||||
dest[i] = 255;
|
dest[i] = 255;
|
||||||
} else if (sample < COTAG_ZERO_THRESHOLD) {
|
} else if (sample < COTAG_ZERO_THRESHOLD) {
|
||||||
dest[i] = 0;
|
dest[i] = 0;
|
||||||
} else {
|
} else {
|
||||||
dest[i] = dest[i - 1];
|
dest[i] = dest[i - 1];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -548,7 +558,7 @@ uint16_t doCotagAcquisitionManchester(uint8_t *dest, uint16_t destlen) {
|
||||||
|
|
||||||
if (dest == NULL)
|
if (dest == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
dest[0] = 0;
|
dest[0] = 0;
|
||||||
|
|
||||||
bool firsthigh = false, firstlow = false;
|
bool firsthigh = false, firstlow = false;
|
||||||
|
|
|
@ -99,7 +99,7 @@ void setSamplingConfig(sample_config *sc);
|
||||||
|
|
||||||
sample_config *getSamplingConfig(void);
|
sample_config *getSamplingConfig(void);
|
||||||
|
|
||||||
void printConfig(void);
|
void printLFConfig(void);
|
||||||
void printSamples(void);
|
void printSamples(void);
|
||||||
|
|
||||||
#endif // __LFSAMPLING_H
|
#endif // __LFSAMPLING_H
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include "ticks.h"
|
#include "ticks.h"
|
||||||
#include "usb_cdc.h" // usb_poll_validate_length
|
#include "usb_cdc.h" // usb_poll_validate_length
|
||||||
#include "spiffs.h" // spiffs
|
#include "spiffs.h" // spiffs
|
||||||
|
#include "appmain.h" // print_stack_usage
|
||||||
|
|
||||||
#ifndef HARDNESTED_AUTHENTICATION_TIMEOUT
|
#ifndef HARDNESTED_AUTHENTICATION_TIMEOUT
|
||||||
# define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation)
|
# define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation)
|
||||||
|
@ -369,7 +370,7 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)
|
||||||
|
|
||||||
countblocks *= 4;
|
countblocks *= 4;
|
||||||
|
|
||||||
reply_mix(CMD_ACK, 1, countblocks, BigBuf_max_traceLen(), 0, 0);
|
reply_mix(CMD_ACK, 1, countblocks, dataout - BigBuf_get_addr(), 0, 0);
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
BigBuf_free();
|
BigBuf_free();
|
||||||
|
@ -443,47 +444,6 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
||||||
set_tracing(false);
|
set_tracing(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* // Command not needed but left for future testing
|
|
||||||
void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain)
|
|
||||||
{
|
|
||||||
uint8_t blockNo = arg0;
|
|
||||||
uint8_t blockdata[16] = {0x00};
|
|
||||||
|
|
||||||
memcpy(blockdata, datain, 16);
|
|
||||||
|
|
||||||
uint8_t uid[10] = {0x00};
|
|
||||||
|
|
||||||
LED_A_ON(); LED_B_OFF(); LED_C_OFF();
|
|
||||||
|
|
||||||
clear_trace();
|
|
||||||
set_tracing(true);
|
|
||||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
|
||||||
|
|
||||||
if(!iso14443a_select_card(uid, NULL, NULL, true, 0, true)) {
|
|
||||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card");
|
|
||||||
OnError(0);
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
if(mifare_ultra_writeblock_compat(blockNo, blockdata)) {
|
|
||||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Write block error");
|
|
||||||
OnError(0);
|
|
||||||
return; };
|
|
||||||
|
|
||||||
if(mifare_ultra_halt()) {
|
|
||||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Halt error");
|
|
||||||
OnError(0);
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
|
|
||||||
|
|
||||||
reply_mix(CMD_ACK,1,0,0,0,0);
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
|
||||||
LEDsoff();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Arg0 : Block to write to.
|
// Arg0 : Block to write to.
|
||||||
// Arg1 : 0 = use no authentication.
|
// Arg1 : 0 = use no authentication.
|
||||||
// 1 = use 0x1A authentication.
|
// 1 = use 0x1A authentication.
|
||||||
|
@ -553,6 +513,75 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
||||||
set_tracing(false);
|
set_tracing(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Arg0 : Block to write to.
|
||||||
|
// Arg1 : 0 = use no authentication.
|
||||||
|
// 1 = use 0x1A authentication.
|
||||||
|
// 2 = use 0x1B authentication.
|
||||||
|
// datain : 16 first bytes is data to be written.
|
||||||
|
// : 4/16 next bytes is authentication key.
|
||||||
|
void MifareUWriteBlockCompat(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
||||||
|
uint8_t blockNo = arg0;
|
||||||
|
bool useKey = (arg1 == 1); //UL_C
|
||||||
|
bool usePwd = (arg1 == 2); //UL_EV1/NTAG
|
||||||
|
uint8_t blockdata[16] = {0x00};
|
||||||
|
|
||||||
|
memcpy(blockdata, datain, 16);
|
||||||
|
|
||||||
|
LEDsoff();
|
||||||
|
LED_A_ON();
|
||||||
|
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||||
|
|
||||||
|
clear_trace();
|
||||||
|
set_tracing(true);
|
||||||
|
|
||||||
|
if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) {
|
||||||
|
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card");
|
||||||
|
OnError(0);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
// UL-C authentication
|
||||||
|
if (useKey) {
|
||||||
|
uint8_t key[16] = {0x00};
|
||||||
|
memcpy(key, datain + 16, sizeof(key));
|
||||||
|
|
||||||
|
if (!mifare_ultra_auth(key)) {
|
||||||
|
OnError(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UL-EV1 / NTAG authentication
|
||||||
|
if (usePwd) {
|
||||||
|
uint8_t pwd[4] = {0x00};
|
||||||
|
memcpy(pwd, datain + 16, 4);
|
||||||
|
uint8_t pack[4] = {0, 0, 0, 0};
|
||||||
|
if (!mifare_ul_ev1_auth(pwd, pack)) {
|
||||||
|
OnError(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mifare_ultra_writeblock_compat(blockNo, blockdata)) {
|
||||||
|
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Write block error");
|
||||||
|
OnError(0);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (mifare_ultra_halt()) {
|
||||||
|
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Halt error");
|
||||||
|
OnError(0);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
|
||||||
|
|
||||||
|
reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
LEDsoff();
|
||||||
|
set_tracing(false);
|
||||||
|
}
|
||||||
|
|
||||||
void MifareUSetPwd(uint8_t arg0, uint8_t *datain) {
|
void MifareUSetPwd(uint8_t arg0, uint8_t *datain) {
|
||||||
|
|
||||||
uint8_t pwd[16] = {0x00};
|
uint8_t pwd[16] = {0x00};
|
||||||
|
@ -905,7 +934,7 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8
|
||||||
set_tracing(true);
|
set_tracing(true);
|
||||||
|
|
||||||
// statistics on nonce distance
|
// statistics on nonce distance
|
||||||
int16_t isOK = 0;
|
int16_t isOK = PM3_SUCCESS;
|
||||||
#define NESTED_MAX_TRIES 12
|
#define NESTED_MAX_TRIES 12
|
||||||
if (calibrate) { // calibrate: for first call only. Otherwise reuse previous calibration
|
if (calibrate) { // calibrate: for first call only. Otherwise reuse previous calibration
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
|
@ -921,7 +950,7 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8
|
||||||
|
|
||||||
// Test if the action was cancelled
|
// Test if the action was cancelled
|
||||||
if (BUTTON_PRESS() || data_available()) {
|
if (BUTTON_PRESS() || data_available()) {
|
||||||
isOK = -2;
|
isOK = PM3_EOPABORTED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -976,7 +1005,7 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8
|
||||||
} else {
|
} else {
|
||||||
unsuccessful_tries++;
|
unsuccessful_tries++;
|
||||||
if (unsuccessful_tries > NESTED_MAX_TRIES) { // card isn't vulnerable to nested attack (random numbers are not predictable)
|
if (unsuccessful_tries > NESTED_MAX_TRIES) { // card isn't vulnerable to nested attack (random numbers are not predictable)
|
||||||
isOK = -3;
|
isOK = PM3_EFAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1002,7 +1031,7 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8
|
||||||
|
|
||||||
// Test if the action was cancelled
|
// Test if the action was cancelled
|
||||||
if (BUTTON_PRESS() || data_available()) {
|
if (BUTTON_PRESS() || data_available()) {
|
||||||
isOK = -2;
|
isOK = PM3_EOPABORTED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1091,12 +1120,7 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8
|
||||||
memcpy(payload.nt_b, &target_nt[1], 4);
|
memcpy(payload.nt_b, &target_nt[1], 4);
|
||||||
memcpy(payload.ks_b, &target_ks[1], 4);
|
memcpy(payload.ks_b, &target_ks[1], 4);
|
||||||
|
|
||||||
LED_B_ON();
|
|
||||||
reply_ng(CMD_HF_MIFARE_NESTED, PM3_SUCCESS, (uint8_t *)&payload, sizeof(payload));
|
reply_ng(CMD_HF_MIFARE_NESTED, PM3_SUCCESS, (uint8_t *)&payload, sizeof(payload));
|
||||||
LED_B_OFF();
|
|
||||||
|
|
||||||
if (DBGLEVEL >= 3) DbpString("NESTED FINISHED");
|
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
set_tracing(false);
|
set_tracing(false);
|
||||||
|
@ -1108,13 +1132,10 @@ void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo,
|
||||||
|
|
||||||
uint64_t ui64Key = 0;
|
uint64_t ui64Key = 0;
|
||||||
ui64Key = bytes_to_num(key, 6);
|
ui64Key = bytes_to_num(key, 6);
|
||||||
|
|
||||||
// variables
|
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
|
|
||||||
uint8_t uid[10] = {0x00};
|
uint8_t uid[10] = {0x00};
|
||||||
uint32_t cuid = 0, nt1, nt2;
|
uint32_t cuid = 0, nt1, nt2;
|
||||||
uint32_t target_nt = {0x00}, target_ks = {0x00};
|
uint32_t target_nt = 0, target_ks = 0;
|
||||||
uint8_t par[1] = {0x00};
|
uint8_t par[1] = {0x00};
|
||||||
uint8_t receivedAnswer[10] = {0x00};
|
uint8_t receivedAnswer[10] = {0x00};
|
||||||
|
|
||||||
|
@ -1132,7 +1153,6 @@ void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo,
|
||||||
set_tracing(true);
|
set_tracing(true);
|
||||||
|
|
||||||
int16_t isOK = 0;
|
int16_t isOK = 0;
|
||||||
|
|
||||||
LED_C_ON();
|
LED_C_ON();
|
||||||
|
|
||||||
for (uint8_t retry = 0; retry < 3 && (isOK == 0); retry++) {
|
for (uint8_t retry = 0; retry < 3 && (isOK == 0); retry++) {
|
||||||
|
@ -1152,7 +1172,7 @@ void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo,
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
// First authenticatoin. Normal auth.
|
// First authentication. Normal auth.
|
||||||
if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, NULL)) {
|
if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, NULL)) {
|
||||||
if (DBGLEVEL >= DBG_INFO) Dbprintf("Nested: Auth1 error");
|
if (DBGLEVEL >= DBG_INFO) Dbprintf("Nested: Auth1 error");
|
||||||
retry--;
|
retry--;
|
||||||
|
@ -1167,9 +1187,8 @@ void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo,
|
||||||
};
|
};
|
||||||
|
|
||||||
nt2 = bytes_to_num(receivedAnswer, 4);
|
nt2 = bytes_to_num(receivedAnswer, 4);
|
||||||
uint32_t nt_tmp = prng_successor(nt1, 160);
|
target_nt = prng_successor(nt1, 160);
|
||||||
target_ks = nt2 ^ nt_tmp;
|
target_ks = nt2 ^ target_nt;
|
||||||
target_nt = nt_tmp;
|
|
||||||
isOK = 1;
|
isOK = 1;
|
||||||
|
|
||||||
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Testing nt1=%08x nt2enc=%08x nt2par=%02x ks=%08x", nt1, nt2, par[0], target_ks);
|
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Testing nt1=%08x nt2enc=%08x nt2par=%02x ks=%08x", nt1, nt2, par[0], target_ks);
|
||||||
|
@ -1689,7 +1708,7 @@ OUT:
|
||||||
DBGLEVEL = oldbg;
|
DBGLEVEL = oldbg;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MifareChkKeys(uint8_t *datain) {
|
void MifareChkKeys(uint8_t *datain, uint8_t reserved_mem) {
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
|
||||||
|
@ -1715,7 +1734,12 @@ void MifareChkKeys(uint8_t *datain) {
|
||||||
bool clearTrace = datain[2];
|
bool clearTrace = datain[2];
|
||||||
uint16_t key_count = (datain[3] << 8) | datain[4];
|
uint16_t key_count = (datain[3] << 8) | datain[4];
|
||||||
|
|
||||||
uint16_t key_mem_available = MIN((PM3_CMD_DATA_SIZE - 5), key_count * 6);
|
uint16_t key_mem_available;
|
||||||
|
if (reserved_mem)
|
||||||
|
key_mem_available = key_count * 6;
|
||||||
|
else
|
||||||
|
key_mem_available = MIN((PM3_CMD_DATA_SIZE - 5), key_count * 6);
|
||||||
|
|
||||||
key_count = key_mem_available / 6;
|
key_count = key_mem_available / 6;
|
||||||
|
|
||||||
datain += 5;
|
datain += 5;
|
||||||
|
@ -1793,6 +1817,8 @@ void MifareChkKeys(uint8_t *datain) {
|
||||||
void MifareChkKeys_file(uint8_t *fn) {
|
void MifareChkKeys_file(uint8_t *fn) {
|
||||||
|
|
||||||
#ifdef WITH_FLASH
|
#ifdef WITH_FLASH
|
||||||
|
BigBuf_free();
|
||||||
|
|
||||||
SpinOff(0);
|
SpinOff(0);
|
||||||
|
|
||||||
int changed = rdv40_spiffs_lazy_mount();
|
int changed = rdv40_spiffs_lazy_mount();
|
||||||
|
@ -1807,7 +1833,7 @@ void MifareChkKeys_file(uint8_t *fn) {
|
||||||
|
|
||||||
SpinOff(0);
|
SpinOff(0);
|
||||||
|
|
||||||
MifareChkKeys(mem);
|
MifareChkKeys(mem, true);
|
||||||
|
|
||||||
BigBuf_free();
|
BigBuf_free();
|
||||||
#endif
|
#endif
|
||||||
|
@ -1966,10 +1992,16 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) {
|
||||||
|
|
||||||
for (uint8_t blockNo = 0; blockNo < NumBlocksPerSector(sectorNo); blockNo++) {
|
for (uint8_t blockNo = 0; blockNo < NumBlocksPerSector(sectorNo); blockNo++) {
|
||||||
if (mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) {
|
if (mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) {
|
||||||
retval = PM3_ESOFT;
|
retval = PM3_EPARTIAL;
|
||||||
|
|
||||||
if (DBGLEVEL > DBG_ERROR) Dbprintf("Error reading sector %2d block %2d", sectorNo, blockNo);
|
if (DBGLEVEL > DBG_ERROR) Dbprintf("Error reading sector %2d block %2d", sectorNo, blockNo);
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (memcmp(dataoutbuf, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (blockNo < NumBlocksPerSector(sectorNo) - 1) {
|
if (blockNo < NumBlocksPerSector(sectorNo) - 1) {
|
||||||
emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1);
|
emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1);
|
||||||
} else { // sector trailer, keep the keys, set only the AC
|
} else { // sector trailer, keep the keys, set only the AC
|
||||||
|
@ -2059,12 +2091,19 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t old_timeout = iso14a_get_timeout();
|
||||||
|
|
||||||
|
// 2000 ms timeout
|
||||||
|
// 13560000 / 1000 / (8 * 16) * timeout
|
||||||
|
iso14a_set_timeout(21190);
|
||||||
|
|
||||||
ReaderTransmit(wipeC, sizeof(wipeC), NULL);
|
ReaderTransmit(wipeC, sizeof(wipeC), NULL);
|
||||||
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("wipeC error");
|
if (DBGLEVEL >= DBG_ERROR) Dbprintf("wipeC error");
|
||||||
errormsg = MAGIC_WIPE;
|
errormsg = MAGIC_WIPE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
iso14a_set_timeout(old_timeout);
|
||||||
|
|
||||||
mifare_classic_halt_ex(NULL);
|
mifare_classic_halt_ex(NULL);
|
||||||
}
|
}
|
||||||
|
@ -2244,6 +2283,26 @@ void MifareCIdent(void) {
|
||||||
if (memcmp(buf, "\x0D\x78\x00\x71\x02\x88\x49\xA1\x30\x20\x15\x06\x08\x56\x3D", 15) == 0) {
|
if (memcmp(buf, "\x0D\x78\x00\x71\x02\x88\x49\xA1\x30\x20\x15\x06\x08\x56\x3D", 15) == 0) {
|
||||||
isGen = MAGIC_GEN_2;
|
isGen = MAGIC_GEN_2;
|
||||||
}
|
}
|
||||||
|
// test for Ultralight magic gen2
|
||||||
|
if (memcmp(buf, "\x0A\x78\x00\x81\x02\xDB\xA0\xC1\x19\x40\x2A\xB5", 12) == 0) {
|
||||||
|
isGen = MAGIC_GEN_2;
|
||||||
|
goto OUT;
|
||||||
|
}
|
||||||
|
// test for Ultralight EV1 magic gen2
|
||||||
|
if (memcmp(buf, "\x85\x00\x00\xA0\x00\x00\x0A\xC3\x00\x04\x03\x01\x01\x00\x0B\x03\x41\xDF", 18) == 0) {
|
||||||
|
isGen = MAGIC_GEN_2;
|
||||||
|
goto OUT;
|
||||||
|
}
|
||||||
|
// test for some other Ultralight EV1 magic gen2
|
||||||
|
if (memcmp(buf, "\x85\x00\x00\xA0\x0A\x00\x0A\xC3\x00\x04\x03\x01\x01\x00\x0B\x03\x16\xD7", 18) == 0) {
|
||||||
|
isGen = MAGIC_GEN_2;
|
||||||
|
goto OUT;
|
||||||
|
}
|
||||||
|
// test for some other Ultralight magic gen2
|
||||||
|
if (memcmp(buf, "\x85\x00\x00\xA0\x0A\x00\x0A\xB0\x00\x00\x00\x00\x00\x00\x00\x00\x18\x4D", 18) == 0) {
|
||||||
|
isGen = MAGIC_GEN_2;
|
||||||
|
goto OUT;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
OUT:
|
OUT:
|
||||||
|
@ -2315,6 +2374,154 @@ void OnErrorMagic(uint8_t reason) {
|
||||||
OnSuccessMagic();
|
OnSuccessMagic();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int DoGen3Cmd(uint8_t *cmd, uint8_t cmd_len) {
|
||||||
|
int retval = PM3_SUCCESS;
|
||||||
|
uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||||
|
uint8_t *buf = BigBuf_malloc(PM3_CMD_DATA_SIZE);
|
||||||
|
|
||||||
|
LED_B_ON();
|
||||||
|
uint32_t save_iso14a_timeout = iso14a_get_timeout();
|
||||||
|
iso14a_set_timeout(13560000 / 1000 / (8 * 16) * 2000); // 2 seconds timeout
|
||||||
|
|
||||||
|
ReaderTransmit(cmd, cmd_len, NULL);
|
||||||
|
int res = ReaderReceive(buf, par);
|
||||||
|
if (res == 4 && memcmp(buf, "\x90\x00\xfd\x07", 4) == 0) {
|
||||||
|
// timeout for card memory reset
|
||||||
|
SpinDelay(1000);
|
||||||
|
} else {
|
||||||
|
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Card operation not completed");
|
||||||
|
retval = PM3_ESOFT;
|
||||||
|
}
|
||||||
|
iso14a_set_timeout(save_iso14a_timeout);
|
||||||
|
LED_B_OFF();
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MifareGen3UID(uint8_t uidlen, uint8_t *uid) {
|
||||||
|
int retval = PM3_SUCCESS;
|
||||||
|
uint8_t uid_cmd[5] = { 0x90, 0xfb, 0xcc, 0xcc, 0x07 };
|
||||||
|
uint8_t *old_uid = BigBuf_malloc(10);
|
||||||
|
uint8_t *cmd = BigBuf_malloc(sizeof(uid_cmd) + uidlen + 2);
|
||||||
|
iso14a_card_select_t *card_info = (iso14a_card_select_t *) BigBuf_malloc(sizeof(iso14a_card_select_t));
|
||||||
|
|
||||||
|
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||||
|
clear_trace();
|
||||||
|
set_tracing(true);
|
||||||
|
|
||||||
|
if (!iso14443a_select_card(old_uid, card_info, NULL, true, 0, true)) {
|
||||||
|
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Card not selected");
|
||||||
|
retval = PM3_ESOFT;
|
||||||
|
goto OUT;
|
||||||
|
}
|
||||||
|
if (card_info->uidlen != uidlen) {
|
||||||
|
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Wrong UID length");
|
||||||
|
retval = PM3_ESOFT;
|
||||||
|
goto OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(cmd, uid_cmd, sizeof(uid_cmd));
|
||||||
|
memcpy(&cmd[sizeof(uid_cmd)], uid, uidlen);
|
||||||
|
AddCrc14A(cmd, sizeof(uid_cmd) + uidlen);
|
||||||
|
|
||||||
|
retval = DoGen3Cmd(cmd, sizeof(uid_cmd) + uidlen + 2);
|
||||||
|
|
||||||
|
OUT:
|
||||||
|
reply_ng(CMD_HF_MIFARE_GEN3UID, retval, old_uid, uidlen);
|
||||||
|
// turns off
|
||||||
|
OnSuccessMagic();
|
||||||
|
BigBuf_free();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MifareGen3Blk(uint8_t block_len, uint8_t *block) {
|
||||||
|
#define MIFARE_BLOCK_SIZE (MAX_MIFARE_FRAME_SIZE - 2)
|
||||||
|
int retval = PM3_SUCCESS;
|
||||||
|
uint8_t block_cmd[5] = { 0x90, 0xf0, 0xcc, 0xcc, 0x10 };
|
||||||
|
uint8_t *uid = BigBuf_malloc(10);
|
||||||
|
uint8_t *cmd = BigBuf_malloc(sizeof(block_cmd) + MAX_MIFARE_FRAME_SIZE);
|
||||||
|
iso14a_card_select_t *card_info = (iso14a_card_select_t *) BigBuf_malloc(sizeof(iso14a_card_select_t));
|
||||||
|
|
||||||
|
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||||
|
clear_trace();
|
||||||
|
set_tracing(true);
|
||||||
|
|
||||||
|
if (!iso14443a_select_card(uid, card_info, NULL, true, 0, true)) {
|
||||||
|
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Card not selected");
|
||||||
|
retval = PM3_ESOFT;
|
||||||
|
goto OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool doReselect = false;
|
||||||
|
if (block_len < MIFARE_BLOCK_SIZE) {
|
||||||
|
if ((mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_READBLOCK, 0, &cmd[sizeof(block_cmd)], NULL, NULL) != MAX_MIFARE_FRAME_SIZE)) {
|
||||||
|
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Read manufacturer block failed");
|
||||||
|
retval = PM3_ESOFT;
|
||||||
|
goto OUT;
|
||||||
|
}
|
||||||
|
doReselect = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block_len > 0) {
|
||||||
|
memcpy(cmd, block_cmd, sizeof(block_cmd));
|
||||||
|
memcpy(&cmd[sizeof(block_cmd)], block, block_len);
|
||||||
|
int ofs = sizeof(block_cmd);
|
||||||
|
if (card_info->uidlen == 4) {
|
||||||
|
cmd[ofs + 4] = cmd[ofs + 0] ^ cmd[ofs + 1] ^ cmd[ofs + 2] ^ cmd[ofs + 3];
|
||||||
|
ofs += 5;
|
||||||
|
} else if (card_info->uidlen == 7) {
|
||||||
|
ofs += 7;
|
||||||
|
} else {
|
||||||
|
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Wrong Card UID length");
|
||||||
|
retval = PM3_ESOFT;
|
||||||
|
goto OUT;
|
||||||
|
}
|
||||||
|
cmd[ofs++] = card_info->sak;
|
||||||
|
cmd[ofs++] = card_info->atqa[0];
|
||||||
|
cmd[ofs++] = card_info->atqa[1];
|
||||||
|
AddCrc14A(cmd, sizeof(block_cmd) + MIFARE_BLOCK_SIZE);
|
||||||
|
|
||||||
|
if (doReselect) {
|
||||||
|
if (!iso14443a_select_card(uid, NULL, NULL, true, 0, true)) {
|
||||||
|
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Card not selected");
|
||||||
|
retval = PM3_ESOFT;
|
||||||
|
goto OUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = DoGen3Cmd(cmd, sizeof(block_cmd) + MAX_MIFARE_FRAME_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
OUT:
|
||||||
|
reply_ng(CMD_HF_MIFARE_GEN3BLK, retval, &cmd[sizeof(block_cmd)], MIFARE_BLOCK_SIZE);
|
||||||
|
// turns off
|
||||||
|
OnSuccessMagic();
|
||||||
|
BigBuf_free();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MifareGen3Freez(void) {
|
||||||
|
int retval = PM3_SUCCESS;
|
||||||
|
uint8_t freeze_cmd[7] = { 0x90, 0xfd, 0x11, 0x11, 0x00, 0xe7, 0x91 };
|
||||||
|
uint8_t *uid = BigBuf_malloc(10);
|
||||||
|
|
||||||
|
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||||
|
clear_trace();
|
||||||
|
set_tracing(true);
|
||||||
|
|
||||||
|
if (!iso14443a_select_card(uid, NULL, NULL, true, 0, true)) {
|
||||||
|
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Card not selected");
|
||||||
|
retval = PM3_ESOFT;
|
||||||
|
goto OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = DoGen3Cmd(freeze_cmd, sizeof(freeze_cmd));
|
||||||
|
|
||||||
|
OUT:
|
||||||
|
reply_ng(CMD_HF_MIFARE_GEN3FREEZ, retval, NULL, 0);
|
||||||
|
// turns off
|
||||||
|
OnSuccessMagic();
|
||||||
|
BigBuf_free();
|
||||||
|
}
|
||||||
|
|
||||||
void MifareSetMod(uint8_t *datain) {
|
void MifareSetMod(uint8_t *datain) {
|
||||||
|
|
||||||
uint8_t mod = datain[0];
|
uint8_t mod = datain[0];
|
||||||
|
|
|
@ -20,7 +20,7 @@ void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes);
|
||||||
void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);
|
void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);
|
||||||
void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||||
void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||||
//void MifareUWriteBlockCompat(uint8_t arg0,uint8_t *datain);
|
void MifareUWriteBlockCompat(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||||
|
|
||||||
void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||||
void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, bool calibrate, uint8_t *key);
|
void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, bool calibrate, uint8_t *key);
|
||||||
|
@ -29,7 +29,7 @@ void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo,
|
||||||
|
|
||||||
void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain);
|
void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain);
|
||||||
void MifareAcquireNonces(uint32_t arg0, uint32_t flags);
|
void MifareAcquireNonces(uint32_t arg0, uint32_t flags);
|
||||||
void MifareChkKeys(uint8_t *datain);
|
void MifareChkKeys(uint8_t *datain, uint8_t reserved_mem);
|
||||||
void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||||
void MifareChkKeys_file(uint8_t *fn);
|
void MifareChkKeys_file(uint8_t *fn);
|
||||||
|
|
||||||
|
@ -44,6 +44,11 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain);
|
||||||
void MifareCIdent(void); // is "magic chinese" card?
|
void MifareCIdent(void); // is "magic chinese" card?
|
||||||
void MifareHasStaticNonce(void); // Has the tag a static nonce?
|
void MifareHasStaticNonce(void); // Has the tag a static nonce?
|
||||||
|
|
||||||
|
int DoGen3Cmd(uint8_t *cmd, uint8_t cmd_len);
|
||||||
|
void MifareGen3UID(uint8_t uidlen, uint8_t *uid); // Gen 3 magic card set UID without manufacturer block
|
||||||
|
void MifareGen3Blk(uint8_t block_len, uint8_t *block); // Gen 3 magic card overwrite manufacturer block
|
||||||
|
void MifareGen3Freez(void); // Gen 3 magic card lock further UID changes
|
||||||
|
|
||||||
void MifareSetMod(uint8_t *datain);
|
void MifareSetMod(uint8_t *datain);
|
||||||
void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint64_t key);
|
void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint64_t key);
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,6 @@ static bool IsTrailerAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t act
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool IsDataAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) {
|
static bool IsDataAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) {
|
||||||
|
|
||||||
uint8_t sector_trailer[16];
|
uint8_t sector_trailer[16];
|
||||||
|
@ -243,7 +242,7 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, uint16_t atqa, uint8_
|
||||||
rSAK[0] = block0[7];
|
rSAK[0] = block0[7];
|
||||||
memcpy(rATQA, &block0[8], sizeof(rATQA));
|
memcpy(rATQA, &block0[8], sizeof(rATQA));
|
||||||
} else {
|
} else {
|
||||||
Dbprintf("[-] ERROR: Invalid dump. UID/SAK/ATQA not found");
|
Dbprintf("ERROR: " _RED_("Invalid dump. UID/SAK/ATQA not found"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -342,7 +341,7 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, uint16_t atqa, uint8_
|
||||||
// Correct uid size bits in ATQA
|
// Correct uid size bits in ATQA
|
||||||
rATQA[0] = (rATQA[0] & 0x3f) | 0x80; // triple size uid
|
rATQA[0] = (rATQA[0] & 0x3f) | 0x80; // triple size uid
|
||||||
} else {
|
} else {
|
||||||
Dbprintf("[-] ERROR: UID size not defined");
|
Dbprintf("ERROR: " _RED_("UID size not defined"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (flags & FLAG_FORCED_ATQA) {
|
if (flags & FLAG_FORCED_ATQA) {
|
||||||
|
@ -529,12 +528,22 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1
|
||||||
LED_D_ON();
|
LED_D_ON();
|
||||||
ResetSspClk();
|
ResetSspClk();
|
||||||
|
|
||||||
|
int counter = 0;
|
||||||
bool finished = false;
|
bool finished = false;
|
||||||
bool button_pushed = BUTTON_PRESS();
|
bool button_pushed = BUTTON_PRESS();
|
||||||
|
while (!button_pushed && !finished) {
|
||||||
|
|
||||||
while (!button_pushed && !finished && !data_available()) {
|
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
|
if (counter == 2000) {
|
||||||
|
if (data_available()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
counter = 0;
|
||||||
|
} else {
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
// find reader field
|
// find reader field
|
||||||
if (cardSTATE == MFEMUL_NOFIELD) {
|
if (cardSTATE == MFEMUL_NOFIELD) {
|
||||||
|
|
||||||
|
|
|
@ -203,14 +203,14 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
|
||||||
iso14a_set_timeout(save_timeout);
|
iso14a_set_timeout(save_timeout);
|
||||||
|
|
||||||
if (!len) {
|
if (!len) {
|
||||||
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Authentication failed. Card timeout.");
|
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Authentication failed. Card timeout");
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
ntpp = prng_successor(nt, 32) ^ crypto1_word(pcs, 0, 0);
|
ntpp = prng_successor(nt, 32) ^ crypto1_word(pcs, 0, 0);
|
||||||
|
|
||||||
if (ntpp != bytes_to_num(receivedAnswer, 4)) {
|
if (ntpp != bytes_to_num(receivedAnswer, 4)) {
|
||||||
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Authentication failed. Error card response.");
|
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Authentication failed. Error card response");
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -225,18 +225,18 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo
|
||||||
|
|
||||||
len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||||
if (len == 1) {
|
if (len == 1) {
|
||||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd Error %02x", receivedAnswer[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (len != 18) {
|
if (len != 18) {
|
||||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd Error: wrong response len: %x (expected 18)", len);
|
if (DBGLEVEL >= DBG_ERROR) Dbprintf("wrong response len %d (expected 18)", len);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(bt, receivedAnswer + 16, 2);
|
memcpy(bt, receivedAnswer + 16, 2);
|
||||||
AddCrc14A(receivedAnswer, 16);
|
AddCrc14A(receivedAnswer, 16);
|
||||||
if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) {
|
if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) {
|
||||||
if (DBGLEVEL >= DBG_INFO) Dbprintf("Cmd CRC response error.");
|
if (DBGLEVEL >= DBG_INFO) Dbprintf("CRC response error");
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,37 +446,37 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* // command not needed, but left for future testing
|
|
||||||
int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData) {
|
int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData) {
|
||||||
uint16_t len;
|
// variables
|
||||||
uint8_t par[3] = {0}; // enough for 18 parity bits
|
uint16_t len = 0;
|
||||||
uint8_t d_block[18] = {0x00};
|
|
||||||
uint8_t receivedAnswer[MAX_FRAME_SIZE];
|
uint8_t d_block[18];
|
||||||
uint8_t receivedAnswerPar[MAX_PARITY_SIZE];
|
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
|
||||||
|
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
|
||||||
|
|
||||||
len = mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
len = mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||||
|
|
||||||
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
|
if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK
|
||||||
if (DBGLEVEL >= DBG_ERROR)
|
if (DBGLEVEL >= DBG_ERROR)
|
||||||
Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]);
|
Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0], len);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(d_block, blockData, 16);
|
memcpy(d_block, blockData, 16);
|
||||||
AddCrc14A(d_block, 16);
|
AddCrc14A(d_block, 16);
|
||||||
|
|
||||||
ReaderTransmitPar(d_block, sizeof(d_block), par, NULL);
|
ReaderTransmit(d_block, sizeof(d_block), NULL);
|
||||||
|
|
||||||
|
// Receive the response
|
||||||
len = ReaderReceive(receivedAnswer, receivedAnswerPar);
|
len = ReaderReceive(receivedAnswer, receivedAnswerPar);
|
||||||
|
|
||||||
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
|
if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK
|
||||||
if (DBGLEVEL >= DBG_ERROR)
|
if (DBGLEVEL >= DBG_ERROR)
|
||||||
Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len);
|
Dbprintf("Cmd Send Data Error: %02x %d", receivedAnswer[0], len);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData) {
|
int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData) {
|
||||||
uint16_t len = 0;
|
uint16_t len = 0;
|
||||||
|
@ -613,7 +613,7 @@ void emlClearMem(void) {
|
||||||
memset(emCARD, 0, CARD_MEMORY_SIZE);
|
memset(emCARD, 0, CARD_MEMORY_SIZE);
|
||||||
|
|
||||||
// fill sectors trailer data
|
// fill sectors trailer data
|
||||||
for (uint16_t b = 3; b <= MIFARE_4K_MAXBLOCK; ((b <= MIFARE_2K_MAXBLOCK) ? (b += 4) : (b += 16)))
|
for (uint16_t b = 3; b < MIFARE_4K_MAXBLOCK; ((b < MIFARE_2K_MAXBLOCK - 4) ? (b += 4) : (b += 16)))
|
||||||
emlSetMem((uint8_t *)trailer, b, 1);
|
emlSetMem((uint8_t *)trailer, b, 1);
|
||||||
|
|
||||||
// uid
|
// uid
|
||||||
|
|
|
@ -73,7 +73,7 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
|
||||||
int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack);
|
int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack);
|
||||||
int mifare_ultra_auth(uint8_t *keybytes);
|
int mifare_ultra_auth(uint8_t *keybytes);
|
||||||
int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData);
|
int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData);
|
||||||
//int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData);
|
int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData);
|
||||||
int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData);
|
int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData);
|
||||||
int mifare_ultra_halt(void);
|
int mifare_ultra_halt(void);
|
||||||
|
|
||||||
|
|
|
@ -67,30 +67,33 @@ static s32_t rdv40_spiffs_llwrite(u32_t addr, u32_t size, u8_t *src) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static s32_t rdv40_spiffs_llerase(u32_t addr, u32_t size) {
|
static s32_t rdv40_spiffs_llerase(u32_t addr, u32_t size) {
|
||||||
|
|
||||||
|
|
||||||
uint8_t erased = 0;
|
uint8_t erased = 0;
|
||||||
|
|
||||||
if (!FlashInit()) {
|
if (!FlashInit()) {
|
||||||
return 130;
|
return 130;
|
||||||
}
|
}
|
||||||
if (DBGLEVEL > 2) Dbprintf("LLERASEDBG : Orig addr : %d\n", addr);
|
|
||||||
|
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("LLERASEDBG : Orig addr : %d\n", addr);
|
||||||
|
|
||||||
uint8_t block, sector = 0;
|
uint8_t block, sector = 0;
|
||||||
block = addr / RDV40_LLERASE_BLOCKSIZE;
|
block = addr / RDV40_LLERASE_BLOCKSIZE;
|
||||||
if (block) {
|
if (block) {
|
||||||
addr = addr - (block * RDV40_LLERASE_BLOCKSIZE);
|
addr = addr - (block * RDV40_LLERASE_BLOCKSIZE);
|
||||||
}
|
}
|
||||||
if (DBGLEVEL > 2) Dbprintf("LLERASEDBG : Result addr : %d\n", addr);
|
|
||||||
|
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("LLERASEDBG : Result addr : %d\n", addr);
|
||||||
|
|
||||||
sector = addr / SPIFFS_CFG_LOG_BLOCK_SZ;
|
sector = addr / SPIFFS_CFG_LOG_BLOCK_SZ;
|
||||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||||
Flash_WriteEnable();
|
Flash_WriteEnable();
|
||||||
if (DBGLEVEL > 2) Dbprintf("LLERASEDBG : block : %d, sector : %d \n", block, sector);
|
|
||||||
erased = Flash_Erase4k(block, sector);
|
|
||||||
|
|
||||||
|
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("LLERASEDBG : block : %d, sector : %d \n", block, sector);
|
||||||
|
|
||||||
|
erased = Flash_Erase4k(block, sector);
|
||||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||||
FlashStop();
|
FlashStop();
|
||||||
|
|
||||||
return SPIFFS_OK == erased ;
|
return (SPIFFS_OK == erased);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -252,7 +255,7 @@ static RDV40SpiFFSFileType filetype_in_spiffs(const char *filename) {
|
||||||
filetype = RDV40_SPIFFS_FILETYPE_SYMLINK;
|
filetype = RDV40_SPIFFS_FILETYPE_SYMLINK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (DBGLEVEL > 1) {
|
if (DBGLEVEL >= DBG_DEBUG) {
|
||||||
switch (filetype) {
|
switch (filetype) {
|
||||||
case RDV40_SPIFFS_FILETYPE_REAL:
|
case RDV40_SPIFFS_FILETYPE_REAL:
|
||||||
Dbprintf("Filetype is : RDV40_SPIFFS_FILETYPE_REAL");
|
Dbprintf("Filetype is : RDV40_SPIFFS_FILETYPE_REAL");
|
||||||
|
@ -472,16 +475,19 @@ int rdv40_spiffs_is_symlink(const char *s) {
|
||||||
// ATTENTION : you must NOT provide the whole filename (so please do not include the .lnk extension)
|
// ATTENTION : you must NOT provide the whole filename (so please do not include the .lnk extension)
|
||||||
// TODO : integrate in read_function
|
// TODO : integrate in read_function
|
||||||
int rdv40_spiffs_read_as_symlink(char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level) {
|
int rdv40_spiffs_read_as_symlink(char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level) {
|
||||||
|
|
||||||
RDV40_SPIFFS_SAFE_FUNCTION(
|
RDV40_SPIFFS_SAFE_FUNCTION(
|
||||||
char linkdest[SPIFFS_OBJ_NAME_LEN];
|
char linkdest[SPIFFS_OBJ_NAME_LEN];
|
||||||
char linkfilename[SPIFFS_OBJ_NAME_LEN];
|
char linkfilename[SPIFFS_OBJ_NAME_LEN];
|
||||||
sprintf(linkfilename, "%s.lnk", filename);
|
sprintf(linkfilename, "%s.lnk", filename);
|
||||||
|
|
||||||
if (DBGLEVEL > 1) Dbprintf("Linkk real filename is : " _YELLOW_("%s"), linkfilename);
|
if (DBGLEVEL >= DBG_DEBUG)
|
||||||
|
Dbprintf("Linkk real filename is : " _YELLOW_("%s"), linkfilename);
|
||||||
|
|
||||||
read_from_spiffs((char *)linkfilename, (uint8_t *)linkdest, SPIFFS_OBJ_NAME_LEN);
|
read_from_spiffs((char *)linkfilename, (uint8_t *)linkdest, SPIFFS_OBJ_NAME_LEN);
|
||||||
|
|
||||||
if (DBGLEVEL > 1) Dbprintf("Symlink destination is : " _YELLOW_("%s"), linkdest);
|
if (DBGLEVEL >= DBG_DEBUG)
|
||||||
|
Dbprintf("Symlink destination is : " _YELLOW_("%s"), linkdest);
|
||||||
|
|
||||||
read_from_spiffs((char *)linkdest, (uint8_t *)dst, size);
|
read_from_spiffs((char *)linkdest, (uint8_t *)dst, size);
|
||||||
)
|
)
|
||||||
|
|
|
@ -58,8 +58,6 @@ typedef uint8_t u8_t;
|
||||||
#define SPIFFS_API_DBGF(str) SPIFFS_API_DBG(str,NULL)
|
#define SPIFFS_API_DBGF(str) SPIFFS_API_DBG(str,NULL)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Defines spiffs debug print formatters
|
// Defines spiffs debug print formatters
|
||||||
// some general signed number
|
// some general signed number
|
||||||
#ifndef _SPIPRIi
|
#ifndef _SPIPRIi
|
||||||
|
|
|
@ -56,7 +56,7 @@ static void usart_fill_rxfifo(void) {
|
||||||
rxfifo_free = us_rxfifo_low - us_rxfifo_high;
|
rxfifo_free = us_rxfifo_low - us_rxfifo_high;
|
||||||
else
|
else
|
||||||
rxfifo_free = sizeof(us_rxfifo) - us_rxfifo_high + us_rxfifo_low;
|
rxfifo_free = sizeof(us_rxfifo) - us_rxfifo_high + us_rxfifo_low;
|
||||||
|
|
||||||
uint16_t available = USART_BUFFLEN - usart_cur_inbuf_off;
|
uint16_t available = USART_BUFFLEN - usart_cur_inbuf_off;
|
||||||
|
|
||||||
if (available <= rxfifo_free) {
|
if (available <= rxfifo_free) {
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef REV64
|
#ifndef REV64
|
||||||
#define REV64(x) (REV32(x) + (REV32((x) >> 32) << 32))
|
#define REV64(x) (REV32(x) + ((uint64_t)(REV32((x) >> 32) << 32)))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef BIT32
|
#ifndef BIT32
|
||||||
|
|
28
client/cmdscripts/test_psk_clone.cmd
Normal file
28
client/cmdscripts/test_psk_clone.cmd
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
clear
|
||||||
|
|
||||||
|
rem Test of Motorola clone & read
|
||||||
|
lf t55xx wipe
|
||||||
|
lf motorola clone a0000000a0002021
|
||||||
|
lf motorola read
|
||||||
|
lf search
|
||||||
|
|
||||||
|
rem Test of Nexwatch clone & read
|
||||||
|
lf t55xx wipe
|
||||||
|
lf nexwatch clone c 1337 m 1 n
|
||||||
|
lf nexwatch read
|
||||||
|
lf search
|
||||||
|
|
||||||
|
rem Test of keri clone & read
|
||||||
|
lf t55xx wipe
|
||||||
|
lf keri clone 1337
|
||||||
|
lf keri read
|
||||||
|
lf search
|
||||||
|
|
||||||
|
rem Test of Indala clone & read
|
||||||
|
lf t55xx wipe
|
||||||
|
lf indala clone --fc 7 --cn 1337
|
||||||
|
lf indala read
|
||||||
|
lf search
|
||||||
|
|
||||||
|
rem done, just wiping your tag.
|
||||||
|
lf t55xx wipe
|
|
@ -7,7 +7,8 @@ set_property(TARGET pm3rrg_rdv4_hardnested_nosimd PROPERTY POSITION_INDEPENDENT_
|
||||||
|
|
||||||
target_include_directories(pm3rrg_rdv4_hardnested_nosimd PRIVATE
|
target_include_directories(pm3rrg_rdv4_hardnested_nosimd PRIVATE
|
||||||
../../common
|
../../common
|
||||||
../../include)
|
../../include
|
||||||
|
../src)
|
||||||
|
|
||||||
## CPU-specific code
|
## CPU-specific code
|
||||||
## These are mostly for x86-based architectures, which is not useful for many Android devices.
|
## These are mostly for x86-based architectures, which is not useful for many Android devices.
|
||||||
|
@ -34,7 +35,8 @@ if ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST X86_CPUS)
|
||||||
|
|
||||||
target_include_directories(pm3rrg_rdv4_hardnested_mmx PRIVATE
|
target_include_directories(pm3rrg_rdv4_hardnested_mmx PRIVATE
|
||||||
../../common
|
../../common
|
||||||
../../include)
|
../../include
|
||||||
|
../src)
|
||||||
|
|
||||||
## x86 / SSE2
|
## x86 / SSE2
|
||||||
add_library(pm3rrg_rdv4_hardnested_sse2 OBJECT
|
add_library(pm3rrg_rdv4_hardnested_sse2 OBJECT
|
||||||
|
@ -48,7 +50,8 @@ if ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST X86_CPUS)
|
||||||
|
|
||||||
target_include_directories(pm3rrg_rdv4_hardnested_sse2 PRIVATE
|
target_include_directories(pm3rrg_rdv4_hardnested_sse2 PRIVATE
|
||||||
../../common
|
../../common
|
||||||
../../include)
|
../../include
|
||||||
|
../src)
|
||||||
|
|
||||||
## x86 / AVX
|
## x86 / AVX
|
||||||
add_library(pm3rrg_rdv4_hardnested_avx OBJECT
|
add_library(pm3rrg_rdv4_hardnested_avx OBJECT
|
||||||
|
@ -62,7 +65,8 @@ if ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST X86_CPUS)
|
||||||
|
|
||||||
target_include_directories(pm3rrg_rdv4_hardnested_avx PRIVATE
|
target_include_directories(pm3rrg_rdv4_hardnested_avx PRIVATE
|
||||||
../../common
|
../../common
|
||||||
../../include)
|
../../include
|
||||||
|
../src)
|
||||||
|
|
||||||
## x86 / AVX2
|
## x86 / AVX2
|
||||||
add_library(pm3rrg_rdv4_hardnested_avx2 OBJECT
|
add_library(pm3rrg_rdv4_hardnested_avx2 OBJECT
|
||||||
|
@ -76,7 +80,8 @@ if ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST X86_CPUS)
|
||||||
|
|
||||||
target_include_directories(pm3rrg_rdv4_hardnested_avx2 PRIVATE
|
target_include_directories(pm3rrg_rdv4_hardnested_avx2 PRIVATE
|
||||||
../../common
|
../../common
|
||||||
../../include)
|
../../include
|
||||||
|
../src)
|
||||||
|
|
||||||
## x86 / AVX512
|
## x86 / AVX512
|
||||||
add_library(pm3rrg_rdv4_hardnested_avx512 OBJECT
|
add_library(pm3rrg_rdv4_hardnested_avx512 OBJECT
|
||||||
|
@ -90,7 +95,8 @@ if ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST X86_CPUS)
|
||||||
|
|
||||||
target_include_directories(pm3rrg_rdv4_hardnested_avx512 PRIVATE
|
target_include_directories(pm3rrg_rdv4_hardnested_avx512 PRIVATE
|
||||||
../../common
|
../../common
|
||||||
../../include)
|
../../include
|
||||||
|
../src)
|
||||||
|
|
||||||
set(SIMD_TARGETS
|
set(SIMD_TARGETS
|
||||||
$<TARGET_OBJECTS:pm3rrg_rdv4_hardnested_mmx>
|
$<TARGET_OBJECTS:pm3rrg_rdv4_hardnested_mmx>
|
||||||
|
|
|
@ -59,7 +59,7 @@ THE SOFTWARE.
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "crapto1/crapto1.h"
|
#include "crapto1/crapto1.h"
|
||||||
#include "parity.h"
|
#include "parity.h"
|
||||||
//#include "util.h"
|
#include "ui.h" // PrintAndLogEx
|
||||||
//#include "common.h"
|
//#include "common.h"
|
||||||
|
|
||||||
// bitslice type
|
// bitslice type
|
||||||
|
@ -238,18 +238,18 @@ uint64_t CRACK_STATES_BITSLICED(uint32_t cuid, uint8_t *best_first_bytes, statel
|
||||||
// bitslice all the even states
|
// bitslice all the even states
|
||||||
bitslice_t **restrict bitsliced_even_states = (bitslice_t **)malloc(((p->len[EVEN_STATE] - 1) / MAX_BITSLICES + 1) * sizeof(bitslice_t *));
|
bitslice_t **restrict bitsliced_even_states = (bitslice_t **)malloc(((p->len[EVEN_STATE] - 1) / MAX_BITSLICES + 1) * sizeof(bitslice_t *));
|
||||||
if (bitsliced_even_states == NULL) {
|
if (bitsliced_even_states == NULL) {
|
||||||
printf("Out of memory error in brute_force. Aborting...");
|
PrintAndLogEx(WARNING, "Out of memory error in brute_force. Aborting...");
|
||||||
exit(4);
|
exit(4);
|
||||||
}
|
}
|
||||||
bitslice_value_t *restrict bitsliced_even_feedback = malloc_bitslice(((p->len[EVEN_STATE] - 1) / MAX_BITSLICES + 1) * sizeof(bitslice_value_t));
|
bitslice_value_t *restrict bitsliced_even_feedback = malloc_bitslice(((p->len[EVEN_STATE] - 1) / MAX_BITSLICES + 1) * sizeof(bitslice_value_t));
|
||||||
if (bitsliced_even_feedback == NULL) {
|
if (bitsliced_even_feedback == NULL) {
|
||||||
printf("Out of memory error in brute_force. Aborting...");
|
PrintAndLogEx(WARNING, "Out of memory error in brute_force. Aborting...");
|
||||||
exit(4);
|
exit(4);
|
||||||
}
|
}
|
||||||
for (uint32_t *restrict p_even = p->states[EVEN_STATE]; p_even < p_even_end; p_even += MAX_BITSLICES) {
|
for (uint32_t *restrict p_even = p->states[EVEN_STATE]; p_even < p_even_end; p_even += MAX_BITSLICES) {
|
||||||
bitslice_t *restrict lstate_p = malloc_bitslice(STATE_SIZE / 2 * sizeof(bitslice_t));
|
bitslice_t *restrict lstate_p = malloc_bitslice(STATE_SIZE / 2 * sizeof(bitslice_t));
|
||||||
if (lstate_p == NULL) {
|
if (lstate_p == NULL) {
|
||||||
printf("Out of memory error in brute_force. Aborting... \n");
|
PrintAndLogEx(WARNING, "Out of memory error in brute_force. Aborting... \n");
|
||||||
exit(4);
|
exit(4);
|
||||||
}
|
}
|
||||||
memset(lstate_p, 0x00, STATE_SIZE / 2 * sizeof(bitslice_t)); // zero even bits
|
memset(lstate_p, 0x00, STATE_SIZE / 2 * sizeof(bitslice_t)); // zero even bits
|
||||||
|
@ -265,8 +265,8 @@ uint64_t CRACK_STATES_BITSLICED(uint32_t cuid, uint8_t *best_first_bytes, statel
|
||||||
#ifdef DEBUG_KEY_ELIMINATION
|
#ifdef DEBUG_KEY_ELIMINATION
|
||||||
if (known_target_key != -1 && e == test_state[EVEN_STATE]) {
|
if (known_target_key != -1 && e == test_state[EVEN_STATE]) {
|
||||||
bucket_contains_test_key[bitsliced_blocks] = true;
|
bucket_contains_test_key[bitsliced_blocks] = true;
|
||||||
// printf("bucket %d contains test key even state\n", bitsliced_blocks);
|
// PrintAndLogEx(INFO, "bucket %d contains test key even state", bitsliced_blocks);
|
||||||
// printf("in slice %d\n", slice_idx);
|
// PrintAndLogEx(INFO, "in slice %d", slice_idx);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
for (uint32_t bit_idx = 0; bit_idx < STATE_SIZE / 2; bit_idx++, e >>= 1) {
|
for (uint32_t bit_idx = 0; bit_idx < STATE_SIZE / 2; bit_idx++, e >>= 1) {
|
||||||
|
@ -336,8 +336,8 @@ uint64_t CRACK_STATES_BITSLICED(uint32_t cuid, uint8_t *best_first_bytes, statel
|
||||||
|
|
||||||
#ifdef DEBUG_KEY_ELIMINATION
|
#ifdef DEBUG_KEY_ELIMINATION
|
||||||
// if (known_target_key != -1 && bucket_contains_test_key[block_idx] && *p_odd == test_state[ODD_STATE]) {
|
// if (known_target_key != -1 && bucket_contains_test_key[block_idx] && *p_odd == test_state[ODD_STATE]) {
|
||||||
// printf("Now testing known target key.\n");
|
// PrintAndLogEx(INFO, "Now testing known target key.");
|
||||||
// printf("block_idx = %d/%d\n", block_idx, bitsliced_blocks);
|
// PrintAndLogEx(INFO, "block_idx = %d/%d", block_idx, bitsliced_blocks);
|
||||||
// }
|
// }
|
||||||
#endif
|
#endif
|
||||||
// add the even state bits
|
// add the even state bits
|
||||||
|
@ -444,8 +444,8 @@ uint64_t CRACK_STATES_BITSLICED(uint32_t cuid, uint8_t *best_first_bytes, statel
|
||||||
#endif
|
#endif
|
||||||
#ifdef DEBUG_KEY_ELIMINATION
|
#ifdef DEBUG_KEY_ELIMINATION
|
||||||
if (known_target_key != -1 && bucket_contains_test_key[block_idx] && *p_odd == test_state[ODD_STATE]) {
|
if (known_target_key != -1 && bucket_contains_test_key[block_idx] && *p_odd == test_state[ODD_STATE]) {
|
||||||
printf("Known target key eliminated in brute_force.\n");
|
PrintAndLogEx(INFO, "Known target key eliminated in brute_force.");
|
||||||
printf("block_idx = %d/%d, nonce = %d/%d\n", block_idx, bitsliced_blocks, tests, nonces_to_bruteforce);
|
PrintAndLogEx(INFO, "block_idx = %d/%d, nonce = %d/%d", block_idx, bitsliced_blocks, tests, nonces_to_bruteforce);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
goto stop_tests;
|
goto stop_tests;
|
||||||
|
@ -495,15 +495,15 @@ uint64_t CRACK_STATES_BITSLICED(uint32_t cuid, uint8_t *best_first_bytes, statel
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_KEY_ELIMINATION
|
#ifdef DEBUG_KEY_ELIMINATION
|
||||||
if (known_target_key != -1 && *p_even_test == test_state[EVEN_STATE] && *p_odd == test_state[ODD_STATE]) {
|
if (known_target_key != -1 && *p_even_test == test_state[EVEN_STATE] && *p_odd == test_state[ODD_STATE]) {
|
||||||
printf("Known target key eliminated in brute_force verification.\n");
|
PrintAndLogEx(INFO, "Known target key eliminated in brute_force verification.");
|
||||||
printf("block_idx = %d/%d\n", block_idx, bitsliced_blocks);
|
PrintAndLogEx(INFO, "block_idx = %d/%d", block_idx, bitsliced_blocks);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_KEY_ELIMINATION
|
#ifdef DEBUG_KEY_ELIMINATION
|
||||||
if (known_target_key != -1 && *p_even_test == test_state[EVEN_STATE] && *p_odd == test_state[ODD_STATE]) {
|
if (known_target_key != -1 && *p_even_test == test_state[EVEN_STATE] && *p_odd == test_state[ODD_STATE]) {
|
||||||
printf("Known target key eliminated in brute_force (results_bit == 0).\n");
|
PrintAndLogEx(INFO, "Known target key eliminated in brute_force (results_bit == 0).");
|
||||||
printf("block_idx = %d/%d\n", block_idx, bitsliced_blocks);
|
PrintAndLogEx(INFO, "block_idx = %d/%d", block_idx, bitsliced_blocks);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
results64 >>= 1;
|
results64 >>= 1;
|
||||||
|
@ -533,7 +533,7 @@ out:
|
||||||
|
|
||||||
#if defined (DEBUG_BRUTE_FORCE)
|
#if defined (DEBUG_BRUTE_FORCE)
|
||||||
for (uint32_t i = 0; i < MAX_ELIMINATION_STEP; i++) {
|
for (uint32_t i = 0; i < MAX_ELIMINATION_STEP; i++) {
|
||||||
printf("Eliminated after %2u test_bytes: %5.2f%%\n", i + 1, (float)keys_eliminated[i] / bucket_states_tested * 100);
|
PrintAndLogEx(INFO, "Eliminated after %2u test_bytes: %5.2f%%", i + 1, (float)keys_eliminated[i] / bucket_states_tested * 100);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return key;
|
return key;
|
||||||
|
|
|
@ -1115,3 +1115,21 @@ fe04ecfe5577
|
||||||
C1E51C63B8F5 # RATB key
|
C1E51C63B8F5 # RATB key
|
||||||
1DB710648A65
|
1DB710648A65
|
||||||
18F34C92A56E # E-GO card key
|
18F34C92A56E # E-GO card key
|
||||||
|
#
|
||||||
|
# Library Card MFP - SL1
|
||||||
|
4a832584637d
|
||||||
|
ca679d6291b0
|
||||||
|
30d9690fc5bc
|
||||||
|
5296c26109d4
|
||||||
|
e77952748484
|
||||||
|
91c2376005a1
|
||||||
|
30b7680b2bc9
|
||||||
|
e2a9e88bfe16
|
||||||
|
43b04995d234
|
||||||
|
aade86b1f9c1
|
||||||
|
5ea088c824c9
|
||||||
|
c67beb41ffbf
|
||||||
|
5ea088c824c9
|
||||||
|
c67beb41ffbf
|
||||||
|
b84d52971107
|
||||||
|
52b0d3f6116e
|
||||||
|
|
431
client/luascripts/mfc_gen3_writer.lua
Normal file
431
client/luascripts/mfc_gen3_writer.lua
Normal file
|
@ -0,0 +1,431 @@
|
||||||
|
local utils = require('utils')
|
||||||
|
local getopt = require('getopt')
|
||||||
|
local cmds = require('commands')
|
||||||
|
local read14a = require('read14a')
|
||||||
|
--
|
||||||
|
---
|
||||||
|
-------------------------------
|
||||||
|
-- Notes
|
||||||
|
-------------------------------
|
||||||
|
---
|
||||||
|
--
|
||||||
|
--[[
|
||||||
|
---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.
|
||||||
|
--- 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.
|
||||||
|
--]]
|
||||||
|
--
|
||||||
|
---
|
||||||
|
-------------------------------
|
||||||
|
-- Script hat
|
||||||
|
-------------------------------
|
||||||
|
---
|
||||||
|
--
|
||||||
|
copyright = 'RRG Team'
|
||||||
|
author = 'Winds'
|
||||||
|
version = 'v1.0.0'
|
||||||
|
desc = [[
|
||||||
|
This script gives you an easy way to write your *.eml dumps into normal MIFARE Classic 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.
|
||||||
|
|
||||||
|
Author Youtube channel: https://yev.ooo/
|
||||||
|
|
||||||
|
Many Thanks,
|
||||||
|
Best Regards
|
||||||
|
]]
|
||||||
|
example = [[
|
||||||
|
1. script run mfc_gen3_writer
|
||||||
|
]]
|
||||||
|
usage = [[
|
||||||
|
Give script to know if you uses an Windows OS
|
||||||
|
Select your *.eml dump from list to write to the card.
|
||||||
|
Follow the wizard.
|
||||||
|
]]
|
||||||
|
--
|
||||||
|
---
|
||||||
|
-------------------------------
|
||||||
|
-- Global variables
|
||||||
|
-------------------------------
|
||||||
|
---
|
||||||
|
--
|
||||||
|
local DEBUG = false -- the debug flag
|
||||||
|
local dumpEML -- Find all *.EML files
|
||||||
|
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)
|
||||||
|
local empty = string.rep('0', 32) -- Writing blocks
|
||||||
|
local default_key = 'FFFFFFFFFFFF' -- Writing blocks
|
||||||
|
local default_key_type = '01' --KeyA: 00, KeyB: 01
|
||||||
|
local default_key_blk = 'FFFFFFFFFFFF7C378800FFFFFFFFFFFF' -- Writing blocks
|
||||||
|
local piswords_uid_lock = 'hf 14a raw -s -c -t 2000 90fd111100'
|
||||||
|
local piswords_uid_change = 'hf 14a raw -s -c -t 2000 90f0cccc10'
|
||||||
|
local cmd_wrbl_a = 'hf mf wrbl %d A %s %s' -- Writing blocks by A key
|
||||||
|
local cmd_wrbl_b = 'hf mf wrbl %d B %s %s' -- Writing blocks by B key
|
||||||
|
--
|
||||||
|
---
|
||||||
|
-------------------------------
|
||||||
|
-- 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
|
||||||
|
--
|
||||||
|
---
|
||||||
|
-------------------------------
|
||||||
|
-- Return key code 00/01 to string
|
||||||
|
-------------------------------
|
||||||
|
---
|
||||||
|
--
|
||||||
|
local function KeyAB()
|
||||||
|
if default_key_type == '00' then
|
||||||
|
return 'KeyA'
|
||||||
|
else
|
||||||
|
return 'KeyB'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--
|
||||||
|
---
|
||||||
|
-------------------------------
|
||||||
|
-- Check response from Proxmark
|
||||||
|
-------------------------------
|
||||||
|
---
|
||||||
|
--
|
||||||
|
local function getblockdata(response)
|
||||||
|
if response.Status == 0 then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--
|
||||||
|
---
|
||||||
|
-------------------------------
|
||||||
|
-- Check 0xFFFFFFFFFFFF key for tag (MFC)
|
||||||
|
-------------------------------
|
||||||
|
---
|
||||||
|
--
|
||||||
|
local function checkkey()
|
||||||
|
local status = 0
|
||||||
|
for i = 1, #eml do
|
||||||
|
cmd = Command:newNG{cmd = cmds.CMD_HF_MIFARE_READBL, data = ('%02x%02x%s'):format((i-1), default_key_type, default_key)}
|
||||||
|
if (getblockdata(cmd:sendNG(false)) == true) then
|
||||||
|
status = status + 1
|
||||||
|
print(('%s %02s %s %s %s'):format(' ', (i-1), KeyAB(), default_key, 'OK'))
|
||||||
|
else
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if status == #eml then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--
|
||||||
|
---
|
||||||
|
-------------------------------
|
||||||
|
-- Check user input A or B for blank tag (MFC)
|
||||||
|
-------------------------------
|
||||||
|
---
|
||||||
|
--
|
||||||
|
local function check_user_key(user_key_type)
|
||||||
|
if user_key_type == 'A' then
|
||||||
|
return cmd_wrbl_a
|
||||||
|
elseif user_key_type == 'B' then
|
||||||
|
return cmd_wrbl_b
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--
|
||||||
|
---
|
||||||
|
-------------------------------
|
||||||
|
-- Main function
|
||||||
|
-------------------------------
|
||||||
|
---
|
||||||
|
--
|
||||||
|
local function main(args)
|
||||||
|
--
|
||||||
|
---
|
||||||
|
-------------------------------
|
||||||
|
-- Arguments for 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
|
||||||
|
--
|
||||||
|
wait()
|
||||||
|
print(tab)
|
||||||
|
--
|
||||||
|
---
|
||||||
|
-------------------------------
|
||||||
|
-- Detect 7/4 byte card
|
||||||
|
-------------------------------
|
||||||
|
---
|
||||||
|
--
|
||||||
|
if (utils.confirm(' Are you use a Windwos OS ?') == true) then
|
||||||
|
dumpEML = 'find "." "*dump.eml"'
|
||||||
|
if string.len(GetUID()) == 14 then
|
||||||
|
eml_file_uid_start = 18
|
||||||
|
eml_file_uid_end = 31
|
||||||
|
eml_file_lengt = 40
|
||||||
|
else
|
||||||
|
eml_file_uid_start = 18
|
||||||
|
eml_file_uid_end = 25
|
||||||
|
eml_file_lengt = 34
|
||||||
|
end
|
||||||
|
else
|
||||||
|
dumpEML = "find '.' -iname '*dump.eml' -type f"
|
||||||
|
if string.len(GetUID()) == 14 then
|
||||||
|
eml_file_uid_start = 9
|
||||||
|
eml_file_uid_end = 22
|
||||||
|
eml_file_lengt = 31
|
||||||
|
else
|
||||||
|
eml_file_uid_start = 9
|
||||||
|
eml_file_uid_end = 16
|
||||||
|
eml_file_lengt = 25
|
||||||
|
end
|
||||||
|
end
|
||||||
|
print(tab)
|
||||||
|
dropfield()
|
||||||
|
--
|
||||||
|
---
|
||||||
|
-------------------------------
|
||||||
|
-- List all EML files in /client
|
||||||
|
-------------------------------
|
||||||
|
---
|
||||||
|
--
|
||||||
|
local p = assert(io.popen(dumpEML))
|
||||||
|
for _ in p:lines() do
|
||||||
|
-- The length of eml file
|
||||||
|
if string.len(_) == eml_file_lengt then
|
||||||
|
num_dumps = num_dumps + 1
|
||||||
|
-- cut UID from eml file
|
||||||
|
files[num_dumps] = string.sub(_, eml_file_uid_start, eml_file_uid_end) -- cut numeretic UID
|
||||||
|
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 uid_no = tonumber(io.read())
|
||||||
|
print(tab)
|
||||||
|
print(' You have been selected card dump No ' .. uid_no .. ', with UID: ' .. files[uid_no] .. '. Your card UID: ' .. GetUID())
|
||||||
|
--
|
||||||
|
--
|
||||||
|
---
|
||||||
|
-------------------------------
|
||||||
|
-- Load eml file
|
||||||
|
-------------------------------
|
||||||
|
---
|
||||||
|
--
|
||||||
|
local dumpfile = assert(io.open('hf-mf-' .. files[uid_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(piswords_uid_change .. 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(piswords_uid_lock)
|
||||||
|
end
|
||||||
|
--
|
||||||
|
print(tab)
|
||||||
|
print(' Going to check the all ' .. KeyAB() .. ' by ' .. default_key)
|
||||||
|
print(tab)
|
||||||
|
--
|
||||||
|
if checkkey() == true then
|
||||||
|
print(tab)
|
||||||
|
if (utils.confirm(' Card is Empty. Write selected dump to card ?') == true) then
|
||||||
|
for i = 1, #eml do
|
||||||
|
core.console(string.format(cmd_wrbl_b, (i-1), default_key, eml[i]))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print(tab)
|
||||||
|
if (utils.confirm(' It this is a new blank card ? Do you wishing to change Access Conditions to using B key ' .. default_key .. ' as main ?') == true) then
|
||||||
|
print(tab)
|
||||||
|
print(' With one key type we will use, A or B ?')
|
||||||
|
print(tab)
|
||||||
|
io.write(' --> ')
|
||||||
|
local user_key_type = tostring(io.read())
|
||||||
|
print(tab)
|
||||||
|
print(' Enter 12 HEX chars of the key for access to card. By default ' .. default_key .. '.')
|
||||||
|
print(tab)
|
||||||
|
io.write(' --> ')
|
||||||
|
local user_key_input = tostring(io.read())
|
||||||
|
wait()
|
||||||
|
for i = 1, #eml do
|
||||||
|
if (i % 4 == 0) then
|
||||||
|
core.console(string.format(check_user_key(user_key_type), (i-1), user_key_input, default_key_blk))
|
||||||
|
else
|
||||||
|
core.console(string.format(check_user_key(user_key_type), (i-1), user_key_input, empty))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print(tab)
|
||||||
|
if (utils.confirm(' Write selected dump to card ?') == true) then
|
||||||
|
print(tab)
|
||||||
|
wait()
|
||||||
|
for i = 1, #eml do
|
||||||
|
core.console(string.format(cmd_wrbl_b, (i-1), b_keys[i], 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_b, (i-1), b_keys[i], default_key_blk))
|
||||||
|
else
|
||||||
|
core.console(string.format(cmd_wrbl_b, (i-1), b_keys[i], empty))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
dropfield()
|
||||||
|
print(tab)
|
||||||
|
print('You are welcome')
|
||||||
|
end
|
||||||
|
--
|
||||||
|
---
|
||||||
|
-------------------------------
|
||||||
|
-- Start Main function
|
||||||
|
-------------------------------
|
||||||
|
---
|
||||||
|
--
|
||||||
|
main(args)
|
|
@ -9,7 +9,7 @@ local floor = math.floor
|
||||||
|
|
||||||
copyright = ''
|
copyright = ''
|
||||||
author = "Iceman"
|
author = "Iceman"
|
||||||
version = 'v1.0.3'
|
version = 'v1.0.4'
|
||||||
desc =[[
|
desc =[[
|
||||||
This script will program a T55x7 TAG with a configuration and four blocks of data.
|
This script will program a T55x7 TAG with a configuration and four blocks of data.
|
||||||
It will then try to detect and read back those block data and compare if read data matches the expected data.
|
It will then try to detect and read back those block data and compare if read data matches the expected data.
|
||||||
|
@ -106,36 +106,93 @@ local function GetConfigs( modulation )
|
||||||
local t = {}
|
local t = {}
|
||||||
|
|
||||||
t['PSK1'] = {
|
t['PSK1'] = {
|
||||||
[1] = '00001040',
|
-- Rf2
|
||||||
[2] = '00041040',
|
[1] = '00001040', -- 8
|
||||||
[3] = '00081040',
|
[2] = '00041040', -- 16
|
||||||
[4] = '000c1040',
|
[3] = '00081040', -- 32
|
||||||
[5] = '00101040',
|
[4] = '000c1040', -- 40
|
||||||
[6] = '00141040',
|
[5] = '00101040', -- 50
|
||||||
[7] = '00181040',
|
[6] = '00141040', -- 64
|
||||||
[8] = '001c1040',
|
[7] = '00181040', -- 100
|
||||||
|
[8] = '001c1040', -- 128
|
||||||
|
-- Rf4
|
||||||
|
[9] = '00001440', -- 8
|
||||||
|
[10] = '00041440', -- 16
|
||||||
|
[11] = '00081440', -- 32
|
||||||
|
[12] = '000c1440', -- 40
|
||||||
|
-- [] = '00101440', -- 50 50/4 == 12.5 invalid
|
||||||
|
[13] = '00141440', -- 64
|
||||||
|
[14] = '00181440', -- 100
|
||||||
|
[15] = '001c1440', -- 128
|
||||||
|
-- Rf8
|
||||||
|
[16] = '00001840', -- 8
|
||||||
|
[17] = '00041840', -- 16
|
||||||
|
[18] = '00081840', -- 32
|
||||||
|
[19] = '000c1840', -- 40
|
||||||
|
-- [] = '00101840', -- 50 50/8 = 6.25 invalid
|
||||||
|
[20] = '00141840', -- 64
|
||||||
|
-- [] = '00181840', -- 100 100/8 == 12.5 invalid
|
||||||
|
[21] = '001c1840', -- 128
|
||||||
}
|
}
|
||||||
|
|
||||||
t['PSK2'] = {
|
t['PSK2'] = {
|
||||||
[1] = '00002040',
|
-- Rf2
|
||||||
[2] = '00042040',
|
[1] = '00002040', -- 8
|
||||||
[3] = '00082040',
|
[2] = '00042040', -- 16
|
||||||
[4] = '000c2040',
|
[3] = '00082040', -- 32
|
||||||
[5] = '00102040',
|
[4] = '000c2040', -- 40
|
||||||
[6] = '00142040',
|
[5] = '00102040', -- 50
|
||||||
[7] = '00182040',
|
[6] = '00142040', -- 64
|
||||||
[8] = '001c2040',
|
[7] = '00182040', -- 100
|
||||||
|
[8] = '001c2040', -- 128
|
||||||
|
-- Rf4
|
||||||
|
[9] = '00002440', -- 8
|
||||||
|
[10] = '00042440', -- 16
|
||||||
|
[11] = '00082440', -- 32
|
||||||
|
[12] = '000c2440', -- 40
|
||||||
|
-- [] = '00102440', -- 50 50/4 == 12.5 invalid
|
||||||
|
[13] = '00142440', -- 64
|
||||||
|
[14] = '00182440', -- 100
|
||||||
|
[15] = '001c2440', -- 128
|
||||||
|
-- Rf8
|
||||||
|
[16] = '00002840', -- 8
|
||||||
|
[17] = '00042840', -- 16
|
||||||
|
[18] = '00082840', -- 32
|
||||||
|
[19] = '000c2840', -- 40
|
||||||
|
-- [] = '00102840', -- 50 50/8 == 6.25 invalid
|
||||||
|
[20] = '00142840', -- 64
|
||||||
|
-- [] = '00182840', -- 100 100/8 == 12.5 invalid
|
||||||
|
[21] = '001c2840', -- 128
|
||||||
}
|
}
|
||||||
|
|
||||||
t['PSK3'] = {
|
t['PSK3'] = {
|
||||||
[1] = '00003040',
|
-- Rf2
|
||||||
[2] = '00043040',
|
[1] = '00003040', -- 8
|
||||||
[3] = '00083040',
|
[2] = '00043040', -- 16
|
||||||
[4] = '000c3040',
|
[3] = '00083040', -- 32
|
||||||
[5] = '00103040',
|
[4] = '000c3040', -- 40
|
||||||
[6] = '00143040',
|
[5] = '00103040', -- 50
|
||||||
[7] = '00183040',
|
[6] = '00143040', -- 64
|
||||||
[8] = '001c3040',
|
[7] = '00183040', -- 100
|
||||||
|
[8] = '001c3040', -- 128
|
||||||
|
-- Rf4
|
||||||
|
[9] = '00003440', -- 8
|
||||||
|
[10] = '00043440', -- 16
|
||||||
|
[11] = '00083440', -- 32
|
||||||
|
[12] = '000c3440', -- 40
|
||||||
|
-- [] = '00103440', -- 50 50/4 == 12.5 invalid
|
||||||
|
[13] = '00143440', -- 64
|
||||||
|
[14] = '00183440', -- 100
|
||||||
|
[15] = '001c3440', -- 128
|
||||||
|
-- Rf2
|
||||||
|
[16] = '00003840', -- 8
|
||||||
|
[17] = '00043840', -- 16
|
||||||
|
[18] = '00083840', -- 32
|
||||||
|
[19] = '000c3840', -- 40
|
||||||
|
-- [] = '00103840', -- 50 50/8 == 6.25 invalid
|
||||||
|
[20] = '00143840', -- 64
|
||||||
|
-- [] = '00183840', -- 100 100/8 == 12.5 invalid
|
||||||
|
[21] = '001c3840', -- 128
|
||||||
}
|
}
|
||||||
|
|
||||||
t['FSK1'] = {
|
t['FSK1'] = {
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include <stdlib.h> // size_t
|
#include <stdlib.h> // size_t
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h> // tolower
|
#include <ctype.h> // tolower
|
||||||
#include <stdio.h> // printf
|
//#include <stdio.h> // printf
|
||||||
#include "commonutil.h" // reflect...
|
#include "commonutil.h" // reflect...
|
||||||
#include "comms.h" // clearCommandBuffer
|
#include "comms.h" // clearCommandBuffer
|
||||||
#include "cmdparser.h" // command_t
|
#include "cmdparser.h" // command_t
|
||||||
|
@ -914,16 +914,33 @@ static int CmdAnalyseDemodBuffer(const char *Cmd) {
|
||||||
if (c == '0')
|
if (c == '0')
|
||||||
DemodBuffer[i] = 0;
|
DemodBuffer[i] = 0;
|
||||||
|
|
||||||
printf("%c", c);
|
PrintAndLogEx(NORMAL, "%c" NOLF, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
DemodBufferLen = len;
|
DemodBufferLen = len;
|
||||||
free(data);
|
free(data);
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int CmdAnalyseFreq(const char *Cmd) {
|
||||||
|
|
||||||
|
// char cmdp = tolower(param_getchar(Cmd, 0));
|
||||||
|
// if (strlen(Cmd) == 0 || cmdp == 'h') return usage_analyse_freq();
|
||||||
|
|
||||||
|
const double c = 299792458;
|
||||||
|
double len_125 = c / 125000;
|
||||||
|
double len_134 = c / 134000;
|
||||||
|
double len_1356 = c / 13560000;
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "Wavelengths");
|
||||||
|
PrintAndLogEx(INFO, " 125 kHz has %f meters", len_125);
|
||||||
|
PrintAndLogEx(INFO, " 134 kHz has %f meters", len_134);
|
||||||
|
PrintAndLogEx(INFO, " 13.56 mHz has %f meters", len_1356);
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static command_t CommandTable[] = {
|
static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||||
{"lcr", CmdAnalyseLCR, AlwaysAvailable, "Generate final byte for XOR LRC"},
|
{"lcr", CmdAnalyseLCR, AlwaysAvailable, "Generate final byte for XOR LRC"},
|
||||||
|
@ -935,6 +952,7 @@ static command_t CommandTable[] = {
|
||||||
{"a", CmdAnalyseA, AlwaysAvailable, "num bits test"},
|
{"a", CmdAnalyseA, AlwaysAvailable, "num bits test"},
|
||||||
{"nuid", CmdAnalyseNuid, AlwaysAvailable, "create NUID from 7byte UID"},
|
{"nuid", CmdAnalyseNuid, AlwaysAvailable, "create NUID from 7byte UID"},
|
||||||
{"demodbuff", CmdAnalyseDemodBuffer, AlwaysAvailable, "Load binary string to demodbuffer"},
|
{"demodbuff", CmdAnalyseDemodBuffer, AlwaysAvailable, "Load binary string to demodbuffer"},
|
||||||
|
{"freq", CmdAnalyseFreq, AlwaysAvailable, "Calc wave lengths"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2104,11 +2104,10 @@ static int Cmdhex2bin(const char *Cmd) {
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
//Uses printf instead of PrintAndLog since the latter adds linebreaks to each printout
|
|
||||||
for (int i = 0 ; i < 4 ; ++i)
|
for (int i = 0 ; i < 4 ; ++i)
|
||||||
printf("%d", (x >> (3 - i)) & 1);
|
PrintAndLogEx(NORMAL, "%d" NOLF, (x >> (3 - i)) & 1);
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "\n");
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ static int usage_hf_tune(void) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PROMPT_CLEARLINE PrintAndLogEx(INPLACE, " ")
|
#define PROMPT_CLEARLINE PrintAndLogEx(INPLACE, " \r")
|
||||||
|
|
||||||
int CmdHFSearch(const char *Cmd) {
|
int CmdHFSearch(const char *Cmd) {
|
||||||
|
|
||||||
|
@ -166,16 +166,16 @@ int CmdHFSearch(const char *Cmd) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
PROMPT_CLEARLINE;
|
PROMPT_CLEARLINE;
|
||||||
PrintAndLogEx(INPLACE, " Searching for FeliCa tag...");
|
PrintAndLogEx(INPLACE, " Searching for FeliCa tag...");
|
||||||
if (IfPm3Felica()) {
|
if (IfPm3Felica()) {
|
||||||
if (readFelicaUid(false) == PM3_SUCCESS) {
|
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;
|
res = PM3_SUCCESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
*/
|
||||||
*/
|
|
||||||
/*
|
/*
|
||||||
PROMPT_CLEARLINE;
|
PROMPT_CLEARLINE;
|
||||||
PrintAndLogEx(INPLACE, " Searching for CryptoRF tag...");
|
PrintAndLogEx(INPLACE, " Searching for CryptoRF tag...");
|
||||||
|
@ -190,10 +190,10 @@ int CmdHFSearch(const char *Cmd) {
|
||||||
PROMPT_CLEARLINE;
|
PROMPT_CLEARLINE;
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
|
|
||||||
PrintAndLogEx(INPLACE, _RED_("No known/supported 13.56 MHz tags found"));
|
PrintAndLogEx(WARNING, _RED_("No known/supported 13.56 MHz tags found"));
|
||||||
res = PM3_ESOFT;
|
res = PM3_ESOFT;
|
||||||
}
|
}
|
||||||
printf("\n");
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -168,6 +168,24 @@ const char *getTagInfo(uint8_t uid) {
|
||||||
static uint16_t frameLength = 0;
|
static uint16_t frameLength = 0;
|
||||||
uint16_t atsFSC[] = {16, 24, 32, 40, 48, 64, 96, 128, 256};
|
uint16_t atsFSC[] = {16, 24, 32, 40, 48, 64, 96, 128, 256};
|
||||||
|
|
||||||
|
static int usage_hf_14a_config(void) {
|
||||||
|
PrintAndLogEx(NORMAL, "Usage: hf 14a config [a 0|1|2] [b 0|1|2] [2 0|1|2] [3 0|1|2]");
|
||||||
|
PrintAndLogEx(NORMAL, "Options:");
|
||||||
|
PrintAndLogEx(NORMAL, " h This help");
|
||||||
|
PrintAndLogEx(NORMAL, " a 0|1|2 ATQA<>anticollision: 0=follow standard 1=execute anticol 2=skip anticol");
|
||||||
|
PrintAndLogEx(NORMAL, " b 0|1|2 BCC: 0=follow standard 1=use fixed BCC 2=use card BCC");
|
||||||
|
PrintAndLogEx(NORMAL, " 2 0|1|2 SAK<>CL2: 0=follow standard 1=execute CL2 2=skip CL2");
|
||||||
|
PrintAndLogEx(NORMAL, " 3 0|1|2 SAK<>CL3: 0=follow standard 1=execute CL3 2=skip CL3");
|
||||||
|
PrintAndLogEx(NORMAL, " r 0|1|2 SAK<>ATS: 0=follow standard 1=execute RATS 2=skip RATS");
|
||||||
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
|
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config ")" Print current configuration");
|
||||||
|
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 1 ")" Force execution of anticollision");
|
||||||
|
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 0 ")" Restore ATQA interpretation");
|
||||||
|
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config b 1 ")" Force fix of bad BCC in anticollision");
|
||||||
|
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config b 0 ")" Restore BCC check");
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static int usage_hf_14a_sim(void) {
|
static int usage_hf_14a_sim(void) {
|
||||||
// PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n");
|
// PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n");
|
||||||
PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 byte UID\n");
|
PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 byte UID\n");
|
||||||
|
@ -234,6 +252,162 @@ static int CmdHF14AList(const char *Cmd) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int hf14a_getconfig(hf14a_config *config) {
|
||||||
|
if (!session.pm3_present) return PM3_ENOTTY;
|
||||||
|
|
||||||
|
if (config == NULL)
|
||||||
|
return PM3_EINVARG;
|
||||||
|
|
||||||
|
clearCommandBuffer();
|
||||||
|
|
||||||
|
SendCommandNG(CMD_HF_ISO14443A_GET_CONFIG, NULL, 0);
|
||||||
|
PacketResponseNG resp;
|
||||||
|
if (!WaitForResponseTimeout(CMD_HF_ISO14443A_GET_CONFIG, &resp, 2000)) {
|
||||||
|
PrintAndLogEx(WARNING, "command execution time out");
|
||||||
|
return PM3_ETIMEOUT;
|
||||||
|
}
|
||||||
|
memcpy(config, resp.data.asBytes, sizeof(hf14a_config));
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hf14a_setconfig(hf14a_config *config) {
|
||||||
|
if (!session.pm3_present) return PM3_ENOTTY;
|
||||||
|
|
||||||
|
clearCommandBuffer();
|
||||||
|
if (config != NULL)
|
||||||
|
SendCommandNG(CMD_HF_ISO14443A_SET_CONFIG, (uint8_t *)config, sizeof(hf14a_config));
|
||||||
|
else
|
||||||
|
SendCommandNG(CMD_HF_ISO14443A_PRINT_CONFIG, NULL, 0);
|
||||||
|
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int CmdHf14AConfig(const char *Cmd) {
|
||||||
|
|
||||||
|
if (!session.pm3_present) return PM3_ENOTTY;
|
||||||
|
|
||||||
|
// if called with no params, just print the device config
|
||||||
|
if (strlen(Cmd) == 0) {
|
||||||
|
return hf14a_setconfig(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
hf14a_config config = {
|
||||||
|
.forceanticol = -1,
|
||||||
|
.forcebcc = -1,
|
||||||
|
.forcecl2 = -1,
|
||||||
|
.forcecl3 = -1,
|
||||||
|
.forcerats = -1
|
||||||
|
};
|
||||||
|
|
||||||
|
bool errors = false;
|
||||||
|
uint8_t cmdp = 0;
|
||||||
|
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||||
|
switch (param_getchar(Cmd, cmdp)) {
|
||||||
|
case 'h':
|
||||||
|
return usage_hf_14a_config();
|
||||||
|
case 'a':
|
||||||
|
switch (param_getchar(Cmd, cmdp + 1)) {
|
||||||
|
case '0':
|
||||||
|
config.forceanticol = 0;
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
config.forceanticol = 1;
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
config.forceanticol = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PrintAndLogEx(WARNING, "Unknown value '%c'", param_getchar(Cmd, cmdp + 1));
|
||||||
|
errors = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cmdp += 2;
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
switch (param_getchar(Cmd, cmdp + 1)) {
|
||||||
|
case '0':
|
||||||
|
config.forcebcc = 0;
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
config.forcebcc = 1;
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
config.forcebcc = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PrintAndLogEx(WARNING, "Unknown value '%c'", param_getchar(Cmd, cmdp + 1));
|
||||||
|
errors = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cmdp += 2;
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
switch (param_getchar(Cmd, cmdp + 1)) {
|
||||||
|
case '0':
|
||||||
|
config.forcecl2 = 0;
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
config.forcecl2 = 1;
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
config.forcecl2 = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PrintAndLogEx(WARNING, "Unknown value '%c'", param_getchar(Cmd, cmdp + 1));
|
||||||
|
errors = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cmdp += 2;
|
||||||
|
break;
|
||||||
|
case '3':
|
||||||
|
switch (param_getchar(Cmd, cmdp + 1)) {
|
||||||
|
case '0':
|
||||||
|
config.forcecl3 = 0;
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
config.forcecl3 = 1;
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
config.forcecl3 = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PrintAndLogEx(WARNING, "Unknown value '%c'", param_getchar(Cmd, cmdp + 1));
|
||||||
|
errors = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cmdp += 2;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
switch (param_getchar(Cmd, cmdp + 1)) {
|
||||||
|
case '0':
|
||||||
|
config.forcerats = 0;
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
config.forcerats = 1;
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
config.forcerats = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PrintAndLogEx(WARNING, "Unknown value '%c'", param_getchar(Cmd, cmdp + 1));
|
||||||
|
errors = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cmdp += 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||||
|
errors = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// validations
|
||||||
|
if (errors) return usage_hf_14a_config();
|
||||||
|
|
||||||
|
return hf14a_setconfig(&config);
|
||||||
|
}
|
||||||
|
|
||||||
int Hf14443_4aGetCardData(iso14a_card_select_t *card) {
|
int Hf14443_4aGetCardData(iso14a_card_select_t *card) {
|
||||||
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
|
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
|
||||||
|
|
||||||
|
@ -1241,6 +1415,7 @@ static command_t CommandTable[] = {
|
||||||
{"chaining", CmdHF14AChaining, IfPm3Iso14443a, "Control ISO 14443-4 input chaining"},
|
{"chaining", CmdHF14AChaining, IfPm3Iso14443a, "Control ISO 14443-4 input chaining"},
|
||||||
{"raw", CmdHF14ACmdRaw, IfPm3Iso14443a, "Send raw hex data to tag"},
|
{"raw", CmdHF14ACmdRaw, IfPm3Iso14443a, "Send raw hex data to tag"},
|
||||||
{"antifuzz", CmdHF14AAntiFuzz, IfPm3Iso14443a, "Fuzzing the anticollision phase. Warning! Readers may react strange"},
|
{"antifuzz", CmdHF14AAntiFuzz, IfPm3Iso14443a, "Fuzzing the anticollision phase. Warning! Readers may react strange"},
|
||||||
|
{"config", CmdHf14AConfig, IfPm3Iso14443a, "Configure 14a settings (use with caution)"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#define CMDHF14A_H__
|
#define CMDHF14A_H__
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "pm3_cmd.h" //hf14a_config
|
||||||
#include "mifare.h" // structs
|
#include "mifare.h" // structs
|
||||||
|
|
||||||
// structure and database for uid -> tagtype lookups
|
// structure and database for uid -> tagtype lookups
|
||||||
|
@ -26,6 +26,8 @@ int CmdHF14A(const char *Cmd);
|
||||||
int CmdHF14ASniff(const char *Cmd); // used by hf topaz sniff
|
int CmdHF14ASniff(const char *Cmd); // used by hf topaz sniff
|
||||||
int CmdHF14ASim(const char *Cmd); // used by hf mfu sim
|
int CmdHF14ASim(const char *Cmd); // used by hf mfu sim
|
||||||
|
|
||||||
|
int hf14a_getconfig(hf14a_config *config);
|
||||||
|
int hf14a_setconfig(hf14a_config *config);
|
||||||
int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search);
|
int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search);
|
||||||
const char *getTagInfo(uint8_t uid);
|
const char *getTagInfo(uint8_t uid);
|
||||||
int Hf14443_4aGetCardData(iso14a_card_select_t *card);
|
int Hf14443_4aGetCardData(iso14a_card_select_t *card);
|
||||||
|
|
|
@ -114,7 +114,7 @@ static int usage_hf_14b_dump(void) {
|
||||||
"Example:\n"
|
"Example:\n"
|
||||||
_YELLOW_("\thf 14b dump f\n")
|
_YELLOW_("\thf 14b dump f\n")
|
||||||
_YELLOW_("\thf 14b dump 2 f mydump")
|
_YELLOW_("\thf 14b dump 2 f mydump")
|
||||||
);
|
);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,7 +752,7 @@ static int CmdHF14BReadSri(const char *Cmd) {
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandMIX(CMD_HF_SRI_READ, blocks, 0, 0, NULL, 0);
|
SendCommandMIX(CMD_HF_SRI_READ, blocks, 0, 0, NULL, 0);
|
||||||
|
|
||||||
// iceman: should download read data and print in client.
|
// iceman: should download read data and print in client.
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -909,7 +909,7 @@ static int CmdHF14BDump(const char *Cmd) {
|
||||||
req[1] = blocknum;
|
req[1] = blocknum;
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_APPEND_CRC | ISO14B_RAW, 2, 0, req, sizeof(req));
|
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_APPEND_CRC | ISO14B_RAW, 2, 0, req, sizeof(req));
|
||||||
|
|
||||||
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000)) {
|
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000)) {
|
||||||
|
|
||||||
|
@ -940,17 +940,16 @@ static int CmdHF14BDump(const char *Cmd) {
|
||||||
blocknum = 0xFF;
|
blocknum = 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(".");
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
fflush(stdout);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
if (blocknum != 0xFF) {
|
if (blocknum != 0xFF) {
|
||||||
PrintAndLogEx(NORMAL, "\n Dump failed");
|
PrintAndLogEx(NORMAL, "Dump failed");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "block# | data | ascii");
|
PrintAndLogEx(NORMAL, "block# | data | ascii");
|
||||||
PrintAndLogEx(NORMAL, "---------+--------------+----------");
|
PrintAndLogEx(NORMAL, "---------+--------------+----------");
|
||||||
|
|
||||||
|
|
|
@ -420,7 +420,7 @@ static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) {
|
||||||
0x29, 0x29, 0xfd, 0xcd, 0x69, 0x8b, 0x34, 0x68, 0xf2
|
0x29, 0x29, 0xfd, 0xcd, 0x69, 0x8b, 0x34, 0x68, 0xf2
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
bool is_valid = false;
|
bool is_valid = false;
|
||||||
for (i = 0; i < ARRAYLEN(nxp_15693_public_keys); i++) {
|
for (i = 0; i < ARRAYLEN(nxp_15693_public_keys); i++) {
|
||||||
|
@ -526,7 +526,7 @@ static bool getUID(bool loop, uint8_t *buf) {
|
||||||
|
|
||||||
int resplen = resp.oldarg[0];
|
int resplen = resp.oldarg[0];
|
||||||
if (resplen >= 12 && CheckCrc15(resp.data.asBytes, 12)) {
|
if (resplen >= 12 && CheckCrc15(resp.data.asBytes, 12)) {
|
||||||
|
|
||||||
if (buf)
|
if (buf)
|
||||||
memcpy(buf, resp.data.asBytes + 2, 8);
|
memcpy(buf, resp.data.asBytes + 2, 8);
|
||||||
|
|
||||||
|
@ -990,7 +990,7 @@ static int CmdHF15Sniff(const char *Cmd) {
|
||||||
SendCommandNG(CMD_HF_ISO15693_SNIFF, NULL, 0);
|
SendCommandNG(CMD_HF_ISO15693_SNIFF, NULL, 0);
|
||||||
|
|
||||||
WaitForResponse(CMD_HF_ISO15693_SNIFF, &resp);
|
WaitForResponse(CMD_HF_ISO15693_SNIFF, &resp);
|
||||||
|
|
||||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf 15 list") "` to view captured tracelog");
|
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf 15 list") "` to view captured tracelog");
|
||||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save h") "` to save tracelog for later analysing");
|
PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save h") "` to save tracelog for later analysing");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
|
@ -1024,7 +1024,7 @@ static int CmdHF15Sim(const char *Cmd) {
|
||||||
|
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_HF_ISO15693_SIMULATE, (uint8_t*)&payload, sizeof(payload));
|
SendCommandNG(CMD_HF_ISO15693_SIMULATE, (uint8_t *)&payload, sizeof(payload));
|
||||||
WaitForResponse(CMD_HF_ISO15693_SIMULATE, &resp);
|
WaitForResponse(CMD_HF_ISO15693_SIMULATE, &resp);
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -1266,8 +1266,7 @@ static int CmdHF15Dump(const char *Cmd) {
|
||||||
retry = 0;
|
retry = 0;
|
||||||
blocknum++;
|
blocknum++;
|
||||||
|
|
||||||
printf(".");
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
fflush(stdout);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1359,7 +1358,7 @@ static int CmdHF15Raw(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandMIX(CMD_HF_ISO15693_COMMAND, datalen, fast, reply, data, datalen);
|
SendCommandMIX(CMD_HF_ISO15693_COMMAND, datalen, fast, reply, data, datalen);
|
||||||
|
|
||||||
if (reply) {
|
if (reply) {
|
||||||
|
@ -1443,7 +1442,7 @@ static int CmdHF15Readmulti(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *data = resp.data.asBytes;
|
uint8_t *data = resp.data.asBytes;
|
||||||
|
|
||||||
if (CheckCrc15(data, status) == false) {
|
if (CheckCrc15(data, status) == false) {
|
||||||
PrintAndLogEx(FAILED, "crc (" _RED_("fail") ")");
|
PrintAndLogEx(FAILED, "crc (" _RED_("fail") ")");
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
|
@ -1742,7 +1741,7 @@ static int CmdHF15Restore(const char *Cmd) {
|
||||||
}
|
}
|
||||||
free(data);
|
free(data);
|
||||||
PrintAndLogEx(INFO, "done");
|
PrintAndLogEx(INFO, "done");
|
||||||
PrintAndLogEx(HINT, "try `" _YELLOW_("hf 15 dump") "` to read your card to verify" );
|
PrintAndLogEx(HINT, "try `" _YELLOW_("hf 15 dump") "` to read your card to verify");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1780,10 +1779,10 @@ static int CmdHF15CSetUID(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "updating tag uid...");
|
PrintAndLogEx(INFO, "updating tag uid...");
|
||||||
|
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_HF_ISO15693_CSETUID, (uint8_t*)&payload, sizeof(payload));
|
SendCommandNG(CMD_HF_ISO15693_CSETUID, (uint8_t *)&payload, sizeof(payload));
|
||||||
|
|
||||||
if (WaitForResponseTimeout(CMD_HF_ISO15693_CSETUID, &resp, 2000) == false) {
|
if (WaitForResponseTimeout(CMD_HF_ISO15693_CSETUID, &resp, 2000) == false) {
|
||||||
PrintAndLogEx(WARNING, "timeout while waiting for reply");
|
PrintAndLogEx(WARNING, "timeout while waiting for reply");
|
||||||
|
@ -1800,10 +1799,10 @@ static int CmdHF15CSetUID(const char *Cmd) {
|
||||||
uint8_t revuid[8] = {0};
|
uint8_t revuid[8] = {0};
|
||||||
uint8_t i = 0;
|
uint8_t i = 0;
|
||||||
while (i < sizeof(revuid)) {
|
while (i < sizeof(revuid)) {
|
||||||
revuid[i] = carduid[7-i];
|
revuid[i] = carduid[7 - i];
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memcmp(revuid, payload.uid, 8) != 0) {
|
if (memcmp(revuid, payload.uid, 8) != 0) {
|
||||||
PrintAndLogEx(FAILED, "setting new UID (" _RED_("failed") ")");
|
PrintAndLogEx(FAILED, "setting new UID (" _RED_("failed") ")");
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
|
|
|
@ -59,7 +59,7 @@ static int usage_hf_cryptorf_sniff(void) {
|
||||||
}
|
}
|
||||||
static int usage_hf_cryptorf_sim(void) {
|
static int usage_hf_cryptorf_sim(void) {
|
||||||
PrintAndLogEx(NORMAL, "Emulating CryptoRF tag with emulator memory\n"
|
PrintAndLogEx(NORMAL, "Emulating CryptoRF tag with emulator memory\n"
|
||||||
"Usage: hf cryptorf sim [h] \n"
|
"Usage: hf cryptorf sim [h] \n"
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
" h this help\n"
|
" h this help\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
|
@ -26,16 +26,16 @@ static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
static int usage_epa_collect(void) {
|
static int usage_epa_collect(void) {
|
||||||
PrintAndLogEx(NORMAL, "Tries to collect nonces when doing part of PACE protocol.\n"
|
PrintAndLogEx(NORMAL, "Tries to collect nonces when doing part of PACE protocol.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Usage: hf epa cnonces <m> <n> <d>\n"
|
"Usage: hf epa cnonces <m> <n> <d>\n"
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
"\t<m> nonce size\n"
|
"\t<m> nonce size\n"
|
||||||
"\t<n> number of nonces to collect\n"
|
"\t<n> number of nonces to collect\n"
|
||||||
"\t<d> delay between\n"
|
"\t<d> delay between\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Example:\n"
|
"Example:\n"
|
||||||
_YELLOW_("\thf epa cnonces 4 4 1")
|
_YELLOW_("\thf epa cnonces 4 4 1")
|
||||||
);
|
);
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,18 +60,18 @@ static int CmdHFEPACollectPACENonces(const char *Cmd) {
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "Collecting %u %u byte nonces", n, m);
|
PrintAndLogEx(SUCCESS, "Collecting %u %u byte nonces", n, m);
|
||||||
PrintAndLogEx(SUCCESS, "Start: %" PRIu64, msclock() / 1000);
|
PrintAndLogEx(SUCCESS, "Start: %" PRIu64, msclock() / 1000);
|
||||||
|
|
||||||
struct p {
|
struct p {
|
||||||
uint32_t m;
|
uint32_t m;
|
||||||
} PACKED payload;
|
} PACKED payload;
|
||||||
payload.m = m;
|
payload.m = m;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < n; i++) {
|
for (uint32_t i = 0; i < n; i++) {
|
||||||
// execute PACE
|
// execute PACE
|
||||||
|
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_HF_EPA_COLLECT_NONCE, (uint8_t*)&payload, sizeof(payload));
|
SendCommandNG(CMD_HF_EPA_COLLECT_NONCE, (uint8_t *)&payload, sizeof(payload));
|
||||||
|
|
||||||
WaitForResponse(CMD_HF_EPA_COLLECT_NONCE, &resp);
|
WaitForResponse(CMD_HF_EPA_COLLECT_NONCE, &resp);
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ static int CmdHFEPACollectPACENonces(const char *Cmd) {
|
||||||
sleep(d);
|
sleep(d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "End: %" PRIu64, msclock() / 1000);
|
PrintAndLogEx(SUCCESS, "End: %" PRIu64, msclock() / 1000);
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1630,27 +1630,30 @@ static int CmdHFFelicaDumpLite(const char *Cmd) {
|
||||||
uint8_t timeout = 0;
|
uint8_t timeout = 0;
|
||||||
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||||
timeout++;
|
timeout++;
|
||||||
printf(".");
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
if (kbd_enter_pressed()) {
|
if (kbd_enter_pressed()) {
|
||||||
PrintAndLogEx(WARNING, "aborted via keyboard!\n");
|
PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_EOPABORTED;
|
return PM3_EOPABORTED;
|
||||||
}
|
}
|
||||||
if (timeout > 100) {
|
if (timeout > 10) {
|
||||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
PrintAndLogEx(WARNING, "\ntimeout while waiting for reply.");
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_ETIMEOUT;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
if (resp.oldarg[0] == 0) {
|
if (resp.oldarg[0] == 0) {
|
||||||
PrintAndLogEx(WARNING, "\nButton pressed. Aborted.");
|
PrintAndLogEx(WARNING, "Button pressed, aborted");
|
||||||
return PM3_EOPABORTED;
|
return PM3_EOPABORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t tracelen = resp.oldarg[1];
|
uint32_t tracelen = resp.oldarg[1];
|
||||||
if (tracelen == 0) {
|
if (tracelen == 0) {
|
||||||
PrintAndLogEx(WARNING, "\nNo trace data! Maybe not a FeliCa Lite card?");
|
PrintAndLogEx(WARNING, "No trace data! Maybe not a FeliCa Lite card?");
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,6 +97,18 @@ static int usage_hf_iclass_esave(void) {
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
static int usage_hf_iclass_eview(void) {
|
||||||
|
PrintAndLogEx(NORMAL, "It displays emulator memory");
|
||||||
|
PrintAndLogEx(NORMAL, "Number of bytes to download defaults to 256. Other value is 2048\n");
|
||||||
|
PrintAndLogEx(NORMAL, " Usage: hf iclass eview [s <num of bytes>] <v>");
|
||||||
|
PrintAndLogEx(NORMAL, " s <bytes> : (256|2048) number of bytes to save (default 256)");
|
||||||
|
PrintAndLogEx(NORMAL, " v : verbose output");
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
|
PrintAndLogEx(NORMAL, _YELLOW_(" hf iclass eview"));
|
||||||
|
PrintAndLogEx(NORMAL, _YELLOW_(" hf iclass eview s 2048 v"));
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
static int usage_hf_iclass_decrypt(void) {
|
static int usage_hf_iclass_decrypt(void) {
|
||||||
PrintAndLogEx(NORMAL, "3DES decrypt data\n");
|
PrintAndLogEx(NORMAL, "3DES decrypt data\n");
|
||||||
PrintAndLogEx(NORMAL, "This is naive implementation, it tries to decrypt every block after block 6.");
|
PrintAndLogEx(NORMAL, "This is naive implementation, it tries to decrypt every block after block 6.");
|
||||||
|
@ -376,7 +388,7 @@ static int cmp_uint32(const void *a, const void *b) {
|
||||||
return mx > my;
|
return mx > my;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_known_default(uint8_t *csn, uint8_t *epurse, uint8_t* rmac, uint8_t* tmac, uint8_t* key) {
|
bool check_known_default(uint8_t *csn, uint8_t *epurse, uint8_t *rmac, uint8_t *tmac, uint8_t *key) {
|
||||||
|
|
||||||
iclass_prekey_t *prekey = calloc(ICLASS_KEYS_MAX, sizeof(iclass_prekey_t));
|
iclass_prekey_t *prekey = calloc(ICLASS_KEYS_MAX, sizeof(iclass_prekey_t));
|
||||||
if (prekey == false) {
|
if (prekey == false) {
|
||||||
|
@ -387,14 +399,14 @@ bool check_known_default(uint8_t *csn, uint8_t *epurse, uint8_t* rmac, uint8_t*
|
||||||
memcpy(ccnr, epurse, 8);
|
memcpy(ccnr, epurse, 8);
|
||||||
memcpy(ccnr + 8, rmac, 4);
|
memcpy(ccnr + 8, rmac, 4);
|
||||||
|
|
||||||
GenerateMacKeyFrom(csn, ccnr, false, false, (uint8_t*)iClass_Key_Table, ICLASS_KEYS_MAX, prekey);
|
GenerateMacKeyFrom(csn, ccnr, false, false, (uint8_t *)iClass_Key_Table, ICLASS_KEYS_MAX, prekey);
|
||||||
qsort(prekey, ICLASS_KEYS_MAX, sizeof(iclass_prekey_t), cmp_uint32);
|
qsort(prekey, ICLASS_KEYS_MAX, sizeof(iclass_prekey_t), cmp_uint32);
|
||||||
|
|
||||||
iclass_prekey_t lookup;
|
iclass_prekey_t lookup;
|
||||||
memcpy(lookup.mac, tmac, 4);
|
memcpy(lookup.mac, tmac, 4);
|
||||||
|
|
||||||
// binsearch
|
// binsearch
|
||||||
iclass_prekey_t * item = (iclass_prekey_t *) bsearch(&lookup, prekey, ICLASS_KEYS_MAX, sizeof(iclass_prekey_t), cmp_uint32);
|
iclass_prekey_t *item = (iclass_prekey_t *) bsearch(&lookup, prekey, ICLASS_KEYS_MAX, sizeof(iclass_prekey_t), cmp_uint32);
|
||||||
if (item != NULL) {
|
if (item != NULL) {
|
||||||
memcpy(key, item->key, 8);
|
memcpy(key, item->key, 8);
|
||||||
return true;
|
return true;
|
||||||
|
@ -962,11 +974,10 @@ static int CmdHFiClassReader_Replay(const char *Cmd) {
|
||||||
SendCommandNG(CMD_HF_ICLASS_REPLAY, (uint8_t *)&payload, sizeof(payload));
|
SendCommandNG(CMD_HF_ICLASS_REPLAY, (uint8_t *)&payload, sizeof(payload));
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
printf(".");
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
fflush(stdout);
|
|
||||||
if (kbd_enter_pressed()) {
|
if (kbd_enter_pressed()) {
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
|
||||||
PrintAndLogEx(WARNING, "aborted via keyboard!\n");
|
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_EOPABORTED;
|
return PM3_EOPABORTED;
|
||||||
}
|
}
|
||||||
|
@ -975,6 +986,7 @@ static int CmdHFiClassReader_Replay(const char *Cmd) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
if (resp.status != PM3_SUCCESS) {
|
if (resp.status != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(ERR, "failed to communicate with card");
|
PrintAndLogEx(ERR, "failed to communicate with card");
|
||||||
return resp.status;
|
return resp.status;
|
||||||
|
@ -1175,7 +1187,7 @@ static int CmdHFiClassESave(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *dump = calloc(bytes, sizeof(uint8_t));
|
uint8_t *dump = calloc(bytes, sizeof(uint8_t));
|
||||||
if (!dump) {
|
if (dump == NULL) {
|
||||||
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
|
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
|
||||||
return PM3_EMALLOC;
|
return PM3_EMALLOC;
|
||||||
}
|
}
|
||||||
|
@ -1189,7 +1201,7 @@ static int CmdHFiClassESave(const char *Cmd) {
|
||||||
|
|
||||||
// user supplied filename?
|
// user supplied filename?
|
||||||
if (len < 1) {
|
if (len < 1) {
|
||||||
fnameptr += sprintf(fnameptr, "hf-iclass-");
|
fnameptr += snprintf(fnameptr, sizeof(filename), "hf-iclass-");
|
||||||
FillFileNameByUID(fnameptr, dump, "-dump", 8);
|
FillFileNameByUID(fnameptr, dump, "-dump", 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1202,6 +1214,88 @@ static int CmdHFiClassESave(const char *Cmd) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int CmdHFiClassEView(const char *Cmd) {
|
||||||
|
|
||||||
|
uint16_t blocks = 32, bytes = 256;
|
||||||
|
bool errors = false, verbose = false;
|
||||||
|
uint8_t cmdp = 0;
|
||||||
|
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||||
|
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||||
|
case 'h':
|
||||||
|
return usage_hf_iclass_eview();
|
||||||
|
case 's':
|
||||||
|
bytes = param_get32ex(Cmd, cmdp + 1, 256, 10);
|
||||||
|
|
||||||
|
if (bytes > 4096) {
|
||||||
|
PrintAndLogEx(WARNING, "Emulator memory is max 4096bytes. Truncating %u to 4096", bytes);
|
||||||
|
bytes = 4096;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes % 8 != 0) {
|
||||||
|
bytes &= 0xFFF8;
|
||||||
|
PrintAndLogEx(WARNING, "Number not divided by 8, truncating to %u", bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
blocks = bytes / 8;
|
||||||
|
cmdp += 2;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
verbose = true;
|
||||||
|
cmdp++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||||
|
errors = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Validations
|
||||||
|
if (errors || bytes == 0) {
|
||||||
|
return usage_hf_iclass_eview();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *dump = calloc(bytes, sizeof(uint8_t));
|
||||||
|
if (dump == NULL) {
|
||||||
|
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
|
||||||
|
return PM3_EMALLOC;
|
||||||
|
}
|
||||||
|
memset(dump, 0, bytes);
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "downloading from emulator memory");
|
||||||
|
if (!GetFromDevice(BIG_BUF_EML, dump, bytes, 0, NULL, 0, NULL, 2500, false)) {
|
||||||
|
PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
|
||||||
|
free(dump);
|
||||||
|
return PM3_ETIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
print_picopass_header((picopass_hdr *) dump);
|
||||||
|
print_picopass_info((picopass_hdr *) dump);
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
uint8_t *csn = dump;
|
||||||
|
PrintAndLogEx(INFO, "------+----+-------------------------+----------");
|
||||||
|
PrintAndLogEx(INFO, " CSN |0x00| " _GREEN_("%s") "|", sprint_hex(csn, 8));
|
||||||
|
printIclassDumpContents(dump, 1, blocks, bytes);
|
||||||
|
|
||||||
|
/*
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(INFO, "----+-------------------------+---------");
|
||||||
|
PrintAndLogEx(INFO, "blk | data | ascii");
|
||||||
|
PrintAndLogEx(INFO, "----+-------------------------+---------");
|
||||||
|
for (uint16_t i = 0; i < blocks; i++){
|
||||||
|
PrintAndLogEx(INFO, "%03d | %s ", i, sprint_hex_ascii(dump + (i * 8) , 8) );
|
||||||
|
}
|
||||||
|
PrintAndLogEx(INFO, "----+-------------------------+---------");
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
*/
|
||||||
|
free(dump);
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int CmdHFiClassDecrypt(const char *Cmd) {
|
static int CmdHFiClassDecrypt(const char *Cmd) {
|
||||||
|
|
||||||
bool errors = false;
|
bool errors = false;
|
||||||
|
@ -1408,7 +1502,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
|
||||||
|
|
||||||
uint64_t pin = bytes_to_num(decrypted + (8 * 9), 5);
|
uint64_t pin = bytes_to_num(decrypted + (8 * 9), 5);
|
||||||
char tmp[17] = {0};
|
char tmp[17] = {0};
|
||||||
sprintf(tmp, "%."PRIu64, BCD2DEC(pin));
|
snprintf(tmp, sizeof(tmp), "%."PRIu64, BCD2DEC(pin));
|
||||||
PrintAndLogEx(INFO, "PIN........................ " _GREEN_("%.*s"), pinsize, tmp);
|
PrintAndLogEx(INFO, "PIN........................ " _GREEN_("%.*s"), pinsize, tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1756,11 +1850,10 @@ static int CmdHFiClassDump(const char *Cmd) {
|
||||||
SendCommandNG(CMD_HF_ICLASS_DUMP, (uint8_t *)&payload, sizeof(payload));
|
SendCommandNG(CMD_HF_ICLASS_DUMP, (uint8_t *)&payload, sizeof(payload));
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
printf(".");
|
|
||||||
fflush(stdout);
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
if (kbd_enter_pressed()) {
|
if (kbd_enter_pressed()) {
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
|
||||||
PrintAndLogEx(WARNING, "aborted via keyboard!\n");
|
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_EOPABORTED;
|
return PM3_EOPABORTED;
|
||||||
}
|
}
|
||||||
|
@ -1769,6 +1862,7 @@ static int CmdHFiClassDump(const char *Cmd) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
if (resp.status != PM3_SUCCESS) {
|
if (resp.status != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(ERR, "failed to communicate with card");
|
PrintAndLogEx(ERR, "failed to communicate with card");
|
||||||
return resp.status;
|
return resp.status;
|
||||||
|
@ -1828,11 +1922,9 @@ static int CmdHFiClassDump(const char *Cmd) {
|
||||||
SendCommandNG(CMD_HF_ICLASS_DUMP, (uint8_t *)&payload, sizeof(payload));
|
SendCommandNG(CMD_HF_ICLASS_DUMP, (uint8_t *)&payload, sizeof(payload));
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
printf(".");
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
fflush(stdout);
|
|
||||||
if (kbd_enter_pressed()) {
|
if (kbd_enter_pressed()) {
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
|
||||||
PrintAndLogEx(WARNING, "aborted via keyboard!\n");
|
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_EOPABORTED;
|
return PM3_EOPABORTED;
|
||||||
}
|
}
|
||||||
|
@ -1840,7 +1932,7 @@ static int CmdHFiClassDump(const char *Cmd) {
|
||||||
if (WaitForResponseTimeout(CMD_HF_ICLASS_DUMP, &resp, 2000))
|
if (WaitForResponseTimeout(CMD_HF_ICLASS_DUMP, &resp, 2000))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
if (resp.status != PM3_SUCCESS) {
|
if (resp.status != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(ERR, "failed to communicate with card");
|
PrintAndLogEx(ERR, "failed to communicate with card");
|
||||||
goto write_dump;
|
goto write_dump;
|
||||||
|
@ -2155,7 +2247,7 @@ static int CmdHFiClassRestore(const char *Cmd) {
|
||||||
|
|
||||||
if (startblock < 5) {
|
if (startblock < 5) {
|
||||||
PrintAndLogEx(WARNING, "you cannot write key blocks this way. yet... make your start block > 4");
|
PrintAndLogEx(WARNING, "you cannot write key blocks this way. yet... make your start block > 4");
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
int total_bytes = (((endblock - startblock) + 1) * 12);
|
int total_bytes = (((endblock - startblock) + 1) * 12);
|
||||||
|
@ -2233,8 +2325,8 @@ static int CmdHFiClassRestore(const char *Cmd) {
|
||||||
for (i = 0; i <= endblock - startblock; i++) {
|
for (i = 0; i <= endblock - startblock; i++) {
|
||||||
memcpy(p, data + (i * 12), 12);
|
memcpy(p, data + (i * 12), 12);
|
||||||
char *s = calloc(70, sizeof(uint8_t));
|
char *s = calloc(70, sizeof(uint8_t));
|
||||||
sprintf(s, "| %s ", sprint_hex(p, 8));
|
snprintf(s, 70, "| %s ", sprint_hex(p, 8));
|
||||||
sprintf(s + strlen(s), "| %s", sprint_hex(p + 8, 4));
|
snprintf(s + strlen(s), 70 - strlen(s), "| %s", sprint_hex(p + 8, 4));
|
||||||
PrintAndLogEx(NORMAL, " %02X %s", i + startblock, s);
|
PrintAndLogEx(NORMAL, " %02X %s", i + startblock, s);
|
||||||
free(s);
|
free(s);
|
||||||
}
|
}
|
||||||
|
@ -3088,11 +3180,9 @@ static int CmdHFiClassCheckKeys(const char *Cmd) {
|
||||||
bool looped = false;
|
bool looped = false;
|
||||||
while (!WaitForResponseTimeout(CMD_HF_ICLASS_CHKKEYS, &resp, 2000)) {
|
while (!WaitForResponseTimeout(CMD_HF_ICLASS_CHKKEYS, &resp, 2000)) {
|
||||||
timeout++;
|
timeout++;
|
||||||
printf(".");
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
fflush(stdout);
|
|
||||||
if (timeout > 120) {
|
if (timeout > 120) {
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(WARNING, "\nNo response from Proxmark3. Aborting...");
|
||||||
PrintAndLogEx(WARNING, "No response from Proxmark3. Aborting...");
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
looped = true;
|
looped = true;
|
||||||
|
@ -3484,6 +3574,7 @@ static command_t CommandTable[] = {
|
||||||
{"sim", CmdHFiClassSim, IfPm3Iclass, "[options..] Simulate iCLASS tag"},
|
{"sim", CmdHFiClassSim, IfPm3Iclass, "[options..] Simulate iCLASS tag"},
|
||||||
{"eload", CmdHFiClassELoad, IfPm3Iclass, "[f <fn> ] Load Picopass / iCLASS dump file into emulator memory"},
|
{"eload", CmdHFiClassELoad, IfPm3Iclass, "[f <fn> ] Load Picopass / iCLASS dump file into emulator memory"},
|
||||||
{"esave", CmdHFiClassESave, IfPm3Iclass, "[f <fn> ] Save emulator memory to file"},
|
{"esave", CmdHFiClassESave, IfPm3Iclass, "[f <fn> ] Save emulator memory to file"},
|
||||||
|
{"eview", CmdHFiClassEView, IfPm3Iclass, "[options..] View emulator memory"},
|
||||||
|
|
||||||
{"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("utils") " ---------------------"},
|
{"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("utils") " ---------------------"},
|
||||||
{"calcnewkey", CmdHFiClassCalcNewKey, AlwaysAvailable, "[options..] Calc diversified keys (blocks 3 & 4) to write new keys"},
|
{"calcnewkey", CmdHFiClassCalcNewKey, AlwaysAvailable, "[options..] Calc diversified keys (blocks 3 & 4) to write new keys"},
|
||||||
|
|
|
@ -41,5 +41,5 @@ void PrintPreCalcMac(uint8_t *keys, uint32_t keycnt, iclass_premac_t *pre_list);
|
||||||
void PrintPreCalc(iclass_prekey_t *list, uint32_t itemcnt);
|
void PrintPreCalc(iclass_prekey_t *list, uint32_t itemcnt);
|
||||||
|
|
||||||
uint8_t get_pagemap(const picopass_hdr *hdr);
|
uint8_t get_pagemap(const picopass_hdr *hdr);
|
||||||
bool check_known_default(uint8_t *csn, uint8_t *epurse, uint8_t* rmac, uint8_t* tmac, uint8_t* key);
|
bool check_known_default(uint8_t *csn, uint8_t *epurse, uint8_t *rmac, uint8_t *tmac, uint8_t *key);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -145,7 +145,7 @@ static int usage_legic_eload(void) {
|
||||||
PrintAndLogEx(NORMAL, " f <filename> : filename w/o .bin to load");
|
PrintAndLogEx(NORMAL, " f <filename> : filename w/o .bin to load");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf legic eload 2 myfile"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" hf legic eload 2 f myfile"));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
static int usage_legic_esave(void) {
|
static int usage_legic_esave(void) {
|
||||||
|
@ -582,13 +582,39 @@ static int CmdLegicRdbl(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdLegicSim(const char *Cmd) {
|
static int CmdLegicSim(const char *Cmd) {
|
||||||
|
|
||||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||||
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_legic_sim();
|
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_legic_sim();
|
||||||
|
|
||||||
uint64_t id = 1;
|
struct {
|
||||||
sscanf(Cmd, " %" SCNi64, &id);
|
uint8_t tagtype;
|
||||||
|
bool send_reply;
|
||||||
|
} PACKED payload;
|
||||||
|
|
||||||
|
payload.send_reply = true;
|
||||||
|
payload.tagtype = param_get8ex(Cmd, 0, 1, 10);
|
||||||
|
if (payload.tagtype > 2) {
|
||||||
|
return usage_legic_sim();
|
||||||
|
}
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandMIX(CMD_HF_LEGIC_SIMULATE, id, 0, 0, NULL, 0);
|
SendCommandNG(CMD_HF_LEGIC_SIMULATE, (uint8_t *)&payload, sizeof(payload));
|
||||||
|
PacketResponseNG resp;
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "Press pm3-button to abort simulation");
|
||||||
|
bool keypress = kbd_enter_pressed();
|
||||||
|
while (keypress == false) {
|
||||||
|
keypress = kbd_enter_pressed();
|
||||||
|
|
||||||
|
if (WaitForResponseTimeout(CMD_HF_LEGIC_SIMULATE, &resp, 1500)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (keypress)
|
||||||
|
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "Done");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -709,16 +735,17 @@ static int CmdLegicWrbl(const char *Cmd) {
|
||||||
char *answer = readline(confirm);
|
char *answer = readline(confirm);
|
||||||
overwrite = (answer[0] == 'y' || answer[0] == 'Y');
|
overwrite = (answer[0] == 'y' || answer[0] == 'Y');
|
||||||
#else
|
#else
|
||||||
printf("%s", confirm);
|
PrintAndLogEx(NORMAL, "%s" NOLF, confirm);
|
||||||
char *answer = NULL;
|
char *answer = NULL;
|
||||||
size_t anslen = 0;
|
size_t anslen = 0;
|
||||||
if (getline(&answer, &anslen, stdin) > 0) {
|
if (getline(&answer, &anslen, stdin) > 0) {
|
||||||
overwrite = (answer[0] == 'y' || answer[0] == 'Y');
|
overwrite = (answer[0] == 'y' || answer[0] == 'Y');
|
||||||
}
|
}
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
#endif
|
#endif
|
||||||
free(answer);
|
free(answer);
|
||||||
if (!overwrite) {
|
if (overwrite == false) {
|
||||||
PrintAndLogEx(NORMAL, "command cancelled");
|
PrintAndLogEx(WARNING, "command cancelled");
|
||||||
return PM3_EOPABORTED;
|
return PM3_EOPABORTED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -731,18 +758,16 @@ static int CmdLegicWrbl(const char *Cmd) {
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandOLD(CMD_HF_LEGIC_WRITER, offset, len, IV, data, len);
|
SendCommandOLD(CMD_HF_LEGIC_WRITER, offset, len, IV, data, len);
|
||||||
|
|
||||||
|
|
||||||
uint8_t timeout = 0;
|
uint8_t timeout = 0;
|
||||||
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||||
++timeout;
|
++timeout;
|
||||||
printf(".");
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
fflush(stdout);
|
|
||||||
if (timeout > 7) {
|
if (timeout > 7) {
|
||||||
PrintAndLogEx(WARNING, "\ncommand execution time out");
|
PrintAndLogEx(WARNING, "\ncommand execution time out");
|
||||||
return PM3_ETIMEOUT;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "\n");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
uint8_t isOK = resp.oldarg[0] & 0xFF;
|
uint8_t isOK = resp.oldarg[0] & 0xFF;
|
||||||
if (!isOK) {
|
if (!isOK) {
|
||||||
|
@ -846,8 +871,7 @@ int legic_read_mem(uint32_t offset, uint32_t len, uint32_t iv, uint8_t *out, uin
|
||||||
uint8_t timeout = 0;
|
uint8_t timeout = 0;
|
||||||
while (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {
|
while (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {
|
||||||
++timeout;
|
++timeout;
|
||||||
printf(".");
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
fflush(stdout);
|
|
||||||
if (timeout > 14) {
|
if (timeout > 14) {
|
||||||
PrintAndLogEx(WARNING, "\ncommand execution time out");
|
PrintAndLogEx(WARNING, "\ncommand execution time out");
|
||||||
return PM3_ETIMEOUT;
|
return PM3_ETIMEOUT;
|
||||||
|
@ -990,14 +1014,13 @@ static int CmdLegicDump(const char *Cmd) {
|
||||||
uint8_t timeout = 0;
|
uint8_t timeout = 0;
|
||||||
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||||
++timeout;
|
++timeout;
|
||||||
printf(".");
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
fflush(stdout);
|
|
||||||
if (timeout > 7) {
|
if (timeout > 7) {
|
||||||
PrintAndLogEx(WARNING, "\ncommand execution time out");
|
PrintAndLogEx(WARNING, "\ncommand execution time out");
|
||||||
return PM3_ETIMEOUT;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "\n");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
uint8_t isOK = resp.oldarg[0] & 0xFF;
|
uint8_t isOK = resp.oldarg[0] & 0xFF;
|
||||||
if (!isOK) {
|
if (!isOK) {
|
||||||
|
@ -1025,7 +1048,7 @@ static int CmdLegicDump(const char *Cmd) {
|
||||||
// user supplied filename?
|
// user supplied filename?
|
||||||
if (fileNameLen < 1) {
|
if (fileNameLen < 1) {
|
||||||
PrintAndLogEx(INFO, "Using UID as filename");
|
PrintAndLogEx(INFO, "Using UID as filename");
|
||||||
fptr += sprintf(fptr, "hf-legic-");
|
fptr += snprintf(fptr, sizeof(filename), "hf-legic-");
|
||||||
FillFileNameByUID(fptr, data, "-dump", 4);
|
FillFileNameByUID(fptr, data, "-dump", 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1134,15 +1157,14 @@ static int CmdLegicRestore(const char *Cmd) {
|
||||||
uint8_t timeout = 0;
|
uint8_t timeout = 0;
|
||||||
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||||
++timeout;
|
++timeout;
|
||||||
printf(".");
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
fflush(stdout);
|
|
||||||
if (timeout > 7) {
|
if (timeout > 7) {
|
||||||
PrintAndLogEx(WARNING, "\ncommand execution time out");
|
PrintAndLogEx(WARNING, "\ncommand execution time out");
|
||||||
free(data);
|
free(data);
|
||||||
return PM3_ETIMEOUT;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "\n");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
uint8_t isOK = resp.oldarg[0] & 0xFF;
|
uint8_t isOK = resp.oldarg[0] & 0xFF;
|
||||||
if (!isOK) {
|
if (!isOK) {
|
||||||
|
@ -1300,7 +1322,7 @@ static int CmdLegicESave(const char *Cmd) {
|
||||||
// user supplied filename?
|
// user supplied filename?
|
||||||
if (fileNameLen < 1) {
|
if (fileNameLen < 1) {
|
||||||
PrintAndLogEx(INFO, "Using UID as filename");
|
PrintAndLogEx(INFO, "Using UID as filename");
|
||||||
fptr += sprintf(fptr, "hf-legic-");
|
fptr += snprintf(fptr, sizeof(filename), "hf-legic-");
|
||||||
FillFileNameByUID(fptr, data, "-dump", 4);
|
FillFileNameByUID(fptr, data, "-dump", 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1344,8 +1366,8 @@ static int CmdLegicWipe(const char *Cmd) {
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
for (size_t i = 7; i < card.cardsize; i += PM3_CMD_DATA_SIZE) {
|
for (size_t i = 7; i < card.cardsize; i += PM3_CMD_DATA_SIZE) {
|
||||||
|
|
||||||
printf(".");
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
fflush(stdout);
|
|
||||||
size_t len = MIN((card.cardsize - i), PM3_CMD_DATA_SIZE);
|
size_t len = MIN((card.cardsize - i), PM3_CMD_DATA_SIZE);
|
||||||
if (len == card.cardsize - i) {
|
if (len == card.cardsize - i) {
|
||||||
// Disable fast mode on last packet
|
// Disable fast mode on last packet
|
||||||
|
@ -1357,15 +1379,14 @@ static int CmdLegicWipe(const char *Cmd) {
|
||||||
uint8_t timeout = 0;
|
uint8_t timeout = 0;
|
||||||
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||||
++timeout;
|
++timeout;
|
||||||
printf(".");
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
fflush(stdout);
|
|
||||||
if (timeout > 7) {
|
if (timeout > 7) {
|
||||||
PrintAndLogEx(WARNING, "\ncommand execution time out");
|
PrintAndLogEx(WARNING, "\ncommand execution time out");
|
||||||
free(data);
|
free(data);
|
||||||
return PM3_ETIMEOUT;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "\n");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
uint8_t isOK = resp.oldarg[0] & 0xFF;
|
uint8_t isOK = resp.oldarg[0] & 0xFF;
|
||||||
if (!isOK) {
|
if (!isOK) {
|
||||||
|
|
|
@ -215,6 +215,9 @@ int applyIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
||||||
case ISO14443A_CMD_RATS:
|
case ISO14443A_CMD_RATS:
|
||||||
snprintf(exp, size, "RATS");
|
snprintf(exp, size, "RATS");
|
||||||
break;
|
break;
|
||||||
|
case ISO14443A_CMD_PPS:
|
||||||
|
snprintf(exp, size, "PPS");
|
||||||
|
break;
|
||||||
case ISO14443A_CMD_OPTS:
|
case ISO14443A_CMD_OPTS:
|
||||||
snprintf(exp, size, "OPTIONAL TIMESLOT");
|
snprintf(exp, size, "OPTIONAL TIMESLOT");
|
||||||
break;
|
break;
|
||||||
|
@ -336,7 +339,7 @@ void annotateIclass(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool
|
||||||
static uint8_t rmac[4];
|
static uint8_t rmac[4];
|
||||||
static uint8_t tmac[4];
|
static uint8_t tmac[4];
|
||||||
|
|
||||||
if ( isResponse == false ) {
|
if (isResponse == false) {
|
||||||
uint8_t c = cmd[0] & 0x0F;
|
uint8_t c = cmd[0] & 0x0F;
|
||||||
uint8_t parity = 0;
|
uint8_t parity = 0;
|
||||||
for (uint8_t i = 0; i < 7; i++) {
|
for (uint8_t i = 0; i < 7; i++) {
|
||||||
|
@ -406,17 +409,17 @@ void annotateIclass(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (curr_state == PICO_SELECT) {
|
if (curr_state == PICO_SELECT) {
|
||||||
memcpy(csn, cmd, 8);
|
memcpy(csn, cmd, 8);
|
||||||
curr_state = PICO_NONE;
|
curr_state = PICO_NONE;
|
||||||
} else if (curr_state == PICO_AUTH_EPURSE) {
|
} else if (curr_state == PICO_AUTH_EPURSE) {
|
||||||
memcpy(epurse, cmd, 8);
|
memcpy(epurse, cmd, 8);
|
||||||
} else if ( curr_state == PICO_AUTH_MACS) {
|
} else if (curr_state == PICO_AUTH_MACS) {
|
||||||
|
|
||||||
uint8_t key[8];
|
uint8_t key[8];
|
||||||
if (check_known_default(csn, epurse, rmac, tmac, key)) {
|
if (check_known_default(csn, epurse, rmac, tmac, key)) {
|
||||||
snprintf(exp, size, "( " _GREEN_("%s") ")", sprint_hex(key, 8) );
|
snprintf(exp, size, "( " _GREEN_("%s") ")", sprint_hex(key, 8));
|
||||||
}
|
}
|
||||||
curr_state = PICO_NONE;
|
curr_state = PICO_NONE;
|
||||||
}
|
}
|
||||||
|
@ -435,11 +438,11 @@ void annotateIso15693(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
||||||
snprintf(exp, size, "STAY_QUIET");
|
snprintf(exp, size, "STAY_QUIET");
|
||||||
return;
|
return;
|
||||||
case ISO15693_READBLOCK: {
|
case ISO15693_READBLOCK: {
|
||||||
|
|
||||||
uint8_t block = 0;
|
uint8_t block = 0;
|
||||||
if (cmdsize == 13)
|
if (cmdsize == 13)
|
||||||
block = cmd[10];
|
block = cmd[10];
|
||||||
|
|
||||||
snprintf(exp, size, "READBLOCK(%d)", block);
|
snprintf(exp, size, "READBLOCK(%d)", block);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -557,7 +560,7 @@ void annotateIso15693(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
||||||
|
|
||||||
if (cmd[1] > ISO15693_STAYQUIET && cmd[1] < ISO15693_READBLOCK) snprintf(exp, size, "Mandatory RFU");
|
if (cmd[1] > ISO15693_STAYQUIET && cmd[1] < ISO15693_READBLOCK) snprintf(exp, size, "Mandatory RFU");
|
||||||
else if (cmd[1] > ISO15693_READ_MULTI_SECSTATUS && cmd[1] <= 0x9F) snprintf(exp, size, "Optional RFU");
|
else if (cmd[1] > ISO15693_READ_MULTI_SECSTATUS && cmd[1] <= 0x9F) snprintf(exp, size, "Optional RFU");
|
||||||
// else if (cmd[1] >= 0xA0 && cmd[1] <= 0xDF) snprintf(exp, size, "Cust IC MFG dependent");
|
// else if (cmd[1] >= 0xA0 && cmd[1] <= 0xDF) snprintf(exp, size, "Cust IC MFG dependent");
|
||||||
else if (cmd[1] > ISO15693_READ_SIGNATURE && cmd[1] <= 0xDF) snprintf(exp, size, "Cust IC MFG dependent");
|
else if (cmd[1] > ISO15693_READ_SIGNATURE && cmd[1] <= 0xDF) snprintf(exp, size, "Cust IC MFG dependent");
|
||||||
else if (cmd[1] >= 0xE0) snprintf(exp, size, "Proprietary IC MFG dependent");
|
else if (cmd[1] >= 0xE0) snprintf(exp, size, "Proprietary IC MFG dependent");
|
||||||
else
|
else
|
||||||
|
@ -608,6 +611,10 @@ void annotateTopaz(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
||||||
|
|
||||||
// iso 7816-3
|
// iso 7816-3
|
||||||
void annotateIso7816(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
void annotateIso7816(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
||||||
|
|
||||||
|
if (cmdsize < 2)
|
||||||
|
return;
|
||||||
|
|
||||||
// S-block
|
// S-block
|
||||||
if ((cmd[0] & 0xC0) && (cmdsize == 3)) {
|
if ((cmd[0] & 0xC0) && (cmdsize == 3)) {
|
||||||
switch ((cmd[0] & 0x3f)) {
|
switch ((cmd[0] & 0x3f)) {
|
||||||
|
@ -715,7 +722,7 @@ void annotateIso7816(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
||||||
snprintf(exp, size, "GET RESPONSE");
|
snprintf(exp, size, "GET RESPONSE");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
snprintf(exp, size, "?");
|
//snprintf(exp, size, "?");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -992,13 +999,13 @@ void annotateCryptoRF(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
||||||
break;
|
break;
|
||||||
case CRYPTORF_DESELECT:
|
case CRYPTORF_DESELECT:
|
||||||
snprintf(exp, size, "DESELECT");
|
snprintf(exp, size, "DESELECT");
|
||||||
break;
|
break;
|
||||||
case CRYPTORF_IDLE:
|
case CRYPTORF_IDLE:
|
||||||
snprintf(exp, size, "IDLE");
|
snprintf(exp, size, "IDLE");
|
||||||
break;
|
break;
|
||||||
case CRYPTORF_CHECK_PASSWORD:
|
case CRYPTORF_CHECK_PASSWORD:
|
||||||
snprintf(exp, size, "CHECK PWD");
|
snprintf(exp, size, "CHECK PWD");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
snprintf(exp, size, "?");
|
snprintf(exp, size, "?");
|
||||||
break;
|
break;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -347,9 +347,9 @@ static char *getCardSizeStr(uint8_t fsize) {
|
||||||
|
|
||||||
// is LSB set?
|
// is LSB set?
|
||||||
if (fsize & 1)
|
if (fsize & 1)
|
||||||
sprintf(retStr, "0x%02X (" _YELLOW_("%d - %d bytes") ")", fsize, usize, lsize);
|
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("%d - %d bytes") ")", fsize, usize, lsize);
|
||||||
else
|
else
|
||||||
sprintf(retStr, "0x%02X (" _YELLOW_("%d bytes") ")", fsize, lsize);
|
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("%d bytes") ")", fsize, lsize);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,14 +359,14 @@ static char *getProtocolStr(uint8_t id, bool hw) {
|
||||||
char *retStr = buf;
|
char *retStr = buf;
|
||||||
|
|
||||||
if (id == 0x04) {
|
if (id == 0x04) {
|
||||||
sprintf(retStr, "0x%02X (" _YELLOW_("ISO 14443-3 MIFARE, 14443-4") ")", id);
|
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("ISO 14443-3 MIFARE, 14443-4") ")", id);
|
||||||
} else if (id == 0x05) {
|
} else if (id == 0x05) {
|
||||||
if (hw)
|
if (hw)
|
||||||
sprintf(retStr, "0x%02X (" _YELLOW_("ISO 14443-2, 14443-3") ")", id);
|
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("ISO 14443-2, 14443-3") ")", id);
|
||||||
else
|
else
|
||||||
sprintf(retStr, "0x%02X (" _YELLOW_("ISO 14443-3, 14443-4") ")", id);
|
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("ISO 14443-3, 14443-4") ")", id);
|
||||||
} else {
|
} else {
|
||||||
sprintf(retStr, "0x%02X (" _YELLOW_("Unknown") ")", id);
|
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("Unknown") ")", id);
|
||||||
}
|
}
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
@ -377,17 +377,17 @@ static char *getVersionStr(uint8_t major, uint8_t minor) {
|
||||||
char *retStr = buf;
|
char *retStr = buf;
|
||||||
|
|
||||||
if (major == 0x00)
|
if (major == 0x00)
|
||||||
sprintf(retStr, "%x.%x (" _YELLOW_("DESFire MF3ICD40") ")", major, minor);
|
snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("DESFire MF3ICD40") ")", major, minor);
|
||||||
else if (major == 0x01 && minor == 0x00)
|
else if (major == 0x01 && minor == 0x00)
|
||||||
sprintf(retStr, "%x.%x (" _YELLOW_("DESFire EV1") ")", major, minor);
|
snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("DESFire EV1") ")", major, minor);
|
||||||
else if (major == 0x12 && minor == 0x00)
|
else if (major == 0x12 && minor == 0x00)
|
||||||
sprintf(retStr, "%x.%x (" _YELLOW_("DESFire EV2") ")", major, minor);
|
snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("DESFire EV2") ")", major, minor);
|
||||||
else if (major == 0x33 && minor == 0x00)
|
else if (major == 0x33 && minor == 0x00)
|
||||||
sprintf(retStr, "%x.%x (" _YELLOW_("DESFire EV3") ")", major, minor);
|
snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("DESFire EV3") ")", major, minor);
|
||||||
else if (major == 0x30 && minor == 0x00)
|
else if (major == 0x30 && minor == 0x00)
|
||||||
sprintf(retStr, "%x.%x (" _YELLOW_("DESFire Light") ")", major, minor);
|
snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("DESFire Light") ")", major, minor);
|
||||||
else
|
else
|
||||||
sprintf(retStr, "%x.%x (" _YELLOW_("Unknown") ")", major, minor);
|
snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("Unknown") ")", major, minor);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3401,6 +3401,7 @@ static void DecodeComSet(uint8_t comset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DecodeAccessValue(uint8_t value) {
|
static char *DecodeAccessValue(uint8_t value) {
|
||||||
|
|
||||||
char *car = (char *)calloc(255, sizeof(char));
|
char *car = (char *)calloc(255, sizeof(char));
|
||||||
if (car == NULL)
|
if (car == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -3413,7 +3414,7 @@ static char *DecodeAccessValue(uint8_t value) {
|
||||||
strcat(car, "(Denied Access)");
|
strcat(car, "(Denied Access)");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sprintf(car, "(Access Key: %d)", value);
|
snprintf(car, 255, "(Access Key: %d)", value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return car;
|
return car;
|
||||||
|
@ -4364,7 +4365,7 @@ static int CmdHF14aDesChk(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!verbose)
|
if (!verbose)
|
||||||
printf("Search keys:\n");
|
PrintAndLogEx(INFO, "Search keys:");
|
||||||
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
uint8_t app_ids[78] = {0};
|
uint8_t app_ids[78] = {0};
|
||||||
|
@ -4382,25 +4383,29 @@ static int CmdHF14aDesChk(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t x = 0; x < app_ids_len / 3; x++) {
|
for (uint32_t 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);
|
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);
|
PrintAndLogEx(ERR, "Checking aid 0x%06X...", curaid);
|
||||||
|
|
||||||
res = AuthCheckDesfire(&app_ids[x * 3], deskeyList, deskeyListLen, aeskeyList, aeskeyListLen, k3kkeyList, k3kkeyListLen, foundKeys, &result);
|
res = AuthCheckDesfire(&app_ids[x * 3], deskeyList, deskeyListLen, aeskeyList, aeskeyListLen, k3kkeyList, k3kkeyListLen, foundKeys, &result);
|
||||||
if (res == PM3_EOPABORTED) {
|
if (res == PM3_EOPABORTED) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pattern2b && startPattern < 0x10000) {
|
if (pattern2b && startPattern < 0x10000) {
|
||||||
if (!verbose)
|
if (verbose == false)
|
||||||
printf("p");
|
PrintAndLogEx(NORMAL, "p" NOLF);
|
||||||
|
|
||||||
aeskeyListLen = 0;
|
aeskeyListLen = 0;
|
||||||
deskeyListLen = 0;
|
deskeyListLen = 0;
|
||||||
k3kkeyListLen = 0;
|
k3kkeyListLen = 0;
|
||||||
DesFill2bPattern(deskeyList, &deskeyListLen, aeskeyList, &aeskeyListLen, k3kkeyList, &k3kkeyListLen, &startPattern);
|
DesFill2bPattern(deskeyList, &deskeyListLen, aeskeyList, &aeskeyListLen, k3kkeyList, &k3kkeyListLen, &startPattern);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dict_filenamelen && endFilePosition) {
|
if (dict_filenamelen && endFilePosition) {
|
||||||
if (!verbose)
|
if (verbose == false)
|
||||||
printf("d");
|
PrintAndLogEx(NORMAL, "d" NOLF);
|
||||||
|
|
||||||
uint32_t keycnt = 0;
|
uint32_t keycnt = 0;
|
||||||
res = loadFileDICTIONARYEx((char *)dict_filename, deskeyList, sizeof(deskeyList), NULL, 16, &keycnt, endFilePosition, &endFilePosition, false);
|
res = loadFileDICTIONARYEx((char *)dict_filename, deskeyList, sizeof(deskeyList), NULL, 16, &keycnt, endFilePosition, &endFilePosition, false);
|
||||||
|
@ -4420,8 +4425,8 @@ static int CmdHF14aDesChk(const char *Cmd) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!verbose)
|
if (verbose == false)
|
||||||
printf("\n");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
// save keys to json
|
// save keys to json
|
||||||
if ((jsonnamelen > 0) && result) {
|
if ((jsonnamelen > 0) && result) {
|
||||||
|
|
|
@ -58,9 +58,9 @@ static char *getCardSizeStr(uint8_t fsize) {
|
||||||
|
|
||||||
// is LSB set?
|
// is LSB set?
|
||||||
if (fsize & 1)
|
if (fsize & 1)
|
||||||
sprintf(retStr, "0x%02X (" _YELLOW_("%d - %d bytes") ")", fsize, usize, lsize);
|
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("%d - %d bytes") ")", fsize, usize, lsize);
|
||||||
else
|
else
|
||||||
sprintf(retStr, "0x%02X (" _YELLOW_("%d bytes") ")", fsize, lsize);
|
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("%d bytes") ")", fsize, lsize);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,14 +70,14 @@ static char *getProtocolStr(uint8_t id, bool hw) {
|
||||||
char *retStr = buf;
|
char *retStr = buf;
|
||||||
|
|
||||||
if (id == 0x04) {
|
if (id == 0x04) {
|
||||||
sprintf(retStr, "0x%02X (" _YELLOW_("ISO 14443-3 MIFARE, 14443-4") ")", id);
|
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("ISO 14443-3 MIFARE, 14443-4") ")", id);
|
||||||
} else if (id == 0x05) {
|
} else if (id == 0x05) {
|
||||||
if (hw)
|
if (hw)
|
||||||
sprintf(retStr, "0x%02X (" _YELLOW_("ISO 14443-2, 14443-3") ")", id);
|
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("ISO 14443-2, 14443-3") ")", id);
|
||||||
else
|
else
|
||||||
sprintf(retStr, "0x%02X (" _YELLOW_("ISO 14443-3, 14443-4") ")", id);
|
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("ISO 14443-3, 14443-4") ")", id);
|
||||||
} else {
|
} else {
|
||||||
sprintf(retStr, "0x%02X (" _YELLOW_("Unknown") ")", id);
|
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("Unknown") ")", id);
|
||||||
}
|
}
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
@ -88,20 +88,20 @@ static char *getVersionStr(uint8_t major, uint8_t minor) {
|
||||||
char *retStr = buf;
|
char *retStr = buf;
|
||||||
|
|
||||||
if (major == 0x00)
|
if (major == 0x00)
|
||||||
sprintf(retStr, "%x.%x (" _YELLOW_("DESFire MF3ICD40") ")", major, minor);
|
snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("DESFire MF3ICD40") ")", major, minor);
|
||||||
else if (major == 0x01 && minor == 0x00)
|
else if (major == 0x01 && minor == 0x00)
|
||||||
sprintf(retStr, "%x.%x (" _YELLOW_("DESFire EV1") ")", major, minor);
|
snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("DESFire EV1") ")", major, minor);
|
||||||
else if (major == 0x12 && minor == 0x00)
|
else if (major == 0x12 && minor == 0x00)
|
||||||
sprintf(retStr, "%x.%x (" _YELLOW_("DESFire EV2") ")", major, minor);
|
snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("DESFire EV2") ")", major, minor);
|
||||||
// else if (major == 0x13 && minor == 0x00)
|
else if (major == 0x33 && minor == 0x00)
|
||||||
// sprintf(retStr, "%x.%x (" _YELLOW_("DESFire EV3") ")", major, minor);
|
snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("DESFire EV3") ")", major, minor);
|
||||||
else if (major == 0x30 && minor == 0x00)
|
else if (major == 0x30 && minor == 0x00)
|
||||||
sprintf(retStr, "%x.%x (" _YELLOW_("DESFire Light") ")", major, minor);
|
snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("DESFire Light") ")", major, minor);
|
||||||
|
|
||||||
else if (major == 0x11 && minor == 0x00)
|
else if (major == 0x11 && minor == 0x00)
|
||||||
sprintf(retStr, "%x.%x (" _YELLOW_("Plus EV1") ")", major, minor);
|
snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("Plus EV1") ")", major, minor);
|
||||||
else
|
else
|
||||||
sprintf(retStr, "%x.%x (" _YELLOW_("Unknown") ")", major, minor);
|
snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("Unknown") ")", major, minor);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,16 +112,16 @@ static char *getTypeStr(uint8_t type) {
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 1:
|
case 1:
|
||||||
sprintf(retStr, "0x%02X (" _YELLOW_("DESFire") ")", type);
|
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("DESFire") ")", type);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
sprintf(retStr, "0x%02X (" _YELLOW_("Plus") ")", type);
|
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("Plus") ")", type);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
sprintf(retStr, "0x%02X (" _YELLOW_("Ultralight") ")", type);
|
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("Ultralight") ")", type);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
sprintf(retStr, "0x%02X (" _YELLOW_("NTAG") ")", type);
|
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("NTAG") ")", type);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -144,8 +144,8 @@ static nxp_cardtype_t getCardType(uint8_t major, uint8_t minor) {
|
||||||
return DESFIRE_EV2;
|
return DESFIRE_EV2;
|
||||||
|
|
||||||
// DESFire EV3
|
// DESFire EV3
|
||||||
// if (major == 0x13 && minor == 0x00 )
|
if (major == 0x33 && minor == 0x00)
|
||||||
// return DESFIRE_EV3;
|
return DESFIRE_EV3;
|
||||||
|
|
||||||
// DESFire Light
|
// DESFire Light
|
||||||
if (major == 0x30 && minor == 0x00)
|
if (major == 0x30 && minor == 0x00)
|
||||||
|
@ -969,8 +969,10 @@ static int MFPKeyCheck(uint8_t startSector, uint8_t endSector, uint8_t startKeyA
|
||||||
// main cycle with key check
|
// main cycle with key check
|
||||||
for (int i = 0; i < keyListLen; i++) {
|
for (int i = 0; i < keyListLen; i++) {
|
||||||
if (i % 10 == 0) {
|
if (i % 10 == 0) {
|
||||||
if (!verbose)
|
|
||||||
printf(".");
|
if (verbose == false)
|
||||||
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
|
|
||||||
if (kbd_enter_pressed()) {
|
if (kbd_enter_pressed()) {
|
||||||
PrintAndLogEx(WARNING, "\nAborted via keyboard!\n");
|
PrintAndLogEx(WARNING, "\nAborted via keyboard!\n");
|
||||||
DropField();
|
DropField();
|
||||||
|
@ -988,9 +990,9 @@ static int MFPKeyCheck(uint8_t startSector, uint8_t endSector, uint8_t startKeyA
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
PrintAndLogEx(WARNING, "retried[%d]...", retry);
|
PrintAndLogEx(WARNING, "\nretried[%d]...", retry);
|
||||||
else
|
else
|
||||||
printf("R");
|
PrintAndLogEx(NORMAL, "R" NOLF);
|
||||||
|
|
||||||
DropField();
|
DropField();
|
||||||
selectCard = true;
|
selectCard = true;
|
||||||
|
@ -998,14 +1000,15 @@ static int MFPKeyCheck(uint8_t startSector, uint8_t endSector, uint8_t startKeyA
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
PrintAndLogEx(WARNING, "sector %02d key %d [%s] res: %d", sector, keyAB, sprint_hex_inrow(keyList[i], 16), res);
|
PrintAndLogEx(WARNING, "\nsector %02d key %d [%s] res: %d", sector, keyAB, sprint_hex_inrow(keyList[i], 16), res);
|
||||||
|
|
||||||
// key for [sector,keyAB] found
|
// key for [sector,keyAB] found
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
if (verbose)
|
if (verbose)
|
||||||
PrintAndLogEx(INFO, "Found key for sector %d key %s [%s]", sector, keyAB == 0 ? "A" : "B", sprint_hex_inrow(keyList[i], 16));
|
PrintAndLogEx(INFO, "\nFound key for sector %d key %s [%s]", sector, keyAB == 0 ? "A" : "B", sprint_hex_inrow(keyList[i], 16));
|
||||||
else
|
else
|
||||||
printf("+");
|
PrintAndLogEx(NORMAL, "+" NOLF);
|
||||||
|
|
||||||
foundKeys[keyAB][sector][0] = 0x01;
|
foundKeys[keyAB][sector][0] = 0x01;
|
||||||
memcpy(&foundKeys[keyAB][sector][1], keyList[i], AES_KEY_LEN);
|
memcpy(&foundKeys[keyAB][sector][1], keyList[i], AES_KEY_LEN);
|
||||||
DropField();
|
DropField();
|
||||||
|
@ -1017,9 +1020,10 @@ static int MFPKeyCheck(uint8_t startSector, uint8_t endSector, uint8_t startKeyA
|
||||||
// 5 - auth error (rnd not equal)
|
// 5 - auth error (rnd not equal)
|
||||||
if (res != 5) {
|
if (res != 5) {
|
||||||
if (verbose)
|
if (verbose)
|
||||||
PrintAndLogEx(ERR, "Exchange error. Aborted.");
|
PrintAndLogEx(ERR, "\nExchange error. Aborted.");
|
||||||
else
|
else
|
||||||
printf("E");
|
PrintAndLogEx(NORMAL, "E" NOLF);
|
||||||
|
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_ECARDEXCHANGE;
|
return PM3_ECARDEXCHANGE;
|
||||||
}
|
}
|
||||||
|
@ -1201,23 +1205,25 @@ static int CmdHFMFPChk(const char *Cmd) {
|
||||||
PrintAndLogEx(INFO, "Loaded " _YELLOW_("%"PRIu32) " keys", keyListLen);
|
PrintAndLogEx(INFO, "Loaded " _YELLOW_("%"PRIu32) " keys", keyListLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!verbose)
|
if (verbose == false)
|
||||||
printf("Search keys:");
|
PrintAndLogEx(NORMAL, "Search keys");
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
res = MFPKeyCheck(startSector, endSector, startKeyAB, endKeyAB, keyList, keyListLen, foundKeys, verbose);
|
res = MFPKeyCheck(startSector, endSector, startKeyAB, endKeyAB, keyList, keyListLen, foundKeys, verbose);
|
||||||
if (res == PM3_EOPABORTED)
|
if (res == PM3_EOPABORTED)
|
||||||
break;
|
break;
|
||||||
if (pattern2b && startPattern < 0x10000) {
|
if (pattern2b && startPattern < 0x10000) {
|
||||||
if (!verbose)
|
if (verbose == false)
|
||||||
printf("p");
|
PrintAndLogEx(NORMAL, "p" NOLF);
|
||||||
|
|
||||||
keyListLen = 0;
|
keyListLen = 0;
|
||||||
Fill2bPattern(keyList, &keyListLen, &startPattern);
|
Fill2bPattern(keyList, &keyListLen, &startPattern);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (dict_filenamelen && endFilePosition) {
|
if (dict_filenamelen && endFilePosition) {
|
||||||
if (!verbose)
|
if (verbose == false)
|
||||||
printf("d");
|
PrintAndLogEx(NORMAL, "d" NOLF);
|
||||||
|
|
||||||
uint32_t keycnt = 0;
|
uint32_t keycnt = 0;
|
||||||
res = loadFileDICTIONARYEx((char *)dict_filename, keyList, sizeof(keyList), NULL, 16, &keycnt, endFilePosition, &endFilePosition, false);
|
res = loadFileDICTIONARYEx((char *)dict_filename, keyList, sizeof(keyList), NULL, 16, &keycnt, endFilePosition, &endFilePosition, false);
|
||||||
keyListLen = keycnt;
|
keyListLen = keycnt;
|
||||||
|
@ -1225,8 +1231,8 @@ static int CmdHFMFPChk(const char *Cmd) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!verbose)
|
if (verbose == false)
|
||||||
printf("\n");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
// print result
|
// print result
|
||||||
bool printedHeader = false;
|
bool printedHeader = false;
|
||||||
|
|
|
@ -123,7 +123,7 @@ static int usage_hf_mfu_wrbl(void) {
|
||||||
PrintAndLogEx(NORMAL, "Usage: hf mfu wrbl b <block number> d <data> k <key> l\n");
|
PrintAndLogEx(NORMAL, "Usage: hf mfu wrbl b <block number> d <data> k <key> l\n");
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
PrintAndLogEx(NORMAL, "Options:");
|
||||||
PrintAndLogEx(NORMAL, " b <no> : block to write");
|
PrintAndLogEx(NORMAL, " b <no> : block to write");
|
||||||
PrintAndLogEx(NORMAL, " d <data> : block data - (8 hex symbols)");
|
PrintAndLogEx(NORMAL, " d <data> : block data - (8 or 32 hex symbols, 32 hex symbols will do a compatibility write)");
|
||||||
PrintAndLogEx(NORMAL, " k <key> : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]");
|
PrintAndLogEx(NORMAL, " k <key> : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]");
|
||||||
PrintAndLogEx(NORMAL, " l : (optional) swap entered key's endianness");
|
PrintAndLogEx(NORMAL, " l : (optional) swap entered key's endianness");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
@ -1096,6 +1096,7 @@ uint32_t GetHF14AMfU_Type(void) {
|
||||||
else if (memcmp(version, "\x00\x04\x03\x02\x01\x00\x0B", 7) == 0) { tagtype = UL_EV1_48; break; }
|
else if (memcmp(version, "\x00\x04\x03\x02\x01\x00\x0B", 7) == 0) { tagtype = UL_EV1_48; break; }
|
||||||
else if (memcmp(version, "\x00\x04\x03\x01\x01\x00\x0E", 7) == 0) { tagtype = UL_EV1_128; break; }
|
else if (memcmp(version, "\x00\x04\x03\x01\x01\x00\x0E", 7) == 0) { tagtype = UL_EV1_128; break; }
|
||||||
else if (memcmp(version, "\x00\x04\x03\x02\x01\x00\x0E", 7) == 0) { tagtype = UL_EV1_128; break; }
|
else if (memcmp(version, "\x00\x04\x03\x02\x01\x00\x0E", 7) == 0) { tagtype = UL_EV1_128; break; }
|
||||||
|
else if (memcmp(version, "\x00\x34\x21\x01\x01\x00\x0E", 7) == 0) { tagtype = UL_EV1_128; break; } // Mikron JSC Russia EV1 41 pages tag
|
||||||
else if (memcmp(version, "\x00\x04\x04\x01\x01\x00\x0B", 7) == 0) { tagtype = NTAG_210; break; }
|
else if (memcmp(version, "\x00\x04\x04\x01\x01\x00\x0B", 7) == 0) { tagtype = NTAG_210; break; }
|
||||||
else if (memcmp(version, "\x00\x04\x04\x01\x01\x00\x0E", 7) == 0) { tagtype = NTAG_212; break; }
|
else if (memcmp(version, "\x00\x04\x04\x01\x01\x00\x0E", 7) == 0) { tagtype = NTAG_212; break; }
|
||||||
else if (memcmp(version, "\x00\x04\x04\x02\x01\x00\x0F", 7) == 0) { tagtype = NTAG_213; break; }
|
else if (memcmp(version, "\x00\x04\x04\x02\x01\x00\x0F", 7) == 0) { tagtype = NTAG_213; break; }
|
||||||
|
@ -1473,8 +1474,9 @@ static int CmdHF14AMfUWrBl(const char *Cmd) {
|
||||||
|
|
||||||
uint8_t cmdp = 0;
|
uint8_t cmdp = 0;
|
||||||
uint8_t keylen = 0;
|
uint8_t keylen = 0;
|
||||||
uint8_t blockdata[20] = {0x00};
|
uint8_t blockdata[16] = {0x00};
|
||||||
uint8_t data[16] = {0x00};
|
uint8_t data[16] = {0x00};
|
||||||
|
uint8_t datalen = 4;
|
||||||
uint8_t authenticationkey[16] = {0x00};
|
uint8_t authenticationkey[16] = {0x00};
|
||||||
uint8_t *authKeyPtr = authenticationkey;
|
uint8_t *authKeyPtr = authenticationkey;
|
||||||
|
|
||||||
|
@ -1516,9 +1518,13 @@ static int CmdHF14AMfUWrBl(const char *Cmd) {
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
if (param_gethex(Cmd, cmdp + 1, blockdata, 8)) {
|
if (param_gethex(Cmd, cmdp + 1, blockdata, 8)) {
|
||||||
PrintAndLogEx(WARNING, "Block data must include 8 HEX symbols");
|
if (param_gethex(Cmd, cmdp + 1, blockdata, 32)) {
|
||||||
errors = true;
|
PrintAndLogEx(WARNING, "Block data must include 8 or 32 HEX symbols");
|
||||||
break;
|
errors = true;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
datalen = 16;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cmdp += 2;
|
cmdp += 2;
|
||||||
break;
|
break;
|
||||||
|
@ -1558,9 +1564,8 @@ static int CmdHF14AMfUWrBl(const char *Cmd) {
|
||||||
PrintAndLogEx(NORMAL, "Block: %0d (0x%02X) [ %s]", blockNo, blockNo, sprint_hex(blockdata, 4));
|
PrintAndLogEx(NORMAL, "Block: %0d (0x%02X) [ %s]", blockNo, blockNo, sprint_hex(blockdata, 4));
|
||||||
|
|
||||||
//Send write Block
|
//Send write Block
|
||||||
uint8_t cmddata[20];
|
uint8_t cmddata[32];
|
||||||
memcpy(cmddata, blockdata, 4);
|
memcpy(cmddata, blockdata, datalen);
|
||||||
uint8_t datalen = 4;
|
|
||||||
uint8_t keytype = 0;
|
uint8_t keytype = 0;
|
||||||
if (hasAuthKey) {
|
if (hasAuthKey) {
|
||||||
keytype = 1;
|
keytype = 1;
|
||||||
|
@ -1573,7 +1578,11 @@ static int CmdHF14AMfUWrBl(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, blockNo, keytype, 0, cmddata, datalen);
|
if (datalen == 16) {
|
||||||
|
SendCommandMIX(CMD_HF_MIFAREU_WRITEBL_COMPAT, blockNo, keytype, 0, cmddata, datalen);
|
||||||
|
} else {
|
||||||
|
SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, blockNo, keytype, 0, cmddata, datalen);
|
||||||
|
}
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||||
uint8_t isOK = resp.oldarg[0] & 0xff;
|
uint8_t isOK = resp.oldarg[0] & 0xff;
|
||||||
|
@ -1982,7 +1991,7 @@ static int CmdHF14AMfUDump(const char *Cmd) {
|
||||||
|
|
||||||
// not ul_c and not std ul then attempt to collect info like
|
// not ul_c and not std ul then attempt to collect info like
|
||||||
// VERSION, SIGNATURE, COUNTERS, TEARING, PACK,
|
// VERSION, SIGNATURE, COUNTERS, TEARING, PACK,
|
||||||
if (!(tagtype & UL_C || tagtype & UL)) {
|
if (!(tagtype & UL_C || tagtype & UL || tagtype & MY_D_MOVE || tagtype & MY_D_MOVE_LEAN)) {
|
||||||
//attempt to read pack
|
//attempt to read pack
|
||||||
uint8_t get_pack[] = {0, 0};
|
uint8_t get_pack[] = {0, 0};
|
||||||
if (ul_auth_select(&card, tagtype, true, authKeyPtr, get_pack, sizeof(get_pack)) != PM3_SUCCESS) {
|
if (ul_auth_select(&card, tagtype, true, authKeyPtr, get_pack, sizeof(get_pack)) != PM3_SUCCESS) {
|
||||||
|
@ -2306,8 +2315,7 @@ static int CmdHF14AMfURestore(const char *Cmd) {
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, b, keytype, 0, data, sizeof(data));
|
SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, b, keytype, 0, data, sizeof(data));
|
||||||
wait4response(b);
|
wait4response(b);
|
||||||
printf(".");
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
fflush(stdout);
|
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "\n");
|
PrintAndLogEx(NORMAL, "\n");
|
||||||
|
|
||||||
|
|
|
@ -696,7 +696,7 @@ void pm3_version(bool verbose, bool oneliner) {
|
||||||
// For "proxmark3 -v", simple printf, avoid logging
|
// For "proxmark3 -v", simple printf, avoid logging
|
||||||
char temp[PM3_CMD_DATA_SIZE - 12]; // same limit as for ARM image
|
char temp[PM3_CMD_DATA_SIZE - 12]; // same limit as for ARM image
|
||||||
FormatVersionInformation(temp, sizeof(temp), "Client: ", &version_information);
|
FormatVersionInformation(temp, sizeof(temp), "Client: ", &version_information);
|
||||||
printf("%s compiled with " PM3CLIENTCOMPILER __VERSION__ PM3HOSTOS PM3HOSTARCH "\n", temp);
|
PrintAndLogEx(NORMAL, "%s compiled with " PM3CLIENTCOMPILER __VERSION__ PM3HOSTOS PM3HOSTARCH "\n", temp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -705,7 +705,6 @@ void pm3_version(bool verbose, bool oneliner) {
|
||||||
|
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
|
|
||||||
SendCommandNG(CMD_VERSION, NULL, 0);
|
SendCommandNG(CMD_VERSION, NULL, 0);
|
||||||
|
|
||||||
if (WaitForResponseTimeout(CMD_VERSION, &resp, 1000)) {
|
if (WaitForResponseTimeout(CMD_VERSION, &resp, 1000)) {
|
||||||
|
|
|
@ -364,16 +364,15 @@ int CmdLFCommandRead(const char *Cmd) {
|
||||||
uint8_t i = 10;
|
uint8_t i = 10;
|
||||||
// 20sec wait loop
|
// 20sec wait loop
|
||||||
while (!WaitForResponseTimeout(CMD_LF_MOD_THEN_ACQ_RAW_ADC, &resp, 2000) && i != 0) {
|
while (!WaitForResponseTimeout(CMD_LF_MOD_THEN_ACQ_RAW_ADC, &resp, 2000) && i != 0) {
|
||||||
printf(".");
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
fflush(stdout);
|
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
printf("\n");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
if (resp.status == PM3_SUCCESS) {
|
if (resp.status == PM3_SUCCESS) {
|
||||||
if (i) {
|
if (i) {
|
||||||
PrintAndLogEx(SUCCESS, "downloading response signal data");
|
PrintAndLogEx(SUCCESS, "downloading response signal data");
|
||||||
getSamples(0, true);
|
getSamples(0, false);
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||||
|
@ -596,7 +595,7 @@ int lf_read(bool verbose, uint32_t samples) {
|
||||||
if (!session.pm3_present) return PM3_ENOTTY;
|
if (!session.pm3_present) return PM3_ENOTTY;
|
||||||
|
|
||||||
struct p {
|
struct p {
|
||||||
uint8_t verbose;
|
bool verbose;
|
||||||
uint32_t samples;
|
uint32_t samples;
|
||||||
} PACKED;
|
} PACKED;
|
||||||
|
|
||||||
|
@ -606,21 +605,19 @@ int lf_read(bool verbose, uint32_t samples) {
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_LF_ACQ_RAW_ADC, (uint8_t *)&payload, sizeof(payload));
|
SendCommandNG(CMD_LF_ACQ_RAW_ADC, (uint8_t *)&payload, sizeof(payload));
|
||||||
|
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
if (g_lf_threshold_set) {
|
if (g_lf_threshold_set) {
|
||||||
WaitForResponse(CMD_LF_ACQ_RAW_ADC, &resp);
|
WaitForResponse(CMD_LF_ACQ_RAW_ADC, &resp);
|
||||||
} else {
|
} else {
|
||||||
if (!WaitForResponseTimeout(CMD_LF_ACQ_RAW_ADC, &resp, 2500)) {
|
if (!WaitForResponseTimeout(CMD_LF_ACQ_RAW_ADC, &resp, 2500)) {
|
||||||
PrintAndLogEx(WARNING, "command execution time out");
|
PrintAndLogEx(WARNING, "(lf_read) command execution time out");
|
||||||
return PM3_ETIMEOUT;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// resp.oldarg[0] is bits read not bytes read.
|
// response is number of bits read
|
||||||
uint32_t bits = (resp.data.asDwords[0] / 8);
|
uint32_t size = (resp.data.asDwords[0] / 8);
|
||||||
getSamples(bits, verbose);
|
getSamples(size, verbose);
|
||||||
|
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -736,15 +733,13 @@ int CmdLFSim(const char *Cmd) {
|
||||||
PrintAndLogEx(INFO, "Bigbuf is full.");
|
PrintAndLogEx(INFO, "Bigbuf is full.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printf(".");
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
fflush(stdout);
|
|
||||||
payload_up.flag = 0;
|
payload_up.flag = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable fast mode before last command
|
// Disable fast mode before last command
|
||||||
conn.block_after_ACK = false;
|
conn.block_after_ACK = false;
|
||||||
printf("\n");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "Simulating");
|
PrintAndLogEx(INFO, "Simulating");
|
||||||
|
|
||||||
struct p {
|
struct p {
|
||||||
|
@ -1194,7 +1189,7 @@ static bool CheckChipType(bool getDeviceData) {
|
||||||
//check for em4x05/em4x69 chips first
|
//check for em4x05/em4x69 chips first
|
||||||
uint32_t word = 0;
|
uint32_t word = 0;
|
||||||
if (EM4x05IsBlock0(&word)) {
|
if (EM4x05IsBlock0(&word)) {
|
||||||
PrintAndLogEx(SUCCESS, "Chipset detection: " _GREEN_("EM4x05/EM4x69"));
|
PrintAndLogEx(SUCCESS, "Chipset detection: " _GREEN_("EM4x05 / EM4x69"));
|
||||||
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf em 4x05`") " commands");
|
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf em 4x05`") " commands");
|
||||||
retval = true;
|
retval = true;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -1215,6 +1210,7 @@ static bool CheckChipType(bool getDeviceData) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "Couldn't identify a chipset");
|
||||||
out:
|
out:
|
||||||
save_restoreGB(GRAPH_RESTORE);
|
save_restoreGB(GRAPH_RESTORE);
|
||||||
save_restoreDB(GRAPH_RESTORE);
|
save_restoreDB(GRAPH_RESTORE);
|
||||||
|
@ -1242,6 +1238,7 @@ int CmdLFfind(const char *Cmd) {
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(INFO, "NOTE: some demods output possible binary");
|
PrintAndLogEx(INFO, "NOTE: some demods output possible binary");
|
||||||
PrintAndLogEx(INFO, "if it finds something that looks like a tag");
|
PrintAndLogEx(INFO, "if it finds something that looks like a tag");
|
||||||
PrintAndLogEx(INFO, "False Positives " _YELLOW_("ARE") " possible");
|
PrintAndLogEx(INFO, "False Positives " _YELLOW_("ARE") " possible");
|
||||||
|
@ -1270,49 +1267,50 @@ int CmdLFfind(const char *Cmd) {
|
||||||
// The improved noise detection will find Cotag.
|
// The improved noise detection will find Cotag.
|
||||||
if (getSignalProperties()->isnoise) {
|
if (getSignalProperties()->isnoise) {
|
||||||
|
|
||||||
|
PrintAndLogEx(INPLACE, "Searching for MOTOROLA tag...");
|
||||||
if (readMotorolaUid()) {
|
if (readMotorolaUid()) {
|
||||||
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Motorola FlexPass ID") " found!");
|
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Motorola FlexPass ID") " found!");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (readCOTAGUid()) {
|
if (readCOTAGUid()) {
|
||||||
|
PrintAndLogEx(INPLACE, "Searching for COTAG tag...");
|
||||||
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("COTAG ID") " found!");
|
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("COTAG ID") " found!");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(FAILED, _RED_("No data found!"));
|
PrintAndLogEx(FAILED, _RED_("No data found!"));
|
||||||
PrintAndLogEx(INFO, "Signal looks like noise. Maybe not an LF tag?");
|
PrintAndLogEx(INFO, "Signal looks like noise. Maybe not an LF tag?");
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (demodVisa2k() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Visa2000 ID") " found!"); goto out;}
|
if (demodVisa2k() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Visa2000 ID") " found!"); goto out;}
|
||||||
if (demodHID() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("HID Prox ID") " found!"); goto out;}
|
if (demodHID() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("HID Prox ID") " found!"); goto out;}
|
||||||
if (demodAWID() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("AWID ID") " found!"); goto out;}
|
if (demodAWID() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("AWID ID") " found!"); goto out;}
|
||||||
if (demodIOProx() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("IO Prox ID") " found!"); goto out;}
|
if (demodIOProx() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("IO Prox ID") " found!"); goto out;}
|
||||||
if (demodParadox() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Paradox ID") " found!"); goto out;}
|
if (demodParadox() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Paradox ID") " found!"); goto out;}
|
||||||
if (demodNexWatch() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("NexWatch ID") " found!"); goto out;}
|
if (demodNexWatch() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("NexWatch ID") " found!"); goto out;}
|
||||||
if (demodIndala() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Indala ID") " found!"); goto out;}
|
if (demodIndala() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Indala ID") " found!"); goto out;}
|
||||||
|
if (demodEM410x() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("EM410x ID") " found!"); goto out;}
|
||||||
|
if (demodFDX() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("FDX-B ID") " found!"); goto out;}
|
||||||
|
if (demodGuard() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Guardall G-Prox II ID") " found!"); goto out; }
|
||||||
|
if (demodIdteck() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Idteck ID") " found!"); goto out;}
|
||||||
|
if (demodJablotron() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Jablotron ID") " found!"); goto out;}
|
||||||
|
if (demodNedap() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("NEDAP ID") " found!"); goto out;}
|
||||||
|
if (demodNoralsy() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Noralsy ID") " found!"); goto out;}
|
||||||
|
if (demodKeri() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("KERI ID") " found!"); goto out;}
|
||||||
|
if (demodPac() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("PAC/Stanley ID") " found!"); goto out;}
|
||||||
|
if (demodPresco() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Presco ID") " found!"); goto out;}
|
||||||
|
if (demodPyramid() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Pyramid ID") " found!"); goto out;}
|
||||||
|
if (demodSecurakey() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Securakey ID") " found!"); goto out;}
|
||||||
|
if (demodViking() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Viking ID") " found!"); goto out;}
|
||||||
|
if (demodGallagher() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("GALLAGHER ID") " found!"); goto out;}
|
||||||
|
|
||||||
if (demodEM410x() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("EM410x ID") " found!"); goto out;}
|
// if (demodTI() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Texas Instrument ID") " found!"); goto out;}
|
||||||
if (demodFDX() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("FDX-B ID") " found!"); goto out;}
|
// if (demodFermax() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Fermax ID") " found!"); goto out;}
|
||||||
if (demodGuard() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Guardall G-Prox II ID") " found!"); goto out; }
|
|
||||||
if (demodIdteck() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Idteck ID") " found!"); goto out;}
|
|
||||||
|
|
||||||
if (demodJablotron() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Jablotron ID") " found!"); goto out;}
|
|
||||||
if (demodNedap() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("NEDAP ID") " found!"); goto out;}
|
|
||||||
if (demodNoralsy() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Noralsy ID") " found!"); goto out;}
|
|
||||||
if (demodKeri() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("KERI ID") " found!"); goto out;}
|
|
||||||
if (demodPac() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("PAC/Stanley ID") " found!"); goto out;}
|
|
||||||
|
|
||||||
if (demodPresco() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Presco ID") " found!"); goto out;}
|
|
||||||
if (demodPyramid() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Pyramid ID") " found!"); goto out;}
|
|
||||||
if (demodSecurakey() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Securakey ID") " found!"); goto out;}
|
|
||||||
if (demodViking() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Viking ID") " found!"); goto out;}
|
|
||||||
if (demodGallagher() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("GALLAGHER ID") " found!"); goto out;}
|
|
||||||
|
|
||||||
// if (demodTI() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Texas Instrument ID") " found!"); goto out;}
|
|
||||||
//if (demodFermax() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Fermax ID") " found!"); goto out;}
|
|
||||||
|
|
||||||
PrintAndLogEx(FAILED, _RED_("No known 125/134 kHz tags found!"));
|
PrintAndLogEx(FAILED, _RED_("No known 125/134 kHz tags found!"));
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ static int usage_lf_awid_sim(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usage_lf_awid_clone(void) {
|
static int usage_lf_awid_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, "Enables cloning of AWID card with specified facility-code and card number onto T55x7.");
|
PrintAndLogEx(NORMAL, "Enables cloning of AWID card with specified facility-code and card number onto T55x7 or Q5/T5555.");
|
||||||
PrintAndLogEx(NORMAL, "The T55x7 must be on the antenna when issuing this command. T55x7 blocks are calculated and printed in the process.");
|
PrintAndLogEx(NORMAL, "The T55x7 must be on the antenna when issuing this command. T55x7 blocks are calculated and printed in the process.");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf awid clone [h] <format> <facility-code> <card-number> [Q5]");
|
PrintAndLogEx(NORMAL, "Usage: lf awid clone [h] <format> <facility-code> <card-number> [Q5]");
|
||||||
|
@ -69,7 +69,7 @@ static int usage_lf_awid_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, " <format> : format length 26|34|37|50");
|
PrintAndLogEx(NORMAL, " <format> : format length 26|34|37|50");
|
||||||
PrintAndLogEx(NORMAL, " <facility-code> : 8|16bit value facility code");
|
PrintAndLogEx(NORMAL, " <facility-code> : 8|16bit value facility code");
|
||||||
PrintAndLogEx(NORMAL, " <card number> : 16|32-bit value card number");
|
PrintAndLogEx(NORMAL, " <card number> : 16|32-bit value card number");
|
||||||
PrintAndLogEx(NORMAL, " Q5 : optional - clone to Q5 (T5555) instead of T55x7 chip");
|
PrintAndLogEx(NORMAL, " Q5 : optional - specify writing to Q5/T5555 tag");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf awid clone 26 224 1337"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf awid clone 26 224 1337"));
|
||||||
|
@ -405,9 +405,10 @@ static int CmdAWIDClone(const char *Cmd) {
|
||||||
|
|
||||||
uint32_t blocks[4] = {T55x7_MODULATION_FSK2a | T55x7_BITRATE_RF_50 | 3 << T55x7_MAXBLOCK_SHIFT, 0, 0, 0};
|
uint32_t blocks[4] = {T55x7_MODULATION_FSK2a | T55x7_BITRATE_RF_50 | 3 << T55x7_MAXBLOCK_SHIFT, 0, 0, 0};
|
||||||
|
|
||||||
if (tolower(param_getchar(Cmd, 3)) == 'q')
|
bool q5 = tolower(param_getchar(Cmd, 3)) == 'q';
|
||||||
|
if (q5)
|
||||||
//t5555 (Q5) BITRATE = (RF-2)/2 (iceman)
|
//t5555 (Q5) BITRATE = (RF-2)/2 (iceman)
|
||||||
blocks[0] = T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(50) | 3 << T5555_MAXBLOCK_SHIFT;
|
blocks[0] = T5555_FIXED | T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(50) | 3 << T5555_MAXBLOCK_SHIFT;
|
||||||
|
|
||||||
verify_values(&fmtlen, &fc, &cn);
|
verify_values(&fmtlen, &fc, &cn);
|
||||||
|
|
||||||
|
@ -425,7 +426,7 @@ static int CmdAWIDClone(const char *Cmd) {
|
||||||
|
|
||||||
free(bits);
|
free(bits);
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "Preparing to clone AWID %u to T55x7 with FC: %u, CN: %u", fmtlen, fc, cn);
|
PrintAndLogEx(INFO, "Preparing to clone AWID %u to " _YELLOW_("%s") " with FC: %u, CN: %u", fmtlen, (q5) ? "Q5/T5555" : "T55x7", fc, cn);
|
||||||
print_blocks(blocks, ARRAYLEN(blocks));
|
print_blocks(blocks, ARRAYLEN(blocks));
|
||||||
|
|
||||||
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
|
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
|
||||||
|
@ -532,7 +533,7 @@ static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "this help"},
|
{"help", CmdHelp, AlwaysAvailable, "this help"},
|
||||||
{"demod", CmdAWIDDemod, AlwaysAvailable, "demodulate an AWID FSK tag from the GraphBuffer"},
|
{"demod", CmdAWIDDemod, AlwaysAvailable, "demodulate an AWID FSK tag from the GraphBuffer"},
|
||||||
{"read", CmdAWIDRead, IfPm3Lf, "attempt to read and extract tag data"},
|
{"read", CmdAWIDRead, IfPm3Lf, "attempt to read and extract tag data"},
|
||||||
{"clone", CmdAWIDClone, IfPm3Lf, "clone AWID tag to T55x7 (or to q5/T5555)"},
|
{"clone", CmdAWIDClone, IfPm3Lf, "clone AWID tag to T55x7 or Q5/T5555"},
|
||||||
{"sim", CmdAWIDSim, IfPm3Lf, "simulate AWID tag"},
|
{"sim", CmdAWIDSim, IfPm3Lf, "simulate AWID tag"},
|
||||||
{"brute", CmdAWIDBrute, IfPm3Lf, "Bruteforce card number against reader"},
|
{"brute", CmdAWIDBrute, IfPm3Lf, "Bruteforce card number against reader"},
|
||||||
{"watch", CmdAWIDWatch, IfPm3Lf, "continuously watch for cards. Reader mode"},
|
{"watch", CmdAWIDWatch, IfPm3Lf, "continuously watch for cards. Reader mode"},
|
||||||
|
|
|
@ -92,19 +92,18 @@ static int CmdCOTAGRead(const char *Cmd) {
|
||||||
|
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_LF_COTAG_READ, (uint8_t*)&payload, sizeof(payload));
|
SendCommandNG(CMD_LF_COTAG_READ, (uint8_t *)&payload, sizeof(payload));
|
||||||
|
|
||||||
uint8_t timeout = 3;
|
uint8_t timeout = 3;
|
||||||
while (!WaitForResponseTimeout(CMD_LF_COTAG_READ, &resp, 2000)) {
|
while (!WaitForResponseTimeout(CMD_LF_COTAG_READ, &resp, 2000)) {
|
||||||
timeout--;
|
timeout--;
|
||||||
printf(".");
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
if (timeout == 0) {
|
if (timeout == 0) {
|
||||||
PrintAndLogEx(WARNING, "command execution time out");
|
PrintAndLogEx(WARNING, "command execution time out");
|
||||||
return PM3_ETIMEOUT;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timeout != 3)
|
if (timeout != 3)
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
|
|
|
@ -64,13 +64,13 @@ static int usage_lf_em410x_watch(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usage_lf_em410x_write(void) {
|
static int usage_lf_em410x_write(void) {
|
||||||
PrintAndLogEx(NORMAL, "Writes EM410x ID to a T55x7 / T5555 (Q5) tag");
|
PrintAndLogEx(NORMAL, "Writes EM410x ID to a T55x7 or Q5/T5555 tag");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf em 410x_write [h] <id> <card> [clock]");
|
PrintAndLogEx(NORMAL, "Usage: lf em 410x_write [h] <id> <card> [clock]");
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
PrintAndLogEx(NORMAL, "Options:");
|
||||||
PrintAndLogEx(NORMAL, " h - this help");
|
PrintAndLogEx(NORMAL, " h - this help");
|
||||||
PrintAndLogEx(NORMAL, " <id> - ID number");
|
PrintAndLogEx(NORMAL, " <id> - ID number");
|
||||||
PrintAndLogEx(NORMAL, " <card> - 0|1 T5555 (Q5) / T55x7");
|
PrintAndLogEx(NORMAL, " <card> - 0|1 0 = Q5/T5555, 1 = T55x7");
|
||||||
PrintAndLogEx(NORMAL, " <clock> - 16|32|40|64, optional, set R/F clock rate, defaults to 64");
|
PrintAndLogEx(NORMAL, " <clock> - 16|32|40|64, optional, set R/F clock rate, defaults to 64");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_write 0F0368568B 1") " = write ID to t55x7 card");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_write 0F0368568B 1") " = write ID to t55x7 card");
|
||||||
|
@ -630,15 +630,11 @@ static int CmdEM410xWrite(const char *Cmd) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (card == 1) {
|
PrintAndLogEx(SUCCESS, "Writing " _YELLOW_("%s") " tag with UID 0x%010" PRIx64 " (clock rate: %d)", (card == 1) ? "T55x7" : "Q5/T5555", id, clock1);
|
||||||
PrintAndLogEx(SUCCESS, "Writing %s tag with UID 0x%010" PRIx64 " (clock rate: %d)", _GREEN_("T55x7"), id, clock1);
|
// NOTE: We really should pass the clock in as a separate argument, but to
|
||||||
// NOTE: We really should pass the clock in as a separate argument, but to
|
// provide for backwards-compatibility for older firmware, and to avoid
|
||||||
// provide for backwards-compatibility for older firmware, and to avoid
|
// having to add another argument to CMD_LF_EM410X_WRITE, we just store
|
||||||
// having to add another argument to CMD_LF_EM410X_WRITE, we just store
|
// the clock rate in bits 8-15 of the card value
|
||||||
// the clock rate in bits 8-15 of the card value
|
|
||||||
} else if (card == 0) {
|
|
||||||
PrintAndLogEx(SUCCESS, "Writing %s tag with UID 0x%010" PRIx64 "(clock rate: %d)", _GREEN_("T5555"), id, clock1);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint8_t card;
|
uint8_t card;
|
||||||
|
@ -695,7 +691,7 @@ static bool downloadSamplesEM(void) {
|
||||||
// 8 bit preamble + 32 bit word response (max clock (128) * 40bits = 5120 samples)
|
// 8 bit preamble + 32 bit word response (max clock (128) * 40bits = 5120 samples)
|
||||||
uint8_t got[6000];
|
uint8_t got[6000];
|
||||||
if (!GetFromDevice(BIG_BUF, got, sizeof(got), 0, NULL, 0, NULL, 2500, false)) {
|
if (!GetFromDevice(BIG_BUF, got, sizeof(got), 0, NULL, 0, NULL, 2500, false)) {
|
||||||
PrintAndLogEx(WARNING, "command execution time out");
|
PrintAndLogEx(WARNING, "(downloadSamplesEM) command execution time out");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -859,6 +855,7 @@ static int demodEM4x05resp(uint32_t *word) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////// 4205 / 4305 commands
|
//////////////// 4205 / 4305 commands
|
||||||
|
#include "util_posix.h" // msclock
|
||||||
static int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *word) {
|
static int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *word) {
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
@ -874,14 +871,14 @@ static int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_LF_EM4X_READWORD, (uint8_t *)&payload, sizeof(payload));
|
SendCommandNG(CMD_LF_EM4X_READWORD, (uint8_t *)&payload, sizeof(payload));
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
if (!WaitForResponseTimeout(CMD_LF_EM4X_READWORD, &resp, 2500)) {
|
if (!WaitForResponseTimeout(CMD_LF_EM4X_READWORD, &resp, 10000)) {
|
||||||
PrintAndLogEx(DEBUG, "timeout while waiting for reply.");
|
PrintAndLogEx(WARNING, "(EM4x05ReadWord_ext) timeout while waiting for reply.");
|
||||||
return PM3_ETIMEOUT;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
if (!downloadSamplesEM()) {
|
|
||||||
|
if (downloadSamplesEM() == false) {
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return demodEM4x05resp(word);
|
return demodEM4x05resp(word);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1386,7 +1383,7 @@ static command_t CommandTable[] = {
|
||||||
{"410x_brute", CmdEM410xBrute, IfPm3Lf, "reader bruteforce attack by simulating EM410x tags"},
|
{"410x_brute", CmdEM410xBrute, IfPm3Lf, "reader bruteforce attack by simulating EM410x tags"},
|
||||||
{"410x_watch", CmdEM410xWatch, IfPm3Lf, "watches for EM410x 125/134 kHz tags (option 'h' for 134)"},
|
{"410x_watch", CmdEM410xWatch, IfPm3Lf, "watches for EM410x 125/134 kHz tags (option 'h' for 134)"},
|
||||||
{"410x_spoof", CmdEM410xWatchnSpoof, IfPm3Lf, "watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" },
|
{"410x_spoof", CmdEM410xWatchnSpoof, IfPm3Lf, "watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" },
|
||||||
{"410x_write", CmdEM410xWrite, IfPm3Lf, "write EM410x UID to T5555(Q5) or T55x7 tag"},
|
{"410x_write", CmdEM410xWrite, IfPm3Lf, "write EM410x UID to T55x7 or Q5/T5555 tag"},
|
||||||
{"----------", CmdHelp, AlwaysAvailable, "-------------------- " _CYAN_("EM 4x05 / 4x69") " -------------------"},
|
{"----------", CmdHelp, AlwaysAvailable, "-------------------- " _CYAN_("EM 4x05 / 4x69") " -------------------"},
|
||||||
{"4x05_demod", CmdEM4x05Demod, AlwaysAvailable, "demodulate a EM4x05/EM4x69 tag from the GraphBuffer"},
|
{"4x05_demod", CmdEM4x05Demod, AlwaysAvailable, "demodulate a EM4x05/EM4x69 tag from the GraphBuffer"},
|
||||||
{"4x05_dump", CmdEM4x05Dump, IfPm3Lf, "dump EM4x05/EM4x69 tag"},
|
{"4x05_dump", CmdEM4x05Dump, IfPm3Lf, "dump EM4x05/EM4x69 tag"},
|
||||||
|
|
|
@ -516,7 +516,7 @@ int em4x50_read(em4x50_data_t *etd, em4x50_word_t *out, bool verbose) {
|
||||||
|
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
|
if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
|
||||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
PrintAndLogEx(WARNING, "(em4x50) timeout while waiting for reply.");
|
||||||
return PM3_ETIMEOUT;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
static int usage_lf_fdx_clone(void) {
|
static int usage_lf_fdx_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, "Clone a FDX-B animal tag to a T55x7 tag.");
|
PrintAndLogEx(NORMAL, "Clone a FDX-B animal tag to a T55x7 or Q5/T5555 tag.");
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf fdx clone [h] <country id> <animal id> <extended> <Q5>");
|
PrintAndLogEx(NORMAL, "Usage: lf fdx clone [h] <country id> <animal id> <extended> <Q5>");
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
PrintAndLogEx(NORMAL, "Options:");
|
||||||
PrintAndLogEx(NORMAL, " h : This help");
|
PrintAndLogEx(NORMAL, " h : This help");
|
||||||
|
@ -58,7 +58,7 @@ static int usage_lf_fdx_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, " <extended> : Extended data");
|
PrintAndLogEx(NORMAL, " <extended> : Extended data");
|
||||||
//reserved/rfu
|
//reserved/rfu
|
||||||
//is animal tag
|
//is animal tag
|
||||||
PrintAndLogEx(NORMAL, " <Q5> : Specify write to Q5 (t5555 instead of t55x7)");
|
PrintAndLogEx(NORMAL, " <Q5> : Specify writing to Q5/T5555 tag");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf fdx clone 999 112233"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf fdx clone 999 112233"));
|
||||||
|
@ -292,7 +292,36 @@ static int CmdFdxDemod(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdFdxRead(const char *Cmd) {
|
static int CmdFdxRead(const char *Cmd) {
|
||||||
lf_read(false, 10000);
|
sample_config config;
|
||||||
|
memset(&config, 0, sizeof(sample_config));
|
||||||
|
int retval = lf_getconfig(&config);
|
||||||
|
if (retval != PM3_SUCCESS) {
|
||||||
|
PrintAndLogEx(ERR, "failed to get current device LF config");
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
int16_t tmp_div = config.divisor;
|
||||||
|
if (tmp_div != LF_DIVISOR_134) {
|
||||||
|
config.divisor = LF_DIVISOR_134;
|
||||||
|
config.verbose = false;
|
||||||
|
retval = lf_config(&config);
|
||||||
|
if (retval != PM3_SUCCESS) {
|
||||||
|
PrintAndLogEx(ERR, "failed to change LF configuration");
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
retval = lf_read(false, 10000);
|
||||||
|
if (retval != PM3_SUCCESS) {
|
||||||
|
PrintAndLogEx(ERR, "failed to get LF read from device");
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
if (tmp_div != LF_DIVISOR_134) {
|
||||||
|
config.divisor = tmp_div;
|
||||||
|
retval = lf_config(&config);
|
||||||
|
if (retval != PM3_SUCCESS) {
|
||||||
|
PrintAndLogEx(ERR, "failed to restore LF configuration");
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
}
|
||||||
return CmdFdxDemod(Cmd);
|
return CmdFdxDemod(Cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,8 +350,9 @@ static int CmdFdxClone(const char *Cmd) {
|
||||||
uint32_t blocks[5] = {T55x7_MODULATION_DIPHASE | T55x7_BITRATE_RF_32 | 4 << T55x7_MAXBLOCK_SHIFT, 0, 0, 0, 0};
|
uint32_t blocks[5] = {T55x7_MODULATION_DIPHASE | T55x7_BITRATE_RF_32 | 4 << T55x7_MAXBLOCK_SHIFT, 0, 0, 0, 0};
|
||||||
|
|
||||||
//Q5
|
//Q5
|
||||||
if (tolower(param_getchar(Cmd, 2)) == 'q')
|
bool q5 = tolower(param_getchar(Cmd, 2)) == 'q';
|
||||||
blocks[0] = T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(32) | 4 << T5555_MAXBLOCK_SHIFT;
|
if (q5)
|
||||||
|
blocks[0] = T5555_FIXED | T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(32) | 4 << T5555_MAXBLOCK_SHIFT;
|
||||||
|
|
||||||
// convert from bit stream to block data
|
// convert from bit stream to block data
|
||||||
blocks[1] = bytebits_to_byte(bits, 32);
|
blocks[1] = bytebits_to_byte(bits, 32);
|
||||||
|
@ -332,7 +362,7 @@ static int CmdFdxClone(const char *Cmd) {
|
||||||
|
|
||||||
free(bits);
|
free(bits);
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "Preparing to clone FDX-B to T55x7 with animal ID: " _GREEN_("%04u-%"PRIu64)" (extended 0x%X)", countryid, animalid, extended);
|
PrintAndLogEx(INFO, "Preparing to clone FDX-B to " _YELLOW_("%s") " with animal ID: " _GREEN_("%04u-%"PRIu64)" (extended 0x%X)", (q5) ? "Q5/T5555" : "T55x7", countryid, animalid, extended);
|
||||||
print_blocks(blocks, ARRAYLEN(blocks));
|
print_blocks(blocks, ARRAYLEN(blocks));
|
||||||
|
|
||||||
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
|
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
|
||||||
|
@ -392,8 +422,8 @@ static int CmdFdxSim(const char *Cmd) {
|
||||||
static command_t CommandTable[] = {
|
static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "this help"},
|
{"help", CmdHelp, AlwaysAvailable, "this help"},
|
||||||
{"demod", CmdFdxDemod, AlwaysAvailable, "demodulate a FDX-B ISO11784/85 tag from the GraphBuffer"},
|
{"demod", CmdFdxDemod, AlwaysAvailable, "demodulate a FDX-B ISO11784/85 tag from the GraphBuffer"},
|
||||||
{"read", CmdFdxRead, IfPm3Lf, "attempt to read and extract tag data"},
|
{"read", CmdFdxRead, IfPm3Lf, "attempt to read at 134kHz and extract tag data"},
|
||||||
{"clone", CmdFdxClone, IfPm3Lf, "clone animal ID tag to T55x7 (or to q5/T5555)"},
|
{"clone", CmdFdxClone, IfPm3Lf, "clone animal ID tag to T55x7 or Q5/T5555"},
|
||||||
{"sim", CmdFdxSim, IfPm3Lf, "simulate Animal ID tag"},
|
{"sim", CmdFdxSim, IfPm3Lf, "simulate Animal ID tag"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
|
@ -103,9 +103,9 @@ static int CmdGallagherDemod(const char *Cmd) {
|
||||||
for (int i = 0, pos = 0; i < ARRAYLEN(arr); i++) {
|
for (int i = 0, pos = 0; i < ARRAYLEN(arr); i++) {
|
||||||
pos = (i * 8) + i;
|
pos = (i * 8) + i;
|
||||||
arr[i] = bytebits_to_byte(DemodBuffer + pos, 8);
|
arr[i] = bytebits_to_byte(DemodBuffer + pos, 8);
|
||||||
printf("%d -", pos);
|
PrintAndLogEx(NORMAL, "%d -" NOLF, pos);
|
||||||
}
|
}
|
||||||
printf("\n");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
// crc
|
// crc
|
||||||
uint8_t crc = bytebits_to_byte(DemodBuffer + 72, 8);
|
uint8_t crc = bytebits_to_byte(DemodBuffer + 72, 8);
|
||||||
|
|
|
@ -27,15 +27,16 @@
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
static int usage_lf_guard_clone(void) {
|
static int usage_lf_guard_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, "clone a Guardall tag to a T55x7 tag.");
|
PrintAndLogEx(NORMAL, "clone a Guardall tag to a T55x7 or Q5/T5555 tag.");
|
||||||
PrintAndLogEx(NORMAL, "The facility-code is 8-bit and the card number is 16-bit. Larger values are truncated. ");
|
PrintAndLogEx(NORMAL, "The facility-code is 8-bit and the card number is 16-bit. Larger values are truncated. ");
|
||||||
PrintAndLogEx(NORMAL, "Currently work only on 26bit");
|
PrintAndLogEx(NORMAL, "Currently work only on 26bit");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf gprox clone [h] <format> <Facility-Code> <Card-Number>");
|
PrintAndLogEx(NORMAL, "Usage: lf gprox clone [h] <format> <Facility-Code> <Card-Number> <Q5>");
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
PrintAndLogEx(NORMAL, "Options:");
|
||||||
PrintAndLogEx(NORMAL, " <format> : format length 26|32|36|40");
|
PrintAndLogEx(NORMAL, " <format> : format length 26|32|36|40");
|
||||||
PrintAndLogEx(NORMAL, " <Facility-Code> : 8-bit value facility code");
|
PrintAndLogEx(NORMAL, " <Facility-Code> : 8-bit value facility code");
|
||||||
PrintAndLogEx(NORMAL, " <Card Number> : 16-bit value card number");
|
PrintAndLogEx(NORMAL, " <Card Number> : 16-bit value card number");
|
||||||
|
PrintAndLogEx(NORMAL, " <Q5> : Specify writing to Q5/T5555 tag");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf gprox clone 26 123 11223"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf gprox clone 26 123 11223"));
|
||||||
|
@ -175,8 +176,9 @@ static int CmdGuardClone(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Q5
|
// Q5
|
||||||
if (param_getchar(Cmd, 3) == 'Q' || param_getchar(Cmd, 3) == 'q')
|
bool q5 = tolower(param_getchar(Cmd, 3)) == 'q';
|
||||||
blocks[0] = T5555_MODULATION_FSK2 | T5555_SET_BITRATE(50) | 3 << T5555_MAXBLOCK_SHIFT;
|
if (q5)
|
||||||
|
blocks[0] = T5555_FIXED | T5555_MODULATION_FSK2 | T5555_SET_BITRATE(50) | 3 << T5555_MAXBLOCK_SHIFT;
|
||||||
|
|
||||||
blocks[1] = bytebits_to_byte(bs, 32);
|
blocks[1] = bytebits_to_byte(bs, 32);
|
||||||
blocks[2] = bytebits_to_byte(bs + 32, 32);
|
blocks[2] = bytebits_to_byte(bs + 32, 32);
|
||||||
|
@ -184,7 +186,7 @@ static int CmdGuardClone(const char *Cmd) {
|
||||||
|
|
||||||
free(bs);
|
free(bs);
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "Preparing to clone Guardall to T55x7 with Facility Code: %u, Card Number: %u", facilitycode, cardnumber);
|
PrintAndLogEx(INFO, "Preparing to clone Guardall to " _YELLOW_("%s") " with Facility Code: %u, Card Number: %u", (q5) ? "Q5/T5555" : "T55x7", facilitycode, cardnumber);
|
||||||
print_blocks(blocks, ARRAYLEN(blocks));
|
print_blocks(blocks, ARRAYLEN(blocks));
|
||||||
|
|
||||||
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
|
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
|
||||||
|
@ -241,7 +243,7 @@ static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "this help"},
|
{"help", CmdHelp, AlwaysAvailable, "this help"},
|
||||||
{"demod", CmdGuardDemod, AlwaysAvailable, "demodulate a G Prox II tag from the GraphBuffer"},
|
{"demod", CmdGuardDemod, AlwaysAvailable, "demodulate a G Prox II tag from the GraphBuffer"},
|
||||||
{"read", CmdGuardRead, IfPm3Lf, "attempt to read and extract tag data from the antenna"},
|
{"read", CmdGuardRead, IfPm3Lf, "attempt to read and extract tag data from the antenna"},
|
||||||
{"clone", CmdGuardClone, IfPm3Lf, "clone Guardall tag to T55x7"},
|
{"clone", CmdGuardClone, IfPm3Lf, "clone Guardall tag to T55x7 or Q5/T5555"},
|
||||||
{"sim", CmdGuardSim, IfPm3Lf, "simulate Guardall tag"},
|
{"sim", CmdGuardSim, IfPm3Lf, "simulate Guardall tag"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
|
@ -557,7 +557,7 @@ static int CmdIndalaClone(const char *Cmd) {
|
||||||
|
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "lf indala clone",
|
CLIParserInit(&ctx, "lf indala clone",
|
||||||
"clone INDALA tag to T55x7 (or to q5/T5555)",
|
"clone INDALA UID to T55x7 or Q5/T5555 tag",
|
||||||
"Examples:\n"
|
"Examples:\n"
|
||||||
_YELLOW_("\tlf indala clone --heden 888\n")
|
_YELLOW_("\tlf indala clone --heden 888\n")
|
||||||
_YELLOW_("\tlf indala clone --fc 123 --cn 1337\n")
|
_YELLOW_("\tlf indala clone --fc 123 --cn 1337\n")
|
||||||
|
@ -566,11 +566,11 @@ static int CmdIndalaClone(const char *Cmd) {
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
arg_lit0("lL", "long", "optional - long UID 224 bits"),
|
arg_lit0("lL", "long", "optional - long UID 224 bits"),
|
||||||
arg_int0("cC", "heden", "<decimal>", "Cardnumber for Heden 2L format"),
|
arg_int0("cC", "heden", "<decimal>", "Cardnumber for Heden 2L format"),
|
||||||
arg_strx0("rR", "raw", "<hex>", "raw bytes"),
|
arg_strx0("rR", "raw", "<hex>", "raw bytes"),
|
||||||
arg_lit0("qQ", "Q5", "optional - specify write to Q5 (t5555 instead of t55x7)"),
|
arg_lit0("qQ", "Q5", "optional - specify writing to Q5/T5555 tag"),
|
||||||
arg_int0("", "fc", "<decimal>", "Facility Code (26 bit format)"),
|
arg_int0("", "fc", "<decimal>", "Facility Code (26 bit format)"),
|
||||||
arg_int0("", "cn", "<decimal>", "Cardnumber (26 bit format)"),
|
arg_int0("", "cn", "<decimal>", "Cardnumber (26 bit format)"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
|
@ -604,7 +604,7 @@ static int CmdIndalaClone(const char *Cmd) {
|
||||||
PrintAndLogEx(INFO, "RawID %s", sprint_hex(data, datalen));
|
PrintAndLogEx(INFO, "RawID %s", sprint_hex(data, datalen));
|
||||||
|
|
||||||
if (is_t5555)
|
if (is_t5555)
|
||||||
blocks[0] = T5555_SET_BITRATE(32) | T5555_MODULATION_PSK2 | (7 << T5555_MAXBLOCK_SHIFT);
|
blocks[0] = T5555_FIXED | T5555_SET_BITRATE(32) | T5555_MODULATION_PSK2 | (7 << T5555_MAXBLOCK_SHIFT);
|
||||||
else
|
else
|
||||||
blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK2 | (7 << T55x7_MAXBLOCK_SHIFT);
|
blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK2 | (7 << T55x7_MAXBLOCK_SHIFT);
|
||||||
|
|
||||||
|
@ -656,7 +656,7 @@ static int CmdIndalaClone(const char *Cmd) {
|
||||||
PrintAndLogEx(INFO, "RawID %s", sprint_hex(data, datalen));
|
PrintAndLogEx(INFO, "RawID %s", sprint_hex(data, datalen));
|
||||||
|
|
||||||
if (is_t5555)
|
if (is_t5555)
|
||||||
blocks[0] = T5555_SET_BITRATE(32) | T5555_MODULATION_PSK1 | (2 << T5555_MAXBLOCK_SHIFT);
|
blocks[0] = T5555_FIXED | T5555_SET_BITRATE(32) | T5555_MODULATION_PSK1 | (2 << T5555_MAXBLOCK_SHIFT);
|
||||||
else
|
else
|
||||||
blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (2 << T55x7_MAXBLOCK_SHIFT);
|
blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (2 << T55x7_MAXBLOCK_SHIFT);
|
||||||
|
|
||||||
|
@ -677,7 +677,7 @@ static command_t CommandTable[] = {
|
||||||
{"demod", CmdIndalaDemod, AlwaysAvailable, "demodulate an indala tag (PSK1) from GraphBuffer"},
|
{"demod", CmdIndalaDemod, AlwaysAvailable, "demodulate an indala tag (PSK1) from GraphBuffer"},
|
||||||
{"altdemod", CmdIndalaDemodAlt, AlwaysAvailable, "alternative method to Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
|
{"altdemod", CmdIndalaDemodAlt, AlwaysAvailable, "alternative method to Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
|
||||||
{"read", CmdIndalaRead, IfPm3Lf, "read an Indala Prox tag from the antenna"},
|
{"read", CmdIndalaRead, IfPm3Lf, "read an Indala Prox tag from the antenna"},
|
||||||
{"clone", CmdIndalaClone, IfPm3Lf, "clone Indala tag to T55x7"},
|
{"clone", CmdIndalaClone, IfPm3Lf, "clone Indala tag to T55x7 or Q5/T5555"},
|
||||||
{"sim", CmdIndalaSim, IfPm3Lf, "simulate Indala tag"},
|
{"sim", CmdIndalaSim, IfPm3Lf, "simulate Indala tag"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
|
@ -59,16 +59,16 @@ static int usage_lf_io_sim(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usage_lf_io_clone(void) {
|
static int usage_lf_io_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, "Enables cloning of IOProx card with specified facility-code and card number onto T55x7.");
|
PrintAndLogEx(NORMAL, "Enables cloning of IOProx card with specified facility-code and card number onto T55x7 or Q5/T5555 tag");
|
||||||
PrintAndLogEx(NORMAL, "The T55x7 must be on the antenna when issuing this command. T55x7 blocks are calculated and printed in the process.");
|
PrintAndLogEx(NORMAL, "The T55x7 must be on the antenna when issuing this command. T55x7 blocks are calculated and printed in the process.");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf io clone [h] <version> <facility-code> <card-number> [Q5]");
|
PrintAndLogEx(NORMAL, "Usage: lf io clone [h] <version> <facility-code> <card-number> <Q5>");
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
PrintAndLogEx(NORMAL, "Options:");
|
||||||
PrintAndLogEx(NORMAL, " h : This help");
|
PrintAndLogEx(NORMAL, " h : This help");
|
||||||
PrintAndLogEx(NORMAL, " <version> : 8bit version (" _YELLOW_("decimal") ")");
|
PrintAndLogEx(NORMAL, " <version> : 8bit version (" _YELLOW_("decimal") ")");
|
||||||
PrintAndLogEx(NORMAL, " <facility-code> : 8bit value facility code (" _YELLOW_("hex") ")");
|
PrintAndLogEx(NORMAL, " <facility-code> : 8bit value facility code (" _YELLOW_("hex") ")");
|
||||||
PrintAndLogEx(NORMAL, " <card number> : 16bit value card number (" _YELLOW_("decimal") ")");
|
PrintAndLogEx(NORMAL, " <card number> : 16bit value card number (" _YELLOW_("decimal") ")");
|
||||||
PrintAndLogEx(NORMAL, " Q5 : optional - clone to Q5 (T5555) instead of T55x7 chip");
|
PrintAndLogEx(NORMAL, " <Q5> : optional - specify writing to Q5/T5555 tag");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf io clone 01 101 1337"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf io clone 01 101 1337"));
|
||||||
|
@ -274,13 +274,14 @@ static int CmdIOProxClone(const char *Cmd) {
|
||||||
|
|
||||||
uint32_t blocks[3] = {T55x7_MODULATION_FSK2a | T55x7_BITRATE_RF_64 | 2 << T55x7_MAXBLOCK_SHIFT, 0, 0};
|
uint32_t blocks[3] = {T55x7_MODULATION_FSK2a | T55x7_BITRATE_RF_64 | 2 << T55x7_MAXBLOCK_SHIFT, 0, 0};
|
||||||
|
|
||||||
if (tolower(param_getchar(Cmd, 3) == 'q'))
|
bool q5 = tolower(param_getchar(Cmd, 3) == 'q');
|
||||||
blocks[0] = T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(64) | 2 << T5555_MAXBLOCK_SHIFT;
|
if (q5)
|
||||||
|
blocks[0] = T5555_FIXED | T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(64) | 2 << T5555_MAXBLOCK_SHIFT;
|
||||||
|
|
||||||
blocks[1] = bytebits_to_byte(bits, 32);
|
blocks[1] = bytebits_to_byte(bits, 32);
|
||||||
blocks[2] = bytebits_to_byte(bits + 32, 32);
|
blocks[2] = bytebits_to_byte(bits + 32, 32);
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "Preparing to clone IOProx to T55x7 with Version: %u FC: %u, CN: %u", version, fc, cn);
|
PrintAndLogEx(INFO, "Preparing to clone IOProx to " _YELLOW_("%s") " with Version: %u FC: %u, CN: %u", (q5) ? "Q5/T5555" : "T55x7", version, fc, cn);
|
||||||
print_blocks(blocks, ARRAYLEN(blocks));
|
print_blocks(blocks, ARRAYLEN(blocks));
|
||||||
|
|
||||||
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
|
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
|
||||||
|
@ -293,7 +294,7 @@ static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "this help"},
|
{"help", CmdHelp, AlwaysAvailable, "this help"},
|
||||||
{"demod", CmdIOProxDemod, AlwaysAvailable, "demodulate an IOProx tag from the GraphBuffer"},
|
{"demod", CmdIOProxDemod, AlwaysAvailable, "demodulate an IOProx tag from the GraphBuffer"},
|
||||||
{"read", CmdIOProxRead, IfPm3Lf, "attempt to read and extract tag data"},
|
{"read", CmdIOProxRead, IfPm3Lf, "attempt to read and extract tag data"},
|
||||||
{"clone", CmdIOProxClone, IfPm3Lf, "clone IOProx tag to T55x7 (or to q5/T5555)"},
|
{"clone", CmdIOProxClone, IfPm3Lf, "clone IOProx tag to T55x7 or Q5/T5555"},
|
||||||
{"sim", CmdIOProxSim, IfPm3Lf, "simulate IOProx tag"},
|
{"sim", CmdIOProxSim, IfPm3Lf, "simulate IOProx tag"},
|
||||||
{"watch", CmdIOProxWatch, IfPm3Lf, "continuously watch for cards. Reader mode"},
|
{"watch", CmdIOProxWatch, IfPm3Lf, "continuously watch for cards. Reader mode"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
|
|
|
@ -30,12 +30,12 @@
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
static int usage_lf_jablotron_clone(void) {
|
static int usage_lf_jablotron_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, "clone a Jablotron tag to a T55x7 tag.");
|
PrintAndLogEx(NORMAL, "clone a Jablotron tag to a T55x7 or Q5/T5555 tag.");
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf jablotron clone [h] <card ID> <Q5>");
|
PrintAndLogEx(NORMAL, "Usage: lf jablotron clone [h] <card ID> <Q5>");
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
PrintAndLogEx(NORMAL, "Options:");
|
||||||
PrintAndLogEx(NORMAL, " h : This help");
|
PrintAndLogEx(NORMAL, " h : This help");
|
||||||
PrintAndLogEx(NORMAL, " <card ID> : jablotron card ID");
|
PrintAndLogEx(NORMAL, " <card ID> : jablotron card ID");
|
||||||
PrintAndLogEx(NORMAL, " <Q5> : specify write to Q5 (t5555 instead of t55x7)");
|
PrintAndLogEx(NORMAL, " <Q5> : specify writing to Q5/T5555 tag");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf jablotron clone 112233"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf jablotron clone 112233"));
|
||||||
|
@ -153,8 +153,9 @@ static int CmdJablotronClone(const char *Cmd) {
|
||||||
fullcode = param_get64ex(Cmd, 0, 0, 16);
|
fullcode = param_get64ex(Cmd, 0, 0, 16);
|
||||||
|
|
||||||
//Q5
|
//Q5
|
||||||
if (tolower(param_getchar(Cmd, 1)) == 'q')
|
bool q5 = tolower(param_getchar(Cmd, 1)) == 'q';
|
||||||
blocks[0] = T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(64) | 2 << T5555_MAXBLOCK_SHIFT;
|
if (q5)
|
||||||
|
blocks[0] = T5555_FIXED | T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(64) | 2 << T5555_MAXBLOCK_SHIFT;
|
||||||
|
|
||||||
// clearing the topbit needed for the preambl detection.
|
// clearing the topbit needed for the preambl detection.
|
||||||
if ((fullcode & 0x7FFFFFFFFF) != fullcode) {
|
if ((fullcode & 0x7FFFFFFFFF) != fullcode) {
|
||||||
|
@ -178,7 +179,7 @@ static int CmdJablotronClone(const char *Cmd) {
|
||||||
|
|
||||||
free(bits);
|
free(bits);
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "Preparing to clone Jablotron to T55x7 with FullCode: %"PRIx64, fullcode);
|
PrintAndLogEx(INFO, "Preparing to clone Jablotron to " _YELLOW_("%s") " with FullCode: %"PRIx64, (q5) ? "Q5/T5555" : "T55x7", fullcode);
|
||||||
print_blocks(blocks, ARRAYLEN(blocks));
|
print_blocks(blocks, ARRAYLEN(blocks));
|
||||||
|
|
||||||
return clone_t55xx_tag(blocks, ARRAYLEN(blocks));
|
return clone_t55xx_tag(blocks, ARRAYLEN(blocks));
|
||||||
|
@ -234,7 +235,7 @@ static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||||
{"demod", CmdJablotronDemod, AlwaysAvailable, "Demodulate an Jablotron tag from the GraphBuffer"},
|
{"demod", CmdJablotronDemod, AlwaysAvailable, "Demodulate an Jablotron tag from the GraphBuffer"},
|
||||||
{"read", CmdJablotronRead, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
|
{"read", CmdJablotronRead, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
|
||||||
{"clone", CmdJablotronClone, IfPm3Lf, "clone jablotron tag to T55x7 (or to q5/T5555)"},
|
{"clone", CmdJablotronClone, IfPm3Lf, "clone jablotron tag to T55x7 or Q5/T5555"},
|
||||||
{"sim", CmdJablotronSim, IfPm3Lf, "simulate jablotron tag"},
|
{"sim", CmdJablotronSim, IfPm3Lf, "simulate jablotron tag"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,21 +28,21 @@
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
static int usage_lf_keri_clone(void) {
|
static int usage_lf_keri_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, "clone a KERI tag to a T55x7 tag.");
|
PrintAndLogEx(NORMAL, "clone a KERI tag to a T55x7 or Q5/T5555 tag\n");
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf keri clone [h] <id> <Q5>");
|
PrintAndLogEx(NORMAL, "Usage: lf keri clone [h] <id> <Q5>");
|
||||||
PrintAndLogEx(NORMAL, "Usage extended: lf keri clone [h] t <m|i> [f <fc>] c <cardid> [Q5]");
|
PrintAndLogEx(NORMAL, "Usage extended: lf keri clone [h] t <m|i> [f <fc>] [c <cardnumber>] <Q5>");
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
PrintAndLogEx(NORMAL, "Options:");
|
||||||
PrintAndLogEx(NORMAL, " h : This help");
|
PrintAndLogEx(NORMAL, " h : This help");
|
||||||
PrintAndLogEx(NORMAL, " <id> : Keri Internal ID");
|
PrintAndLogEx(NORMAL, " <id> : Keri Internal ID");
|
||||||
PrintAndLogEx(NORMAL, " <Q5> : specify write to Q5 (t5555 instead of t55x7)");
|
PrintAndLogEx(NORMAL, " <Q5> : specify writing to Q5/T5555 tag");
|
||||||
// New format
|
// New format
|
||||||
PrintAndLogEx(NORMAL, " <t> [m|i] : Type. m - MS, i - Internal ID");
|
PrintAndLogEx(NORMAL, " <t> [m|i] : Type m - MS, i - Internal ID");
|
||||||
PrintAndLogEx(NORMAL, " <f> <fc> : Facility Code");
|
PrintAndLogEx(NORMAL, " <f> <fc> : Facility Code");
|
||||||
PrintAndLogEx(NORMAL, " <c> <cn> : Card Number");
|
PrintAndLogEx(NORMAL, " <c> <cn> : Card Number");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf keri clone 112233"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf keri clone 112233"));
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf keri clone type ms fc 6 cn 12345"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf keri clone t i fc 6 cn 12345"));
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf keri clone t m f 6 c 12345"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf keri clone t m f 6 c 12345"));
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
|
@ -212,8 +212,6 @@ int demodKeri(void) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int CmdKeriRead(const char *Cmd) {
|
static int CmdKeriRead(const char *Cmd) {
|
||||||
lf_read(false, 10000);
|
lf_read(false, 10000);
|
||||||
return CmdKeriDemod(Cmd);
|
return CmdKeriDemod(Cmd);
|
||||||
|
@ -221,6 +219,7 @@ static int CmdKeriRead(const char *Cmd) {
|
||||||
|
|
||||||
static int CmdKeriClone(const char *Cmd) {
|
static int CmdKeriClone(const char *Cmd) {
|
||||||
|
|
||||||
|
bool q5 = false;
|
||||||
uint8_t cmdidx = 0;
|
uint8_t cmdidx = 0;
|
||||||
char keritype = 'i'; // default to internalid
|
char keritype = 'i'; // default to internalid
|
||||||
uint32_t fc = 0;
|
uint32_t fc = 0;
|
||||||
|
@ -263,11 +262,8 @@ static int CmdKeriClone(const char *Cmd) {
|
||||||
cmdidx += 2;
|
cmdidx += 2;
|
||||||
break;
|
break;
|
||||||
case 'q': // q5
|
case 'q': // q5
|
||||||
blocks[0] =
|
blocks[0] = T5555_FIXED | T5555_MODULATION_PSK1 | T5555_SET_BITRATE(32) | T5555_PSK_RF_2 | 2 << T5555_MAXBLOCK_SHIFT;
|
||||||
T5555_MODULATION_PSK1 |
|
q5 = true;
|
||||||
T5555_SET_BITRATE(128) |
|
|
||||||
T5555_PSK_RF_2 |
|
|
||||||
2 << T5555_MAXBLOCK_SHIFT;
|
|
||||||
cmdidx++;
|
cmdidx++;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -290,7 +286,7 @@ static int CmdKeriClone(const char *Cmd) {
|
||||||
// Prepare and write to card
|
// Prepare and write to card
|
||||||
// 3 LSB is ONE
|
// 3 LSB is ONE
|
||||||
uint64_t data = ((uint64_t)internalid << 3) + 7;
|
uint64_t data = ((uint64_t)internalid << 3) + 7;
|
||||||
PrintAndLogEx(INFO, "Preparing to clone KERI to T55x7 with Internal Id: %" PRIx32, internalid);
|
PrintAndLogEx(INFO, "Preparing to clone KERI to " _YELLOW_("%s") " with Internal Id " _YELLOW_("%" PRIx32), (q5) ? "Q5/T5555" : "T55x7", internalid);
|
||||||
|
|
||||||
blocks[1] = data >> 32;
|
blocks[1] = data >> 32;
|
||||||
blocks[2] = data & 0xFFFFFFFF;
|
blocks[2] = data & 0xFFFFFFFF;
|
||||||
|
@ -348,7 +344,7 @@ static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||||
{"demod", CmdKeriDemod, AlwaysAvailable, "Demodulate an KERI tag from the GraphBuffer"},
|
{"demod", CmdKeriDemod, AlwaysAvailable, "Demodulate an KERI tag from the GraphBuffer"},
|
||||||
{"read", CmdKeriRead, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
|
{"read", CmdKeriRead, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
|
||||||
{"clone", CmdKeriClone, IfPm3Lf, "clone KERI tag to T55x7 (or to q5/T5555)"},
|
{"clone", CmdKeriClone, IfPm3Lf, "clone KERI tag to T55x7 or Q5/T5555"},
|
||||||
{"sim", CmdKeriSim, IfPm3Lf, "simulate KERI tag"},
|
{"sim", CmdKeriSim, IfPm3Lf, "simulate KERI tag"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
@ -370,21 +366,25 @@ int detectKeri(uint8_t *dest, size_t *size, bool *invert) {
|
||||||
uint8_t preamble[] = {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
|
uint8_t preamble[] = {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
|
||||||
|
|
||||||
// sanity check.
|
// sanity check.
|
||||||
if (*size < sizeof(preamble) + 100) return -1;
|
if (*size < sizeof(preamble)) return -1;
|
||||||
|
|
||||||
size_t startIdx = 0;
|
size_t startIdx = 0;
|
||||||
|
size_t found_size = *size;
|
||||||
|
|
||||||
if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) {
|
if (!preambleSearch(dest, preamble, sizeof(preamble), &found_size, &startIdx)) {
|
||||||
|
|
||||||
|
found_size = *size;
|
||||||
// if didn't find preamble try again inverting
|
// if didn't find preamble try again inverting
|
||||||
uint8_t preamble_i[] = {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0};
|
uint8_t preamble_i[] = {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0};
|
||||||
if (!preambleSearch(DemodBuffer, preamble_i, sizeof(preamble_i), size, &startIdx))
|
if (!preambleSearch(DemodBuffer, preamble_i, sizeof(preamble_i), &found_size, &startIdx))
|
||||||
return -2;
|
return -2;
|
||||||
|
|
||||||
*invert ^= 1;
|
*invert ^= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*size < 64) return -3; //wrong demoded size
|
if (found_size < 64) return -3; //wrong demoded size
|
||||||
|
|
||||||
|
*size = found_size;
|
||||||
|
|
||||||
return (int)startIdx;
|
return (int)startIdx;
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,7 +173,7 @@ static int CmdMotorolaClone(const char *Cmd) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
//TODO add selection of chip for Q5 or T55x7
|
//TODO add selection of chip for Q5 or T55x7
|
||||||
// data[0] = T5555_SET_BITRATE(32 | T5555_MODULATION_PSK1 | 2 << T5555_MAXBLOCK_SHIFT;
|
// data[0] = T5555_FIXED | T5555_SET_BITRATE(32 | T5555_MODULATION_PSK1 | 2 << T5555_MAXBLOCK_SHIFT;
|
||||||
|
|
||||||
// config for Motorola 64 format (RF/32;PSK1 with RF/2; Maxblock=2)
|
// config for Motorola 64 format (RF/32;PSK1 with RF/2; Maxblock=2)
|
||||||
PrintAndLogEx(INFO, "Preparing to clone Motorola 64bit tag with RawID %s", sprint_hex(data, datalen));
|
PrintAndLogEx(INFO, "Preparing to clone Motorola 64bit tag with RawID %s", sprint_hex(data, datalen));
|
||||||
|
|
|
@ -9,18 +9,21 @@
|
||||||
|
|
||||||
#include "cmdlfnedap.h"
|
#include "cmdlfnedap.h"
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "cmdparser.h" // command_t
|
#include "cmdparser.h" // command_t
|
||||||
#include "comms.h"
|
#include "comms.h"
|
||||||
#include "crc16.h"
|
#include "crc16.h"
|
||||||
#include "cmdlft55xx.h" // verifywrite
|
#include "cmdlft55xx.h" // verify write
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "cmddata.h"
|
#include "cmddata.h"
|
||||||
#include "cmdlf.h"
|
#include "cmdlf.h"
|
||||||
#include "lfdemod.h"
|
#include "lfdemod.h"
|
||||||
|
#include "protocols.h"
|
||||||
|
|
||||||
#define FIXED_71 0x71
|
#define FIXED_71 0x71
|
||||||
#define FIXED_40 0x40
|
#define FIXED_40 0x40
|
||||||
|
@ -47,16 +50,16 @@ static int usage_lf_nedap_gen(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usage_lf_nedap_clone(void) {
|
static int usage_lf_nedap_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, "clone a Nedap tag to a T55x7 tag.");
|
PrintAndLogEx(NORMAL, "clone a Nedap tag to a T55x7 or Q5/T5555 tag.");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf nedap clone [h] [s <subtype>] c <code> i <id> [l]");
|
PrintAndLogEx(NORMAL, "Usage: lf nedap clone [h] [s <subtype>] c <code> i <id> [l] <Q5>");
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
PrintAndLogEx(NORMAL, "Options:");
|
||||||
PrintAndLogEx(NORMAL, " h : This help");
|
PrintAndLogEx(NORMAL, " h : This help");
|
||||||
PrintAndLogEx(NORMAL, " s <subtype> : optional, default=5");
|
PrintAndLogEx(NORMAL, " s <subtype> : optional, default=5");
|
||||||
PrintAndLogEx(NORMAL, " c <code> : customerCode");
|
PrintAndLogEx(NORMAL, " c <code> : customerCode");
|
||||||
PrintAndLogEx(NORMAL, " i <id> : ID (max 99999)");
|
PrintAndLogEx(NORMAL, " i <id> : ID (max 99999)");
|
||||||
PrintAndLogEx(NORMAL, " l : optional - long (128), default to short (64)");
|
PrintAndLogEx(NORMAL, " l : optional - long (128), default to short (64)");
|
||||||
// PrintAndLogEx(NORMAL, " Q5 : optional - clone to Q5 (T5555) instead of T55x7 chip");
|
PrintAndLogEx(NORMAL, " Q5 : optional - specify writing to Q5/T5555 tag");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf nedap clone s 1 c 123 i 12345"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf nedap clone s 1 c 123 i 12345"));
|
||||||
|
@ -399,6 +402,9 @@ static int CmdLfNedapGen(const char *Cmd) {
|
||||||
isLong = true;
|
isLong = true;
|
||||||
cmdp++;
|
cmdp++;
|
||||||
break;
|
break;
|
||||||
|
case 'q':
|
||||||
|
cmdp++;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||||
errors = true;
|
errors = true;
|
||||||
|
@ -449,14 +455,8 @@ static int CmdLFNedapClone(const char *Cmd) {
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
//CmdPrintDemodBuff("x");
|
|
||||||
|
|
||||||
// What we had before in commented code:
|
|
||||||
//NEDAP - compat mode, ASK/DIphase, data rate 64, 4 data blocks
|
//NEDAP - compat mode, ASK/DIphase, data rate 64, 4 data blocks
|
||||||
// DI-phase (CDP) T55x7_MODULATION_DIPHASE
|
// DI-phase (CDP) T55x7_MODULATION_DIPHASE
|
||||||
// blocks[0] = T55x7_MODULATION_DIPHASE | T55x7_BITRATE_RF_64 | 7 << T55x7_MAXBLOCK_SHIFT;
|
|
||||||
// if (param_getchar(Cmd, 3) == 'Q' || param_getchar(Cmd, 3) == 'q')
|
|
||||||
// blocks[0] = T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(64) | 7 <<T5555_MAXBLOCK_SHIFT;
|
|
||||||
|
|
||||||
if (DemodBufferLen == 64) {
|
if (DemodBufferLen == 64) {
|
||||||
max = 3;
|
max = 3;
|
||||||
|
@ -465,12 +465,20 @@ static int CmdLFNedapClone(const char *Cmd) {
|
||||||
max = 5;
|
max = 5;
|
||||||
blocks[0] = T55X7_NEDAP_128_CONFIG_BLOCK;
|
blocks[0] = T55X7_NEDAP_128_CONFIG_BLOCK;
|
||||||
}
|
}
|
||||||
|
bool q5 = (strstr(Cmd, "q") != NULL);
|
||||||
|
if (q5) {
|
||||||
|
if (DemodBufferLen == 64) {
|
||||||
|
blocks[0] = T5555_FIXED | T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(64) | 2 << T5555_MAXBLOCK_SHIFT;
|
||||||
|
} else {
|
||||||
|
blocks[0] = T5555_FIXED | T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(64) | 4 << T5555_MAXBLOCK_SHIFT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (uint8_t i = 1; i < max ; i++) {
|
for (uint8_t i = 1; i < max ; i++) {
|
||||||
blocks[i] = bytebits_to_byte(DemodBuffer + ((i - 1) * 32), 32);
|
blocks[i] = bytebits_to_byte(DemodBuffer + ((i - 1) * 32), 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "Preparing to clone NEDAP to T55x7");
|
PrintAndLogEx(SUCCESS, "Preparing to clone NEDAP to " _YELLOW_("%s") " tag", (q5) ? "Q5/T5555" : "T55x7");
|
||||||
print_blocks(blocks, max);
|
print_blocks(blocks, max);
|
||||||
|
|
||||||
int res = clone_t55xx_tag(blocks, max);
|
int res = clone_t55xx_tag(blocks, max);
|
||||||
|
@ -531,7 +539,7 @@ static command_t CommandTable[] = {
|
||||||
{"demod", CmdLFNedapDemod, AlwaysAvailable, "Demodulate Nedap tag from the GraphBuffer"},
|
{"demod", CmdLFNedapDemod, AlwaysAvailable, "Demodulate Nedap tag from the GraphBuffer"},
|
||||||
{"generate", CmdLfNedapGen, AlwaysAvailable, "Generate Nedap bitstream in DemodBuffer"},
|
{"generate", CmdLfNedapGen, AlwaysAvailable, "Generate Nedap bitstream in DemodBuffer"},
|
||||||
{"read", CmdLFNedapRead, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
|
{"read", CmdLFNedapRead, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
|
||||||
{"clone", CmdLFNedapClone, IfPm3Lf, "Clone Nedap tag to T55x7"},
|
{"clone", CmdLFNedapClone, IfPm3Lf, "Clone Nedap tag to T55x7 or Q5/T5555"},
|
||||||
{"sim", CmdLFNedapSim, IfPm3Lf, "Simulate Nedap tag"},
|
{"sim", CmdLFNedapSim, IfPm3Lf, "Simulate Nedap tag"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,13 +26,13 @@
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
static int usage_lf_noralsy_clone(void) {
|
static int usage_lf_noralsy_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, "clone a Noralsy tag to a T55x7 tag.");
|
PrintAndLogEx(NORMAL, "clone a Noralsy tag to a T55x7 or Q5/T5555 tag.");
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf noralsy clone [h] <card id> <year> <Q5>");
|
PrintAndLogEx(NORMAL, "Usage: lf noralsy clone [h] <card id> <year> <Q5>");
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
PrintAndLogEx(NORMAL, "Options:");
|
||||||
PrintAndLogEx(NORMAL, " h : This help");
|
PrintAndLogEx(NORMAL, " h : This help");
|
||||||
PrintAndLogEx(NORMAL, " <card id> : Noralsy card ID");
|
PrintAndLogEx(NORMAL, " <card id> : Noralsy card ID");
|
||||||
PrintAndLogEx(NORMAL, " <year> : Tag allocation year");
|
PrintAndLogEx(NORMAL, " <year> : Tag allocation year");
|
||||||
PrintAndLogEx(NORMAL, " <Q5> : specify write to Q5 (t5555 instead of t55x7)");
|
PrintAndLogEx(NORMAL, " <Q5> : specify writing to Q5/T5555 tag");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf noralsy clone 112233"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf noralsy clone 112233"));
|
||||||
|
@ -150,8 +150,9 @@ static int CmdNoralsyClone(const char *Cmd) {
|
||||||
year = param_get32ex(Cmd, 1, 2000, 10);
|
year = param_get32ex(Cmd, 1, 2000, 10);
|
||||||
|
|
||||||
//Q5
|
//Q5
|
||||||
if (tolower(param_getchar(Cmd, 2) == 'q'))
|
bool q5 = tolower(param_getchar(Cmd, 2) == 'q');
|
||||||
blocks[0] = T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(32) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT;
|
if (q5)
|
||||||
|
blocks[0] = T5555_FIXED | T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(32) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT;
|
||||||
|
|
||||||
uint8_t *bits = calloc(96, sizeof(uint8_t));
|
uint8_t *bits = calloc(96, sizeof(uint8_t));
|
||||||
if (getnoralsyBits(id, year, bits) != PM3_SUCCESS) {
|
if (getnoralsyBits(id, year, bits) != PM3_SUCCESS) {
|
||||||
|
@ -166,7 +167,7 @@ static int CmdNoralsyClone(const char *Cmd) {
|
||||||
|
|
||||||
free(bits);
|
free(bits);
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "Preparing to clone Noralsy to T55x7 with CardId: %u", id);
|
PrintAndLogEx(INFO, "Preparing to clone Noralsy to " _YELLOW_("%s") " with CardId: %u", (q5) ? "Q5/T5555" : "T55x7", id);
|
||||||
print_blocks(blocks, ARRAYLEN(blocks));
|
print_blocks(blocks, ARRAYLEN(blocks));
|
||||||
|
|
||||||
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
|
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
|
||||||
|
@ -222,7 +223,7 @@ static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||||
{"demod", CmdNoralsyDemod, AlwaysAvailable, "Demodulate an Noralsy tag from the GraphBuffer"},
|
{"demod", CmdNoralsyDemod, AlwaysAvailable, "Demodulate an Noralsy tag from the GraphBuffer"},
|
||||||
{"read", CmdNoralsyRead, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
|
{"read", CmdNoralsyRead, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
|
||||||
{"clone", CmdNoralsyClone, IfPm3Lf, "clone Noralsy tag to T55x7 (or to q5/T5555)"},
|
{"clone", CmdNoralsyClone, IfPm3Lf, "clone Noralsy tag to T55x7 or Q5/T5555"},
|
||||||
{"sim", CmdNoralsySim, IfPm3Lf, "simulate Noralsy tag"},
|
{"sim", CmdNoralsySim, IfPm3Lf, "simulate Noralsy tag"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,13 +27,13 @@
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
static int usage_lf_presco_clone(void) {
|
static int usage_lf_presco_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, "clone a Presco tag to a T55x7 tag.");
|
PrintAndLogEx(NORMAL, "clone a Presco tag to a T55x7 or Q5/T5555 tag.");
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf presco clone [h] d <Card-ID> c <hex-ID> <Q5>");
|
PrintAndLogEx(NORMAL, "Usage: lf presco clone [h] d <Card-ID> c <hex-ID> <Q5>");
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
PrintAndLogEx(NORMAL, "Options:");
|
||||||
PrintAndLogEx(NORMAL, " h : this help");
|
PrintAndLogEx(NORMAL, " h : this help");
|
||||||
PrintAndLogEx(NORMAL, " d <Card-ID> : 9 digit presco card ID");
|
PrintAndLogEx(NORMAL, " d <Card-ID> : 9 digit presco card ID");
|
||||||
PrintAndLogEx(NORMAL, " c <hex-ID> : 8 digit hex card number");
|
PrintAndLogEx(NORMAL, " c <hex-ID> : 8 digit hex card number");
|
||||||
PrintAndLogEx(NORMAL, " <Q5> : specify write to Q5 (t5555 instead of t55x7)");
|
PrintAndLogEx(NORMAL, " <Q5> : specify writing to Q5/T5555 tag");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf presco clone d 123456789"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf presco clone d 123456789"));
|
||||||
|
@ -116,7 +116,7 @@ static int CmdPrescoClone(const char *Cmd) {
|
||||||
if (getWiegandFromPresco(Cmd, &sitecode, &usercode, &fullcode, &Q5) == PM3_EINVARG) return usage_lf_presco_clone();
|
if (getWiegandFromPresco(Cmd, &sitecode, &usercode, &fullcode, &Q5) == PM3_EINVARG) return usage_lf_presco_clone();
|
||||||
|
|
||||||
if (Q5)
|
if (Q5)
|
||||||
blocks[0] = T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(32) | 4 << T5555_MAXBLOCK_SHIFT | T5555_ST_TERMINATOR;
|
blocks[0] = T5555_FIXED | T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(32) | 4 << T5555_MAXBLOCK_SHIFT | T5555_ST_TERMINATOR;
|
||||||
|
|
||||||
if ((sitecode & 0xFF) != sitecode) {
|
if ((sitecode & 0xFF) != sitecode) {
|
||||||
sitecode &= 0xFF;
|
sitecode &= 0xFF;
|
||||||
|
@ -133,7 +133,7 @@ static int CmdPrescoClone(const char *Cmd) {
|
||||||
blocks[3] = 0x00000000;
|
blocks[3] = 0x00000000;
|
||||||
blocks[4] = fullcode;
|
blocks[4] = fullcode;
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "Preparing to clone Presco to T55x7 with SiteCode: %u, UserCode: %u, FullCode: %08x", sitecode, usercode, fullcode);
|
PrintAndLogEx(INFO, "Preparing to clone Presco to " _YELLOW_("%s") " with SiteCode: %u, UserCode: %u, FullCode: %08x", (Q5) ? "Q5/T5555" : "T55x7", sitecode, usercode, fullcode);
|
||||||
print_blocks(blocks, ARRAYLEN(blocks));
|
print_blocks(blocks, ARRAYLEN(blocks));
|
||||||
|
|
||||||
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
|
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
|
||||||
|
@ -179,7 +179,7 @@ static int CmdPrescoSim(const char *Cmd) {
|
||||||
static command_t CommandTable[] = {
|
static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||||
{"read", CmdPrescoRead, IfPm3Lf, "Attempt to read and Extract tag data"},
|
{"read", CmdPrescoRead, IfPm3Lf, "Attempt to read and Extract tag data"},
|
||||||
{"clone", CmdPrescoClone, IfPm3Lf, "clone presco tag to T55x7 (or to q5/T5555)"},
|
{"clone", CmdPrescoClone, IfPm3Lf, "clone presco tag to T55x7 or Q5/T5555"},
|
||||||
{"sim", CmdPrescoSim, IfPm3Lf, "simulate presco tag"},
|
{"sim", CmdPrescoSim, IfPm3Lf, "simulate presco tag"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
static int usage_lf_pyramid_clone(void) {
|
static int usage_lf_pyramid_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, "clone a Farpointe/Pyramid tag to a T55x7 tag.");
|
PrintAndLogEx(NORMAL, "clone a Farpointe/Pyramid tag to a T55x7 or Q5/T5555 tag.");
|
||||||
PrintAndLogEx(NORMAL, "The facility-code is 8-bit and the card number is 16-bit. Larger values are truncated. ");
|
PrintAndLogEx(NORMAL, "The facility-code is 8-bit and the card number is 16-bit. Larger values are truncated. ");
|
||||||
PrintAndLogEx(NORMAL, "Currently only works on 26bit");
|
PrintAndLogEx(NORMAL, "Currently only works on 26bit");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
@ -40,7 +40,7 @@ static int usage_lf_pyramid_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, " h : this help");
|
PrintAndLogEx(NORMAL, " h : this help");
|
||||||
PrintAndLogEx(NORMAL, " <Facility-Code> : 8-bit value facility code");
|
PrintAndLogEx(NORMAL, " <Facility-Code> : 8-bit value facility code");
|
||||||
PrintAndLogEx(NORMAL, " <Card Number> : 16-bit value card number");
|
PrintAndLogEx(NORMAL, " <Card Number> : 16-bit value card number");
|
||||||
PrintAndLogEx(NORMAL, " Q5 : optional - clone to Q5 (T5555) instead of T55x7 chip");
|
PrintAndLogEx(NORMAL, " Q5 : optional - specify writing to Q5/T5555 tag");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf pyramid clone 123 11223"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf pyramid clone 123 11223"));
|
||||||
|
@ -242,8 +242,9 @@ static int CmdPyramidClone(const char *Cmd) {
|
||||||
blocks[0] = T55x7_MODULATION_FSK2a | T55x7_BITRATE_RF_50 | 4 << T55x7_MAXBLOCK_SHIFT;
|
blocks[0] = T55x7_MODULATION_FSK2a | T55x7_BITRATE_RF_50 | 4 << T55x7_MAXBLOCK_SHIFT;
|
||||||
|
|
||||||
// Q5
|
// Q5
|
||||||
if (param_getchar(Cmd, 2) == 'Q' || param_getchar(Cmd, 2) == 'q')
|
bool q5 = tolower(param_getchar(Cmd, 2)) == 'q';
|
||||||
blocks[0] = T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(50) | 4 << T5555_MAXBLOCK_SHIFT;
|
if (q5)
|
||||||
|
blocks[0] = T5555_FIXED | T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(50) | 4 << T5555_MAXBLOCK_SHIFT;
|
||||||
|
|
||||||
blocks[1] = bytebits_to_byte(bs, 32);
|
blocks[1] = bytebits_to_byte(bs, 32);
|
||||||
blocks[2] = bytebits_to_byte(bs + 32, 32);
|
blocks[2] = bytebits_to_byte(bs + 32, 32);
|
||||||
|
@ -252,7 +253,7 @@ static int CmdPyramidClone(const char *Cmd) {
|
||||||
|
|
||||||
free(bs);
|
free(bs);
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "Preparing to clone Farpointe/Pyramid to T55x7 with Facility Code: %u, Card Number: %u", facilitycode, cardnumber);
|
PrintAndLogEx(INFO, "Preparing to clone Farpointe/Pyramid to " _YELLOW_("%s") " with Facility Code: %u, Card Number: %u", (q5) ? "Q5/T5555" : "T55x7", facilitycode, cardnumber);
|
||||||
print_blocks(blocks, ARRAYLEN(blocks));
|
print_blocks(blocks, ARRAYLEN(blocks));
|
||||||
|
|
||||||
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
|
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
|
||||||
|
@ -308,7 +309,7 @@ static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "this help"},
|
{"help", CmdHelp, AlwaysAvailable, "this help"},
|
||||||
{"demod", CmdPyramidDemod, AlwaysAvailable, "demodulate a Pyramid FSK tag from the GraphBuffer"},
|
{"demod", CmdPyramidDemod, AlwaysAvailable, "demodulate a Pyramid FSK tag from the GraphBuffer"},
|
||||||
{"read", CmdPyramidRead, IfPm3Lf, "attempt to read and extract tag data"},
|
{"read", CmdPyramidRead, IfPm3Lf, "attempt to read and extract tag data"},
|
||||||
{"clone", CmdPyramidClone, IfPm3Lf, "clone pyramid tag to T55x7 (or to q5/T5555)"},
|
{"clone", CmdPyramidClone, IfPm3Lf, "clone pyramid tag to T55x7 or Q5/T5555"},
|
||||||
{"sim", CmdPyramidSim, IfPm3Lf, "simulate pyramid tag"},
|
{"sim", CmdPyramidSim, IfPm3Lf, "simulate pyramid tag"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
|
@ -86,7 +86,7 @@ static int usage_t55xx_config(void) {
|
||||||
PrintAndLogEx(NORMAL, " d <FSK|FSK1|FSK1a|FSK2|FSK2a|ASK|PSK1|PSK2|NRZ|BI|BIa> - Set demodulation FSK / ASK / PSK / NRZ / Biphase / Biphase A");
|
PrintAndLogEx(NORMAL, " d <FSK|FSK1|FSK1a|FSK2|FSK2a|ASK|PSK1|PSK2|NRZ|BI|BIa> - Set demodulation FSK / ASK / PSK / NRZ / Biphase / Biphase A");
|
||||||
PrintAndLogEx(NORMAL, " i [0/1] - Set/reset data signal inversion");
|
PrintAndLogEx(NORMAL, " i [0/1] - Set/reset data signal inversion");
|
||||||
PrintAndLogEx(NORMAL, " o [offset] - Set offset, where data should start decode in bitstream");
|
PrintAndLogEx(NORMAL, " o [offset] - Set offset, where data should start decode in bitstream");
|
||||||
PrintAndLogEx(NORMAL, " Q5 [0/1] - Set/reset as T5555 ( Q5 ) chip instead of T55x7");
|
PrintAndLogEx(NORMAL, " Q5 [0/1] - Set/reset as Q5/T5555 chip instead of T55x7");
|
||||||
PrintAndLogEx(NORMAL, " ST [0/1] - Set/reset Sequence Terminator on");
|
PrintAndLogEx(NORMAL, " ST [0/1] - Set/reset Sequence Terminator on");
|
||||||
PrintAndLogEx(NORMAL, ""); // layout is a little differnet, so seperate until a better fix
|
PrintAndLogEx(NORMAL, ""); // layout is a little differnet, so seperate until a better fix
|
||||||
print_usage_t55xx_downloadlink(T55XX_DLMODE_SINGLE, config.downlink_mode);
|
print_usage_t55xx_downloadlink(T55XX_DLMODE_SINGLE, config.downlink_mode);
|
||||||
|
@ -311,11 +311,11 @@ static int usage_t55xx_wipe(void) {
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
PrintAndLogEx(NORMAL, "Options:");
|
||||||
PrintAndLogEx(NORMAL, " h - this help");
|
PrintAndLogEx(NORMAL, " h - this help");
|
||||||
PrintAndLogEx(NORMAL, " c <block0> - set configuration from a block0");
|
PrintAndLogEx(NORMAL, " c <block0> - set configuration from a block0");
|
||||||
PrintAndLogEx(NORMAL, " q - indicates to use T5555 ( Q5 ) default configuration block");
|
PrintAndLogEx(NORMAL, " q - indicates to use Q5/T5555 default configuration block");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx wipe") " - wipes a T55x7 tag, config block 0x000880E0");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx wipe") " - wipes a T55x7 tag, config block 0x000880E0");
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx wipe q") " - wipes a T5555 ( Q5 ) tag, config block 0x6001F004");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx wipe q") " - wipes a Q5/T5555 tag, config block 0x6001F004");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
static int usage_t55xx_deviceconfig(void) {
|
static int usage_t55xx_deviceconfig(void) {
|
||||||
|
@ -829,7 +829,7 @@ static int CmdT55xxSetConfig(const char *Cmd) {
|
||||||
return printConfiguration(config);
|
return printConfiguration(config);
|
||||||
}
|
}
|
||||||
int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, uint8_t override, uint32_t password, uint8_t downlink_mode) {
|
int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, uint8_t override, uint32_t password, uint8_t downlink_mode) {
|
||||||
return T55xxReadBlockEx(block, page1, usepwd, override, password, downlink_mode, true);
|
return T55xxReadBlockEx(block, page1, usepwd, override, password, downlink_mode, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int T55xxReadBlockEx(uint8_t block, bool page1, bool usepwd, uint8_t override, uint32_t password, uint8_t downlink_mode, bool verbose) {
|
int T55xxReadBlockEx(uint8_t block, bool page1, bool usepwd, uint8_t override, uint32_t password, uint8_t downlink_mode, bool verbose) {
|
||||||
|
@ -994,7 +994,7 @@ static int SanityOfflineCheck(bool useGraphBuffer) {
|
||||||
|
|
||||||
static void T55xx_Print_DownlinkMode(uint8_t downlink_mode) {
|
static void T55xx_Print_DownlinkMode(uint8_t downlink_mode) {
|
||||||
char msg[80];
|
char msg[80];
|
||||||
sprintf(msg, "Downlink Mode used : ");
|
snprintf(msg, sizeof(msg), "Downlink Mode used : ");
|
||||||
|
|
||||||
switch (downlink_mode) {
|
switch (downlink_mode) {
|
||||||
case 1 :
|
case 1 :
|
||||||
|
@ -1075,7 +1075,7 @@ static int CmdT55xxDetect(const char *Cmd) {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
found = true;
|
found = true;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1587,7 +1587,7 @@ int special(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int printConfiguration(t55xx_conf_block_t b) {
|
int printConfiguration(t55xx_conf_block_t b) {
|
||||||
PrintAndLogEx(INFO, " Chip Type : " _GREEN_("%s"), (b.Q5) ? "T5555 ( Q5 )" : "T55x7");
|
PrintAndLogEx(INFO, " Chip Type : " _GREEN_("%s"), (b.Q5) ? "Q5/T5555" : "T55x7");
|
||||||
PrintAndLogEx(INFO, " Modulation : " _GREEN_("%s"), GetSelectedModulationStr(b.modulation));
|
PrintAndLogEx(INFO, " Modulation : " _GREEN_("%s"), GetSelectedModulationStr(b.modulation));
|
||||||
PrintAndLogEx(INFO, " Bit Rate : %s", GetBitRateStr(b.bitrate, (b.block0 & T55x7_X_MODE && (b.block0 >> 28 == 6 || b.block0 >> 28 == 9))));
|
PrintAndLogEx(INFO, " Bit Rate : %s", GetBitRateStr(b.bitrate, (b.block0 & T55x7_X_MODE && (b.block0 >> 28 == 6 || b.block0 >> 28 == 9))));
|
||||||
PrintAndLogEx(INFO, " Inverted : %s", (b.inverted) ? _GREEN_("Yes") : "No");
|
PrintAndLogEx(INFO, " Inverted : %s", (b.inverted) ? _GREEN_("Yes") : "No");
|
||||||
|
@ -1864,7 +1864,7 @@ static int CmdT55xxReadTrace(const char *Cmd) {
|
||||||
si += 9;
|
si += 9;
|
||||||
|
|
||||||
if (hdr != 0x1FF) {
|
if (hdr != 0x1FF) {
|
||||||
PrintAndLogEx(FAILED, "Invalid T555 ( Q5 ) Trace data header (expected 0x1FF, found %X)", hdr);
|
PrintAndLogEx(FAILED, "Invalid Q5/T5555 Trace data header (expected 0x1FF, found %X)", hdr);
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1955,7 +1955,7 @@ static int CmdT55xxReadTrace(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void printT55x7Trace(t55x7_tracedata_t data, uint8_t repeat) {
|
void printT55x7Trace(t55x7_tracedata_t data, uint8_t repeat) {
|
||||||
PrintAndLogEx(NORMAL, "-- T55x7 Trace Information ----------------------------------");
|
PrintAndLogEx(NORMAL, "--- " _CYAN_("T55x7 Trace Information") " ----------------------------------");
|
||||||
PrintAndLogEx(NORMAL, "-------------------------------------------------------------");
|
PrintAndLogEx(NORMAL, "-------------------------------------------------------------");
|
||||||
PrintAndLogEx(NORMAL, " ACL Allocation class (ISO/IEC 15963-1) : 0x%02X (%d)", data.acl, data.acl);
|
PrintAndLogEx(NORMAL, " ACL Allocation class (ISO/IEC 15963-1) : 0x%02X (%d)", data.acl, data.acl);
|
||||||
PrintAndLogEx(NORMAL, " MFC Manufacturer ID (ISO/IEC 7816-6) : 0x%02X (%d) - %s", data.mfc, data.mfc, getTagInfo(data.mfc));
|
PrintAndLogEx(NORMAL, " MFC Manufacturer ID (ISO/IEC 7816-6) : 0x%02X (%d) - %s", data.mfc, data.mfc, getTagInfo(data.mfc));
|
||||||
|
@ -2002,7 +2002,7 @@ void printT55x7Trace(t55x7_tracedata_t data, uint8_t repeat) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void printT5555Trace(t5555_tracedata_t data, uint8_t repeat) {
|
void printT5555Trace(t5555_tracedata_t data, uint8_t repeat) {
|
||||||
PrintAndLogEx(NORMAL, "-- T5555 ( Q5 ) Trace Information ---------------------------");
|
PrintAndLogEx(NORMAL, "--- " _CYAN_("Q5/T5555 Trace Information") " ---------------------------");
|
||||||
PrintAndLogEx(NORMAL, "-------------------------------------------------------------");
|
PrintAndLogEx(NORMAL, "-------------------------------------------------------------");
|
||||||
PrintAndLogEx(NORMAL, " ICR IC Revision : %d", data.icr);
|
PrintAndLogEx(NORMAL, " ICR IC Revision : %d", data.icr);
|
||||||
PrintAndLogEx(NORMAL, " Lot : %c%d", data.lotidc, data.lotid);
|
PrintAndLogEx(NORMAL, " Lot : %c%d", data.lotidc, data.lotid);
|
||||||
|
@ -2327,7 +2327,7 @@ static int CmdT55xxDump(const char *Cmd) {
|
||||||
strcpy(preferredName, "lf-t55xx");
|
strcpy(preferredName, "lf-t55xx");
|
||||||
for (uint8_t i = 1; i <= 7; i++) {
|
for (uint8_t i = 1; i <= 7; i++) {
|
||||||
if ((cardmem[i].blockdata != 0x00) && (cardmem[i].blockdata != 0xFFFFFFFF))
|
if ((cardmem[i].blockdata != 0x00) && (cardmem[i].blockdata != 0xFFFFFFFF))
|
||||||
sprintf(preferredName + strlen(preferredName), "-%08X", cardmem[i].blockdata);
|
snprintf(preferredName + strlen(preferredName), sizeof(preferredName) - strlen(preferredName), "-%08X", cardmem[i].blockdata);
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2416,7 +2416,7 @@ static int CmdT55xxRestore(const char *Cmd) {
|
||||||
if (success == PM3_SUCCESS) { // Got data, so write to cards
|
if (success == PM3_SUCCESS) { // Got data, so write to cards
|
||||||
if (datalen == T55x7_BLOCK_COUNT * 4) { // 12 blocks * 4 bytes per block
|
if (datalen == T55x7_BLOCK_COUNT * 4) { // 12 blocks * 4 bytes per block
|
||||||
if (usepwd)
|
if (usepwd)
|
||||||
sprintf(pwdOpt, "p %08X", password);
|
snprintf(pwdOpt, sizeof(pwdOpt), "p %08X", password);
|
||||||
|
|
||||||
// Restore endien for writing to card
|
// Restore endien for writing to card
|
||||||
for (blockidx = 0; blockidx < 12; blockidx++)
|
for (blockidx = 0; blockidx < 12; blockidx++)
|
||||||
|
@ -2433,18 +2433,20 @@ static int CmdT55xxRestore(const char *Cmd) {
|
||||||
|
|
||||||
// write out blocks 1-7 page 0
|
// write out blocks 1-7 page 0
|
||||||
for (blockidx = 1; blockidx <= 7; blockidx++) {
|
for (blockidx = 1; blockidx <= 7; blockidx++) {
|
||||||
sprintf(writeCmdOpt, "b %d d %08X %s", blockidx, data[blockidx], pwdOpt);
|
snprintf(writeCmdOpt, sizeof(writeCmdOpt), "b %d d %08X %s", blockidx, data[blockidx], pwdOpt);
|
||||||
|
|
||||||
if (CmdT55xxWriteBlock(writeCmdOpt) != PM3_SUCCESS)
|
if (CmdT55xxWriteBlock(writeCmdOpt) != PM3_SUCCESS)
|
||||||
PrintAndLogEx(WARNING, "Warning: error writing blk %d", blockidx);
|
PrintAndLogEx(WARNING, "Warning: error writing blk %d", blockidx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if password was set on the "blank" update as we may have just changed it
|
// if password was set on the "blank" update as we may have just changed it
|
||||||
if (usepwd)
|
if (usepwd)
|
||||||
sprintf(pwdOpt, "p %08X", data[7]);
|
snprintf(pwdOpt, sizeof(pwdOpt), "p %08X", data[7]);
|
||||||
|
|
||||||
// write out blocks 1-3 page 1
|
// write out blocks 1-3 page 1
|
||||||
for (blockidx = 9; blockidx <= 11; blockidx++) {
|
for (blockidx = 9; blockidx <= 11; blockidx++) {
|
||||||
sprintf(writeCmdOpt, "b %d 1 d %08X %s", blockidx - 8, data[blockidx], pwdOpt);
|
snprintf(writeCmdOpt, sizeof(writeCmdOpt), "b %d 1 d %08X %s", blockidx - 8, data[blockidx], pwdOpt);
|
||||||
|
|
||||||
if (CmdT55xxWriteBlock(writeCmdOpt) != PM3_SUCCESS)
|
if (CmdT55xxWriteBlock(writeCmdOpt) != PM3_SUCCESS)
|
||||||
PrintAndLogEx(WARNING, "Warning: error writing blk %d", blockidx);
|
PrintAndLogEx(WARNING, "Warning: error writing blk %d", blockidx);
|
||||||
}
|
}
|
||||||
|
@ -2453,7 +2455,7 @@ static int CmdT55xxRestore(const char *Cmd) {
|
||||||
config.downlink_mode = downlink_mode;
|
config.downlink_mode = downlink_mode;
|
||||||
|
|
||||||
// Write the page 0 config
|
// Write the page 0 config
|
||||||
sprintf(writeCmdOpt, "b 0 d %08X %s", data[0], pwdOpt);
|
snprintf(writeCmdOpt, sizeof(writeCmdOpt), "b 0 d %08X %s", data[0], pwdOpt);
|
||||||
if (CmdT55xxWriteBlock(writeCmdOpt) != PM3_SUCCESS)
|
if (CmdT55xxWriteBlock(writeCmdOpt) != PM3_SUCCESS)
|
||||||
PrintAndLogEx(WARNING, "Warning: error writing blk 0");
|
PrintAndLogEx(WARNING, "Warning: error writing blk 0");
|
||||||
}
|
}
|
||||||
|
@ -2811,7 +2813,7 @@ static void t55x7_create_config_block(int tagtype) {
|
||||||
snprintf(retStr, sizeof(buf), "%08X - T55X7 Raw", T55X7_RAW_CONFIG_BLOCK);
|
snprintf(retStr, sizeof(buf), "%08X - T55X7 Raw", T55X7_RAW_CONFIG_BLOCK);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
snprintf(retStr, sizeof(buf), "%08X - T5555 ( Q5 ) Default", T5555_DEFAULT_CONFIG_BLOCK);
|
snprintf(retStr, sizeof(buf), "%08X - Q5/T5555 Default", T5555_DEFAULT_CONFIG_BLOCK);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -2916,7 +2918,7 @@ static int CmdT55xxWipe(const char *Cmd) {
|
||||||
if (errors) return usage_t55xx_wipe();
|
if (errors) return usage_t55xx_wipe();
|
||||||
|
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "\nBegin wiping %s", (Q5) ? "T5555 ( Q5 ) tag" : "T55x7 tag");
|
PrintAndLogEx(INFO, "\nBegin wiping " _YELLOW_("%s")" tag", (Q5) ? "Q5/T5555" : "T55x7");
|
||||||
|
|
||||||
// default config blocks.
|
// default config blocks.
|
||||||
if (gotconf == false) {
|
if (gotconf == false) {
|
||||||
|
@ -3039,18 +3041,18 @@ static int CmdT55xxChkPwds(const char *Cmd) {
|
||||||
|
|
||||||
while (!WaitForResponseTimeout(CMD_LF_T55XX_CHK_PWDS, &resp, 2000)) {
|
while (!WaitForResponseTimeout(CMD_LF_T55XX_CHK_PWDS, &resp, 2000)) {
|
||||||
timeout++;
|
timeout++;
|
||||||
printf(".");
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
fflush(stdout);
|
|
||||||
if (timeout > 180) {
|
if (timeout > 180) {
|
||||||
PrintAndLogEx(WARNING, "\nNo response from Proxmark3. Aborting...");
|
PrintAndLogEx(WARNING, "\nNo response from Proxmark3. Aborting...");
|
||||||
return PM3_ENODATA;
|
return PM3_ENODATA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
struct p {
|
struct p {
|
||||||
bool found;
|
bool found;
|
||||||
uint32_t candidate;
|
uint32_t candidate;
|
||||||
} PACKED;
|
} PACKED;
|
||||||
struct p* packet = (struct p*)resp.data.asBytes;
|
struct p *packet = (struct p *)resp.data.asBytes;
|
||||||
|
|
||||||
if (packet->found) {
|
if (packet->found) {
|
||||||
PrintAndLogEx(SUCCESS, "\nFound a candidate [ " _YELLOW_("%08"PRIX32) " ]", packet->candidate);
|
PrintAndLogEx(SUCCESS, "\nFound a candidate [ " _YELLOW_("%08"PRIX32) " ]", packet->candidate);
|
||||||
|
@ -3178,8 +3180,7 @@ static int CmdT55xxBruteForce(const char *Cmd) {
|
||||||
|
|
||||||
while (found == 0) {
|
while (found == 0) {
|
||||||
|
|
||||||
printf(".");
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
if (IsCancelled()) {
|
if (IsCancelled()) {
|
||||||
return PM3_EOPABORTED;
|
return PM3_EOPABORTED;
|
||||||
|
@ -3223,7 +3224,7 @@ uint8_t tryOnePassword(uint32_t password, uint8_t downlink_mode) {
|
||||||
if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, password, dl_mode)) {
|
if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, password, dl_mode)) {
|
||||||
// if (getSignalProperties()->isnoise == false) {
|
// if (getSignalProperties()->isnoise == false) {
|
||||||
// } else {
|
// } else {
|
||||||
if (tryDetectModulationEx(dl_mode, T55XX_PrintConfig, 0 ,password)) {
|
if (tryDetectModulationEx(dl_mode, T55XX_PrintConfig, 0, password)) {
|
||||||
return 1 + (dl_mode << 1);
|
return 1 + (dl_mode << 1);
|
||||||
}
|
}
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -27,15 +27,15 @@
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
static int usage_lf_viking_clone(void) {
|
static int usage_lf_viking_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, "clone a Viking AM tag to a T55x7 tag.");
|
PrintAndLogEx(NORMAL, "clone a Viking AM tag to a T55x7 or Q5/T5555 tag.");
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf viking clone <Card ID - 8 hex digits> <Q5>");
|
PrintAndLogEx(NORMAL, "Usage: lf viking clone <Card ID - 8 hex digits> <Q5>");
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
PrintAndLogEx(NORMAL, "Options:");
|
||||||
PrintAndLogEx(NORMAL, " <Card Number> : 8 digit hex viking card number");
|
PrintAndLogEx(NORMAL, " <Card Number> : 8 digit hex viking card number");
|
||||||
PrintAndLogEx(NORMAL, " <Q5> : specify write to Q5 (t5555 instead of t55x7)");
|
PrintAndLogEx(NORMAL, " <Q5> : specify writing to Q5/T5555 tag)");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf viking clone 1A337"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf viking clone 1A337"));
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf viking clone 1A337 Q5"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf viking clone 1A337 Q5") " - encode for Q5/T5555 tag");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +114,11 @@ static int CmdVikingClone(const char *Cmd) {
|
||||||
|
|
||||||
num_to_bytes(rawID, 8, &payload.blocks[0]);
|
num_to_bytes(rawID, 8, &payload.blocks[0]);
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "Preparing to clone Viking tag - ID " _YELLOW_("%08X")" raw " _YELLOW_("%s"), id, sprint_hex(payload.blocks, sizeof(payload.blocks)));
|
PrintAndLogEx(INFO, "Preparing to clone Viking tag on " _YELLOW_("%s") " - ID " _YELLOW_("%08X")" raw " _YELLOW_("%s")
|
||||||
|
, (Q5) ? "Q5/T5555" : "T55x7"
|
||||||
|
, id
|
||||||
|
, sprint_hex(payload.blocks, sizeof(payload.blocks))
|
||||||
|
);
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
|
|
||||||
|
@ -169,7 +173,7 @@ static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||||
{"demod", CmdVikingDemod, AlwaysAvailable, "Demodulate a Viking tag from the GraphBuffer"},
|
{"demod", CmdVikingDemod, AlwaysAvailable, "Demodulate a Viking tag from the GraphBuffer"},
|
||||||
{"read", CmdVikingRead, IfPm3Lf, "Attempt to read and Extract tag data from the antenna"},
|
{"read", CmdVikingRead, IfPm3Lf, "Attempt to read and Extract tag data from the antenna"},
|
||||||
{"clone", CmdVikingClone, IfPm3Lf, "clone Viking tag to T55x7 (or to q5/T5555)"},
|
{"clone", CmdVikingClone, IfPm3Lf, "clone Viking tag to T55x7 or Q5/T5555"},
|
||||||
{"sim", CmdVikingSim, IfPm3Lf, "simulate Viking tag"},
|
{"sim", CmdVikingSim, IfPm3Lf, "simulate Viking tag"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,15 +33,16 @@
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
static int usage_lf_visa2k_clone(void) {
|
static int usage_lf_visa2k_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, "clone a Visa2000 tag to a T55x7 tag.");
|
PrintAndLogEx(NORMAL, "clone a Visa2000 tag to a T55x7 or Q5/T5555 tag.");
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf visa2000 clone [h] <card ID> <Q5>");
|
PrintAndLogEx(NORMAL, "Usage: lf visa2000 clone [h] <card ID> <Q5>");
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
PrintAndLogEx(NORMAL, "Options:");
|
||||||
PrintAndLogEx(NORMAL, " h : This help");
|
PrintAndLogEx(NORMAL, " h : This help");
|
||||||
PrintAndLogEx(NORMAL, " <card ID> : Visa2k card ID");
|
PrintAndLogEx(NORMAL, " <card ID> : Visa2k card ID");
|
||||||
PrintAndLogEx(NORMAL, " <Q5> : specify write to Q5 (t5555 instead of t55x7)");
|
PrintAndLogEx(NORMAL, " <Q5> : specify writing to Q5/T5555 tag");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf visa2000 clone 112233"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf visa2000 clone 112233"));
|
||||||
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf visa2000 clone 112233 q5") " -- encode for Q5/T5555");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,13 +178,14 @@ static int CmdVisa2kClone(const char *Cmd) {
|
||||||
id = param_get32ex(Cmd, 0, 0, 10);
|
id = param_get32ex(Cmd, 0, 0, 10);
|
||||||
|
|
||||||
//Q5
|
//Q5
|
||||||
if (tolower(param_getchar(Cmd, 1)) == 'q')
|
bool q5 = tolower(param_getchar(Cmd, 1)) == 'q';
|
||||||
blocks[0] = T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(64) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT;
|
if (q5)
|
||||||
|
blocks[0] = T5555_FIXED | T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(64) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT;
|
||||||
|
|
||||||
blocks[2] = id;
|
blocks[2] = id;
|
||||||
blocks[3] = (visa_parity(id) << 4) | visa_chksum(id);
|
blocks[3] = (visa_parity(id) << 4) | visa_chksum(id);
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "Preparing to clone Visa2000 to T55x7 with CardId: %"PRIu64, id);
|
PrintAndLogEx(INFO, "Preparing to clone Visa2000 to " _YELLOW_("%s") " with CardId: %"PRIu64, (q5) ? "Q5/T5555" : "T55x7", id);
|
||||||
print_blocks(blocks, ARRAYLEN(blocks));
|
print_blocks(blocks, ARRAYLEN(blocks));
|
||||||
|
|
||||||
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
|
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
|
||||||
|
@ -233,7 +235,7 @@ static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||||
{"demod", CmdVisa2kDemod, AlwaysAvailable, "demodulate an VISA2000 tag from the GraphBuffer"},
|
{"demod", CmdVisa2kDemod, AlwaysAvailable, "demodulate an VISA2000 tag from the GraphBuffer"},
|
||||||
{"read", CmdVisa2kRead, IfPm3Lf, "attempt to read and extract tag data from the antenna"},
|
{"read", CmdVisa2kRead, IfPm3Lf, "attempt to read and extract tag data from the antenna"},
|
||||||
{"clone", CmdVisa2kClone, IfPm3Lf, "clone Visa2000 tag to T55x7 (or to q5/T5555)"},
|
{"clone", CmdVisa2kClone, IfPm3Lf, "clone Visa2000 tag to T55x7 or Q5/T5555"},
|
||||||
{"sim", CmdVisa2kSim, IfPm3Lf, "simulate Visa2000 tag"},
|
{"sim", CmdVisa2kSim, IfPm3Lf, "simulate Visa2000 tag"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
|
@ -885,7 +885,7 @@ static void smart_brute_prim(void) {
|
||||||
static int smart_brute_sfi(bool decodeTLV) {
|
static int smart_brute_sfi(bool decodeTLV) {
|
||||||
|
|
||||||
uint8_t *buf = calloc(PM3_CMD_DATA_SIZE, sizeof(uint8_t));
|
uint8_t *buf = calloc(PM3_CMD_DATA_SIZE, sizeof(uint8_t));
|
||||||
if (!buf)
|
if (buf == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
int len;
|
int len;
|
||||||
|
@ -895,8 +895,7 @@ static int smart_brute_sfi(bool decodeTLV) {
|
||||||
|
|
||||||
for (uint8_t sfi = 1; sfi <= 31; sfi++) {
|
for (uint8_t sfi = 1; sfi <= 31; sfi++) {
|
||||||
|
|
||||||
printf(".");
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
for (uint16_t rec = 1; rec <= 255; rec++) {
|
for (uint16_t rec = 1; rec <= 255; rec++) {
|
||||||
|
|
||||||
|
@ -1024,8 +1023,7 @@ static int CmdSmartBruteforceSFI(const char *Cmd) {
|
||||||
|
|
||||||
for (int i = 0; i < json_array_size(root); i++) {
|
for (int i = 0; i < json_array_size(root); i++) {
|
||||||
|
|
||||||
printf("+");
|
PrintAndLogEx(NORMAL, "+" NOLF);
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
if (caid)
|
if (caid)
|
||||||
free(caid);
|
free(caid);
|
||||||
|
@ -1033,21 +1031,21 @@ static int CmdSmartBruteforceSFI(const char *Cmd) {
|
||||||
json_t *data, *jaid;
|
json_t *data, *jaid;
|
||||||
|
|
||||||
data = json_array_get(root, i);
|
data = json_array_get(root, i);
|
||||||
if (!json_is_object(data)) {
|
if (json_is_object(data) == false) {
|
||||||
PrintAndLogEx(ERR, "data %d is not an object\n", i + 1);
|
PrintAndLogEx(ERR, "\ndata %d is not an object\n", i + 1);
|
||||||
json_decref(root);
|
json_decref(root);
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
jaid = json_object_get(data, "AID");
|
jaid = json_object_get(data, "AID");
|
||||||
if (!json_is_string(jaid)) {
|
if (json_is_string(jaid) == false) {
|
||||||
PrintAndLogEx(ERR, "AID data [%d] is not a string", i + 1);
|
PrintAndLogEx(ERR, "\nAID data [%d] is not a string", i + 1);
|
||||||
json_decref(root);
|
json_decref(root);
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *aid = json_string_value(jaid);
|
const char *aid = json_string_value(jaid);
|
||||||
if (!aid)
|
if (aid == false)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
size_t aidlen = strlen(aid);
|
size_t aidlen = strlen(aid);
|
||||||
|
@ -1069,7 +1067,7 @@ static int CmdSmartBruteforceSFI(const char *Cmd) {
|
||||||
|
|
||||||
json_t *jvendor, *jname;
|
json_t *jvendor, *jname;
|
||||||
jvendor = json_object_get(data, "Vendor");
|
jvendor = json_object_get(data, "Vendor");
|
||||||
if (!json_is_string(jvendor)) {
|
if (json_is_string(jvendor) == false) {
|
||||||
PrintAndLogEx(ERR, "Vendor data [%d] is not a string", i + 1);
|
PrintAndLogEx(ERR, "Vendor data [%d] is not a string", i + 1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1079,7 +1077,7 @@ static int CmdSmartBruteforceSFI(const char *Cmd) {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
jname = json_object_get(data, "Name");
|
jname = json_object_get(data, "Name");
|
||||||
if (!json_is_string(jname)) {
|
if (json_is_string(jname) == false) {
|
||||||
PrintAndLogEx(ERR, "Name data [%d] is not a string", i + 1);
|
PrintAndLogEx(ERR, "Name data [%d] is not a string", i + 1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -245,6 +245,7 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
||||||
case ISO_14443A:
|
case ISO_14443A:
|
||||||
case MFDES:
|
case MFDES:
|
||||||
case LTO:
|
case LTO:
|
||||||
|
case ISO_7816_4:
|
||||||
crcStatus = iso14443A_CRC_check(hdr->isResponse, frame, data_len);
|
crcStatus = iso14443A_CRC_check(hdr->isResponse, frame, data_len);
|
||||||
break;
|
break;
|
||||||
case THINFILM:
|
case THINFILM:
|
||||||
|
@ -260,7 +261,6 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
||||||
crcStatus = iso15693_CRC_check(frame, data_len);
|
crcStatus = iso15693_CRC_check(frame, data_len);
|
||||||
break;
|
break;
|
||||||
case PROTO_CRYPTORF:
|
case PROTO_CRYPTORF:
|
||||||
case ISO_7816_4:
|
|
||||||
case PROTO_HITAG1:
|
case PROTO_HITAG1:
|
||||||
case PROTO_HITAG2:
|
case PROTO_HITAG2:
|
||||||
case PROTO_HITAGS:
|
case PROTO_HITAGS:
|
||||||
|
@ -334,10 +334,10 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
||||||
// Draw the CRC column
|
// Draw the CRC column
|
||||||
const char *crc = (crcStatus == 0 ? "!crc" : (crcStatus == 1 ? " ok " : " "));
|
const char *crc = (crcStatus == 0 ? "!crc" : (crcStatus == 1 ? " ok " : " "));
|
||||||
|
|
||||||
// mark short bytes (less than 8 Bit + Parity)
|
// mark short bytes (less than 8 Bit + Parity)
|
||||||
if (protocol == ISO_14443A ||
|
if (protocol == ISO_14443A ||
|
||||||
protocol == PROTO_MIFARE ||
|
protocol == PROTO_MIFARE ||
|
||||||
protocol == THINFILM) {
|
protocol == THINFILM) {
|
||||||
|
|
||||||
// approximated with 128 * (9 * data_len);
|
// approximated with 128 * (9 * data_len);
|
||||||
uint16_t bitime = 1056 + 32;
|
uint16_t bitime = 1056 + 32;
|
||||||
|
@ -346,17 +346,17 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
||||||
|
|
||||||
uint8_t m = 7;
|
uint8_t m = 7;
|
||||||
while (m > 0) {
|
while (m > 0) {
|
||||||
bitime -= 128;
|
bitime -= 128;
|
||||||
if ( duration > bitime) {
|
if (duration > bitime) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
m--;
|
m--;
|
||||||
}
|
}
|
||||||
line[(data_len-1)/16][((data_len-1)%16) * 4 + 2] = '(';
|
line[(data_len - 1) / 16][((data_len - 1) % 16) * 4 + 2] = '(';
|
||||||
line[(data_len-1)/16][((data_len-1)%16) * 4 + 3] = m + 0x30;
|
line[(data_len - 1) / 16][((data_len - 1) % 16) * 4 + 3] = m + 0x30;
|
||||||
line[(data_len-1)/16][((data_len-1)%16) * 4 + 4] = ')';
|
line[(data_len - 1) / 16][((data_len - 1) % 16) * 4 + 4] = ')';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t previous_end_of_transmission_timestamp = 0;
|
uint32_t previous_end_of_transmission_timestamp = 0;
|
||||||
|
@ -388,8 +388,8 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
||||||
annotateHitagS(explanation, sizeof(explanation), frame, data_len, hdr->isResponse);
|
annotateHitagS(explanation, sizeof(explanation), frame, data_len, hdr->isResponse);
|
||||||
break;
|
break;
|
||||||
case ICLASS:
|
case ICLASS:
|
||||||
annotateIclass(explanation, sizeof(explanation), frame, data_len, hdr->isResponse);
|
annotateIclass(explanation, sizeof(explanation), frame, data_len, hdr->isResponse);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -413,6 +413,7 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
||||||
annotateTopaz(explanation, sizeof(explanation), frame, data_len);
|
annotateTopaz(explanation, sizeof(explanation), frame, data_len);
|
||||||
break;
|
break;
|
||||||
case ISO_7816_4:
|
case ISO_7816_4:
|
||||||
|
annotateIso14443a(explanation, sizeof(explanation), frame, data_len);
|
||||||
annotateIso7816(explanation, sizeof(explanation), frame, data_len);
|
annotateIso7816(explanation, sizeof(explanation), frame, data_len);
|
||||||
break;
|
break;
|
||||||
case ISO_15693:
|
case ISO_15693:
|
||||||
|
|
|
@ -298,13 +298,13 @@ static void PacketResponseReceived(PacketResponseNG *packet) {
|
||||||
PrintAndLogEx(NORMAL, "[" _BLUE_("#") "] %s", s);
|
PrintAndLogEx(NORMAL, "[" _BLUE_("#") "] %s", s);
|
||||||
} else {
|
} else {
|
||||||
if (flag & FLAG_INPLACE)
|
if (flag & FLAG_INPLACE)
|
||||||
printf("\r");
|
PrintAndLogEx(NORMAL, "\r" NOLF);
|
||||||
printf("%s", s);
|
|
||||||
if (flag & FLAG_NEWLINE)
|
|
||||||
printf("\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
fflush(stdout);
|
PrintAndLogEx(NORMAL, "%s" NOLF, s);
|
||||||
|
|
||||||
|
if (flag & FLAG_NEWLINE)
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_DEBUG_PRINT_INTEGERS: {
|
case CMD_DEBUG_PRINT_INTEGERS: {
|
||||||
|
|
|
@ -24,8 +24,8 @@
|
||||||
#include <mbedtls/ctr_drbg.h>
|
#include <mbedtls/ctr_drbg.h>
|
||||||
#include <mbedtls/entropy.h>
|
#include <mbedtls/entropy.h>
|
||||||
#include <mbedtls/error.h>
|
#include <mbedtls/error.h>
|
||||||
#include <util.h>
|
#include "util.h"
|
||||||
|
#include "ui.h"
|
||||||
// NIST Special Publication 800-38A — Recommendation for block cipher modes of operation: methods and techniques, 2001.
|
// NIST Special Publication 800-38A — Recommendation for block cipher modes of operation: methods and techniques, 2001.
|
||||||
int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length) {
|
int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length) {
|
||||||
uint8_t iiv[16] = {0};
|
uint8_t iiv[16] = {0};
|
||||||
|
@ -416,10 +416,10 @@ int ecdsa_nist_test(bool verbose) {
|
||||||
|
|
||||||
// NIST ecdsa test
|
// NIST ecdsa test
|
||||||
if (verbose)
|
if (verbose)
|
||||||
printf(" ECDSA NIST test: ");
|
PrintAndLogEx(INFO, " ECDSA NIST test: " NOLF);
|
||||||
// make signature
|
// make signature
|
||||||
res = ecdsa_signature_create_test(curveid, T_PRIVATE_KEY, T_Q_X, T_Q_Y, T_K, input, length, signature, &siglen);
|
res = ecdsa_signature_create_test(curveid, T_PRIVATE_KEY, T_Q_X, T_Q_Y, T_K, input, length, signature, &siglen);
|
||||||
// printf("res: %x signature[%x]: %s\n", (res<0)?-res:res, siglen, sprint_hex(signature, siglen));
|
// PrintAndLogEx(INFO, "res: %x signature[%x]: %s", (res < 0)? -res : res, siglen, sprint_hex(signature, siglen));
|
||||||
if (res)
|
if (res)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
|
@ -436,7 +436,7 @@ int ecdsa_nist_test(bool verbose) {
|
||||||
uint8_t sval_s[33] = {0};
|
uint8_t sval_s[33] = {0};
|
||||||
param_gethex_to_eol(T_S, 0, sval_s, sizeof(sval_s), &slen);
|
param_gethex_to_eol(T_S, 0, sval_s, sizeof(sval_s), &slen);
|
||||||
if (strncmp((char *)rval, (char *)rval_s, 32) || strncmp((char *)sval, (char *)sval_s, 32)) {
|
if (strncmp((char *)rval, (char *)rval_s, 32) || strncmp((char *)sval, (char *)sval_s, 32)) {
|
||||||
printf("R or S check error\n");
|
PrintAndLogEx(INFO, "R or S check error");
|
||||||
res = 100;
|
res = 100;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
@ -449,14 +449,14 @@ int ecdsa_nist_test(bool verbose) {
|
||||||
// verify wrong signature
|
// verify wrong signature
|
||||||
input[0] ^= 0xFF;
|
input[0] ^= 0xFF;
|
||||||
res = ecdsa_signature_verify_keystr(curveid, T_Q_X, T_Q_Y, input, length, signature, siglen, true);
|
res = ecdsa_signature_verify_keystr(curveid, T_Q_X, T_Q_Y, input, length, signature, siglen, true);
|
||||||
if (!res) {
|
if (res == false) {
|
||||||
res = 1;
|
res = 1;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
printf("passed\n");
|
PrintAndLogEx(NORMAL, _GREEN_("passed"));
|
||||||
printf(" ECDSA binary signature create/check test: ");
|
PrintAndLogEx(INFO, " ECDSA binary signature create/check test: " NOLF);
|
||||||
}
|
}
|
||||||
|
|
||||||
// random ecdsa test
|
// random ecdsa test
|
||||||
|
@ -483,11 +483,11 @@ int ecdsa_nist_test(bool verbose) {
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
printf("passed\n\n");
|
PrintAndLogEx(NORMAL, _GREEN_("passed\n"));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
exit:
|
exit:
|
||||||
if (verbose)
|
if (verbose)
|
||||||
printf("failed\n\n");
|
PrintAndLogEx(NORMAL, _RED_("failed\n"));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,8 @@ static mbedtls_mpi_uint mpi_get_uint(const mbedtls_mpi *X) {
|
||||||
if (X->n == 1 && X->s > 0) {
|
if (X->n == 1 && X->s > 0) {
|
||||||
return X->p[0];
|
return X->p[0];
|
||||||
}
|
}
|
||||||
printf("ZERRRRO!!!\n");
|
|
||||||
|
PrintAndLogEx(WARNING, "ZERRRRO!!!\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +83,7 @@ static void print_mpi(const char *msg, int radix, const mbedtls_mpi *X) {
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
|
|
||||||
mbedtls_mpi_write_string(X, radix, Xchar, sizeof(Xchar), &len);
|
mbedtls_mpi_write_string(X, radix, Xchar, sizeof(Xchar), &len);
|
||||||
printf("%s[%zu] %s\n", msg, len, Xchar);
|
PrintAndLogEx(INFO, "%s[%zu] %s\n", msg, len, Xchar);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
bool emv_rocacheck(const unsigned char *buf, size_t buflen, bool verbose) {
|
bool emv_rocacheck(const unsigned char *buf, size_t buflen, bool verbose) {
|
||||||
|
|
|
@ -11,16 +11,15 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "cbortools.h"
|
#include "cbortools.h"
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include "emv/emvjson.h"
|
#include "emv/emvjson.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "ui.h" // PrintAndLogEx(
|
||||||
#include "fidocore.h"
|
#include "fidocore.h"
|
||||||
|
|
||||||
static void indent(int nestingLevel) {
|
static void indent(int nestingLevel) {
|
||||||
while (nestingLevel--)
|
while (nestingLevel--)
|
||||||
printf(" ");
|
PrintAndLogEx(NORMAL, " " NOLF);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CborError dumpelm(CborValue *it, bool *got_next, int nestingLevel) {
|
static CborError dumpelm(CborValue *it, bool *got_next, int nestingLevel) {
|
||||||
|
@ -32,14 +31,14 @@ static CborError dumpelm(CborValue *it, bool *got_next, int nestingLevel) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case CborMapType:
|
case CborMapType:
|
||||||
case CborArrayType: {
|
case CborArrayType: {
|
||||||
printf(type == CborArrayType ? "Array[" : "Map[");
|
PrintAndLogEx(NORMAL, "%s" NOLF, (type == CborArrayType) ? "Array[" : "Map[");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CborIntegerType: {
|
case CborIntegerType: {
|
||||||
int64_t val;
|
int64_t val;
|
||||||
cbor_value_get_int64(it, &val); // can't fail
|
cbor_value_get_int64(it, &val); // can't fail
|
||||||
printf("%lld", (long long)val);
|
PrintAndLogEx(NORMAL, "%lld" NOLF, (long long)val);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +49,8 @@ static CborError dumpelm(CborValue *it, bool *got_next, int nestingLevel) {
|
||||||
*got_next = true;
|
*got_next = true;
|
||||||
if (err)
|
if (err)
|
||||||
return err; // parse error
|
return err; // parse error
|
||||||
printf("%s", sprint_hex(buf, n));
|
|
||||||
|
PrintAndLogEx(NORMAL, "%s" NOLF, sprint_hex(buf, n));
|
||||||
free(buf);
|
free(buf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,8 @@ static CborError dumpelm(CborValue *it, bool *got_next, int nestingLevel) {
|
||||||
*got_next = true;
|
*got_next = true;
|
||||||
if (err)
|
if (err)
|
||||||
return err; // parse error
|
return err; // parse error
|
||||||
printf("%s", buf);
|
|
||||||
|
PrintAndLogEx(NORMAL, "%s" NOLF, buf);
|
||||||
free(buf);
|
free(buf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -70,29 +71,29 @@ static CborError dumpelm(CborValue *it, bool *got_next, int nestingLevel) {
|
||||||
case CborTagType: {
|
case CborTagType: {
|
||||||
CborTag tag;
|
CborTag tag;
|
||||||
cbor_value_get_tag(it, &tag);
|
cbor_value_get_tag(it, &tag);
|
||||||
printf("Tag(%lld)", (long long)tag);
|
PrintAndLogEx(NORMAL, "Tag(%lld)" NOLF, (long long)tag);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CborSimpleType: {
|
case CborSimpleType: {
|
||||||
uint8_t t;
|
uint8_t t;
|
||||||
cbor_value_get_simple_type(it, &t);
|
cbor_value_get_simple_type(it, &t);
|
||||||
printf("simple(%u)", t);
|
PrintAndLogEx(NORMAL, "simple(%u)" NOLF, t);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CborNullType:
|
case CborNullType:
|
||||||
printf("null");
|
PrintAndLogEx(NORMAL, "null" NOLF);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CborUndefinedType:
|
case CborUndefinedType:
|
||||||
printf("undefined");
|
PrintAndLogEx(NORMAL, "undefined" NOLF);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CborBooleanType: {
|
case CborBooleanType: {
|
||||||
bool val;
|
bool val;
|
||||||
cbor_value_get_boolean(it, &val); // can't fail
|
cbor_value_get_boolean(it, &val); // can't fail
|
||||||
printf("%s", val ? "true" : "false");
|
PrintAndLogEx(NORMAL, "%s" NOLF, (val) ? "true" : "false");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,18 +107,18 @@ static CborError dumpelm(CborValue *it, bool *got_next, int nestingLevel) {
|
||||||
} else {
|
} else {
|
||||||
cbor_value_get_double(it, &val);
|
cbor_value_get_double(it, &val);
|
||||||
}
|
}
|
||||||
printf("%g", val);
|
PrintAndLogEx(NORMAL, "%g" NOLF, val);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CborHalfFloatType: {
|
case CborHalfFloatType: {
|
||||||
uint16_t val;
|
uint16_t val;
|
||||||
cbor_value_get_half_float(it, &val);
|
cbor_value_get_half_float(it, &val);
|
||||||
printf("__f16(%04x)", val);
|
PrintAndLogEx(NORMAL, "__f16(%04x)" NOLF, val);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CborInvalidType:
|
case CborInvalidType:
|
||||||
printf("CborInvalidType!!!");
|
PrintAndLogEx(NORMAL, _RED_("CborInvalidType!!!") NOLF);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +130,7 @@ static CborError dumprecursive(uint8_t cmdCode, bool isResponse, CborValue *it,
|
||||||
while (!cbor_value_at_end(it)) {
|
while (!cbor_value_at_end(it)) {
|
||||||
CborError err;
|
CborError err;
|
||||||
CborType type = cbor_value_get_type(it);
|
CborType type = cbor_value_get_type(it);
|
||||||
//printf("^%x^", type);
|
|
||||||
bool got_next = false;
|
bool got_next = false;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -140,18 +141,23 @@ static CborError dumprecursive(uint8_t cmdCode, bool isResponse, CborValue *it,
|
||||||
assert(cbor_value_is_container(it));
|
assert(cbor_value_is_container(it));
|
||||||
if (!(isMapType && (elmCount % 2)))
|
if (!(isMapType && (elmCount % 2)))
|
||||||
indent(nestingLevel);
|
indent(nestingLevel);
|
||||||
printf(type == CborArrayType ? "Array[\n" : "Map[\n");
|
|
||||||
|
PrintAndLogEx(NORMAL, "%s" NOLF, (type == CborArrayType) ? "Array[\n" : "Map[\n");
|
||||||
|
|
||||||
err = cbor_value_enter_container(it, &recursed);
|
err = cbor_value_enter_container(it, &recursed);
|
||||||
if (err)
|
if (err)
|
||||||
return err; // parse error
|
return err; // parse error
|
||||||
|
|
||||||
err = dumprecursive(cmdCode, isResponse, &recursed, (type == CborMapType), nestingLevel + 1);
|
err = dumprecursive(cmdCode, isResponse, &recursed, (type == CborMapType), nestingLevel + 1);
|
||||||
if (err)
|
if (err)
|
||||||
return err; // parse error
|
return err; // parse error
|
||||||
|
|
||||||
err = cbor_value_leave_container(it, &recursed);
|
err = cbor_value_leave_container(it, &recursed);
|
||||||
if (err)
|
if (err)
|
||||||
return err; // parse error
|
return err; // parse error
|
||||||
|
|
||||||
indent(nestingLevel);
|
indent(nestingLevel);
|
||||||
printf("]");
|
PrintAndLogEx(NORMAL, "]" NOLF);
|
||||||
got_next = true;
|
got_next = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -170,12 +176,13 @@ static CborError dumprecursive(uint8_t cmdCode, bool isResponse, CborValue *it,
|
||||||
err = dumpelm(it, &got_next, (isMapType && (elmCount % 2)) ? 0 : nestingLevel);
|
err = dumpelm(it, &got_next, (isMapType && (elmCount % 2)) ? 0 : nestingLevel);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (cmdCode > 0 && nestingLevel == 1 && isMapType && !(elmCount % 2)) {
|
if (cmdCode > 0 && nestingLevel == 1 && isMapType && !(elmCount % 2)) {
|
||||||
int64_t val;
|
int64_t val;
|
||||||
cbor_value_get_int64(it, &val);
|
cbor_value_get_int64(it, &val);
|
||||||
const char *desc = fido2GetCmdMemberDescription(cmdCode, isResponse, val);
|
const char *desc = fido2GetCmdMemberDescription(cmdCode, isResponse, val);
|
||||||
if (desc)
|
if (desc)
|
||||||
printf(" (%s)", desc);
|
PrintAndLogEx(NORMAL, " (%s)" NOLF, desc);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -187,9 +194,9 @@ static CborError dumprecursive(uint8_t cmdCode, bool isResponse, CborValue *it,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if (isMapType && !(elmCount % 2)) {
|
if (isMapType && !(elmCount % 2)) {
|
||||||
printf(": ");
|
PrintAndLogEx(NORMAL, ": " NOLF);
|
||||||
} else {
|
} else {
|
||||||
printf("\n");
|
PrintAndLogEx(NORMAL, "");
|
||||||
}
|
}
|
||||||
elmCount++;
|
elmCount++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -429,18 +429,18 @@ int saveFileJSONex(const char *preferredName, JSONFileType ftype, uint8_t *data,
|
||||||
}
|
}
|
||||||
case jsfIclass: {
|
case jsfIclass: {
|
||||||
JsonSaveStr(root, "FileType", "iclass");
|
JsonSaveStr(root, "FileType", "iclass");
|
||||||
|
|
||||||
picopass_hdr *hdr = (picopass_hdr *)data;
|
picopass_hdr *hdr = (picopass_hdr *)data;
|
||||||
JsonSaveBufAsHexCompact(root, "$.Card.CSN", hdr->csn, sizeof(hdr->csn));
|
JsonSaveBufAsHexCompact(root, "$.Card.CSN", hdr->csn, sizeof(hdr->csn));
|
||||||
JsonSaveBufAsHexCompact(root, "$.Card.Configuration",(uint8_t *)&hdr->conf, sizeof(hdr->conf));
|
JsonSaveBufAsHexCompact(root, "$.Card.Configuration", (uint8_t *)&hdr->conf, sizeof(hdr->conf));
|
||||||
|
|
||||||
uint8_t pagemap = get_pagemap(hdr);
|
uint8_t pagemap = get_pagemap(hdr);
|
||||||
if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) {
|
if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) {
|
||||||
picopass_ns_hdr *ns_hdr = (picopass_ns_hdr *)data;
|
picopass_ns_hdr *ns_hdr = (picopass_ns_hdr *)data;
|
||||||
JsonSaveBufAsHexCompact(root, "$.Card.AIA", ns_hdr->app_issuer_area, sizeof(ns_hdr->app_issuer_area));
|
JsonSaveBufAsHexCompact(root, "$.Card.AIA", ns_hdr->app_issuer_area, sizeof(ns_hdr->app_issuer_area));
|
||||||
} else {
|
} else {
|
||||||
JsonSaveBufAsHexCompact(root, "$.Card.Epurse", hdr->epurse, sizeof(hdr->epurse));
|
JsonSaveBufAsHexCompact(root, "$.Card.Epurse", hdr->epurse, sizeof(hdr->epurse));
|
||||||
JsonSaveBufAsHexCompact(root, "$.Card.Kd",hdr->key_d, sizeof(hdr->key_d));
|
JsonSaveBufAsHexCompact(root, "$.Card.Kd", hdr->key_d, sizeof(hdr->key_d));
|
||||||
JsonSaveBufAsHexCompact(root, "$.Card.Kc", hdr->key_c, sizeof(hdr->key_c));
|
JsonSaveBufAsHexCompact(root, "$.Card.Kc", hdr->key_c, sizeof(hdr->key_c));
|
||||||
JsonSaveBufAsHexCompact(root, "$.Card.AIA", hdr->app_issuer_area, sizeof(hdr->app_issuer_area));
|
JsonSaveBufAsHexCompact(root, "$.Card.AIA", hdr->app_issuer_area, sizeof(hdr->app_issuer_area));
|
||||||
}
|
}
|
||||||
|
@ -1483,9 +1483,9 @@ static int filelist(const char *path, const char *ext, uint8_t last, bool tentat
|
||||||
char tmp_fullpath[1024] = {0};
|
char tmp_fullpath[1024] = {0};
|
||||||
strncat(tmp_fullpath, path, sizeof(tmp_fullpath) - 1);
|
strncat(tmp_fullpath, path, sizeof(tmp_fullpath) - 1);
|
||||||
strncat(tmp_fullpath, namelist[i]->d_name, strlen(tmp_fullpath) - 1);
|
strncat(tmp_fullpath, namelist[i]->d_name, strlen(tmp_fullpath) - 1);
|
||||||
|
|
||||||
if (is_directory(tmp_fullpath)) {
|
if (is_directory(tmp_fullpath)) {
|
||||||
|
|
||||||
char newpath[1024];
|
char newpath[1024];
|
||||||
if (strcmp(namelist[i]->d_name, ".") == 0 || strcmp(namelist[i]->d_name, "..") == 0)
|
if (strcmp(namelist[i]->d_name, ".") == 0 || strcmp(namelist[i]->d_name, "..") == 0)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1496,9 +1496,9 @@ static int filelist(const char *path, const char *ext, uint8_t last, bool tentat
|
||||||
|
|
||||||
filelist(newpath, ext, last + ((i == n - 1) << (indent + 1)), tentative, indent + 1, strlen(path));
|
filelist(newpath, ext, last + ((i == n - 1) << (indent + 1)), tentative, indent + 1, strlen(path));
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if ((ext == NULL) || (ext && (str_endswith(namelist[i]->d_name, ext)))) {
|
if ((ext == NULL) || (ext && (str_endswith(namelist[i]->d_name, ext)))) {
|
||||||
|
|
||||||
for (uint8_t j = 0; j < indent + 1; j++) {
|
for (uint8_t j = 0; j < indent + 1; j++) {
|
||||||
PrintAndLogEx(NORMAL, "%s " NOLF, ((last >> j) & 1) ? " " : "│");
|
PrintAndLogEx(NORMAL, "%s " NOLF, ((last >> j) & 1) ? " " : "│");
|
||||||
}
|
}
|
||||||
|
|
|
@ -383,7 +383,7 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) {
|
||||||
|
|
||||||
// success
|
// success
|
||||||
if (memcmp(calculated_MAC, item.mac, 4) == 0) {
|
if (memcmp(calculated_MAC, item.mac, 4) == 0) {
|
||||||
printf("\r\n");
|
PrintAndLogEx(NORMAL, "");
|
||||||
for (i = 0 ; i < numbytes_to_recover; i++) {
|
for (i = 0 ; i < numbytes_to_recover; i++) {
|
||||||
PrintAndLogEx(INFO, "%d: 0x%02x", bytes_to_recover[i], 0xFF & keytable[bytes_to_recover[i]]);
|
PrintAndLogEx(INFO, "%d: 0x%02x", bytes_to_recover[i], 0xFF & keytable[bytes_to_recover[i]]);
|
||||||
}
|
}
|
||||||
|
@ -393,16 +393,15 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) {
|
||||||
|
|
||||||
brute++;
|
brute++;
|
||||||
if ((brute & 0xFFFF) == 0) {
|
if ((brute & 0xFFFF) == 0) {
|
||||||
printf("%3d,", (brute >> 16) & 0xFF);
|
PrintAndLogEx(NORMAL, "%3d," NOLF, (brute >> 16) & 0xFF);
|
||||||
if (((brute >> 16) % 0x10) == 0)
|
if (((brute >> 16) % 0x10) == 0)
|
||||||
printf("\n");
|
PrintAndLogEx(NORMAL, "");
|
||||||
fflush(stdout);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int errors = PM3_SUCCESS;
|
int errors = PM3_SUCCESS;
|
||||||
|
|
||||||
if (!found) {
|
if (found == false) {
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(WARNING, "Failed to recover %d bytes using the following CSN", numbytes_to_recover);
|
PrintAndLogEx(WARNING, "Failed to recover %d bytes using the following CSN", numbytes_to_recover);
|
||||||
PrintAndLogEx(INFO, "CSN %s", sprint_hex(item.csn, 8));
|
PrintAndLogEx(INFO, "CSN %s", sprint_hex(item.csn, 8));
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "elite_crack.h"
|
#include "elite_crack.h"
|
||||||
|
#include "ui.h"
|
||||||
|
|
||||||
static void calc_score(uint8_t *csn, uint8_t *k) {
|
static void calc_score(uint8_t *csn, uint8_t *k) {
|
||||||
uint8_t score = 0 ;
|
uint8_t score = 0 ;
|
||||||
|
@ -41,34 +42,33 @@ static void calc_score(uint8_t *csn, uint8_t *k) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (score >= 2 && badscore < 2) {
|
if (score >= 2 && badscore < 2) {
|
||||||
printf("CSN\t%02x%02x%02x%02x%02x%02x%02x%02x\t%02x %02x %02x %02x %02x %02x %02x %02x\t"
|
PrintAndLogEx(NORMAL, "CSN\t%02x%02x%02x%02x%02x%02x%02x%02x\t%02x %02x %02x %02x %02x %02x %02x %02x\t" NOLF
|
||||||
, csn[0], csn[1], csn[2], csn[3], csn[4], csn[5], csn[6], csn[7]
|
, csn[0], csn[1], csn[2], csn[3], csn[4], csn[5], csn[6], csn[7]
|
||||||
, k[0], k[1], k[2], k[3], k[4], k[5], k[6], k[7]
|
, k[0], k[1], k[2], k[3], k[4], k[5], k[6], k[7]
|
||||||
);
|
);
|
||||||
|
|
||||||
for (i = 0 ; i < score; i++) {
|
for (i = 0 ; i < score; i++) {
|
||||||
printf("%d,", uniq_vals[i]);
|
PrintAndLogEx(NORMAL, "%d," NOLF, uniq_vals[i]);
|
||||||
}
|
}
|
||||||
printf("\tbadscore: %d (%02x)", badscore, badval);
|
PrintAndLogEx(NORMAL, "\tbadscore: %d (%02x)" NOLF, badscore, badval);
|
||||||
printf("\r\n");
|
PrintAndLogEx(NORMAL, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void brute_hash1(void) {
|
void brute_hash1(void) {
|
||||||
uint16_t a, b, c, d;
|
|
||||||
uint8_t csn[8] = {0, 0, 0, 0, 0xf7, 0xff, 0x12, 0xe0};
|
uint8_t csn[8] = {0, 0, 0, 0, 0xf7, 0xff, 0x12, 0xe0};
|
||||||
uint8_t k[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
uint8_t k[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
uint8_t testcsn[8] = {0x00, 0x0d, 0x0f, 0xfd, 0xf7, 0xff, 0x12, 0xe0} ;
|
uint8_t testcsn[8] = {0x00, 0x0d, 0x0f, 0xfd, 0xf7, 0xff, 0x12, 0xe0} ;
|
||||||
uint8_t testkey[8] = {0x05, 0x01, 0x00, 0x10, 0x45, 0x08, 0x45, 0x56} ;
|
uint8_t testkey[8] = {0x05, 0x01, 0x00, 0x10, 0x45, 0x08, 0x45, 0x56} ;
|
||||||
calc_score(testcsn, testkey);
|
calc_score(testcsn, testkey);
|
||||||
printf("Brute forcing hashones\n");
|
|
||||||
//exit(1);
|
|
||||||
|
|
||||||
for (a = 0; a < 256; a++) {
|
PrintAndLogEx(INFO, "Brute forcing hashones");
|
||||||
//if(a > 0)printf("%d/256 done...\n", a);
|
|
||||||
for (b = 0; b < 256; b++)
|
for (uint16_t a = 0; a < 256; a++) {
|
||||||
for (c = 0; c < 256; c++)
|
for (uint16_t b = 0; b < 256; b++) {
|
||||||
for (d = 0; d < 256; d++) {
|
for (uint16_t c = 0; c < 256; c++) {
|
||||||
|
for (uint16_t d = 0; d < 256; d++) {
|
||||||
csn[0] = a;
|
csn[0] = a;
|
||||||
csn[1] = b;
|
csn[1] = b;
|
||||||
csn[2] = c;
|
csn[2] = c;
|
||||||
|
@ -80,6 +80,8 @@ void brute_hash1(void) {
|
||||||
hash1(csn, k);
|
hash1(csn, k);
|
||||||
calc_score(csn, k);
|
calc_score(csn, k);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -333,7 +333,7 @@ void hash0(uint64_t c, uint8_t k[8]) {
|
||||||
uint8_t p_i = p >> i & 0x1;
|
uint8_t p_i = p >> i & 0x1;
|
||||||
|
|
||||||
if (k[i]) { // yi = 1
|
if (k[i]) { // yi = 1
|
||||||
//printf("k[%d] +1\n", i);
|
// PrintAndLogEx(NORMAL, "k[%d] + 1", i);
|
||||||
k[i] |= ~zTilde_i & 0x7E;
|
k[i] |= ~zTilde_i & 0x7E;
|
||||||
k[i] |= p_i & 1;
|
k[i] |= p_i & 1;
|
||||||
k[i] += 1;
|
k[i] += 1;
|
||||||
|
@ -399,7 +399,7 @@ static void testPermute(void) {
|
||||||
permute(&p_in, x, 0, 4, &out);
|
permute(&p_in, x, 0, 4, &out);
|
||||||
|
|
||||||
uint64_t permuted = x_bytes_to_num(outbuffer, 8);
|
uint64_t permuted = x_bytes_to_num(outbuffer, 8);
|
||||||
//printf("zTilde 0x%"PRIX64"\n", zTilde);
|
// PrintAndLogEx(NORMAL, "zTilde 0x%"PRIX64, zTilde);
|
||||||
permuted >>= 16;
|
permuted >>= 16;
|
||||||
|
|
||||||
uint8_t res[8] = { getSixBitByte(permuted, 0),
|
uint8_t res[8] = { getSixBitByte(permuted, 0),
|
||||||
|
@ -694,28 +694,21 @@ int doKeyTests(void) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
void checkParity2(uint8_t* key)
|
void checkParity2(uint8_t* key) {
|
||||||
{
|
|
||||||
|
|
||||||
uint8_t stored_parity = key[7];
|
uint8_t stored_parity = key[7];
|
||||||
printf("Parity byte: 0x%02x\n", stored_parity);
|
PrintAndLogEx(NORMAL, "Parity byte: 0x%02x", stored_parity);
|
||||||
int i;
|
int i, byte, fails = 0;
|
||||||
int byte;
|
|
||||||
int fails =0;
|
|
||||||
BitstreamIn bits = {key, 56, 0};
|
BitstreamIn bits = {key, 56, 0};
|
||||||
|
|
||||||
bool parity = 0;
|
bool parity = 0;
|
||||||
|
|
||||||
for(i =0 ; i < 56; i++)
|
for (i = 0; i < 56; i++) {
|
||||||
{
|
|
||||||
|
|
||||||
if ( i > 0 && i % 7 == 0)
|
if ( i > 0 && i % 7 == 0){
|
||||||
{
|
|
||||||
parity = !parity;
|
parity = !parity;
|
||||||
bool pbit = stored_parity & (0x80 >> (byte));
|
bool pbit = stored_parity & (0x80 >> (byte));
|
||||||
if(parity != pbit)
|
if (parity != pbit) {
|
||||||
{
|
PrintAndLogEx(NORMAL, "parity2 fail byte %d, should be %d, was %d", (i / 7), parity, pbit);
|
||||||
printf("parity2 fail byte %d, should be %d, was %d\n", (i / 7), parity, pbit);
|
|
||||||
fails++;
|
fails++;
|
||||||
}
|
}
|
||||||
parity =0 ;
|
parity =0 ;
|
||||||
|
@ -723,35 +716,32 @@ void checkParity2(uint8_t* key)
|
||||||
}
|
}
|
||||||
parity = parity ^ headBit(&bits);
|
parity = parity ^ headBit(&bits);
|
||||||
}
|
}
|
||||||
if(fails)
|
if (fails) {
|
||||||
{
|
PrintAndLogEx(FAILED, "parity2 fails: %d", fails);
|
||||||
printf("parity2 fails: %d\n", fails);
|
} else {
|
||||||
}else
|
PrintAndLogEx(INFO, "Key syntax is with parity bits grouped in the last byte!");
|
||||||
{
|
|
||||||
printf("Key syntax is with parity bits grouped in the last byte!\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void modifyKey_put_parity_last(uint8_t * key, uint8_t* output)
|
|
||||||
{
|
void modifyKey_put_parity_last(uint8_t * key, uint8_t* output) {
|
||||||
|
|
||||||
uint8_t paritybits = 0;
|
uint8_t paritybits = 0;
|
||||||
bool parity =0;
|
bool parity =0;
|
||||||
BitstreamOut out = { output, 0,0};
|
BitstreamOut out = { output, 0, 0};
|
||||||
unsigned int bbyte, bbit;
|
unsigned int bbyte, bbit;
|
||||||
for(bbyte=0; bbyte <8 ; bbyte++ )
|
for (bbyte = 0; bbyte <8; bbyte++ ) {
|
||||||
{
|
for(bbit = 0; bbit < 7; bbit++) {
|
||||||
for(bbit =0 ; bbit< 7 ; bbit++)
|
bool bit = *(key + bbyte) & (1 << (7 - bbit));
|
||||||
{
|
pushBit(&out, bit);
|
||||||
bool bit = *(key+bbyte) & (1 << (7-bbit));
|
|
||||||
pushBit(&out,bit);
|
|
||||||
parity ^= bit;
|
parity ^= bit;
|
||||||
}
|
}
|
||||||
bool paritybit = *(key+bbyte) & 1;
|
bool paritybit = *(key + bbyte) & 1;
|
||||||
paritybits |= paritybit << (7-bbyte);
|
paritybits |= paritybit << (7 - bbyte);
|
||||||
parity = 0;
|
parity = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
output[7] = paritybits;
|
output[7] = paritybits;
|
||||||
printf("Parity byte: %02x\n", paritybits);
|
PrintAndLogEx(INFO, "Parity byte: %02x", paritybits);
|
||||||
}
|
}
|
||||||
|
|
||||||
* @brief Modifies a key with parity bits last, so that it is formed with parity
|
* @brief Modifies a key with parity bits last, so that it is formed with parity
|
||||||
|
@ -759,25 +749,24 @@ void modifyKey_put_parity_last(uint8_t * key, uint8_t* output)
|
||||||
* @param key
|
* @param key
|
||||||
* @param output
|
* @param output
|
||||||
|
|
||||||
void modifyKey_put_parity_allover(uint8_t * key, uint8_t* output)
|
void modifyKey_put_parity_allover(uint8_t * key, uint8_t* output) {
|
||||||
{
|
|
||||||
bool parity =0;
|
bool parity =0;
|
||||||
BitstreamOut out = { output, 0,0};
|
BitstreamOut out = {output, 0, 0};
|
||||||
BitstreamIn in = {key, 0,0};
|
BitstreamIn in = {key, 0, 0};
|
||||||
unsigned int bbyte, bbit;
|
unsigned int bbyte, bbit;
|
||||||
for(bbit =0 ; bbit < 56 ; bbit++) {
|
for (bbit = 0; bbit < 56; bbit++) {
|
||||||
if( bbit > 0 && bbit % 7 == 0) {
|
if (bbit > 0 && bbit % 7 == 0) {
|
||||||
pushBit(&out,!parity);
|
pushBit(&out, !parity);
|
||||||
parity = 0;
|
parity = 0;
|
||||||
}
|
}
|
||||||
bool bit = headBit(&in);
|
bool bit = headBit(&in);
|
||||||
pushBit(&out,bit );
|
pushBit(&out, bit);
|
||||||
parity ^= bit;
|
parity ^= bit;
|
||||||
}
|
}
|
||||||
pushBit(&out, !parity);
|
pushBit(&out, !parity);
|
||||||
|
|
||||||
if( des_key_check_key_parity(output))
|
if (des_key_check_key_parity(output))
|
||||||
printf("modifyKey_put_parity_allover fail, DES key invalid parity!");
|
PrintAndLogEx(FAILED, "modifyKey_put_parity_allover fail, DES key invalid parity!");
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -34,10 +34,10 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
|
||||||
bool first_run = true;
|
bool first_run = true;
|
||||||
|
|
||||||
// message
|
// message
|
||||||
PrintAndLogEx(INFO, "--------------------------------------------------------------------------------\n");
|
PrintAndLogEx(INFO, "--------------------------------------------------------------------------------");
|
||||||
PrintAndLogEx(INFO, "executing Darkside attack. Expected execution time: 25sec on average");
|
PrintAndLogEx(INFO, "Executing darkside attack. Expected execution time: 25sec on average");
|
||||||
PrintAndLogEx(INFO, "press pm3-button on the Proxmark3 device to abort both Proxmark3 and client.");
|
PrintAndLogEx(INFO, "press pm3-button on the Proxmark3 device to abort both Proxmark3 and client");
|
||||||
PrintAndLogEx(INFO, "--------------------------------------------------------------------------------\n");
|
PrintAndLogEx(INFO, "--------------------------------------------------------------------------------");
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
|
@ -58,8 +58,8 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
|
||||||
|
|
||||||
// wait cycle
|
// wait cycle
|
||||||
while (true) {
|
while (true) {
|
||||||
printf(".");
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
fflush(stdout);
|
|
||||||
if (kbd_enter_pressed()) {
|
if (kbd_enter_pressed()) {
|
||||||
return PM3_EOPABORTED;
|
return PM3_EOPABORTED;
|
||||||
}
|
}
|
||||||
|
@ -206,8 +206,7 @@ int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk,
|
||||||
|
|
||||||
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||||
timeout++;
|
timeout++;
|
||||||
printf(".");
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
fflush(stdout);
|
|
||||||
// max timeout for one chunk of 85keys, 60*3sec = 180seconds
|
// max timeout for one chunk of 85keys, 60*3sec = 180seconds
|
||||||
// s70 with 40*2 keys to check, 80*85 = 6800 auth.
|
// s70 with 40*2 keys to check, 80*85 = 6800 auth.
|
||||||
// takes about 97s, still some margin before abort
|
// takes about 97s, still some margin before abort
|
||||||
|
@ -221,7 +220,7 @@ int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk,
|
||||||
// time to convert the returned data.
|
// time to convert the returned data.
|
||||||
uint8_t curr_keys = resp.oldarg[0];
|
uint8_t curr_keys = resp.oldarg[0];
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "\nChunk: %.1fs | found %u/%u keys (%u)", (float)(t2 / 1000.0), curr_keys, (sectorsCnt << 1), size);
|
PrintAndLogEx(INFO, "Chunk: %.1fs | found %u/%u keys (%u)", (float)(t2 / 1000.0), curr_keys, (sectorsCnt << 1), size);
|
||||||
|
|
||||||
// all keys?
|
// all keys?
|
||||||
if (curr_keys == sectorsCnt * 2 || lastChunk) {
|
if (curr_keys == sectorsCnt * 2 || lastChunk) {
|
||||||
|
@ -311,6 +310,7 @@ int mfCheckKeys_file(uint8_t *destfn, uint64_t *key) {
|
||||||
} PACKED;
|
} PACKED;
|
||||||
struct kr *keyresult = (struct kr *)&resp.data.asBytes;
|
struct kr *keyresult = (struct kr *)&resp.data.asBytes;
|
||||||
if (!keyresult->found) return PM3_ESOFT;
|
if (!keyresult->found) return PM3_ESOFT;
|
||||||
|
|
||||||
*key = bytes_to_num(keyresult->key, sizeof(keyresult->key));
|
*key = bytes_to_num(keyresult->key, sizeof(keyresult->key));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -418,9 +418,6 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
|
||||||
return PM3_ETIMEOUT;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resp.status != PM3_SUCCESS)
|
|
||||||
return PM3_ESOFT;
|
|
||||||
|
|
||||||
struct p {
|
struct p {
|
||||||
int16_t isOK;
|
int16_t isOK;
|
||||||
uint8_t block;
|
uint8_t block;
|
||||||
|
@ -433,8 +430,9 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
|
||||||
} PACKED;
|
} PACKED;
|
||||||
struct p *package = (struct p *)resp.data.asBytes;
|
struct p *package = (struct p *)resp.data.asBytes;
|
||||||
|
|
||||||
// error during nested
|
// error during nested on device side
|
||||||
if (package->isOK) return package->isOK;
|
if (package->isOK != PM3_SUCCESS)
|
||||||
|
return package->isOK;
|
||||||
|
|
||||||
memcpy(&uid, package->cuid, sizeof(package->cuid));
|
memcpy(&uid, package->cuid, sizeof(package->cuid));
|
||||||
|
|
||||||
|
@ -450,7 +448,6 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
|
||||||
memcpy(&statelists[1].nt_enc, package->nt_b, sizeof(package->nt_b));
|
memcpy(&statelists[1].nt_enc, package->nt_b, sizeof(package->nt_b));
|
||||||
memcpy(&statelists[1].ks1, package->ks_b, sizeof(package->ks_b));
|
memcpy(&statelists[1].ks1, package->ks_b, sizeof(package->ks_b));
|
||||||
|
|
||||||
|
|
||||||
// calc keys
|
// calc keys
|
||||||
pthread_t thread_id[2];
|
pthread_t thread_id[2];
|
||||||
|
|
||||||
|
@ -538,32 +535,30 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
|
||||||
free(statelists[1].head.slhead);
|
free(statelists[1].head.slhead);
|
||||||
num_to_bytes(key64, 6, resultKey);
|
num_to_bytes(key64, 6, resultKey);
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "target block:%3u key type: %c -- found valid key [" _YELLOW_("%s") "]",
|
PrintAndLogEx(SUCCESS, "\ntarget block:%3u key type: %c -- found valid key [" _YELLOW_("%s") "]",
|
||||||
package->block,
|
package->block,
|
||||||
package->keytype ? 'B' : 'A',
|
package->keytype ? 'B' : 'A',
|
||||||
sprint_hex(resultKey, 6)
|
sprint_hex(resultKey, 6)
|
||||||
);
|
);
|
||||||
return -5;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (i + 1 % 10 == 0) {
|
|
||||||
float bruteforce_per_second = (float)(i + max_keys) / ((msclock() - start_time) / 1000.0);
|
float bruteforce_per_second = (float)(i + max_keys) / ((msclock() - start_time) / 1000.0);
|
||||||
PrintAndLogEx(INFO, "%6d/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt, bruteforce_per_second, (keycnt - i) / bruteforce_per_second);
|
PrintAndLogEx(INPLACE, "%6d/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt, bruteforce_per_second, (keycnt - i) / bruteforce_per_second);
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
PrintAndLogEx(SUCCESS, "target block:%3u key type: %c",
|
PrintAndLogEx(SUCCESS, "\ntarget block:%3u key type: %c",
|
||||||
package->block,
|
package->block,
|
||||||
package->keytype ? 'B' : 'A'
|
package->keytype ? 'B' : 'A'
|
||||||
);
|
);
|
||||||
|
|
||||||
free(statelists[0].head.slhead);
|
free(statelists[0].head.slhead);
|
||||||
free(statelists[1].head.slhead);
|
free(statelists[1].head.slhead);
|
||||||
return -4;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey) {
|
int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey) {
|
||||||
|
|
||||||
uint32_t uid;
|
uint32_t uid;
|
||||||
|
@ -612,7 +607,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
|
||||||
statelists[0].keyType = package->keytype;
|
statelists[0].keyType = package->keytype;
|
||||||
statelists[0].uid = uid;
|
statelists[0].uid = uid;
|
||||||
|
|
||||||
memcpy(&statelists[0].nt_enc, package->nt, sizeof(package->nt));
|
memcpy(&statelists[0].nt_enc, package->nt, sizeof(package->nt));
|
||||||
memcpy(&statelists[0].ks1, package->ks, sizeof(package->ks));
|
memcpy(&statelists[0].ks1, package->ks, sizeof(package->ks));
|
||||||
|
|
||||||
// calc keys
|
// calc keys
|
||||||
|
@ -678,6 +673,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
|
||||||
//flush queue
|
//flush queue
|
||||||
while (kbd_enter_pressed()) {
|
while (kbd_enter_pressed()) {
|
||||||
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
free(mem);
|
free(mem);
|
||||||
return PM3_EOPABORTED;
|
return PM3_EOPABORTED;
|
||||||
}
|
}
|
||||||
|
@ -694,14 +690,17 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
|
||||||
|
|
||||||
// check a block of generated key candidates.
|
// check a block of generated key candidates.
|
||||||
if (IfPm3Flash()) {
|
if (IfPm3Flash()) {
|
||||||
|
|
||||||
|
mem[3] = ((chunk >> 8) & 0xFF);
|
||||||
|
mem[4] = (chunk & 0xFF);
|
||||||
|
|
||||||
// upload to flash.
|
// upload to flash.
|
||||||
res = flashmem_spiffs_load(destfn, mem, 5 + (chunk * 6));
|
res = flashmem_spiffs_load(destfn, mem, 5 + (chunk * 6));
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(WARNING, "SPIFFS upload failed");
|
PrintAndLogEx(WARNING, "\nSPIFFS upload failed");
|
||||||
free(mem);
|
free(mem);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = mfCheckKeys_file(destfn, &key64);
|
res = mfCheckKeys_file(destfn, &key64);
|
||||||
} else {
|
} else {
|
||||||
res = mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, chunk, mem, &key64);
|
res = mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, chunk, mem, &key64);
|
||||||
|
@ -714,6 +713,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
|
||||||
|
|
||||||
num_to_bytes(key64, 6, resultKey);
|
num_to_bytes(key64, 6, resultKey);
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(SUCCESS, "target block:%3u key type: %c -- found valid key [" _YELLOW_("%s") "]",
|
PrintAndLogEx(SUCCESS, "target block:%3u key type: %c -- found valid key [" _YELLOW_("%s") "]",
|
||||||
package->block,
|
package->block,
|
||||||
package->keytype ? 'B' : 'A',
|
package->keytype ? 'B' : 'A',
|
||||||
|
@ -721,21 +721,20 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
|
||||||
);
|
);
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
} else if (res == PM3_ETIMEOUT || res == PM3_EOPABORTED) {
|
} else if (res == PM3_ETIMEOUT || res == PM3_EOPABORTED) {
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
free(mem);
|
free(mem);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (i%10 == 0) {
|
|
||||||
float bruteforce_per_second = (float)(i + max_keys_chunk) / ((msclock() - start_time) / 1000.0);
|
float bruteforce_per_second = (float)(i + max_keys_chunk) / ((msclock() - start_time) / 1000.0);
|
||||||
PrintAndLogEx(INFO, "%6u/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt, bruteforce_per_second, (keycnt - i) / bruteforce_per_second);
|
PrintAndLogEx(INPLACE, "%6u/%u keys | %5.1f keys/sec | worst case %6.1f seconds", i, keycnt, bruteforce_per_second, (keycnt - i) / bruteforce_per_second);
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p_keyblock = NULL;
|
p_keyblock = NULL;
|
||||||
free(mem);
|
free(mem);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
PrintAndLogEx(SUCCESS, "target block:%3u key type: %c",
|
PrintAndLogEx(SUCCESS, "\ntarget block:%3u key type: %c",
|
||||||
package->block,
|
package->block,
|
||||||
package->keytype ? 'B' : 'A'
|
package->keytype ? 'B' : 'A'
|
||||||
);
|
);
|
||||||
|
@ -865,7 +864,7 @@ int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, uint8_
|
||||||
|
|
||||||
int mfCWipe(uint8_t *uid, uint8_t *atqa, uint8_t *sak) {
|
int mfCWipe(uint8_t *uid, uint8_t *atqa, uint8_t *sak) {
|
||||||
uint8_t block0[16] = {0x01, 0x02, 0x03, 0x04, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xAF};
|
uint8_t block0[16] = {0x01, 0x02, 0x03, 0x04, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xAF};
|
||||||
//uint8_t blockD[16] = {0x00};
|
uint8_t blockD[16] = {0x00};
|
||||||
uint8_t blockK[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x77, 0x8F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
uint8_t blockK[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x77, 0x8F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||||
uint8_t params = MAGIC_SINGLE;
|
uint8_t params = MAGIC_SINGLE;
|
||||||
|
|
||||||
|
@ -887,12 +886,12 @@ int mfCWipe(uint8_t *uid, uint8_t *atqa, uint8_t *sak) {
|
||||||
PrintAndLogEx(INPLACE, "wipe block %d", blockNo);
|
PrintAndLogEx(INPLACE, "wipe block %d", blockNo);
|
||||||
|
|
||||||
if (blockNo == 0) {
|
if (blockNo == 0) {
|
||||||
res = mfCSetBlock(blockNo, block0, NULL, (params | MAGIC_WIPE));
|
res = mfCSetBlock(blockNo, block0, NULL, params);
|
||||||
} else {
|
} else {
|
||||||
if (mfIsSectorTrailer(blockNo))
|
if (mfIsSectorTrailer(blockNo))
|
||||||
res = mfCSetBlock(blockNo, blockK, NULL, params);
|
res = mfCSetBlock(blockNo, blockK, NULL, params);
|
||||||
// else
|
else
|
||||||
// res = mfCSetBlock(blockNo, blockD, NULL, params);
|
res = mfCSetBlock(blockNo, blockD, NULL, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res == PM3_SUCCESS)
|
if (res == PM3_SUCCESS)
|
||||||
|
@ -916,7 +915,7 @@ int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params) {
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandMIX(CMD_HF_MIFARE_CSETBL, params, blockNo, 0, data, 16);
|
SendCommandMIX(CMD_HF_MIFARE_CSETBL, params, blockNo, 0, data, 16);
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 3500)) {
|
||||||
uint8_t isOK = resp.oldarg[0] & 0xff;
|
uint8_t isOK = resp.oldarg[0] & 0xff;
|
||||||
if (uid != NULL)
|
if (uid != NULL)
|
||||||
memcpy(uid, resp.data.asBytes, 4);
|
memcpy(uid, resp.data.asBytes, 4);
|
||||||
|
@ -945,8 +944,47 @@ int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SNIFFER
|
int mfGen3UID(uint8_t *uid, uint8_t uidlen, uint8_t *oldUid) {
|
||||||
// [iceman] so many global variables....
|
clearCommandBuffer();
|
||||||
|
SendCommandMIX(CMD_HF_MIFARE_GEN3UID, uidlen, 0, 0, uid, uidlen);
|
||||||
|
PacketResponseNG resp;
|
||||||
|
if (WaitForResponseTimeout(CMD_HF_MIFARE_GEN3UID, &resp, 3500)) {
|
||||||
|
if (resp.status == PM3_SUCCESS && oldUid) {
|
||||||
|
memcpy(oldUid, resp.data.asBytes, uidlen);
|
||||||
|
}
|
||||||
|
return resp.status;
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(WARNING, "Command execute timeout");
|
||||||
|
return PM3_ETIMEOUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int mfGen3Blk(uint8_t *block, int blockLen, uint8_t *newBlock) {
|
||||||
|
clearCommandBuffer();
|
||||||
|
SendCommandMIX(CMD_HF_MIFARE_GEN3BLK, blockLen, 0, 0, block, 16);
|
||||||
|
PacketResponseNG resp;
|
||||||
|
if (WaitForResponseTimeout(CMD_HF_MIFARE_GEN3BLK, &resp, 3500)) {
|
||||||
|
if (resp.status == PM3_SUCCESS && newBlock) {
|
||||||
|
memcpy(newBlock, resp.data.asBytes, 16);
|
||||||
|
}
|
||||||
|
return resp.status;
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(WARNING, "Command execute timeout");
|
||||||
|
return PM3_ETIMEOUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int mfGen3Freez(void) {
|
||||||
|
clearCommandBuffer();
|
||||||
|
SendCommandNG(CMD_HF_MIFARE_GEN3FREEZ, NULL, 0);
|
||||||
|
PacketResponseNG resp;
|
||||||
|
if (WaitForResponseTimeout(CMD_HF_MIFARE_GEN3FREEZ, &resp, 3500)) {
|
||||||
|
return resp.status;
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(WARNING, "Command execute timeout");
|
||||||
|
return PM3_ETIMEOUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
uint32_t cuid = 0; // uid part used for crypto1.
|
uint32_t cuid = 0; // uid part used for crypto1.
|
||||||
|
@ -1037,14 +1075,16 @@ int detect_classic_nackbug(bool verbose) {
|
||||||
PrintAndLogEx(SUCCESS, "press pm3-button on the Proxmark3 device to abort both Proxmark3 and client.\n");
|
PrintAndLogEx(SUCCESS, "press pm3-button on the Proxmark3 device to abort both Proxmark3 and client.\n");
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
printf(".");
|
|
||||||
fflush(stdout);
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
if (kbd_enter_pressed()) {
|
if (kbd_enter_pressed()) {
|
||||||
return PM3_EOPABORTED;
|
return PM3_EOPABORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_NACK_DETECT, &resp, 500)) {
|
if (WaitForResponseTimeout(CMD_HF_MIFARE_NACK_DETECT, &resp, 500)) {
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
if (resp.status == PM3_EOPABORTED) {
|
if (resp.status == PM3_EOPABORTED) {
|
||||||
PrintAndLogEx(WARNING, "button pressed. Aborted.");
|
PrintAndLogEx(WARNING, "button pressed. Aborted.");
|
||||||
return PM3_EOPABORTED;
|
return PM3_EOPABORTED;
|
||||||
|
@ -1053,7 +1093,6 @@ int detect_classic_nackbug(bool verbose) {
|
||||||
uint8_t ok = resp.data.asBytes[0];
|
uint8_t ok = resp.data.asBytes[0];
|
||||||
uint8_t nacks = resp.data.asBytes[1];
|
uint8_t nacks = resp.data.asBytes[1];
|
||||||
uint16_t auths = bytes_to_num(resp.data.asBytes + 2, 2);
|
uint16_t auths = bytes_to_num(resp.data.asBytes + 2, 2);
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
PrintAndLogEx(SUCCESS, "num of auth requests : %u", auths);
|
PrintAndLogEx(SUCCESS, "num of auth requests : %u", auths);
|
||||||
|
@ -1070,7 +1109,7 @@ int detect_classic_nackbug(bool verbose) {
|
||||||
case 97 : {
|
case 97 : {
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
PrintAndLogEx(FAILED, "card random number generator seems to be based on the well-known generating polynomial");
|
PrintAndLogEx(FAILED, "card random number generator seems to be based on the well-known generating polynomial");
|
||||||
PrintAndLogEx(NORMAL, "[- ]with 16 effective bits only, but shows unexpected behavior, try again.");
|
PrintAndLogEx(FAILED, "with 16 effective bits only, but shows unexpected behavior, try again.");
|
||||||
}
|
}
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,6 +80,10 @@ int mfCWipe(uint8_t *uid, uint8_t *atqa, uint8_t *sak);
|
||||||
int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params);
|
int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params);
|
||||||
int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params);
|
int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params);
|
||||||
|
|
||||||
|
int mfGen3UID(uint8_t *uid, uint8_t uidlen, uint8_t *oldUid);
|
||||||
|
int mfGen3Blk(uint8_t *block, int blockLen, uint8_t *newBlock);
|
||||||
|
int mfGen3Freez(void);
|
||||||
|
|
||||||
int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len);
|
int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len);
|
||||||
|
|
||||||
int detect_classic_prng(void);
|
int detect_classic_prng(void);
|
||||||
|
|
|
@ -108,7 +108,7 @@ static void showBanner(void) {
|
||||||
#endif
|
#endif
|
||||||
// PrintAndLogEx(NORMAL, "\nSupport iceman on patreon - https://www.patreon.com/iceman1001/");
|
// PrintAndLogEx(NORMAL, "\nSupport iceman on patreon - https://www.patreon.com/iceman1001/");
|
||||||
// PrintAndLogEx(NORMAL, " on paypal - https://www.paypal.me/iceman1001");
|
// PrintAndLogEx(NORMAL, " on paypal - https://www.paypal.me/iceman1001");
|
||||||
// printf("\nMonero: 43mNJLpgBVaTvyZmX9ajcohpvVkaRy1kbZPm8tqAb7itZgfuYecgkRF36rXrKFUkwEGeZedPsASRxgv4HPBHvJwyJdyvQuP");
|
// PrintAndLogEx(NORMAL, "\nMonero: 43mNJLpgBVaTvyZmX9ajcohpvVkaRy1kbZPm8tqAb7itZgfuYecgkRF36rXrKFUkwEGeZedPsASRxgv4HPBHvJwyJdyvQuP");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG;
|
g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG;
|
||||||
|
@ -678,55 +678,8 @@ finish2:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if windows AnsiColor Support is enabled in the registery
|
|
||||||
// [HKEY_CURRENT_USER\Console]
|
|
||||||
// "VirtualTerminalLevel"=dword:00000001
|
|
||||||
// 2nd Key needs to be enabled... This key takes the console out of legacy mode.
|
|
||||||
// [HKEY_CURRENT_USER\Console]
|
|
||||||
// "ForceV2"=dword:00000001
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
static bool DetectWindowsAnsiSupport(void) {
|
static bool DetectWindowsAnsiSupport(void) {
|
||||||
HKEY hKey = NULL;
|
|
||||||
bool virtualTerminalLevelSet = false;
|
|
||||||
bool forceV2Set = false;
|
|
||||||
|
|
||||||
if (RegOpenKeyA(HKEY_CURRENT_USER, "Console", &hKey) == ERROR_SUCCESS) {
|
|
||||||
DWORD dwType = REG_SZ;
|
|
||||||
BYTE KeyValue[sizeof(dwType)];
|
|
||||||
DWORD len = sizeof(KeyValue);
|
|
||||||
|
|
||||||
if (RegQueryValueEx(hKey, "VirtualTerminalLevel", NULL, &dwType, KeyValue, &len) != ERROR_FILE_NOT_FOUND) {
|
|
||||||
uint8_t i;
|
|
||||||
uint32_t Data = 0;
|
|
||||||
for (i = 0; i < 4; i++)
|
|
||||||
Data += KeyValue[i] << (8 * i);
|
|
||||||
|
|
||||||
if (Data == 1) { // Reg key is set to 1, Ansi Color Enabled
|
|
||||||
virtualTerminalLevelSet = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RegCloseKey(hKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RegOpenKeyA(HKEY_CURRENT_USER, "Console", &hKey) == ERROR_SUCCESS) {
|
|
||||||
DWORD dwType = REG_SZ;
|
|
||||||
BYTE KeyValue[sizeof(dwType)];
|
|
||||||
DWORD len = sizeof(KeyValue);
|
|
||||||
|
|
||||||
if (RegQueryValueEx(hKey, "ForceV2", NULL, &dwType, KeyValue, &len) != ERROR_FILE_NOT_FOUND) {
|
|
||||||
uint8_t i;
|
|
||||||
uint32_t Data = 0;
|
|
||||||
for (i = 0; i < 4; i++)
|
|
||||||
Data += KeyValue[i] << (8 * i);
|
|
||||||
|
|
||||||
if (Data == 1) { // Reg key is set to 1, Not using legacy Mode.
|
|
||||||
forceV2Set = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RegCloseKey(hKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||||
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
|
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
|
||||||
#endif
|
#endif
|
||||||
|
@ -735,10 +688,8 @@ static bool DetectWindowsAnsiSupport(void) {
|
||||||
DWORD dwMode = 0;
|
DWORD dwMode = 0;
|
||||||
GetConsoleMode(hOut, &dwMode);
|
GetConsoleMode(hOut, &dwMode);
|
||||||
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||||
SetConsoleMode(hOut, dwMode);
|
|
||||||
|
|
||||||
// If both VirtualTerminalLevel and ForceV2 is set, AnsiColor should work
|
return SetConsoleMode(hOut, dwMode) ? true : false;
|
||||||
return virtualTerminalLevelSet && forceV2Set;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -474,14 +474,14 @@ static int l_mfDarkside(lua_State *L) {
|
||||||
static int l_foobar(lua_State *L) {
|
static int l_foobar(lua_State *L) {
|
||||||
//Check number of arguments
|
//Check number of arguments
|
||||||
int n = lua_gettop(L);
|
int n = lua_gettop(L);
|
||||||
printf("foobar called with %d arguments", n);
|
PrintAndLogEx(INFO, "foobar called with %d arguments", n);
|
||||||
lua_settop(L, 0);
|
lua_settop(L, 0);
|
||||||
printf("Arguments discarded, stack now contains %d elements", lua_gettop(L));
|
PrintAndLogEx(INFO, "Arguments discarded, stack now contains %d elements", lua_gettop(L));
|
||||||
|
|
||||||
// todo: this is not used, where was it intended for?
|
// todo: this is not used, where was it intended for?
|
||||||
// PacketCommandOLD response = {CMD_HF_MIFARE_READBL, {1337, 1338, 1339}, {{0}}};
|
// PacketCommandOLD response = {CMD_HF_MIFARE_READBL, {1337, 1338, 1339}, {{0}}};
|
||||||
|
|
||||||
printf("Now returning a uint64_t as a string");
|
PrintAndLogEx(INFO, "Now returning a uint64_t as a string");
|
||||||
uint64_t x = 0xDEADC0DE;
|
uint64_t x = 0xDEADC0DE;
|
||||||
uint8_t destination[8];
|
uint8_t destination[8];
|
||||||
num_to_bytes(x, sizeof(x), destination);
|
num_to_bytes(x, sizeof(x), destination);
|
||||||
|
@ -1046,7 +1046,7 @@ static int l_T55xx_detect(lua_State *L) {
|
||||||
|
|
||||||
sscanf(p_gb, "%u", &gb);
|
sscanf(p_gb, "%u", &gb);
|
||||||
useGB = (gb) ? true : false;
|
useGB = (gb) ? true : false;
|
||||||
printf("p_gb size %zu | %c \n", size, useGB ? 'Y' : 'N');
|
PrintAndLogEx(INFO, "p_gb size %zu | %c", size, useGB ? 'Y' : 'N');
|
||||||
}
|
}
|
||||||
case 1: {
|
case 1: {
|
||||||
const char *p_pwd = luaL_checklstring(L, 1, &size);
|
const char *p_pwd = luaL_checklstring(L, 1, &size);
|
||||||
|
@ -1129,9 +1129,7 @@ static int l_remark(lua_State *L) {
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size;
|
size_t size;
|
||||||
// data
|
|
||||||
const char *s = luaL_checklstring(L, 1, &size);
|
const char *s = luaL_checklstring(L, 1, &size);
|
||||||
|
|
||||||
int res = CmdRem(s);
|
int res = CmdRem(s);
|
||||||
lua_pushinteger(L, res);
|
lua_pushinteger(L, res);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1199,6 +1197,19 @@ static int l_cwd(lua_State *L) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ref: https://github.com/RfidResearchGroup/proxmark3/issues/891
|
||||||
|
// redirect LUA's print to Proxmark3 PrintAndLogEx
|
||||||
|
static int l_printandlogex(lua_State *L) {
|
||||||
|
|
||||||
|
int n = lua_gettop(L);
|
||||||
|
for (int i = 1; i <= n; i++) {
|
||||||
|
if (lua_isstring(L, i)) {
|
||||||
|
PrintAndLogEx(NORMAL, "%s", lua_tostring(L, i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the lua path to include "./lualibs/?.lua", in order for a script to be
|
* @brief Sets the lua path to include "./lualibs/?.lua", in order for a script to be
|
||||||
* able to do "require('foobar')" if foobar.lua is within lualibs folder.
|
* able to do "require('foobar')" if foobar.lua is within lualibs folder.
|
||||||
|
@ -1269,21 +1280,24 @@ int set_pm3_libraries(lua_State *L) {
|
||||||
|
|
||||||
lua_pushglobaltable(L);
|
lua_pushglobaltable(L);
|
||||||
// Core library is in this table. Contains '
|
// Core library is in this table. Contains '
|
||||||
//this is 'pm3' table
|
// this is 'pm3' table
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
|
|
||||||
//Put the function into the hash table.
|
// put the function into the hash table.
|
||||||
for (int i = 0; libs[i].name; i++) {
|
for (int i = 0; libs[i].name; i++) {
|
||||||
lua_pushcfunction(L, libs[i].func);
|
lua_pushcfunction(L, libs[i].func);
|
||||||
lua_setfield(L, -2, libs[i].name);//set the name, pop stack
|
lua_setfield(L, -2, libs[i].name);//set the name, pop stack
|
||||||
}
|
}
|
||||||
//Name of 'core'
|
// Name of 'core'
|
||||||
lua_setfield(L, -2, "core");
|
lua_setfield(L, -2, "core");
|
||||||
|
|
||||||
//-- remove the global environment table from the stack
|
// remove the global environment table from the stack
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
//--add to the LUA_PATH (package.path in lua)
|
// print redirect here
|
||||||
|
lua_register(L, "print", l_printandlogex);
|
||||||
|
|
||||||
|
// add to the LUA_PATH (package.path in lua)
|
||||||
// so we can load scripts from various places:
|
// so we can load scripts from various places:
|
||||||
const char *exec_path = get_my_executable_directory();
|
const char *exec_path = get_my_executable_directory();
|
||||||
if (exec_path != NULL) {
|
if (exec_path != NULL) {
|
||||||
|
|
|
@ -359,7 +359,7 @@ void uart_close(const serial_port sp) {
|
||||||
int err = fcntl(spu->fd, F_SETLK, &fl);
|
int err = fcntl(spu->fd, F_SETLK, &fl);
|
||||||
if (err == -1) {
|
if (err == -1) {
|
||||||
//silent error message as it can be called from uart_open failing modes, e.g. when waiting for port to appear
|
//silent error message as it can be called from uart_open failing modes, e.g. when waiting for port to appear
|
||||||
//printf("[!] UART error while closing port\n");
|
//PrintAndLogEx(ERR, "UART error while closing port");
|
||||||
}
|
}
|
||||||
close(spu->fd);
|
close(spu->fd);
|
||||||
free(sp);
|
free(sp);
|
||||||
|
@ -401,12 +401,12 @@ int uart_receive(const serial_port sp, uint8_t *pbtRx, uint32_t pszMaxRxLen, uin
|
||||||
|
|
||||||
// Retrieve the count of the incoming bytes
|
// Retrieve the count of the incoming bytes
|
||||||
res = ioctl(((serial_port_unix *)sp)->fd, FIONREAD, &byteCount);
|
res = ioctl(((serial_port_unix *)sp)->fd, FIONREAD, &byteCount);
|
||||||
// printf("UART:: RX ioctl res %d byteCount %u\n", res, byteCount);
|
// PrintAndLogEx(ERR, "UART:: RX ioctl res %d byteCount %u", res, byteCount);
|
||||||
if (res < 0) return PM3_ENOTTY;
|
if (res < 0) return PM3_ENOTTY;
|
||||||
|
|
||||||
// Cap the number of bytes, so we don't overrun the buffer
|
// Cap the number of bytes, so we don't overrun the buffer
|
||||||
if (pszMaxRxLen - (*pszRxLen) < byteCount) {
|
if (pszMaxRxLen - (*pszRxLen) < byteCount) {
|
||||||
// printf("UART:: RX prevent overrun (have %u, need %u)\n", pszMaxRxLen - (*pszRxLen), byteCount);
|
// PrintAndLogEx(ERR, "UART:: RX prevent overrun (have %u, need %u)", pszMaxRxLen - (*pszRxLen), byteCount);
|
||||||
byteCount = pszMaxRxLen - (*pszRxLen);
|
byteCount = pszMaxRxLen - (*pszRxLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,13 +443,13 @@ int uart_send(const serial_port sp, const uint8_t *pbtTx, const uint32_t len) {
|
||||||
|
|
||||||
// Write error
|
// Write error
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
printf("UART:: write error (%d)\n", res);
|
PrintAndLogEx(ERR, "UART:: write error (%d)", res);
|
||||||
return PM3_ENOTTY;
|
return PM3_ENOTTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write time-out
|
// Write time-out
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
printf("UART:: write time-out\n");
|
PrintAndLogEx(ERR, "UART:: write time-out");
|
||||||
return PM3_ETIMEOUT;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ extern "C" {
|
||||||
#define _USE_MATH_DEFINES
|
#define _USE_MATH_DEFINES
|
||||||
|
|
||||||
typedef enum logLevel {NORMAL, SUCCESS, INFO, FAILED, WARNING, ERR, DEBUG, INPLACE, HINT} logLevel_t;
|
typedef enum logLevel {NORMAL, SUCCESS, INFO, FAILED, WARNING, ERR, DEBUG, INPLACE, HINT} logLevel_t;
|
||||||
#define NOLF "\xff"
|
|
||||||
typedef enum emojiMode {ALIAS, EMOJI, ALTTEXT, ERASE} emojiMode_t;
|
typedef enum emojiMode {ALIAS, EMOJI, ALTTEXT, ERASE} emojiMode_t;
|
||||||
typedef enum clientdebugLevel {cdbOFF, cdbSIMPLE, cdbFULL} clientdebugLevel_t;
|
typedef enum clientdebugLevel {cdbOFF, cdbSIMPLE, cdbFULL} clientdebugLevel_t;
|
||||||
// typedef enum devicedebugLevel {ddbOFF, ddbERROR, ddbINFO, ddbDEBUG, ddbEXTENDED} devicedebugLevel_t;
|
// typedef enum devicedebugLevel {ddbOFF, ddbERROR, ddbINFO, ddbDEBUG, ddbEXTENDED} devicedebugLevel_t;
|
||||||
|
|
|
@ -96,6 +96,7 @@ void FillFileNameByUID(char *filenamePrefix, const uint8_t *uid, const char *ext
|
||||||
|
|
||||||
for (int j = 0; j < uidlen; j++)
|
for (int j = 0; j < uidlen; j++)
|
||||||
sprintf(filenamePrefix + len + j * 2, "%02X", uid[j]);
|
sprintf(filenamePrefix + len + j * 2, "%02X", uid[j]);
|
||||||
|
|
||||||
strcat(filenamePrefix, ext);
|
strcat(filenamePrefix, ext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,26 +177,27 @@ void print_hex(const uint8_t *data, const size_t len) {
|
||||||
if (data == NULL || len == 0) return;
|
if (data == NULL || len == 0) return;
|
||||||
|
|
||||||
for (size_t i = 0; i < len; i++)
|
for (size_t i = 0; i < len; i++)
|
||||||
printf("%02x ", data[i]);
|
PrintAndLogEx(NORMAL, "%02x " NOLF, data[i]);
|
||||||
printf("\n");
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_hex_break(const uint8_t *data, const size_t len, uint8_t breaks) {
|
void print_hex_break(const uint8_t *data, const size_t len, uint8_t breaks) {
|
||||||
if (data == NULL || len == 0) return;
|
if (data == NULL || len == 0) return;
|
||||||
|
|
||||||
int rownum = 0;
|
int rownum = 0;
|
||||||
printf("[%02d] | ", rownum);
|
PrintAndLogEx(NORMAL, "[%02d] | " NOLF, rownum);
|
||||||
for (size_t i = 0; i < len; ++i) {
|
for (size_t i = 0; i < len; ++i) {
|
||||||
|
|
||||||
printf("%02X ", data[i]);
|
PrintAndLogEx(NORMAL, "%02X " NOLF, data[i]);
|
||||||
|
|
||||||
// check if a line break is needed
|
// check if a line break is needed
|
||||||
if (breaks > 0 && !((i + 1) % breaks) && (i + 1 < len)) {
|
if (breaks > 0 && !((i + 1) % breaks) && (i + 1 < len)) {
|
||||||
++rownum;
|
++rownum;
|
||||||
printf("\n[%02d] | ", rownum);
|
PrintAndLogEx(NORMAL, "\n[%02d] | " NOLF, rownum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("\n");
|
PrintAndLogEx(NORMAL, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
char *sprint_hex(const uint8_t *data, const size_t len) {
|
char *sprint_hex(const uint8_t *data, const size_t len) {
|
||||||
|
@ -229,7 +231,7 @@ char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t brea
|
||||||
if (breaks > 0 && len % breaks != 0)
|
if (breaks > 0 && len % breaks != 0)
|
||||||
rowlen = (len + (len / breaks) > MAX_BIN_BREAK_LENGTH) ? MAX_BIN_BREAK_LENGTH : len + (len / breaks);
|
rowlen = (len + (len / breaks) > MAX_BIN_BREAK_LENGTH) ? MAX_BIN_BREAK_LENGTH : len + (len / breaks);
|
||||||
|
|
||||||
//printf("(sprint_bin_break) rowlen %d\n", rowlen);
|
//PrintAndLogEx(NORMAL, "(sprint_bin_break) rowlen %d", rowlen);
|
||||||
|
|
||||||
static char buf[MAX_BIN_BREAK_LENGTH]; // 3072 + end of line characters if broken at 8 bits
|
static char buf[MAX_BIN_BREAK_LENGTH]; // 3072 + end of line characters if broken at 8 bits
|
||||||
//clear memory
|
//clear memory
|
||||||
|
@ -267,7 +269,7 @@ void sprint_bin_break_ex(uint8_t *src, size_t srclen, char *dest , uint8_t break
|
||||||
else
|
else
|
||||||
rowlen = ( len+(len/breaks) > MAX_BIN_BREAK_LENGTH ) ? MAX_BIN_BREAK_LENGTH : len+(len/breaks);
|
rowlen = ( len+(len/breaks) > MAX_BIN_BREAK_LENGTH ) ? MAX_BIN_BREAK_LENGTH : len+(len/breaks);
|
||||||
|
|
||||||
printf("(sprint_bin_break) rowlen %d\n", rowlen);
|
PrintAndLogEx(NORMAL, "(sprint_bin_break) rowlen %d", rowlen);
|
||||||
|
|
||||||
// 3072 + end of line characters if broken at 8 bits
|
// 3072 + end of line characters if broken at 8 bits
|
||||||
dest = (char *)calloc(MAX_BIN_BREAK_LENGTH, sizeof(uint8_t));
|
dest = (char *)calloc(MAX_BIN_BREAK_LENGTH, sizeof(uint8_t));
|
||||||
|
@ -307,10 +309,13 @@ char *sprint_hex_ascii(const uint8_t *data, const size_t len) {
|
||||||
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
size_t pos = (max_len * 3) + 2;
|
size_t pos = (max_len * 3) + 2;
|
||||||
|
|
||||||
while (i < max_len) {
|
while (i < max_len) {
|
||||||
|
|
||||||
char c = data[i];
|
char c = data[i];
|
||||||
if ((c < 32) || (c == 127))
|
if ((c < 32) || (c == 127))
|
||||||
c = '.';
|
c = '.';
|
||||||
|
|
||||||
sprintf(tmp + pos + i, "%c", c);
|
sprintf(tmp + pos + i, "%c", c);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
@ -682,7 +687,7 @@ int hextobinarray(char *target, char *source) {
|
||||||
else if (x >= 'A' && x <= 'F')
|
else if (x >= 'A' && x <= 'F')
|
||||||
x -= 'A' - 10;
|
x -= 'A' - 10;
|
||||||
else {
|
else {
|
||||||
printf("Discovered unknown character %c %d at idx %d of %s\n", x, x, (int16_t)(source - start), start);
|
PrintAndLogEx(INFO, "(hextobinarray) discovered unknown character %c %d at idx %d of %s", x, x, (int16_t)(source - start), start);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// output
|
// output
|
||||||
|
|
|
@ -134,7 +134,6 @@ static uint8_t get_length_from_header(wiegand_message_t *data) {
|
||||||
hfmt = 0;
|
hfmt = 0;
|
||||||
len = 37;
|
len = 37;
|
||||||
} else if ((data->Mid & 0x0000001F) > 0) { // 36-32 bits
|
} else if ((data->Mid & 0x0000001F) > 0) { // 36-32 bits
|
||||||
printf("a\n");
|
|
||||||
hfmt = data->Mid & 0x0000001F;
|
hfmt = data->Mid & 0x0000001F;
|
||||||
len = 32;
|
len = 32;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -15,7 +15,7 @@ There are two ways to install, build and use Proxmark3 on Windows:
|
||||||
## Driver Installation
|
## Driver Installation
|
||||||
|
|
||||||
Install required drivers for your Windows installation. You may need admin privileges to do this.
|
Install required drivers for your Windows installation. You may need admin privileges to do this.
|
||||||
Step by step guides are online such as [RiscCorps](https://store.ryscc.com/blogs/news/how-to-install-a-proxmark3-driver-on-windows-10).
|
Step by step guides are online such as [RyscCorps](https://store.ryscc.com/blogs/news/how-to-install-a-proxmark3-driver-on-windows-10).
|
||||||
|
|
||||||
## Download / clone ProxSpace repo
|
## Download / clone ProxSpace repo
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
### First things on your RDV40
|
### First things on your RDV40
|
||||||
|
|
||||||
You will need to run these commands to make sure your rdv4 is prepared
|
You will need to run these commands to make sure your rdv4 is prepared
|
||||||
```
|
```
|
||||||
|
[usb] pm3 --> script run init_rdv4
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
The lua script actually executes the following commands below. These are here because of documentation, you can jump down to *Verify sim module firmware version* part.
|
||||||
|
```
|
||||||
[usb] pm3 --> mem load f mfc_default_keys m
|
[usb] pm3 --> mem load f mfc_default_keys m
|
||||||
[usb] pm3 --> mem load f t55xx_default_pwds t
|
[usb] pm3 --> mem load f t55xx_default_pwds t
|
||||||
[usb] pm3 --> mem load f iclass_default_keys i
|
[usb] pm3 --> mem load f iclass_default_keys i
|
||||||
|
@ -13,6 +20,7 @@ Set all t55xx settings to defaults (will set all 4 at once)
|
||||||
[usb] pm3 --> lf t55xx deviceconfig z p
|
[usb] pm3 --> lf t55xx deviceconfig z p
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Verify sim module firmware version
|
### Verify sim module firmware version
|
||||||
|
|
||||||
To make sure you got the latest sim module firmware.
|
To make sure you got the latest sim module firmware.
|
||||||
|
|
|
@ -80,17 +80,19 @@ Here are the supported values you can assign to `STANDALONE` in `Makefile.platfo
|
||||||
| STANDALONE | DESCRIPTION |
|
| STANDALONE | DESCRIPTION |
|
||||||
|-----------------|----------------------------------------|
|
|-----------------|----------------------------------------|
|
||||||
| | No standalone mode
|
| | No standalone mode
|
||||||
| LF_SKELETON | standalone mode skeleton - Iceman
|
| LF_SKELETON | standalone mode skeleton - Iceman1001
|
||||||
| LF_EM4100EMUL | LF EM4100 simulator standalone mode - temskiy
|
| LF_EM4100EMUL | LF EM4100 simulator standalone mode - temskiy
|
||||||
| LF_EM4100RSWB | LF EM4100 read/write/clone/brute mode - Monster1024
|
| LF_EM4100RSWB | LF EM4100 read/write/clone/brute mode - Monster1024
|
||||||
| LF_EM4100RWC | LF EM4100 read/write/clone mode - temskiy
|
| LF_EM4100RWC | LF EM4100 read/write/clone mode - temskiy
|
||||||
| LF_HIDBRUTE | HID corporate 1000 bruteforce - Federico dotta & Maurizio Agazzini
|
| LF_HIDBRUTE | HID corporate 1000 bruteforce - Federico dotta & Maurizio Agazzini
|
||||||
| LF_ICEHID | LF HID collector to flashmem - Iceman
|
| LF_ICEHID | LF HID collector to flashmem - Iceman1001
|
||||||
| LF_PROXBRUTE | HID ProxII bruteforce - Brad Antoniewicz
|
| LF_PROXBRUTE | HID ProxII bruteforce - Brad Antoniewicz
|
||||||
| LF_SAMYRUN | HID26 read/clone/sim - Samy Kamkar
|
| LF_SAMYRUN | HID26 read/clone/sim - Samy Kamkar
|
||||||
| HF_14ASNIFF | 14a sniff storing to flashmem - Micolous
|
| HF_14ASNIFF | 14a sniff storing to flashmem - Micolous
|
||||||
|
| HF_AVEFUL | MIFARE Ultralight read/simulation - Ave Ozkal
|
||||||
| HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth storing in flashmem - Bogito
|
| HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth storing in flashmem - Bogito
|
||||||
| HF_COLIN | Mifare ultra fast sniff/sim/clone - Colin Brigato
|
| HF_COLIN | Mifare ultra fast sniff/sim/clone - Colin Brigato
|
||||||
|
| HF_ICECLASS | iCLASS 4-1 mode sim/read & dump/loclass/glitch & config to flashmem - Iceman1001
|
||||||
| HF_LEGIC | HF Legic Prime standalone - uhei
|
| HF_LEGIC | HF Legic Prime standalone - uhei
|
||||||
| HF_MATTYRUN | Mifare sniff/clone - Matías A. Ré Medina
|
| HF_MATTYRUN | Mifare sniff/clone - Matías A. Ré Medina
|
||||||
| HF_MSDSAL (def)| EMV Read and emulation - Salvador Mendoza
|
| HF_MSDSAL (def)| EMV Read and emulation - Salvador Mendoza
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#ifndef __ANSI_H
|
#ifndef __ANSI_H
|
||||||
#define __ANSI_H
|
#define __ANSI_H
|
||||||
|
|
||||||
|
// Not ANSI but dirty trick to specify we don't want a \n
|
||||||
|
#define NOLF "\xff"
|
||||||
|
|
||||||
#define AEND "\x1b[0m"
|
#define AEND "\x1b[0m"
|
||||||
|
|
||||||
#define _BLUE_(s) "\x1b[34m" s AEND
|
#define _BLUE_(s) "\x1b[34m" s AEND
|
||||||
|
|
|
@ -122,6 +122,15 @@ typedef struct {
|
||||||
bool verbose;
|
bool verbose;
|
||||||
} PACKED sample_config;
|
} PACKED sample_config;
|
||||||
|
|
||||||
|
// A struct used to send hf14a-configs over USB
|
||||||
|
typedef struct {
|
||||||
|
int8_t forceanticol; // 0:auto 1:force executing anticol 2:force skipping anticol
|
||||||
|
int8_t forcebcc; // 0:expect valid BCC 1:force using computed BCC 2:force using card BCC
|
||||||
|
int8_t forcecl2; // 0:auto 1:force executing CL2 2:force skipping CL2
|
||||||
|
int8_t forcecl3; // 0:auto 1:force executing CL3 2:force skipping CL3
|
||||||
|
int8_t forcerats; // 0:auto 1:force executing RATS 2:force skipping RATS
|
||||||
|
} PACKED hf14a_config;
|
||||||
|
|
||||||
// Tracelog Header struct
|
// Tracelog Header struct
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t timestamp;
|
uint32_t timestamp;
|
||||||
|
@ -569,6 +578,11 @@ typedef struct {
|
||||||
#define CMD_HF_FELICALITE_DUMP 0x03AA
|
#define CMD_HF_FELICALITE_DUMP 0x03AA
|
||||||
#define CMD_HF_FELICALITE_SIMULATE 0x03AB
|
#define CMD_HF_FELICALITE_SIMULATE 0x03AB
|
||||||
|
|
||||||
|
// For 14a config
|
||||||
|
#define CMD_HF_ISO14443A_PRINT_CONFIG 0x03B0
|
||||||
|
#define CMD_HF_ISO14443A_GET_CONFIG 0x03B1
|
||||||
|
#define CMD_HF_ISO14443A_SET_CONFIG 0x03B2
|
||||||
|
|
||||||
// For measurements of the antenna tuning
|
// For measurements of the antenna tuning
|
||||||
#define CMD_MEASURE_ANTENNA_TUNING 0x0400
|
#define CMD_MEASURE_ANTENNA_TUNING 0x0400
|
||||||
#define CMD_MEASURE_ANTENNA_TUNING_HF 0x0401
|
#define CMD_MEASURE_ANTENNA_TUNING_HF 0x0401
|
||||||
|
@ -604,6 +618,7 @@ typedef struct {
|
||||||
#define CMD_HF_MIFAREU_READCARD 0x0721
|
#define CMD_HF_MIFAREU_READCARD 0x0721
|
||||||
#define CMD_HF_MIFARE_WRITEBL 0x0622
|
#define CMD_HF_MIFARE_WRITEBL 0x0622
|
||||||
#define CMD_HF_MIFAREU_WRITEBL 0x0722
|
#define CMD_HF_MIFAREU_WRITEBL 0x0722
|
||||||
|
#define CMD_HF_MIFAREU_WRITEBL_COMPAT 0x0723
|
||||||
|
|
||||||
#define CMD_HF_MIFARE_CHKKEYS 0x0623
|
#define CMD_HF_MIFARE_CHKKEYS 0x0623
|
||||||
#define CMD_HF_MIFARE_SETMOD 0x0624
|
#define CMD_HF_MIFARE_SETMOD 0x0624
|
||||||
|
@ -648,6 +663,11 @@ typedef struct {
|
||||||
//For Atmel CryptoRF
|
//For Atmel CryptoRF
|
||||||
#define CMD_HF_CRYPTORF_SIM 0x0820
|
#define CMD_HF_CRYPTORF_SIM 0x0820
|
||||||
|
|
||||||
|
// Gen 3 magic cards
|
||||||
|
#define CMD_HF_MIFARE_GEN3UID 0x0850
|
||||||
|
#define CMD_HF_MIFARE_GEN3BLK 0x0851
|
||||||
|
#define CMD_HF_MIFARE_GEN3FREEZ 0x0852
|
||||||
|
|
||||||
#define CMD_UNKNOWN 0xFFFF
|
#define CMD_UNKNOWN 0xFFFF
|
||||||
|
|
||||||
//Mifare simulation flags
|
//Mifare simulation flags
|
||||||
|
@ -714,7 +734,7 @@ typedef struct {
|
||||||
#define PM3_ETIMEOUT -4
|
#define PM3_ETIMEOUT -4
|
||||||
// Operation aborted (by user) client/pm3: kbd/button pressed
|
// Operation aborted (by user) client/pm3: kbd/button pressed
|
||||||
#define PM3_EOPABORTED -5
|
#define PM3_EOPABORTED -5
|
||||||
// Not (yet) implemented client/pm3: TBD placeholder
|
// Not (yet) implemented client/pm3: TBD place holder
|
||||||
#define PM3_ENOTIMPL -6
|
#define PM3_ENOTIMPL -6
|
||||||
// Error while RF transmission client/pm3: fail between pm3 & card
|
// Error while RF transmission client/pm3: fail between pm3 & card
|
||||||
#define PM3_ERFTRANS -7
|
#define PM3_ERFTRANS -7
|
||||||
|
@ -732,7 +752,7 @@ typedef struct {
|
||||||
#define PM3_EFILE -13
|
#define PM3_EFILE -13
|
||||||
// Generic TTY error
|
// Generic TTY error
|
||||||
#define PM3_ENOTTY -14
|
#define PM3_ENOTTY -14
|
||||||
// Initialization error pm3: error related to trying to initalize the pm3 / fpga for different operations
|
// Initialization error pm3: error related to trying to initialize the pm3 / fpga for different operations
|
||||||
#define PM3_EINIT -15
|
#define PM3_EINIT -15
|
||||||
// Expected a different answer error client/pm3: error when expecting one answer and got another one
|
// Expected a different answer error client/pm3: error when expecting one answer and got another one
|
||||||
#define PM3_EWRONGANSWER -16
|
#define PM3_EWRONGANSWER -16
|
||||||
|
@ -745,6 +765,12 @@ typedef struct {
|
||||||
#define PM3_EAPDU_ENCODEFAIL -19
|
#define PM3_EAPDU_ENCODEFAIL -19
|
||||||
// APDU responded with a failure code
|
// APDU responded with a failure code
|
||||||
#define PM3_EAPDU_FAIL -20
|
#define PM3_EAPDU_FAIL -20
|
||||||
|
|
||||||
|
// execute pm3 cmd failed client/pm3: when one of our pm3 cmd tries and fails. opposite from PM3_SUCCESS
|
||||||
|
#define PM3_EFAILED -21
|
||||||
|
// partial success client/pm3: when tring to dump a tag and fails on some blocks. Partial dump.
|
||||||
|
#define PM3_EPARTIAL -22
|
||||||
|
|
||||||
// No data pm3: no data available, no host frame available (not really an error)
|
// No data pm3: no data available, no host frame available (not really an error)
|
||||||
#define PM3_ENODATA -98
|
#define PM3_ENODATA -98
|
||||||
// Quit program client: reserved, order to quit the program
|
// Quit program client: reserved, order to quit the program
|
||||||
|
|
|
@ -15,6 +15,9 @@ ISO14443A (usually NFC tags)
|
||||||
95 20 = Anticollision of cascade level2
|
95 20 = Anticollision of cascade level2
|
||||||
95 70 = Select of cascade level2
|
95 70 = Select of cascade level2
|
||||||
50 00 = Halt (usage: 5000+2bytes ISO14443A-CRC - no answer from card)
|
50 00 = Halt (usage: 5000+2bytes ISO14443A-CRC - no answer from card)
|
||||||
|
|
||||||
|
E0 = RATS
|
||||||
|
D0 = PPS
|
||||||
Mifare
|
Mifare
|
||||||
60 = Authenticate with KeyA
|
60 = Authenticate with KeyA
|
||||||
61 = Authenticate with KeyB
|
61 = Authenticate with KeyB
|
||||||
|
@ -148,6 +151,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
|
||||||
#define ISO14443A_CMD_WRITEBLOCK 0xA0
|
#define ISO14443A_CMD_WRITEBLOCK 0xA0
|
||||||
#define ISO14443A_CMD_HALT 0x50
|
#define ISO14443A_CMD_HALT 0x50
|
||||||
#define ISO14443A_CMD_RATS 0xE0
|
#define ISO14443A_CMD_RATS 0xE0
|
||||||
|
#define ISO14443A_CMD_PPS 0xD0
|
||||||
#define ISO14443A_CMD_NXP_DESELECT 0xC2
|
#define ISO14443A_CMD_NXP_DESELECT 0xC2
|
||||||
|
|
||||||
#define MIFARE_SELECT_CT 0x88
|
#define MIFARE_SELECT_CT 0x88
|
||||||
|
@ -519,6 +523,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
|
||||||
#define T5555_BITRATE_SHIFT 12 //(RF=2n+2) ie 64=2*0x1F+2 or n = (RF-2)/2
|
#define T5555_BITRATE_SHIFT 12 //(RF=2n+2) ie 64=2*0x1F+2 or n = (RF-2)/2
|
||||||
#define T5555_FAST_WRITE 0x00004000
|
#define T5555_FAST_WRITE 0x00004000
|
||||||
#define T5555_PAGE_SELECT 0x00008000
|
#define T5555_PAGE_SELECT 0x00008000
|
||||||
|
#define T5555_FIXED 0x60000000
|
||||||
|
|
||||||
#define T55XX_WRITE_TIMEOUT 1500
|
#define T55XX_WRITE_TIMEOUT 1500
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue