Merge pull request #44 from RfidResearchGroup/master

Rebase
This commit is contained in:
mwalker33 2020-09-09 09:20:51 +10:00 committed by GitHub
commit 5f9aa3801b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
98 changed files with 3284 additions and 1341 deletions

View 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

View file

@ -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...
## [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)
- Fix missing t55x7 config block detection (@iceman1001)
- Fix missing define on proxspace (@mwalker33)

View file

@ -38,6 +38,9 @@ define KNOWN_STANDALONE_DEFINITIONS
| HF_14ASNIFF | 14a sniff to flashmem |
| (RDV4 only) | |
+----------------------------------------------------------+
| HF_AVEFUL | Mifare ultralight read/simulation |
| | - Ave Ozkal |
+----------------------------------------------------------+
| HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth |
| (RDV4 only) | storing in flashmem - Bogito |
+----------------------------------------------------------+
@ -62,7 +65,7 @@ define KNOWN_STANDALONE_DEFINITIONS
endef
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_FLASH := LF_ICEHID HF_14ASNIFF HF_BOG HF_COLIN HF_ICECLASS
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),)

View file

@ -37,6 +37,10 @@ endif
ifneq (,$(findstring WITH_STANDALONE_HF_14ASNIFF,$(APP_CFLAGS)))
SRC_STANDALONE = hf_14asniff.c
endif
# WITH_STANDALONE_HF_AVEFUL
ifneq (,$(findstring WITH_STANDALONE_HF_AVEFUL,$(APP_CFLAGS)))
SRC_STANDALONE = hf_aveful.c
endif
# WITH_STANDALONE_LF_ICEHID
ifneq (,$(findstring WITH_STANDALONE_LF_ICEHID,$(APP_CFLAGS)))
SRC_STANDALONE = lf_icehid.c

View 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();
}

View file

@ -7,6 +7,15 @@
//-----------------------------------------------------------------------------
// 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 "proxmark3_arm.h"
#include "appmain.h"

View file

