mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 13:23:51 -07:00
commit
9b7dd1cc4f
26 changed files with 13131 additions and 459 deletions
|
@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file.
|
|||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- Add low level support for 14b' aka Innovatron (@doegox)
|
||||
- Add doc/cliparser.md (@mwalker33)
|
||||
- Add `hf 14b apdu` - send APDU over ISO14443B (@iceman1001)
|
||||
- Add `lf t55xx chk e <EM4100> option` - Checks calculated password based on the EM4100 id from some white cloners forumla by paleopterix (@mwalker33)
|
||||
- Add `lf t55xx sniff` to allow extracting commands and passwords used be cloners. (@mwalker33)
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
|[Notes on file formats used with Proxmark3](/doc/extensions_notes.md)|[Notes on MFU binary format](/doc/mfu_binary_format_notes.md)|[Notes on FPGA & ARM](/doc/fpga_arm_notes.md)|
|
||||
|[Developing standalone mode](/armsrc/Standalone/readme.md)|[Wiki about standalone mode](https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode)|[Notes on Magic cards](/doc/magic_cards_notes.md)|
|
||||
|[Notes on Color usage](/doc/colors_notes.md)|[Makefile vs CMake](/doc/md/Development/Makefile-vs-CMake.md)|[Notes on Cloner guns](/doc/cloner_notes.md)|
|
||||
|
||||
|[Notes on cliparser usage](/doc/cliparser.md)|||
|
||||
|
||||
## Build for non-RDV4 Proxmark3 platforms
|
||||
|
||||
|
|
|
@ -1126,11 +1126,10 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
break;
|
||||
}
|
||||
case CMD_HF_ISO14443B_SIMULATE: {
|
||||
SimulateIso14443bTag(packet->oldarg[0]);
|
||||
SimulateIso14443bTag(packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ISO14443B_COMMAND: {
|
||||
//SendRawCommand14443B(packet->oldarg[0],packet->oldarg[1],packet->oldarg[2],packet->data.asBytes);
|
||||
SendRawCommand14443B_Ex(packet);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "commonutil.h"
|
||||
#include "dbprint.h"
|
||||
#include "ticks.h"
|
||||
#include "mifare.h"
|
||||
#include "iso18.h"
|
||||
|
||||
// FeliCa timings
|
||||
// minimum time between the start bits of consecutive transfers from reader to tag: 6800 carrier (13.56MHz) cycles
|
||||
|
|
|
@ -274,8 +274,7 @@ static struct {
|
|||
enum {
|
||||
DEMOD_UNSYNCD,
|
||||
DEMOD_PHASE_REF_TRAINING,
|
||||
DEMOD_AWAITING_FALLING_EDGE_OF_SOF,
|
||||
DEMOD_GOT_FALLING_EDGE_OF_SOF,
|
||||
WAIT_FOR_RISING_EDGE_OF_SOF,
|
||||
DEMOD_AWAITING_START_BIT,
|
||||
DEMOD_RECEIVING_DATA
|
||||
} state;
|
||||
|
@ -531,7 +530,7 @@ static void TransmitFor14443b_AsTag(uint8_t *response, uint16_t len) {
|
|||
// Main loop of simulated tag: receive commands from reader, decide what
|
||||
// response to send, and send it.
|
||||
//-----------------------------------------------------------------------------
|
||||
void SimulateIso14443bTag(uint32_t pupi) {
|
||||
void SimulateIso14443bTag(uint8_t *pupi) {
|
||||
|
||||
LED_A_ON();
|
||||
// the only commands we understand is WUPB, AFI=0, Select All, N=1:
|
||||
|
@ -554,15 +553,15 @@ void SimulateIso14443bTag(uint32_t pupi) {
|
|||
0x5e, 0xd7
|
||||
};
|
||||
|
||||
// response to HLTB and ATTRIB
|
||||
static const uint8_t respOK[] = {0x00, 0x78, 0xF0};
|
||||
|
||||
// ...PUPI/UID supplied from user. Adjust ATQB response accordingly
|
||||
if (pupi > 0) {
|
||||
num_to_bytes(pupi, 4, respATQB + 1);
|
||||
if (memcmp("\x00\x00\x00\x00", pupi, 4) != 0) {
|
||||
memcpy(respATQB + 1, pupi, 4);
|
||||
AddCrc14B(respATQB, 12);
|
||||
}
|
||||
|
||||
// response to HLTB and ATTRIB
|
||||
static const uint8_t respOK[] = {0x00, 0x78, 0xF0};
|
||||
|
||||
// setup device.
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
|
@ -724,6 +723,13 @@ void SimulateIso14443bTag(uint32_t pupi) {
|
|||
// tag's response, which we leave in the buffer to be demodulated on the
|
||||
// PC side.
|
||||
//=============================================================================
|
||||
// We support both 14b framing and 14b' framing.
|
||||
// 14b framing looks like:
|
||||
// xxxxxxxx1111111111111111-000000000011-0........1-0........1-0........1-1-0........1-0........1-1000000000011xxxxxx
|
||||
// TR1 SOF 10*0+2*1 start-stop ^^^^^^^^byte ^ occasional stuff bit EOF 10*0+N*1
|
||||
// 14b' framing looks like:
|
||||
// xxxxxxxxxxxxxxxx111111111111111111111-0........1-0........1-0........1-1-0........1-0........1-000000000000xxxxxxx
|
||||
// SOF? start-stop ^^^^^^^^byte ^ occasional stuff bit EOF
|
||||
|
||||
/*
|
||||
* Handles reception of a bit from the tag
|
||||
|
@ -774,57 +780,33 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
|
|||
break;
|
||||
}
|
||||
case DEMOD_PHASE_REF_TRAINING: {
|
||||
if (Demod.posCount < 8) {
|
||||
if (AMPLITUDE(ci, cq) > SUBCARRIER_DETECT_THRESHOLD) {
|
||||
// set the reference phase (will code a logic '1') by averaging over 32 1/fs.
|
||||
// note: synchronization time > 80 1/fs
|
||||
Demod.sumI += ci;
|
||||
Demod.sumQ += cq;
|
||||
Demod.posCount++;
|
||||
// While we get a constant signal
|
||||
if (AMPLITUDE(ci, cq) > SUBCARRIER_DETECT_THRESHOLD) {
|
||||
if (((ABS(Demod.sumI) > ABS(Demod.sumQ)) && (((ci > 0) && (Demod.sumI > 0)) || ((ci < 0) && (Demod.sumI < 0)))) || // signal closer to horizontal, polarity check based on on I
|
||||
((ABS(Demod.sumI) <= ABS(Demod.sumQ)) && (((cq > 0) && (Demod.sumQ > 0)) || ((cq < 0) && (Demod.sumQ < 0))))) { // signal closer to vertical, polarity check based on on Q
|
||||
if (Demod.posCount < 10) { // refine signal approximation during first 10 samples
|
||||
Demod.sumI += ci;
|
||||
Demod.sumQ += cq;
|
||||
}
|
||||
Demod.posCount += 1;
|
||||
} else {
|
||||
// subcarrier lost
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
// transition
|
||||
if (Demod.posCount < 10) {
|
||||
// subcarrier lost
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
break;
|
||||
} else {
|
||||
// at this point it can be start of 14b' data or start of 14b SOF
|
||||
MAKE_SOFT_DECISION();
|
||||
Demod.posCount = 1; // this was the first half
|
||||
Demod.thisBit = v;
|
||||
Demod.shiftReg = 0;
|
||||
Demod.state = DEMOD_RECEIVING_DATA;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DEMOD_AWAITING_FALLING_EDGE_OF_SOF: {
|
||||
|
||||
MAKE_SOFT_DECISION();
|
||||
|
||||
if (v < 0) { // logic '0' detected
|
||||
Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF;
|
||||
Demod.posCount = 0; // start of SOF sequence
|
||||
} else {
|
||||
if (Demod.posCount > 200/4) { // maximum length of TR1 = 200 1/fs
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
}
|
||||
}
|
||||
Demod.posCount++;
|
||||
break;
|
||||
}
|
||||
case DEMOD_GOT_FALLING_EDGE_OF_SOF: {
|
||||
|
||||
Demod.posCount++;
|
||||
MAKE_SOFT_DECISION();
|
||||
|
||||
if (v > 0) {
|
||||
if (Demod.posCount < 9 * 2) { // low phase of SOF too short (< 9 etu). Note: spec is >= 10, but FPGA tends to "smear" edges
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
} else {
|
||||
LED_C_ON(); // Got SOF
|
||||
Demod.posCount = 0;
|
||||
Demod.bitCount = 0;
|
||||
Demod.len = 0;
|
||||
Demod.state = DEMOD_AWAITING_START_BIT;
|
||||
}
|
||||
} else {
|
||||
if (Demod.posCount > 12 * 2) { // low phase of SOF too long (> 12 etu)
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
LED_C_OFF();
|
||||
}
|
||||
// subcarrier lost
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -848,6 +830,28 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case WAIT_FOR_RISING_EDGE_OF_SOF: {
|
||||
|
||||
Demod.posCount++;
|
||||
MAKE_SOFT_DECISION();
|
||||
if (v > 0) {
|
||||
if (Demod.posCount < 9 * 2) { // low phase of SOF too short (< 9 etu). Note: spec is >= 10, but FPGA tends to "smear" edges
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
} else {
|
||||
LED_C_ON(); // Got SOF
|
||||
Demod.posCount = 0;
|
||||
Demod.bitCount = 0;
|
||||
Demod.len = 0;
|
||||
Demod.state = DEMOD_AWAITING_START_BIT;
|
||||
}
|
||||
} else {
|
||||
if (Demod.posCount > 12 * 2) { // low phase of SOF too long (> 12 etu)
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
LED_C_OFF();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DEMOD_RECEIVING_DATA: {
|
||||
|
||||
MAKE_SOFT_DECISION();
|
||||
|
@ -874,12 +878,35 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
|
|||
Demod.bitCount = 0;
|
||||
Demod.state = DEMOD_AWAITING_START_BIT;
|
||||
} else {
|
||||
Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF;
|
||||
LED_C_OFF();
|
||||
if (s == 0x000) {
|
||||
// This is EOF (start, stop and all data bits == '0'
|
||||
return true;
|
||||
if (Demod.len > 0) {
|
||||
LED_C_OFF();
|
||||
// This is EOF (start, stop and all data bits == '0'
|
||||
return true;
|
||||
} else {
|
||||
// Zeroes but no data acquired yet?
|
||||
// => Still in SOF of 14b, wait for raising edge
|
||||
Demod.posCount = 10 * 2;
|
||||
Demod.bitCount = 0;
|
||||
Demod.len = 0;
|
||||
Demod.state = WAIT_FOR_RISING_EDGE_OF_SOF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (AMPLITUDE(ci, cq) < SUBCARRIER_DETECT_THRESHOLD) {
|
||||
LED_C_OFF();
|
||||
// subcarrier lost
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
if (Demod.len > 0) { // no EOF but no signal anymore and we got data, e.g. ASK CTx
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// we have still signal but no proper byte or EOF? this shouldn't happen
|
||||
//Demod.posCount = 10 * 2;
|
||||
Demod.bitCount = 0;
|
||||
Demod.len = 0;
|
||||
Demod.state = WAIT_FOR_RISING_EDGE_OF_SOF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Demod.posCount = 0;
|
||||
|
@ -1230,6 +1257,79 @@ int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, uint8
|
|||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* ASK CTS initialise.
|
||||
*/
|
||||
static int iso14443b_select_cts_card(iso14b_cts_card_select_t *card) {
|
||||
// INITIATE command: wake up the tag using the INITIATE
|
||||
uint8_t cmdINIT[] = {ASK_REQT, 0xF9, 0xE0};
|
||||
uint8_t cmdMSBUID[] = {ASK_SELECT, 0xFF, 0xFF, 0x00, 0x00};
|
||||
uint8_t cmdLSBUID[] = {0xC4, 0x00, 0x00};
|
||||
|
||||
AddCrc14B(cmdMSBUID, 3);
|
||||
AddCrc14B(cmdLSBUID, 1);
|
||||
|
||||
uint8_t r[8];
|
||||
|
||||
uint32_t start_time = 0;
|
||||
uint32_t eof_time = 0;
|
||||
CodeAndTransmit14443bAsReader(cmdINIT, sizeof(cmdINIT), &start_time, &eof_time);
|
||||
|
||||
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
|
||||
int retlen = Get14443bAnswerFromTag(r, sizeof(r), ISO14443B_READER_TIMEOUT, &eof_time);
|
||||
FpgaDisableTracing();
|
||||
|
||||
if (retlen != 4) {
|
||||
return -1;
|
||||
}
|
||||
if (check_crc(CRC_14443_B, r, retlen) == false) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (card) {
|
||||
// pc. fc Product code, Facility code
|
||||
card->pc = r[0];
|
||||
card->fc = r[1];
|
||||
}
|
||||
|
||||
start_time = eof_time + DELAY_ISO14443B_VICC_TO_VCD_READER;
|
||||
CodeAndTransmit14443bAsReader(cmdMSBUID, sizeof(cmdMSBUID), &start_time, &eof_time);
|
||||
|
||||
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
|
||||
retlen = Get14443bAnswerFromTag(r, sizeof(r), ISO14443B_READER_TIMEOUT, &eof_time);
|
||||
FpgaDisableTracing();
|
||||
|
||||
if (retlen != 4) {
|
||||
return -1;
|
||||
}
|
||||
if (check_crc(CRC_14443_B, r, retlen) == false) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (card) {
|
||||
memcpy(card->uid, r, 2);
|
||||
}
|
||||
|
||||
start_time = eof_time + DELAY_ISO14443B_VICC_TO_VCD_READER;
|
||||
CodeAndTransmit14443bAsReader(cmdLSBUID, sizeof(cmdLSBUID), &start_time, &eof_time);
|
||||
|
||||
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
|
||||
retlen = Get14443bAnswerFromTag(r, sizeof(r), ISO14443B_READER_TIMEOUT, &eof_time);
|
||||
FpgaDisableTracing();
|
||||
|
||||
if (retlen != 4) {
|
||||
return -1;
|
||||
}
|
||||
if (check_crc(CRC_14443_B, r, retlen) == false) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (card) {
|
||||
memcpy(card->uid + 2, r, 2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* SRx Initialise.
|
||||
*/
|
||||
|
@ -1248,8 +1348,9 @@ static int iso14443b_select_srx_card(iso14b_card_select_t *card) {
|
|||
int retlen = Get14443bAnswerFromTag(r_init, sizeof(r_init), ISO14443B_READER_TIMEOUT, &eof_time);
|
||||
FpgaDisableTracing();
|
||||
|
||||
if (retlen <= 0)
|
||||
if (retlen <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Randomly generated Chip ID
|
||||
if (card) {
|
||||
|
@ -1272,8 +1373,6 @@ static int iso14443b_select_srx_card(iso14b_card_select_t *card) {
|
|||
if (retlen != 3) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check the CRC of the answer:
|
||||
if (!check_crc(CRC_14443_B, r_select, retlen)) {
|
||||
return -2;
|
||||
}
|
||||
|
@ -1298,8 +1397,6 @@ static int iso14443b_select_srx_card(iso14b_card_select_t *card) {
|
|||
if (retlen != 10) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// The check the CRC of the answer
|
||||
if (!check_crc(CRC_14443_B, r_papid, retlen)) {
|
||||
return -2;
|
||||
}
|
||||
|
@ -1692,7 +1789,7 @@ void SniffIso14443b(void) {
|
|||
expect_tag_answer = false;
|
||||
tag_is_active = false;
|
||||
} else {
|
||||
tag_is_active = (Demod.state > DEMOD_GOT_FALLING_EDGE_OF_SOF);
|
||||
tag_is_active = (Demod.state > WAIT_FOR_RISING_EDGE_OF_SOF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1770,6 +1867,15 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) {
|
|||
if (status > 0) goto out;
|
||||
}
|
||||
|
||||
if ((param & ISO14B_SELECT_CTS) == ISO14B_SELECT_CTS) {
|
||||
iso14b_cts_card_select_t cts;
|
||||
sendlen = sizeof(iso14b_cts_card_select_t);
|
||||
status = iso14443b_select_cts_card(&cts);
|
||||
reply_mix(CMD_HF_ISO14443B_COMMAND, status, sendlen, 0, (uint8_t *)&cts, sendlen);
|
||||
// 0: OK 2: demod fail, 3:crc fail,
|
||||
if (status > 0) goto out;
|
||||
}
|
||||
|
||||
if ((param & ISO14B_APDU) == ISO14B_APDU) {
|
||||
status = iso14443b_apdu(cmd, len, (param & ISO14B_SEND_CHAINING), buf, sizeof(buf));
|
||||
sendlen = MIN(Demod.len, PM3_CMD_DATA_SIZE);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
#include "common.h"
|
||||
|
||||
#include "mifare.h"
|
||||
#include "iso14b.h"
|
||||
#include "pm3_cmd.h"
|
||||
|
||||
#ifndef AddCrc14A
|
||||
|
@ -32,7 +32,7 @@ int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, uint8
|
|||
int iso14443b_select_card(iso14b_card_select_t *card);
|
||||
int iso14443b_select_card_srx(iso14b_card_select_t *card);
|
||||
|
||||
void SimulateIso14443bTag(uint32_t pupi);
|
||||
void SimulateIso14443bTag(uint8_t *pupi);
|
||||
void AcquireRawAdcSamplesIso14443b(uint32_t parameter);
|
||||
void ReadSTMemoryIso14443b(uint16_t numofblocks);
|
||||
void SniffIso14443b(void);
|
||||
|
|
|
@ -236,8 +236,8 @@ static int usage_hf_14a_sim(void) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_hf_14a_sniff(void) {
|
||||
PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer.");
|
||||
PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf list 14a'");
|
||||
PrintAndLogEx(NORMAL, "Collect data from the field and save into command buffer.");
|
||||
PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf 14a list'");
|
||||
PrintAndLogEx(NORMAL, "Usage: hf 14a sniff [c][r]");
|
||||
PrintAndLogEx(NORMAL, "c - triggered by first data from card");
|
||||
PrintAndLogEx(NORMAL, "r - triggered by first 7-bit request from reader (REQ,WUP,...)");
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "cmdhf14b.h"
|
||||
#include <ctype.h>
|
||||
#include "iso14b.h"
|
||||
#include "fileutils.h"
|
||||
#include "cmdparser.h" // command_t
|
||||
#include "commonutil.h" // ARRAYLEN
|
||||
|
@ -33,69 +34,6 @@ bool apdu_in_framing_enable = true;
|
|||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
static int usage_hf_14b_info(void) {
|
||||
PrintAndLogEx(NORMAL, "Usage: hf 14b info [h] [s]");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h this help");
|
||||
PrintAndLogEx(NORMAL, " s silently");
|
||||
PrintAndLogEx(NORMAL, "Example:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14b info"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_hf_14b_reader(void) {
|
||||
PrintAndLogEx(NORMAL, "Usage: hf 14b reader [h] [s]");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h this help");
|
||||
PrintAndLogEx(NORMAL, " s silently");
|
||||
PrintAndLogEx(NORMAL, "Example:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14b reader"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_hf_14b_raw(void) {
|
||||
PrintAndLogEx(NORMAL, "Usage: hf 14b raw [-h] [-r] [-c] [-k] [-s / -ss] [-t] <0A 0B 0C ... hex>");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " -h this help");
|
||||
PrintAndLogEx(NORMAL, " -r do not read response");
|
||||
PrintAndLogEx(NORMAL, " -c calculate and append CRC");
|
||||
PrintAndLogEx(NORMAL, " -k keep signal field ON after receive");
|
||||
PrintAndLogEx(NORMAL, " -s active signal field ON with select");
|
||||
PrintAndLogEx(NORMAL, " -ss active signal field ON with select for SRx ST Microelectronics tags");
|
||||
PrintAndLogEx(NORMAL, " -t timeout in ms");
|
||||
PrintAndLogEx(NORMAL, "Example:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14b raw -s -c -k 0200a40400"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_hf_14b_sniff(void) {
|
||||
PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer.");
|
||||
PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf list 14b'");
|
||||
PrintAndLogEx(NORMAL, "Usage: hf 14b sniff [h]");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h this help");
|
||||
PrintAndLogEx(NORMAL, "Example:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14b sniff"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_hf_14b_sim(void) {
|
||||
PrintAndLogEx(NORMAL, "Emulating ISO/IEC 14443 type B tag with 4 UID / PUPI");
|
||||
PrintAndLogEx(NORMAL, "Usage: hf 14b sim [h] u <uid>");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h this help");
|
||||
PrintAndLogEx(NORMAL, " u 4byte UID/PUPI");
|
||||
PrintAndLogEx(NORMAL, "Example:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14b sim"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14b sim u 11223344"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_hf_14b_read_srx(void) {
|
||||
PrintAndLogEx(NORMAL, "Usage: hf 14b sriread [h] <1|2>");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h this help");
|
||||
PrintAndLogEx(NORMAL, " <1|2> 1 = SRIX4K , 2 = SRI512");
|
||||
PrintAndLogEx(NORMAL, "Example:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14b sriread 1"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14b sriread 2"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_hf_14b_write_srx(void) {
|
||||
PrintAndLogEx(NORMAL, "Usage: hf 14b [h] sriwrite <1|2> <block> <data>");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
|
@ -110,21 +48,6 @@ static int usage_hf_14b_write_srx(void) {
|
|||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14b sriwrite 2 FF 11223344"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_hf_14b_dump(void) {
|
||||
PrintAndLogEx(NORMAL, "This command dumps the contents of a ISO-14443-B tag and save it to file\n"
|
||||
"If memory size defaults to SRI4K if auto detect fails.\n"
|
||||
"\n"
|
||||
"Usage: hf 14b dump [h] <f filename> \n"
|
||||
"Options:\n"
|
||||
"\th this help\n"
|
||||
"\tf <name> (optional) filename, if no <name> UID will be used as filename\n"
|
||||
"\n"
|
||||
"Example:\n"
|
||||
_YELLOW_("\thf 14b dump\n")
|
||||
_YELLOW_("\thf 14b dump f mydump")
|
||||
);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int switch_off_field_14b(void) {
|
||||
clearCommandBuffer();
|
||||
|
@ -140,7 +63,7 @@ static uint16_t get_sw(uint8_t *d, uint8_t n) {
|
|||
return d[n] * 0x0100 + d[n + 1];
|
||||
}
|
||||
|
||||
static bool waitCmd14b(bool verbose) {
|
||||
static bool wait_cmd_14b(bool verbose) {
|
||||
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
|
||||
|
@ -161,6 +84,8 @@ static bool waitCmd14b(bool verbose) {
|
|||
(crc) ? _GREEN_("ok") : _RED_("fail")
|
||||
);
|
||||
} else if (len == 0) {
|
||||
if (verbose)
|
||||
PrintAndLogEx(INFO, "no response from tag");
|
||||
} else {
|
||||
PrintAndLogEx(SUCCESS, "len %u | %s", len, sprint_hex(data, len));
|
||||
}
|
||||
|
@ -179,108 +104,132 @@ static int CmdHF14BList(const char *Cmd) {
|
|||
}
|
||||
|
||||
static int CmdHF14BSim(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 'h') return usage_hf_14b_sim();
|
||||
|
||||
uint32_t pupi = 0;
|
||||
if (cmdp == 'u') {
|
||||
pupi = param_get32ex(Cmd, 1, 0, 16);
|
||||
}
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 14b sim",
|
||||
"Simulate a ISO/IEC 14443 type B tag with 4 byte UID / PUPI",
|
||||
"hf 14b sim\n"
|
||||
"hf 14b sim -u 11AA33BB"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("u", "uid", "hex", "4byte UID/PUPI"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
||||
uint8_t pupi[4];
|
||||
int n = 0;
|
||||
CLIParamHexToBuf(arg_get_str(ctx, 1), pupi, sizeof(pupi), &n);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_ISO14443B_SIMULATE, pupi, 0, 0, NULL, 0);
|
||||
SendCommandNG(CMD_HF_ISO14443B_SIMULATE, pupi, sizeof(pupi));
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdHF14BSniff(const char *Cmd) {
|
||||
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 'h') return usage_hf_14b_sniff();
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 14b sniff",
|
||||
"Sniff the communication reader and tag",
|
||||
"hf 14b sniff"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
PacketResponseNG resp;
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_ISO14443B_SNIFF, NULL, 0);
|
||||
|
||||
WaitForResponse(CMD_HF_ISO14443B_SNIFF, &resp);
|
||||
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf 14b list") "` to view captured tracelog");
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save h") "` to save tracelog for later analysing");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdHF14BCmdRaw(const char *Cmd) {
|
||||
bool reply = true, keep_field_on = false, select = false, hasTimeout = false;
|
||||
char buf[5] = "";
|
||||
int i = 0;
|
||||
uint8_t data[PM3_CMD_DATA_SIZE] = {0x00};
|
||||
uint16_t datalen = 0;
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 14b raw",
|
||||
"Sends raw bytes to card ",
|
||||
"hf 14b raw -s -c -k 0200a40400\n"
|
||||
"hf 14b raw --sr -c -k 0200a40400\n"
|
||||
"hf 14b raw --cts -c -k 0200a40400\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("k", "keep", "leave the signal field ON after receive response"),
|
||||
arg_lit0("s", "std", "activate field and select standard card"),
|
||||
arg_lit0(NULL, "sr", "activate field and select SRx ST"),
|
||||
arg_lit0(NULL, "cts", "activate field and select ASK C-ticket"),
|
||||
arg_lit0("c", "crc", "calculate and append CRC"),
|
||||
arg_lit0("r", "noresponse", "do not read response"),
|
||||
arg_int0("t", "timeout", "decimal", "timeout in ms"),
|
||||
arg_lit0("v", "verbose", "verbose"),
|
||||
arg_strx0(NULL, NULL, "<data (hex)>", "bytes to send"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
bool select = false;
|
||||
bool keep_field_on = arg_get_lit(ctx, 1);
|
||||
bool select_std = arg_get_lit(ctx, 2);
|
||||
bool select_sr = arg_get_lit(ctx, 3);
|
||||
bool select_cts = arg_get_lit(ctx, 4);
|
||||
bool add_crc = arg_get_lit(ctx, 5);
|
||||
bool read_reply = !arg_get_lit(ctx, 6);
|
||||
int user_timeout = arg_get_int_def(ctx, 7, -1);
|
||||
bool verbose = arg_get_lit(ctx, 8);
|
||||
|
||||
uint32_t flags = ISO14B_CONNECT;
|
||||
uint32_t temp = 0, user_timeout = 0, time_wait = 0;
|
||||
|
||||
if (strlen(Cmd) < 2) return usage_hf_14b_raw();
|
||||
|
||||
// strip
|
||||
while (*Cmd == ' ' || *Cmd == '\t') ++Cmd;
|
||||
|
||||
while (Cmd[i] != '\0') {
|
||||
if (Cmd[i] == ' ' || Cmd[i] == '\t') { ++i; continue; }
|
||||
if (Cmd[i] == '-') {
|
||||
switch (tolower(Cmd[i + 1])) {
|
||||
case 'h':
|
||||
return usage_hf_14b_raw();
|
||||
case 'r':
|
||||
reply = false;
|
||||
break;
|
||||
case 'c':
|
||||
flags |= ISO14B_APPEND_CRC;
|
||||
break;
|
||||
case 'k':
|
||||
keep_field_on = true;
|
||||
break;
|
||||
case 's':
|
||||
select = true;
|
||||
if (tolower(Cmd[i + 2]) == 's') {
|
||||
flags |= ISO14B_SELECT_SR;
|
||||
++i;
|
||||
} else {
|
||||
flags |= ISO14B_SELECT_STD;
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
hasTimeout = true;
|
||||
sscanf(Cmd + i + 2, "%d", &user_timeout);
|
||||
i += 3;
|
||||
while (Cmd[i] != ' ' && Cmd[i] != '\0') { i++; }
|
||||
i -= 2;
|
||||
break;
|
||||
default:
|
||||
return usage_hf_14b_raw();
|
||||
}
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
if ((Cmd[i] >= '0' && Cmd[i] <= '9') ||
|
||||
(Cmd[i] >= 'a' && Cmd[i] <= 'f') ||
|
||||
(Cmd[i] >= 'A' && Cmd[i] <= 'F')) {
|
||||
buf[strlen(buf) + 1] = 0;
|
||||
buf[strlen(buf)] = Cmd[i];
|
||||
i++;
|
||||
|
||||
if (strlen(buf) >= 2) {
|
||||
sscanf(buf, "%x", &temp);
|
||||
data[datalen++] = (uint8_t)(temp & 0xff);
|
||||
*buf = 0;
|
||||
memset(buf, 0x00, sizeof(buf));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
PrintAndLogEx(WARNING, "unknown parameter '%c'\n", param_getchar(Cmd, i));
|
||||
return PM3_EINVARG;
|
||||
if (add_crc) {
|
||||
flags |= ISO14B_APPEND_CRC;
|
||||
}
|
||||
|
||||
if (hasTimeout) {
|
||||
if (select_std) {
|
||||
select = true;
|
||||
flags |= ISO14B_SELECT_STD;
|
||||
if (verbose)
|
||||
PrintAndLogEx(INFO, "using standard select");
|
||||
} else if (select_sr) {
|
||||
select = true;
|
||||
flags |= ISO14B_SELECT_SR;
|
||||
if (verbose)
|
||||
PrintAndLogEx(INFO, "using SRx ST select");
|
||||
} else if (select_cts) {
|
||||
select = true;
|
||||
flags |= ISO14B_SELECT_CTS;
|
||||
if (verbose)
|
||||
PrintAndLogEx(INFO, "using ASK C-ticket select");
|
||||
}
|
||||
|
||||
uint8_t data[PM3_CMD_DATA_SIZE] = {0x00};
|
||||
int datalen = 0;
|
||||
CLIParamHexToBuf(arg_get_str(ctx, 9), data, sizeof(data), &datalen);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
uint32_t time_wait = 0;
|
||||
if (user_timeout > 0) {
|
||||
|
||||
#define MAX_14B_TIMEOUT 40542464 // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s
|
||||
flags |= ISO14B_SET_TIMEOUT;
|
||||
if (user_timeout > MAX_14B_TIMEOUT) {
|
||||
user_timeout = MAX_14B_TIMEOUT;
|
||||
PrintAndLogEx(INFO, "Set timeout to 40542 seconds (11.26 hours). The max we can wait for response");
|
||||
PrintAndLogEx(INFO, "set timeout to 40542 seconds (11.26 hours). The max we can wait for response");
|
||||
}
|
||||
time_wait = 13560000 / 1000 / (8 * 16) * user_timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
|
||||
if (verbose)
|
||||
PrintAndLogEx(INFO, "using timeout %u", user_timeout);
|
||||
}
|
||||
|
||||
if (keep_field_on == 0)
|
||||
|
@ -294,20 +243,19 @@ static int CmdHF14BCmdRaw(const char *Cmd) {
|
|||
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, flags, datalen, time_wait, data, datalen);
|
||||
|
||||
if (reply == false) {
|
||||
if (read_reply == false) {
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
// get back iso14b_card_select_t, don't print it.
|
||||
if (select) {
|
||||
success = waitCmd14b(false);
|
||||
success = wait_cmd_14b(verbose);
|
||||
}
|
||||
|
||||
// get back response from the raw bytes you sent.
|
||||
if (success && datalen > 0) {
|
||||
waitCmd14b(true);
|
||||
wait_cmd_14b(true);
|
||||
}
|
||||
|
||||
return PM3_SUCCESS;
|
||||
|
@ -400,7 +348,7 @@ static int print_atqb_resp(uint8_t *data, uint8_t cid) {
|
|||
}
|
||||
|
||||
// get SRx chip model (from UID) // from ST Microelectronics
|
||||
static char *get_ST_Chip_Model(uint8_t data) {
|
||||
static char *get_st_chip_model(uint8_t data) {
|
||||
static char model[20];
|
||||
char *retStr = model;
|
||||
memset(model, 0, sizeof(model));
|
||||
|
@ -629,15 +577,26 @@ static void print_st_general_info(uint8_t *data, uint8_t len) {
|
|||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(SwapEndian64(data, 8, 8), len));
|
||||
PrintAndLogEx(SUCCESS, " MFG: %02X, " _YELLOW_("%s"), mfgid, getTagInfo(mfgid));
|
||||
PrintAndLogEx(SUCCESS, "Chip: %02X, " _YELLOW_("%s"), chipid, get_ST_Chip_Model(chipid));
|
||||
PrintAndLogEx(SUCCESS, "Chip: %02X, " _YELLOW_("%s"), chipid, get_st_chip_model(chipid));
|
||||
}
|
||||
|
||||
// iceman, some 14B APDU break down
|
||||
// print UID info from ASK CT chips
|
||||
static void print_ct_general_info(void *vcard) {
|
||||
iso14b_cts_card_select_t card;
|
||||
memcpy(&card, (iso14b_cts_card_select_t *)vcard, sizeof(iso14b_cts_card_select_t));
|
||||
|
||||
uint32_t uid32 = (card.uid[0] |card.uid[1] << 8 |card.uid[2] << 16 | card.uid[3] << 24);
|
||||
PrintAndLogEx(SUCCESS, "ASK C-Ticket");
|
||||
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s") " ( " _YELLOW_("%010u") " )", sprint_hex(card.uid, sizeof(card.uid)), uid32);
|
||||
PrintAndLogEx(SUCCESS, " Product Code: %02X", card.pc);
|
||||
PrintAndLogEx(SUCCESS, " Facility Code: %02X", card.fc);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
}
|
||||
|
||||
// iceman, calypso?
|
||||
// 05 00 00 = find one tag in field
|
||||
// 1d xx xx xx xx 00 08 01 00 = attrib xx=UID (resp 10 [f9 e0])
|
||||
// a3 = ? (resp 03 [e2 c2])
|
||||
// 02 = ? (resp 02 [6a d3])
|
||||
// 022b (resp 02 67 00 [29 5b])
|
||||
// 0200a40400 (resp 02 67 00 [29 5b])
|
||||
// 0200a4040c07a0000002480300 (resp 02 67 00 [29 5b])
|
||||
// 0200a4040c07a0000002480200 (resp 02 67 00 [29 5b])
|
||||
|
@ -646,10 +605,6 @@ static void print_st_general_info(uint8_t *data, uint8_t len) {
|
|||
// 0200a404000cd2760001354b414e4d30310000 (resp 02 6a 82 [4b 4c])
|
||||
// 0200a404000ca000000063504b43532d313500 (resp 02 6a 82 [4b 4c])
|
||||
// 0200a4040010a000000018300301000000000000000000 (resp 02 6a 82 [4b 4c])
|
||||
// 03 = ? (resp 03 [e3 c2])
|
||||
// c2 = ? (resp c2 [66 15])
|
||||
// b2 = ? (resp a3 [e9 67])
|
||||
// a2 = ? (resp 02 [6a d3])
|
||||
|
||||
// 14b get and print Full Info (as much as we know)
|
||||
static bool HF14B_Std_Info(bool verbose) {
|
||||
|
@ -719,14 +674,24 @@ static bool HF14B_ST_Info(bool verbose) {
|
|||
|
||||
// menu command to get and print all info known about any known 14b tag
|
||||
static int CmdHF14Binfo(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 'h') return usage_hf_14b_info();
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 14b info",
|
||||
"Tag information for ISO/IEC 14443 type B based tags",
|
||||
"hf 14b info\n"
|
||||
);
|
||||
|
||||
bool verbose = !(cmdp == 's');
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("v", "verbose", "verbose"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
bool verbose = arg_get_lit(ctx, 1);
|
||||
CLIParserFree(ctx);
|
||||
return infoHF14B(verbose);
|
||||
}
|
||||
|
||||
static bool HF14B_ST_Reader(bool verbose) {
|
||||
static bool HF14B_st_reader(bool verbose) {
|
||||
|
||||
bool is_success = false;
|
||||
|
||||
|
@ -751,22 +716,22 @@ static bool HF14B_ST_Reader(bool verbose) {
|
|||
is_success = true;
|
||||
break;
|
||||
case -1:
|
||||
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail");
|
||||
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ST ATTRIB fail");
|
||||
break;
|
||||
case -2:
|
||||
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail");
|
||||
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ST CRC fail");
|
||||
break;
|
||||
case -3:
|
||||
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 random chip id fail");
|
||||
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ST random chip id fail");
|
||||
break;
|
||||
default:
|
||||
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select SRx failed");
|
||||
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b ST card select SRx failed");
|
||||
break;
|
||||
}
|
||||
return is_success;
|
||||
}
|
||||
|
||||
static bool HF14B_Std_Reader(bool verbose) {
|
||||
static bool HF14B_std_reader(bool verbose) {
|
||||
|
||||
bool is_success = false;
|
||||
|
||||
|
@ -810,8 +775,45 @@ static bool HF14B_Std_Reader(bool verbose) {
|
|||
return is_success;
|
||||
}
|
||||
|
||||
static bool HF14B_ask_ct_reader(bool verbose) {
|
||||
|
||||
bool is_success = false;
|
||||
|
||||
// 14b get and print UID only (general info)
|
||||
clearCommandBuffer();
|
||||
PacketResponseNG resp;
|
||||
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_CTS | ISO14B_DISCONNECT, 0, 0, NULL, 0);
|
||||
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) {
|
||||
if (verbose) PrintAndLogEx(WARNING, "command execution timeout");
|
||||
return false;
|
||||
}
|
||||
|
||||
int status = resp.oldarg[0];
|
||||
|
||||
switch (status) {
|
||||
case 0: {
|
||||
print_ct_general_info(resp.data.asBytes);
|
||||
is_success = true;
|
||||
break;
|
||||
}
|
||||
case -1: {
|
||||
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CTS wrong length");
|
||||
break;
|
||||
}
|
||||
case -2: {
|
||||
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CTS CRC fail");
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b CTS card select failed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return is_success;
|
||||
}
|
||||
|
||||
// test for other 14b type tags (mimic another reader - don't have tags to identify)
|
||||
static bool HF14B_Other_Reader(bool verbose) {
|
||||
static bool HF14B_other_reader(bool verbose) {
|
||||
|
||||
uint8_t data[] = {0x00, 0x0b, 0x3f, 0x80};
|
||||
uint8_t datalen = 4;
|
||||
|
@ -898,9 +900,20 @@ static bool HF14B_Other_Reader(bool verbose) {
|
|||
|
||||
// menu command to get and print general info about all known 14b chips
|
||||
static int CmdHF14BReader(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 'h') return usage_hf_14b_reader();
|
||||
bool verbose = !(cmdp == 's');
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 14b reader",
|
||||
"Act as a 14443B reader to identify a tag",
|
||||
"hf 14b reader\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("v", "verbose", "verbose"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
bool verbose = arg_get_lit(ctx, 1);
|
||||
CLIParserFree(ctx);
|
||||
return readHF14B(verbose);
|
||||
}
|
||||
|
||||
|
@ -909,11 +922,36 @@ static int CmdHF14BReader(const char *Cmd) {
|
|||
* this command just dumps the contents of the memory/
|
||||
*/
|
||||
static int CmdHF14BReadSri(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) < 1 || cmdp == 'h') return usage_hf_14b_read_srx();
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 14b sriread",
|
||||
"Read contents of a SRI512 | SRIX4K tag",
|
||||
"hf 14b sriread\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
iso14b_card_select_t card;
|
||||
if (get_14b_UID(&card) == false) {
|
||||
PrintAndLogEx(WARNING, "no tag found");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t tagtype = param_get8(Cmd, 0);
|
||||
uint8_t blocks = (tagtype == 1) ? 0x7F : 0x0F;
|
||||
if (card.uidlen != 8) {
|
||||
PrintAndLogEx(FAILED, "current dump command only work with SRI4K / SRI512 tags");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
// detect cardsize
|
||||
// 1 = 4096
|
||||
// 2 = 512
|
||||
uint8_t cardtype = get_st_cardsize(card.uid);
|
||||
uint8_t blocks = (cardtype == 1) ? 0x7F : 0x0F;
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_SRI_READ, blocks, 0, 0, NULL, 0);
|
||||
|
@ -991,43 +1029,45 @@ static int CmdHF14BWriteSri(const char *Cmd) {
|
|||
// need to write to file
|
||||
static int CmdHF14BDump(const char *Cmd) {
|
||||
|
||||
uint8_t fileNameLen = 0;
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 14b dump",
|
||||
"This command dumps the contents of a ISO-14443-B tag and save it to file\n"
|
||||
"Tries to autodetect cardtype, memory size defaults to SRI4K",
|
||||
"hf 14b dump\n"
|
||||
"hf 14b dump -f myfilename\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("f", "file", "<filename>", "(optional) filename, if no <name> UID will be used as filename"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
||||
int fnlen = 0;
|
||||
char filename[FILE_PATH_SIZE] = {0};
|
||||
char *fptr = filename;
|
||||
bool errors = false;
|
||||
uint8_t cmdp = 0, cardtype = 1;
|
||||
uint16_t cardsize = 0;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
return usage_hf_14b_dump();
|
||||
case 'f':
|
||||
fileNameLen = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE);
|
||||
cmdp += 2;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Validations
|
||||
if (errors) return usage_hf_14b_dump();
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t*)filename, FILE_PATH_SIZE, &fnlen);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
iso14b_card_select_t card;
|
||||
if (get_14b_UID(&card) == false) {
|
||||
PrintAndLogEx(WARNING, "No tag found.");
|
||||
PrintAndLogEx(WARNING, "no tag found");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
if (card.uidlen != 8) {
|
||||
PrintAndLogEx(FAILED, "current dump command only work with SRI4K / SRI512 tags");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
// detect cardsize
|
||||
// 1 = 4096
|
||||
// 2 = 512
|
||||
cardtype = get_st_cardsize(card.uid);
|
||||
|
||||
uint8_t cardtype = get_st_cardsize(card.uid);
|
||||
uint8_t blocks = 0;
|
||||
uint16_t cardsize = 0;
|
||||
|
||||
switch (cardtype) {
|
||||
case 2:
|
||||
cardsize = (512 / 8) + 4;
|
||||
|
@ -1040,17 +1080,17 @@ static int CmdHF14BDump(const char *Cmd) {
|
|||
break;
|
||||
}
|
||||
|
||||
if (fileNameLen < 1) {
|
||||
PrintAndLogEx(INFO, "Using UID as filename");
|
||||
if (fnlen < 1) {
|
||||
PrintAndLogEx(INFO, "using UID as filename");
|
||||
fptr += sprintf(fptr, "hf-14b-");
|
||||
FillFileNameByUID(fptr, SwapEndian64(card.uid, card.uidlen, 8), "-dump", card.uidlen);
|
||||
}
|
||||
|
||||
uint8_t chipid = get_st_chipid(card.uid);
|
||||
PrintAndLogEx(SUCCESS, "Found a " _GREEN_("%s") " tag", get_ST_Chip_Model(chipid));
|
||||
PrintAndLogEx(SUCCESS, "found a " _GREEN_("%s") " tag", get_st_chip_model(chipid));
|
||||
|
||||
// detect blocksize from card :)
|
||||
PrintAndLogEx(INFO, "Reading memory from tag UID " _GREEN_("%s"), sprint_hex_inrow(SwapEndian64(card.uid, card.uidlen, 8), card.uidlen));
|
||||
PrintAndLogEx(INFO, "reading tag memory from UID " _GREEN_("%s"), sprint_hex_inrow(SwapEndian64(card.uid, card.uidlen, 8), card.uidlen));
|
||||
|
||||
uint8_t data[cardsize];
|
||||
memset(data, 0, sizeof(data));
|
||||
|
@ -1118,7 +1158,7 @@ static int CmdHF14BDump(const char *Cmd) {
|
|||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
if (blocknum != 0xFF) {
|
||||
PrintAndLogEx(FAILED, "Dump failed");
|
||||
PrintAndLogEx(FAILED, "dump failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -1278,14 +1318,20 @@ static int select_card_14443b_4(bool disconnect, iso14b_card_select_t *card) {
|
|||
// Anticollision + SELECT STD card
|
||||
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD, 0, 0, NULL, 0);
|
||||
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) {
|
||||
PrintAndLogEx(INFO, "Trying 14B Select SR");
|
||||
PrintAndLogEx(INFO, "Trying 14B Select SRx");
|
||||
|
||||
// Anticollision + SELECT SR card
|
||||
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR, 0, 0, NULL, 0);
|
||||
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) {
|
||||
PrintAndLogEx(ERR, "connection timeout");
|
||||
switch_off_field_14b();
|
||||
return PM3_ESOFT;
|
||||
PrintAndLogEx(INFO, "Trying 14B Select CTS");
|
||||
|
||||
// Anticollision + SELECT ASK C-Ticket card
|
||||
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_CTS, 0, 0, NULL, 0);
|
||||
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) {
|
||||
PrintAndLogEx(ERR, "connection timeout");
|
||||
switch_off_field_14b();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1737,16 +1783,20 @@ int infoHF14B(bool verbose) {
|
|||
int readHF14B(bool verbose) {
|
||||
|
||||
// try std 14b (atqb)
|
||||
if (HF14B_Std_Reader(verbose))
|
||||
if (HF14B_std_reader(verbose))
|
||||
return 1;
|
||||
|
||||
// try ST Microelectronics 14b
|
||||
if (HF14B_ST_Reader(verbose))
|
||||
if (HF14B_st_reader(verbose))
|
||||
return 1;
|
||||
|
||||
// try ASK CT 14b
|
||||
if (HF14B_ask_ct_reader(verbose))
|
||||
return 1;
|
||||
|
||||
// try unknown 14b read commands (to be identified later)
|
||||
// could be read of calypso, CEPAS, moneo, or pico pass.
|
||||
if (HF14B_Other_Reader(verbose))
|
||||
if (HF14B_other_reader(verbose))
|
||||
return 1;
|
||||
|
||||
if (verbose) PrintAndLogEx(FAILED, "no 14443-B tag found");
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "crc16.h"
|
||||
#include "cmdhf14a.h"
|
||||
#include "protocols.h" // definitions of ISO14B protocol
|
||||
#include "iso14b.h"
|
||||
|
||||
#define TIMEOUT 2000
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "crc16.h"
|
||||
#include "util.h"
|
||||
#include "ui.h"
|
||||
#include "mifare.h" // felica_card_select_t struct
|
||||
#include "iso18.h" // felica_card_select_t struct
|
||||
#include "des.h"
|
||||
#define AddCrc(data, len) compute_crc(CRC_FELICA, (data), (len), (data)+(len)+1, (data)+(len))
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#define CMDHFFELICA_H__
|
||||
|
||||
#include "common.h"
|
||||
#include "mifare.h"
|
||||
#include "iso18.h"
|
||||
|
||||
int CmdHFFelica(const char *Cmd);
|
||||
int readFelicaUid(bool verbose);
|
||||
|
|
153
doc/cliparser.md
Normal file
153
doc/cliparser.md
Normal file
|
@ -0,0 +1,153 @@
|
|||
# Cliparser
|
||||
|
||||
The old style with mixed custom commandline parsing of user parameters or options was messy and confusing. You can find all kinds in the Proxmark3 client.
|
||||
Samples
|
||||
```
|
||||
data xxxx h
|
||||
script run x.lua -h
|
||||
hf 14a raw -h
|
||||
hf 14b raw -ss
|
||||
lf search 1
|
||||
lf config h H
|
||||
```
|
||||
In order to counter this and unify it, there was discussion over at the official repository a few years ago (link to issue) and there it became clear a change is needed. Among the different solutions suggested @merlokk's idea of using the lib cliparser was agreed upon. The lib was adapted and implemented for commands like
|
||||
```
|
||||
emv
|
||||
hf fido
|
||||
```
|
||||
And then it fell into silence since it wasn't well documented how to use the cliparser. Looking at source code wasn't very efficient. However the need of a better cli parsing was still there. Fast forward today, where more commands has used the cliparser but it still wasn't the natural way when adding a new client command to the Proxmark3 client. After more discussions among @doegox, @iceman1001 and @mrwalker the concept became more clear on how to use the cliparser lib in the _preferred_ way. The aftermath was a design and layout specfied which lead to a simpler implemtentation of the cliparser in the client source code while still unfiy all helptexts with the new colours support and a defined layout. As seen below, the simplicity and clearness.
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
## cliparser setup and use
|
||||
|
||||
The parser will format and color and layout as needed.
|
||||
It will also add the `-h --help` option automatic.
|
||||
|
||||
## design comments
|
||||
|
||||
* where possiable all options should be lowercase.
|
||||
* extended options preceeded with -- should be short
|
||||
* options provided directly (without an option identifier) should be avoided.
|
||||
* -vv for extra verbos should be avoided; use of debug level is prefered.
|
||||
* with --options the equal is not needed (will work with and without) so dont use '='
|
||||
e.g. cmd --cn 12345
|
||||
|
||||
|
||||
|
||||
## common options
|
||||
-h --help : help
|
||||
--cn : card number
|
||||
--fn : facility number
|
||||
--q5 : target is lf q5 card
|
||||
--raw : raw data
|
||||
-k --key : key supplied
|
||||
-n --keyno : key number to use
|
||||
-v --verbose : flag when output should provide more information, not conidered debug.
|
||||
-1 --buffer : use the sample buffer
|
||||
|
||||
|
||||
|
||||
## How to implement in source code
|
||||
|
||||
### setup the parser data structure
|
||||
Header file to include
|
||||
|
||||
#include "cliparser.h"
|
||||
|
||||
In the command function, setup the context
|
||||
|
||||
CLIParserContext *ctx;
|
||||
|
||||
|
||||
### define the text
|
||||
CLIParserInit (\<context\>, \<description\>, \<notes\n examples ... \>);
|
||||
|
||||
use -> to seperate example and example comment and \\n to seperate examples.
|
||||
e.g. lf indala clone -r a0000000a0002021 -> this uses .....
|
||||
|
||||
CLIParserInit(&ctx, "lf indala clone",
|
||||
"clone INDALA UID to T55x7 or Q5/T5555 tag",
|
||||
"lf indala clone --heden 888\n"
|
||||
"lf indala clone --fc 123 --cn 1337\n"
|
||||
"lf indala clone -r a0000000a0002021\n"
|
||||
"lf indala clone -l -r 80000001b23523a6c2e31eba3cbee4afb3c6ad1fcf649393928c14e5");
|
||||
|
||||
### define the options
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("l", "long", "optional - long UID 224 bits"),
|
||||
arg_int0("c", "heden", "<decimal>", "Cardnumber for Heden 2L format"),
|
||||
arg_strx0("r", "raw", "<hex>", "raw bytes"),
|
||||
arg_lit0("q", "Q5", "optional - specify writing to Q5/T5555 tag"),
|
||||
arg_int0(NULL, "fc", "<decimal>", "Facility Code (26 bit format)"),
|
||||
arg_int0(NULL, "cn", "<decimal>", "Cardnumber (26 bit format)"),
|
||||
arg_param_end
|
||||
};
|
||||
|
||||
_All options has a parameter index, since `-h --help` is added automatic, it will be assigned index 0.
|
||||
Hence all options you add will start at index 1 and upwards._
|
||||
|
||||
**Notes:**
|
||||
booleen : arg_lit0 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
||||
|
||||
**integer**
|
||||
optional integer : arg_int0 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)\
|
||||
required integer : arg_int1 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
||||
|
||||
**Strings 0 or 1**
|
||||
optional string : arg_str0("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)\
|
||||
required string : arg_str1("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
||||
|
||||
**Strings x to 250**
|
||||
optional string : arg_strx0 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)\
|
||||
required string : arg_strx1 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
||||
|
||||
**if an option does not have a short or long option, use NULL in its place**
|
||||
|
||||
### show the menu
|
||||
CLIExecWithReturn(\<context\>, \<command line to parse\>, \<arg/opt table\>, \<return on error\>);
|
||||
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
### clean up
|
||||
Once you have extracted the options, cleanup the context.
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
||||
### retreiving options
|
||||
**bool option**
|
||||
arg_get_lit(\<context\>, \<opt index\>);
|
||||
|
||||
is_long_uid = arg_get_lit(ctx, 1);
|
||||
|
||||
**int option**
|
||||
arg_get_int_def(\<context\>, \<opt index\>, \<default value\>);
|
||||
|
||||
cardnumber = arg_get_int_def(ctx, 2, -1);
|
||||
|
||||
**hex option**
|
||||
CLIGetHexWithReturn(\<context\>, \<opt index\>, \<store variable\>, \<ptr to stored length\>);
|
||||
?? as an array of uint_8 ??
|
||||
|
||||
uint8_t aid[2] = {0};
|
||||
int aidlen;
|
||||
CLIGetHexWithReturn(ctx, 2, aid, &aidlen);
|
||||
|
||||
**hex option returning ???**
|
||||
|
||||
uint8_t key[24] = {0};
|
||||
int keylen = 0;
|
||||
int res_klen = CLIParamHexToBuf(arg_get_str(ctx, 3), key, 24, &keylen);
|
||||
quick test : seems res_keylen == 0 when ok so not key len ???
|
||||
|
||||
**string option**
|
||||
CLIGetStrWithReturn(\<context\>,\<opt index\>, \<unsigned char \*\>, \<int \*\>);
|
||||
|
||||
uint8_t Buffer[100];
|
||||
int BufLen;
|
||||
CLIGetStrWithReturn(ctx,7, Buffer, &BufLen);
|
||||
|
|
@ -92,7 +92,8 @@ module fpga_hf(
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Attempt to write up how its hooked up. Iceman 2020.
|
||||
Attempt to write up how its hooked up.
|
||||
/ Iceman, 2020
|
||||
|
||||
Communication between ARM / FPGA is done inside armsrc/fpgaloader.c see: function FpgaSendCommand()
|
||||
Send 16 bit command / data pair to FPGA
|
||||
|
@ -108,8 +109,9 @@ module fpga_hf(
|
|||
bit | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
-----+-------------------------------------------
|
||||
cmd | x x x x
|
||||
major| x x x
|
||||
opt | x x x
|
||||
major| x x x
|
||||
opt | x x x x
|
||||
sub | x x
|
||||
divi | x x x x x x x x
|
||||
thres| x x x x x x x x
|
||||
-----+-------------------------------------------
|
||||
|
|
|
@ -100,7 +100,7 @@ module fpga_lf(
|
|||
lf_ed_threshold = 8bits threshold value.
|
||||
|
||||
conf_word 12bits
|
||||
conf_word[7:5] = 3bit major mode.
|
||||
conf_word[8:6] = 3bit major mode.
|
||||
conf_word[0] = 1bit lf_field
|
||||
conf_word[1] = 1bit lf_ed_toggle_mode
|
||||
conf_word[7:0] = 8bit divisor
|
||||
|
@ -110,7 +110,7 @@ module fpga_lf(
|
|||
bit | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
-----+-------------------------------------------
|
||||
cmd | x x x x
|
||||
major| x x x
|
||||
major| x x x
|
||||
opt | x x
|
||||
divi | x x x x x x x x
|
||||
thres| x x x x x x x x
|
||||
|
|
|
@ -39,6 +39,7 @@ wire disabl = mod_type[0];
|
|||
// Most off, oe4 for modulation;
|
||||
// Trying reader emulation (would presumably just require switching power on, but I am not sure)
|
||||
assign pwr_lo = 1'b0;
|
||||
assign pwr_oe2 = 1'b0;
|
||||
|
||||
// 512x64/fc -wait before ts0, 32768 ticks
|
||||
// tslot: 256*64/fc
|
||||
|
@ -339,7 +340,6 @@ end
|
|||
//put modulation here to maintain the correct clock. Seems that some readers are sensitive to that
|
||||
reg pwr_hi;
|
||||
reg pwr_oe1;
|
||||
reg pwr_oe2;
|
||||
reg pwr_oe3;
|
||||
reg pwr_oe4;
|
||||
|
||||
|
@ -351,7 +351,6 @@ begin
|
|||
begin
|
||||
pwr_hi <= ck_1356meg;
|
||||
pwr_oe1 <= 1'b0;//mod;
|
||||
pwr_oe2 <= 1'b0;//mod;
|
||||
pwr_oe3 <= 1'b0;//mod;
|
||||
pwr_oe4 <= mod;//1'b0;
|
||||
end
|
||||
|
@ -359,10 +358,12 @@ begin
|
|||
begin
|
||||
pwr_hi <= 1'b0;
|
||||
pwr_oe1 <= 1'b0;
|
||||
pwr_oe2 <= 1'b0;
|
||||
pwr_oe3 <= 1'b0;
|
||||
pwr_oe4 <= mod;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -540,16 +540,14 @@ begin
|
|||
bit_to_arm = sendbit;
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
assign ssp_din = bit_to_arm;
|
||||
|
||||
// Subcarrier (adc_clk/16, for FPGA_HF_ISO14443A_TAGSIM_MOD only).
|
||||
wire sub_carrier;
|
||||
assign sub_carrier = ~sub_carrier_cnt[3];
|
||||
|
||||
// in FPGA_HF_ISO14443A_READER_MOD: drop carrier for mod_sig_coil==1 (pause); in FPGA_HF_ISO14443A_READER_LISTEN: carrier always on; in other modes: carrier always off
|
||||
// in FPGA_HF_ISO14443A_READER_MOD: drop carrier for mod_sig_coil == 1 (pause);
|
||||
// in FPGA_HF_ISO14443A_READER_LISTEN: carrier always on; in other modes: carrier always off
|
||||
assign pwr_hi = (ck_1356meg & (((mod_type == `FPGA_HF_ISO14443A_READER_MOD) & ~mod_sig_coil) || (mod_type == `FPGA_HF_ISO14443A_READER_LISTEN)));
|
||||
|
||||
|
||||
|
@ -566,7 +564,6 @@ assign pwr_oe4 = mod_sig_coil & sub_carrier & (mod_type == `FPGA_HF_ISO14443A_TA
|
|||
assign pwr_oe2 = 1'b0;
|
||||
assign pwr_lo = 1'b0;
|
||||
|
||||
|
||||
assign dbg = negedge_cnt[3];
|
||||
|
||||
endmodule
|
||||
|
|
43
include/iso14b.h
Normal file
43
include/iso14b.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// (c) 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
// ISO 14443B type prototyping
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _ISO14B_H_
|
||||
#define _ISO14B_H_
|
||||
|
||||
#include "common.h"
|
||||
typedef struct {
|
||||
uint8_t uid[10];
|
||||
uint8_t uidlen;
|
||||
uint8_t atqb[7];
|
||||
uint8_t chipid;
|
||||
uint8_t cid;
|
||||
} PACKED iso14b_card_select_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t uid[4];
|
||||
uint8_t pc;
|
||||
uint8_t fc;
|
||||
} PACKED iso14b_cts_card_select_t;
|
||||
|
||||
typedef enum ISO14B_COMMAND {
|
||||
ISO14B_CONNECT = (1 << 0),
|
||||
ISO14B_DISCONNECT = (1 << 1),
|
||||
ISO14B_APDU = (1 << 2),
|
||||
ISO14B_RAW = (1 << 3),
|
||||
ISO14B_REQUEST_TRIGGER = (1 << 4),
|
||||
ISO14B_APPEND_CRC = (1 << 5),
|
||||
ISO14B_SELECT_STD = (1 << 6),
|
||||
ISO14B_SELECT_SR = (1 << 7),
|
||||
ISO14B_SET_TIMEOUT = (1 << 8),
|
||||
ISO14B_SEND_CHAINING = (1 << 9),
|
||||
ISO14B_SELECT_CTS = (1 << 10),
|
||||
} iso14b_command_t;
|
||||
|
||||
#endif // _ISO14B_H_
|
33
include/iso15.h
Normal file
33
include/iso15.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// (c) 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
// ISO 15693 type prototyping
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _ISO15_H_
|
||||
#define _ISO15_H_
|
||||
|
||||
#include "common.h"
|
||||
typedef struct {
|
||||
uint8_t uid[10];
|
||||
uint8_t uidlen;
|
||||
uint8_t atqb[7];
|
||||
uint8_t chipid;
|
||||
uint8_t cid;
|
||||
} PACKED iso14b_card_select_t;
|
||||
|
||||
typedef enum ISO15_COMMAND {
|
||||
ISO15_CONNECT = (1 << 0),
|
||||
ISO15_NO_DISCONNECT = (1 << 1),
|
||||
ISO15_RAW = (1 << 2),
|
||||
ISO15_APPEND_CRC = (1 << 3),
|
||||
ISO15_HIGH_SPEED = (1 << 4),
|
||||
ISO15_READ_RESPONSE = (1 << 5)
|
||||
} iso15_command_t;
|
||||
|
||||
|
||||
#endif // _ISO15_H_
|
119
include/iso18.h
Normal file
119
include/iso18.h
Normal file
|
@ -0,0 +1,119 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// (c) 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
// ISO 18002 / FeliCa type prototyping
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef _ISO18_H_
|
||||
#define _ISO18_H_
|
||||
|
||||
#include "common.h"
|
||||
|
||||
typedef enum FELICA_COMMAND {
|
||||
FELICA_CONNECT = (1 << 0),
|
||||
FELICA_NO_DISCONNECT = (1 << 1),
|
||||
FELICA_RAW = (1 << 3),
|
||||
FELICA_APPEND_CRC = (1 << 5),
|
||||
FELICA_NO_SELECT = (1 << 6),
|
||||
} felica_command_t;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// FeliCa
|
||||
//-----------------------------------------------------------------------------
|
||||
// IDm = ID manufacturer
|
||||
// mc = manufactureCode
|
||||
// mc1 mc2 u1 u2 u3 u4 u5 u6
|
||||
// PMm = Product manufacturer
|
||||
// icCode =
|
||||
// ic1 = ROM
|
||||
// ic2 = IC
|
||||
// maximum response time =
|
||||
// B3(request service)
|
||||
// B4(request response)
|
||||
// B5(authenticate)
|
||||
// B6(read)
|
||||
// B7(write)
|
||||
// B8()
|
||||
|
||||
// ServiceCode 2bytes (access-rights)
|
||||
// FileSystem = 1 Block = 16 bytes
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t IDm[8];
|
||||
uint8_t code[2];
|
||||
uint8_t uid[6];
|
||||
uint8_t PMm[8];
|
||||
uint8_t iccode[2];
|
||||
uint8_t mrt[6];
|
||||
uint8_t servicecode[2];
|
||||
} PACKED felica_card_select_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t sync[2];
|
||||
uint8_t length[1];
|
||||
uint8_t cmd_code[1];
|
||||
uint8_t IDm[8];
|
||||
} PACKED felica_frame_response_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t status_flag1[1];
|
||||
uint8_t status_flag2[1];
|
||||
} PACKED felica_status_flags_t;
|
||||
|
||||
typedef struct {
|
||||
felica_frame_response_t frame_response;
|
||||
uint8_t node_number[1];
|
||||
uint8_t node_key_versions[2];
|
||||
} PACKED felica_request_service_response_t;
|
||||
|
||||
typedef struct {
|
||||
felica_frame_response_t frame_response;
|
||||
uint8_t mode[1];
|
||||
} PACKED felica_request_request_response_t;
|
||||
|
||||
typedef struct {
|
||||
felica_frame_response_t frame_response;
|
||||
felica_status_flags_t status_flags;
|
||||
uint8_t number_of_block[1];
|
||||
uint8_t block_data[16];
|
||||
uint8_t block_element_number[1];
|
||||
} PACKED felica_read_without_encryption_response_t;
|
||||
|
||||
typedef struct {
|
||||
felica_frame_response_t frame_response;
|
||||
felica_status_flags_t status_flags;
|
||||
} PACKED felica_status_response_t;
|
||||
|
||||
typedef struct {
|
||||
felica_frame_response_t frame_response;
|
||||
uint8_t number_of_systems[1];
|
||||
uint8_t system_code_list[32];
|
||||
} PACKED felica_syscode_response_t;
|
||||
|
||||
typedef struct {
|
||||
felica_frame_response_t frame_response;
|
||||
felica_status_flags_t status_flags;
|
||||
uint8_t format_version[1];
|
||||
uint8_t basic_version[2];
|
||||
uint8_t number_of_option[1];
|
||||
uint8_t option_version_list[4];
|
||||
} PACKED felica_request_spec_response_t;
|
||||
|
||||
typedef struct {
|
||||
felica_frame_response_t frame_response;
|
||||
uint8_t m2c[8];
|
||||
uint8_t m3c[8];
|
||||
} PACKED felica_auth1_response_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t code[1];
|
||||
uint8_t IDtc[8];
|
||||
uint8_t IDi[8];
|
||||
uint8_t PMi[8];
|
||||
} PACKED felica_auth2_response_t;
|
||||
|
||||
#endif // _ISO18_H_
|
150
include/mifare.h
150
include/mifare.h
|
@ -94,40 +94,6 @@ typedef enum {
|
|||
MFDES_ALGO_AES = 4
|
||||
} mifare_des_authalgo_t;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ISO 14443B
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
uint8_t uid[10];
|
||||
uint8_t uidlen;
|
||||
uint8_t atqb[7];
|
||||
uint8_t chipid;
|
||||
uint8_t cid;
|
||||
} PACKED iso14b_card_select_t;
|
||||
|
||||
typedef enum ISO14B_COMMAND {
|
||||
ISO14B_CONNECT = (1 << 0),
|
||||
ISO14B_DISCONNECT = (1 << 1),
|
||||
ISO14B_APDU = (1 << 2),
|
||||
ISO14B_RAW = (1 << 3),
|
||||
ISO14B_REQUEST_TRIGGER = (1 << 4),
|
||||
ISO14B_APPEND_CRC = (1 << 5),
|
||||
ISO14B_SELECT_STD = (1 << 6),
|
||||
ISO14B_SELECT_SR = (1 << 7),
|
||||
ISO14B_SET_TIMEOUT = (1 << 8),
|
||||
ISO14B_SEND_CHAINING = (1 << 9),
|
||||
} iso14b_command_t;
|
||||
|
||||
typedef enum ISO15_COMMAND {
|
||||
ISO15_CONNECT = (1 << 0),
|
||||
ISO15_NO_DISCONNECT = (1 << 1),
|
||||
ISO15_RAW = (1 << 2),
|
||||
ISO15_APPEND_CRC = (1 << 3),
|
||||
ISO15_HIGH_SPEED = (1 << 4),
|
||||
ISO15_READ_RESPONSE = (1 << 5)
|
||||
} iso15_command_t;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// "hf 14a sim x", "hf mf sim x" attacks
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -158,116 +124,14 @@ typedef struct {
|
|||
} PACKED smart_card_atr_t;
|
||||
|
||||
typedef enum SMARTCARD_COMMAND {
|
||||
SC_CONNECT = (1 << 0),
|
||||
SC_NO_DISCONNECT = (1 << 1),
|
||||
SC_RAW = (1 << 2),
|
||||
SC_SELECT = (1 << 3),
|
||||
SC_RAW_T0 = (1 << 4),
|
||||
SC_CLEARLOG = (1 << 5),
|
||||
SC_LOG = (1 << 6),
|
||||
SC_CONNECT = (1 << 0),
|
||||
SC_NO_DISCONNECT = (1 << 1),
|
||||
SC_RAW = (1 << 2),
|
||||
SC_SELECT = (1 << 3),
|
||||
SC_RAW_T0 = (1 << 4),
|
||||
SC_CLEARLOG = (1 << 5),
|
||||
SC_LOG = (1 << 6),
|
||||
} smartcard_command_t;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// FeliCa
|
||||
//-----------------------------------------------------------------------------
|
||||
// IDm = ID manufacturer
|
||||
// mc = manufactureCode
|
||||
// mc1 mc2 u1 u2 u3 u4 u5 u6
|
||||
// PMm = Product manufacturer
|
||||
// icCode =
|
||||
// ic1 = ROM
|
||||
// ic2 = IC
|
||||
// maximum response time =
|
||||
// B3(request service)
|
||||
// B4(request response)
|
||||
// B5(authenticate)
|
||||
// B6(read)
|
||||
// B7(write)
|
||||
// B8()
|
||||
|
||||
// ServiceCode 2bytes (access-rights)
|
||||
// FileSystem = 1 Block = 16 bytes
|
||||
typedef struct {
|
||||
uint8_t IDm[8];
|
||||
uint8_t code[2];
|
||||
uint8_t uid[6];
|
||||
uint8_t PMm[8];
|
||||
uint8_t iccode[2];
|
||||
uint8_t mrt[6];
|
||||
uint8_t servicecode[2];
|
||||
} PACKED felica_card_select_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t sync[2];
|
||||
uint8_t length[1];
|
||||
uint8_t cmd_code[1];
|
||||
uint8_t IDm[8];
|
||||
} PACKED felica_frame_response_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t status_flag1[1];
|
||||
uint8_t status_flag2[1];
|
||||
} PACKED felica_status_flags_t;
|
||||
|
||||
typedef struct {
|
||||
felica_frame_response_t frame_response;
|
||||
uint8_t node_number[1];
|
||||
uint8_t node_key_versions[2];
|
||||
} PACKED felica_request_service_response_t;
|
||||
|
||||
typedef struct {
|
||||
felica_frame_response_t frame_response;
|
||||
uint8_t mode[1];
|
||||
} PACKED felica_request_request_response_t;
|
||||
|
||||
typedef struct {
|
||||
felica_frame_response_t frame_response;
|
||||
felica_status_flags_t status_flags;
|
||||
uint8_t number_of_block[1];
|
||||
uint8_t block_data[16];
|
||||
uint8_t block_element_number[1];
|
||||
} PACKED felica_read_without_encryption_response_t;
|
||||
|
||||
typedef struct {
|
||||
felica_frame_response_t frame_response;
|
||||
felica_status_flags_t status_flags;
|
||||
} PACKED felica_status_response_t;
|
||||
|
||||
typedef struct {
|
||||
felica_frame_response_t frame_response;
|
||||
uint8_t number_of_systems[1];
|
||||
uint8_t system_code_list[32];
|
||||
} PACKED felica_syscode_response_t;
|
||||
|
||||
typedef struct {
|
||||
felica_frame_response_t frame_response;
|
||||
felica_status_flags_t status_flags;
|
||||
uint8_t format_version[1];
|
||||
uint8_t basic_version[2];
|
||||
uint8_t number_of_option[1];
|
||||
uint8_t option_version_list[4];
|
||||
} PACKED felica_request_spec_response_t;
|
||||
|
||||
typedef struct {
|
||||
felica_frame_response_t frame_response;
|
||||
uint8_t m2c[8];
|
||||
uint8_t m3c[8];
|
||||
} PACKED felica_auth1_response_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t code[1];
|
||||
uint8_t IDtc[8];
|
||||
uint8_t IDi[8];
|
||||
uint8_t PMi[8];
|
||||
} PACKED felica_auth2_response_t;
|
||||
|
||||
|
||||
typedef enum FELICA_COMMAND {
|
||||
FELICA_CONNECT = (1 << 0),
|
||||
FELICA_NO_DISCONNECT = (1 << 1),
|
||||
FELICA_RAW = (1 << 3),
|
||||
FELICA_APPEND_CRC = (1 << 5),
|
||||
FELICA_NO_SELECT = (1 << 6),
|
||||
} felica_command_t;
|
||||
|
||||
#endif // _MIFARE_H_
|
||||
|
|
|
@ -247,6 +247,16 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
|
|||
#define ISO14443B_PING 0xBA
|
||||
#define ISO14443B_PONG 0xAB
|
||||
|
||||
// ASK C-ticket
|
||||
#define ASK_REQT 0x10
|
||||
#define ASK_IDENTIFY 0x0F
|
||||
#define ASK_SELECT 0x9F
|
||||
#define ASK_MULTREAD (0x1 << 4) // High nibble
|
||||
#define ASK_UPDATE (0x3 << 4) // High nibble
|
||||
#define ASK_WRITE (0x5 << 4) // High nibble
|
||||
#define ASK_READ (0x6 << 4) // High nibble
|
||||
#define ASK_DESACTIVATE 0xF0
|
||||
|
||||
|
||||
// defined crypto RF commands
|
||||
// only interpreting channel 1 communication
|
||||
|
|
|
@ -64,7 +64,11 @@
|
|||
|
||||
|filename|description|
|
||||
|--------|-----------|
|
||||
|hf_14b_raw_050008_resp.pm3 |Response to `hf 14b raw -c 050008`|
|
||||
|hf_14b_raw_050008_resp.pm3 |Response of 14b card to `hf 14b raw -c 050008`|
|
||||
|hf_14b_raw_0600_st_sri512.pm3 |Response of ST SRI512 to `hf 14b raw -c 0600`|
|
||||
|hf_14b_raw_0600_st_sri512_collision.pm3 |Same but with two cards, showing the collisions in answers|
|
||||
|hf_14b_raw_10_ask_ctx.pm3 |Response of ASK CTx to `hf 14b raw -c 10`|
|
||||
|hf_14b_raw_010fxxxxxxxx_innovatron.pm3 |Response of 14b' card to `hf 14b raw -c -k 010fxxxxxxxx`|
|
||||
|
||||
## HF sniffed traces
|
||||
|
||||
|
|
3072
traces/hf_14b_raw_010fxxxxxxxx_innovatron.pm3
Normal file
3072
traces/hf_14b_raw_010fxxxxxxxx_innovatron.pm3
Normal file
File diff suppressed because it is too large
Load diff
3072
traces/hf_14b_raw_0600_st_sri512.pm3
Normal file
3072
traces/hf_14b_raw_0600_st_sri512.pm3
Normal file
File diff suppressed because it is too large
Load diff
3072
traces/hf_14b_raw_0600_st_sri512_collision.pm3
Normal file
3072
traces/hf_14b_raw_0600_st_sri512_collision.pm3
Normal file
File diff suppressed because it is too large
Load diff
3072
traces/hf_14b_raw_10_ask_ctx.pm3
Normal file
3072
traces/hf_14b_raw_10_ask_ctx.pm3
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue