Merge pull request #2269 from lnv42/master

iso15 sim & sniff improvments & HF_15SIM standalone
This commit is contained in:
Iceman
2024-01-24 16:56:35 +01:00
committed by GitHub
14 changed files with 1010 additions and 375 deletions
+3
View File
@@ -3,6 +3,9 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased]
- Added `HF_15SIM` standalone mode that dump then simulate iso15 tags (@lnv42)
- Changed `iso15 simulation`, reworked, added support for lot of features (@lnv42)
- Changed `hf 15 sniff` quality while low signal (@lnv42)
- Fixed `hf sniff` broken since 17ab86c52 (@nvx)
- Added `--dumpmem` to proxmark3 client for memory dumping to file (@martian01010)
- Changed `hw readmem` to allow larger reads, write to file and better hex viewer (@martian01010)
+4 -1
View File
@@ -80,6 +80,9 @@ define KNOWN_STANDALONE_DEFINITIONS
| HF_15SNIFF | 15693 sniff to flashmem (rdv4) or ram |
| | |
+----------------------------------------------------------+
| HF_15SIM | 15693 tag simulator |
| | |
+----------------------------------------------------------+
| HF_AVEFUL | Mifare ultralight read/simulation |
| | - Ave Ozkal |
+----------------------------------------------------------+
@@ -136,7 +139,7 @@ endef
STANDALONE_MODES := LF_SKELETON
STANDALONE_MODES += LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RSWW LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_MULTIHID LF_NEDAP_SIM LF_NEXID LF_PROXBRUTE LF_PROX2BRUTE LF_SAMYRUN LF_THAREXDE
STANDALONE_MODES += HF_14ASNIFF HF_14BSNIFF HF_15SNIFF HF_AVEFUL HF_BOG HF_CARDHOPPER HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_LEGICSIM HF_MATTYRUN HF_MFCSIM HF_MSDSAL HF_REBLAY HF_TCPRST HF_TMUDFORD HF_UNISNIFF HF_YOUNG
STANDALONE_MODES += HF_14ASNIFF HF_14BSNIFF HF_15SNIFF HF_15SIM HF_AVEFUL HF_BOG HF_CARDHOPPER HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_LEGICSIM HF_MATTYRUN HF_MFCSIM HF_MSDSAL HF_REBLAY HF_TCPRST HF_TMUDFORD HF_UNISNIFF HF_YOUNG
STANDALONE_MODES += DANKARMULTI
STANDALONE_MODES_REQ_BT := HF_CARDHOPPER HF_REBLAY
STANDALONE_MODES_REQ_SMARTCARD :=
+4
View File
@@ -89,6 +89,10 @@ endif
ifneq (,$(findstring WITH_STANDALONE_HF_15SNIFF,$(APP_CFLAGS)))
SRC_STANDALONE = hf_15sniff.c
endif
# WITH_STANDALONE_HF_15SIM
ifneq (,$(findstring WITH_STANDALONE_HF_15SIM,$(APP_CFLAGS)))
SRC_STANDALONE = hf_15sim.c
endif
# WITH_STANDALONE_HF_AVEFUL
ifneq (,$(findstring WITH_STANDALONE_HF_AVEFUL,$(APP_CFLAGS)))
SRC_STANDALONE = hf_aveful.c
+238
View File
@@ -0,0 +1,238 @@
//-----------------------------------------------------------------------------
// Copyright (C) lnv42 2024
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// See LICENSE.txt for the text of the license.
//-----------------------------------------------------------------------------
// Main code for standalone HF/iso15693 Simulation
// This code is trying to dump an iso15 tag, then simulate it
// It doesn't support any password protected/authenticated features
//-----------------------------------------------------------------------------
#include "standalone.h" // standalone definitions
#include "proxmark3_arm.h"
#include "fpgaloader.h"
#include "iso15693.h"
#include "iso15.h"
#include "protocols.h"
#include "iso15693tools.h"
#include "util.h"
#include "spiffs.h"
#include "appmain.h"
#include "dbprint.h"
#include "ticks.h"
#include "BigBuf.h"
#include "crc16.h"
#define AddCrc15(data, len) compute_crc(CRC_15693, (data), (len), (data)+(len), (data)+(len)+1)
//#define CalculateCrc15(data, len) Crc16ex(CRC_15693, (data), (len) + 2);
#define CheckCrc15(data, len) check_crc(CRC_15693, (data), (len))
#define ISO15693_READER_TIMEOUT 330 // 330/212kHz = 1558us
#define HF_15693SIM_LOGFILE "hf_15693sim.trace"
static void DownloadTraceInstructions(void) {
Dbprintf("");
#ifdef WITH_FLASH
Dbprintf("To get the trace from flash and display it:");
Dbprintf("1. mem spiffs dump -s "HF_15693SIM_LOGFILE" -d hf_15693sim.trace");
Dbprintf("2. trace load -f hf_15693sim.trace");
Dbprintf("3. trace list -t 15 -1");
#else
Dbprintf("To get the trace from PM3 memory:");
Dbprintf("trace list -t 15");
#endif
}
void ModInfo(void) {
DbpString(" HF 15693 SIM, a ISO15693 simulator - lnv42");
DownloadTraceInstructions();
}
void RunMod(void) {
StandAloneMode();
Dbprintf(_YELLOW_("HF 15693 SIM started"));
#ifdef WITH_FLASH
rdv40_spiffs_lazy_mount();
#endif
FpgaDownloadAndGo(FPGA_BITSTREAM_HF_15);
iso15_tag_t *tag = (iso15_tag_t*) BigBuf_get_EM_addr();
if (tag == NULL) return;
uint8_t cmd[8] = {0};
int res;
uint16_t recvLen;
uint8_t recv[32];
uint32_t eof_time = 0, start_time;
cmd[0] = ISO15_REQ_DATARATE_HIGH;
cmd[1] = ISO15693_GET_SYSTEM_INFO;
AddCrc15(cmd, 2);
uint8_t i;
LED_B_ON();
Dbprintf("Wait for a dumpable tag");
while (1) {
SpinDelay(200);
LED_B_OFF();
if (BUTTON_HELD(500) > 0)
{
LEDsoff();
Dbprintf("Quiting");
return;
}
start_time = 0;//eof_time;
res = SendDataTag(cmd, 4, true, true, recv, sizeof(recv), start_time, ISO15693_READER_TIMEOUT, &eof_time, &recvLen);
if (res < 0)
continue;
if (recvLen<10) // error: recv too short
{
Dbprintf("recvLen<10");
continue;
}
if (!CheckCrc15(recv,recvLen)) // error crc not valid
{
Dbprintf("crc failed");
continue;
}
if (recv[0] & ISO15_RES_ERROR) // received error from tag
{
Dbprintf("error received");
continue;
}
Dbprintf("Start dumping tag");
memset(tag, 0, sizeof(iso15_tag_t));
memcpy(tag->uid, &recv[2], 8);
i=10;
if (recv[1] & 0x01)
tag->dsfid = recv[i++];
if (recv[1] & 0x02)
tag->afi = recv[i++];
if (recv[1] & 0x04)
{
tag->pagesCount = recv[i++]+1;
tag->bytesPerPage = recv[i++]+1;
}
else
{ // Set default tag values (if can't be readed in SYSINFO)
tag->bytesPerPage = 4;
tag->pagesCount = 128;
}
if (recv[1] & 0x08)
tag->ic = recv[i++];
break;
}
cmd[0] = ISO15_REQ_DATARATE_HIGH | ISO15_REQ_OPTION;
cmd[1] = ISO15693_READBLOCK;
uint8_t blocknum = 0;
int retry;
for (retry = 0; retry < 8; retry++) {
if (blocknum >= tag->pagesCount)
break;
cmd[2] = blocknum;
AddCrc15(cmd, 3);
start_time = eof_time;
res = SendDataTag(cmd, 5, false, true, recv, sizeof(recv), start_time, ISO15693_READER_TIMEOUT, &eof_time, &recvLen);
if (res < 0)
{
SpinDelay(100);
continue;
}
if (recvLen < 4 + tag->bytesPerPage) // error: recv too short
{
Dbprintf("recvLen < 4 + tag->bytesPerPage");
continue;
}
if (!CheckCrc15(recv,recvLen)) // error crc not valid
{
Dbprintf("crc failed");
continue;
}
if (recv[0] & ISO15_RES_ERROR) // received error from tag
{
Dbprintf("error received");
continue;
}
tag->locks[blocknum] = recv[1];
memcpy(&tag->data[blocknum * tag->bytesPerPage], recv + 2, tag->bytesPerPage);
retry = 0;
blocknum++;
}
LEDsoff();
if (retry >= 8)
{
Dbprintf("Max retry attemps exeeded");
Dbprintf("-=[ exit ]=-");
return;
}
Dbprintf("Tag dumped");
Dbprintf("Start simulation");
SimTagIso15693(0, 0);
Dbprintf("Simulation stopped");
SpinDelay(200);
uint32_t trace_len = BigBuf_get_traceLen();
#ifndef WITH_FLASH
// Keep stuff in BigBuf for USB/BT dumping
if (trace_len > 0)
Dbprintf("[!] Trace length (bytes) = %u", trace_len);
#else
// Write stuff to spiffs logfile
if (trace_len > 0) {
Dbprintf("[!] Trace length (bytes) = %u", trace_len);
uint8_t *trace_buffer = BigBuf_get_addr();
if (!exists_in_spiffs(HF_15693SSIM_LOGFILE)) {
rdv40_spiffs_write(
HF_15693SIM_LOGFILE, trace_buffer, trace_len, RDV40_SPIFFS_SAFETY_SAFE);
Dbprintf("[!] Wrote trace to "HF_15693SIM_LOGFILE);
} else {
rdv40_spiffs_append(
HF_15693SIM_LOGFILE, trace_buffer, trace_len, RDV40_SPIFFS_SAFETY_SAFE);
Dbprintf("[!] Appended trace to "HF_15693SIM_LOGFILE);
}
} else {
Dbprintf("[!] Trace buffer is empty, nothing to write!");
}
LED_D_ON();
rdv40_spiffs_lazy_unmount();
LED_D_OFF();
SpinErr(LED_A, 200, 5);
SpinDelay(100);
#endif
Dbprintf("-=[ exit ]=-");
LEDsoff();
DownloadTraceInstructions();
}
+513 -258
View File
File diff suppressed because it is too large Load Diff
+149 -114
View File
@@ -532,15 +532,13 @@ static uint8_t arg_add_default(void *at[]) {
}
static uint16_t arg_get_raw_flag(uint8_t uidlen, bool unaddressed, bool scan, bool add_option) {
uint16_t flags = 0;
if (unaddressed) {
// unaddressed mode may not be supported by all vendors
flags |= (ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY);
;
if (uidlen == 8 || scan || unaddressed) {
flags = (ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY);
}
if (uidlen == 8) {
flags |= (ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS);
}
if (scan) {
flags |= (ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS);
if ((!unaddressed) || scan)
{
flags |= ISO15_REQ_ADDRESS;
}
if (add_option) {
flags |= (ISO15_REQ_OPTION);
@@ -1176,7 +1174,7 @@ static int CmdHF15ELoad(const char *Cmd) {
return res;
}
if (bytes_read > CARD_MEMORY_SIZE) {
if (bytes_read > CARD_MEMORY_SIZE || bytes_read > sizeof(iso15_tag_t)) {
PrintAndLogEx(FAILED, "Memory image too large.");
free(data);
return PM3_EINVARG;
@@ -1232,13 +1230,10 @@ static int CmdHF15ESave(const char *Cmd) {
CLIParserInit(&ctx, "hf 15 esave",
"Save emulator memory into two files (bin/json) ",
"hf 15 esave -f hf-15-01020304"
"hf 15 esave -b 8 -c 42 -f hf-15-01020304"
);
void *argtable[] = {
arg_param_begin,
arg_str1("f", "file", "<fn>", "Specify a filename for dump file"),
arg_int0(NULL, "bsize", "<dec>", "block size (def 4)"),
arg_int0("c", "count", "<dec>", "number of blocks to export (def all)"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
@@ -1246,20 +1241,9 @@ static int CmdHF15ESave(const char *Cmd) {
int fnlen = 0;
char filename[FILE_PATH_SIZE];
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
int blocksize = arg_get_int_def(ctx, 2, 4);
int count = arg_get_int_def(ctx, 3, -1);
CLIParserFree(ctx);
// sanity checks
if (blocksize < 4) {
PrintAndLogEx(WARNING, "Blocksize too small, using default 4 bytes");
blocksize = 4;
}
int bytes = CARD_MEMORY_SIZE;
if (count > 0 && count * blocksize <= bytes) {
bytes = count * blocksize;
}
int bytes = sizeof(iso15_tag_t);
// reserve memory
uint8_t *dump = calloc(bytes, sizeof(uint8_t));
@@ -1275,11 +1259,7 @@ static int CmdHF15ESave(const char *Cmd) {
return PM3_ETIMEOUT;
}
if (blocksize == 8) {
pm3_save_dump(filename, dump, bytes, jsf15_v3);
} else {
pm3_save_dump(filename, dump, bytes, jsf15_v2);
}
pm3_save_dump(filename, dump, bytes, jsf15_v4);
free(dump);
return PM3_SUCCESS;
@@ -1297,6 +1277,13 @@ static void print_blocks_15693(uint8_t *data, uint16_t bytes, int blocksize, boo
PrintAndLogEx(INFO, "----------- " _CYAN_("Tag Memory") " ---------------");
PrintAndLogEx(NORMAL, "");
if (blocksize == 0 || bytes == 0)
{
PrintAndLogEx(INFO, "Tag is empty!");
return;
}
print_hrule(blocksize);
char spaces[] = " ";
@@ -1354,38 +1341,46 @@ static void print_blocks_15693(uint8_t *data, uint16_t bytes, int blocksize, boo
PrintAndLogEx(NORMAL, "");
}
static void print_emltag_info_15693(iso15_tag_t *tag) {
PrintAndLogEx(SUCCESS, " TYPE... " _YELLOW_("%s"), getTagInfo_15(tag->uid));
PrintAndLogEx(SUCCESS, " UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, tag->uid));
PrintAndLogEx(SUCCESS, " - DSFID [0x%02X]", tag->dsfid);
PrintAndLogEx(SUCCESS, " - AFI [0x%02X]", tag->afi);
PrintAndLogEx(SUCCESS, " - IC reference [0x%02X]", tag->ic);
PrintAndLogEx(SUCCESS, " - Tag memory layout");
PrintAndLogEx(SUCCESS, " %u bytes/blocks x %u blocks", tag->bytesPerPage, tag->pagesCount);
}
static void print_emltag_15693(iso15_tag_t *tag, bool dense_output) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Emulator Tag Information") " ---------------------------");
print_emltag_info_15693(tag);
print_blocks_15693(tag->data, (tag->pagesCount * tag->bytesPerPage),
tag->bytesPerPage, dense_output);
}
static int CmdHF15EView(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 15 eview",
"It displays emulator memory",
"hf 15 eview\n"
"hf 15 eview -b 8 -c 60\n"
"hf 15 eview -z\n"
);
void *argtable[] = {
arg_param_begin,
arg_int0("b", "blocksize", "<dec>", "block size (def 4)"),
arg_int0("c", "count", "<dec>", "number of blocks to display (def all)"),
arg_lit0("z", "dense", "dense dump output style"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
int blocksize = arg_get_int_def(ctx, 1, 4);
int count = arg_get_int_def(ctx, 2, -1);
bool dense_output = (g_session.dense_output || arg_get_lit(ctx, 3));
bool dense_output = (g_session.dense_output || arg_get_lit(ctx, 1));
CLIParserFree(ctx);
// santity checks
if (blocksize < 4) {
PrintAndLogEx(WARNING, "Blocksize too small, using default 4 bytes");
blocksize = 4;
}
int bytes = CARD_MEMORY_SIZE;
if (count > 0 && count * blocksize <= bytes) {
bytes = count * blocksize;
}
int bytes = sizeof(iso15_tag_t);
// reserve memory
uint8_t *dump = calloc(bytes, sizeof(uint8_t));
if (dump == NULL) {
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
@@ -1399,7 +1394,8 @@ static int CmdHF15EView(const char *Cmd) {
return PM3_ETIMEOUT;
}
print_blocks_15693(dump, bytes, blocksize, dense_output);
print_emltag_15693((iso15_tag_t *)dump, dense_output);
free(dump);
return PM3_SUCCESS;
}
@@ -1411,39 +1407,49 @@ static int CmdHF15Sim(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 15 sim",
"Simulate a ISO-15693 tag\n",
"hf 15 sim\n"
"hf 15 sim -u E011223344556677");
void *argtable[] = {
arg_param_begin,
arg_str1("u", "uid", "<hex>", "UID, 8 hex bytes"),
arg_str0("u", "uid", "<hex>", "UID, 8 hex bytes"),
arg_int0("b", "blocksize", "<dec>", "block size (def 4)"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
CLIExecWithReturn(ctx, Cmd, argtable, true);
struct {
uint8_t uid[HF15_UID_LENGTH];
uint8_t block_size;
} PACKED payload;
memset(&payload, 0, sizeof(payload));
int uidlen = 0;
CLIGetHexWithReturn(ctx, 1, payload.uid, &uidlen);
if (uidlen != HF15_UID_LENGTH) {
if (uidlen != 0 && uidlen != HF15_UID_LENGTH) {
PrintAndLogEx(WARNING, "UID must include 8 hex bytes");
CLIParserFree(ctx);
return PM3_EINVARG;
}
payload.block_size = arg_get_int_def(ctx, 2, 4);
CLIParserFree(ctx);
// santity checks
if (payload.block_size < 4) {
PrintAndLogEx(WARNING, "Blocksize too small, using default 4 bytes");
payload.block_size = 4;
}
if (uidlen == 0) // get UID from emulator
{
// reserve memory
iso15_tag_t *tag = calloc(1, sizeof(iso15_tag_t));
if (tag == NULL) {
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
return PM3_EMALLOC;
}
PrintAndLogEx(SUCCESS, "Starting simulating UID " _YELLOW_("%s"), iso15693_sprintUID(NULL, payload.uid));
if (GetFromDevice(BIG_BUF_EML, (uint8_t*)tag, sizeof(iso15_tag_t), 0, NULL, 0, NULL, 2500, false) == false) {
PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
free(tag);
return PM3_ETIMEOUT;
}
PrintAndLogEx(SUCCESS, "Starting simulating UID " _YELLOW_("%s"), iso15693_sprintUID(NULL, tag->uid));
free(tag);
}
PrintAndLogEx(INFO, "Press " _YELLOW_("`pm3-button`") " to abort simulation");
PacketResponseNG resp;
@@ -1723,8 +1729,8 @@ static int CmdHF15Dump(const char *Cmd) {
uint8_t arglen = arg_add_default(argtable);
argtable[arglen++] = arg_str0("f", "file", "<fn>", "Specify a filename for dump file"),
argtable[arglen++] = arg_int0(NULL, "bs", "<dec>", "block size (def 4)"),
argtable[arglen++] = arg_lit0(NULL, "ns", "no save to file"),
argtable[arglen++] = arg_lit0("v", "verbose", "verbose output");
argtable[arglen++] = arg_lit0(NULL, "ns", "no save to file"),
argtable[arglen++] = arg_lit0("v", "verbose", "verbose output");
argtable[arglen++] = arg_param_end;
CLIExecWithReturn(ctx, Cmd, argtable, true);
@@ -1748,7 +1754,7 @@ static int CmdHF15Dump(const char *Cmd) {
CLIParserFree(ctx);
// sanity checks
if ((scan + unaddressed + uidlen) > 1) {
if ((scan + unaddressed + (uidlen > 0)) > 1) {
PrintAndLogEx(WARNING, "Select only one option /scan/unaddress/uid");
return PM3_EINVARG;
}
@@ -1759,8 +1765,7 @@ static int CmdHF15Dump(const char *Cmd) {
}
// default fallback to scan for tag.
// overriding unaddress parameter :)
if (uidlen != HF15_UID_LENGTH) {
if (uidlen != HF15_UID_LENGTH && !unaddressed) {
scan = true;
}
@@ -1772,9 +1777,16 @@ static int CmdHF15Dump(const char *Cmd) {
return PM3_EMALLOC;
}
iso15_tag_t *tag = (iso15_tag_t *)calloc(1, sizeof(iso15_tag_t));
if (tag == NULL) {
PrintAndLogEx(FAILED, "failed to allocate memory");
return PM3_EMALLOC;
};
// ISO15693 Protocol params
packet->raw[packet->rawlen++] = arg_get_raw_flag(uidlen, unaddressed, scan, add_option);
packet->raw[packet->rawlen++] = ISO15693_READBLOCK;
packet->raw[packet->rawlen++] = ISO15693_GET_SYSTEM_INFO;
bool used_uid = false;
if (unaddressed == false) {
@@ -1796,9 +1808,8 @@ static int CmdHF15Dump(const char *Cmd) {
PrintAndLogEx(SUCCESS, "Using unaddressed mode");
}
if (verbose) {
PrintAndLogEx(INFO, "Using block size... " _YELLOW_("%d"), blocksize);
}
AddCrc15(packet->raw, packet->rawlen);
packet->rawlen += 2;
// PM3 params
packet->flags = (ISO15_CONNECT | ISO15_READ_RESPONSE | ISO15_NO_DISCONNECT);
@@ -1806,31 +1817,69 @@ static int CmdHF15Dump(const char *Cmd) {
packet->flags |= ISO15_HIGH_SPEED;
}
// add CRC length (2) to packet and blockno (1)
packet->rawlen += 3;
clearCommandBuffer();
SendCommandNG(CMD_HF_ISO15693_COMMAND, (uint8_t *)packet, ISO15_RAW_LEN(packet->rawlen));
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_HF_ISO15693_COMMAND, &resp, 2000) == false) {
PrintAndLogEx(DEBUG, "iso15693 timeout");
return PM3_ETIMEOUT;
}
if (resp.status == PM3_ETEAROFF) {
return resp.status;
}
if (resp.length < 2) {
PrintAndLogEx(WARNING, "iso15693 card doesn't answer to systeminfo command (%d)", resp.length);
PrintAndLogEx(WARNING, "%%d)", resp.length);
return PM3_EWRONGANSWER;
}
uint8_t *d = resp.data.asBytes;
uint8_t dCpt = 10;
ISO15_ERROR_HANDLING_CARD_RESPONSE(d, resp.length);
memcpy(tag->uid, &d[2], 8);
if (d[1] & 0x01)
tag->dsfid = d[dCpt++];
if (d[1] & 0x02)
tag->afi = d[dCpt++];
if (d[1] & 0x04)
{
tag->pagesCount = d[dCpt++]+1;
tag->bytesPerPage = d[dCpt++]+1;
}
else
{ // Set tag memory layout values (if can't be readed in SYSINFO)
tag->bytesPerPage = blocksize;
tag->pagesCount = 128;
}
if (d[1] & 0x08)
tag->ic = d[dCpt++];
if (verbose)
{
print_emltag_info_15693(tag);
}
// add lenght for blockno (1)
packet->rawlen++;
packet->raw[0] |= ISO15_REQ_OPTION; // Add option to dump lock status
packet->raw[1] = ISO15693_READBLOCK;
packet->flags = (ISO15_READ_RESPONSE | ISO15_NO_DISCONNECT);
if (fast) {
packet->flags |= ISO15_HIGH_SPEED;
}
PrintAndLogEx(SUCCESS, "Reading memory");
int blocknum = 0;
// memory.
t15memory_t mem[256];
uint8_t data[256 * 4];
memset(data, 0, sizeof(data));
// keep track of which block length tag returned?
uint8_t blklen = blocksize;
for (int retry = 0; (retry < 2 && blocknum < 0x100); retry++) {
if (blocknum > 0) {
packet->flags = (ISO15_READ_RESPONSE | ISO15_NO_DISCONNECT);
if (fast) {
packet->flags |= ISO15_HIGH_SPEED;
}
}
for (int retry = 0; (retry < 2 && blocknum < tag->pagesCount); retry++) {
if (used_uid) {
packet->raw[10] = (uint8_t)blocknum & 0xFF;
AddCrc15(packet->raw, 11);
@@ -1841,7 +1890,7 @@ static int CmdHF15Dump(const char *Cmd) {
clearCommandBuffer();
SendCommandNG(CMD_HF_ISO15693_COMMAND, (uint8_t *)packet, ISO15_RAW_LEN(packet->rawlen));
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_HF_ISO15693_COMMAND, &resp, 2000)) {
if (resp.length < 2) {
@@ -1850,7 +1899,7 @@ static int CmdHF15Dump(const char *Cmd) {
continue;
}
uint8_t *d = resp.data.asBytes;
d = resp.data.asBytes;
if (CheckCrc15(d, resp.length) == false) {
PrintAndLogEx(NORMAL, "");
@@ -1870,21 +1919,10 @@ static int CmdHF15Dump(const char *Cmd) {
break;
}
// is tag responding with 4 or 8 bytes?
if (resp.length > 8) {
blklen = 8;
}
uint8_t offset = 0;
if (add_option) {
offset = 1;
}
// lock byte value
mem[blocknum].lock = d[0 + offset];
tag->locks[blocknum] = d[1];
// copy read data
memcpy(mem[blocknum].block, d + 1 + offset, blklen);
memcpy(data + (blocknum * 4), d + 1 + offset, 4);
memcpy(&tag->data[blocknum * tag->bytesPerPage], d + 2, tag->bytesPerPage);
retry = 0;
blocknum++;
@@ -1896,9 +1934,9 @@ static int CmdHF15Dump(const char *Cmd) {
free(packet);
DropField();
if (blklen != blocksize) {
if (tag->bytesPerPage != blocksize) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, _YELLOW_("%u") " byte block length detected, called with " _YELLOW_("%d"), blklen, blocksize);
PrintAndLogEx(INFO, _YELLOW_("%u") " byte block length detected, called with " _YELLOW_("%d"), tag->bytesPerPage, blocksize);
}
PrintAndLogEx(NORMAL, "");
@@ -1910,18 +1948,18 @@ static int CmdHF15Dump(const char *Cmd) {
for (int i = 0; i < blocknum; i++) {
char lck[16] = {0};
if (mem[i].lock) {
snprintf(lck, sizeof(lck), _RED_("%d"), mem[i].lock);
if (tag->locks[i]) {
snprintf(lck, sizeof(lck), _RED_("%d"), tag->locks[i]);
} else {
snprintf(lck, sizeof(lck), "%d", mem[i].lock);
snprintf(lck, sizeof(lck), "%d", tag->locks[i]);
}
PrintAndLogEx(INFO, "%3d/0x%02X | %s| %s | %s"
, i
, i
, sprint_hex(mem[i].block, blklen)
, sprint_hex(&tag->data[i*tag->bytesPerPage], tag->bytesPerPage)
, lck
, sprint_ascii(mem[i].block, blklen)
, sprint_ascii(&tag->data[i*tag->bytesPerPage], tag->bytesPerPage)
);
}
PrintAndLogEx(INFO, "---------+-------------+---+-------");
@@ -1941,11 +1979,8 @@ static int CmdHF15Dump(const char *Cmd) {
FillFileNameByUID(fptr, SwapEndian64(uid, sizeof(uid), 8), "-dump", sizeof(uid));
}
if (blklen == 8) {
pm3_save_dump(filename, data, (size_t)(blocknum * blklen), jsf15_v3);
} else {
pm3_save_dump(filename, data, (size_t)(blocknum * blklen), jsf15_v2);
}
pm3_save_dump(filename, (uint8_t*)tag, sizeof(iso15_tag_t), jsf15_v4);
return PM3_SUCCESS;
}
+63
View File
@@ -28,6 +28,7 @@
#include "util.h"
#include "cmdhficlass.h" // pagemap
#include "iclass_cmd.h"
#include "iso15.h"
#ifdef _WIN32
#include "scandir.h"
@@ -518,6 +519,33 @@ int saveFileJSONex(const char *preferredName, JSONFileType ftype, uint8_t *data,
}
break;
}
// handles ISO15693 in iso15_tag_t format
case jsf15_v4: {
JsonSaveStr(root, "FileType", "15693 v4");
iso15_tag_t *tag = (iso15_tag_t *)data;
JsonSaveBufAsHexCompact(root, "$.Card.uid", tag->uid, 8);
JsonSaveBufAsHexCompact(root, "$.Card.dsfid", &tag->dsfid, 1);
JsonSaveBufAsHexCompact(root, "$.Card.dsfidLock", (uint8_t*)&tag->dsfidLock, 1);
JsonSaveBufAsHexCompact(root, "$.Card.afi", &tag->afi, 1);
JsonSaveBufAsHexCompact(root, "$.Card.afiLock", (uint8_t*)&tag->afiLock, 1);
JsonSaveBufAsHexCompact(root, "$.Card.bytesPerPage", &tag->bytesPerPage, 1);
JsonSaveBufAsHexCompact(root, "$.Card.pagesCount", &tag->pagesCount, 1);
JsonSaveBufAsHexCompact(root, "$.Card.IC", &tag->ic, 1);
JsonSaveBufAsHexCompact(root, "$.Card.locks", tag->locks, tag->pagesCount);
JsonSaveBufAsHexCompact(root, "$.Card.random", tag->random, 2);
JsonSaveBufAsHexCompact(root, "$.Card.privacyPasswd", tag->privacyPasswd, 4);
JsonSaveBufAsHexCompact(root, "$.Card.state", (uint8_t*)&tag->state, 1);
for (size_t i = 0 ; i < tag->pagesCount ; i++) {
if (((i+1) * tag->bytesPerPage) > ISO15693_TAG_MAX_SIZE)
break;
snprintf(path, sizeof(path), "$.blocks.%zu", i);
JsonSaveBufAsHexCompact(root, path,
&tag->data[i * tag->bytesPerPage],
tag->bytesPerPage);
}
break;
}
case jsfLegic_v2: {
JsonSaveStr(root, "FileType", "legic v2");
JsonSaveBufAsHexCompact(root, "$.Card.UID", data, 4);
@@ -1673,6 +1701,41 @@ int loadFileJSONex(const char *preferredName, void *data, size_t maxdatalen, siz
goto out;
}
if (!strcmp(ctype, "15693 v4")) {
iso15_tag_t *tag = (iso15_tag_t *)udata.bytes;
JsonLoadBufAsHex(root, "$.Card.UID", tag->uid, 8, datalen);
JsonLoadBufAsHex(root, "$.Card.dsfid", &tag->dsfid, 1, datalen);
JsonLoadBufAsHex(root, "$.Card.dsfidLock", (uint8_t*)&tag->dsfidLock, 1, datalen);
JsonLoadBufAsHex(root, "$.Card.afi", &tag->afi, 1, datalen);
JsonLoadBufAsHex(root, "$.Card.afiLock", (uint8_t*)&tag->afiLock, 1, datalen);
JsonLoadBufAsHex(root, "$.Card.bytesPerPage", &tag->bytesPerPage, 1, datalen);
JsonLoadBufAsHex(root, "$.Card.pagesCount", &tag->pagesCount, 1, datalen);
JsonLoadBufAsHex(root, "$.Card.IC", &tag->ic, 1, datalen);
JsonLoadBufAsHex(root, "$.Card.locks", tag->locks, tag->pagesCount, datalen);
JsonLoadBufAsHex(root, "$.Card.random", tag->random, 2, datalen);
JsonLoadBufAsHex(root, "$.Card.privacyPasswd", tag->privacyPasswd, 4, datalen);
JsonLoadBufAsHex(root, "$.Card.state", (uint8_t*)&tag->state, 1, datalen);
size_t sptr = 0;
for (int i = 0; i < tag->pagesCount ; i++) {
if (((i+1) * tag->bytesPerPage) > ISO15693_TAG_MAX_SIZE) {
PrintAndLogEx(ERR, "loadFileJSONex: maxdatalen=%zu (%04zx) block (i)=%4d (%04x) sptr=%zu (%04zx) -- exceeded maxdatalen", maxdatalen, maxdatalen, i, i, sptr, sptr);
retval = PM3_EMALLOC;
goto out;
}
snprintf(blocks, sizeof(blocks), "$.blocks.%d", i);
JsonLoadBufAsHex(root, blocks, &tag->data[sptr], tag->bytesPerPage, &len);
if (load_file_sanity(ctype, tag->bytesPerPage, i, len) == false) {
break;
}
sptr += len;
}
*datalen = sptr;
goto out;
}
if (!strcmp(ctype, "legic v2")) {
size_t sptr = 0;
for (int i = 0; i < 64; i++) {
+1
View File
@@ -55,6 +55,7 @@ typedef enum {
jsf15,
jsf15_v2,
jsf15_v3,
jsf15_v4,
jsfLegic,
jsfLegic_v2,
jsfT55x7,
@@ -127,6 +127,7 @@ Here are the supported values you can assign to `STANDALONE` in `Makefile.platfo
| HF_14ASNIFF | 14a sniff storing to flashmem - Micolous
| HF_14BSNIFF | 14b sniff - jacopo-j
| HF_15SNIFF | 15693 sniff storing to flashmem - Glaser
| HF_15SNIFF | 15693 simulator - lnv42
| HF_AVEFUL | MIFARE Ultralight read/simulation - Ave Ozkal
| HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth storing in flashmem - Bogito
| HF_CARDHOPPER | Long distance (over IP) relay of 14a protocols - Sam Haskins
+1 -1
View File
@@ -67,7 +67,7 @@ TARGET1_OPTIONS = -define \{WITH_LF WITH_LF0 WITH_LF1 WITH_LF2 WITH_LF3\}
# RDV40/Generic - Enable all HF modules except Felica
TARGET2_OPTIONS = -define \{WITH_HF0 WITH_HF1 WITH_HF2 WITH_HF3 WITH_HF5\}
# RDV40/Generic - Enable all HF modules except Felica and ISO14443, select HF_15 instead of HF
TARGET3_OPTIONS = -define \{WITH_HF0 WITH_HF1 WITH_HF3 WITH_HF5 WITH_HF_15\}
TARGET3_OPTIONS = -define \{WITH_HF0 WITH_HF1 WITH_HF3 WITH_HF5 WITH_HF_15 WITH_HF_15_LOWSIGNAL\}
# RDV40/Generic - Enable all HF modules except ISO14443
TARGET4_OPTIONS = -define \{WITH_HF0 WITH_HF1 WITH_HF3 WITH_HF4 WITH_HF5\}
# ICOPYX
Binary file not shown.
+5
View File
@@ -44,8 +44,13 @@ reg after_hysteresis, after_hysteresis_prev, after_hysteresis_prev_prev;
reg [11:0] has_been_low_for;
always @(negedge adc_clk)
begin
`ifdef WITH_HF_15_LOWSIGNAL
if (& adc_d[7:4]) after_hysteresis <= 1'b1;
else if (~(| adc_d[7:6])) after_hysteresis <= 1'b0;
`else
if (& adc_d[7:0]) after_hysteresis <= 1'b1;
else if (~(| adc_d[7:0])) after_hysteresis <= 1'b0;
`endif
if (after_hysteresis)
begin
+27
View File
@@ -44,4 +44,31 @@ typedef struct {
uint8_t raw[]; // First byte in raw, raw[0] is ISO15693 protocol flag byte
} PACKED iso15_raw_cmd_t;
#define ISO15693_TAG_MAX_PAGES 64 // in page
#define ISO15693_TAG_MAX_SIZE 2048 // in byte (64 pages of 256 bits)
typedef struct {
uint8_t uid[8];
uint8_t dsfid;
bool dsfidLock;
uint8_t afi;
bool afiLock;
uint8_t bytesPerPage;
uint8_t pagesCount;
uint8_t ic;
uint8_t locks[ISO15693_TAG_MAX_PAGES];
uint8_t data[ISO15693_TAG_MAX_SIZE];
uint8_t random[2];
uint8_t privacyPasswd[4];
enum {
TAG_STATE_NO_FIELD,
TAG_STATE_READY,
TAG_STATE_ACTIVATED, // useless ?
TAG_STATE_SELECTED,
TAG_STATE_SILENCED
} state;
bool expectFast;
bool expectFsk;
} PACKED iso15_tag_t;
#endif // _ISO15_H_
+1 -1
View File
@@ -32,7 +32,7 @@ mv bootrom/obj/bootrom.elf "$DEST/PM3BOOTROM.elf"
# cf armsrc/Standalone/Makefile.hal
STANDALONE_MODES=(LF_SKELETON)
STANDALONE_MODES+=(LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RSWW LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_MULTIHID LF_NEDAP_SIM LF_NEXID LF_PROXBRUTE LF_PROX2BRUTE LF_SAMYRUN LF_THAREXDE)
STANDALONE_MODES+=(HF_14ASNIFF HF_14BSNIFF HF_15SNIFF HF_AVEFUL HF_BOG HF_CARDHOPPER HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_LEGICSIM HF_MATTYRUN HF_MFCSIM HF_MSDSAL HF_REBLAY HF_TCPRST HF_TMUDFORD HF_UNISNIFF HF_YOUNG)
STANDALONE_MODES+=(HF_14ASNIFF HF_14BSNIFF HF_15SNIFF HF_15SIM HF_AVEFUL HF_BOG HF_CARDHOPPER HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_LEGICSIM HF_MATTYRUN HF_MFCSIM HF_MSDSAL HF_REBLAY HF_TCPRST HF_TMUDFORD HF_UNISNIFF HF_YOUNG)
STANDALONE_MODES+=(DANKARMULTI)
STANDALONE_MODES_REQ_BT=(HF_CARDHOPPER HF_REBLAY)
STANDALONE_MODES_REQ_SMARTCARD=()