@ -22,7 +22,6 @@
#include "legic.h" // legic_card_select_t struct
#include "spiffs.h" // flashmem
/*
* To list all dump files from flash:
*
@ -106,6 +105,7 @@ void RunMod(void) {
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
Dbprintf("[=] >> HF Legic Prime Read/Simulate Started <<");
DbpString("[=] press and HOLD button to exit standalone mode");
for (;;) {
WDT_HIT();
@ -163,7 +163,7 @@ void RunMod(void) {
}
// The read data is migrated to a MIM1024 card
LegicRfSimulate(ct);
LegicRfSimulate(ct, false);
}
}

View file

@ -355,8 +355,11 @@ static void SendStatus(void) {
I2C_print_status();
#endif
#ifdef WITH_LF
printConfig(); // LF Sampling config
printLFConfig(); // LF Sampling config
printT55xxConfig(); // LF T55XX Config
#endif
#ifdef WITH_ISO14443a
printHf14aConfig(); // HF 14a config
#endif
printConnSpeed();
DbpString(_CYAN_("Various"));
@ -739,7 +742,7 @@ static void PacketReceived(PacketCommandNG *packet) {
break;
}
case CMD_LF_SAMPLING_PRINT_CONFIG: {
printConfig();
printLFConfig();
break;
}
case CMD_LF_SAMPLING_GET_CONFIG: {
@ -756,7 +759,7 @@ static void PacketReceived(PacketCommandNG *packet) {
}
case CMD_LF_ACQ_RAW_ADC: {
struct p {
uint8_t verbose;
bool verbose;
uint32_t samples;
} PACKED;
struct p *payload = (struct p *)packet->data.asBytes;
@ -1065,7 +1068,12 @@ static void PacketReceived(PacketCommandNG *packet) {
#ifdef WITH_LEGICRF
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;
}
case CMD_HF_LEGIC_WRITER: {
@ -1140,6 +1148,21 @@ static void PacketReceived(PacketCommandNG *packet) {
#endif
#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: {
SniffIso14443a(packet->data.asBytes[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);
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: {
MifareAcquireEncryptedNonces(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes);
break;
@ -1248,7 +1275,7 @@ static void PacketReceived(PacketCommandNG *packet) {
break;
}
case CMD_HF_MIFARE_CHKKEYS: {
MifareChkKeys(packet->data.asBytes);
MifareChkKeys(packet->data.asBytes, false);
break;
}
case CMD_HF_MIFARE_CHKKEYS_FAST: {
@ -1318,6 +1345,19 @@ static void PacketReceived(PacketCommandNG *packet) {
MifareCIdent();
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
// case CMD_HF_MIFARE_SNIFF: {
// SniffMifare(packet->oldarg[0]);
@ -1806,12 +1846,9 @@ static void PacketReceived(PacketCommandNG *packet) {
uint8_t filename[32];
uint8_t *pfilename = packet->data.asBytes;
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];
//uint8_t buff[size];
uint8_t *buff = BigBuf_malloc(size);
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 *pfilename = packet->data.asBytes;
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();
uint32_t size = size_in_spiffs((char *)filename);
if (changed) rdv40_spiffs_lazy_unmount();
@ -1849,7 +1886,7 @@ static void PacketReceived(PacketCommandNG *packet) {
uint8_t filename[32];
uint8_t *pfilename = packet->data.asBytes;
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);
LED_B_OFF();
break;
@ -1864,9 +1901,9 @@ static void PacketReceived(PacketCommandNG *packet) {
strncpy((char *)src, token, sizeof(src) - 1);
token = strtok(NULL, ",");
strncpy((char *)dest, token, sizeof(dest) - 1);
if (DBGLEVEL > 1) {
Dbprintf("> Filename received as source for spiffs RENAME : %s", src);
Dbprintf("> Filename received as destination for spiffs RENAME : %s", dest);
if (DBGLEVEL >= DBG_DEBUG) {
Dbprintf("Filename received as source for spiffs RENAME : %s", src);
Dbprintf("Filename received as destination for spiffs RENAME : %s", dest);
}
rdv40_spiffs_rename((char *) src, (char *)dest, RDV40_SPIFFS_SAFETY_SAFE);
LED_B_OFF();
@ -1882,9 +1919,9 @@ static void PacketReceived(PacketCommandNG *packet) {
strncpy((char *)src, token, sizeof(src) - 1);
token = strtok(NULL, ",");
strncpy((char *)dest, token, sizeof(dest) - 1);
if (DBGLEVEL > 1) {
Dbprintf("> Filename received as source for spiffs COPY : %s", src);
Dbprintf("> Filename received as destination for spiffs COPY : %s", dest);
if (DBGLEVEL >= DBG_DEBUG) {
Dbprintf("Filename received as source for spiffs COPY : %s", src);
Dbprintf("Filename received as destination for spiffs COPY : %s", dest);
}
rdv40_spiffs_copy((char *) src, (char *)dest, RDV40_SPIFFS_SAFETY_SAFE);
LED_B_OFF();
@ -1896,14 +1933,12 @@ static void PacketReceived(PacketCommandNG *packet) {
uint32_t append = packet->oldarg[0];
uint32_t size = packet->oldarg[1];
uint8_t *data = packet->data.asBytes;
//rdv40_spiffs_lazy_mount();
uint8_t *pfilename = packet->data.asBytes;
memcpy(filename, pfilename, 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) {
rdv40_spiffs_write((char *) filename, (uint8_t *)data, size, RDV40_SPIFFS_SAFETY_SAFE);
} else {

View file

@ -90,6 +90,7 @@ static em4x50_tag_t tag = {
#define EM4X50_COMMAND_WRITE_PASSWORD 0x11
#define EM4X50_COMMAND_SELECTIVE_READ 0x0A
#define EM4X50_COMMAND_TIMEOUT 5000
#define FPGA_TIMER_0 0
int gHigh = 0;
@ -99,6 +100,8 @@ int gLow = 0;
static void init_tag(void) {
// iceman: memset(tag.sectors, 0x00, sizeof));
// initialize global tag structure
for (int i = 0; i < 34; i++)
for (int j = 0; j < 7; j++)
@ -185,10 +188,9 @@ static void em4x50_setup_read(void) {
// 50ms for the resonant antenna to settle.
SpinDelay(50);
// Now set up the SSC to get the ADC samples that are now streaming at us.
FpgaSetupSsc(FPGA_MAJOR_MODE_LF_READER);
// start a 1.5ticks is 1us
StartTicks();
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_125);
@ -255,10 +257,9 @@ static bool get_signalproperties(void) {
signal_found = true;
break;
}
}
if (!signal_found)
if (signal_found == false)
return false;
// 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) {
// Dbprintf( _CYAN_("4x50 get_pulse_length A") );
int32_t timeout = (T0 * 3 * EM4X50_T_TAG_FULL_PERIOD);
// iterates pulse length (low -> high -> low)
uint8_t sample = 0;
volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
while (sample > gLow && (timeout--)) {
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
}
while (sample > gLow)
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
if (timeout == 0)
return 0;
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;
}
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;
}
if (timeout == 0)
return 0;
return (uint32_t)AT91C_BASE_TC1->TC_CV;
}
static bool check_pulse_length(uint32_t pl, int length) {
// check if pulse length <pl> corresponds to given length <length>
if ((pl >= T0 * (length - EM4X50_TAG_TOLERANCE)) &
(pl <= T0 * (length + EM4X50_TAG_TOLERANCE)))
return true;
else
return false;
return ((pl >= T0 * (length - EM4X50_TAG_TOLERANCE)) & (pl <= T0 * (length + EM4X50_TAG_TOLERANCE)));
}
static void em4x50_send_bit(int bit) {
@ -428,13 +440,9 @@ static bool find_single_listen_window(void) {
// listen window found
return true;
}
} else {
}
cnt_pulses++;
}
}
return false;
@ -494,7 +502,6 @@ static bool find_double_listen_window(bool bcommand) {
return true;
}
}
} else {
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
// 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) {
@ -516,9 +521,7 @@ static bool request_receive_mode(void) {
// To issue a command we have to find a listen window first.
// Because identification and sychronization at the same time is not
// possible when using pulse lengths a double listen window is used.
bool bcommand = true;
return find_double_listen_window(bcommand);
}

View file

@ -329,7 +329,7 @@ void EPA_PACE_Collect_Nonce(PacketCommandNG *c) {
struct p {
uint32_t m;
} 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);
// check if the command succeeded

View file

@ -122,6 +122,51 @@ static uint32_t LastProxToAirDuration;
#define SEC_Y 0x00
#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) {
g_trigger = enable;
}
@ -1832,8 +1877,8 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) {
for (;;) {
WDT_HIT();
if (check == 1000) {
if (BUTTON_PRESS() || data_available())
if (check == 2000) {
if (BUTTON_PRESS())
return 1;
check = 0;
}
@ -1959,7 +2004,6 @@ int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen) {
b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR);
(void)b;
}
if (BUTTON_PRESS()) break;
}
// 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_par[MAX_PARITY_SIZE] = {0};
uint8_t sak = 0x04; // cascade uid
uint8_t sak; // cascade uid
bool do_cascade = 1;
int cascade_level = 0;
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);
}
if (hf14aconfig.forceanticol == 0) {
// 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
// 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.
for (; sak & 0x04; cascade_level++) {
for (; do_cascade; cascade_level++) {
// SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97)
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 uid_resp[4] = {0};
uint8_t uid_resp[5] = {0}; // UID + original BCC
sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2;
if (anticollision) {
// SELECT_ALL
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
memset(uid_resp, 0, 4);
memset(uid_resp, 0, 5);
uint16_t uid_resp_bits = 0;
uint16_t collision_answer_offset = 0;
// 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_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
for (uint16_t i = 0; i <= uid_resp_bits / 8; 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
memcpy(uid_resp, resp, 4);
memcpy(uid_resp, resp, 5); // UID + original BCC
}
} else {
@ -2426,18 +2477,51 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
// 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)
memcpy(sel_uid + 2, uid_resp, 4); // the UID received during anticollision, or the provided UID
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
ReaderTransmit(sel_uid, sizeof(sel_uid), NULL);
// 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];
// 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:
// http://www.nxp.com/documents/application_note/AN10927.pdf
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;
}
// PICC compilant with iso14443a-4 ---> (SAK & 0x20 != 0)
if (hf14aconfig.forcerats == 0) {
// 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
if (!no_rats) {

View file

@ -96,6 +96,9 @@ typedef struct {
# define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len))
#endif
void printHf14aConfig(void);
void setHf14aConfig(hf14a_config *hc);
hf14a_config *getHf14aConfig(void);
void iso14a_set_timeout(uint32_t timeout);
uint32_t iso14a_get_timeout(void);

View file

@ -44,7 +44,7 @@
# define FWT_TIMEOUT_14B 35312
#endif
// 330/848kHz = 1558us / 4 == 400us,
// 330/848kHz = 1558us / 4 == 400us,
#define ISO14443B_READER_TIMEOUT 1700 //330
// 1024/3.39MHz = 302.1us between end of tag response and next reader cmd
@ -761,7 +761,7 @@ 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)))
#define AMPLITUDE(ci,cq) (MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2))
switch(Demod.state) {
switch (Demod.state) {
case DEMOD_UNSYNCD: {
if (AMPLITUDE(ci, cq) > SUBCARRIER_DETECT_THRESHOLD) { // subcarrier detected
@ -1434,7 +1434,7 @@ void ReadSTMemoryIso14443b(uint16_t numofblocks) {
iso14443b_setup();
uint8_t *mem = BigBuf_malloc((numofblocks + 1) * 4 );
uint8_t *mem = BigBuf_malloc((numofblocks + 1) * 4);
iso14b_card_select_t card;
uint8_t res = iso14443b_select_srx_card(&card);
@ -1450,7 +1450,7 @@ void ReadSTMemoryIso14443b(uint16_t numofblocks) {
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;
break;
}
@ -1706,14 +1706,14 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) {
if ((param & ISO14B_SELECT_STD) == ISO14B_SELECT_STD) {
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,
if (status != 0) goto out;
}
if ((param & ISO14B_SELECT_SR) == ISO14B_SELECT_SR) {
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,
if (status > 0) goto out;
}

View file

@ -1715,7 +1715,6 @@ void SimTagIso15693(uint8_t *uid) {
uint32_t reader_eof_time = 0;
int cmd_len = GetIso15693CommandFromReader(cmd, sizeof(cmd), &reader_eof_time);
if (cmd_len < 0) {
Dbprintf("button pressed, exiting");
button_pressed = true;
exit_loop = true;
break;

View file

@ -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)
//-----------------------------------------------------------------------------
static uint8_t rx_byte_from_fpga(void) {
static uint16_t rx_frame_from_fpga(void) {
for (;;) {
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)) {
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 kernel was initialy designed to receive BSPK/2-PSK. Hance, it reports an
// I/Q pair every 18.9us (8 bits i and 8 bits q).
// The FPGA running xcorrelation samples the subcarrier at ~13.56 MHz. The mode
// was initialy designed to receive BSPK/2-PSK. Hance, it reports an I/Q pair
// every 4.7us (8 bits i and 8 bits q).
//
// 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:
// am = MAX(ABS(i),ABS(q)) + 1/2*MIN(ABS(i),ABSq))
//
// Note: The SSC receiver is never synchronized the calculation may be performed
// on a i/q pair from two subsequent correlations, but does not matter.
// Note: inlining this function would fail with -Os
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
// The bit time is 99.1us (21 I/Q pairs). The receiver skips the first 5 samples
// and averages the next (most stable) 8 samples. The final 8 samples are dropped
// also.
//
// An aproximated power measurement is available every 18.9us. The bit time
// is 100us. The code samples 5 times and uses the last (most stable) sample.
// The demodulated should be alligned to the bit period by the caller. This is
// done in rx_bit and rx_ack.
//
// 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.
//
// Note: inlining this function would fail with -Os
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) {
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) {
// insert pause
LOW(GPIO_SSC_DOUT);
HIGH(GPIO_SSC_DOUT);
last_frame_end += RWD_TIME_PAUSE;
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;
while (GET_TICKS < last_frame_end) { };
}
//-----------------------------------------------------------------------------
// Frame Handling
// Frame Handling (Reader)
//
// The LEGIC RF protocol from card to reader does not include explicit frame
// 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
LOW(GPIO_SSC_DOUT);
HIGH(GPIO_SSC_DOUT);
last_frame_end += RWD_TIME_PAUSE;
while (GET_TICKS < last_frame_end) { };
HIGH(GPIO_SSC_DOUT);
LOW(GPIO_SSC_DOUT);
// log
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->addrsize = 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
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
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
AT91C_BASE_PIOA->PIO_OER = 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.
legic_mem = BigBuf_get_EM_addr();
@ -406,11 +411,11 @@ legic_card_select_t *getLegicCardInfo(void) {
void LegicRfInfo(void) {
// configure ARM and FPGA
init_reader(false);
init_reader();
// establish shared secret and detect card type
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);
goto OUT;
}
@ -446,11 +451,11 @@ int LegicRfReaderEx(uint16_t offset, uint16_t len, uint8_t iv) {
int res = PM3_SUCCESS;
// configure ARM and FPGA
init_reader(false);
init_reader();
// establish shared secret and detect card type
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;
goto OUT;
}
@ -481,11 +486,11 @@ OUT:
void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) {
// configure ARM and FPGA
init_reader(false);
init_reader();
// establish shared secret and detect card type
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);
goto OUT;
}
@ -518,7 +523,7 @@ OUT:
void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data) {
// configure ARM and FPGA
init_reader(false);
init_reader();
// uid is not writeable
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
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);
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
while (len-- > 0 && !BUTTON_PRESS()) {
if (!write_byte(len + offset, data[len], card.addrsize)) {
while (len-- > 0 && BUTTON_PRESS() == false) {
if (write_byte(len + offset, data[len], card.addrsize) == false) {
Dbprintf("operation failed | %02X | %02X | %02X", len + offset, len, data[len]);
reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT;

View file

@ -15,7 +15,7 @@
#include "crc.h" /* legic crc-4 */
#include "legic_prng.h" /* legic PRNG impl */
#include "legic.h" /* legic_card_select_t struct */
#include "cmd.h"
#include "proxmark3_arm.h"
#include "BigBuf.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->addrsize = 0;
p_card->cardsize = 0;
return 2;
return PM3_ESOFT;
}
return 0;
return PM3_SUCCESS;
}
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
//-----------------------------------------------------------------------------
void LegicRfSimulate(uint8_t cardtype) {
void LegicRfSimulate(uint8_t tagtype, bool send_reply) {
// configure ARM and FPGA
init_tag();
int res = PM3_SUCCESS;
// verify command line input
if (init_card(cardtype, &card) != 0) {
DbpString("[!] Unknown tagtype.");
if (init_card(tagtype, &card) != PM3_SUCCESS) {
DbpString("Unknown tagtype to simulate");
res = PM3_ESOFT;
goto OUT;
}
uint16_t counter = 0;
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();
if (counter >= 2000) {
if (data_available()) {
res = PM3_EOPABORTED;
break;
}
counter = 0;
}
counter++;
// 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;
}
@ -481,13 +495,25 @@ void LegicRfSimulate(uint8_t cardtype) {
}
// conection is established, process commands until one fails
while (!connected_phase(&card)) {
while (connected_phase(&card) == false) {
WDT_HIT();
}
}
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();
StopTicks();
if (send_reply)
reply_ng(CMD_HF_LEGIC_SIMULATE, res, NULL, 0);
BigBuf_free_keep_EM();
}

View file

@ -1,7 +1,8 @@
//-----------------------------------------------------------------------------
// (c) 2009 Henryk Plötz <henryk@ploetzli.ch>
// 2018 AntiCat
//
// 2019 Piwi
// 2020 Iceman
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
@ -14,6 +15,6 @@
#include "common.h"
void LegicRfSimulate(uint8_t cardtype);
void LegicRfSimulate(uint8_t tagtype, bool send_reply);
#endif /* __LEGICRFSIM_H */

View file

@ -2041,7 +2041,7 @@ void T55xxReadBlock(uint8_t page, bool pwd_mode, bool brute_mem, uint8_t block,
// Acquisition
// Now do the acquisition
DoPartialAcquisition(0, false, samples, 0);
DoPartialAcquisition(0, false, samples, 1000);
// Turn the field off
if (brute_mem == false) {
@ -2165,7 +2165,7 @@ OUT:
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
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();
}
@ -2492,36 +2492,37 @@ static void SendForward(uint8_t fwd_bit_count) {
}
static void EM4xLogin(uint32_t pwd) {
uint8_t len;
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);
SendForward(len);
//WaitUS(20); // no wait for login command.
// should receive
// 0000 1010 ok.
// 0000 1010 ok
// 0000 0001 fail
}
void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) {
LED_A_ON();
uint8_t len;
StartTicks();
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);
StartTicks();
/* should we read answer from Logincommand?
*
* should receive
* 0000 1010 ok.
* 0000 1010 ok
* 0000 0001 fail
**/
if (usepwd) EM4xLogin(pwd);
forward_ptr = forwardLink_data;
len = Prepare_Cmd(FWD_CMD_READ);
uint8_t len = Prepare_Cmd(FWD_CMD_READ);
len += Prepare_Addr(addr);
SendForward(len);
@ -2530,19 +2531,23 @@ void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) {
DoPartialAcquisition(20, false, 6000, 1000);
StopTicks();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
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) {
LED_A_ON();
uint8_t len;
//clear buffer now so it does not interfere with timing later
BigBuf_Clear_ext(false);
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 receive
@ -2552,20 +2557,21 @@ void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd) {
if (usepwd) EM4xLogin(pwd);
forward_ptr = forwardLink_data;
len = Prepare_Cmd(FWD_CMD_WRITE);
uint8_t len = Prepare_Cmd(FWD_CMD_WRITE);
len += Prepare_Addr(addr);
len += Prepare_Data(data & 0xFFFF, data >> 16);
SendForward(len);
//Wait 20ms for write to complete?
// Wait 20ms for write to complete?
WaitMS(7);
DoPartialAcquisition(20, false, 6000, 1000);
StopTicks();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
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();
LFSetupFPGAForADC(LF_DIVISOR_125, true);
LFSetupFPGAForADC(LF_FREQ2DIV(132), true); //132
//clear buffer now so it does not interfere with timing later
BigBuf_free();
BigBuf_Clear_ext(false);
//send COTAG start pulse
// send COTAG start pulse
// http://www.proxmark.org/forum/viewtopic.php?id=4455
/*
ON(740) OFF(2035)
ON(3330) OFF(2035)
ON(740) OFF(2035)
ON(1000)
/*
ON(2000)
*/
ON(800) OFF(2200)
ON(3600) OFF(2200)
ON(800) OFF(2200)
ON(3400)
*/
ON(2000) // ON(3400)
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_FREQ2DIV(66)); // 66kHz
switch (rawsignal) {
case 0: {
doCotagAcquisition();
@ -2658,7 +2666,6 @@ void Cotag(uint32_t arg0) {
// Turn the field off
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
/*

View file

@ -36,7 +36,7 @@ static BitstreamOut data = {0, 0, 0};
// internal struct to keep track of samples gathered
static sampling_t samples = {0, 0, 0, 0};
void printConfig(void) {
void printLFConfig(void) {
uint32_t d = config.divisor;
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));
@ -97,7 +97,7 @@ void setSamplingConfig(sample_config *sc) {
config.samples_to_skip = sc->samples_to_skip;
if (sc->verbose)
printConfig();
printLFConfig();
}
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);
if (DBGLEVEL >= DBG_DEBUG) {
Dbprintf("lf sampling - after init");
printSamples();
}
bool trigger_hit = false;
uint32_t cancel_counter = 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.
// interruptible only when logging not yet triggered
if ((checked >= 4000) && (trigger_threshold > 0)) {
if ((checked >= 4000) && trigger_hit == false) {
if (data_available()) {
checked = -1;
break;
@ -298,10 +298,11 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
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();
// threshold either high or low values 128 = center 0. if trigger = 178
if (trigger_hit == false) {
if ((trigger_threshold > 0) && (sample < (trigger_threshold + 128)) && (sample > (128 - trigger_threshold))) {
if (cancel_after > 0) {
cancel_counter++;
@ -310,8 +311,9 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in
}
continue;
}
}
trigger_threshold = 0;
trigger_hit = true;
if (samples_to_skip > 0) {
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) {
if (verbose) {
if (checked == -1) {
Dbprintf("lf sampling aborted");
} else if (cancel_counter == cancel_after) {
Dbprintf("lf sampling cancelled after %u", cancel_counter);
}
if (verbose) {
Dbprintf("Done, saved " _YELLOW_("%d")" out of " _YELLOW_("%d")" seen samples at " _YELLOW_("%d")" bits/sample", samples.total_saved, samples.counter, bits_per_sample);
}
// Ensure that DC offset removal and noise check is performed for any device-side processing
removeSignalOffset(data.buffer, samples.total_saved);
computeSignalProperties(data.buffer, samples.total_saved);
return data.numbits;
}
/**
@ -356,20 +359,28 @@ uint32_t DoAcquisition_config(bool verbose, uint32_t sample_size) {
, config.trigger_threshold
, verbose
, sample_size
, 0
, 0 // cancel_after
, config.samples_to_skip);
}
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) {
if (verbose)
printConfig();
printLFConfig();
LFSetupFPGAForADC(config.divisor, reader_field);
uint32_t ret = DoAcquisition_config(verbose, sample_size);
StopTicks();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
return ret;
}
@ -495,7 +506,7 @@ void doCotagAcquisition(void) {
bool firsthigh = false, firstlow = false;
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())
break;
@ -527,7 +538,7 @@ void doCotagAcquisition(void) {
firstlow = true;
}
if (++i < bufsize) {
++i;
if (sample > COTAG_ONE_THRESHOLD) {
dest[i] = 255;
} else if (sample < COTAG_ZERO_THRESHOLD) {
@ -537,7 +548,6 @@ void doCotagAcquisition(void) {
}
}
}
}
// Ensure that DC offset removal and noise check is performed for any device-side processing
removeSignalOffset(dest, i);

View file

@ -99,7 +99,7 @@ void setSamplingConfig(sample_config *sc);
sample_config *getSamplingConfig(void);
void printConfig(void);
void printLFConfig(void);
void printSamples(void);
#endif // __LFSAMPLING_H

View file

@ -34,6 +34,7 @@
#include "ticks.h"
#include "usb_cdc.h" // usb_poll_validate_length
#include "spiffs.h" // spiffs
#include "appmain.h" // print_stack_usage
#ifndef HARDNESTED_AUTHENTICATION_TIMEOUT
# 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;
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);
LEDsoff();
BigBuf_free();
@ -443,47 +444,6 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
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.
// Arg1 : 0 = use no authentication.
// 1 = use 0x1A authentication.
@ -553,6 +513,75 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
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) {
uint8_t pwd[16] = {0x00};
@ -905,7 +934,7 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8
set_tracing(true);
// statistics on nonce distance
int16_t isOK = 0;
int16_t isOK = PM3_SUCCESS;
#define NESTED_MAX_TRIES 12
if (calibrate) { // calibrate: for first call only. Otherwise reuse previous calibration
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
if (BUTTON_PRESS() || data_available()) {
isOK = -2;
isOK = PM3_EOPABORTED;
break;
}
@ -976,7 +1005,7 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8
} else {
unsuccessful_tries++;
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
if (BUTTON_PRESS() || data_available()) {
isOK = -2;
isOK = PM3_EOPABORTED;
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.ks_b, &target_ks[1], 4);
LED_B_ON();
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);
LEDsoff();
set_tracing(false);
@ -1108,13 +1132,10 @@ void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo,
uint64_t ui64Key = 0;
ui64Key = bytes_to_num(key, 6);
// variables
uint16_t len;
uint8_t uid[10] = {0x00};
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 receivedAnswer[10] = {0x00};
@ -1132,7 +1153,6 @@ void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo,
set_tracing(true);
int16_t isOK = 0;
LED_C_ON();
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;
};
// First authenticatoin. Normal auth.
// First authentication. Normal auth.
if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, NULL)) {
if (DBGLEVEL >= DBG_INFO) Dbprintf("Nested: Auth1 error");
retry--;
@ -1167,9 +1187,8 @@ void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo,
};
nt2 = bytes_to_num(receivedAnswer, 4);
uint32_t nt_tmp = prng_successor(nt1, 160);
target_ks = nt2 ^ nt_tmp;
target_nt = nt_tmp;
target_nt = prng_successor(nt1, 160);
target_ks = nt2 ^ target_nt;
isOK = 1;
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;
}
void MifareChkKeys(uint8_t *datain) {
void MifareChkKeys(uint8_t *datain, uint8_t reserved_mem) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
@ -1715,7 +1734,12 @@ void MifareChkKeys(uint8_t *datain) {
bool clearTrace = datain[2];
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;
datain += 5;
@ -1793,6 +1817,8 @@ void MifareChkKeys(uint8_t *datain) {
void MifareChkKeys_file(uint8_t *fn) {
#ifdef WITH_FLASH
BigBuf_free();
SpinOff(0);
int changed = rdv40_spiffs_lazy_mount();
@ -1807,7 +1833,7 @@ void MifareChkKeys_file(uint8_t *fn) {
SpinOff(0);
MifareChkKeys(mem);
MifareChkKeys(mem, true);
BigBuf_free();
#endif
@ -1966,10 +1992,16 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) {
for (uint8_t blockNo = 0; blockNo < NumBlocksPerSector(sectorNo); blockNo++) {
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);
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) {
emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1);
} 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;
}
uint32_t old_timeout = iso14a_get_timeout();
// 2000 ms timeout
// 13560000 / 1000 / (8 * 16) * timeout
iso14a_set_timeout(21190);
ReaderTransmit(wipeC, sizeof(wipeC), NULL);
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
if (DBGLEVEL >= DBG_ERROR) Dbprintf("wipeC error");
errormsg = MAGIC_WIPE;
break;
}
iso14a_set_timeout(old_timeout);
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) {
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:
@ -2315,6 +2374,154 @@ void OnErrorMagic(uint8_t reason) {
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) {
uint8_t mod = datain[0];

View file

@ -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 MifareReadSector(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 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 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_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 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 MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint64_t key);

View file

@ -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) {
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];
memcpy(rATQA, &block0[8], sizeof(rATQA));
} else {
Dbprintf("[-] ERROR: Invalid dump. UID/SAK/ATQA not found");
Dbprintf("ERROR: " _RED_("Invalid dump. UID/SAK/ATQA not found"));
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
rATQA[0] = (rATQA[0] & 0x3f) | 0x80; // triple size uid
} else {
Dbprintf("[-] ERROR: UID size not defined");
Dbprintf("ERROR: " _RED_("UID size not defined"));
return false;
}
if (flags & FLAG_FORCED_ATQA) {
@ -529,12 +528,22 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1
LED_D_ON();
ResetSspClk();
int counter = 0;
bool finished = false;
bool button_pushed = BUTTON_PRESS();
while (!button_pushed && !finished) {
while (!button_pushed && !finished && !data_available()) {
WDT_HIT();
if (counter == 2000) {
if (data_available()) {
break;
}
counter = 0;
} else {
counter++;
}
// find reader field
if (cardSTATE == MFEMUL_NOFIELD) {

View file

@ -203,14 +203,14 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
iso14a_set_timeout(save_timeout);
if (!len) {
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Authentication failed. Card timeout.");
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Authentication failed. Card timeout");
return 2;
}
ntpp = prng_successor(nt, 32) ^ crypto1_word(pcs, 0, 0);
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 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);
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;
}
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;
}
memcpy(bt, receivedAnswer + 16, 2);
AddCrc14A(receivedAnswer, 16);
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;
}
@ -446,37 +446,37 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
return 0;
}
/* // command not needed, but left for future testing
int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData) {
uint16_t len;
uint8_t par[3] = {0}; // enough for 18 parity bits
uint8_t d_block[18] = {0x00};
uint8_t receivedAnswer[MAX_FRAME_SIZE];
uint8_t receivedAnswerPar[MAX_PARITY_SIZE];
// variables
uint16_t len = 0;
uint8_t d_block[18];
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);
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK
if (DBGLEVEL >= DBG_ERROR)
Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]);
Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0], len);
return 1;
}
memcpy(d_block, blockData, 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);
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK
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 0;
}
*/
int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData) {
uint16_t len = 0;
@ -613,7 +613,7 @@ void emlClearMem(void) {
memset(emCARD, 0, CARD_MEMORY_SIZE);
// 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);
// uid

View file

@ -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_ultra_auth(uint8_t *keybytes);
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_halt(void);

View file

@ -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) {
uint8_t erased = 0;
if (!FlashInit()) {
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;
block = addr / RDV40_LLERASE_BLOCKSIZE;
if (block) {
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;
Flash_CheckBusy(BUSY_TIMEOUT);
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);
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;
}
}
if (DBGLEVEL > 1) {
if (DBGLEVEL >= DBG_DEBUG) {
switch (filetype) {
case 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)
// TODO : integrate in read_function
int rdv40_spiffs_read_as_symlink(char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level) {
RDV40_SPIFFS_SAFE_FUNCTION(
char linkdest[SPIFFS_OBJ_NAME_LEN];
char linkfilename[SPIFFS_OBJ_NAME_LEN];
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);
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);
)

View file

@ -58,8 +58,6 @@ typedef uint8_t u8_t;
#define SPIFFS_API_DBGF(str) SPIFFS_API_DBG(str,NULL)
#endif
// Defines spiffs debug print formatters
// some general signed number
#ifndef _SPIPRIi

View file

@ -63,7 +63,7 @@
#endif
#ifndef REV64
#define REV64(x) (REV32(x) + (REV32((x) >> 32) << 32))
#define REV64(x) (REV32(x) + ((uint64_t)(REV32((x) >> 32) << 32)))
#endif
#ifndef BIT32

View 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

View file

@ -7,7 +7,8 @@ set_property(TARGET pm3rrg_rdv4_hardnested_nosimd PROPERTY POSITION_INDEPENDENT_
target_include_directories(pm3rrg_rdv4_hardnested_nosimd PRIVATE
../../common
../../include)
../../include
../src)
## CPU-specific code
## 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
../../common
../../include)
../../include
../src)
## x86 / SSE2
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
../../common
../../include)
../../include
../src)
## x86 / AVX
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
../../common
../../include)
../../include
../src)
## x86 / AVX2
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
../../common
../../include)
../../include
../src)
## x86 / AVX512
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
../../common
../../include)
../../include
../src)
set(SIMD_TARGETS
$<TARGET_OBJECTS:pm3rrg_rdv4_hardnested_mmx>

View file

@ -59,7 +59,7 @@ THE SOFTWARE.
#include <string.h>
#include "crapto1/crapto1.h"
#include "parity.h"
//#include "util.h"
#include "ui.h" // PrintAndLogEx
//#include "common.h"
// 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_t **restrict bitsliced_even_states = (bitslice_t **)malloc(((p->len[EVEN_STATE] - 1) / MAX_BITSLICES + 1) * sizeof(bitslice_t *));
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);
}
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) {
printf("Out of memory error in brute_force. Aborting...");
PrintAndLogEx(WARNING, "Out of memory error in brute_force. Aborting...");
exit(4);
}
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));
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);
}
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
if (known_target_key != -1 && e == test_state[EVEN_STATE]) {
bucket_contains_test_key[bitsliced_blocks] = true;
// printf("bucket %d contains test key even state\n", bitsliced_blocks);
// printf("in slice %d\n", slice_idx);
// PrintAndLogEx(INFO, "bucket %d contains test key even state", bitsliced_blocks);
// PrintAndLogEx(INFO, "in slice %d", slice_idx);
}
#endif
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
// if (known_target_key != -1 && bucket_contains_test_key[block_idx] && *p_odd == test_state[ODD_STATE]) {
// printf("Now testing known target key.\n");
// printf("block_idx = %d/%d\n", block_idx, bitsliced_blocks);
// PrintAndLogEx(INFO, "Now testing known target key.");
// PrintAndLogEx(INFO, "block_idx = %d/%d", block_idx, bitsliced_blocks);
// }
#endif
// add the even state bits
@ -444,8 +444,8 @@ uint64_t CRACK_STATES_BITSLICED(uint32_t cuid, uint8_t *best_first_bytes, statel
#endif
#ifdef DEBUG_KEY_ELIMINATION
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");
printf("block_idx = %d/%d, nonce = %d/%d\n", block_idx, bitsliced_blocks, tests, nonces_to_bruteforce);
PrintAndLogEx(INFO, "Known target key eliminated in brute_force.");
PrintAndLogEx(INFO, "block_idx = %d/%d, nonce = %d/%d", block_idx, bitsliced_blocks, tests, nonces_to_bruteforce);
}
#endif
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
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");
printf("block_idx = %d/%d\n", block_idx, bitsliced_blocks);
PrintAndLogEx(INFO, "Known target key eliminated in brute_force verification.");
PrintAndLogEx(INFO, "block_idx = %d/%d", block_idx, bitsliced_blocks);
}
#endif
}
#ifdef DEBUG_KEY_ELIMINATION
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");
printf("block_idx = %d/%d\n", block_idx, bitsliced_blocks);
PrintAndLogEx(INFO, "Known target key eliminated in brute_force (results_bit == 0).");
PrintAndLogEx(INFO, "block_idx = %d/%d", block_idx, bitsliced_blocks);
}
#endif
results64 >>= 1;
@ -533,7 +533,7 @@ out:
#if defined (DEBUG_BRUTE_FORCE)
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
return key;

View file

@ -1115,3 +1115,21 @@ fe04ecfe5577
C1E51C63B8F5 # RATB key
1DB710648A65
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

View 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)

View file

@ -9,7 +9,7 @@ local floor = math.floor
copyright = ''
author = "Iceman"
version = 'v1.0.3'
version = 'v1.0.4'
desc =[[
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.
@ -106,36 +106,93 @@ local function GetConfigs( modulation )
local t = {}
t['PSK1'] = {
[1] = '00001040',
[2] = '00041040',
[3] = '00081040',
[4] = '000c1040',
[5] = '00101040',
[6] = '00141040',
[7] = '00181040',
[8] = '001c1040',
-- Rf2
[1] = '00001040', -- 8
[2] = '00041040', -- 16
[3] = '00081040', -- 32
[4] = '000c1040', -- 40
[5] = '00101040', -- 50
[6] = '00141040', -- 64
[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'] = {
[1] = '00002040',
[2] = '00042040',
[3] = '00082040',
[4] = '000c2040',
[5] = '00102040',
[6] = '00142040',
[7] = '00182040',
[8] = '001c2040',
-- Rf2
[1] = '00002040', -- 8
[2] = '00042040', -- 16
[3] = '00082040', -- 32
[4] = '000c2040', -- 40
[5] = '00102040', -- 50
[6] = '00142040', -- 64
[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'] = {
[1] = '00003040',
[2] = '00043040',
[3] = '00083040',
[4] = '000c3040',
[5] = '00103040',
[6] = '00143040',
[7] = '00183040',
[8] = '001c3040',
-- Rf2
[1] = '00003040', -- 8
[2] = '00043040', -- 16
[3] = '00083040', -- 32
[4] = '000c3040', -- 40
[5] = '00103040', -- 50
[6] = '00143040', -- 64
[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'] = {

View file

@ -12,7 +12,7 @@
#include <stdlib.h> // size_t
#include <string.h>
#include <ctype.h> // tolower
#include <stdio.h> // printf
//#include <stdio.h> // printf
#include "commonutil.h" // reflect...
#include "comms.h" // clearCommandBuffer
#include "cmdparser.h" // command_t
@ -914,16 +914,33 @@ static int CmdAnalyseDemodBuffer(const char *Cmd) {
if (c == '0')
DemodBuffer[i] = 0;
printf("%c", c);
PrintAndLogEx(NORMAL, "%c" NOLF, c);
}
printf("\n");
PrintAndLogEx(NORMAL, "");
DemodBufferLen = len;
free(data);
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[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"lcr", CmdAnalyseLCR, AlwaysAvailable, "Generate final byte for XOR LRC"},
@ -935,6 +952,7 @@ static command_t CommandTable[] = {
{"a", CmdAnalyseA, AlwaysAvailable, "num bits test"},
{"nuid", CmdAnalyseNuid, AlwaysAvailable, "create NUID from 7byte UID"},
{"demodbuff", CmdAnalyseDemodBuffer, AlwaysAvailable, "Load binary string to demodbuffer"},
{"freq", CmdAnalyseFreq, AlwaysAvailable, "Calc wave lengths"},
{NULL, NULL, NULL, NULL}
};

View file

@ -2104,11 +2104,10 @@ static int Cmdhex2bin(const char *Cmd) {
else
continue;
//Uses printf instead of PrintAndLog since the latter adds linebreaks to each printout
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;
}

View file

@ -84,7 +84,7 @@ static int usage_hf_tune(void) {
return PM3_SUCCESS;
}
#define PROMPT_CLEARLINE PrintAndLogEx(INPLACE, " ")
#define PROMPT_CLEARLINE PrintAndLogEx(INPLACE, " \r")
int CmdHFSearch(const char *Cmd) {
@ -166,7 +166,7 @@ int CmdHFSearch(const char *Cmd) {
}
}
/*
/*
PROMPT_CLEARLINE;
PrintAndLogEx(INPLACE, " Searching for FeliCa tag...");
if (IfPm3Felica()) {
@ -175,7 +175,7 @@ int CmdHFSearch(const char *Cmd) {
res = PM3_SUCCESS;
}
}
*/
*/
/*
PROMPT_CLEARLINE;
PrintAndLogEx(INPLACE, " Searching for CryptoRF tag...");
@ -190,10 +190,10 @@ int CmdHFSearch(const char *Cmd) {
PROMPT_CLEARLINE;
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;
}
printf("\n");
return res;
}

View file

@ -168,6 +168,24 @@ const char *getTagInfo(uint8_t uid) {
static uint16_t frameLength = 0;
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) {
// 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");
@ -234,6 +252,162 @@ static int CmdHF14AList(const char *Cmd) {
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) {
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"},
{"raw", CmdHF14ACmdRaw, IfPm3Iso14443a, "Send raw hex data to tag"},
{"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}
};

View file

@ -13,7 +13,7 @@
#define CMDHF14A_H__
#include "common.h"
#include "pm3_cmd.h" //hf14a_config
#include "mifare.h" // structs
// 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 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);
const char *getTagInfo(uint8_t uid);
int Hf14443_4aGetCardData(iso14a_card_select_t *card);

View file

@ -940,17 +940,16 @@ static int CmdHF14BDump(const char *Cmd) {
blocknum = 0xFF;
}
printf(".");
fflush(stdout);
PrintAndLogEx(NORMAL, "." NOLF);
}
}
PrintAndLogEx(NORMAL, "");
if (blocknum != 0xFF) {
PrintAndLogEx(NORMAL, "\n Dump failed");
PrintAndLogEx(NORMAL, "Dump failed");
goto out;
}
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "block# | data | ascii");
PrintAndLogEx(NORMAL, "---------+--------------+----------");

View file

@ -1024,7 +1024,7 @@ static int CmdHF15Sim(const char *Cmd) {
PacketResponseNG resp;
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);
return PM3_SUCCESS;
}
@ -1266,8 +1266,7 @@ static int CmdHF15Dump(const char *Cmd) {
retry = 0;
blocknum++;
printf(".");
fflush(stdout);
PrintAndLogEx(NORMAL, "." NOLF);
}
}
@ -1742,7 +1741,7 @@ static int CmdHF15Restore(const char *Cmd) {
}
free(data);
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;
}
@ -1783,7 +1782,7 @@ static int CmdHF15CSetUID(const char *Cmd) {
PacketResponseNG resp;
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) {
PrintAndLogEx(WARNING, "timeout while waiting for reply");
@ -1800,7 +1799,7 @@ static int CmdHF15CSetUID(const char *Cmd) {
uint8_t revuid[8] = {0};
uint8_t i = 0;
while (i < sizeof(revuid)) {
revuid[i] = carduid[7-i];
revuid[i] = carduid[7 - i];
i++;
}

View file

@ -71,7 +71,7 @@ static int CmdHFEPACollectPACENonces(const char *Cmd) {
PacketResponseNG resp;
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);

View file

@ -1630,27 +1630,30 @@ static int CmdHFFelicaDumpLite(const char *Cmd) {
uint8_t timeout = 0;
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
timeout++;
printf(".");
PrintAndLogEx(NORMAL, "." NOLF);
fflush(stdout);
if (kbd_enter_pressed()) {
PrintAndLogEx(WARNING, "aborted via keyboard!\n");
PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
DropField();
return PM3_EOPABORTED;
}
if (timeout > 100) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
if (timeout > 10) {
PrintAndLogEx(WARNING, "\ntimeout while waiting for reply.");
DropField();
return PM3_ETIMEOUT;
}
}
PrintAndLogEx(NORMAL, "");
if (resp.oldarg[0] == 0) {
PrintAndLogEx(WARNING, "\nButton pressed. Aborted.");
PrintAndLogEx(WARNING, "Button pressed, aborted");
return PM3_EOPABORTED;
}
uint32_t tracelen = resp.oldarg[1];
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;
}

View file

@ -97,6 +97,18 @@ static int usage_hf_iclass_esave(void) {
PrintAndLogEx(NORMAL, "");
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) {
PrintAndLogEx(NORMAL, "3DES decrypt data\n");
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;
}
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));
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 + 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);
iclass_prekey_t lookup;
memcpy(lookup.mac, tmac, 4);
// 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) {
memcpy(key, item->key, 8);
return true;
@ -962,11 +974,10 @@ static int CmdHFiClassReader_Replay(const char *Cmd) {
SendCommandNG(CMD_HF_ICLASS_REPLAY, (uint8_t *)&payload, sizeof(payload));
while (true) {
printf(".");
fflush(stdout);
PrintAndLogEx(NORMAL, "." NOLF);
if (kbd_enter_pressed()) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(WARNING, "aborted via keyboard!\n");
PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
DropField();
return PM3_EOPABORTED;
}
@ -975,6 +986,7 @@ static int CmdHFiClassReader_Replay(const char *Cmd) {
break;
}
PrintAndLogEx(NORMAL, "");
if (resp.status != PM3_SUCCESS) {
PrintAndLogEx(ERR, "failed to communicate with card");
return resp.status;
@ -1175,7 +1187,7 @@ static int CmdHFiClassESave(const char *Cmd) {
}
uint8_t *dump = calloc(bytes, sizeof(uint8_t));
if (!dump) {
if (dump == NULL) {
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
return PM3_EMALLOC;
}
@ -1189,7 +1201,7 @@ static int CmdHFiClassESave(const char *Cmd) {
// user supplied filename?
if (len < 1) {
fnameptr += sprintf(fnameptr, "hf-iclass-");
fnameptr += snprintf(fnameptr, sizeof(filename), "hf-iclass-");
FillFileNameByUID(fnameptr, dump, "-dump", 8);
}
@ -1202,6 +1214,88 @@ static int CmdHFiClassESave(const char *Cmd) {
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) {
bool errors = false;
@ -1408,7 +1502,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
uint64_t pin = bytes_to_num(decrypted + (8 * 9), 5);
char tmp[17] = {0};
sprintf(tmp, "%."PRIu64, BCD2DEC(pin));
snprintf(tmp, sizeof(tmp), "%."PRIu64, BCD2DEC(pin));
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));
while (true) {
printf(".");
fflush(stdout);
PrintAndLogEx(NORMAL, "." NOLF);
if (kbd_enter_pressed()) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(WARNING, "aborted via keyboard!\n");
PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
DropField();
return PM3_EOPABORTED;
}
@ -1769,6 +1862,7 @@ static int CmdHFiClassDump(const char *Cmd) {
break;
}
PrintAndLogEx(NORMAL, "");
if (resp.status != PM3_SUCCESS) {
PrintAndLogEx(ERR, "failed to communicate with card");
return resp.status;
@ -1828,11 +1922,9 @@ static int CmdHFiClassDump(const char *Cmd) {
SendCommandNG(CMD_HF_ICLASS_DUMP, (uint8_t *)&payload, sizeof(payload));
while (true) {
printf(".");
fflush(stdout);
PrintAndLogEx(NORMAL, "." NOLF);
if (kbd_enter_pressed()) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(WARNING, "aborted via keyboard!\n");
PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
DropField();
return PM3_EOPABORTED;
}
@ -1840,7 +1932,7 @@ static int CmdHFiClassDump(const char *Cmd) {
if (WaitForResponseTimeout(CMD_HF_ICLASS_DUMP, &resp, 2000))
break;
}
PrintAndLogEx(NORMAL, "");
if (resp.status != PM3_SUCCESS) {
PrintAndLogEx(ERR, "failed to communicate with card");
goto write_dump;
@ -2233,8 +2325,8 @@ static int CmdHFiClassRestore(const char *Cmd) {
for (i = 0; i <= endblock - startblock; i++) {
memcpy(p, data + (i * 12), 12);
char *s = calloc(70, sizeof(uint8_t));
sprintf(s, "| %s ", sprint_hex(p, 8));
sprintf(s + strlen(s), "| %s", sprint_hex(p + 8, 4));
snprintf(s, 70, "| %s ", sprint_hex(p, 8));
snprintf(s + strlen(s), 70 - strlen(s), "| %s", sprint_hex(p + 8, 4));
PrintAndLogEx(NORMAL, " %02X %s", i + startblock, s);
free(s);
}
@ -3088,11 +3180,9 @@ static int CmdHFiClassCheckKeys(const char *Cmd) {
bool looped = false;
while (!WaitForResponseTimeout(CMD_HF_ICLASS_CHKKEYS, &resp, 2000)) {
timeout++;
printf(".");
fflush(stdout);
PrintAndLogEx(NORMAL, "." NOLF);
if (timeout > 120) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(WARNING, "No response from Proxmark3. Aborting...");
PrintAndLogEx(WARNING, "\nNo response from Proxmark3. Aborting...");
goto out;
}
looped = true;
@ -3484,6 +3574,7 @@ static command_t CommandTable[] = {
{"sim", CmdHFiClassSim, IfPm3Iclass, "[options..] Simulate iCLASS tag"},
{"eload", CmdHFiClassELoad, IfPm3Iclass, "[f <fn> ] Load Picopass / iCLASS dump file into emulator memory"},
{"esave", CmdHFiClassESave, IfPm3Iclass, "[f <fn> ] Save emulator memory to file"},
{"eview", CmdHFiClassEView, IfPm3Iclass, "[options..] View emulator memory"},
{"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("utils") " ---------------------"},
{"calcnewkey", CmdHFiClassCalcNewKey, AlwaysAvailable, "[options..] Calc diversified keys (blocks 3 & 4) to write new keys"},

View file

@ -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);
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

View file

@ -145,7 +145,7 @@ static int usage_legic_eload(void) {
PrintAndLogEx(NORMAL, " f <filename> : filename w/o .bin to load");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf legic eload 2 myfile"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf legic eload 2 f myfile"));
return PM3_SUCCESS;
}
static int usage_legic_esave(void) {
@ -582,13 +582,39 @@ static int CmdLegicRdbl(const char *Cmd) {
}
static int CmdLegicSim(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_legic_sim();
uint64_t id = 1;
sscanf(Cmd, " %" SCNi64, &id);
struct {
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();
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;
}
@ -709,16 +735,17 @@ static int CmdLegicWrbl(const char *Cmd) {
char *answer = readline(confirm);
overwrite = (answer[0] == 'y' || answer[0] == 'Y');
#else
printf("%s", confirm);
PrintAndLogEx(NORMAL, "%s" NOLF, confirm);
char *answer = NULL;
size_t anslen = 0;
if (getline(&answer, &anslen, stdin) > 0) {
overwrite = (answer[0] == 'y' || answer[0] == 'Y');
}
PrintAndLogEx(NORMAL, "");
#endif
free(answer);
if (!overwrite) {
PrintAndLogEx(NORMAL, "command cancelled");
if (overwrite == false) {
PrintAndLogEx(WARNING, "command cancelled");
return PM3_EOPABORTED;
}
}
@ -731,18 +758,16 @@ static int CmdLegicWrbl(const char *Cmd) {
clearCommandBuffer();
SendCommandOLD(CMD_HF_LEGIC_WRITER, offset, len, IV, data, len);
uint8_t timeout = 0;
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
++timeout;
printf(".");
fflush(stdout);
PrintAndLogEx(NORMAL, "." NOLF);
if (timeout > 7) {
PrintAndLogEx(WARNING, "\ncommand execution time out");
return PM3_ETIMEOUT;
}
}
PrintAndLogEx(NORMAL, "\n");
PrintAndLogEx(NORMAL, "");
uint8_t isOK = resp.oldarg[0] & 0xFF;
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;
while (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {
++timeout;
printf(".");
fflush(stdout);
PrintAndLogEx(NORMAL, "." NOLF);
if (timeout > 14) {
PrintAndLogEx(WARNING, "\ncommand execution time out");
return PM3_ETIMEOUT;
@ -990,14 +1014,13 @@ static int CmdLegicDump(const char *Cmd) {
uint8_t timeout = 0;
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
++timeout;
printf(".");
fflush(stdout);
PrintAndLogEx(NORMAL, "." NOLF);
if (timeout > 7) {
PrintAndLogEx(WARNING, "\ncommand execution time out");
return PM3_ETIMEOUT;
}
}
PrintAndLogEx(NORMAL, "\n");
PrintAndLogEx(NORMAL, "");
uint8_t isOK = resp.oldarg[0] & 0xFF;
if (!isOK) {
@ -1025,7 +1048,7 @@ static int CmdLegicDump(const char *Cmd) {
// user supplied filename?
if (fileNameLen < 1) {
PrintAndLogEx(INFO, "Using UID as filename");
fptr += sprintf(fptr, "hf-legic-");
fptr += snprintf(fptr, sizeof(filename), "hf-legic-");
FillFileNameByUID(fptr, data, "-dump", 4);
}
@ -1134,15 +1157,14 @@ static int CmdLegicRestore(const char *Cmd) {
uint8_t timeout = 0;
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
++timeout;
printf(".");
fflush(stdout);
PrintAndLogEx(NORMAL, "." NOLF);
if (timeout > 7) {
PrintAndLogEx(WARNING, "\ncommand execution time out");
free(data);
return PM3_ETIMEOUT;
}
}
PrintAndLogEx(NORMAL, "\n");
PrintAndLogEx(NORMAL, "");
uint8_t isOK = resp.oldarg[0] & 0xFF;
if (!isOK) {
@ -1300,7 +1322,7 @@ static int CmdLegicESave(const char *Cmd) {
// user supplied filename?
if (fileNameLen < 1) {
PrintAndLogEx(INFO, "Using UID as filename");
fptr += sprintf(fptr, "hf-legic-");
fptr += snprintf(fptr, sizeof(filename), "hf-legic-");
FillFileNameByUID(fptr, data, "-dump", 4);
}
@ -1344,8 +1366,8 @@ static int CmdLegicWipe(const char *Cmd) {
PacketResponseNG resp;
for (size_t i = 7; i < card.cardsize; i += PM3_CMD_DATA_SIZE) {
printf(".");
fflush(stdout);
PrintAndLogEx(NORMAL, "." NOLF);
size_t len = MIN((card.cardsize - i), PM3_CMD_DATA_SIZE);
if (len == card.cardsize - i) {
// Disable fast mode on last packet
@ -1357,15 +1379,14 @@ static int CmdLegicWipe(const char *Cmd) {
uint8_t timeout = 0;
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
++timeout;
printf(".");
fflush(stdout);
PrintAndLogEx(NORMAL, "." NOLF);
if (timeout > 7) {
PrintAndLogEx(WARNING, "\ncommand execution time out");
free(data);
return PM3_ETIMEOUT;
}
}
PrintAndLogEx(NORMAL, "\n");
PrintAndLogEx(NORMAL, "");
uint8_t isOK = resp.oldarg[0] & 0xFF;
if (!isOK) {

View file

@ -215,6 +215,9 @@ int applyIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
case ISO14443A_CMD_RATS:
snprintf(exp, size, "RATS");
break;
case ISO14443A_CMD_PPS:
snprintf(exp, size, "PPS");
break;
case ISO14443A_CMD_OPTS:
snprintf(exp, size, "OPTIONAL TIMESLOT");
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 tmac[4];
if ( isResponse == false ) {
if (isResponse == false) {
uint8_t c = cmd[0] & 0x0F;
uint8_t parity = 0;
for (uint8_t i = 0; i < 7; i++) {
@ -412,11 +415,11 @@ void annotateIclass(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool
curr_state = PICO_NONE;
} else if (curr_state == PICO_AUTH_EPURSE) {
memcpy(epurse, cmd, 8);
} else if ( curr_state == PICO_AUTH_MACS) {
} else if (curr_state == PICO_AUTH_MACS) {
uint8_t key[8];
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;
}
@ -608,6 +611,10 @@ void annotateTopaz(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
// iso 7816-3
void annotateIso7816(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
if (cmdsize < 2)
return;
// S-block
if ((cmd[0] & 0xC0) && (cmdsize == 3)) {
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");
break;
default:
snprintf(exp, size, "?");
//snprintf(exp, size, "?");
break;
}
}

File diff suppressed because it is too large Load diff

View file

@ -347,9 +347,9 @@ static char *getCardSizeStr(uint8_t fsize) {
// is LSB set?
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
sprintf(retStr, "0x%02X (" _YELLOW_("%d bytes") ")", fsize, lsize);
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("%d bytes") ")", fsize, lsize);
return buf;
}
@ -359,14 +359,14 @@ static char *getProtocolStr(uint8_t id, bool hw) {
char *retStr = buf;
if (id == 0x04) {
sprintf(retStr, "0x%02X (" _YELLOW_("ISO 14443-3 MIFARE, 14443-4") ")", id);
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("ISO 14443-3 MIFARE, 14443-4") ")", id);
} else if (id == 0x05) {
if (hw)
sprintf(retStr, "0x%02X (" _YELLOW_("ISO 14443-2, 14443-3") ")", id);
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("ISO 14443-2, 14443-3") ")", id);
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 {
sprintf(retStr, "0x%02X (" _YELLOW_("Unknown") ")", id);
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("Unknown") ")", id);
}
return buf;
}
@ -377,17 +377,17 @@ static char *getVersionStr(uint8_t major, uint8_t minor) {
char *retStr = buf;
if (major == 0x00)
sprintf(retStr, "%x.%x (" _YELLOW_("DESFire MF3ICD40") ")", major, minor);
snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("DESFire MF3ICD40") ")", major, minor);
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)
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)
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)
sprintf(retStr, "%x.%x (" _YELLOW_("DESFire Light") ")", major, minor);
snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("DESFire Light") ")", major, minor);
else
sprintf(retStr, "%x.%x (" _YELLOW_("Unknown") ")", major, minor);
snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("Unknown") ")", major, minor);
return buf;
}
@ -3401,6 +3401,7 @@ static void DecodeComSet(uint8_t comset) {
}
static char *DecodeAccessValue(uint8_t value) {
char *car = (char *)calloc(255, sizeof(char));
if (car == NULL)
return NULL;
@ -3413,7 +3414,7 @@ static char *DecodeAccessValue(uint8_t value) {
strcat(car, "(Denied Access)");
break;
default:
sprintf(car, "(Access Key: %d)", value);
snprintf(car, 255, "(Access Key: %d)", value);
break;
}
return car;
@ -4364,7 +4365,7 @@ static int CmdHF14aDesChk(const char *Cmd) {
}
if (!verbose)
printf("Search keys:\n");
PrintAndLogEx(INFO, "Search keys:");
bool result = false;
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++) {
uint32_t curaid = (app_ids[x * 3] & 0xFF) + ((app_ids[(x * 3) + 1] & 0xFF) << 8) + ((app_ids[(x * 3) + 2] & 0xFF) << 16);
PrintAndLogEx(ERR, "Checking aid 0x%06X...", curaid);
res = AuthCheckDesfire(&app_ids[x * 3], deskeyList, deskeyListLen, aeskeyList, aeskeyListLen, k3kkeyList, k3kkeyListLen, foundKeys, &result);
if (res == PM3_EOPABORTED) {
break;
}
if (pattern2b && startPattern < 0x10000) {
if (!verbose)
printf("p");
if (verbose == false)
PrintAndLogEx(NORMAL, "p" NOLF);
aeskeyListLen = 0;
deskeyListLen = 0;
k3kkeyListLen = 0;
DesFill2bPattern(deskeyList, &deskeyListLen, aeskeyList, &aeskeyListLen, k3kkeyList, &k3kkeyListLen, &startPattern);
continue;
}
if (dict_filenamelen && endFilePosition) {
if (!verbose)
printf("d");
if (verbose == false)
PrintAndLogEx(NORMAL, "d" NOLF);
uint32_t keycnt = 0;
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;
}
}
if (!verbose)
printf("\n");
if (verbose == false)
PrintAndLogEx(NORMAL, "");
// save keys to json
if ((jsonnamelen > 0) && result) {

View file

@ -58,9 +58,9 @@ static char *getCardSizeStr(uint8_t fsize) {
// is LSB set?
if (fsize & 1)
sprintf(retStr, "0x%02X (" _YELLOW_("%d - %d bytes") ")", fsize, usize, lsize);
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("%d - %d bytes") ")", fsize, usize, lsize);
else
sprintf(retStr, "0x%02X (" _YELLOW_("%d bytes") ")", fsize, lsize);
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("%d bytes") ")", fsize, lsize);
return buf;
}
@ -70,14 +70,14 @@ static char *getProtocolStr(uint8_t id, bool hw) {
char *retStr = buf;
if (id == 0x04) {
sprintf(retStr, "0x%02X (" _YELLOW_("ISO 14443-3 MIFARE, 14443-4") ")", id);
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("ISO 14443-3 MIFARE, 14443-4") ")", id);
} else if (id == 0x05) {
if (hw)
sprintf(retStr, "0x%02X (" _YELLOW_("ISO 14443-2, 14443-3") ")", id);
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("ISO 14443-2, 14443-3") ")", id);
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 {
sprintf(retStr, "0x%02X (" _YELLOW_("Unknown") ")", id);
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("Unknown") ")", id);
}
return buf;
}
@ -88,20 +88,20 @@ static char *getVersionStr(uint8_t major, uint8_t minor) {
char *retStr = buf;
if (major == 0x00)
sprintf(retStr, "%x.%x (" _YELLOW_("DESFire MF3ICD40") ")", major, minor);
snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("DESFire MF3ICD40") ")", major, minor);
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)
sprintf(retStr, "%x.%x (" _YELLOW_("DESFire EV2") ")", major, minor);
// else if (major == 0x13 && minor == 0x00)
// sprintf(retStr, "%x.%x (" _YELLOW_("DESFire EV3") ")", major, minor);
snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("DESFire EV2") ")", major, minor);
else if (major == 0x33 && minor == 0x00)
snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("DESFire EV3") ")", major, minor);
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)
sprintf(retStr, "%x.%x (" _YELLOW_("Plus EV1") ")", major, minor);
snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("Plus EV1") ")", major, minor);
else
sprintf(retStr, "%x.%x (" _YELLOW_("Unknown") ")", major, minor);
snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("Unknown") ")", major, minor);
return buf;
}
@ -112,16 +112,16 @@ static char *getTypeStr(uint8_t type) {
switch (type) {
case 1:
sprintf(retStr, "0x%02X (" _YELLOW_("DESFire") ")", type);
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("DESFire") ")", type);
break;
case 2:
sprintf(retStr, "0x%02X (" _YELLOW_("Plus") ")", type);
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("Plus") ")", type);
break;
case 3:
sprintf(retStr, "0x%02X (" _YELLOW_("Ultralight") ")", type);
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("Ultralight") ")", type);
break;
case 4:
sprintf(retStr, "0x%02X (" _YELLOW_("NTAG") ")", type);
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("NTAG") ")", type);
break;
default:
break;
@ -144,8 +144,8 @@ static nxp_cardtype_t getCardType(uint8_t major, uint8_t minor) {
return DESFIRE_EV2;
// DESFire EV3
// if (major == 0x13 && minor == 0x00 )
// return DESFIRE_EV3;
if (major == 0x33 && minor == 0x00)
return DESFIRE_EV3;
// DESFire Light
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
for (int i = 0; i < keyListLen; i++) {
if (i % 10 == 0) {
if (!verbose)
printf(".");
if (verbose == false)
PrintAndLogEx(NORMAL, "." NOLF);
if (kbd_enter_pressed()) {
PrintAndLogEx(WARNING, "\nAborted via keyboard!\n");
DropField();
@ -988,9 +990,9 @@ static int MFPKeyCheck(uint8_t startSector, uint8_t endSector, uint8_t startKeyA
break;
if (verbose)
PrintAndLogEx(WARNING, "retried[%d]...", retry);
PrintAndLogEx(WARNING, "\nretried[%d]...", retry);
else
printf("R");
PrintAndLogEx(NORMAL, "R" NOLF);
DropField();
selectCard = true;
@ -998,14 +1000,15 @@ static int MFPKeyCheck(uint8_t startSector, uint8_t endSector, uint8_t startKeyA
}
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
if (res == 0) {
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
printf("+");
PrintAndLogEx(NORMAL, "+" NOLF);
foundKeys[keyAB][sector][0] = 0x01;
memcpy(&foundKeys[keyAB][sector][1], keyList[i], AES_KEY_LEN);
DropField();
@ -1017,9 +1020,10 @@ static int MFPKeyCheck(uint8_t startSector, uint8_t endSector, uint8_t startKeyA
// 5 - auth error (rnd not equal)
if (res != 5) {
if (verbose)
PrintAndLogEx(ERR, "Exchange error. Aborted.");
PrintAndLogEx(ERR, "\nExchange error. Aborted.");
else
printf("E");
PrintAndLogEx(NORMAL, "E" NOLF);
DropField();
return PM3_ECARDEXCHANGE;
}
@ -1201,23 +1205,25 @@ static int CmdHFMFPChk(const char *Cmd) {
PrintAndLogEx(INFO, "Loaded " _YELLOW_("%"PRIu32) " keys", keyListLen);
}
if (!verbose)
printf("Search keys:");
if (verbose == false)
PrintAndLogEx(NORMAL, "Search keys");
while (true) {
res = MFPKeyCheck(startSector, endSector, startKeyAB, endKeyAB, keyList, keyListLen, foundKeys, verbose);
if (res == PM3_EOPABORTED)
break;
if (pattern2b && startPattern < 0x10000) {
if (!verbose)
printf("p");
if (verbose == false)
PrintAndLogEx(NORMAL, "p" NOLF);
keyListLen = 0;
Fill2bPattern(keyList, &keyListLen, &startPattern);
continue;
}
if (dict_filenamelen && endFilePosition) {
if (!verbose)
printf("d");
if (verbose == false)
PrintAndLogEx(NORMAL, "d" NOLF);
uint32_t keycnt = 0;
res = loadFileDICTIONARYEx((char *)dict_filename, keyList, sizeof(keyList), NULL, 16, &keycnt, endFilePosition, &endFilePosition, false);
keyListLen = keycnt;
@ -1225,8 +1231,8 @@ static int CmdHFMFPChk(const char *Cmd) {
}
break;
}
if (!verbose)
printf("\n");
if (verbose == false)
PrintAndLogEx(NORMAL, "");
// print result
bool printedHeader = false;

View file

@ -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, "Options:");
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, " l : (optional) swap entered key's endianness");
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\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\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\x0E", 7) == 0) { tagtype = NTAG_212; 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 keylen = 0;
uint8_t blockdata[20] = {0x00};
uint8_t blockdata[16] = {0x00};
uint8_t data[16] = {0x00};
uint8_t datalen = 4;
uint8_t authenticationkey[16] = {0x00};
uint8_t *authKeyPtr = authenticationkey;
@ -1516,9 +1518,13 @@ static int CmdHF14AMfUWrBl(const char *Cmd) {
break;
case 'd':
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)) {
PrintAndLogEx(WARNING, "Block data must include 8 or 32 HEX symbols");
errors = true;
break;
} else {
datalen = 16;
}
}
cmdp += 2;
break;
@ -1558,9 +1564,8 @@ static int CmdHF14AMfUWrBl(const char *Cmd) {
PrintAndLogEx(NORMAL, "Block: %0d (0x%02X) [ %s]", blockNo, blockNo, sprint_hex(blockdata, 4));
//Send write Block
uint8_t cmddata[20];
memcpy(cmddata, blockdata, 4);
uint8_t datalen = 4;
uint8_t cmddata[32];
memcpy(cmddata, blockdata, datalen);
uint8_t keytype = 0;
if (hasAuthKey) {
keytype = 1;
@ -1573,7 +1578,11 @@ static int CmdHF14AMfUWrBl(const char *Cmd) {
}
clearCommandBuffer();
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;
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
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
// 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
uint8_t get_pack[] = {0, 0};
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();
SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, b, keytype, 0, data, sizeof(data));
wait4response(b);
printf(".");
fflush(stdout);
PrintAndLogEx(NORMAL, "." NOLF);
}
PrintAndLogEx(NORMAL, "\n");

View file

@ -696,7 +696,7 @@ void pm3_version(bool verbose, bool oneliner) {
// For "proxmark3 -v", simple printf, avoid logging
char temp[PM3_CMD_DATA_SIZE - 12]; // same limit as for ARM image
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;
}
@ -705,7 +705,6 @@ void pm3_version(bool verbose, bool oneliner) {
PacketResponseNG resp;
clearCommandBuffer();
SendCommandNG(CMD_VERSION, NULL, 0);
if (WaitForResponseTimeout(CMD_VERSION, &resp, 1000)) {

View file

@ -364,16 +364,15 @@ int CmdLFCommandRead(const char *Cmd) {
uint8_t i = 10;
// 20sec wait loop
while (!WaitForResponseTimeout(CMD_LF_MOD_THEN_ACQ_RAW_ADC, &resp, 2000) && i != 0) {
printf(".");
fflush(stdout);
PrintAndLogEx(NORMAL, "." NOLF);
i--;
}
printf("\n");
PrintAndLogEx(NORMAL, "");
if (resp.status == PM3_SUCCESS) {
if (i) {
PrintAndLogEx(SUCCESS, "downloading response signal data");
getSamples(0, true);
getSamples(0, false);
return PM3_SUCCESS;
} else {
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;
struct p {
uint8_t verbose;
bool verbose;
uint32_t samples;
} PACKED;
@ -606,21 +605,19 @@ int lf_read(bool verbose, uint32_t samples) {
clearCommandBuffer();
SendCommandNG(CMD_LF_ACQ_RAW_ADC, (uint8_t *)&payload, sizeof(payload));
PacketResponseNG resp;
if (g_lf_threshold_set) {
WaitForResponse(CMD_LF_ACQ_RAW_ADC, &resp);
} else {
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;
}
}
// resp.oldarg[0] is bits read not bytes read.
uint32_t bits = (resp.data.asDwords[0] / 8);
getSamples(bits, verbose);
// response is number of bits read
uint32_t size = (resp.data.asDwords[0] / 8);
getSamples(size, verbose);
return PM3_SUCCESS;
}
@ -736,15 +733,13 @@ int CmdLFSim(const char *Cmd) {
PrintAndLogEx(INFO, "Bigbuf is full.");
break;
}
printf(".");
fflush(stdout);
PrintAndLogEx(NORMAL, "." NOLF);
payload_up.flag = 0;
}
// Disable fast mode before last command
conn.block_after_ACK = false;
printf("\n");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "Simulating");
struct p {
@ -1194,7 +1189,7 @@ static bool CheckChipType(bool getDeviceData) {
//check for em4x05/em4x69 chips first
uint32_t word = 0;
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");
retval = true;
goto out;
@ -1215,6 +1210,7 @@ static bool CheckChipType(bool getDeviceData) {
goto out;
}
PrintAndLogEx(NORMAL, "Couldn't identify a chipset");
out:
save_restoreGB(GRAPH_RESTORE);
save_restoreDB(GRAPH_RESTORE);
@ -1242,6 +1238,7 @@ int CmdLFfind(const char *Cmd) {
return PM3_ESOFT;
}
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "NOTE: some demods output possible binary");
PrintAndLogEx(INFO, "if it finds something that looks like a tag");
PrintAndLogEx(INFO, "False Positives " _YELLOW_("ARE") " possible");
@ -1270,18 +1267,22 @@ int CmdLFfind(const char *Cmd) {
// The improved noise detection will find Cotag.
if (getSignalProperties()->isnoise) {
PrintAndLogEx(INPLACE, "Searching for MOTOROLA tag...");
if (readMotorolaUid()) {
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Motorola FlexPass ID") " found!");
return PM3_SUCCESS;
}
if (readCOTAGUid()) {
PrintAndLogEx(INPLACE, "Searching for COTAG tag...");
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("COTAG ID") " found!");
return PM3_SUCCESS;
}
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(FAILED, _RED_("No data found!"));
PrintAndLogEx(INFO, "Signal looks like noise. Maybe not an LF tag?");
PrintAndLogEx(NORMAL, "");
return PM3_ESOFT;
}
}
@ -1293,18 +1294,15 @@ int CmdLFfind(const char *Cmd) {
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 (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;}
@ -1312,7 +1310,7 @@ int CmdLFfind(const char *Cmd) {
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;}
// if (demodFermax() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Fermax ID") " found!"); goto out;}
PrintAndLogEx(FAILED, _RED_("No known 125/134 kHz tags found!"));

View file

@ -60,7 +60,7 @@ static int usage_lf_awid_sim(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, "");
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, " <facility-code> : 8|16bit value facility code");
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, "Examples:");
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};
if (tolower(param_getchar(Cmd, 3)) == 'q')
bool q5 = tolower(param_getchar(Cmd, 3)) == 'q';
if (q5)
//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);
@ -425,7 +426,7 @@ static int CmdAWIDClone(const char *Cmd) {
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));
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
@ -532,7 +533,7 @@ static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "this help"},
{"demod", CmdAWIDDemod, AlwaysAvailable, "demodulate an AWID FSK tag from the GraphBuffer"},
{"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"},
{"brute", CmdAWIDBrute, IfPm3Lf, "Bruteforce card number against reader"},
{"watch", CmdAWIDWatch, IfPm3Lf, "continuously watch for cards. Reader mode"},

View file

@ -92,19 +92,18 @@ static int CmdCOTAGRead(const char *Cmd) {
PacketResponseNG resp;
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;
while (!WaitForResponseTimeout(CMD_LF_COTAG_READ, &resp, 2000)) {
timeout--;
printf(".");
fflush(stdout);
PrintAndLogEx(NORMAL, "." NOLF);
if (timeout == 0) {
PrintAndLogEx(WARNING, "command execution time out");
return PM3_ETIMEOUT;
}
}
if (timeout != 3)
PrintAndLogEx(NORMAL, "");

View file

@ -64,13 +64,13 @@ static int usage_lf_em410x_watch(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, "Usage: lf em 410x_write [h] <id> <card> [clock]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h - this help");
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, "Examples:");
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;
}
if (card == 1) {
PrintAndLogEx(SUCCESS, "Writing %s tag with UID 0x%010" PRIx64 " (clock rate: %d)", _GREEN_("T55x7"), id, clock1);
PrintAndLogEx(SUCCESS, "Writing " _YELLOW_("%s") " tag with UID 0x%010" PRIx64 " (clock rate: %d)", (card == 1) ? "T55x7" : "Q5/T5555", id, clock1);
// NOTE: We really should pass the clock in as a separate argument, but to
// provide for backwards-compatibility for older firmware, and to avoid
// having to add another argument to CMD_LF_EM410X_WRITE, we just store
// 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 {
uint8_t card;
@ -695,7 +691,7 @@ static bool downloadSamplesEM(void) {
// 8 bit preamble + 32 bit word response (max clock (128) * 40bits = 5120 samples)
uint8_t got[6000];
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;
}
@ -859,6 +855,7 @@ static int demodEM4x05resp(uint32_t *word) {
}
//////////////// 4205 / 4305 commands
#include "util_posix.h" // msclock
static int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *word) {
struct {
@ -874,14 +871,14 @@ static int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t
clearCommandBuffer();
SendCommandNG(CMD_LF_EM4X_READWORD, (uint8_t *)&payload, sizeof(payload));
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_LF_EM4X_READWORD, &resp, 2500)) {
PrintAndLogEx(DEBUG, "timeout while waiting for reply.");
if (!WaitForResponseTimeout(CMD_LF_EM4X_READWORD, &resp, 10000)) {
PrintAndLogEx(WARNING, "(EM4x05ReadWord_ext) timeout while waiting for reply.");
return PM3_ETIMEOUT;
}
if (!downloadSamplesEM()) {
if (downloadSamplesEM() == false) {
return PM3_ESOFT;
}
return demodEM4x05resp(word);
}
@ -1386,7 +1383,7 @@ static command_t CommandTable[] = {
{"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_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") " -------------------"},
{"4x05_demod", CmdEM4x05Demod, AlwaysAvailable, "demodulate a EM4x05/EM4x69 tag from the GraphBuffer"},
{"4x05_dump", CmdEM4x05Dump, IfPm3Lf, "dump EM4x05/EM4x69 tag"},

View file

@ -516,7 +516,7 @@ int em4x50_read(em4x50_data_t *etd, em4x50_word_t *out, bool verbose) {
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
PrintAndLogEx(WARNING, "(em4x50) timeout while waiting for reply.");
return PM3_ETIMEOUT;
}

View file

@ -49,7 +49,7 @@
static int CmdHelp(const char *Cmd);
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, "Options:");
PrintAndLogEx(NORMAL, " h : This help");
@ -58,7 +58,7 @@ static int usage_lf_fdx_clone(void) {
PrintAndLogEx(NORMAL, " <extended> : Extended data");
//reserved/rfu
//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, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf fdx clone 999 112233"));
@ -292,7 +292,36 @@ static int CmdFdxDemod(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);
}
@ -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};
//Q5
if (tolower(param_getchar(Cmd, 2)) == 'q')
blocks[0] = T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(32) | 4 << T5555_MAXBLOCK_SHIFT;
bool q5 = tolower(param_getchar(Cmd, 2)) == 'q';
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
blocks[1] = bytebits_to_byte(bits, 32);
@ -332,7 +362,7 @@ static int CmdFdxClone(const char *Cmd) {
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));
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
@ -392,8 +422,8 @@ static int CmdFdxSim(const char *Cmd) {
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "this help"},
{"demod", CmdFdxDemod, AlwaysAvailable, "demodulate a FDX-B ISO11784/85 tag from the GraphBuffer"},
{"read", CmdFdxRead, IfPm3Lf, "attempt to read and extract tag data"},
{"clone", CmdFdxClone, IfPm3Lf, "clone animal ID tag to T55x7 (or to q5/T5555)"},
{"read", CmdFdxRead, IfPm3Lf, "attempt to read at 134kHz and extract tag data"},
{"clone", CmdFdxClone, IfPm3Lf, "clone animal ID tag to T55x7 or Q5/T5555"},
{"sim", CmdFdxSim, IfPm3Lf, "simulate Animal ID tag"},
{NULL, NULL, NULL, NULL}
};

View file

@ -103,9 +103,9 @@ static int CmdGallagherDemod(const char *Cmd) {
for (int i = 0, pos = 0; i < ARRAYLEN(arr); i++) {
pos = (i * 8) + i;
arr[i] = bytebits_to_byte(DemodBuffer + pos, 8);
printf("%d -", pos);
PrintAndLogEx(NORMAL, "%d -" NOLF, pos);
}
printf("\n");
PrintAndLogEx(NORMAL, "");
// crc
uint8_t crc = bytebits_to_byte(DemodBuffer + 72, 8);

View file

@ -27,15 +27,16 @@
static int CmdHelp(const char *Cmd);
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, "Currently work only on 26bit");
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, " <format> : format length 26|32|36|40");
PrintAndLogEx(NORMAL, " <Facility-Code> : 8-bit value facility code");
PrintAndLogEx(NORMAL, " <Card Number> : 16-bit value card number");
PrintAndLogEx(NORMAL, " <Q5> : Specify writing to Q5/T5555 tag");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf gprox clone 26 123 11223"));
@ -175,8 +176,9 @@ static int CmdGuardClone(const char *Cmd) {
}
// Q5
if (param_getchar(Cmd, 3) == 'Q' || param_getchar(Cmd, 3) == 'q')
blocks[0] = T5555_MODULATION_FSK2 | T5555_SET_BITRATE(50) | 3 << T5555_MAXBLOCK_SHIFT;
bool q5 = tolower(param_getchar(Cmd, 3)) == 'q';
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[2] = bytebits_to_byte(bs + 32, 32);
@ -184,7 +186,7 @@ static int CmdGuardClone(const char *Cmd) {
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));
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
@ -241,7 +243,7 @@ static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "this help"},
{"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"},
{"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"},
{NULL, NULL, NULL, NULL}
};

View file

@ -557,7 +557,7 @@ static int CmdIndalaClone(const char *Cmd) {
CLIParserContext *ctx;
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"
_YELLOW_("\tlf indala clone --heden 888\n")
_YELLOW_("\tlf indala clone --fc 123 --cn 1337\n")
@ -569,7 +569,7 @@ static int CmdIndalaClone(const char *Cmd) {
arg_lit0("lL", "long", "optional - long UID 224 bits"),
arg_int0("cC", "heden", "<decimal>", "Cardnumber for Heden 2L format"),
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("", "cn", "<decimal>", "Cardnumber (26 bit format)"),
arg_param_end
@ -604,7 +604,7 @@ static int CmdIndalaClone(const char *Cmd) {
PrintAndLogEx(INFO, "RawID %s", sprint_hex(data, datalen));
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
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));
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
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"},
{"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"},
{"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"},
{NULL, NULL, NULL, NULL}
};

View file

@ -59,16 +59,16 @@ static int usage_lf_io_sim(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, "");
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, " h : This help");
PrintAndLogEx(NORMAL, " <version> : 8bit version (" _YELLOW_("decimal") ")");
PrintAndLogEx(NORMAL, " <facility-code> : 8bit value facility code (" _YELLOW_("hex") ")");
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, "Examples:");
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};
if (tolower(param_getchar(Cmd, 3) == 'q'))
blocks[0] = T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(64) | 2 << T5555_MAXBLOCK_SHIFT;
bool q5 = tolower(param_getchar(Cmd, 3) == 'q');
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[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));
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
@ -293,7 +294,7 @@ static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "this help"},
{"demod", CmdIOProxDemod, AlwaysAvailable, "demodulate an IOProx tag from the GraphBuffer"},
{"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"},
{"watch", CmdIOProxWatch, IfPm3Lf, "continuously watch for cards. Reader mode"},
{NULL, NULL, NULL, NULL}

View file

@ -30,12 +30,12 @@
static int CmdHelp(const char *Cmd);
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, "Options:");
PrintAndLogEx(NORMAL, " h : This help");
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, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf jablotron clone 112233"));
@ -153,8 +153,9 @@ static int CmdJablotronClone(const char *Cmd) {
fullcode = param_get64ex(Cmd, 0, 0, 16);
//Q5
if (tolower(param_getchar(Cmd, 1)) == 'q')
blocks[0] = T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(64) | 2 << T5555_MAXBLOCK_SHIFT;
bool q5 = tolower(param_getchar(Cmd, 1)) == 'q';
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.
if ((fullcode & 0x7FFFFFFFFF) != fullcode) {
@ -178,7 +179,7 @@ static int CmdJablotronClone(const char *Cmd) {
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));
return clone_t55xx_tag(blocks, ARRAYLEN(blocks));
@ -234,7 +235,7 @@ static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdJablotronDemod, AlwaysAvailable, "Demodulate an Jablotron tag from the GraphBuffer"},
{"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"},
{NULL, NULL, NULL, NULL}
};

View file

@ -28,21 +28,21 @@
static int CmdHelp(const char *Cmd);
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 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, " h : This help");
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
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, " <c> <cn> : Card Number");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
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, "");
return PM3_SUCCESS;
@ -212,8 +212,6 @@ int demodKeri(void) {
return PM3_SUCCESS;
}
static int CmdKeriRead(const char *Cmd) {
lf_read(false, 10000);
return CmdKeriDemod(Cmd);
@ -221,6 +219,7 @@ static int CmdKeriRead(const char *Cmd) {
static int CmdKeriClone(const char *Cmd) {
bool q5 = false;
uint8_t cmdidx = 0;
char keritype = 'i'; // default to internalid
uint32_t fc = 0;
@ -263,11 +262,8 @@ static int CmdKeriClone(const char *Cmd) {
cmdidx += 2;
break;
case 'q': // q5
blocks[0] =
T5555_MODULATION_PSK1 |
T5555_SET_BITRATE(128) |
T5555_PSK_RF_2 |
2 << T5555_MAXBLOCK_SHIFT;
blocks[0] = T5555_FIXED | T5555_MODULATION_PSK1 | T5555_SET_BITRATE(32) | T5555_PSK_RF_2 | 2 << T5555_MAXBLOCK_SHIFT;
q5 = true;
cmdidx++;
break;
default:
@ -290,7 +286,7 @@ static int CmdKeriClone(const char *Cmd) {
// Prepare and write to card
// 3 LSB is ONE
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[2] = data & 0xFFFFFFFF;
@ -348,7 +344,7 @@ static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdKeriDemod, AlwaysAvailable, "Demodulate an KERI tag from the GraphBuffer"},
{"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"},
{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};
// sanity check.
if (*size < sizeof(preamble) + 100) return -1;
if (*size < sizeof(preamble)) return -1;
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
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;
*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;
}

View file

@ -173,7 +173,7 @@ static int CmdMotorolaClone(const char *Cmd) {
CLIParserFree(ctx);
//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)
PrintAndLogEx(INFO, "Preparing to clone Motorola 64bit tag with RawID %s", sprint_hex(data, datalen));

View file

@ -9,18 +9,21 @@
#include "cmdlfnedap.h"
#define _GNU_SOURCE
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include "cmdparser.h" // command_t
#include "comms.h"
#include "crc16.h"
#include "cmdlft55xx.h" // verifywrite
#include "cmdlft55xx.h" // verify write
#include "ui.h"
#include "cmddata.h"
#include "cmdlf.h"
#include "lfdemod.h"
#include "protocols.h"
#define FIXED_71 0x71
#define FIXED_40 0x40
@ -47,16 +50,16 @@ static int usage_lf_nedap_gen(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, "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, " h : This help");
PrintAndLogEx(NORMAL, " s <subtype> : optional, default=5");
PrintAndLogEx(NORMAL, " c <code> : customerCode");
PrintAndLogEx(NORMAL, " i <id> : ID (max 99999)");
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, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf nedap clone s 1 c 123 i 12345"));
@ -399,6 +402,9 @@ static int CmdLfNedapGen(const char *Cmd) {
isLong = true;
cmdp++;
break;
case 'q':
cmdp++;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
@ -449,14 +455,8 @@ static int CmdLFNedapClone(const char *Cmd) {
return PM3_ESOFT;
}
//CmdPrintDemodBuff("x");
// What we had before in commented code:
//NEDAP - compat mode, ASK/DIphase, data rate 64, 4 data blocks
// 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) {
max = 3;
@ -465,12 +465,20 @@ static int CmdLFNedapClone(const char *Cmd) {
max = 5;
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++) {
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);
int res = clone_t55xx_tag(blocks, max);
@ -531,7 +539,7 @@ static command_t CommandTable[] = {
{"demod", CmdLFNedapDemod, AlwaysAvailable, "Demodulate Nedap tag from the GraphBuffer"},
{"generate", CmdLfNedapGen, AlwaysAvailable, "Generate Nedap bitstream in DemodBuffer"},
{"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"},
{NULL, NULL, NULL, NULL}
};

View file

@ -26,13 +26,13 @@
static int CmdHelp(const char *Cmd);
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, "Options:");
PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " <card id> : Noralsy card ID");
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, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf noralsy clone 112233"));
@ -150,8 +150,9 @@ static int CmdNoralsyClone(const char *Cmd) {
year = param_get32ex(Cmd, 1, 2000, 10);
//Q5
if (tolower(param_getchar(Cmd, 2) == 'q'))
blocks[0] = T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(32) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT;
bool q5 = tolower(param_getchar(Cmd, 2) == 'q');
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));
if (getnoralsyBits(id, year, bits) != PM3_SUCCESS) {
@ -166,7 +167,7 @@ static int CmdNoralsyClone(const char *Cmd) {
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));
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
@ -222,7 +223,7 @@ static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdNoralsyDemod, AlwaysAvailable, "Demodulate an Noralsy tag from the GraphBuffer"},
{"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"},
{NULL, NULL, NULL, NULL}
};

View file

@ -27,13 +27,13 @@
static int CmdHelp(const char *Cmd);
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, "Options:");
PrintAndLogEx(NORMAL, " h : this help");
PrintAndLogEx(NORMAL, " d <Card-ID> : 9 digit presco card ID");
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, "Examples:");
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 (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) {
sitecode &= 0xFF;
@ -133,7 +133,7 @@ static int CmdPrescoClone(const char *Cmd) {
blocks[3] = 0x00000000;
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));
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
@ -179,7 +179,7 @@ static int CmdPrescoSim(const char *Cmd) {
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"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"},
{NULL, NULL, NULL, NULL}
};

View file

@ -31,7 +31,7 @@
static int CmdHelp(const char *Cmd);
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, "Currently only works on 26bit");
PrintAndLogEx(NORMAL, "");
@ -40,7 +40,7 @@ static int usage_lf_pyramid_clone(void) {
PrintAndLogEx(NORMAL, " h : this help");
PrintAndLogEx(NORMAL, " <Facility-Code> : 8-bit value facility code");
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, "Examples:");
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;
// Q5
if (param_getchar(Cmd, 2) == 'Q' || param_getchar(Cmd, 2) == 'q')
blocks[0] = T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(50) | 4 << T5555_MAXBLOCK_SHIFT;
bool q5 = tolower(param_getchar(Cmd, 2)) == 'q';
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[2] = bytebits_to_byte(bs + 32, 32);
@ -252,7 +253,7 @@ static int CmdPyramidClone(const char *Cmd) {
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));
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
@ -308,7 +309,7 @@ static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "this help"},
{"demod", CmdPyramidDemod, AlwaysAvailable, "demodulate a Pyramid FSK tag from the GraphBuffer"},
{"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"},
{NULL, NULL, NULL, NULL}
};

View file

@ -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, " i [0/1] - Set/reset data signal inversion");
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, ""); // layout is a little differnet, so seperate until a better fix
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, " h - this help");
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, "Examples:");
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;
}
static int usage_t55xx_deviceconfig(void) {
@ -829,7 +829,7 @@ static int CmdT55xxSetConfig(const char *Cmd) {
return printConfiguration(config);
}
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) {
@ -994,7 +994,7 @@ static int SanityOfflineCheck(bool useGraphBuffer) {
static void T55xx_Print_DownlinkMode(uint8_t downlink_mode) {
char msg[80];
sprintf(msg, "Downlink Mode used : ");
snprintf(msg, sizeof(msg), "Downlink Mode used : ");
switch (downlink_mode) {
case 1 :
@ -1587,7 +1587,7 @@ int special(const char *Cmd) {
}
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, " 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");
@ -1864,7 +1864,7 @@ static int CmdT55xxReadTrace(const char *Cmd) {
si += 9;
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;
}
@ -1955,7 +1955,7 @@ static int CmdT55xxReadTrace(const char *Cmd) {
}
void printT55x7Trace(t55x7_tracedata_t data, uint8_t repeat) {
PrintAndLogEx(NORMAL, "-- T55x7 Trace Information ----------------------------------");
PrintAndLogEx(NORMAL, "--- " _CYAN_("T55x7 Trace Information") " ----------------------------------");
PrintAndLogEx(NORMAL, "-------------------------------------------------------------");
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));
@ -2002,7 +2002,7 @@ void printT55x7Trace(t55x7_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, " ICR IC Revision : %d", data.icr);
PrintAndLogEx(NORMAL, " Lot : %c%d", data.lotidc, data.lotid);
@ -2327,7 +2327,7 @@ static int CmdT55xxDump(const char *Cmd) {
strcpy(preferredName, "lf-t55xx");
for (uint8_t i = 1; i <= 7; i++) {
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
break;
}
@ -2416,7 +2416,7 @@ static int CmdT55xxRestore(const char *Cmd) {
if (success == PM3_SUCCESS) { // Got data, so write to cards
if (datalen == T55x7_BLOCK_COUNT * 4) { // 12 blocks * 4 bytes per block
if (usepwd)
sprintf(pwdOpt, "p %08X", password);
snprintf(pwdOpt, sizeof(pwdOpt), "p %08X", password);
// Restore endien for writing to card
for (blockidx = 0; blockidx < 12; blockidx++)
@ -2433,18 +2433,20 @@ static int CmdT55xxRestore(const char *Cmd) {
// write out blocks 1-7 page 0
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)
PrintAndLogEx(WARNING, "Warning: error writing blk %d", blockidx);
}
// if password was set on the "blank" update as we may have just changed it
if (usepwd)
sprintf(pwdOpt, "p %08X", data[7]);
snprintf(pwdOpt, sizeof(pwdOpt), "p %08X", data[7]);
// write out blocks 1-3 page 1
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)
PrintAndLogEx(WARNING, "Warning: error writing blk %d", blockidx);
}
@ -2453,7 +2455,7 @@ static int CmdT55xxRestore(const char *Cmd) {
config.downlink_mode = downlink_mode;
// 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)
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);
break;
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;
default:
break;
@ -2916,7 +2918,7 @@ static int CmdT55xxWipe(const char *Cmd) {
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.
if (gotconf == false) {
@ -3039,18 +3041,18 @@ static int CmdT55xxChkPwds(const char *Cmd) {
while (!WaitForResponseTimeout(CMD_LF_T55XX_CHK_PWDS, &resp, 2000)) {
timeout++;
printf(".");
fflush(stdout);
PrintAndLogEx(NORMAL, "." NOLF);
if (timeout > 180) {
PrintAndLogEx(WARNING, "\nNo response from Proxmark3. Aborting...");
return PM3_ENODATA;
}
}
PrintAndLogEx(NORMAL, "");
struct p {
bool found;
uint32_t candidate;
} PACKED;
struct p* packet = (struct p*)resp.data.asBytes;
struct p *packet = (struct p *)resp.data.asBytes;
if (packet->found) {
PrintAndLogEx(SUCCESS, "\nFound a candidate [ " _YELLOW_("%08"PRIX32) " ]", packet->candidate);
@ -3178,8 +3180,7 @@ static int CmdT55xxBruteForce(const char *Cmd) {
while (found == 0) {
printf(".");
fflush(stdout);
PrintAndLogEx(NORMAL, "." NOLF);
if (IsCancelled()) {
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 (getSignalProperties()->isnoise == false) {
// } else {
if (tryDetectModulationEx(dl_mode, T55XX_PrintConfig, 0 ,password)) {
if (tryDetectModulationEx(dl_mode, T55XX_PrintConfig, 0, password)) {
return 1 + (dl_mode << 1);
}
// }

View file

@ -27,15 +27,15 @@
static int CmdHelp(const char *Cmd);
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, "Options:");
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, "Examples:");
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;
}
@ -114,7 +114,11 @@ static int CmdVikingClone(const char *Cmd) {
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();
@ -169,7 +173,7 @@ static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdVikingDemod, AlwaysAvailable, "Demodulate a Viking tag from the GraphBuffer"},
{"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"},
{NULL, NULL, NULL, NULL}
};

View file

@ -33,15 +33,16 @@
static int CmdHelp(const char *Cmd);
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, "Options:");
PrintAndLogEx(NORMAL, " h : This help");
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, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf visa2000 clone 112233"));
PrintAndLogEx(NORMAL, _YELLOW_(" lf visa2000 clone 112233 q5") " -- encode for Q5/T5555");
return PM3_SUCCESS;
}
@ -177,13 +178,14 @@ static int CmdVisa2kClone(const char *Cmd) {
id = param_get32ex(Cmd, 0, 0, 10);
//Q5
if (tolower(param_getchar(Cmd, 1)) == 'q')
blocks[0] = T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(64) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT;
bool q5 = tolower(param_getchar(Cmd, 1)) == 'q';
if (q5)
blocks[0] = T5555_FIXED | T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(64) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT;
blocks[2] = 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));
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
@ -233,7 +235,7 @@ static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdVisa2kDemod, AlwaysAvailable, "demodulate an VISA2000 tag from the GraphBuffer"},
{"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"},
{NULL, NULL, NULL, NULL}
};

View file

@ -885,7 +885,7 @@ static void smart_brute_prim(void) {
static int smart_brute_sfi(bool decodeTLV) {
uint8_t *buf = calloc(PM3_CMD_DATA_SIZE, sizeof(uint8_t));
if (!buf)
if (buf == NULL)
return 1;
int len;
@ -895,8 +895,7 @@ static int smart_brute_sfi(bool decodeTLV) {
for (uint8_t sfi = 1; sfi <= 31; sfi++) {
printf(".");
fflush(stdout);
PrintAndLogEx(NORMAL, "." NOLF);
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++) {
printf("+");
fflush(stdout);
PrintAndLogEx(NORMAL, "+" NOLF);
if (caid)
free(caid);
@ -1033,21 +1031,21 @@ static int CmdSmartBruteforceSFI(const char *Cmd) {
json_t *data, *jaid;
data = json_array_get(root, i);
if (!json_is_object(data)) {
PrintAndLogEx(ERR, "data %d is not an object\n", i + 1);
if (json_is_object(data) == false) {
PrintAndLogEx(ERR, "\ndata %d is not an object\n", i + 1);
json_decref(root);
return PM3_ESOFT;
}
jaid = json_object_get(data, "AID");
if (!json_is_string(jaid)) {
PrintAndLogEx(ERR, "AID data [%d] is not a string", i + 1);
if (json_is_string(jaid) == false) {
PrintAndLogEx(ERR, "\nAID data [%d] is not a string", i + 1);
json_decref(root);
return PM3_ESOFT;
}
const char *aid = json_string_value(jaid);
if (!aid)
if (aid == false)
continue;
size_t aidlen = strlen(aid);
@ -1069,7 +1067,7 @@ static int CmdSmartBruteforceSFI(const char *Cmd) {
json_t *jvendor, *jname;
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);
continue;
}
@ -1079,7 +1077,7 @@ static int CmdSmartBruteforceSFI(const char *Cmd) {
continue;
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);
continue;
}

View file

@ -245,6 +245,7 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
case ISO_14443A:
case MFDES:
case LTO:
case ISO_7816_4:
crcStatus = iso14443A_CRC_check(hdr->isResponse, frame, data_len);
break;
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);
break;
case PROTO_CRYPTORF:
case ISO_7816_4:
case PROTO_HITAG1:
case PROTO_HITAG2:
case PROTO_HITAGS:
@ -347,14 +347,14 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
uint8_t m = 7;
while (m > 0) {
bitime -= 128;
if ( duration > bitime) {
if (duration > bitime) {
break;
}
m--;
}
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 + 4] = ')';
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 + 4] = ')';
}
}
@ -413,6 +413,7 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
annotateTopaz(explanation, sizeof(explanation), frame, data_len);
break;
case ISO_7816_4:
annotateIso14443a(explanation, sizeof(explanation), frame, data_len);
annotateIso7816(explanation, sizeof(explanation), frame, data_len);
break;
case ISO_15693:

View file

@ -298,13 +298,13 @@ static void PacketResponseReceived(PacketResponseNG *packet) {
PrintAndLogEx(NORMAL, "[" _BLUE_("#") "] %s", s);
} else {
if (flag & FLAG_INPLACE)
printf("\r");
printf("%s", s);
if (flag & FLAG_NEWLINE)
printf("\r\n");
}
PrintAndLogEx(NORMAL, "\r" NOLF);
fflush(stdout);
PrintAndLogEx(NORMAL, "%s" NOLF, s);
if (flag & FLAG_NEWLINE)
PrintAndLogEx(NORMAL, "");
}
break;
}
case CMD_DEBUG_PRINT_INTEGERS: {

View file

@ -24,8 +24,8 @@
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/entropy.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.
int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length) {
uint8_t iiv[16] = {0};
@ -416,10 +416,10 @@ int ecdsa_nist_test(bool verbose) {
// NIST ecdsa test
if (verbose)
printf(" ECDSA NIST test: ");
PrintAndLogEx(INFO, " ECDSA NIST test: " NOLF);
// make signature
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)
goto exit;
@ -436,7 +436,7 @@ int ecdsa_nist_test(bool verbose) {
uint8_t sval_s[33] = {0};
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)) {
printf("R or S check error\n");
PrintAndLogEx(INFO, "R or S check error");
res = 100;
goto exit;
}
@ -449,14 +449,14 @@ int ecdsa_nist_test(bool verbose) {
// verify wrong signature
input[0] ^= 0xFF;
res = ecdsa_signature_verify_keystr(curveid, T_Q_X, T_Q_Y, input, length, signature, siglen, true);
if (!res) {
if (res == false) {
res = 1;
goto exit;
}
if (verbose) {
printf("passed\n");
printf(" ECDSA binary signature create/check test: ");
PrintAndLogEx(NORMAL, _GREEN_("passed"));
PrintAndLogEx(INFO, " ECDSA binary signature create/check test: " NOLF);
}
// random ecdsa test
@ -483,11 +483,11 @@ int ecdsa_nist_test(bool verbose) {
goto exit;
if (verbose)
printf("passed\n\n");
PrintAndLogEx(NORMAL, _GREEN_("passed\n"));
return 0;
exit:
if (verbose)
printf("failed\n\n");
PrintAndLogEx(NORMAL, _RED_("failed\n"));
return res;
}

View file

@ -71,7 +71,8 @@ static mbedtls_mpi_uint mpi_get_uint(const mbedtls_mpi *X) {
if (X->n == 1 && X->s > 0) {
return X->p[0];
}
printf("ZERRRRO!!!\n");
PrintAndLogEx(WARNING, "ZERRRRO!!!\n");
return 0;
}
@ -82,7 +83,7 @@ static void print_mpi(const char *msg, int radix, const mbedtls_mpi *X) {
size_t len = 0;
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) {

View file

@ -11,16 +11,15 @@
//
#include "cbortools.h"
#include <inttypes.h>
#include "emv/emvjson.h"
#include "util.h"
#include "ui.h" // PrintAndLogEx(
#include "fidocore.h"
static void indent(int nestingLevel) {
while (nestingLevel--)
printf(" ");
PrintAndLogEx(NORMAL, " " NOLF);
}
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) {
case CborMapType:
case CborArrayType: {
printf(type == CborArrayType ? "Array[" : "Map[");
PrintAndLogEx(NORMAL, "%s" NOLF, (type == CborArrayType) ? "Array[" : "Map[");
break;
}
case CborIntegerType: {
int64_t val;
cbor_value_get_int64(it, &val); // can't fail
printf("%lld", (long long)val);
PrintAndLogEx(NORMAL, "%lld" NOLF, (long long)val);
break;
}
@ -50,7 +49,8 @@ static CborError dumpelm(CborValue *it, bool *got_next, int nestingLevel) {
*got_next = true;
if (err)
return err; // parse error
printf("%s", sprint_hex(buf, n));
PrintAndLogEx(NORMAL, "%s" NOLF, sprint_hex(buf, n));
free(buf);
break;
}
@ -62,7 +62,8 @@ static CborError dumpelm(CborValue *it, bool *got_next, int nestingLevel) {
*got_next = true;
if (err)
return err; // parse error
printf("%s", buf);
PrintAndLogEx(NORMAL, "%s" NOLF, buf);
free(buf);
break;
}
@ -70,29 +71,29 @@ static CborError dumpelm(CborValue *it, bool *got_next, int nestingLevel) {
case CborTagType: {
CborTag tag;
cbor_value_get_tag(it, &tag);
printf("Tag(%lld)", (long long)tag);
PrintAndLogEx(NORMAL, "Tag(%lld)" NOLF, (long long)tag);
break;
}
case CborSimpleType: {
uint8_t t;
cbor_value_get_simple_type(it, &t);
printf("simple(%u)", t);
PrintAndLogEx(NORMAL, "simple(%u)" NOLF, t);
break;
}
case CborNullType:
printf("null");
PrintAndLogEx(NORMAL, "null" NOLF);
break;
case CborUndefinedType:
printf("undefined");
PrintAndLogEx(NORMAL, "undefined" NOLF);
break;
case CborBooleanType: {
bool val;
cbor_value_get_boolean(it, &val); // can't fail
printf("%s", val ? "true" : "false");
PrintAndLogEx(NORMAL, "%s" NOLF, (val) ? "true" : "false");
break;
}
@ -106,18 +107,18 @@ static CborError dumpelm(CborValue *it, bool *got_next, int nestingLevel) {
} else {
cbor_value_get_double(it, &val);
}
printf("%g", val);
PrintAndLogEx(NORMAL, "%g" NOLF, val);
break;
}
case CborHalfFloatType: {
uint16_t val;
cbor_value_get_half_float(it, &val);
printf("__f16(%04x)", val);
PrintAndLogEx(NORMAL, "__f16(%04x)" NOLF, val);
break;
}
case CborInvalidType:
printf("CborInvalidType!!!");
PrintAndLogEx(NORMAL, _RED_("CborInvalidType!!!") NOLF);
break;
}
@ -129,7 +130,7 @@ static CborError dumprecursive(uint8_t cmdCode, bool isResponse, CborValue *it,
while (!cbor_value_at_end(it)) {
CborError err;
CborType type = cbor_value_get_type(it);
//printf("^%x^", type);
bool got_next = false;
switch (type) {
@ -140,18 +141,23 @@ static CborError dumprecursive(uint8_t cmdCode, bool isResponse, CborValue *it,
assert(cbor_value_is_container(it));
if (!(isMapType && (elmCount % 2)))
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);
if (err)
return err; // parse error
err = dumprecursive(cmdCode, isResponse, &recursed, (type == CborMapType), nestingLevel + 1);
if (err)
return err; // parse error
err = cbor_value_leave_container(it, &recursed);
if (err)
return err; // parse error
indent(nestingLevel);
printf("]");
PrintAndLogEx(NORMAL, "]" NOLF);
got_next = true;
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);
if (err)
return err;
if (cmdCode > 0 && nestingLevel == 1 && isMapType && !(elmCount % 2)) {
int64_t val;
cbor_value_get_int64(it, &val);
const char *desc = fido2GetCmdMemberDescription(cmdCode, isResponse, val);
if (desc)
printf(" (%s)", desc);
PrintAndLogEx(NORMAL, " (%s)" NOLF, desc);
}
break;
}
@ -187,9 +194,9 @@ static CborError dumprecursive(uint8_t cmdCode, bool isResponse, CborValue *it,
return err;
}
if (isMapType && !(elmCount % 2)) {
printf(": ");
PrintAndLogEx(NORMAL, ": " NOLF);
} else {
printf("\n");
PrintAndLogEx(NORMAL, "");
}
elmCount++;
}

View file

@ -432,7 +432,7 @@ int saveFileJSONex(const char *preferredName, JSONFileType ftype, uint8_t *data,
picopass_hdr *hdr = (picopass_hdr *)data;
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);
if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) {
@ -440,7 +440,7 @@ int saveFileJSONex(const char *preferredName, JSONFileType ftype, uint8_t *data,
JsonSaveBufAsHexCompact(root, "$.Card.AIA", ns_hdr->app_issuer_area, sizeof(ns_hdr->app_issuer_area));
} else {
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.AIA", hdr->app_issuer_area, sizeof(hdr->app_issuer_area));
}

View file

@ -383,7 +383,7 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) {
// success
if (memcmp(calculated_MAC, item.mac, 4) == 0) {
printf("\r\n");
PrintAndLogEx(NORMAL, "");
for (i = 0 ; i < numbytes_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++;
if ((brute & 0xFFFF) == 0) {
printf("%3d,", (brute >> 16) & 0xFF);
PrintAndLogEx(NORMAL, "%3d," NOLF, (brute >> 16) & 0xFF);
if (((brute >> 16) % 0x10) == 0)
printf("\n");
fflush(stdout);
PrintAndLogEx(NORMAL, "");
}
}
int errors = PM3_SUCCESS;
if (!found) {
if (found == false) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(WARNING, "Failed to recover %d bytes using the following CSN", numbytes_to_recover);
PrintAndLogEx(INFO, "CSN %s", sprint_hex(item.csn, 8));

View file

@ -7,6 +7,7 @@
#include <unistd.h>
#include <ctype.h>
#include "elite_crack.h"
#include "ui.h"
static void calc_score(uint8_t *csn, uint8_t *k) {
uint8_t score = 0 ;
@ -41,34 +42,33 @@ static void calc_score(uint8_t *csn, uint8_t *k) {
}
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]
, k[0], k[1], k[2], k[3], k[4], k[5], k[6], k[7]
);
for (i = 0 ; i < score; i++) {
printf("%d,", uniq_vals[i]);
PrintAndLogEx(NORMAL, "%d," NOLF, uniq_vals[i]);
}
printf("\tbadscore: %d (%02x)", badscore, badval);
printf("\r\n");
PrintAndLogEx(NORMAL, "\tbadscore: %d (%02x)" NOLF, badscore, badval);
PrintAndLogEx(NORMAL, "");
}
}
void brute_hash1(void) {
uint16_t a, b, c, d;
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 testcsn[8] = {0x00, 0x0d, 0x0f, 0xfd, 0xf7, 0xff, 0x12, 0xe0} ;
uint8_t testkey[8] = {0x05, 0x01, 0x00, 0x10, 0x45, 0x08, 0x45, 0x56} ;
calc_score(testcsn, testkey);
printf("Brute forcing hashones\n");
//exit(1);
for (a = 0; a < 256; a++) {
//if(a > 0)printf("%d/256 done...\n", a);
for (b = 0; b < 256; b++)
for (c = 0; c < 256; c++)
for (d = 0; d < 256; d++) {
PrintAndLogEx(INFO, "Brute forcing hashones");
for (uint16_t a = 0; a < 256; a++) {
for (uint16_t b = 0; b < 256; b++) {
for (uint16_t c = 0; c < 256; c++) {
for (uint16_t d = 0; d < 256; d++) {
csn[0] = a;
csn[1] = b;
csn[2] = c;
@ -81,5 +81,7 @@ void brute_hash1(void) {
calc_score(csn, k);
}
}
}
}
}

View file

@ -333,7 +333,7 @@ void hash0(uint64_t c, uint8_t k[8]) {
uint8_t p_i = p >> i & 0x1;
if (k[i]) { // yi = 1
//printf("k[%d] +1\n", i);
// PrintAndLogEx(NORMAL, "k[%d] + 1", i);
k[i] |= ~zTilde_i & 0x7E;
k[i] |= p_i & 1;
k[i] += 1;
@ -399,7 +399,7 @@ static void testPermute(void) {
permute(&p_in, x, 0, 4, &out);
uint64_t permuted = x_bytes_to_num(outbuffer, 8);
//printf("zTilde 0x%"PRIX64"\n", zTilde);
// PrintAndLogEx(NORMAL, "zTilde 0x%"PRIX64, zTilde);
permuted >>= 16;
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];
printf("Parity byte: 0x%02x\n", stored_parity);
int i;
int byte;
int fails =0;
PrintAndLogEx(NORMAL, "Parity byte: 0x%02x", stored_parity);
int i, byte, fails = 0;
BitstreamIn bits = {key, 56, 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;
bool pbit = stored_parity & (0x80 >> (byte));
if(parity != pbit)
{
printf("parity2 fail byte %d, should be %d, was %d\n", (i / 7), parity, pbit);
if (parity != pbit) {
PrintAndLogEx(NORMAL, "parity2 fail byte %d, should be %d, was %d", (i / 7), parity, pbit);
fails++;
}
parity =0 ;
@ -723,35 +716,32 @@ void checkParity2(uint8_t* key)
}
parity = parity ^ headBit(&bits);
}
if(fails)
{
printf("parity2 fails: %d\n", fails);
}else
{
printf("Key syntax is with parity bits grouped in the last byte!\n");
if (fails) {
PrintAndLogEx(FAILED, "parity2 fails: %d", fails);
} else {
PrintAndLogEx(INFO, "Key syntax is with parity bits grouped in the last byte!");
}
}
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;
bool parity =0;
BitstreamOut out = { output, 0,0};
BitstreamOut out = { output, 0, 0};
unsigned int bbyte, bbit;
for(bbyte=0; bbyte <8 ; bbyte++ )
{
for(bbit =0 ; bbit< 7 ; bbit++)
{
bool bit = *(key+bbyte) & (1 << (7-bbit));
pushBit(&out,bit);
for (bbyte = 0; bbyte <8; bbyte++ ) {
for(bbit = 0; bbit < 7; bbit++) {
bool bit = *(key + bbyte) & (1 << (7 - bbit));
pushBit(&out, bit);
parity ^= bit;
}
bool paritybit = *(key+bbyte) & 1;
paritybits |= paritybit << (7-bbyte);
bool paritybit = *(key + bbyte) & 1;
paritybits |= paritybit << (7 - bbyte);
parity = 0;
}
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
@ -759,25 +749,24 @@ void modifyKey_put_parity_last(uint8_t * key, uint8_t* output)
* @param key
* @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;
BitstreamOut out = { output, 0,0};
BitstreamIn in = {key, 0,0};
BitstreamOut out = {output, 0, 0};
BitstreamIn in = {key, 0, 0};
unsigned int bbyte, bbit;
for(bbit =0 ; bbit < 56 ; bbit++) {
if( bbit > 0 && bbit % 7 == 0) {
pushBit(&out,!parity);
for (bbit = 0; bbit < 56; bbit++) {
if (bbit > 0 && bbit % 7 == 0) {
pushBit(&out, !parity);
parity = 0;
}
bool bit = headBit(&in);
pushBit(&out,bit );
pushBit(&out, bit);
parity ^= bit;
}
pushBit(&out, !parity);
if( des_key_check_key_parity(output))
printf("modifyKey_put_parity_allover fail, DES key invalid parity!");
if (des_key_check_key_parity(output))
PrintAndLogEx(FAILED, "modifyKey_put_parity_allover fail, DES key invalid parity!");
}
*/

View file

@ -34,10 +34,10 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
bool first_run = true;
// message
PrintAndLogEx(INFO, "--------------------------------------------------------------------------------\n");
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, "--------------------------------------------------------------------------------\n");
PrintAndLogEx(INFO, "--------------------------------------------------------------------------------");
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, "--------------------------------------------------------------------------------");
while (true) {
clearCommandBuffer();
@ -58,8 +58,8 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
// wait cycle
while (true) {
printf(".");
fflush(stdout);
PrintAndLogEx(NORMAL, "." NOLF);
if (kbd_enter_pressed()) {
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)) {
timeout++;
printf(".");
fflush(stdout);
PrintAndLogEx(NORMAL, "." NOLF);
// max timeout for one chunk of 85keys, 60*3sec = 180seconds
// s70 with 40*2 keys to check, 80*85 = 6800 auth.
// 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.
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?
if (curr_keys == sectorsCnt * 2 || lastChunk) {
@ -311,6 +310,7 @@ int mfCheckKeys_file(uint8_t *destfn, uint64_t *key) {
} PACKED;
struct kr *keyresult = (struct kr *)&resp.data.asBytes;
if (!keyresult->found) return PM3_ESOFT;
*key = bytes_to_num(keyresult->key, sizeof(keyresult->key));
return PM3_SUCCESS;
}
@ -418,9 +418,6 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
return PM3_ETIMEOUT;
}
if (resp.status != PM3_SUCCESS)
return PM3_ESOFT;
struct p {
int16_t isOK;
uint8_t block;
@ -433,8 +430,9 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
} PACKED;
struct p *package = (struct p *)resp.data.asBytes;
// error during nested
if (package->isOK) return package->isOK;
// error during nested on device side
if (package->isOK != PM3_SUCCESS)
return package->isOK;
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].ks1, package->ks_b, sizeof(package->ks_b));
// calc keys
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);
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->keytype ? 'B' : 'A',
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);
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:
PrintAndLogEx(SUCCESS, "target block:%3u key type: %c",
PrintAndLogEx(SUCCESS, "\ntarget block:%3u key type: %c",
package->block,
package->keytype ? 'B' : 'A'
);
free(statelists[0].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) {
uint32_t uid;
@ -678,6 +673,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
//flush queue
while (kbd_enter_pressed()) {
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
PrintAndLogEx(NORMAL, "");
free(mem);
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.
if (IfPm3Flash()) {
mem[3] = ((chunk >> 8) & 0xFF);
mem[4] = (chunk & 0xFF);
// upload to flash.
res = flashmem_spiffs_load(destfn, mem, 5 + (chunk * 6));
if (res != PM3_SUCCESS) {
PrintAndLogEx(WARNING, "SPIFFS upload failed");
PrintAndLogEx(WARNING, "\nSPIFFS upload failed");
free(mem);
return res;
}
res = mfCheckKeys_file(destfn, &key64);
} else {
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);
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, "target block:%3u key type: %c -- found valid key [" _YELLOW_("%s") "]",
package->block,
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;
} else if (res == PM3_ETIMEOUT || res == PM3_EOPABORTED) {
PrintAndLogEx(NORMAL, "");
free(mem);
return res;
}
// if (i%10 == 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;
free(mem);
out:
PrintAndLogEx(SUCCESS, "target block:%3u key type: %c",
PrintAndLogEx(SUCCESS, "\ntarget block:%3u key type: %c",
package->block,
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) {
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 params = MAGIC_SINGLE;
@ -887,12 +886,12 @@ int mfCWipe(uint8_t *uid, uint8_t *atqa, uint8_t *sak) {
PrintAndLogEx(INPLACE, "wipe block %d", blockNo);
if (blockNo == 0) {
res = mfCSetBlock(blockNo, block0, NULL, (params | MAGIC_WIPE));
res = mfCSetBlock(blockNo, block0, NULL, params);
} else {
if (mfIsSectorTrailer(blockNo))
res = mfCSetBlock(blockNo, blockK, NULL, params);
// else
// res = mfCSetBlock(blockNo, blockD, NULL, params);
else
res = mfCSetBlock(blockNo, blockD, NULL, params);
}
if (res == PM3_SUCCESS)
@ -916,7 +915,7 @@ int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params) {
clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFARE_CSETBL, params, blockNo, 0, data, 16);
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
if (WaitForResponseTimeout(CMD_ACK, &resp, 3500)) {
uint8_t isOK = resp.oldarg[0] & 0xff;
if (uid != NULL)
memcpy(uid, resp.data.asBytes, 4);
@ -945,8 +944,47 @@ int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params) {
return PM3_SUCCESS;
}
// SNIFFER
// [iceman] so many global variables....
int mfGen3UID(uint8_t *uid, uint8_t uidlen, uint8_t *oldUid) {
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
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");
while (true) {
printf(".");
fflush(stdout);
PrintAndLogEx(NORMAL, "." NOLF);
if (kbd_enter_pressed()) {
return PM3_EOPABORTED;
}
if (WaitForResponseTimeout(CMD_HF_MIFARE_NACK_DETECT, &resp, 500)) {
PrintAndLogEx(NORMAL, "");
if (resp.status == PM3_EOPABORTED) {
PrintAndLogEx(WARNING, "button pressed. Aborted.");
return PM3_EOPABORTED;
@ -1053,7 +1093,6 @@ int detect_classic_nackbug(bool verbose) {
uint8_t ok = resp.data.asBytes[0];
uint8_t nacks = resp.data.asBytes[1];
uint16_t auths = bytes_to_num(resp.data.asBytes + 2, 2);
PrintAndLogEx(NORMAL, "");
if (verbose) {
PrintAndLogEx(SUCCESS, "num of auth requests : %u", auths);
@ -1070,7 +1109,7 @@ int detect_classic_nackbug(bool verbose) {
case 97 : {
if (verbose) {
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;
}

View file

@ -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 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 detect_classic_prng(void);

View file

@ -108,7 +108,7 @@ static void showBanner(void) {
#endif
// PrintAndLogEx(NORMAL, "\nSupport iceman on patreon - https://www.patreon.com/iceman1001/");
// PrintAndLogEx(NORMAL, " on paypal - https://www.paypal.me/iceman1001");
// printf("\nMonero: 43mNJLpgBVaTvyZmX9ajcohpvVkaRy1kbZPm8tqAb7itZgfuYecgkRF36rXrKFUkwEGeZedPsASRxgv4HPBHvJwyJdyvQuP");
// PrintAndLogEx(NORMAL, "\nMonero: 43mNJLpgBVaTvyZmX9ajcohpvVkaRy1kbZPm8tqAb7itZgfuYecgkRF36rXrKFUkwEGeZedPsASRxgv4HPBHvJwyJdyvQuP");
PrintAndLogEx(NORMAL, "");
fflush(stdout);
g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG;
@ -678,55 +678,8 @@ finish2:
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)
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
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
#endif
@ -735,10 +688,8 @@ static bool DetectWindowsAnsiSupport(void) {
DWORD dwMode = 0;
GetConsoleMode(hOut, &dwMode);
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
SetConsoleMode(hOut, dwMode);
// If both VirtualTerminalLevel and ForceV2 is set, AnsiColor should work
return virtualTerminalLevelSet && forceV2Set;
return SetConsoleMode(hOut, dwMode) ? true : false;
}
#endif

View file

@ -474,14 +474,14 @@ static int l_mfDarkside(lua_State *L) {
static int l_foobar(lua_State *L) {
//Check number of arguments
int n = lua_gettop(L);
printf("foobar called with %d arguments", n);
PrintAndLogEx(INFO, "foobar called with %d arguments", n);
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?
// 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;
uint8_t destination[8];
num_to_bytes(x, sizeof(x), destination);
@ -1046,7 +1046,7 @@ static int l_T55xx_detect(lua_State *L) {
sscanf(p_gb, "%u", &gb);
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: {
const char *p_pwd = luaL_checklstring(L, 1, &size);
@ -1129,9 +1129,7 @@ static int l_remark(lua_State *L) {
}
size_t size;
// data
const char *s = luaL_checklstring(L, 1, &size);
int res = CmdRem(s);
lua_pushinteger(L, res);
return 1;
@ -1199,6 +1197,19 @@ static int l_cwd(lua_State *L) {
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
* 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);
// Core library is in this table. Contains '
//this is 'pm3' table
// this is 'pm3' table
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++) {
lua_pushcfunction(L, libs[i].func);
lua_setfield(L, -2, libs[i].name);//set the name, pop stack
}
//Name of 'core'
// Name of '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);
//--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:
const char *exec_path = get_my_executable_directory();
if (exec_path != NULL) {

View file

@ -359,7 +359,7 @@ void uart_close(const serial_port sp) {
int err = fcntl(spu->fd, F_SETLK, &fl);
if (err == -1) {
//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);
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
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;
// Cap the number of bytes, so we don't overrun the buffer
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);
}
@ -443,13 +443,13 @@ int uart_send(const serial_port sp, const uint8_t *pbtTx, const uint32_t len) {
// Write error
if (res < 0) {
printf("UART:: write error (%d)\n", res);
PrintAndLogEx(ERR, "UART:: write error (%d)", res);
return PM3_ENOTTY;
}
// Write time-out
if (res == 0) {
printf("UART:: write time-out\n");
PrintAndLogEx(ERR, "UART:: write time-out");
return PM3_ETIMEOUT;
}

View file

@ -22,7 +22,6 @@ extern "C" {
#define _USE_MATH_DEFINES
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 clientdebugLevel {cdbOFF, cdbSIMPLE, cdbFULL} clientdebugLevel_t;
// typedef enum devicedebugLevel {ddbOFF, ddbERROR, ddbINFO, ddbDEBUG, ddbEXTENDED} devicedebugLevel_t;

View file

@ -96,6 +96,7 @@ void FillFileNameByUID(char *filenamePrefix, const uint8_t *uid, const char *ext
for (int j = 0; j < uidlen; j++)
sprintf(filenamePrefix + len + j * 2, "%02X", uid[j]);
strcat(filenamePrefix, ext);
}
@ -176,26 +177,27 @@ void print_hex(const uint8_t *data, const size_t len) {
if (data == NULL || len == 0) return;
for (size_t i = 0; i < len; i++)
printf("%02x ", data[i]);
printf("\n");
PrintAndLogEx(NORMAL, "%02x " NOLF, data[i]);
PrintAndLogEx(NORMAL, "");
}
void print_hex_break(const uint8_t *data, const size_t len, uint8_t breaks) {
if (data == NULL || len == 0) return;
int rownum = 0;
printf("[%02d] | ", rownum);
PrintAndLogEx(NORMAL, "[%02d] | " NOLF, rownum);
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
if (breaks > 0 && !((i + 1) % breaks) && (i + 1 < len)) {
++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) {
@ -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)
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
//clear memory
@ -267,7 +269,7 @@ void sprint_bin_break_ex(uint8_t *src, size_t srclen, char *dest , uint8_t break
else
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
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 pos = (max_len * 3) + 2;
while (i < max_len) {
char c = data[i];
if ((c < 32) || (c == 127))
c = '.';
sprintf(tmp + pos + i, "%c", c);
++i;
}
@ -682,7 +687,7 @@ int hextobinarray(char *target, char *source) {
else if (x >= 'A' && x <= 'F')
x -= 'A' - 10;
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;
}
// output

View file

@ -134,7 +134,6 @@ static uint8_t get_length_from_header(wiegand_message_t *data) {
hfmt = 0;
len = 37;
} else if ((data->Mid & 0x0000001F) > 0) { // 36-32 bits
printf("a\n");
hfmt = data->Mid & 0x0000001F;
len = 32;
} else {

View file

@ -15,7 +15,7 @@ There are two ways to install, build and use Proxmark3 on Windows:
## Driver Installation
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

View file

@ -1,6 +1,13 @@
### First things on your RDV40
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 t55xx_default_pwds t
[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
```
### Verify sim module firmware version
To make sure you got the latest sim module firmware.

View file

@ -80,17 +80,19 @@ Here are the supported values you can assign to `STANDALONE` in `Makefile.platfo
| STANDALONE | DESCRIPTION |
|-----------------|----------------------------------------|
| | No standalone mode
| LF_SKELETON | standalone mode skeleton - Iceman
| LF_SKELETON | standalone mode skeleton - Iceman1001
| LF_EM4100EMUL | LF EM4100 simulator standalone mode - temskiy
| LF_EM4100RSWB | LF EM4100 read/write/clone/brute mode - Monster1024
| LF_EM4100RWC | LF EM4100 read/write/clone mode - temskiy
| 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_SAMYRUN | HID26 read/clone/sim - Samy Kamkar
| 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_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_MATTYRUN | Mifare sniff/clone - Matías A. Ré Medina
| HF_MSDSAL (def)| EMV Read and emulation - Salvador Mendoza

View file

@ -1,6 +1,9 @@
#ifndef __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 _BLUE_(s) "\x1b[34m" s AEND

View file

@ -122,6 +122,15 @@ typedef struct {
bool verbose;
} 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
typedef struct {
uint32_t timestamp;
@ -569,6 +578,11 @@ typedef struct {
#define CMD_HF_FELICALITE_DUMP 0x03AA
#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
#define CMD_MEASURE_ANTENNA_TUNING 0x0400
#define CMD_MEASURE_ANTENNA_TUNING_HF 0x0401
@ -604,6 +618,7 @@ typedef struct {
#define CMD_HF_MIFAREU_READCARD 0x0721
#define CMD_HF_MIFARE_WRITEBL 0x0622
#define CMD_HF_MIFAREU_WRITEBL 0x0722
#define CMD_HF_MIFAREU_WRITEBL_COMPAT 0x0723
#define CMD_HF_MIFARE_CHKKEYS 0x0623
#define CMD_HF_MIFARE_SETMOD 0x0624
@ -648,6 +663,11 @@ typedef struct {
//For Atmel CryptoRF
#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
//Mifare simulation flags
@ -714,7 +734,7 @@ typedef struct {
#define PM3_ETIMEOUT -4
// Operation aborted (by user) client/pm3: kbd/button pressed
#define PM3_EOPABORTED -5
// Not (yet) implemented client/pm3: TBD placeholder
// Not (yet) implemented client/pm3: TBD place holder
#define PM3_ENOTIMPL -6
// Error while RF transmission client/pm3: fail between pm3 & card
#define PM3_ERFTRANS -7
@ -732,7 +752,7 @@ typedef struct {
#define PM3_EFILE -13
// Generic TTY error
#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
// Expected a different answer error client/pm3: error when expecting one answer and got another one
#define PM3_EWRONGANSWER -16
@ -745,6 +765,12 @@ typedef struct {
#define PM3_EAPDU_ENCODEFAIL -19
// APDU responded with a failure code
#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)
#define PM3_ENODATA -98
// Quit program client: reserved, order to quit the program

View file

@ -15,6 +15,9 @@ ISO14443A (usually NFC tags)
95 20 = Anticollision of cascade level2
95 70 = Select of cascade level2
50 00 = Halt (usage: 5000+2bytes ISO14443A-CRC - no answer from card)
E0 = RATS
D0 = PPS
Mifare
60 = Authenticate with KeyA
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_HALT 0x50
#define ISO14443A_CMD_RATS 0xE0
#define ISO14443A_CMD_PPS 0xD0
#define ISO14443A_CMD_NXP_DESELECT 0xC2
#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_FAST_WRITE 0x00004000
#define T5555_PAGE_SELECT 0x00008000
#define T5555_FIXED 0x60000000
#define T55XX_WRITE_TIMEOUT 1500