mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-14 10:37:23 -07:00
Merge pull request #6 from RfidResearchGroup/master
Update from upstream.
This commit is contained in:
commit
8d2021e0cb
96 changed files with 112808 additions and 2561 deletions
55
.vscode/launch.json
vendored
Normal file
55
.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "(gdb) Attach",
|
||||
"type": "cppdbg",
|
||||
"request": "attach",
|
||||
"program": "${cwd}/client/proxmark3",
|
||||
//"processId": "${command:pickProcess}",
|
||||
"processId": "${input:ProcessID}",
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
},{
|
||||
"name": "(gdb) Build & Launch",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${cwd}/client/proxmark3",
|
||||
"args": ["/dev/ttyACM0"],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
],
|
||||
"preLaunchTask": "client: Debug: clean & make",
|
||||
"miDebuggerPath": "/usr/bin/gdb"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
// Using Extension "Tasks Shell Input" https://marketplace.visualstudio.com/items?itemName=augustocdias.tasks-shell-input
|
||||
"id": "ProcessID",
|
||||
"type": "command",
|
||||
"command": "shellCommand.execute",
|
||||
"args": {
|
||||
"command": "pgrep -n proxmark3",
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
72
.vscode/tasks.json
vendored
72
.vscode/tasks.json
vendored
|
@ -4,24 +4,82 @@
|
|||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "build",
|
||||
"label": "all: Make & run",
|
||||
"type": "shell",
|
||||
"command": "make clean && make all -j$(nproc --all)",
|
||||
"command": "make -j && ./pm3",
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
]
|
||||
],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "flash fullimage",
|
||||
"label": "choose: Make",
|
||||
"type": "shell",
|
||||
"command": "sudo ./pm3-flash-fullimage",
|
||||
"command": "make ${input:componentType} -j",
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
],
|
||||
"group": "build",
|
||||
},
|
||||
{
|
||||
"label": "client: Debug: make",
|
||||
"type": "shell",
|
||||
"command": "make client -j DEBUG=1",
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
],
|
||||
"group": "build",
|
||||
},
|
||||
{
|
||||
"label": "client: Debug: clean & make",
|
||||
"type": "shell",
|
||||
"command": "make client/clean && make client -j DEBUG=1",
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
],
|
||||
"group": "build",
|
||||
},
|
||||
{
|
||||
"label": "fullimage: Make & Flash",
|
||||
"type": "shell",
|
||||
"command": "make fullimage && ./pm3-flash-fullimage",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "FLASH BOOTROM",
|
||||
"label": "BOOTROM: Make & Flash",
|
||||
"type": "shell",
|
||||
"command": "sudo ./pm3-flash-bootrom",
|
||||
"command": "make bootrom && ./pm3-flash-bootrom",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Run client",
|
||||
"type": "shell",
|
||||
"command": "./pm3",
|
||||
"problemMatcher": []
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"type": "pickString",
|
||||
"id": "componentType",
|
||||
"description": "What Makefile target do you want to execute?",
|
||||
"options": [
|
||||
"all",
|
||||
"client",
|
||||
"bootrom",
|
||||
"fullimage",
|
||||
"recovery",
|
||||
"clean",
|
||||
"install",
|
||||
"uninstall",
|
||||
"style",
|
||||
"miscchecks",
|
||||
"check",
|
||||
],
|
||||
"default": "all"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -3,6 +3,7 @@ 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]
|
||||
- Removed 'hf iclass replay' - use the 'hf iclass dump' or 'hf iclass rdbl' with option "n" instead (@iceman1001). Concept taken from official repo (@pwpiwi)
|
||||
- Add low level support for 14b' aka Innovatron (@doegox)
|
||||
- Add doc/cliparser.md (@mwalker33)
|
||||
- Add `hf 14b apdu` - send APDU over ISO14443B (@iceman1001)
|
||||
|
|
|
@ -27,6 +27,9 @@ LD = g++
|
|||
SH = sh
|
||||
BASH = bash
|
||||
PERL = perl
|
||||
CCC =foo
|
||||
CC_VERSION = $(shell $(CC) -dumpversion 2>/dev/null|sed 's/\..*//')
|
||||
CC_VERSION := $(or $(strip $(CC_VERSION)),0)
|
||||
|
||||
PATHSEP=/
|
||||
PREFIX ?= /usr/local
|
||||
|
@ -40,17 +43,29 @@ INSTALLDOCSRELPATH ?= share/doc/proxmark3
|
|||
platform = $(shell uname)
|
||||
DETECTED_OS=$(platform)
|
||||
|
||||
ifeq ($(platform),Darwin)
|
||||
AR= /usr/bin/ar rcs
|
||||
RANLIB= /usr/bin/ranlib
|
||||
ifeq ($(shell $(CC) -v 2>&1 | grep -c "clang version"), 1)
|
||||
DETECTED_COMPILER = clang
|
||||
else
|
||||
AR= ar rcs
|
||||
RANLIB= ranlib
|
||||
DETECTED_COMPILER = gcc
|
||||
endif
|
||||
|
||||
DEFCXXFLAGS = -Wall -Werror -O3 -pipe
|
||||
DEFCFLAGS = -Wall -Werror -O3 -fstrict-aliasing -pipe
|
||||
DEFLDFLAGS =
|
||||
ifeq ($(platform),Darwin)
|
||||
AR= /usr/bin/ar rcs
|
||||
RANLIB= /usr/bin/ranlib
|
||||
else
|
||||
AR= ar rcs
|
||||
RANLIB= ranlib
|
||||
endif
|
||||
|
||||
ifeq ($(DEBUG),1)
|
||||
DEFCXXFLAGS = -g -O0 -pipe
|
||||
DEFCFLAGS = -g -O0 -fstrict-aliasing -pipe
|
||||
DEFLDFLAGS =
|
||||
else
|
||||
DEFCXXFLAGS = -Wall -Werror -O3 -pipe
|
||||
DEFCFLAGS = -Wall -Werror -O3 -fstrict-aliasing -pipe
|
||||
DEFLDFLAGS =
|
||||
endif
|
||||
# Next ones are activated only if SANITIZE=1
|
||||
ifeq ($(SANITIZE),1)
|
||||
DEFCFLAGS += -g -fsanitize=address -fno-omit-frame-pointer
|
||||
|
@ -62,12 +77,18 @@ DEFCFLAGS += -Wbad-function-cast -Wredundant-decls -Wmissing-prototypes -Wchar-s
|
|||
# Some more warnings we need first to eliminate, so temporarely tolerated:
|
||||
DEFCFLAGS += -Wcast-align -Wno-error=cast-align
|
||||
DEFCFLAGS += -Wswitch-enum -Wno-error=switch-enum
|
||||
|
||||
# GCC 10 has issues with false positives on stringop-overflow, let's disable them for now (cf https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92955, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94335)
|
||||
# beware these flags didn't exist for GCC < 7
|
||||
ifeq ($(shell expr $(CC_VERSION) \>= 10), 1)
|
||||
ifneq ($(DETECTED_COMPILER), clang)
|
||||
DEFCFLAGS += -Wno-stringop-overflow -Wno-error=stringop-overflow
|
||||
endif
|
||||
endif
|
||||
ifeq ($(platform),Darwin)
|
||||
# their readline has strict-prototype issues
|
||||
DEFCFLAGS += -Wno-strict-prototypes
|
||||
# their readline has strict-prototype issues
|
||||
DEFCFLAGS += -Wno-strict-prototypes
|
||||
else
|
||||
DEFCFLAGS += -Wstrict-prototypes
|
||||
DEFCFLAGS += -Wstrict-prototypes
|
||||
endif
|
||||
|
||||
# Next ones are activated only if GCCEXTRA=1 or CLANGEXTRA=1
|
||||
|
|
|
@ -302,15 +302,17 @@ static int reader_dump_mode(void) {
|
|||
Iso15693InitReader();
|
||||
set_tracing(false);
|
||||
|
||||
|
||||
picopass_hdr *hdr = (picopass_hdr *)card_data;
|
||||
|
||||
// select tag.
|
||||
uint32_t eof_time = 0;
|
||||
bool res = select_iclass_tag(card_data, auth.use_credit_key, &eof_time);
|
||||
bool res = select_iclass_tag(hdr, auth.use_credit_key, &eof_time);
|
||||
if (res == false) {
|
||||
switch_off();
|
||||
continue;
|
||||
}
|
||||
|
||||
picopass_hdr *hdr = (picopass_hdr *)card_data;
|
||||
// sanity check of CSN.
|
||||
if (hdr->csn[7] != 0xE0 && hdr->csn[6] != 0x12) {
|
||||
switch_off();
|
||||
|
@ -366,7 +368,7 @@ static int reader_dump_mode(void) {
|
|||
auth.use_credit_key = true;
|
||||
memcpy(auth.key, aa2_key, sizeof(auth.key));
|
||||
|
||||
res = select_iclass_tag(card_data, auth.use_credit_key, &eof_time);
|
||||
res = select_iclass_tag(hdr, auth.use_credit_key, &eof_time);
|
||||
if (res) {
|
||||
|
||||
// sanity check of CSN.
|
||||
|
|
|
@ -970,6 +970,23 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
);
|
||||
break;
|
||||
}
|
||||
case CMD_LF_EM4X_LOGIN: {
|
||||
struct p {
|
||||
uint32_t password;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
EM4xLogin(payload->password);
|
||||
break;
|
||||
}
|
||||
case CMD_LF_EM4X_BF: {
|
||||
struct p {
|
||||
uint32_t start_pwd;
|
||||
uint32_t n;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
EM4xBruteforce(payload->start_pwd, payload->n);
|
||||
break;
|
||||
}
|
||||
case CMD_LF_EM4X_READWORD: {
|
||||
struct p {
|
||||
uint32_t password;
|
||||
|
@ -1242,7 +1259,11 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
break;
|
||||
}
|
||||
case CMD_HF_ISO14443A_ANTIFUZZ: {
|
||||
iso14443a_antifuzz(packet->oldarg[0]);
|
||||
struct p {
|
||||
uint8_t flag;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
iso14443a_antifuzz(payload->flag);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_EPA_COLLECT_NONCE: {
|
||||
|
@ -1473,12 +1494,12 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
MifareU_Otp_Tearoff(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_MFU_COUNTER_TEAROFF: {
|
||||
case CMD_HF_MFU_COUNTER_TEAROFF: {
|
||||
struct p {
|
||||
uint8_t counter;
|
||||
uint32_t tearoff_time;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
MifareU_Counter_Tearoff(payload->counter, payload->tearoff_time);
|
||||
break;
|
||||
}
|
||||
|
@ -1512,6 +1533,14 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
break;
|
||||
}
|
||||
case CMD_HF_ICLASS_SIMULATE: {
|
||||
/*
|
||||
struct p {
|
||||
uint8_t reader[4];
|
||||
uint8_t mac[4];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
*/
|
||||
|
||||
SimulateIClass(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
|
@ -1519,15 +1548,6 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
ReaderIClass(packet->oldarg[0]);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ICLASS_REPLAY: {
|
||||
struct p {
|
||||
uint8_t reader[4];
|
||||
uint8_t mac[4];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
ReaderIClass_Replay(payload->reader, payload->mac);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ICLASS_EML_MEMSET: {
|
||||
//iceman, should call FPGADOWNLOAD before, since it corrupts BigBuf
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
@ -1554,18 +1574,8 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
iClass_Dump(packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ICLASS_CLONE: {
|
||||
struct p {
|
||||
uint8_t startblock;
|
||||
uint8_t endblock;
|
||||
uint8_t data[];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *)packet->data.asBytes;
|
||||
iClass_Clone(payload->startblock, payload->endblock, payload->data);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ICLASS_RESTORE: {
|
||||
iClass_Restore(packet->data.asBytes);
|
||||
iClass_Restore((iclass_restore_req_t *)packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
@ -1607,7 +1617,11 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
break;
|
||||
}
|
||||
case CMD_SMART_SETCLOCK: {
|
||||
SmartCardSetClock(packet->oldarg[0]);
|
||||
struct p {
|
||||
uint32_t new_clk;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *)packet->data.asBytes;
|
||||
SmartCardSetClock(payload->new_clk);
|
||||
break;
|
||||
}
|
||||
case CMD_SMART_RAW: {
|
||||
|
|
100
armsrc/em4x50.c
100
armsrc/em4x50.c
|
@ -14,6 +14,7 @@
|
|||
#include "lfadc.h"
|
||||
#include "commonutil.h"
|
||||
#include "em4x50.h"
|
||||
#include "appmain.h" // tear
|
||||
|
||||
// 4 data bytes
|
||||
// + byte with row parities
|
||||
|
@ -470,10 +471,12 @@ static bool find_double_listen_window(bool bcommand) {
|
|||
|
||||
if (bcommand) {
|
||||
|
||||
// SpinDelay(10);
|
||||
|
||||
// data transmission from card has to be stopped, because
|
||||
// a commamd shall be issued
|
||||
|
||||
// unfortunately the posititon in listen window (where
|
||||
// unfortunately the position in listen window (where
|
||||
// command request has to be sent) has gone, so if a
|
||||
// second window follows - sync on this to issue a command
|
||||
|
||||
|
@ -519,7 +522,7 @@ static bool find_em4x50_tag(void) {
|
|||
static bool request_receive_mode(void) {
|
||||
|
||||
// To issue a command we have to find a listen window first.
|
||||
// Because identification and sychronization at the same time is not
|
||||
// Because identification and synchronization at the same time is not
|
||||
// possible when using pulse lengths a double listen window is used.
|
||||
bool bcommand = true;
|
||||
return find_double_listen_window(bcommand);
|
||||
|
@ -556,7 +559,7 @@ static bool check_ack(bool bliw) {
|
|||
// "bit" of listen window)
|
||||
wait_timer(FPGA_TIMER_0, T0 * 2 * EM4X50_T_TAG_FULL_PERIOD);
|
||||
|
||||
// check for listen window (if first bit cannot be inerpreted
|
||||
// check for listen window (if first bit cannot be interpreted
|
||||
// as a valid bit it must belong to a listen window)
|
||||
if (get_next_bit() == EM4X50_BIT_OTHER) {
|
||||
|
||||
|
@ -727,7 +730,7 @@ static bool standard_read(int *now) {
|
|||
int fwr = *now;
|
||||
uint8_t bits[EM4X50_TAG_WORD] = {0};
|
||||
|
||||
// start with the identification of two succsessive listening windows
|
||||
// start with the identification of two successive listening windows
|
||||
if (find_double_listen_window(false)) {
|
||||
|
||||
// read and save words until following double listen window is detected
|
||||
|
@ -816,7 +819,7 @@ void em4x50_info(em4x50_data_t *etd) {
|
|||
status = (bsuccess << 1) + blogin;
|
||||
|
||||
lf_finalize();
|
||||
reply_ng(CMD_ACK, status, (uint8_t *)tag.sectors, 238);
|
||||
reply_ng(CMD_LF_EM4X50_INFO, status, (uint8_t *)tag.sectors, 238);
|
||||
}
|
||||
|
||||
void em4x50_read(em4x50_data_t *etd) {
|
||||
|
@ -860,14 +863,13 @@ void em4x50_read(em4x50_data_t *etd) {
|
|||
status = (now << 2) + (bsuccess << 1) + blogin;
|
||||
|
||||
lf_finalize();
|
||||
reply_ng(CMD_ACK, status, (uint8_t *)tag.sectors, 238);
|
||||
reply_ng(CMD_LF_EM4X50_READ, status, (uint8_t *)tag.sectors, 238);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// write functions
|
||||
//==============================================================================
|
||||
|
||||
static bool write(uint8_t word[4], uint8_t address) {
|
||||
static int write(uint8_t word[4], uint8_t address) {
|
||||
|
||||
// writes <word> to specified <address>
|
||||
|
||||
|
@ -882,17 +884,23 @@ static bool write(uint8_t word[4], uint8_t address) {
|
|||
// send data
|
||||
em4x50_send_word(word);
|
||||
|
||||
// wait for T0 * EM4X50_T_TAG_TWA (write access time)
|
||||
wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_TWA);
|
||||
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred
|
||||
reply_ng(CMD_LF_EM4X50_WRITE, PM3_ETEAROFF, NULL, 0);
|
||||
return PM3_ETEAROFF;
|
||||
} else {
|
||||
|
||||
// look for ACK sequence
|
||||
if (check_ack(false)) {
|
||||
// wait for T0 * EM4X50_T_TAG_TWA (write access time)
|
||||
wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_TWA);
|
||||
|
||||
// now EM4x50 needs T0 * EM4X50_T_TAG_TWEE (EEPROM write time)
|
||||
// for saving data and should return with ACK
|
||||
if (check_ack(false))
|
||||
return true;
|
||||
// look for ACK sequence
|
||||
if (check_ack(false)) {
|
||||
|
||||
// now EM4x50 needs T0 * EM4X50_T_TAG_TWEE (EEPROM write time)
|
||||
// for saving data and should return with ACK
|
||||
if (check_ack(false))
|
||||
return PM3_SUCCESS;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -900,10 +908,10 @@ static bool write(uint8_t word[4], uint8_t address) {
|
|||
Dbprintf("error in command request");
|
||||
}
|
||||
|
||||
return false;
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
static bool write_password(uint8_t password[4], uint8_t new_password[4]) {
|
||||
static int write_password(uint8_t password[4], uint8_t new_password[4]) {
|
||||
|
||||
// changes password from <password> to <new_password>
|
||||
|
||||
|
@ -915,23 +923,29 @@ static bool write_password(uint8_t password[4], uint8_t new_password[4]) {
|
|||
// send address data
|
||||
em4x50_send_word(password);
|
||||
|
||||
// wait for T0 * EM4x50_T_TAG_TPP (processing pause time)
|
||||
wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_TPP);
|
||||
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred
|
||||
reply_ng(CMD_LF_EM4X50_WRITE, PM3_ETEAROFF, NULL, 0);
|
||||
return PM3_ETEAROFF;
|
||||
} else {
|
||||
|
||||
// look for ACK sequence and send rm request
|
||||
// during following listen window
|
||||
if (check_ack(true)) {
|
||||
// wait for T0 * EM4x50_T_TAG_TPP (processing pause time)
|
||||
wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_TPP);
|
||||
|
||||
// send new password
|
||||
em4x50_send_word(new_password);
|
||||
// look for ACK sequence and send rm request
|
||||
// during following listen window
|
||||
if (check_ack(true)) {
|
||||
|
||||
// wait for T0 * EM4X50_T_TAG_TWA (write access time)
|
||||
wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_TWA);
|
||||
// send new password
|
||||
em4x50_send_word(new_password);
|
||||
|
||||
// wait for T0 * EM4X50_T_TAG_TWA (write access time)
|
||||
wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_TWA);
|
||||
|
||||
if (check_ack(false))
|
||||
if (check_ack(false))
|
||||
return true;
|
||||
if (check_ack(false))
|
||||
return PM3_SUCCESS;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -939,7 +953,7 @@ static bool write_password(uint8_t password[4], uint8_t new_password[4]) {
|
|||
Dbprintf("error in command request");
|
||||
}
|
||||
|
||||
return false;
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
void em4x50_write(em4x50_data_t *etd) {
|
||||
|
@ -966,8 +980,13 @@ void em4x50_write(em4x50_data_t *etd) {
|
|||
blogin = login(etd->password);
|
||||
|
||||
// write word to given address
|
||||
if (write(etd->word, etd->address)) {
|
||||
int res = write(etd->word, etd->address);
|
||||
if (res == PM3_ETEAROFF) {
|
||||
lf_finalize();
|
||||
return;
|
||||
}
|
||||
|
||||
if (res == PM3_SUCCESS) {
|
||||
// to verify result reset EM4x50
|
||||
if (reset()) {
|
||||
|
||||
|
@ -996,14 +1015,13 @@ void em4x50_write(em4x50_data_t *etd) {
|
|||
}
|
||||
|
||||
status = (bsuccess << 1) + blogin;
|
||||
|
||||
lf_finalize();
|
||||
reply_ng(CMD_ACK, status, (uint8_t *)tag.sectors, 238);
|
||||
reply_ng(CMD_LF_EM4X50_WRITE, status, (uint8_t *)tag.sectors, 238);
|
||||
}
|
||||
|
||||
void em4x50_write_password(em4x50_data_t *etd) {
|
||||
|
||||
// sinmple change of password
|
||||
// simple change of password
|
||||
|
||||
bool bsuccess = false;
|
||||
|
||||
|
@ -1015,12 +1033,18 @@ void em4x50_write_password(em4x50_data_t *etd) {
|
|||
|
||||
// login and change password
|
||||
if (login(etd->password)) {
|
||||
bsuccess = write_password(etd->password, etd->new_password);
|
||||
|
||||
int res = write_password(etd->password, etd->new_password);
|
||||
if (res == PM3_ETEAROFF) {
|
||||
lf_finalize();
|
||||
return;
|
||||
}
|
||||
bsuccess = (res == PM3_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
lf_finalize();
|
||||
reply_ng(CMD_ACK, bsuccess, 0, 0);
|
||||
reply_ng(CMD_LF_EM4X50_WRITE_PASSWORD, bsuccess, 0, 0);
|
||||
}
|
||||
|
||||
void em4x50_wipe(em4x50_data_t *etd) {
|
||||
|
@ -1049,7 +1073,7 @@ void em4x50_wipe(em4x50_data_t *etd) {
|
|||
// to verify result reset EM4x50
|
||||
if (reset()) {
|
||||
|
||||
// login not necessary because protectd word has been set to 0
|
||||
// login not necessary because protected word has been set to 0
|
||||
// -> no read protected words
|
||||
// -> selective read can be called immediately
|
||||
if (selective_read(addresses)) {
|
||||
|
@ -1078,5 +1102,5 @@ void em4x50_wipe(em4x50_data_t *etd) {
|
|||
}
|
||||
|
||||
lf_finalize();
|
||||
reply_ng(CMD_ACK, bsuccess, (uint8_t *)tag.sectors, 238);
|
||||
reply_ng(CMD_LF_EM4X50_WIPE, bsuccess, (uint8_t *)tag.sectors, 238);
|
||||
}
|
||||
|
|
43
armsrc/i2c.c
43
armsrc/i2c.c
|
@ -47,12 +47,6 @@ static void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) {
|
|||
#define I2C_DELAY_2CLK I2CSpinDelayClk(2)
|
||||
#define I2C_DELAY_XCLK(x) I2CSpinDelayClk((x))
|
||||
|
||||
#define I2C_DELAY_100us I2CSpinDelayClk( 100 / 3)
|
||||
#define I2C_DELAY_600us I2CSpinDelayClk( 600 / 3)
|
||||
#define I2C_DELAY_10ms I2CSpinDelayClk( 10 * 1000 / 3 )
|
||||
#define I2C_DELAY_30ms I2CSpinDelayClk( 30 * 1000 / 3 )
|
||||
#define I2C_DELAY_100ms I2CSpinDelayClk( 100 * 1000 / 3)
|
||||
|
||||
#define ISO7618_MAX_FRAME 255
|
||||
|
||||
// try i2c bus recovery at 100kHz = 5us high, 5us low
|
||||
|
@ -134,11 +128,11 @@ void I2C_Reset_EnterMainProgram(void) {
|
|||
StartTicks();
|
||||
I2C_init();
|
||||
I2C_SetResetStatus(0, 0, 0);
|
||||
I2C_DELAY_30ms;
|
||||
WaitMS(30);
|
||||
I2C_SetResetStatus(1, 0, 0);
|
||||
I2C_DELAY_30ms;
|
||||
WaitMS(30);
|
||||
I2C_SetResetStatus(1, 1, 1);
|
||||
I2C_DELAY_10ms;
|
||||
WaitMS(10);
|
||||
}
|
||||
|
||||
// Reset the SIM_Adapter, then enter the bootloader program
|
||||
|
@ -147,9 +141,9 @@ void I2C_Reset_EnterBootloader(void) {
|
|||
StartTicks();
|
||||
I2C_init();
|
||||
I2C_SetResetStatus(0, 1, 1);
|
||||
I2C_DELAY_100ms;
|
||||
WaitMS(100);
|
||||
I2C_SetResetStatus(1, 1, 1);
|
||||
I2C_DELAY_10ms;
|
||||
WaitMS(10);
|
||||
}
|
||||
|
||||
// Wait for the clock to go High.
|
||||
|
@ -187,13 +181,13 @@ static bool WaitSCL_L(void) {
|
|||
// It timeout reading response from card
|
||||
// Which ever comes first
|
||||
static bool WaitSCL_L_timeout(void) {
|
||||
volatile uint32_t delay = 18000;
|
||||
volatile uint32_t delay = 1800;
|
||||
while (delay--) {
|
||||
// exit on SCL LOW
|
||||
if (!SCL_read)
|
||||
return true;
|
||||
|
||||
I2C_DELAY_100us;
|
||||
WaitMS(1);
|
||||
}
|
||||
return (delay == 0);
|
||||
}
|
||||
|
@ -225,7 +219,7 @@ static bool I2C_WaitForSim(void) {
|
|||
// 8051 speaks with smart card.
|
||||
// 1000*50*3.07 = 153.5ms
|
||||
// 1byte transfer == 1ms with max frame being 256bytes
|
||||
if (!WaitSCL_H_delay(30 * 1000 * 50))
|
||||
if (!WaitSCL_H_delay(20 * 1000 * 50))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -440,8 +434,7 @@ int16_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t d
|
|||
|
||||
// extra wait 500us (514us measured)
|
||||
// 200us (xx measured)
|
||||
// WaitUS(600);
|
||||
I2C_DELAY_600us;
|
||||
WaitUS(600);
|
||||
|
||||
bool bBreak = true;
|
||||
uint16_t readcount = 0;
|
||||
|
@ -641,6 +634,9 @@ bool sc_rx_bytes(uint8_t *dest, uint8_t *destlen) {
|
|||
|
||||
len = I2C_BufferRead(dest, *destlen, I2C_DEVICE_CMD_READ, I2C_DEVICE_ADDRESS_MAIN);
|
||||
|
||||
|
||||
LED_C_ON();
|
||||
|
||||
if (len > 1) {
|
||||
break;
|
||||
} else if (len == 1) {
|
||||
|
@ -674,7 +670,7 @@ bool GetATR(smart_card_atr_t *card_ptr, bool verbose) {
|
|||
// 1byte = 1ms , max frame 256bytes. Should wait 256ms atleast just in case.
|
||||
if (I2C_WaitForSim() == false)
|
||||
return false;
|
||||
|
||||
|
||||
// read bytes from module
|
||||
uint8_t len = sizeof(card_ptr->atr);
|
||||
if (sc_rx_bytes(card_ptr->atr, &len) == false)
|
||||
|
@ -713,12 +709,12 @@ bool GetATR(smart_card_atr_t *card_ptr, bool verbose) {
|
|||
}
|
||||
|
||||
void SmartCardAtr(void) {
|
||||
smart_card_atr_t card;
|
||||
LED_D_ON();
|
||||
set_tracing(true);
|
||||
I2C_Reset_EnterMainProgram();
|
||||
bool isOK = GetATR(&card, true);
|
||||
reply_mix(CMD_ACK, isOK, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t));
|
||||
smart_card_atr_t card;
|
||||
int res = GetATR(&card, true) ? PM3_SUCCESS : PM3_ETIMEOUT;
|
||||
reply_ng(CMD_SMART_ATR, res, (uint8_t*)&card, sizeof(smart_card_atr_t));
|
||||
set_tracing(false);
|
||||
LEDsoff();
|
||||
}
|
||||
|
@ -811,8 +807,7 @@ void SmartCardUpgrade(uint64_t arg0) {
|
|||
}
|
||||
|
||||
// writing takes time.
|
||||
// WaitMS(50);
|
||||
I2C_DELAY_100ms;
|
||||
WaitMS(100);
|
||||
|
||||
// read
|
||||
res = I2C_ReadFW(verfiydata, size, msb, lsb, I2C_DEVICE_ADDRESS_BOOT);
|
||||
|
@ -844,12 +839,10 @@ void SmartCardSetClock(uint64_t arg0) {
|
|||
LED_D_ON();
|
||||
set_tracing(true);
|
||||
I2C_Reset_EnterMainProgram();
|
||||
|
||||
// Send SIM CLC
|
||||
// start [C0 05 xx] stop
|
||||
I2C_WriteByte(arg0, I2C_DEVICE_CMD_SIM_CLC, I2C_DEVICE_ADDRESS_MAIN);
|
||||
|
||||
reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
|
||||
reply_ng(CMD_SMART_SETCLOCK, PM3_SUCCESS, NULL, 0);
|
||||
set_tracing(false);
|
||||
LEDsoff();
|
||||
}
|
||||
|
|
281
armsrc/iclass.c
281
armsrc/iclass.c
|
@ -1276,7 +1276,7 @@ static bool iclass_send_cmd_with_retries(uint8_t *cmd, size_t cmdsize, uint8_t *
|
|||
* @return false = fail
|
||||
* true = Got all.
|
||||
*/
|
||||
static bool select_iclass_tag_ex(uint8_t *card_data, bool use_credit_key, uint32_t *eof_time, uint8_t *status) {
|
||||
static bool select_iclass_tag_ex(picopass_hdr *hdr, bool use_credit_key, uint32_t *eof_time, uint8_t *status) {
|
||||
|
||||
static uint8_t act_all[] = { ICLASS_CMD_ACTALL };
|
||||
static uint8_t identify[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x00, 0x73, 0x33 };
|
||||
|
@ -1286,8 +1286,6 @@ static bool select_iclass_tag_ex(uint8_t *card_data, bool use_credit_key, uint32
|
|||
uint8_t read_check_cc[] = { 0x80 | ICLASS_CMD_READCHECK, 0x02 };
|
||||
uint8_t resp[ICLASS_BUFFER_SIZE] = {0};
|
||||
|
||||
picopass_hdr *hdr = (picopass_hdr *)card_data;
|
||||
|
||||
// Bit 4: K.If this bit equals to one, the READCHECK will use the Credit Key (Kc); if equals to zero, Debit Key (Kd) will be used
|
||||
// bit 7: parity.
|
||||
if (use_credit_key)
|
||||
|
@ -1370,6 +1368,8 @@ static bool select_iclass_tag_ex(uint8_t *card_data, bool use_credit_key, uint32
|
|||
|
||||
} else {
|
||||
|
||||
// on NON_SECURE_PAGEMODE cards, AIA is on block2..
|
||||
|
||||
// read App Issuer Area block 2
|
||||
read_aia[1] = 0x02;
|
||||
read_aia[2] = 0x61;
|
||||
|
@ -1385,23 +1385,23 @@ static bool select_iclass_tag_ex(uint8_t *card_data, bool use_credit_key, uint32
|
|||
|
||||
if (status) {
|
||||
*status |= FLAG_ICLASS_AIA;
|
||||
memcpy(card_data + (8 * 2), resp, 8);
|
||||
memcpy(hdr->epurse, resp, sizeof(hdr->epurse));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool select_iclass_tag(uint8_t *card_data, bool use_credit_key, uint32_t *eof_time) {
|
||||
bool select_iclass_tag(picopass_hdr *hdr, bool use_credit_key, uint32_t *eof_time) {
|
||||
uint8_t result = 0;
|
||||
return select_iclass_tag_ex(card_data, use_credit_key, eof_time, &result);
|
||||
return select_iclass_tag_ex(hdr, use_credit_key, eof_time, &result);
|
||||
}
|
||||
|
||||
// Reader iClass Anticollission
|
||||
// turn off afterwards
|
||||
void ReaderIClass(uint8_t flags) {
|
||||
|
||||
uint8_t card_data[6 * 8] = {0xFF};
|
||||
picopass_hdr hdr = {0};
|
||||
// uint8_t last_csn[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
uint8_t resp[ICLASS_BUFFER_SIZE] = {0};
|
||||
memset(resp, 0xFF, sizeof(resp));
|
||||
|
@ -1419,14 +1419,13 @@ void ReaderIClass(uint8_t flags) {
|
|||
|
||||
uint8_t result_status = 0;
|
||||
uint32_t eof_time = 0;
|
||||
bool status = select_iclass_tag_ex(card_data, use_credit_key, &eof_time, &result_status);
|
||||
bool status = select_iclass_tag_ex(&hdr, use_credit_key, &eof_time, &result_status);
|
||||
if (status == false) {
|
||||
reply_mix(CMD_ACK, 0xFF, 0, 0, card_data, 0);
|
||||
reply_mix(CMD_ACK, 0xFF, 0, 0, NULL, 0);
|
||||
switch_off();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Page mapping for secure mode
|
||||
// 0 : CSN
|
||||
// 1 : Configuration
|
||||
|
@ -1444,7 +1443,7 @@ void ReaderIClass(uint8_t flags) {
|
|||
// with 0xFF:s in block 3 and 4.
|
||||
|
||||
LED_B_ON();
|
||||
reply_mix(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data));
|
||||
reply_mix(CMD_ACK, result_status, 0, 0, (uint8_t *)&hdr, sizeof(hdr));
|
||||
|
||||
//Send back to client, but don't bother if we already sent this -
|
||||
// only useful if looping in arm (not try_once && not abort_after_read)
|
||||
|
@ -1470,101 +1469,6 @@ void ReaderIClass(uint8_t flags) {
|
|||
switch_off();
|
||||
}
|
||||
|
||||
// turn off afterwards
|
||||
void ReaderIClass_Replay(uint8_t *rnr, uint8_t *mac) {
|
||||
|
||||
BigBuf_free();
|
||||
|
||||
uint8_t check[] = { ICLASS_CMD_CHECK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
memcpy(check + 1, rnr, 4);
|
||||
memcpy(check + 5, mac, 4);
|
||||
|
||||
uint8_t *card_data = BigBuf_malloc(ICLASS_16KS_SIZE);
|
||||
if (card_data == NULL) {
|
||||
DbpString("fail to allocate memory");
|
||||
reply_ng(CMD_HF_ICLASS_REPLAY, PM3_EMALLOC, NULL, 0);
|
||||
return;
|
||||
}
|
||||
memset(card_data, 0xFF, ICLASS_16KS_SIZE);
|
||||
|
||||
uint32_t start_time = 0;
|
||||
uint32_t eof_time = 0;
|
||||
|
||||
Iso15693InitReader();
|
||||
|
||||
picopass_hdr hdr = {0};
|
||||
bool res = select_iclass_tag((uint8_t *)&hdr, false, &eof_time);
|
||||
if (res == false) {
|
||||
reply_ng(CMD_HF_ICLASS_REPLAY, PM3_ETIMEOUT, NULL, 0);
|
||||
switch_off();
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t resp[10] = {0};
|
||||
|
||||
//for now replay captured auth (as cc not updated)
|
||||
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||
res = iclass_send_cmd_with_retries(check, sizeof(check), resp, sizeof(resp), 4, 3, &start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time);
|
||||
if (res == false) {
|
||||
reply_ng(CMD_HF_ICLASS_REPLAY, PM3_ETIMEOUT, NULL, 0);
|
||||
switch_off();
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t mem = hdr.conf.mem_config;
|
||||
uint8_t cardsize = ((mem & 0x80) == 0x80) ? 255 : 32;
|
||||
|
||||
/*
|
||||
static struct memory_t {
|
||||
int k16;
|
||||
int book;
|
||||
int k2;
|
||||
int lockauth;
|
||||
int keyaccess;
|
||||
} memory;
|
||||
|
||||
// memory.k16 = ((mem & 0x80) == 0x80);
|
||||
// memory.book = ((mem & 0x20) == 0x20);
|
||||
// memory.k2 = ((mem & 0x08) == 0x08);
|
||||
// memory.lockauth = ((mem & 0x02) == 0x02);
|
||||
// memory.keyaccess = ((mem & 0x01) == 0x01);
|
||||
// uint8_t cardsize = memory.k16 ? 255 : 32;
|
||||
*/
|
||||
|
||||
bool dumpsuccess = true;
|
||||
|
||||
// main read loop
|
||||
uint16_t i;
|
||||
for (i = 0; i <= cardsize; i++) {
|
||||
|
||||
uint8_t c[] = {ICLASS_CMD_READ_OR_IDENTIFY, i, 0x00, 0x00};
|
||||
AddCrc(c + 1, 1);
|
||||
|
||||
res = iclass_send_cmd_with_retries(c, sizeof(c), resp, sizeof(resp), 10, 3, &start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time);
|
||||
if (res) {
|
||||
memcpy(card_data + (8 * i), resp, 8);
|
||||
} else {
|
||||
Dbprintf("failed to read block %u ( 0x%02x)", i, i);
|
||||
dumpsuccess = false;
|
||||
}
|
||||
}
|
||||
|
||||
struct p {
|
||||
bool isOK;
|
||||
uint16_t block_cnt;
|
||||
uint32_t bb_offset;
|
||||
} PACKED response;
|
||||
|
||||
response.isOK = dumpsuccess;
|
||||
response.block_cnt = i;
|
||||
response.bb_offset = card_data - BigBuf_get_addr();
|
||||
reply_ng(CMD_HF_ICLASS_REPLAY, PM3_SUCCESS, (uint8_t *)&response, sizeof(response));
|
||||
|
||||
BigBuf_free();
|
||||
switch_off();
|
||||
}
|
||||
|
||||
// used with function select_and_auth (cmdhficlass.c)
|
||||
// which needs to authenticate before doing more things like read/write
|
||||
// selects and authenticate to a card, sends back div_key and mac to client.
|
||||
|
@ -1585,24 +1489,30 @@ bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr *hdr, uint
|
|||
|
||||
memcpy(ccnr, hdr->epurse, sizeof(hdr->epurse));
|
||||
|
||||
if (payload->use_raw)
|
||||
memcpy(div_key, payload->key, 8);
|
||||
else
|
||||
iclass_calc_div_key(hdr->csn, payload->key, div_key, payload->use_elite);
|
||||
if (payload->use_replay) {
|
||||
|
||||
if (payload->use_credit_key)
|
||||
memcpy(hdr->key_c, div_key, sizeof(hdr->key_c));
|
||||
else
|
||||
memcpy(hdr->key_d, div_key, sizeof(hdr->key_d));
|
||||
memcpy(pmac, payload->key + 4, 4);
|
||||
memcpy(cmd_check + 1, payload->key, 8);
|
||||
|
||||
opt_doReaderMAC(ccnr, div_key, pmac);
|
||||
} else {
|
||||
if (payload->use_raw)
|
||||
memcpy(div_key, payload->key, 8);
|
||||
else
|
||||
iclass_calc_div_key(hdr->csn, payload->key, div_key, payload->use_elite);
|
||||
|
||||
// copy MAC to check command (readersignature)
|
||||
cmd_check[5] = pmac[0];
|
||||
cmd_check[6] = pmac[1];
|
||||
cmd_check[7] = pmac[2];
|
||||
cmd_check[8] = pmac[3];
|
||||
if (payload->use_credit_key)
|
||||
memcpy(hdr->key_c, div_key, sizeof(hdr->key_c));
|
||||
else
|
||||
memcpy(hdr->key_d, div_key, sizeof(hdr->key_d));
|
||||
|
||||
opt_doReaderMAC(ccnr, div_key, pmac);
|
||||
|
||||
// copy MAC to check command (readersignature)
|
||||
cmd_check[5] = pmac[0];
|
||||
cmd_check[6] = pmac[1];
|
||||
cmd_check[7] = pmac[2];
|
||||
cmd_check[8] = pmac[3];
|
||||
}
|
||||
return iclass_send_cmd_with_retries(cmd_check, sizeof(cmd_check), resp_auth, sizeof(resp_auth), 4, 2, start_time, ICLASS_READER_TIMEOUT_OTHERS, eof_time);
|
||||
}
|
||||
|
||||
|
@ -1632,7 +1542,7 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) {
|
|||
readcheck_cc[0] = 0x10 | ICLASS_CMD_READCHECK;
|
||||
|
||||
// select card / e-purse
|
||||
uint8_t card_data[6 * 8] = {0};
|
||||
picopass_hdr hdr = {0};
|
||||
|
||||
iclass_premac_t *keys = (iclass_premac_t *)datain;
|
||||
|
||||
|
@ -1646,7 +1556,7 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) {
|
|||
|
||||
uint32_t start_time = 0, eof_time = 0;
|
||||
|
||||
if (select_iclass_tag(card_data, use_credit_key, &eof_time) == false)
|
||||
if (select_iclass_tag(&hdr, use_credit_key, &eof_time) == false)
|
||||
goto out;
|
||||
|
||||
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||
|
@ -1723,7 +1633,7 @@ void iClass_ReadBlock(uint8_t *msg) {
|
|||
// select tag.
|
||||
uint32_t eof_time = 0;
|
||||
picopass_hdr hdr = {0};
|
||||
bool res = select_iclass_tag((uint8_t *)&hdr, payload->use_credit_key, &eof_time);
|
||||
bool res = select_iclass_tag(&hdr, payload->use_credit_key, &eof_time);
|
||||
if (res == false) {
|
||||
if (payload->send_reply) {
|
||||
response.isOK = res;
|
||||
|
@ -1796,7 +1706,7 @@ void iClass_Dump(uint8_t *msg) {
|
|||
// select tag.
|
||||
uint32_t eof_time = 0;
|
||||
picopass_hdr hdr = {0};
|
||||
bool res = select_iclass_tag((uint8_t *)&hdr, req->use_credit_key, &eof_time);
|
||||
bool res = select_iclass_tag(&hdr, req->use_credit_key, &eof_time);
|
||||
if (res == false) {
|
||||
if (req->send_reply) {
|
||||
reply_ng(CMD_HF_ICLASS_DUMP, PM3_ETIMEOUT, NULL, 0);
|
||||
|
@ -1866,10 +1776,12 @@ void iClass_Dump(uint8_t *msg) {
|
|||
BigBuf_free();
|
||||
}
|
||||
|
||||
static bool iclass_writeblock_ext(uint8_t blockno, uint8_t *data) {
|
||||
static bool iclass_writeblock_ext(uint8_t blockno, uint8_t *data, uint8_t *mac) {
|
||||
|
||||
// write command: cmd, 1 blockno, 8 data, 4 mac
|
||||
uint8_t write[16] = { 0x80 | ICLASS_CMD_UPDATE, blockno };
|
||||
memcpy(write + 2, data, 12); // data + mac
|
||||
memcpy(write + 2, data, 8);
|
||||
memcpy(write + 10, mac, 4);
|
||||
AddCrc(write + 1, 13);
|
||||
|
||||
uint8_t resp[10] = {0};
|
||||
|
@ -1914,7 +1826,7 @@ void iClass_WriteBlock(uint8_t *msg) {
|
|||
// select tag.
|
||||
uint32_t eof_time = 0;
|
||||
picopass_hdr hdr = {0};
|
||||
bool res = select_iclass_tag((uint8_t *)&hdr, payload->req.use_credit_key, &eof_time);
|
||||
bool res = select_iclass_tag(&hdr, payload->req.use_credit_key, &eof_time);
|
||||
if (res == false) {
|
||||
goto out;
|
||||
}
|
||||
|
@ -1937,10 +1849,14 @@ void iClass_WriteBlock(uint8_t *msg) {
|
|||
wb[0] = payload->req.blockno;
|
||||
memcpy(wb + 1, payload->data, 8);
|
||||
|
||||
if (payload->req.use_credit_key)
|
||||
doMAC_N(wb, sizeof(wb), hdr.key_c, mac);
|
||||
else
|
||||
doMAC_N(wb, sizeof(wb), hdr.key_d, mac);
|
||||
if (payload->req.use_replay) {
|
||||
doMAC_N(wb, sizeof(wb), payload->req.key + 4, mac);
|
||||
} else {
|
||||
if (payload->req.use_credit_key)
|
||||
doMAC_N(wb, sizeof(wb), hdr.key_c, mac);
|
||||
else
|
||||
doMAC_N(wb, sizeof(wb), hdr.key_d, mac);
|
||||
}
|
||||
|
||||
memcpy(write + 2, payload->data, 8); // data
|
||||
memcpy(write + 10, mac, sizeof(mac)); // mac
|
||||
|
@ -1949,8 +1865,29 @@ void iClass_WriteBlock(uint8_t *msg) {
|
|||
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||
|
||||
uint8_t resp[10] = {0};
|
||||
res = iclass_send_cmd_with_retries(write, sizeof(write), resp, sizeof(resp), 10, 3, &start_time, ICLASS_READER_TIMEOUT_UPDATE, &eof_time);
|
||||
if (res == false) {
|
||||
|
||||
uint8_t tries = 3;
|
||||
while (tries-- > 0) {
|
||||
|
||||
iclass_send_as_reader(write, sizeof(write), &start_time, &eof_time);
|
||||
|
||||
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured
|
||||
res = false;
|
||||
switch_off();
|
||||
if (payload->req.send_reply)
|
||||
reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_ETEAROFF, (uint8_t *)&res, sizeof(uint8_t));
|
||||
return;
|
||||
} else {
|
||||
|
||||
if (GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_UPDATE, &eof_time) == 10) {
|
||||
res = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tries == 0) {
|
||||
res = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -1983,29 +1920,75 @@ out:
|
|||
reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_SUCCESS, (uint8_t *)&res, sizeof(uint8_t));
|
||||
}
|
||||
|
||||
// turn off afterwards
|
||||
void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data) {
|
||||
}
|
||||
void iClass_Restore(iclass_restore_req_t *msg) {
|
||||
|
||||
void iClass_Restore(uint8_t *msg) {
|
||||
// sanitation
|
||||
if (msg == NULL) {
|
||||
reply_ng(CMD_HF_ICLASS_RESTORE, PM3_ESOFT, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
iclass_restore_req_t *cmd = (iclass_restore_req_t *)msg;
|
||||
// iclass_auth_req_t *req = &cmd->req;
|
||||
if (msg->item_cnt == 0) {
|
||||
if (msg->req.send_reply) {
|
||||
reply_ng(CMD_HF_ICLASS_RESTORE, PM3_ESOFT, NULL, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
LED_A_ON();
|
||||
uint16_t written = 0;
|
||||
uint16_t total_blocks = (cmd->end_block - cmd->start_block) + 1;
|
||||
for (uint8_t b = cmd->start_block; b < total_blocks; b++) {
|
||||
Iso15693InitReader();
|
||||
|
||||
if (iclass_writeblock_ext(b, cmd->data + ((b - cmd->start_block) * 12))) {
|
||||
Dbprintf("Write block [%02x] successful", b);
|
||||
written++;
|
||||
} else {
|
||||
Dbprintf("Write block [%02x] failed", b);
|
||||
uint16_t written = 0;
|
||||
uint32_t eof_time = 0;
|
||||
picopass_hdr hdr = {0};
|
||||
|
||||
// select
|
||||
bool res = select_iclass_tag(&hdr, msg->req.use_credit_key, &eof_time);
|
||||
if (res == false) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
// authenticate
|
||||
uint8_t mac[4] = {0};
|
||||
uint32_t start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||
|
||||
// authenticate
|
||||
if (msg->req.do_auth) {
|
||||
res = authenticate_iclass_tag(&msg->req, &hdr, &start_time, &eof_time, mac);
|
||||
if (res == false) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
// main loop
|
||||
for (uint8_t i = 0; i < msg->item_cnt; i++) {
|
||||
|
||||
iclass_restore_item_t item = msg->blocks[i];
|
||||
|
||||
// calc new mac for data, using 1b blockno, 8b data,
|
||||
uint8_t wb[9] = {0};
|
||||
wb[0] = item.blockno;
|
||||
memcpy(wb + 1, item.data, 8);
|
||||
|
||||
if (msg->req.use_credit_key)
|
||||
doMAC_N(wb, sizeof(wb), hdr.key_c, mac);
|
||||
else
|
||||
doMAC_N(wb, sizeof(wb), hdr.key_d, mac);
|
||||
|
||||
// data + mac
|
||||
if (iclass_writeblock_ext(item.blockno, item.data, mac)) {
|
||||
Dbprintf("Write block [%02x] " _GREEN_("successful"), item.blockno);
|
||||
written++;
|
||||
} else {
|
||||
Dbprintf("Write block [%02x] " _RED_("failed"), item.blockno);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
switch_off();
|
||||
uint8_t isOK = (written == total_blocks) ? 1 : 0;
|
||||
reply_ng(CMD_HF_ICLASS_CLONE, PM3_SUCCESS, (uint8_t *)&isOK, sizeof(uint8_t));
|
||||
if (msg->req.send_reply) {
|
||||
int isOK = (written == msg->item_cnt) ? PM3_SUCCESS : PM3_ESOFT;
|
||||
reply_ng(CMD_HF_ICLASS_RESTORE, isOK, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,13 +17,11 @@
|
|||
|
||||
void SniffIClass(uint8_t jam_search_len, uint8_t *jam_search_string);
|
||||
void ReaderIClass(uint8_t arg0);
|
||||
void ReaderIClass_Replay(uint8_t *rnr, uint8_t *mac);
|
||||
|
||||
void iClass_WriteBlock(uint8_t *msg);
|
||||
void iClass_Dump(uint8_t *msg);
|
||||
|
||||
void iClass_Restore(uint8_t *msg);
|
||||
void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data);
|
||||
void iClass_Restore(iclass_restore_req_t *msg);
|
||||
|
||||
int do_iclass_simulation_nonsec(void);
|
||||
int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf);
|
||||
|
@ -37,6 +35,6 @@ bool iclass_auth(iclass_auth_req_t *payload, uint8_t *out);
|
|||
void iClass_ReadBlock(uint8_t *msg);
|
||||
bool iclass_read_block(uint16_t blockno, uint8_t *data, uint32_t *start_time, uint32_t *eof_time);
|
||||
|
||||
bool select_iclass_tag(uint8_t *card_data, bool use_credit_key, uint32_t *eof_time);
|
||||
bool select_iclass_tag(picopass_hdr *hdr, bool use_credit_key, uint32_t *eof_time);
|
||||
bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr *hdr, uint32_t *start_time, uint32_t *eof_time, uint8_t *mac_out);
|
||||
#endif
|
||||
|
|
|
@ -1778,9 +1778,10 @@ static void PrepareDelayedTransfer(uint16_t delay) {
|
|||
//-------------------------------------------------------------------------------------
|
||||
static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing) {
|
||||
|
||||
if (!hf_field_active)
|
||||
if (!hf_field_active) {
|
||||
Dbprintf("Warning: HF field is off, ignoring TransmitFor14443a command");
|
||||
return;
|
||||
|
||||
}
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
|
||||
|
||||
if (timing) {
|
||||
|
@ -2189,8 +2190,10 @@ bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_Start
|
|||
//-----------------------------------------------------------------------------
|
||||
bool GetIso14443aAnswerFromTag_Thinfilm(uint8_t *receivedResponse, uint8_t *received_len) {
|
||||
|
||||
if (!hf_field_active)
|
||||
if (!hf_field_active) {
|
||||
Dbprintf("Warning: HF field is off, ignoring GetIso14443aAnswerFromTag_Thinfilm command");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set FPGA mode to "reader listen mode", no modulation (listen
|
||||
// only, since we are receiving, not transmitting).
|
||||
|
@ -2390,7 +2393,7 @@ void iso14443a_antifuzz(uint32_t flags) {
|
|||
}
|
||||
}
|
||||
|
||||
reply_old(CMD_ACK, 1, 0, 0, 0, 0);
|
||||
reply_ng(CMD_HF_ISO14443A_ANTIFUZZ, PM3_SUCCESS, NULL, 0);
|
||||
switch_off();
|
||||
BigBuf_free_keep_EM();
|
||||
}
|
||||
|
@ -2624,13 +2627,13 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
|
|||
} // else force RATS
|
||||
|
||||
// RATS, Request for answer to select
|
||||
if (!no_rats) {
|
||||
uint8_t rats[] = { ISO14443A_CMD_RATS, 0x80, 0x00, 0x00 }; // FSD=256, FSDI=8, CID=0
|
||||
if (no_rats == false) {
|
||||
uint8_t rats[] = { ISO14443A_CMD_RATS, 0x80, 0x00, 0x00 }; // FSD=256, FSDI=8, CID=0
|
||||
AddCrc14A(rats, 2);
|
||||
ReaderTransmit(rats, sizeof(rats), NULL);
|
||||
int len = ReaderReceive(resp, resp_par);
|
||||
|
||||
if (!len) return 0;
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
if (p_card) {
|
||||
memcpy(p_card->ats, resp, sizeof(p_card->ats));
|
||||
|
@ -2932,7 +2935,7 @@ void ReaderIso14443a(PacketCommandNG *c) {
|
|||
|
||||
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured
|
||||
FpgaDisableTracing();
|
||||
reply_old(CMD_ACK, 0, 0, 0, NULL, 0);
|
||||
reply_mix(CMD_ACK, 0, 0, 0, NULL, 0);
|
||||
} else {
|
||||
arg0 = ReaderReceive(buf, par);
|
||||
FpgaDisableTracing();
|
||||
|
|
|
@ -1895,12 +1895,17 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) {
|
|||
uint32_t eof_time = 0;
|
||||
CodeAndTransmit14443bAsReader(cmd, len, &start_time, &eof_time);
|
||||
|
||||
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
|
||||
status = Get14443bAnswerFromTag(buf, sizeof(buf), 5 * ISO14443B_READER_TIMEOUT, &eof_time); // raw
|
||||
FpgaDisableTracing();
|
||||
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured
|
||||
FpgaDisableTracing();
|
||||
reply_mix(CMD_HF_ISO14443B_COMMAND, -2, 0, 0, NULL, 0);
|
||||
} else {
|
||||
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
|
||||
status = Get14443bAnswerFromTag(buf, sizeof(buf), 5 * ISO14443B_READER_TIMEOUT, &eof_time); // raw
|
||||
FpgaDisableTracing();
|
||||
|
||||
sendlen = MIN(Demod.len, PM3_CMD_DATA_SIZE);
|
||||
reply_mix(CMD_HF_ISO14443B_COMMAND, status, sendlen, 0, Demod.output, sendlen);
|
||||
sendlen = MIN(Demod.len, PM3_CMD_DATA_SIZE);
|
||||
reply_mix(CMD_HF_ISO14443B_COMMAND, status, sendlen, 0, Demod.output, sendlen);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
|
|
|
@ -290,6 +290,7 @@ void TransmitTo15693Tag(const uint8_t *cmd, int len, uint32_t *start_time) {
|
|||
LED_B_OFF();
|
||||
|
||||
*start_time = *start_time + DELAY_ARM_TO_TAG;
|
||||
FpgaDisableTracing();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -732,6 +733,7 @@ int GetIso15693AnswerFromTag(uint8_t *response, uint16_t max_len, uint16_t timeo
|
|||
}
|
||||
|
||||
FpgaDisableSscDma();
|
||||
FpgaDisableTracing();
|
||||
|
||||
uint32_t sof_time = *eof_time
|
||||
- (dt->len * 8 * 8 * 16) // time for byte transfers
|
||||
|
@ -1469,17 +1471,22 @@ int SendDataTag(uint8_t *send, int sendlen, bool init, bool speed_fast, uint8_t
|
|||
// low speed (1 out of 256)
|
||||
CodeIso15693AsReader256(send, sendlen);
|
||||
}
|
||||
|
||||
int res = 0;
|
||||
tosend_t *ts = get_tosend();
|
||||
TransmitTo15693Tag(ts->buf, ts->max, &start_time);
|
||||
*eof_time = start_time + 32 * ((8 * ts->max) - 4); // substract the 4 padding bits after EOF
|
||||
LogTrace_ISO15693(send, sendlen, (start_time * 4), (*eof_time * 4), NULL, true);
|
||||
|
||||
int res = 0;
|
||||
if (recv != NULL) {
|
||||
res = GetIso15693AnswerFromTag(recv, max_recv_len, timeout, eof_time);
|
||||
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured
|
||||
|
||||
res = PM3_ETEAROFF;
|
||||
|
||||
} else {
|
||||
|
||||
*eof_time = start_time + 32 * ((8 * ts->max) - 4); // substract the 4 padding bits after EOF
|
||||
LogTrace_ISO15693(send, sendlen, (start_time * 4), (*eof_time * 4), NULL, true);
|
||||
if (recv != NULL) {
|
||||
res = GetIso15693AnswerFromTag(recv, max_recv_len, timeout, eof_time);
|
||||
}
|
||||
}
|
||||
FpgaDisableTracing();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -1495,7 +1502,6 @@ int SendDataTagEOF(uint8_t *recv, uint16_t max_recv_len, uint32_t start_time, ui
|
|||
if (recv != NULL) {
|
||||
res = GetIso15693AnswerFromTag(recv, max_recv_len, timeout, eof_time);
|
||||
}
|
||||
FpgaDisableTracing();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -1588,41 +1594,49 @@ void ReaderIso15693(uint32_t parameter) {
|
|||
BuildIdentifyRequest(cmd);
|
||||
uint32_t start_time = 0;
|
||||
uint32_t eof_time;
|
||||
int answerLen = SendDataTag(cmd, sizeof(cmd), true, true, answer, ISO15693_MAX_RESPONSE_LENGTH, start_time, ISO15693_READER_TIMEOUT, &eof_time);
|
||||
start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
|
||||
int recvlen = SendDataTag(cmd, sizeof(cmd), true, true, answer, ISO15693_MAX_RESPONSE_LENGTH, start_time, ISO15693_READER_TIMEOUT, &eof_time);
|
||||
|
||||
// we should do a better check than this
|
||||
if (answerLen >= 12) {
|
||||
uint8_t uid[8];
|
||||
uid[0] = answer[9]; // always E0
|
||||
uid[1] = answer[8]; // IC Manufacturer code
|
||||
uid[2] = answer[7];
|
||||
uid[3] = answer[6];
|
||||
uid[4] = answer[5];
|
||||
uid[5] = answer[4];
|
||||
uid[6] = answer[3];
|
||||
uid[7] = answer[2];
|
||||
if (recvlen == PM3_ETEAROFF) { // tearoff occured
|
||||
reply_mix(CMD_ACK, recvlen, 0, 0, NULL, 0);
|
||||
} else {
|
||||
|
||||
if (DBGLEVEL >= DBG_EXTENDED) {
|
||||
Dbprintf("[+] UID = %02X%02X%02X%02X%02X%02X%02X%02X",
|
||||
uid[0], uid[1], uid[2], uid[3],
|
||||
uid[4], uid[5], uid[5], uid[6]
|
||||
);
|
||||
start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
|
||||
|
||||
// we should do a better check than this
|
||||
if (recvlen >= 12) {
|
||||
uint8_t uid[8];
|
||||
uid[0] = answer[9]; // always E0
|
||||
uid[1] = answer[8]; // IC Manufacturer code
|
||||
uid[2] = answer[7];
|
||||
uid[3] = answer[6];
|
||||
uid[4] = answer[5];
|
||||
uid[5] = answer[4];
|
||||
uid[6] = answer[3];
|
||||
uid[7] = answer[2];
|
||||
|
||||
if (DBGLEVEL >= DBG_EXTENDED) {
|
||||
Dbprintf("[+] UID = %02X%02X%02X%02X%02X%02X%02X%02X",
|
||||
uid[0], uid[1], uid[2], uid[3],
|
||||
uid[4], uid[5], uid[5], uid[6]
|
||||
);
|
||||
}
|
||||
// send UID back to client.
|
||||
// arg0 = 1 = OK
|
||||
// arg1 = len of response (12 bytes)
|
||||
// arg2 = rtf
|
||||
// asbytes = uid.
|
||||
reply_mix(CMD_ACK, 1, sizeof(uid), 0, uid, sizeof(uid));
|
||||
|
||||
if (DBGLEVEL >= DBG_EXTENDED) {
|
||||
Dbprintf("[+] %d octets read from IDENTIFY request:", recvlen);
|
||||
DbdecodeIso15693Answer(recvlen, answer);
|
||||
Dbhexdump(recvlen, answer, true);
|
||||
}
|
||||
} else {
|
||||
DbpString("Failed to select card");
|
||||
reply_mix(CMD_ACK, 0, 0, 0, NULL, 0);
|
||||
}
|
||||
// send UID back to client.
|
||||
// arg0 = 1 = OK
|
||||
// arg1 = len of response (12 bytes)
|
||||
// arg2 = rtf
|
||||
// asbytes = uid.
|
||||
reply_mix(CMD_ACK, 1, sizeof(uid), 0, uid, sizeof(uid));
|
||||
}
|
||||
|
||||
if (DBGLEVEL >= DBG_EXTENDED) {
|
||||
Dbprintf("[+] %d octets read from IDENTIFY request:", answerLen);
|
||||
DbdecodeIso15693Answer(answerLen, answer);
|
||||
Dbhexdump(answerLen, answer, true);
|
||||
}
|
||||
|
||||
switch_off();
|
||||
BigBuf_free();
|
||||
}
|
||||
|
@ -1694,6 +1708,11 @@ void SimTagIso15693(uint8_t *uid) {
|
|||
|
||||
bool exit_loop = false;
|
||||
while (exit_loop == false) {
|
||||
|
||||
button_pressed = BUTTON_PRESS();
|
||||
if (button_pressed || data_available())
|
||||
break;
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
// find reader field
|
||||
|
@ -1767,6 +1786,11 @@ void BruteforceIso15693Afi(uint32_t speed) {
|
|||
|
||||
if (recvlen >= 12) {
|
||||
Dbprintf("NoAFI UID = %s", iso15693_sprintUID(NULL, recv + 2));
|
||||
} else {
|
||||
DbpString("Failed to select card");
|
||||
reply_ng(CMD_ACK, PM3_ESOFT, NULL, 0);
|
||||
switch_off();
|
||||
return;
|
||||
}
|
||||
|
||||
// now with AFI
|
||||
|
@ -1816,10 +1840,9 @@ void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint
|
|||
|
||||
LED_A_ON();
|
||||
|
||||
int recvlen = 0;
|
||||
uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
|
||||
uint32_t eof_time = 0;
|
||||
uint16_t timeout;
|
||||
uint32_t eof_time = 0;
|
||||
bool request_answer = false;
|
||||
|
||||
switch (data[1]) {
|
||||
|
@ -1837,43 +1860,29 @@ void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint
|
|||
timeout = ISO15693_READER_TIMEOUT;
|
||||
}
|
||||
|
||||
if (DBGLEVEL >= DBG_EXTENDED) {
|
||||
Dbprintf("SEND:");
|
||||
Dbhexdump(datalen, data, false);
|
||||
}
|
||||
|
||||
uint32_t start_time = 0;
|
||||
recvlen = SendDataTag(data, datalen, true, speed, (recv ? recvbuf : NULL), sizeof(recvbuf), start_time, timeout, &eof_time);
|
||||
int recvlen = SendDataTag(data, datalen, true, speed, (recv ? recvbuf : NULL), sizeof(recvbuf), start_time, timeout, &eof_time);
|
||||
|
||||
// send a single EOF to get the tag response
|
||||
if (request_answer) {
|
||||
start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
|
||||
recvlen = SendDataTagEOF((recv ? recvbuf : NULL), sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT, &eof_time);
|
||||
if (recvlen == PM3_ETEAROFF) { // tearoff occured
|
||||
reply_mix(CMD_ACK, recvlen, 0, 0, NULL, 0);
|
||||
} else {
|
||||
|
||||
// send a single EOF to get the tag response
|
||||
if (request_answer) {
|
||||
start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
|
||||
recvlen = SendDataTagEOF((recv ? recvbuf : NULL), sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT, &eof_time);
|
||||
}
|
||||
|
||||
if (recv) {
|
||||
recvlen = MIN(recvlen, ISO15693_MAX_RESPONSE_LENGTH);
|
||||
reply_mix(CMD_ACK, recvlen, 0, 0, recvbuf, recvlen);
|
||||
} else {
|
||||
reply_mix(CMD_ACK, 1, 0, 0, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// for the time being, switch field off to protect rdv4.0
|
||||
// note: this prevents using hf 15 cmd with s option - which isn't implemented yet anyway
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LED_D_OFF();
|
||||
|
||||
if (recv) {
|
||||
|
||||
if (recvlen > ISO15693_MAX_RESPONSE_LENGTH) {
|
||||
recvlen = ISO15693_MAX_RESPONSE_LENGTH;
|
||||
}
|
||||
reply_mix(CMD_ACK, recvlen, 0, 0, recvbuf, recvlen);
|
||||
|
||||
if (DBGLEVEL >= DBG_EXTENDED) {
|
||||
|
||||
Dbprintf("RECV:");
|
||||
if (recvlen > 0) {
|
||||
Dbhexdump(recvlen, recvbuf, false);
|
||||
DbdecodeIso15693Answer(recvlen, recvbuf);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
101
armsrc/lfops.c
101
armsrc/lfops.c
|
@ -2467,7 +2467,7 @@ static uint8_t Prepare_Data(uint16_t data_low, uint16_t data_hi) {
|
|||
// Requires: forwarLink_data filled with valid bits (1 bit per byte)
|
||||
// fwd_bit_count set with number of bits to be sent
|
||||
//====================================================================
|
||||
static void SendForward(uint8_t fwd_bit_count) {
|
||||
static void SendForward(uint8_t fwd_bit_count, bool fast) {
|
||||
|
||||
// iceman, 21.3us increments for the USclock verification.
|
||||
// 55FC * 8us == 440us / 21.3 === 20.65 steps. could be too short. Go for 56FC instead
|
||||
|
@ -2480,9 +2480,10 @@ static void SendForward(uint8_t fwd_bit_count) {
|
|||
fwd_write_ptr = forwardLink_data;
|
||||
fwd_bit_sz = fwd_bit_count;
|
||||
|
||||
// Set up FPGA, 125kHz or 95 divisor
|
||||
LFSetupFPGAForADC(LF_DIVISOR_125, true);
|
||||
|
||||
if (! fast) {
|
||||
// Set up FPGA, 125kHz or 95 divisor
|
||||
LFSetupFPGAForADC(LF_DIVISOR_125, true);
|
||||
}
|
||||
// force 1st mod pulse (start gap must be longer for 4305)
|
||||
fwd_bit_sz--; //prepare next bit modulation
|
||||
fwd_write_ptr++;
|
||||
|
@ -2490,28 +2491,98 @@ static void SendForward(uint8_t fwd_bit_count) {
|
|||
TurnReadLF_off(EM_START_GAP);
|
||||
TurnReadLFOn(18 * 8);
|
||||
|
||||
// now start writting with bitbanging the antenna. (each bit should be 32*8 total length)
|
||||
// now start writing with bitbanging the antenna. (each bit should be 32*8 total length)
|
||||
while (fwd_bit_sz-- > 0) { //prepare next bit modulation
|
||||
if (((*fwd_write_ptr++) & 1) == 1) {
|
||||
WaitUS(32 * 8);
|
||||
} else {
|
||||
TurnReadLF_off(23 * 8);
|
||||
TurnReadLFOn((32 - 23) * 8);
|
||||
TurnReadLFOn(18 * 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void EM4xLogin(uint32_t pwd) {
|
||||
static void EM4xLoginEx(uint32_t pwd) {
|
||||
forward_ptr = forwardLink_data;
|
||||
uint8_t len = Prepare_Cmd(FWD_CMD_LOGIN);
|
||||
len += Prepare_Data(pwd & 0xFFFF, pwd >> 16);
|
||||
SendForward(len);
|
||||
SendForward(len, false);
|
||||
//WaitUS(20); // no wait for login command.
|
||||
// should receive
|
||||
// 0000 1010 ok
|
||||
// 0000 0001 fail
|
||||
}
|
||||
|
||||
void EM4xBruteforce(uint32_t start_pwd, uint32_t n) {
|
||||
// With current timing, 18.6 ms per test = 53.8 pwds/s
|
||||
reply_ng(CMD_LF_EM4X_BF, PM3_SUCCESS, NULL, 0);
|
||||
StartTicks();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
WaitMS(20);
|
||||
LED_A_ON();
|
||||
LFSetupFPGAForADC(LF_DIVISOR_125, true);
|
||||
uint32_t candidates_found = 0;
|
||||
for (uint32_t pwd = start_pwd; pwd < 0xFFFFFFFF; pwd++) {
|
||||
if (((pwd - start_pwd) & 0x3F) == 0x00) {
|
||||
WDT_HIT();
|
||||
if (BUTTON_PRESS() || data_available()) {
|
||||
Dbprintf("EM4x05 Bruteforce Interrupted");
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Report progress every 256 attempts
|
||||
if (((pwd - start_pwd) & 0xFF) == 0x00) {
|
||||
Dbprintf("Trying: %06Xxx", pwd >> 8);
|
||||
}
|
||||
clear_trace();
|
||||
|
||||
forward_ptr = forwardLink_data;
|
||||
uint8_t len = Prepare_Cmd(FWD_CMD_LOGIN);
|
||||
len += Prepare_Data(pwd & 0xFFFF, pwd >> 16);
|
||||
SendForward(len, true);
|
||||
|
||||
WaitUS(400);
|
||||
DoPartialAcquisition(0, false, 350, 1000);
|
||||
uint8_t *mem = BigBuf_get_addr();
|
||||
if (mem[334] < 128) {
|
||||
candidates_found++;
|
||||
Dbprintf("Password candidate: " _GREEN_("%08X"), pwd);
|
||||
if ((n != 0) && (candidates_found == n)) {
|
||||
Dbprintf("EM4x05 Bruteforce Stopped. %i candidate%s found", candidates_found, candidates_found > 1 ? "s" : "");
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Beware: if smaller, tag might not have time to be back in listening state yet
|
||||
WaitMS(1);
|
||||
}
|
||||
StopTicks();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
}
|
||||
|
||||
void EM4xLogin(uint32_t pwd) {
|
||||
|
||||
StartTicks();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
WaitMS(20);
|
||||
|
||||
LED_A_ON();
|
||||
|
||||
// clear buffer now so it does not interfere with timing later
|
||||
BigBuf_Clear_ext(false);
|
||||
|
||||
EM4xLoginEx(pwd);
|
||||
|
||||
WaitUS(400);
|
||||
// We need to acquire more than needed, to help demodulators finding the proper modulation
|
||||
DoPartialAcquisition(0, false, 6000, 1000);
|
||||
|
||||
StopTicks();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
reply_ng(CMD_LF_EM4X_LOGIN, PM3_SUCCESS, NULL, 0);
|
||||
LEDsoff();
|
||||
}
|
||||
|
||||
void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) {
|
||||
|
||||
StartTicks();
|
||||
|
@ -2529,17 +2600,17 @@ void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) {
|
|||
* 0000 1010 ok
|
||||
* 0000 0001 fail
|
||||
**/
|
||||
if (usepwd) EM4xLogin(pwd);
|
||||
if (usepwd) EM4xLoginEx(pwd);
|
||||
|
||||
forward_ptr = forwardLink_data;
|
||||
uint8_t len = Prepare_Cmd(FWD_CMD_READ);
|
||||
len += Prepare_Addr(addr);
|
||||
|
||||
SendForward(len);
|
||||
SendForward(len, false);
|
||||
|
||||
WaitUS(400);
|
||||
|
||||
DoPartialAcquisition(20, false, 6000, 1000);
|
||||
DoPartialAcquisition(0, false, 6000, 1000);
|
||||
|
||||
StopTicks();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
|
@ -2564,14 +2635,14 @@ void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd) {
|
|||
* 0000 1010 ok.
|
||||
* 0000 0001 fail
|
||||
**/
|
||||
if (usepwd) EM4xLogin(pwd);
|
||||
if (usepwd) EM4xLoginEx(pwd);
|
||||
|
||||
forward_ptr = forwardLink_data;
|
||||
uint8_t len = Prepare_Cmd(FWD_CMD_WRITE);
|
||||
len += Prepare_Addr(addr);
|
||||
len += Prepare_Data(data & 0xFFFF, data >> 16);
|
||||
|
||||
SendForward(len);
|
||||
SendForward(len, false);
|
||||
|
||||
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured
|
||||
StopTicks();
|
||||
|
@ -2607,13 +2678,13 @@ void EM4xProtectWord(uint32_t data, uint32_t pwd, uint8_t usepwd) {
|
|||
* 0000 1010 ok.
|
||||
* 0000 0001 fail
|
||||
**/
|
||||
if (usepwd) EM4xLogin(pwd);
|
||||
if (usepwd) EM4xLoginEx(pwd);
|
||||
|
||||
forward_ptr = forwardLink_data;
|
||||
uint8_t len = Prepare_Cmd(FWD_CMD_PROTECT);
|
||||
len += Prepare_Data(data & 0xFFFF, data >> 16);
|
||||
|
||||
SendForward(len);
|
||||
SendForward(len, false);
|
||||
|
||||
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured
|
||||
StopTicks();
|
||||
|
|
|
@ -56,6 +56,8 @@ void T55xxDangerousRawTest(uint8_t *data);
|
|||
|
||||
void TurnReadLFOn(uint32_t delay);
|
||||
|
||||
void EM4xLogin(uint32_t pwd);
|
||||
void EM4xBruteforce(uint32_t start_pwd, uint32_t n);
|
||||
void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd);
|
||||
void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd);
|
||||
void EM4xProtectWord(uint32_t data, uint32_t pwd, uint8_t usepwd);
|
||||
|
|
|
@ -2752,15 +2752,15 @@ void MifareU_Counter_Tearoff(uint8_t counter, uint32_t tearoff_time) {
|
|||
|
||||
// Send MFU counter increase cmd
|
||||
uint8_t cmd[] = {
|
||||
MIFARE_ULEV1_INCR_CNT,
|
||||
counter,
|
||||
0, // lsb
|
||||
0,
|
||||
0, // msb
|
||||
0, // rfu
|
||||
0,
|
||||
0,
|
||||
};
|
||||
MIFARE_ULEV1_INCR_CNT,
|
||||
counter,
|
||||
0, // lsb
|
||||
0,
|
||||
0, // msb
|
||||
0, // rfu
|
||||
0,
|
||||
0,
|
||||
};
|
||||
AddCrc14A(cmd, sizeof(cmd) - 2);
|
||||
|
||||
// anticollision / select card
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
# -DANDROID_NATIVE_API_LEVEL=android-19 \
|
||||
# -DSKIPBT=1 -DSKIPPYTHON=1 -DSKIPPTHREAD=1 ..
|
||||
|
||||
message(STATUS "CMake ${CMAKE_VERSION}")
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
project(proxmark3)
|
||||
SET (PM3_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/..)
|
||||
|
@ -248,6 +249,7 @@ set (TARGET_SOURCES
|
|||
${PM3_ROOT}/client/src/cmdlfcotag.c
|
||||
${PM3_ROOT}/client/src/cmdlfdestron.c
|
||||
${PM3_ROOT}/client/src/cmdlfem4x.c
|
||||
${PM3_ROOT}/client/src/cmdlfem4x05.c
|
||||
${PM3_ROOT}/client/src/cmdlfem4x50.c
|
||||
${PM3_ROOT}/client/src/cmdlffdxb.c
|
||||
${PM3_ROOT}/client/src/cmdlfgallagher.c
|
||||
|
@ -495,20 +497,10 @@ if (NOT APPLE)
|
|||
set(ADDITIONAL_LNK ${ADDITIONAL_LNK} -Wl,--as-needed -latomic -Wl,--no-as-needed)
|
||||
endif (NOT APPLE)
|
||||
|
||||
|
||||
find_library(pm3rrg_rdv4_cliparser REQUIRED)
|
||||
find_library(pm3rrg_rdv4_tinycbor REQUIRED)
|
||||
find_library(pm3rrg_rdv4_lua REQUIRED)
|
||||
find_library(pm3rrg_rdv4_mbedtls REQUIRED)
|
||||
find_library(pm3rrg_rdv4_reveng REQUIRED)
|
||||
find_library(pm3rrg_rdv4_hardnested REQUIRED)
|
||||
|
||||
if (NOT JANSSON_FOUND)
|
||||
find_library(pm3rrg_rdv4_jansson REQUIRED)
|
||||
set(ADDITIONAL_LNK pm3rrg_rdv4_jansson ${ADDITIONAL_LNK})
|
||||
endif (NOT JANSSON_FOUND)
|
||||
if (NOT WHEREAMI_FOUND)
|
||||
find_library(pm3rrg_rdv4_whereami REQUIRED)
|
||||
set(ADDITIONAL_LNK pm3rrg_rdv4_whereami ${ADDITIONAL_LNK})
|
||||
endif (NOT WHEREAMI_FOUND)
|
||||
|
||||
|
|
|
@ -443,6 +443,7 @@ SRCS = aidsearch.c \
|
|||
cmdlfcotag.c \
|
||||
cmdlfdestron.c \
|
||||
cmdlfem4x.c \
|
||||
cmdlfem4x05.c \
|
||||
cmdlfem4x50.c \
|
||||
cmdlffdxb.c \
|
||||
cmdlfguard.c \
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# version
|
||||
message(STATUS "CMake ${CMAKE_VERSION}")
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -fvisibility=hidden -w")
|
||||
|
@ -12,7 +13,6 @@ add_subdirectory(../deps deps)
|
|||
if (CMAKE_MAKE_PROGRAM MATCHES ".*ninja.*")
|
||||
set(BZIP2_INCLUDE_DIRS ${BZIP2_ROOT})
|
||||
set(BZIP2_LIBRARIES pm3rrg_rdv4_bzip2)
|
||||
find_library(pm3rrg_rdv4_bzip2 REQUIRED)
|
||||
elseif (UNIX) # Cross compile at Unix Makefile System.
|
||||
# bzip2 dep.
|
||||
include(ExternalProject)
|
||||
|
@ -190,15 +190,6 @@ target_include_directories(pm3rrg_rdv4 PRIVATE
|
|||
${PM3_ROOT}/common_fpga
|
||||
${PM3_ROOT}/client/src)
|
||||
|
||||
find_library(pm3rrg_rdv4_cliparser REQUIRED)
|
||||
find_library(pm3rrg_rdv4_jansson REQUIRED)
|
||||
find_library(pm3rrg_rdv4_tinycbor REQUIRED)
|
||||
find_library(pm3rrg_rdv4_lua REQUIRED)
|
||||
find_library(pm3rrg_rdv4_mbedtls REQUIRED)
|
||||
find_library(pm3rrg_rdv4_reveng REQUIRED)
|
||||
find_library(pm3rrg_rdv4_hardnested REQUIRED)
|
||||
find_library(pm3rrg_rdv4_whereami REQUIRED)
|
||||
|
||||
target_link_libraries(pm3rrg_rdv4
|
||||
${BZIP2_LIBRARIES}
|
||||
pm3rrg_rdv4_hardnested
|
||||
|
|
|
@ -14,7 +14,6 @@ add_library(pm3rrg_rdv4_amiibo STATIC
|
|||
if (NOT TARGET pm3rrg_rdv4_mbedtls)
|
||||
include(mbedtls.cmake)
|
||||
endif()
|
||||
find_library(pm3rrg_rdv4_mbedtls REQUIRED)
|
||||
target_link_libraries(pm3rrg_rdv4_amiibo PRIVATE
|
||||
m
|
||||
pm3rrg_rdv4_mbedtls)
|
||||
|
|
|
@ -3,6 +3,7 @@ add_library(pm3rrg_rdv4_cliparser STATIC
|
|||
cliparser/cliparser.c
|
||||
)
|
||||
|
||||
target_compile_definitions(pm3rrg_rdv4_cliparser PRIVATE _ISOC99_SOURCE)
|
||||
target_include_directories(pm3rrg_rdv4_cliparser PRIVATE
|
||||
../../common
|
||||
../../include
|
||||
|
|
|
@ -9,3 +9,12 @@ MYSRCS = \
|
|||
LIB_A = libcliparser.a
|
||||
|
||||
include ../../../Makefile.host
|
||||
|
||||
$(info PLATFORM $(platform))
|
||||
ifneq (,$(findstring MINGW,$(platform)))
|
||||
# Mingw uses by default Microsoft printf, we want the GNU printf (e.g. for %z)
|
||||
# and setting _ISOC99_SOURCE sets internally __USE_MINGW_ANSI_STDIO=1
|
||||
# FTR __USE_MINGW_ANSI_STDIO seems deprecated in Mingw32
|
||||
# but not Mingw64 https://fr.osdn.net/projects/mingw/lists/archive/users/2019-January/000199.html
|
||||
CFLAGS += -D_ISOC99_SOURCE
|
||||
endif
|
||||
|
|
|
@ -11,8 +11,10 @@
|
|||
#include "cliparser.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <util.h> // Get color constants
|
||||
#include <ui.h> // get PrintAndLogEx
|
||||
#include <util.h> // Get color constants
|
||||
#include <ui.h> // get PrintAndLogEx
|
||||
#include <ctype.h> // tolower
|
||||
#include <inttypes.h> // PRIu64
|
||||
|
||||
#ifndef ARRAYLEN
|
||||
# define ARRAYLEN(x) (sizeof(x)/sizeof((x)[0]))
|
||||
|
@ -125,7 +127,6 @@ int CLIParserParseArg(CLIParserContext *ctx, int argc, char **argv, void *vargta
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
enum ParserState {
|
||||
PS_FIRST,
|
||||
PS_ARGUMENT,
|
||||
|
@ -203,34 +204,33 @@ int CLIParserParseStringEx(CLIParserContext *ctx, const char *str, void *vargtab
|
|||
int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) {
|
||||
*datalen = 0;
|
||||
|
||||
int ibuf = 0;
|
||||
uint8_t tmp_buf[512] = {0};
|
||||
int res = CLIParamStrToBuf(argstr, tmp_buf, maxdatalen * 2, &ibuf); // *2 because here HEX
|
||||
int tmplen = 0;
|
||||
uint8_t tmpstr[(256 * 2) + 1] = {0};
|
||||
|
||||
// concat all strings in argstr into tmpstr[]
|
||||
//
|
||||
int res = CLIParamStrToBuf(argstr, tmpstr, sizeof(tmpstr), &tmplen);
|
||||
if (res) {
|
||||
printf("Parameter error: buffer overflow.\n");
|
||||
fflush(stdout);
|
||||
return res;
|
||||
}
|
||||
if (ibuf == 0) {
|
||||
if (tmplen == 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
switch (param_gethex_to_eol((char *)tmp_buf, 0, data, maxdatalen, datalen)) {
|
||||
res = param_gethex_to_eol((char *)tmpstr, 0, data, maxdatalen, datalen);
|
||||
switch (res) {
|
||||
case 1:
|
||||
printf("Parameter error: Invalid HEX value.\n");
|
||||
fflush(stdout);
|
||||
return 1;
|
||||
printf("Parameter error: Invalid HEX value\n");
|
||||
break;
|
||||
case 2:
|
||||
printf("Parameter error: parameter too large.\n");
|
||||
fflush(stdout);
|
||||
return 2;
|
||||
printf("Parameter error: parameter too large\n");
|
||||
break;
|
||||
case 3:
|
||||
printf("Parameter error: Hex string must have even number of digits.\n");
|
||||
fflush(stdout);
|
||||
return 3;
|
||||
printf("Parameter error: Hex string must have EVEN number of digits\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
fflush(stdout);
|
||||
return res;
|
||||
}
|
||||
|
||||
int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) {
|
||||
|
@ -238,28 +238,55 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
|
|||
if (!argstr->count)
|
||||
return 0;
|
||||
|
||||
uint8_t tmp_buf[512] = {0};
|
||||
uint8_t tmpstr[(256 * 2) + 1] = {0};
|
||||
int ibuf = 0;
|
||||
|
||||
for (int i = 0; i < argstr->count; i++) {
|
||||
|
||||
int len = strlen(argstr->sval[i]);
|
||||
memcpy(&tmp_buf[ibuf], argstr->sval[i], len);
|
||||
|
||||
if (len > ((sizeof(tmpstr) / 2) - ibuf)) {
|
||||
printf("Parameter error: string too long (%i chars), expect MAX %zu chars\n", len + ibuf, (sizeof(tmpstr) / 2));
|
||||
fflush(stdout);
|
||||
return 2;
|
||||
}
|
||||
|
||||
memcpy(&tmpstr[ibuf], argstr->sval[i], len);
|
||||
|
||||
ibuf += len;
|
||||
}
|
||||
tmp_buf[ibuf] = 0;
|
||||
|
||||
if (!ibuf)
|
||||
ibuf = MIN(ibuf, (sizeof(tmpstr) / 2));
|
||||
tmpstr[ibuf] = 0;
|
||||
|
||||
if (ibuf == 0)
|
||||
return 0;
|
||||
|
||||
if (ibuf + 1 > maxdatalen) {
|
||||
printf("Parameter error: string too long, expect max %i chars\n", maxdatalen - 1);
|
||||
if (ibuf > maxdatalen) {
|
||||
printf("Parameter error: string too long (%i chars), expected MAX %i chars\n", ibuf, maxdatalen);
|
||||
fflush(stdout);
|
||||
return 2;
|
||||
}
|
||||
|
||||
memcpy(data, tmp_buf, ibuf + 1);
|
||||
memcpy(data, tmpstr, ibuf + 1);
|
||||
*datalen = ibuf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t arg_get_u64_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint64_t def) {
|
||||
uint64_t rv = 0;
|
||||
uint8_t data[8];
|
||||
int datalen = 0;
|
||||
int res = CLIParamHexToBuf(arg_get_str(ctx, paramnum), data, sizeof(data), &datalen);
|
||||
if (res == 0 && datalen > 0) {
|
||||
for (uint8_t i = 0; i < datalen; i++) {
|
||||
rv <<= 8;
|
||||
rv |= data[i];
|
||||
}
|
||||
} else {
|
||||
rv = def;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
|
||||
#define CLIGetHexWithReturn(ctx, paramnum, data, datalen) if (CLIParamHexToBuf(arg_get_str((ctx), (paramnum)), (data), sizeof((data)), (datalen))) {CLIParserFree((ctx)); return PM3_ESOFT;}
|
||||
|
||||
#define CLIGetStrWithReturn(ctx, paramnum, data, datalen) if (CLIParamStrToBuf(arg_get_str((ctx), (paramnum)), (data), sizeof((data)), (datalen))) {CLIParserFree((ctx)); return PM3_ESOFT;}
|
||||
#define CLIGetStrWithReturn(ctx, paramnum, data, datalen) if (CLIParamStrToBuf(arg_get_str((ctx), (paramnum)), (data), (*datalen), (datalen))) {CLIParserFree((ctx)); return PM3_ESOFT;}
|
||||
|
||||
typedef struct {
|
||||
void **argtable;
|
||||
|
@ -66,4 +66,6 @@ int CLIParserParseArg(CLIParserContext *ctx, int argc, char **argv, void *vargta
|
|||
|
||||
int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen);
|
||||
int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen);
|
||||
|
||||
uint64_t arg_get_u64_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint64_t def);
|
||||
#endif
|
||||
|
|
|
@ -1203,3 +1203,9 @@ FEE2A3FBC5B6
|
|||
# taurus avm
|
||||
#
|
||||
005078565703
|
||||
#
|
||||
# Ving?
|
||||
#
|
||||
0602721E8F06
|
||||
FC0B50AF8700
|
||||
F7BA51A9434E
|
|
@ -26,6 +26,8 @@ A5B4C3D2
|
|||
50520901
|
||||
# default PROX
|
||||
50524F58
|
||||
# blue gun EM4305
|
||||
F9DCEBA0
|
||||
# Default pwd, simple:
|
||||
00000000
|
||||
11111111
|
||||
|
@ -45,9 +47,6 @@ EEEEEEEE
|
|||
FFFFFFFF
|
||||
a0a1a2a3
|
||||
b0b1b2b3
|
||||
aabbccdd
|
||||
bbccddee
|
||||
ccddeeff
|
||||
50415353
|
||||
00000001
|
||||
00000002
|
||||
|
@ -123,3 +122,7 @@ b5f44686 # seeds ul-ev1
|
|||
C6EF3720 # TEA
|
||||
7854794A # xbox tea constant :)
|
||||
F1EA5EED # burtle
|
||||
69314718 # ln2
|
||||
57721566 # euler constant (dec)
|
||||
93C467E3 # euler constant (hex)
|
||||
27182818 # natural log
|
||||
|
|
|
@ -36,7 +36,7 @@ arguments = [[
|
|||
-k <key> - the current six byte key with write access
|
||||
-n <key> - the new key that will be written to the card
|
||||
-a <access> - the new access bytes that will be written to the card
|
||||
-x - execute the commands aswell.
|
||||
-x - execute the commands as well.
|
||||
]]
|
||||
|
||||
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
|
||||
|
|
|
@ -36,7 +36,7 @@ arguments = [[
|
|||
end
|
||||
]]
|
||||
|
||||
local set_tearoff_delay = 'hw tearoff -s --on --delay %d'
|
||||
local set_tearoff_delay = 'hw tearoff --on --delay %d'
|
||||
local wr_template = 'lf em 4x05_write %s %s %s'
|
||||
|
||||
---
|
||||
|
@ -250,6 +250,10 @@ local function main(args)
|
|||
local wordstr14b = ('%08X'):format(word14b)
|
||||
if (wordstr14b == '00000000') then
|
||||
reset(wr_value, password)
|
||||
word14b, err14b = core.em4x05_read(14, password)
|
||||
if err14b then
|
||||
return oops(err14b)
|
||||
end
|
||||
end
|
||||
if (wordstr14b ~= rd_value) then
|
||||
local word15b, err15b = core.em4x05_read(15, password)
|
||||
|
@ -299,17 +303,17 @@ local function main(args)
|
|||
else
|
||||
print(('[=] Status: failed to commit => '..ansicolors.red..'FAIL: '..ansicolors.reset..'14: %08X 15: %08X'):format(word14b, word15b))
|
||||
end
|
||||
if auto then
|
||||
n = 0
|
||||
ed = sd
|
||||
else
|
||||
tries = 0
|
||||
soon = 0
|
||||
late = 0
|
||||
end
|
||||
else
|
||||
print(('[=] Status: 15 bitflipped but inactive => '..ansicolors.yellow..'PROMISING: '..ansicolors.reset..'14: %08X 15: '..ansicolors.cyan..'%08X'..ansicolors.reset):format(word14, word15))
|
||||
end
|
||||
if auto then
|
||||
n = 0
|
||||
ed = sd
|
||||
else
|
||||
tries = 0
|
||||
soon = 0
|
||||
late = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
if not auto then
|
||||
|
|
|
@ -57,7 +57,7 @@ static int usage_hf_search(void) {
|
|||
}
|
||||
|
||||
static int usage_hf_sniff(void) {
|
||||
PrintAndLogEx(NORMAL, "The high frequence sniffer will assign all available memory on device for sniffed data");
|
||||
PrintAndLogEx(NORMAL, "The high frequency sniffer will assign all available memory on device for sniffed data");
|
||||
PrintAndLogEx(NORMAL, "Use " _YELLOW_("'data samples'")" command to download from device, and " _YELLOW_("'data plot'")" to look at it");
|
||||
PrintAndLogEx(NORMAL, "Press button to quit the sniffing.\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: hf sniff <skip pairs> <skip triggers>");
|
||||
|
@ -311,19 +311,8 @@ int CmdHFSniff(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int CmdHFPlot(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf plot",
|
||||
"Plots HF signal after RF signal path and A/D conversion.",
|
||||
"This can be used after any hf command and will show the last few milliseconds of the HF signal.\n"
|
||||
"Note: If the last hf command terminated because of a timeout you will most probably see nothing.\n");
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
int handle_hf_plot(void) {
|
||||
|
||||
uint8_t buf[FPGA_TRACE_SIZE];
|
||||
|
||||
PacketResponseNG response;
|
||||
|
@ -333,7 +322,7 @@ int CmdHFPlot(const char *Cmd) {
|
|||
}
|
||||
|
||||
for (size_t i = 0; i < FPGA_TRACE_SIZE; i++) {
|
||||
GraphBuffer[i] = ((int)buf[i]) - 127;
|
||||
GraphBuffer[i] = ((int)buf[i]) - 128;
|
||||
}
|
||||
|
||||
GraphTraceLen = FPGA_TRACE_SIZE;
|
||||
|
@ -349,14 +338,31 @@ int CmdHFPlot(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int CmdHFPlot(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf plot",
|
||||
"Plots HF signal after RF signal path and A/D conversion.",
|
||||
"This can be used after any hf command and will show the last few milliseconds of the HF signal.\n"
|
||||
"Note: If the last hf command terminated because of a timeout you will most probably see nothing.\n");
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
return handle_hf_plot();
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
|
||||
{"--------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("High Frequency") " -----------------------"},
|
||||
{"14a", CmdHF14A, AlwaysAvailable, "{ ISO14443A RFIDs... }"},
|
||||
{"14b", CmdHF14B, AlwaysAvailable, "{ ISO14443B RFIDs... }"},
|
||||
{"15", CmdHF15, AlwaysAvailable, "{ ISO15693 RFIDs... }"},
|
||||
// {"cryptorf", CmdHFCryptoRF, AlwaysAvailable, "{ CryptoRF RFIDs... }"},
|
||||
{"epa", CmdHFEPA, AlwaysAvailable, "{ German Identification Card... }"},
|
||||
{"felica", CmdHFFelica, AlwaysAvailable, "{ ISO18092 / Felica RFIDs... }"},
|
||||
{"felica", CmdHFFelica, AlwaysAvailable, "{ ISO18092 / FeliCa RFIDs... }"},
|
||||
{"fido", CmdHFFido, AlwaysAvailable, "{ FIDO and FIDO2 authenticators... }"},
|
||||
{"iclass", CmdHFiClass, AlwaysAvailable, "{ ICLASS RFIDs... }"},
|
||||
{"legic", CmdHFLegic, AlwaysAvailable, "{ LEGIC RFIDs... }"},
|
||||
|
@ -369,6 +375,8 @@ static command_t CommandTable[] = {
|
|||
{"thinfilm", CmdHFThinfilm, AlwaysAvailable, "{ Thinfilm RFIDs... }"},
|
||||
{"topaz", CmdHFTopaz, AlwaysAvailable, "{ TOPAZ (NFC Type 1) RFIDs... }"},
|
||||
{"waveshare", CmdHFWaveshare, AlwaysAvailable, "{ Waveshare NFC ePaper... }"},
|
||||
{"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"},
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"list", CmdTraceList, AlwaysAvailable, "List protocol data in trace buffer"},
|
||||
{"plot", CmdHFPlot, IfPm3Hfplot, "Plot signal"},
|
||||
{"tune", CmdHFTune, IfPm3Present, "Continuously measure HF antenna tuning"},
|
||||
|
|
|
@ -19,4 +19,5 @@ int CmdHFSearch(const char *Cmd);
|
|||
int CmdHFSniff(const char *Cmd);
|
||||
int CmdHFPlot(const char *Cmd);
|
||||
|
||||
int handle_hf_plot(void);
|
||||
#endif
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include "crc16.h"
|
||||
#include "util_posix.h" // msclock
|
||||
#include "aidsearch.h"
|
||||
#include "cmdhf.h" // handle HF plot
|
||||
|
||||
|
||||
bool APDUInFramingEnable = true;
|
||||
|
||||
|
@ -265,6 +267,7 @@ static int usage_hf_14a_reader(void) {
|
|||
PrintAndLogEx(NORMAL, " s silent (no messages)");
|
||||
PrintAndLogEx(NORMAL, " x just drop the signal field");
|
||||
PrintAndLogEx(NORMAL, " 3 ISO14443-3 select only (skip RATS)");
|
||||
PrintAndLogEx(NORMAL, " @ continuous mode. Updates hf plot as well");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -475,9 +478,9 @@ int Hf14443_4aGetCardData(iso14a_card_select_t *card) {
|
|||
static int CmdHF14AReader(const char *Cmd) {
|
||||
|
||||
uint32_t cm = ISO14A_CONNECT;
|
||||
bool disconnectAfter = true, silent = false;
|
||||
bool disconnectAfter = true, silent = false, continuous = false;
|
||||
int cmdp = 0;
|
||||
|
||||
int res = PM3_SUCCESS;
|
||||
while (param_getchar(Cmd, cmdp) != 0x00) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
|
@ -494,6 +497,9 @@ static int CmdHF14AReader(const char *Cmd) {
|
|||
case 'x':
|
||||
cm &= ~ISO14A_CONNECT;
|
||||
break;
|
||||
case '@':
|
||||
continuous = true;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown command.");
|
||||
return PM3_EINVARG;
|
||||
|
@ -503,60 +509,86 @@ static int CmdHF14AReader(const char *Cmd) {
|
|||
|
||||
if (!disconnectAfter)
|
||||
cm |= ISO14A_NO_DISCONNECT;
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_ISO14443A_READER, cm, 0, 0, NULL, 0);
|
||||
|
||||
if (ISO14A_CONNECT & cm) {
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
|
||||
if (!silent) PrintAndLogEx(WARNING, "iso14443a card select failed");
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
iso14a_card_select_t card;
|
||||
memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
|
||||
|
||||
/*
|
||||
0: couldn't read
|
||||
1: OK, with ATS
|
||||
2: OK, no ATS
|
||||
3: proprietary Anticollision
|
||||
*/
|
||||
uint64_t select_status = resp.oldarg[0];
|
||||
|
||||
if (select_status == 0) {
|
||||
if (!silent) PrintAndLogEx(WARNING, "iso14443a card select failed");
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
if (select_status == 3) {
|
||||
PrintAndLogEx(INFO, "Card doesn't support standard iso14443-3 anticollision");
|
||||
PrintAndLogEx(SUCCESS, "ATQA: %02x %02x", card.atqa[1], card.atqa[0]);
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
|
||||
PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02x %02x"), card.atqa[1], card.atqa[0]);
|
||||
PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02x [%" PRIu64 "]"), card.sak, resp.oldarg[0]);
|
||||
|
||||
if (card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
|
||||
PrintAndLogEx(SUCCESS, " ATS: " _GREEN_("%s"), sprint_hex(card.ats, card.ats_len));
|
||||
}
|
||||
|
||||
if (!disconnectAfter) {
|
||||
if (!silent) PrintAndLogEx(SUCCESS, "Card is selected. You can now start sending commands");
|
||||
}
|
||||
if (continuous) {
|
||||
PrintAndLogEx(INFO, "Press " _GREEN_("Enter") " to exit");
|
||||
}
|
||||
do {
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_ISO14443A_READER, cm, 0, 0, NULL, 0);
|
||||
|
||||
if (ISO14A_CONNECT & cm) {
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
|
||||
if (!silent) PrintAndLogEx(WARNING, "iso14443a card select failed");
|
||||
DropField();
|
||||
res = PM3_ESOFT;
|
||||
goto plot;
|
||||
}
|
||||
|
||||
iso14a_card_select_t card;
|
||||
memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
|
||||
|
||||
/*
|
||||
0: couldn't read
|
||||
1: OK, with ATS
|
||||
2: OK, no ATS
|
||||
3: proprietary Anticollision
|
||||
*/
|
||||
uint64_t select_status = resp.oldarg[0];
|
||||
|
||||
if (select_status == 0) {
|
||||
if (!silent) PrintAndLogEx(WARNING, "iso14443a card select failed");
|
||||
DropField();
|
||||
res = PM3_ESOFT;
|
||||
goto plot;
|
||||
}
|
||||
|
||||
if (select_status == 3) {
|
||||
if (!(silent && continuous)) {
|
||||
PrintAndLogEx(INFO, "Card doesn't support standard iso14443-3 anticollision");
|
||||
PrintAndLogEx(SUCCESS, "ATQA: %02x %02x", card.atqa[1], card.atqa[0]);
|
||||
}
|
||||
DropField();
|
||||
res = PM3_ESOFT;
|
||||
goto plot;
|
||||
}
|
||||
if (!(silent && continuous)) {
|
||||
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
|
||||
PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02x %02x"), card.atqa[1], card.atqa[0]);
|
||||
PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02x [%" PRIu64 "]"), card.sak, resp.oldarg[0]);
|
||||
|
||||
if (card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
|
||||
PrintAndLogEx(SUCCESS, " ATS: " _GREEN_("%s"), sprint_hex(card.ats, card.ats_len));
|
||||
}
|
||||
}
|
||||
if (!disconnectAfter) {
|
||||
if (!silent) PrintAndLogEx(SUCCESS, "Card is selected. You can now start sending commands");
|
||||
}
|
||||
}
|
||||
plot:
|
||||
if (continuous) {
|
||||
res = handle_hf_plot();
|
||||
if (res != PM3_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (kbd_enter_pressed()) {
|
||||
break;
|
||||
}
|
||||
|
||||
} while (continuous);
|
||||
|
||||
if (disconnectAfter) {
|
||||
if (!silent) PrintAndLogEx(INFO, "field dropped.");
|
||||
if (silent == false) {
|
||||
PrintAndLogEx(INFO, "field dropped.");
|
||||
}
|
||||
}
|
||||
|
||||
return PM3_SUCCESS;
|
||||
if (continuous)
|
||||
return PM3_SUCCESS;
|
||||
else
|
||||
return res;
|
||||
}
|
||||
|
||||
static int CmdHF14AInfo(const char *Cmd) {
|
||||
|
@ -1338,7 +1370,7 @@ static int CmdHF14ACmdRaw(const char *Cmd) {
|
|||
if (!res && datalen > 0)
|
||||
waitCmd(0, timeout);
|
||||
}
|
||||
return 0;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int waitCmd(uint8_t iSelect, uint32_t timeout) {
|
||||
|
@ -1398,16 +1430,20 @@ static int CmdHF14AAntiFuzz(const char *Cmd) {
|
|||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
uint8_t arg0 = FLAG_4B_UID_IN_DATA;
|
||||
struct {
|
||||
uint8_t flag;
|
||||
} PACKED param;
|
||||
param.flag = FLAG_4B_UID_IN_DATA;
|
||||
|
||||
if (arg_get_lit(ctx, 2))
|
||||
arg0 = FLAG_7B_UID_IN_DATA;
|
||||
param.flag = FLAG_7B_UID_IN_DATA;
|
||||
if (arg_get_lit(ctx, 3))
|
||||
arg0 = FLAG_10B_UID_IN_DATA;
|
||||
param.flag = FLAG_10B_UID_IN_DATA;
|
||||
|
||||
CLIParserFree(ctx);
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_ISO14443A_ANTIFUZZ, arg0, 0, 0, NULL, 0);
|
||||
return 0;
|
||||
SendCommandNG(CMD_HF_ISO14443A_ANTIFUZZ, (uint8_t*)¶m, sizeof(param));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdHF14AChaining(const char *Cmd) {
|
||||
|
@ -1438,7 +1474,7 @@ static int CmdHF14AChaining(const char *Cmd) {
|
|||
|
||||
PrintAndLogEx(INFO, "\nISO 14443-4 input chaining %s.\n", APDUInFramingEnable ? "enabled" : "disabled");
|
||||
|
||||
return 0;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static void printTag(const char *tag) {
|
||||
|
@ -1681,10 +1717,16 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
|||
}
|
||||
getTagLabel(card.uid[0], card.uid[1]);
|
||||
break;
|
||||
case 0x57: // Qualcomm
|
||||
case 0x46:
|
||||
if (memcmp(card.uid, "FSTN10m", 7) == 0) {
|
||||
isMifareClassic = false;
|
||||
printTag("Waveshare NFC-Powered e-Paper 1.54\" (please disregard MANUFACTURER mapping above)");
|
||||
}
|
||||
break;
|
||||
case 0x57:
|
||||
if (memcmp(card.uid, "WSDZ10m", 7) == 0) {
|
||||
isMifareClassic = false;
|
||||
printTag("Waveshare NFC-Powered e-Paper");
|
||||
printTag("Waveshare NFC-Powered e-Paper (please disregard MANUFACTURER mapping above)");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -1831,11 +1873,47 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
|||
if (card.ats[0] > pos && card.ats[0] < card.ats_len - 2) {
|
||||
const char *tip = "";
|
||||
if (card.ats[0] - pos >= 7) {
|
||||
if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
|
||||
tip = "-> MIFARE Plus X 2K or 4K";
|
||||
} else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
|
||||
tip = "-> MIFARE Plus S 2K or 4K";
|
||||
|
||||
if ((card.sak & 0x70) == 0x40) { // and no GetVersion()..
|
||||
|
||||
if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
|
||||
tip = "-> MIFARE Plus X 2K/4K (SL3)";
|
||||
} else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
|
||||
|
||||
if ((card.atqa[0] & 0x02) == 0x02)
|
||||
tip = "-> MIFARE Plus S 2K (SL3)";
|
||||
else if ((card.atqa[0] & 0x04) == 0x04)
|
||||
tip = "-> MIFARE Plus S 4K (SL3)";
|
||||
|
||||
} else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x00\xF6\xD1", 7) == 0) {
|
||||
tip = "-> MIFARE Plus SE 1K (17pF)";
|
||||
} else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x10\xF6\xD1", 7) == 0) {
|
||||
tip = "-> MIFARE Plus SE 1K (70pF)";
|
||||
}
|
||||
|
||||
} else { //SAK B4,5,6
|
||||
|
||||
if ((card.sak & 0x20) == 0x20) { // and no GetVersion()..
|
||||
|
||||
|
||||
if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
|
||||
tip = "-> MIFARE Plus X 2K (SL1)";
|
||||
} else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
|
||||
tip = "-> MIFARE Plus S 2K (SL1)";
|
||||
} else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x00\xF6\xD1", 7) == 0) {
|
||||
tip = "-> MIFARE Plus SE 1K (17pF)";
|
||||
} else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x10\xF6\xD1", 7) == 0) {
|
||||
tip = "-> MIFARE Plus SE 1K (70pF)";
|
||||
}
|
||||
} else {
|
||||
if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
|
||||
tip = "-> MIFARE Plus X 4K (SL1)";
|
||||
} else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
|
||||
tip = "-> MIFARE Plus S 4K (SL1)";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, " - HB : %s%s", sprint_hex(card.ats + pos, card.ats[0] - pos), tip);
|
||||
if (card.ats[pos] == 0xC1) {
|
||||
|
|
|
@ -130,7 +130,6 @@ static int CmdHF14BSim(const char *Cmd) {
|
|||
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"
|
||||
);
|
||||
|
||||
|
@ -139,7 +138,7 @@ static int CmdHF14BSim(const char *Cmd) {
|
|||
arg_strx0("u", "uid", "hex", "4byte UID/PUPI"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
uint8_t pupi[4];
|
||||
int n = 0;
|
||||
|
@ -150,6 +149,9 @@ static int CmdHF14BSim(const char *Cmd) {
|
|||
PrintAndLogEx(FAILED, "failed to read pupi");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "Simulate with PUPI : " _GREEN_("%s"), sprint_hex_inrow(pupi, sizeof(pupi)));
|
||||
PrintAndLogEx(INFO, "Press pm3-button to abort simulation");
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_ISO14443B_SIMULATE, pupi, sizeof(pupi));
|
||||
return PM3_SUCCESS;
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "crc16.h" // iso15 crc
|
||||
#include "cmddata.h" // getsamples
|
||||
#include "fileutils.h" // savefileEML
|
||||
#include "cliparser.h"
|
||||
|
||||
#define FrameSOF Iso15693FrameSOF
|
||||
#define Logic0 Iso15693Logic0
|
||||
|
@ -209,16 +210,6 @@ const productName_t uidmapping[] = {
|
|||
|
||||
static int CmdHF15Help(const char *Cmd);
|
||||
|
||||
static int usage_15_demod(void) {
|
||||
PrintAndLogEx(NORMAL, "Tries to demodulate / decode ISO15693, from downloaded samples.\n"
|
||||
"Gather samples with 'hf 15 read' / 'hf 15 record'");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_15_samples(void) {
|
||||
PrintAndLogEx(NORMAL, "Acquire samples as Reader (enables carrier, send inquiry\n"
|
||||
"and download it to graphbuffer. Try 'hf 15 demod' to try to demodulate/decode signal");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_15_info(void) {
|
||||
PrintAndLogEx(NORMAL, "Uses the optional command 'get_systeminfo' 0x2B to try and extract information\n"
|
||||
"command may fail, depending on tag.\n"
|
||||
|
@ -235,36 +226,7 @@ static int usage_15_info(void) {
|
|||
_YELLOW_("\thf 15 info u"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_15_record(void) {
|
||||
PrintAndLogEx(NORMAL, "Record activity without enabling carrier");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_15_reader(void) {
|
||||
PrintAndLogEx(NORMAL, "This command identifies a ISO 15693 tag\n"
|
||||
"\n"
|
||||
"Usage: hf 15 reader [h]\n"
|
||||
"Options:\n"
|
||||
"\th this help\n"
|
||||
"\t1 read once\n"
|
||||
"\n"
|
||||
"Example:\n"
|
||||
_YELLOW_("\thf 15 reader\n")
|
||||
_YELLOW_("\thf 15 reader 1\n"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_15_sim(void) {
|
||||
PrintAndLogEx(NORMAL, "Usage: hf 15 sim <UID>\n"
|
||||
"\n"
|
||||
"Example:\n"
|
||||
_YELLOW_("\thf 15 sim E016240000000000"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_15_findafi(void) {
|
||||
PrintAndLogEx(NORMAL, "This command attempts to brute force AFI of an ISO15693 tag\n"
|
||||
"\n"
|
||||
"Usage: hf 15 findafi");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int usage_15_writeafi(void) {
|
||||
PrintAndLogEx(NORMAL, "Usage: hf 15 writeafi <uid|u|*> <afi>\n"
|
||||
"\tuid (either): \n"
|
||||
|
@ -323,7 +285,7 @@ static int usage_15_raw(void) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_15_read(void) {
|
||||
PrintAndLogEx(NORMAL, "Usage: hf 15 read [options] <uid|s|u|*> <page>\n"
|
||||
PrintAndLogEx(NORMAL, "Usage: hf 15 rdbl [options] <uid|s|u|*> <page>\n"
|
||||
"Options:\n"
|
||||
"\t-2 use slower '1 out of 256' mode\n"
|
||||
"\tuid (either): \n"
|
||||
|
@ -334,7 +296,7 @@ static int usage_15_read(void) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_15_write(void) {
|
||||
PrintAndLogEx(NORMAL, "Usage: hf 15 write [options] <uid|s|u|*> <page> <hexdata>\n"
|
||||
PrintAndLogEx(NORMAL, "Usage: hf 15 wrbl [options] <uid|s|u|*> <page> <hexdata>\n"
|
||||
"Options:\n"
|
||||
"\t-2 use slower '1 out of 256' mode\n"
|
||||
"\t-o set OPTION Flag (needed for TI)\n"
|
||||
|
@ -358,17 +320,6 @@ static int usage_15_readmulti(void) {
|
|||
"\t <count> 1-6, number of pages");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_15_csetuid(void) {
|
||||
PrintAndLogEx(NORMAL, "Set UID for magic Chinese card (only works with such cards)\n"
|
||||
"\n"
|
||||
"Usage: hf 15 csetuid <uid>\n"
|
||||
"Options:\n"
|
||||
"\tuid : <8B hex> full UID eg E011223344556677\n"
|
||||
"\n"
|
||||
"Example:\n"
|
||||
_YELLOW_("\thf 15 csetuid E011223344556677"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) {
|
||||
|
||||
|
@ -691,17 +642,31 @@ static bool prepareHF15Cmd(char **cmd, uint16_t *reqlen, uint8_t *arg1, uint8_t
|
|||
}
|
||||
|
||||
// Mode 3
|
||||
//helptext
|
||||
static int CmdHF15Demod(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 'h') return usage_15_demod();
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 15 demod",
|
||||
"Tries to demodulate / decode ISO15693, from downloaded samples.\n"
|
||||
"Gather samples with 'hf 15 samples' / 'hf 15 sniff'",
|
||||
"hf 15 demod\n");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
// The sampling rate is 106.353 ksps/s, for T = 18.8 us
|
||||
int i, j;
|
||||
int max = 0, maxPos = 0;
|
||||
int skip = 4;
|
||||
|
||||
if (GraphTraceLen < 1000) return PM3_ESOFT;
|
||||
if (GraphTraceLen < 1000) {
|
||||
PrintAndLogEx(FAILED, "Too few samples in GraphBuffer. Need more than 1000");
|
||||
PrintAndLogEx(HINT, "Run " _YELLOW_("`hf 15 samples`") " to collect and download data");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
// First, correlate for SOF
|
||||
for (i = 0; i < 1000; i++) {
|
||||
|
@ -719,7 +684,7 @@ static int CmdHF15Demod(const char *Cmd) {
|
|||
|
||||
i = maxPos + ARRAYLEN(FrameSOF) / skip;
|
||||
int k = 0;
|
||||
uint8_t outBuf[20];
|
||||
uint8_t outBuf[2048] = {0};
|
||||
memset(outBuf, 0, sizeof(outBuf));
|
||||
uint8_t mask = 0x01;
|
||||
for (;;) {
|
||||
|
@ -746,40 +711,80 @@ static int CmdHF15Demod(const char *Cmd) {
|
|||
} else {
|
||||
i += ARRAYLEN(Logic0) / skip;
|
||||
}
|
||||
|
||||
mask <<= 1;
|
||||
if (mask == 0) {
|
||||
k++;
|
||||
mask = 0x01;
|
||||
}
|
||||
|
||||
if ((i + (int)ARRAYLEN(FrameEOF)) >= GraphTraceLen) {
|
||||
PrintAndLogEx(INFO, "ran off end!");
|
||||
break;
|
||||
}
|
||||
|
||||
if (k > 2048) {
|
||||
PrintAndLogEx(INFO, "ran out of buffer");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mask != 0x01) {
|
||||
PrintAndLogEx(WARNING, "Warning, uneven octet! (discard extra bits!)");
|
||||
PrintAndLogEx(INFO, " mask = %02x", mask);
|
||||
}
|
||||
PrintAndLogEx(INFO, "%d octets", k);
|
||||
|
||||
for (i = 0; i < k; i++)
|
||||
PrintAndLogEx(SUCCESS, "# %2d: %02x ", i, outBuf[i]);
|
||||
if (k == 0) {
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, "CRC %04x", Crc15(outBuf, k - 2));
|
||||
i = 0;
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "Got %d octets, decoded as following", k);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(SUCCESS, " idx | data");
|
||||
PrintAndLogEx(SUCCESS, "-----+-------------------------------------------------");
|
||||
if (k / 16 > 0) {
|
||||
for (; i < k; i += 16) {
|
||||
PrintAndLogEx(SUCCESS, " %3i | %s", i, sprint_hex(outBuf + i, 16));
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t mod = (k % 16);
|
||||
if (mod > 0) {
|
||||
PrintAndLogEx(SUCCESS, " %3i | %s", i, sprint_hex(outBuf + i, mod));
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, "-----+-------------------------------------------------");
|
||||
if (k > 2) {
|
||||
PrintAndLogEx(SUCCESS, "--> CRC %04x", Crc15(outBuf, k - 2));
|
||||
}
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
// * Acquire Samples as Reader (enables carrier, sends inquiry)
|
||||
//helptext
|
||||
static int CmdHF15Samples(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 'h') return usage_15_samples();
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 15 samples",
|
||||
"Acquire samples as Reader (enables carrier, send inquiry\n"
|
||||
"and download it to graphbuffer. Try 'hf 15 demod' to try to demodulate/decode signal",
|
||||
"hf 15 samples");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_ISO15693_ACQ_RAW_ADC, NULL, 0);
|
||||
|
||||
getSamples(0, true);
|
||||
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf 15 demod") "` to decode signal");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -816,6 +821,10 @@ static int NxpSysInfo(uint8_t *uid) {
|
|||
DropField();
|
||||
|
||||
int status = resp.oldarg[0];
|
||||
if (status == PM3_ETEAROFF) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (status < 2) {
|
||||
PrintAndLogEx(WARNING, "iso15693 card doesn't answer to NXP systeminfo command");
|
||||
return PM3_EWRONGANSWER;
|
||||
|
@ -975,6 +984,9 @@ static int CmdHF15Info(const char *Cmd) {
|
|||
DropField();
|
||||
|
||||
int status = resp.oldarg[0];
|
||||
if (status == PM3_ETEAROFF) {
|
||||
return status;
|
||||
}
|
||||
if (status < 2) {
|
||||
PrintAndLogEx(WARNING, "iso15693 card doesn't answer to systeminfo command (%d)", status);
|
||||
return PM3_EWRONGANSWER;
|
||||
|
@ -1033,11 +1045,19 @@ static int CmdHF15Info(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
// Record Activity without enabling carrier
|
||||
//helptext
|
||||
// Sniff Activity without enabling carrier
|
||||
static int CmdHF15Sniff(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 'h') return usage_15_record();
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 15 sniff",
|
||||
"Sniff activity without enabling carrier",
|
||||
"hf 15 sniff\n");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
PacketResponseNG resp;
|
||||
clearCommandBuffer();
|
||||
|
@ -1051,30 +1071,58 @@ static int CmdHF15Sniff(const char *Cmd) {
|
|||
}
|
||||
|
||||
static int CmdHF15Reader(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 'h') return usage_15_reader();
|
||||
bool loop_read = (cmdp == '1') ? false : true;
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 15 reader",
|
||||
"Act as a ISO15693 reader. Look for ISO15693 tags until Enter or the pm3 button is pressed\n",
|
||||
"hf 15 reader\n"
|
||||
"hf 15 reader -1");
|
||||
|
||||
readHF15Uid(loop_read, true);
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("1", "one", "read once"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
bool read_once = arg_get_lit(ctx, 1);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
PrintAndLogEx(INFO, "Starting ISO15 reader mode");
|
||||
PrintAndLogEx(INFO, "press " _YELLOW_("`enter`") " to cancel");
|
||||
readHF15Uid(!read_once, true);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
// Simulation is still not working very good
|
||||
// helptext
|
||||
static int CmdHF15Sim(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) < 1 || cmdp == 'h') return usage_15_sim();
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 15 sim",
|
||||
"Simulate a ISO15693 tag\n",
|
||||
"hf 15 sim -u E011223344556677");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str1("u", "uid", "<8b hex>", "UID eg E011223344556677"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
struct {
|
||||
uint8_t uid[8];
|
||||
} PACKED payload;
|
||||
|
||||
if (param_gethex(Cmd, 0, payload.uid, 16)) {
|
||||
int uidlen = 0;
|
||||
CLIGetHexWithReturn(ctx, 1, payload.uid, &uidlen);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (uidlen != 8) {
|
||||
PrintAndLogEx(WARNING, "UID must include 16 HEX symbols");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, "Starting simulating UID " _YELLOW_("%s"), iso15693_sprintUID(NULL, payload.uid));
|
||||
PrintAndLogEx(INFO, "press " _YELLOW_("`Pm3 button`") " to cancel");
|
||||
|
||||
PacketResponseNG resp;
|
||||
clearCommandBuffer();
|
||||
|
@ -1087,17 +1135,25 @@ static int CmdHF15Sim(const char *Cmd) {
|
|||
// (There is no standard way of reading the AFI, although some tags support this)
|
||||
// helptext
|
||||
static int CmdHF15FindAfi(const char *Cmd) {
|
||||
PacketResponseNG resp;
|
||||
uint32_t timeout = 0;
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 15 findafi",
|
||||
"This command attempts to brute force AFI of an ISO15693 tag\n",
|
||||
"hf 15 findafi");
|
||||
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 'h') return usage_15_findafi();
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
PrintAndLogEx(SUCCESS, "press pm3-button to cancel");
|
||||
|
||||
clearCommandBuffer();
|
||||
PacketResponseNG resp;
|
||||
SendCommandMIX(CMD_HF_ISO15693_FINDAFI, strtol(Cmd, NULL, 0), 0, 0, NULL, 0);
|
||||
|
||||
uint32_t timeout = 0;
|
||||
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
timeout++;
|
||||
|
||||
|
@ -1153,9 +1209,13 @@ static int CmdHF15WriteAfi(const char *Cmd) {
|
|||
DropField();
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
DropField();
|
||||
|
||||
int status = resp.oldarg[0];
|
||||
if (status == PM3_ETEAROFF) {
|
||||
return status;
|
||||
}
|
||||
|
||||
uint8_t *data = resp.data.asBytes;
|
||||
|
||||
if ((data[0] & ISO15_RES_ERROR) == ISO15_RES_ERROR) {
|
||||
|
@ -1212,6 +1272,10 @@ static int CmdHF15WriteDsfid(const char *Cmd) {
|
|||
}
|
||||
|
||||
DropField();
|
||||
int status = resp.oldarg[0];
|
||||
if (status == PM3_ETEAROFF) {
|
||||
return status;
|
||||
}
|
||||
|
||||
uint8_t *data = resp.data.asBytes;
|
||||
|
||||
|
@ -1296,6 +1360,9 @@ static int CmdHF15Dump(const char *Cmd) {
|
|||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
|
||||
int len = resp.oldarg[0];
|
||||
if (len == PM3_ETEAROFF) {
|
||||
continue;
|
||||
}
|
||||
if (len < 2) {
|
||||
PrintAndLogEx(FAILED, "iso15693 command failed");
|
||||
continue;
|
||||
|
@ -1321,6 +1388,7 @@ static int CmdHF15Dump(const char *Cmd) {
|
|||
blocknum++;
|
||||
|
||||
PrintAndLogEx(NORMAL, "." NOLF);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1419,6 +1487,10 @@ static int CmdHF15Raw(const char *Cmd) {
|
|||
if (reply) {
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
int len = resp.oldarg[0];
|
||||
if (len == PM3_ETEAROFF) {
|
||||
DropField();
|
||||
return len;
|
||||
}
|
||||
if (len < 2) {
|
||||
PrintAndLogEx(WARNING, "command failed");
|
||||
} else {
|
||||
|
@ -1491,6 +1563,10 @@ static int CmdHF15Readmulti(const char *Cmd) {
|
|||
DropField();
|
||||
|
||||
int status = resp.oldarg[0];
|
||||
if (status == PM3_ETEAROFF) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (status < 2) {
|
||||
PrintAndLogEx(FAILED, "iso15693 card readmulti failed");
|
||||
return PM3_EWRONGANSWER;
|
||||
|
@ -1574,6 +1650,9 @@ static int CmdHF15Read(const char *Cmd) {
|
|||
DropField();
|
||||
|
||||
int status = resp.oldarg[0];
|
||||
if (status == PM3_ETEAROFF) {
|
||||
return status;
|
||||
}
|
||||
if (status < 2) {
|
||||
PrintAndLogEx(ERR, "iso15693 command failed");
|
||||
return PM3_EWRONGANSWER;
|
||||
|
@ -1661,6 +1740,10 @@ static int CmdHF15Write(const char *Cmd) {
|
|||
DropField();
|
||||
|
||||
int status = resp.oldarg[0];
|
||||
if (status == PM3_ETEAROFF) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (status < 2) {
|
||||
PrintAndLogEx(FAILED, "iso15693 command failed");
|
||||
return PM3_EWRONGANSWER;
|
||||
|
@ -1806,16 +1889,28 @@ static int CmdHF15Restore(const char *Cmd) {
|
|||
*/
|
||||
static int CmdHF15CSetUID(const char *Cmd) {
|
||||
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) < 1 || cmdp == 'h') return usage_15_csetuid();
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 15 csetuid",
|
||||
"Set UID for magic Chinese card (only works with such cards)\n",
|
||||
"hf 15 csetuid -u E011223344556677");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str1("u", "uid", "<8b hex>", "UID eg E011223344556677"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
struct {
|
||||
uint8_t uid[8];
|
||||
} PACKED payload;
|
||||
|
||||
if (param_gethex(Cmd, 0, payload.uid, 16)) {
|
||||
PrintAndLogEx(WARNING, "UID must include 16 HEX symbols");
|
||||
int uidlen = 0;
|
||||
CLIGetHexWithReturn(ctx, 1, payload.uid, &uidlen);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (uidlen != 8) {
|
||||
PrintAndLogEx(WARNING, "UID must include 16 HEX symbols got ");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
|
@ -1838,9 +1933,10 @@ static int CmdHF15CSetUID(const char *Cmd) {
|
|||
PacketResponseNG resp;
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_ISO15693_CSETUID, (uint8_t *)&payload, sizeof(payload));
|
||||
|
||||
if (WaitForResponseTimeout(CMD_HF_ISO15693_CSETUID, &resp, 2000) == false) {
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply");
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "getting updated card details...");
|
||||
|
@ -1876,13 +1972,13 @@ static command_t CommandTable[] = {
|
|||
{"info", CmdHF15Info, IfPm3Iso15693, "Tag information"},
|
||||
{"sniff", CmdHF15Sniff, IfPm3Iso15693, "Sniff ISO15693 traffic"},
|
||||
{"raw", CmdHF15Raw, IfPm3Iso15693, "Send raw hex data to tag"},
|
||||
{"read", CmdHF15Read, IfPm3Iso15693, "Read a block"},
|
||||
{"rdbl", CmdHF15Read, IfPm3Iso15693, "Read a block"},
|
||||
{"reader", CmdHF15Reader, IfPm3Iso15693, "Act like an ISO15693 reader"},
|
||||
{"readmulti", CmdHF15Readmulti, IfPm3Iso15693, "Reads multiple Blocks"},
|
||||
{"restore", CmdHF15Restore, IfPm3Iso15693, "Restore from file to all memory pages of an ISO15693 tag"},
|
||||
{"samples", CmdHF15Samples, IfPm3Iso15693, "Acquire Samples as Reader (enables carrier, sends inquiry)"},
|
||||
{"sim", CmdHF15Sim, IfPm3Iso15693, "Fake an ISO15693 tag"},
|
||||
{"write", CmdHF15Write, IfPm3Iso15693, "Write a block"},
|
||||
{"wrbl", CmdHF15Write, IfPm3Iso15693, "Write a block"},
|
||||
{"-----------", CmdHF15Help, IfPm3Iso15693, "----------------------- " _CYAN_("afi") " -----------------------"},
|
||||
{"findafi", CmdHF15FindAfi, IfPm3Iso15693, "Brute force AFI of an ISO15693 tag"},
|
||||
{"writeafi", CmdHF15WriteAfi, IfPm3Iso15693, "Writes the AFI on an ISO15693 tag"},
|
||||
|
|
|
@ -209,6 +209,7 @@ static int cmd_hf_fido_register(const char *cmd) {
|
|||
|
||||
if (paramsPlain) {
|
||||
memset(cdata, 0x00, 32);
|
||||
chlen = sizeof(cdata);
|
||||
CLIGetStrWithReturn(ctx, 6, cdata, &chlen);
|
||||
if (chlen > 16) {
|
||||
PrintAndLogEx(ERR, "ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", chlen);
|
||||
|
@ -216,6 +217,7 @@ static int cmd_hf_fido_register(const char *cmd) {
|
|||
return PM3_EINVARG;
|
||||
}
|
||||
} else {
|
||||
chlen = sizeof(cdata);
|
||||
CLIGetHexWithReturn(ctx, 6, cdata, &chlen);
|
||||
if (chlen && chlen != 32) {
|
||||
PrintAndLogEx(ERR, "ERROR: challenge parameter length must be 32 bytes only.");
|
||||
|
@ -229,6 +231,7 @@ static int cmd_hf_fido_register(const char *cmd) {
|
|||
|
||||
if (paramsPlain) {
|
||||
memset(adata, 0x00, 32);
|
||||
applen = sizeof(adata);
|
||||
CLIGetStrWithReturn(ctx, 7, adata, &applen);
|
||||
if (applen > 16) {
|
||||
PrintAndLogEx(ERR, "ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", applen);
|
||||
|
@ -236,6 +239,7 @@ static int cmd_hf_fido_register(const char *cmd) {
|
|||
return PM3_EINVARG;
|
||||
}
|
||||
} else {
|
||||
applen = sizeof(adata);
|
||||
CLIGetHexWithReturn(ctx, 7, adata, &applen);
|
||||
if (applen && applen != 32) {
|
||||
PrintAndLogEx(ERR, "ERROR: application parameter length must be 32 bytes only.");
|
||||
|
@ -485,6 +489,7 @@ static int cmd_hf_fido_authenticate(const char *cmd) {
|
|||
|
||||
if (paramsPlain) {
|
||||
memset(hdata, 0x00, 32);
|
||||
hdatalen = sizeof(hdata);
|
||||
CLIGetStrWithReturn(ctx, 9, hdata, &hdatalen);
|
||||
if (hdatalen > 16) {
|
||||
PrintAndLogEx(ERR, "ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen);
|
||||
|
@ -492,6 +497,7 @@ static int cmd_hf_fido_authenticate(const char *cmd) {
|
|||
return PM3_EINVARG;
|
||||
}
|
||||
} else {
|
||||
hdatalen = sizeof(hdata);
|
||||
CLIGetHexWithReturn(ctx, 10, hdata, &hdatalen);
|
||||
if (hdatalen && hdatalen != 32) {
|
||||
PrintAndLogEx(ERR, "ERROR: challenge parameter length must be 32 bytes only.");
|
||||
|
@ -505,6 +511,7 @@ static int cmd_hf_fido_authenticate(const char *cmd) {
|
|||
|
||||
if (paramsPlain) {
|
||||
memset(hdata, 0x00, 32);
|
||||
hdatalen = sizeof(hdata);
|
||||
CLIGetStrWithReturn(ctx, 11, hdata, &hdatalen);
|
||||
if (hdatalen > 16) {
|
||||
PrintAndLogEx(ERR, "ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen);
|
||||
|
@ -512,6 +519,7 @@ static int cmd_hf_fido_authenticate(const char *cmd) {
|
|||
return PM3_EINVARG;
|
||||
}
|
||||
} else {
|
||||
hdatalen = sizeof(hdata);
|
||||
CLIGetHexWithReturn(ctx, 10, hdata, &hdatalen);
|
||||
if (hdatalen && hdatalen != 32) {
|
||||
PrintAndLogEx(ERR, "ERROR: application parameter length must be 32 bytes only.");
|
||||
|
@ -693,6 +701,7 @@ static int cmd_hf_fido_2make_credential(const char *cmd) {
|
|||
uint8_t jsonname[FILE_PATH_SIZE] = {0};
|
||||
char *cjsonname = (char *)jsonname;
|
||||
int jsonnamelen = 0;
|
||||
jsonnamelen = sizeof(jsonname);
|
||||
CLIGetStrWithReturn(ctx, 5, jsonname, &jsonnamelen);
|
||||
|
||||
if (!jsonnamelen) {
|
||||
|
@ -817,7 +826,7 @@ static int cmd_hf_fido_2get_assertion(const char *cmd) {
|
|||
|
||||
uint8_t jsonname[FILE_PATH_SIZE] = {0};
|
||||
char *cjsonname = (char *)jsonname;
|
||||
int jsonnamelen = 0;
|
||||
int jsonnamelen = sizeof(jsonname);
|
||||
CLIGetStrWithReturn(ctx, 5, jsonname, &jsonnamelen);
|
||||
|
||||
if (!jsonnamelen) {
|
||||
|
@ -915,7 +924,7 @@ static int cmd_hf_fido_2get_assertion(const char *cmd) {
|
|||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help."},
|
||||
{"info", cmd_hf_fido_list, IfPm3Iso14443a, "List ISO 14443A history"},
|
||||
{"list", cmd_hf_fido_list, IfPm3Iso14443a, "List ISO 14443A history"},
|
||||
{"info", cmd_hf_fido_info, IfPm3Iso14443a, "Info about FIDO tag."},
|
||||
{"reg", cmd_hf_fido_register, IfPm3Iso14443a, "FIDO U2F Registration Message."},
|
||||
{"auth", cmd_hf_fido_authenticate, IfPm3Iso14443a, "FIDO U2F Authentication Message."},
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -419,7 +419,7 @@ void annotateIclass(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool
|
|||
|
||||
uint8_t key[8];
|
||||
if (check_known_default(csn, epurse, rmac, tmac, key)) {
|
||||
snprintf(exp, size, "( " _GREEN_("%s") ")", sprint_hex(key, 8));
|
||||
snprintf(exp, size, "( " _GREEN_("%s") " )", sprint_hex_inrow(key, 8));
|
||||
}
|
||||
curr_state = PICO_NONE;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,15 @@
|
|||
#include "protocols.h"
|
||||
#include "fileutils.h" //saveFile
|
||||
|
||||
/*
|
||||
iceman notes
|
||||
We can't dump LTO 5 or 6 tags yet since we don't have a datasheet.
|
||||
If you have access to datasheet, le me know!
|
||||
|
||||
LTO w Type info 00 01 has 101 blocks.
|
||||
LTO w Type info 00 03 has 255 blocks.
|
||||
LTO w Type info 00 xx has NN blocks.
|
||||
*/
|
||||
#define CM_MEM_MAX_SIZE 0x1FE0 // (32byte/block * 255block = 8160byte)
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
@ -185,6 +194,17 @@ static int CmdHfLTOInfo(const char *Cmd) {
|
|||
return infoLTO(true);
|
||||
}
|
||||
|
||||
static const char* lto_print_size(uint8_t ti) {
|
||||
switch(ti) {
|
||||
case 1:
|
||||
return "101 blocks / 3232 bytes";
|
||||
case 3:
|
||||
return "255 blocks / 8160 bytes";
|
||||
default :
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
int infoLTO(bool verbose) {
|
||||
|
||||
clearCommandBuffer();
|
||||
|
@ -199,8 +219,9 @@ int infoLTO(bool verbose) {
|
|||
|
||||
if (ret_val == PM3_SUCCESS) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(SUCCESS, "UID: " _YELLOW_("%s"), sprint_hex_inrow(serial_number, sizeof(serial_number)));
|
||||
PrintAndLogEx(SUCCESS, "TYPE INFO: " _YELLOW_("%s"), sprint_hex_inrow(type_info, sizeof(type_info)));
|
||||
PrintAndLogEx(SUCCESS, "UID......... " _YELLOW_("%s"), sprint_hex_inrow(serial_number, sizeof(serial_number)));
|
||||
PrintAndLogEx(SUCCESS, "Type info... " _YELLOW_("%s"), sprint_hex_inrow(type_info, sizeof(type_info)));
|
||||
PrintAndLogEx(SUCCESS, "Memory...... " _YELLOW_("%s"), lto_print_size(type_info[1]));
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
|
@ -442,11 +463,18 @@ int dumpLTO(uint8_t *dump, bool verbose) {
|
|||
lto_switch_off_field();
|
||||
return ret_val;
|
||||
}
|
||||
// 0003 == 255 blocks x 32 = 8160 bytes
|
||||
// 0001 == 101 blocks x 32 = 3232 bytes
|
||||
uint8_t blocks = 0xFF;
|
||||
if (type_info[1] == 0x01) {
|
||||
blocks = 0x65;
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, "Found LTO tag w " _YELLOW_("%s") " memory", lto_print_size(type_info[1]));
|
||||
|
||||
uint8_t block_data_d00_d15[18];
|
||||
uint8_t block_data_d16_d31[18];
|
||||
|
||||
for (uint8_t i = 0; i < 255; i++) {
|
||||
for (uint8_t i = 0; i < blocks; i++) {
|
||||
|
||||
ret_val = lto_rdbl(i, block_data_d00_d15, block_data_d16_d31, verbose);
|
||||
|
||||
|
@ -458,6 +486,8 @@ int dumpLTO(uint8_t *dump, bool verbose) {
|
|||
lto_switch_off_field();
|
||||
return ret_val;
|
||||
}
|
||||
PrintAndLogEx(INPLACE, "...reading block %d", i);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
lto_switch_off_field();
|
||||
|
@ -502,6 +532,7 @@ static int CmdHfLTODump(const char *Cmd) {
|
|||
}
|
||||
|
||||
int ret_val = dumpLTO(dump, true);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
if (ret_val != PM3_SUCCESS) {
|
||||
free(dump);
|
||||
return ret_val;
|
||||
|
|
|
@ -627,6 +627,76 @@ static void decode_print_st(uint16_t blockno, uint8_t *data) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static uint16_t NumOfBlocks(char card) {
|
||||
switch (card) {
|
||||
case '0' :
|
||||
return MIFARE_MINI_MAXBLOCK;
|
||||
case '1' :
|
||||
return MIFARE_1K_MAXBLOCK;
|
||||
case '2' :
|
||||
return MIFARE_2K_MAXBLOCK;
|
||||
case '4' :
|
||||
return MIFARE_4K_MAXBLOCK;
|
||||
default :
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t NumOfSectors(char card) {
|
||||
switch (card) {
|
||||
case '0' :
|
||||
return MIFARE_MINI_MAXSECTOR;
|
||||
case '1' :
|
||||
return MIFARE_1K_MAXSECTOR;
|
||||
case '2' :
|
||||
return MIFARE_2K_MAXSECTOR;
|
||||
case '4' :
|
||||
return MIFARE_4K_MAXSECTOR;
|
||||
default :
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t FirstBlockOfSector(uint8_t sectorNo) {
|
||||
if (sectorNo < 32) {
|
||||
return sectorNo * 4;
|
||||
} else {
|
||||
return 32 * 4 + (sectorNo - 32) * 16;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t NumBlocksPerSector(uint8_t sectorNo) {
|
||||
if (sectorNo < 32) {
|
||||
return 4;
|
||||
} else {
|
||||
return 16;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t GetSectorFromBlockNo(uint8_t blockNo) {
|
||||
if (blockNo < 128)
|
||||
return blockNo / 4;
|
||||
else
|
||||
return 32 + ((128 - blockNo) / 16);
|
||||
}
|
||||
|
||||
static char GetFormatFromSector(uint8_t sectorNo) {
|
||||
switch (sectorNo) {
|
||||
case MIFARE_MINI_MAXSECTOR:
|
||||
return '0';
|
||||
case MIFARE_1K_MAXSECTOR:
|
||||
return '1';
|
||||
case MIFARE_2K_MAXSECTOR:
|
||||
return '2';
|
||||
case MIFARE_4K_MAXSECTOR:
|
||||
return '4';
|
||||
default :
|
||||
return ' ';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int CmdHF14AMfDarkside(const char *Cmd) {
|
||||
uint8_t blockno = 0, key_type = MIFARE_AUTH_KEYA;
|
||||
uint64_t key = 0;
|
||||
|
@ -825,12 +895,9 @@ static int CmdHF14AMfRdSc(const char *Cmd) {
|
|||
PrintAndLogEx(NORMAL, "isOk:%02x", isOK);
|
||||
if (isOK) {
|
||||
|
||||
uint8_t blocks = 4;
|
||||
uint8_t start = sectorNo * 4;
|
||||
if (sectorNo >= 32) {
|
||||
blocks = 16;
|
||||
start = 128 + (sectorNo - 32) * 16;
|
||||
}
|
||||
uint8_t blocks = NumBlocksPerSector(sectorNo);
|
||||
uint8_t start = FirstBlockOfSector(sectorNo);
|
||||
|
||||
for (int i = 0; i < blocks; i++) {
|
||||
PrintAndLogEx(NORMAL, "%3d | %s", start + i, sprint_hex(data + (i * 16), 16));
|
||||
}
|
||||
|
@ -843,74 +910,6 @@ static int CmdHF14AMfRdSc(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static uint16_t NumOfBlocks(char card) {
|
||||
switch (card) {
|
||||
case '0' :
|
||||
return MIFARE_MINI_MAXBLOCK;
|
||||
case '1' :
|
||||
return MIFARE_1K_MAXBLOCK;
|
||||
case '2' :
|
||||
return MIFARE_2K_MAXBLOCK;
|
||||
case '4' :
|
||||
return MIFARE_4K_MAXBLOCK;
|
||||
default :
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t NumOfSectors(char card) {
|
||||
switch (card) {
|
||||
case '0' :
|
||||
return MIFARE_MINI_MAXSECTOR;
|
||||
case '1' :
|
||||
return MIFARE_1K_MAXSECTOR;
|
||||
case '2' :
|
||||
return MIFARE_2K_MAXSECTOR;
|
||||
case '4' :
|
||||
return MIFARE_4K_MAXSECTOR;
|
||||
default :
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t FirstBlockOfSector(uint8_t sectorNo) {
|
||||
if (sectorNo < 32) {
|
||||
return sectorNo * 4;
|
||||
} else {
|
||||
return 32 * 4 + (sectorNo - 32) * 16;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t NumBlocksPerSector(uint8_t sectorNo) {
|
||||
if (sectorNo < 32) {
|
||||
return 4;
|
||||
} else {
|
||||
return 16;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t GetSectorFromBlockNo(uint8_t blockNo) {
|
||||
if (blockNo < 128)
|
||||
return blockNo / 4;
|
||||
else
|
||||
return 32 + ((128 - blockNo) / 16);
|
||||
}
|
||||
|
||||
static char GetFormatFromSector(uint8_t sectorNo) {
|
||||
switch (sectorNo) {
|
||||
case MIFARE_MINI_MAXSECTOR:
|
||||
return '0';
|
||||
case MIFARE_1K_MAXSECTOR:
|
||||
return '1';
|
||||
case MIFARE_2K_MAXSECTOR:
|
||||
return '2';
|
||||
case MIFARE_4K_MAXSECTOR:
|
||||
return '4';
|
||||
default :
|
||||
return ' ';
|
||||
}
|
||||
}
|
||||
|
||||
static int FastDumpWithEcFill(uint8_t numsectors) {
|
||||
PacketResponseNG resp;
|
||||
|
||||
|
@ -2963,7 +2962,7 @@ out:
|
|||
printKeyTable(sectorsCnt, e_sector);
|
||||
|
||||
if (use_flashmemory && found_keys == (sectorsCnt << 1)) {
|
||||
PrintAndLogEx(SUCCESS, "Card dumped aswell. run " _YELLOW_("`%s %c`"),
|
||||
PrintAndLogEx(SUCCESS, "Card dumped as well. run " _YELLOW_("`%s %c`"),
|
||||
"hf mf esave",
|
||||
GetFormatFromSector(sectorsCnt)
|
||||
);
|
||||
|
|
|
@ -233,6 +233,7 @@ static int plus_print_version(uint8_t *version) {
|
|||
PrintAndLogEx(SUCCESS, " Production date: week " _GREEN_("%02x") " / " _GREEN_("20%02x"), version[7 + 7 + 7 + 5], version[7 + 7 + 7 + 5 + 1]);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("Hardware Information"));
|
||||
PrintAndLogEx(INFO, " Raw : %s", sprint_hex(version, 7));
|
||||
PrintAndLogEx(INFO, " Vendor Id: " _YELLOW_("%s"), getTagInfo(version[0]));
|
||||
PrintAndLogEx(INFO, " Type: %s", getTypeStr(version[1]));
|
||||
PrintAndLogEx(INFO, " Subtype: " _YELLOW_("0x%02X"), version[2]);
|
||||
|
@ -241,6 +242,7 @@ static int plus_print_version(uint8_t *version) {
|
|||
PrintAndLogEx(INFO, " Protocol: %s", getProtocolStr(version[6], true));
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("Software Information"));
|
||||
PrintAndLogEx(INFO, " Raw : %s", sprint_hex(version + 7, 6));
|
||||
PrintAndLogEx(INFO, " Vendor Id: " _YELLOW_("%s"), getTagInfo(version[7]));
|
||||
PrintAndLogEx(INFO, " Type: %s", getTypeStr(version[8]));
|
||||
PrintAndLogEx(INFO, " Subtype: " _YELLOW_("0x%02X"), version[9]);
|
||||
|
@ -265,13 +267,21 @@ static int get_plus_version(uint8_t *version, int *version_len) {
|
|||
|
||||
static int CmdHFMFPInfo(const char *Cmd) {
|
||||
|
||||
if (Cmd && strlen(Cmd) > 0)
|
||||
PrintAndLogEx(WARNING, "command don't have any parameters.\n");
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------");
|
||||
PrintAndLogEx(INFO, "-------------------------------------------------------------");
|
||||
|
||||
// Mifare Plus info
|
||||
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
WaitForResponse(CMD_ACK, &resp);
|
||||
|
||||
iso14a_card_select_t card;
|
||||
memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
|
||||
|
||||
uint64_t select_status = resp.oldarg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
|
||||
|
||||
|
||||
bool supportVersion = false;
|
||||
bool supportSignature = false;
|
||||
|
||||
|
@ -284,17 +294,11 @@ static int CmdHFMFPInfo(const char *Cmd) {
|
|||
} else {
|
||||
// info about 14a part
|
||||
infoHF14A(false, false, false);
|
||||
|
||||
// Historical bytes.
|
||||
|
||||
}
|
||||
|
||||
// Mifare Plus info
|
||||
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
WaitForResponse(CMD_ACK, &resp);
|
||||
|
||||
iso14a_card_select_t card;
|
||||
memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
|
||||
|
||||
uint64_t select_status = resp.oldarg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
|
||||
|
||||
// Signature originality check
|
||||
uint8_t signature[56] = {0};
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "generator.h"
|
||||
#include "mifare/ndef.h"
|
||||
#include "cliparser.h"
|
||||
#include "cmdmain.h"
|
||||
|
||||
|
||||
#define MAX_UL_BLOCKS 0x0F
|
||||
|
@ -241,7 +242,7 @@ static int usage_hf_mfu_otp_tearoff(void) {
|
|||
PrintAndLogEx(NORMAL, " s <time> : (optional) start time to run the test - default 0 us");
|
||||
PrintAndLogEx(NORMAL, " d <data> : (optional) data to full-write before trying the OTP test - default 0x00");
|
||||
PrintAndLogEx(NORMAL, " t <data> : (optional) data to write while running the OTP test - default 0x00");
|
||||
PrintAndLogEx(NORMAL, " m <data> : (optional) exit criteria, if block matches this value");
|
||||
PrintAndLogEx(NORMAL, " m <data> : (optional) exit criteria, if block matches this value");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " hf mfu otptear b 3");
|
||||
|
@ -343,21 +344,28 @@ static int ul_send_cmd_raw(uint8_t *cmd, uint8_t cmdlen, uint8_t *response, uint
|
|||
return resplen;
|
||||
}
|
||||
|
||||
static int ul_select(iso14a_card_select_t *card) {
|
||||
static bool ul_select(iso14a_card_select_t *card) {
|
||||
|
||||
ul_switch_on_field();
|
||||
|
||||
PacketResponseNG resp;
|
||||
bool ans = WaitForResponseTimeout(CMD_ACK, &resp, 1500);
|
||||
|
||||
if (!ans || resp.oldarg[0] < 1) {
|
||||
PrintAndLogEx(WARNING, "iso14443a card select failed");
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||
DropField();
|
||||
return 0;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
|
||||
memcpy(card, resp.data.asBytes, sizeof(iso14a_card_select_t));
|
||||
return 1;
|
||||
uint16_t len = (resp.oldarg[1] & 0xFFFF);
|
||||
if (len == 0) {
|
||||
PrintAndLogEx(WARNING, "iso14443a card select failed");
|
||||
DropField();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (card)
|
||||
memcpy(card, resp.data.asBytes, sizeof(iso14a_card_select_t));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// This read command will at least return 16bytes.
|
||||
|
@ -885,7 +893,7 @@ static int ulev1_print_counters(void) {
|
|||
len = ulev1_readCounter(i, counter, sizeof(counter));
|
||||
if (len == 3) {
|
||||
PrintAndLogEx(INFO, " [%0d]: %s", i, sprint_hex(counter, 3));
|
||||
PrintAndLogEx(SUCCESS, " - %02X tearing (" _GREEN_("%s") ")", tear[0], (tear[0] == 0xBD) ? "ok" : "failure");
|
||||
PrintAndLogEx(SUCCESS, " - %02X tearing (%s)", tear[0], (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("failure"));
|
||||
}
|
||||
}
|
||||
return len;
|
||||
|
@ -1027,11 +1035,10 @@ static int ulc_magic_test(){
|
|||
iso14a_card_select_t card;
|
||||
uint8_t nonce1[11] = {0x00};
|
||||
uint8_t nonce2[11] = {0x00};
|
||||
int status = ul_select(&card);
|
||||
if ( !status ){
|
||||
if ( !ul_select(&card) ){
|
||||
return UL_ERROR;
|
||||
}
|
||||
status = ulc_requestAuthentication(nonce1, sizeof(nonce1));
|
||||
int status = ulc_requestAuthentication(nonce1, sizeof(nonce1));
|
||||
if ( status > 0 ) {
|
||||
status = ulc_requestAuthentication(nonce2, sizeof(nonce2));
|
||||
returnValue = ( !memcmp(nonce1, nonce2, 11) ) ? UL_C_MAGIC : UL_C;
|
||||
|
@ -1620,7 +1627,7 @@ static int CmdHF14AMfUWrBl(const char *Cmd) {
|
|||
PrintAndLogEx(WARNING, "Command execute timeout");
|
||||
}
|
||||
|
||||
return 0;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
//
|
||||
// Read Single Block
|
||||
|
@ -2839,12 +2846,10 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
|
|||
return usage_hf_mfu_otp_tearoff();
|
||||
case 'b':
|
||||
blockNoUint = param_get8(Cmd, cmdp + 1);
|
||||
/*
|
||||
if (blockNoUint < 2) {
|
||||
PrintAndLogEx(WARNING, "Wrong block number");
|
||||
errors = true;
|
||||
}
|
||||
*/
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'i':
|
||||
|
@ -2892,7 +2897,7 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
|
|||
}
|
||||
use_match = true;
|
||||
cmdp += 2;
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
|
@ -2942,11 +2947,19 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
|
|||
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_MFU_OTP_TEAROFF, blockNoUint, actualTime, 0, teardata, 8);
|
||||
|
||||
// we be getting ACK that we are silently ignoring here..
|
||||
|
||||
if (!WaitForResponseTimeout(CMD_HF_MFU_OTP_TEAROFF, &resp, 2000)) {
|
||||
PrintAndLogEx(WARNING, "Failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
PrintAndLogEx(WARNING, "Tear off reporting failure to select tag");
|
||||
continue;
|
||||
}
|
||||
|
||||
got_post = false;
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_MIFAREU_READBL, blockNoUint, 0, 0, NULL, 0);
|
||||
|
@ -3046,7 +3059,38 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
static int counter_reset_tear(iso14a_card_select_t *card, uint8_t cnt_no) {
|
||||
|
||||
PrintAndLogEx(INFO, "Reset tear check");
|
||||
|
||||
uint8_t cw[6] = { MIFARE_ULEV1_INCR_CNT, cnt_no, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t ct[1] = {0};
|
||||
uint8_t resp[10] = {0};
|
||||
|
||||
if (ul_select(card) == false) {
|
||||
PrintAndLogEx(FAILED, "failed to select card, exiting...");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
if (ul_send_cmd_raw(cw, sizeof(cw), resp, sizeof(resp)) < 0) {
|
||||
PrintAndLogEx(FAILED, "failed to write all ZEROS");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
if (ulev1_readTearing(cnt_no, ct, sizeof(ct)) < 0) {
|
||||
PrintAndLogEx(FAILED, "AFTER, failed to read ANTITEAR, exiting...");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
DropField();
|
||||
|
||||
if (ct[0] != 0xBD) {
|
||||
PrintAndLogEx(INFO, "Resetting seem to have failed, WHY!?");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
|
||||
|
||||
CLIParserContext *ctx;
|
||||
|
@ -3062,16 +3106,33 @@ static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
|
|||
arg_int0("c", "cnt", "<0,1,2>", "Target this EV1 counter (0,1,2)"),
|
||||
arg_int0("i", "inc", "<dec>", "time interval to increase in each iteration - default 10 us"),
|
||||
arg_int0("l", "limit", "<dec>", "test upper limit time - default 3000 us"),
|
||||
arg_int0("s", "start", "<dec>", "test start time - default 0 us"),
|
||||
arg_int0("s", "start", "<dec>", "test start time - default 0 us"),
|
||||
arg_int0(NULL, "fix", "<dec>", "test fixed loop delay"),
|
||||
arg_str0("x", "hex", NULL, "3 byte hex to increase counter with"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
int interval = 0;
|
||||
int time_limit, start_time = 0;
|
||||
int counter = arg_get_int_def(ctx, 1, 0);
|
||||
int interval = arg_get_int_def(ctx, 2, 10);
|
||||
int time_limit = arg_get_int_def(ctx, 3, 3000);
|
||||
int start_time = arg_get_int_def(ctx, 4, 0);
|
||||
int fixed = arg_get_int_def(ctx, 5, -1);
|
||||
|
||||
if ( fixed == -1 ) {
|
||||
interval = arg_get_int_def(ctx, 2, 10);
|
||||
time_limit = arg_get_int_def(ctx, 3, 3000);
|
||||
start_time = arg_get_int_def(ctx, 4, 0);
|
||||
} else {
|
||||
start_time = fixed;
|
||||
interval = 0;
|
||||
time_limit = fixed;
|
||||
}
|
||||
|
||||
uint8_t newvalue[5] = {0};
|
||||
int newvaluelen = 0;
|
||||
CLIGetHexWithReturn(ctx, 6, newvalue, &newvaluelen);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
|
||||
// Validations
|
||||
if (start_time > (time_limit - interval)) {
|
||||
PrintAndLogEx(WARNING, "Wrong start time number");
|
||||
|
@ -3095,109 +3156,303 @@ static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
|
|||
|
||||
iso14a_card_select_t card;
|
||||
|
||||
if (ul_select(&card) == 0) {
|
||||
PrintAndLogEx(WARNING, "Failed to select card");
|
||||
// reset counter tear
|
||||
counter_reset_tear(&card, cnt_no);
|
||||
|
||||
if (ul_select(&card) == false) {
|
||||
PrintAndLogEx(INFO, "failed to select card, exiting...");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
||||
uint8_t inital_cnt[3] = {0, 0, 0};
|
||||
int len = ulev1_readCounter(cnt_no, inital_cnt, sizeof(inital_cnt));
|
||||
DropField();
|
||||
if ( len != sizeof(inital_cnt) ) {
|
||||
PrintAndLogEx(WARNING, "Failed to read counter");
|
||||
PrintAndLogEx(WARNING, "failed to read counter");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
uint8_t inital_tear[1] = {0};
|
||||
len = ulev1_readTearing(cnt_no, inital_tear, sizeof(inital_tear));
|
||||
DropField();
|
||||
if ( len != sizeof(inital_tear) ) {
|
||||
PrintAndLogEx(WARNING, "failed to read ANTITEAR, exiting... %d", len);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
uint32_t wr_value = ( newvalue[0] | newvalue[1] << 8 | newvalue[2] << 16 );
|
||||
uint32_t inital_value = ( inital_cnt[0] | inital_cnt[1] << 8 | inital_cnt[2] << 16 );;
|
||||
|
||||
PrintAndLogEx(INFO, "----------------- " _CYAN_("MFU Ev1 Counter Tear off") " ---------------------");
|
||||
PrintAndLogEx(INFO, "Target counter no " _GREEN_("%u"), counter);
|
||||
PrintAndLogEx(INFO, "Target initial value " _GREEN_("%s"), sprint_hex_inrow(inital_cnt, sizeof(inital_cnt)));
|
||||
PrintAndLogEx(INFO, "Target counter no [ " _GREEN_("%u") " ]", counter);
|
||||
PrintAndLogEx(INFO, " counter value [ " _GREEN_("%s") " ]", sprint_hex_inrow(inital_cnt, sizeof(inital_cnt)));
|
||||
PrintAndLogEx(INFO, " anti-tear value [ " _GREEN_("%02X") " ]", inital_tear[0]);
|
||||
PrintAndLogEx(INFO, " increase value [ " _GREEN_("%s") " ]", sprint_hex_inrow(newvalue, newvaluelen));
|
||||
PrintAndLogEx(INFO, "----------------------------------------------------");
|
||||
|
||||
bool got_pre = false, got_post = false;
|
||||
uint8_t pre_tear = 0, post_tear = 0;
|
||||
uint8_t pre[3] = {0};
|
||||
uint8_t post[3] = {0};
|
||||
uint32_t actual_time = start_time;
|
||||
uint32_t a = 0, b = 0;
|
||||
uint32_t loop = 0;
|
||||
|
||||
uint16_t late = 0;
|
||||
|
||||
while (actual_time <= (time_limit - interval)) {
|
||||
|
||||
|
||||
DropField();
|
||||
|
||||
loop++;
|
||||
|
||||
if (kbd_enter_pressed()) {
|
||||
PrintAndLogEx(INFO, "\naborted via keyboard!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
PrintAndLogEx(INPLACE, "Using tear-off delay " _GREEN_("%" PRIu32) " us", actual_time);
|
||||
PrintAndLogEx(INPLACE, "Using tear-off delay " _GREEN_("%" PRIu32) " us (attempt %u)", actual_time, loop);
|
||||
|
||||
if (ul_select(&card) == 0)
|
||||
return PM3_ESOFT;
|
||||
if (ul_select(&card) == false) {
|
||||
PrintAndLogEx(FAILED, "BEFORE, failed to select card, looping...");
|
||||
continue;
|
||||
}
|
||||
|
||||
got_pre = false;
|
||||
uint8_t cntresp[3] = {0, 0, 0};
|
||||
int rlen = ulev1_readCounter(cnt_no, cntresp, sizeof(cntresp));
|
||||
if ( rlen == sizeof(cntresp) ) {
|
||||
memcpy(pre, cntresp, sizeof(pre));
|
||||
got_pre = true;
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(FAILED, "BEFORE, failed to read COUNTER, exiting...");
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t tear[1] = {0};
|
||||
int tlen = ulev1_readTearing(cnt_no, tear, sizeof(tear));
|
||||
if ( tlen == sizeof(tear) ) {
|
||||
pre_tear = tear[0];
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(FAILED, "BEFORE, failed to read ANTITEAR, exiting... %d", tlen);
|
||||
break;
|
||||
}
|
||||
|
||||
DropField();
|
||||
|
||||
struct p {
|
||||
uint8_t counter;
|
||||
uint32_t tearoff_time;
|
||||
uint8_t value[3];
|
||||
} PACKED payload;
|
||||
payload.counter = cnt_no;
|
||||
payload.tearoff_time = actual_time;
|
||||
memcpy(payload.value, newvalue, sizeof(payload.value));
|
||||
|
||||
clearCommandBuffer();
|
||||
PacketResponseNG resp;
|
||||
SendCommandNG(CMD_HF_MFU_COUNTER_TEAROFF, (uint8_t*)&payload, sizeof(payload));
|
||||
if (!WaitForResponseTimeout(CMD_HF_MFU_COUNTER_TEAROFF, &resp, 2000)) {
|
||||
PrintAndLogEx(WARNING, "\ntear off command failed");
|
||||
return PM3_ESOFT;
|
||||
continue;
|
||||
}
|
||||
|
||||
got_post = false;
|
||||
if (ul_select(&card) == 0)
|
||||
return PM3_ESOFT;
|
||||
if (ul_select(&card) == false) {
|
||||
PrintAndLogEx(FAILED, "AFTER, failed to select card, exiting...");
|
||||
break;
|
||||
}
|
||||
|
||||
rlen = ulev1_readCounter(cnt_no, cntresp, sizeof(cntresp));
|
||||
if ( rlen == sizeof(cntresp) ) {
|
||||
memcpy(post, cntresp, sizeof(post));
|
||||
got_post = true;
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(FAILED, "AFTER, failed to read COUNTER, exiting...");
|
||||
break;
|
||||
}
|
||||
|
||||
tear[0] = 0;
|
||||
tlen = ulev1_readTearing(cnt_no, tear, sizeof(tear));
|
||||
if ( tlen == sizeof(tear) ) {
|
||||
post_tear = tear[0];
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(FAILED, "AFTER, failed to read ANTITEAR, exiting...");
|
||||
break;
|
||||
}
|
||||
|
||||
DropField();
|
||||
|
||||
if (got_pre && got_post) {
|
||||
char prestr[20] = {0};
|
||||
snprintf(prestr, sizeof(prestr), "%s", sprint_hex_inrow(pre, sizeof(pre)));
|
||||
char poststr[20] = {0};
|
||||
snprintf(poststr, sizeof(poststr), "%s", sprint_hex_inrow(post, sizeof(post)));
|
||||
|
||||
char prestr[20] = {0};
|
||||
snprintf(prestr, sizeof(prestr), "%s", sprint_hex_inrow(pre, sizeof(pre)));
|
||||
char poststr[20] = {0};
|
||||
snprintf(poststr, sizeof(poststr), "%s", sprint_hex_inrow(post, sizeof(post)));
|
||||
bool post_tear_check = (post_tear == 0xBD);
|
||||
a = (pre[0] | pre[1] << 8 | pre[2] << 16);
|
||||
b = (post[0] | post[1] << 8 | post[2] << 16);
|
||||
|
||||
if (memcmp(pre, post, sizeof(pre)) == 0) {
|
||||
// PrintAndLogEx(INFO, "Current %d - %s", cnt_no, poststr);
|
||||
// A != B
|
||||
if (memcmp(pre, post, sizeof(pre)) != 0) {
|
||||
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
if (inital_value != a ) {
|
||||
|
||||
if ( inital_value != b )
|
||||
PrintAndLogEx(INFO, "pre %08x, post %08x != inital %08x | tear: 0x%02X == 0x%02X", a, b, inital_value, pre_tear, post_tear);
|
||||
else
|
||||
PrintAndLogEx(INFO, "pre %08x != inital and post %08x == inital %08x | tear: 0x%02X == 0x%02X", a, b, inital_value, pre_tear, post_tear);
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, _CYAN_("Tear off occured") " : %d %s vs " _RED_("%s")
|
||||
, cnt_no, prestr, poststr);
|
||||
|
||||
if ( inital_value != b )
|
||||
PrintAndLogEx(INFO, "pre %08x == inital and post %08x != inital %08x | tear: 0x%02X == 0x%02X", a, b, inital_value, pre_tear, post_tear);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (got_pre == false) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(FAILED, "Failed to read Counter BEFORE");
|
||||
if ( b == 0 ) {
|
||||
PrintAndLogEx(INFO, _CYAN_("Tear off occured (ZEROS value!) -> ") "%s vs " _GREEN_("%s") " Tear status: 0x%02X == 0x%02X ( %s )"
|
||||
, prestr
|
||||
, poststr
|
||||
, pre_tear
|
||||
, post_tear
|
||||
, post_tear_check ? _GREEN_("OK") : _RED_("DETECTED")
|
||||
);
|
||||
break;
|
||||
}
|
||||
if (got_post == false) {
|
||||
|
||||
if ( a > b ) {
|
||||
PrintAndLogEx(INFO, _CYAN_("Tear off occured " _RED_("( LESS )") " -> ") "%s vs " _GREEN_("%s") " Tear status: 0x%02X == 0x%02X ( %s )"
|
||||
, prestr
|
||||
, poststr
|
||||
, pre_tear
|
||||
, post_tear
|
||||
, post_tear_check ? _GREEN_("OK") : _RED_("DETECTED")
|
||||
);
|
||||
|
||||
|
||||
if (counter_reset_tear(&card, cnt_no) != PM3_SUCCESS){
|
||||
PrintAndLogEx(FAILED, "failed to reset tear, exiting...");
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t bar = (0x1000000 - b) + 2;
|
||||
// wr_value = bar;
|
||||
// newvalue[0] = (bar) & 0xFF;
|
||||
// newvalue[1] = ((bar >> 8) & 0xFF);
|
||||
// newvalue[2] = ((bar >> 16) & 0xFF);
|
||||
|
||||
wr_value = 0;
|
||||
newvalue[0] = 0;
|
||||
newvalue[1] = 0;
|
||||
newvalue[2] = 0;
|
||||
|
||||
PrintAndLogEx(INFO, " 0x1000000 - 0x%x == 0x%x", b, bar);
|
||||
PrintAndLogEx(INFO, " new increase value 0x%x" , wr_value);
|
||||
PrintAndLogEx(INFO, " because BAR + post == 0x%x" , bar + b);
|
||||
|
||||
PrintAndLogEx(INFO, "New increase value " _YELLOW_("%s"), sprint_hex_inrow(newvalue, newvaluelen));
|
||||
continue;
|
||||
} else {
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(FAILED, "Failed to read Counter AFTER");
|
||||
PrintAndLogEx(INFO, _CYAN_("Tear off occured (+1) (too late) -> ") "%s vs %s Tear: 0x%02X == 0x%02X ( %s )"
|
||||
, prestr
|
||||
, poststr
|
||||
, pre_tear
|
||||
, post_tear
|
||||
, post_tear_check ? _GREEN_("OK") : _RED_("DETECTED")
|
||||
);
|
||||
|
||||
if ( post_tear_check && b == inital_value) {
|
||||
PrintAndLogEx(INFO, "Reverted to previous value");
|
||||
break;
|
||||
}
|
||||
if ( wr_value != 0 ) {
|
||||
|
||||
//uint32_t bar = (0x1000000 - b) + 2;
|
||||
wr_value = 0;
|
||||
newvalue[0] = 0;
|
||||
newvalue[1] = 0;
|
||||
newvalue[2] = 0;
|
||||
|
||||
if ( b >= (inital_value + (2 * wr_value))) {
|
||||
PrintAndLogEx(INFO, "Large " _YELLOW_("( JUMP )") " detected");
|
||||
|
||||
|
||||
// wr_value = bar;
|
||||
// newvalue[0] = (bar) & 0xFF;
|
||||
// newvalue[1] = ((bar >> 8) & 0xFF);
|
||||
// newvalue[2] = ((bar >> 16) & 0xFF);
|
||||
} else {
|
||||
|
||||
// wr_value = bar;
|
||||
// newvalue[0] = (bar) & 0xFF;
|
||||
// newvalue[1] = ((bar >> 8) & 0xFF);
|
||||
// newvalue[2] = ((bar >> 16) & 0xFF);
|
||||
// wr_value = 0;
|
||||
// newvalue[0] = 0;
|
||||
// newvalue[1] = 0;
|
||||
// newvalue[2] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
PrintAndLogEx(INFO, "New increase value " _YELLOW_("%s"), sprint_hex_inrow(newvalue, newvaluelen));
|
||||
|
||||
//actual_time--;
|
||||
late++;
|
||||
}
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, _CYAN_("Status: same value! -> ") "%s == %s Tear: 0x%02X == 0x%02X ( %s )"
|
||||
, prestr
|
||||
, poststr
|
||||
, pre_tear
|
||||
, post_tear
|
||||
, post_tear_check ? _GREEN_("OK") : _RED_("DETECTED")
|
||||
);
|
||||
|
||||
if ( post_tear_check ) {
|
||||
if ( a == b ) {
|
||||
//actual_time--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( b == inital_value ) {
|
||||
PrintAndLogEx(INFO, "Reverted to previous value");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
||||
if (counter_reset_tear(&card, cnt_no) != PM3_SUCCESS){
|
||||
PrintAndLogEx(FAILED, "failed to reset tear, exiting...");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
actual_time += interval;
|
||||
}
|
||||
|
||||
DropField();
|
||||
|
||||
PrintAndLogEx(INFO, " Sent %u tear offs ", loop);
|
||||
|
||||
counter_reset_tear(&card, cnt_no);
|
||||
|
||||
PrintAndLogEx(INFO, "hf 14a raw -s -c 3900 --> read counter 0");
|
||||
PrintAndLogEx(INFO, "hf 14a raw -s -c 3e00 --> read tearing 0");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
char read_cnt_str[30];
|
||||
sprintf(read_cnt_str, "hf 14a raw -s -c 39%02x", counter);
|
||||
CommandReceived(read_cnt_str);
|
||||
char read_tear_str[30];
|
||||
sprintf(read_tear_str, "hf 14a raw -s -c 3e%02x", counter);
|
||||
CommandReceived(read_tear_str);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
static int CmdHF14MfuNDEF(const char *Cmd) {
|
||||
|
||||
|
@ -3329,7 +3584,7 @@ static command_t CommandTable[] = {
|
|||
{"gen", CmdHF14AMfUGenDiverseKeys, AlwaysAvailable, "Generate 3des mifare diversified keys"},
|
||||
{"pwdgen", CmdHF14AMfUPwdGen, AlwaysAvailable, "Generate pwd from known algos"},
|
||||
{"otptear", CmdHF14AMfuOtpTearoff, IfPm3Iso14443a, "Tear-off test on OTP bits"},
|
||||
{"countertear", CmdHF14AMfuEv1CounterTearoff, IfPm3Iso14443a, "Tear-off test on Ev1 Counter bits"},
|
||||
// {"countertear", CmdHF14AMfuEv1CounterTearoff, IfPm3Iso14443a, "Tear-off test on Ev1 Counter bits"},
|
||||
{"ndef", CmdHF14MfuNDEF, IfPm3Iso14443a, "Prints NDEF records from card"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
|
|
@ -215,15 +215,20 @@ int infoHF_ST(void) {
|
|||
int aSELECT_AID_n = 0;
|
||||
param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
|
||||
int res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
||||
if (res)
|
||||
if (res) {
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
|
||||
if (resplen < 2)
|
||||
if (resplen < 2) {
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
uint16_t sw = get_sw(response, resplen);
|
||||
if (sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "Selecting NDEF aid failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -235,12 +240,15 @@ int infoHF_ST(void) {
|
|||
int aSELECT_FILE_CC_n = 0;
|
||||
param_gethex_to_eol("00a4000c02e103", 0, aSELECT_FILE_CC, sizeof(aSELECT_FILE_CC), &aSELECT_FILE_CC_n);
|
||||
res = ExchangeAPDU14a(aSELECT_FILE_CC, aSELECT_FILE_CC_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
||||
if (res)
|
||||
if (res) {
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
|
||||
sw = get_sw(response, resplen);
|
||||
if (sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "Selecting CC file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -248,12 +256,15 @@ int infoHF_ST(void) {
|
|||
int aREAD_CC_n = 0;
|
||||
param_gethex_to_eol("00b000000f", 0, aREAD_CC, sizeof(aREAD_CC), &aREAD_CC_n);
|
||||
res = ExchangeAPDU14a(aREAD_CC, aREAD_CC_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
||||
if (res)
|
||||
if (res) {
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
|
||||
sw = get_sw(response, resplen);
|
||||
if (sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "reading CC file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -265,12 +276,15 @@ int infoHF_ST(void) {
|
|||
int aSELECT_FILE_SYS_n = 0;
|
||||
param_gethex_to_eol("00a4000c02e101", 0, aSELECT_FILE_SYS, sizeof(aSELECT_FILE_SYS), &aSELECT_FILE_SYS_n);
|
||||
res = ExchangeAPDU14a(aSELECT_FILE_SYS, aSELECT_FILE_SYS_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
||||
if (res)
|
||||
if (res) {
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
|
||||
sw = get_sw(response, resplen);
|
||||
if (sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "Selecting system file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -280,12 +294,15 @@ int infoHF_ST(void) {
|
|||
int aREAD_SYS_n = 0;
|
||||
param_gethex_to_eol("00b0000012", 0, aREAD_SYS, sizeof(aREAD_SYS), &aREAD_SYS_n);
|
||||
res = ExchangeAPDU14a(aREAD_SYS, aREAD_SYS_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
||||
if (res)
|
||||
if (res) {
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
|
||||
sw = get_sw(response, resplen);
|
||||
if (sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "reading system file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
print_st_system_info(response, resplen - 2);
|
||||
|
@ -377,15 +394,20 @@ static int cmd_hf_st_ndef(const char *Cmd) {
|
|||
int aSELECT_AID_n = 0;
|
||||
param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
|
||||
int res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
||||
if (res)
|
||||
if (res) {
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
|
||||
if (resplen < 2)
|
||||
if (resplen < 2) {
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
uint16_t sw = get_sw(response, resplen);
|
||||
if (sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "Selecting NDEF aid failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -397,12 +419,15 @@ static int cmd_hf_st_ndef(const char *Cmd) {
|
|||
int aSELECT_FILE_NDEF_n = 0;
|
||||
param_gethex_to_eol("00a4000c020001", 0, aSELECT_FILE_NDEF, sizeof(aSELECT_FILE_NDEF), &aSELECT_FILE_NDEF_n);
|
||||
res = ExchangeAPDU14a(aSELECT_FILE_NDEF, aSELECT_FILE_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
||||
if (res)
|
||||
if (res) {
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
|
||||
sw = get_sw(response, resplen);
|
||||
if (sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "Selecting NDEF file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -412,8 +437,10 @@ static int cmd_hf_st_ndef(const char *Cmd) {
|
|||
int aVERIFY_n = 0;
|
||||
param_gethex_to_eol("0020000100", 0, aVERIFY, sizeof(aVERIFY), &aVERIFY_n);
|
||||
res = ExchangeAPDU14a(aVERIFY, aVERIFY_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
||||
if (res)
|
||||
if (res) {
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
|
||||
sw = get_sw(response, resplen);
|
||||
if (sw == 0x6300) {
|
||||
|
@ -421,12 +448,15 @@ static int cmd_hf_st_ndef(const char *Cmd) {
|
|||
param_gethex_to_eol("0020000110", 0, aVERIFY, sizeof(aVERIFY), &aVERIFY_n);
|
||||
memcpy(aVERIFY + aVERIFY_n, pwd, pwdlen);
|
||||
res = ExchangeAPDU14a(aVERIFY, aVERIFY_n + pwdlen, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
||||
if (res)
|
||||
if (res) {
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
|
||||
sw = get_sw(response, resplen);
|
||||
if (sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "Verify password failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
}
|
||||
|
@ -437,12 +467,15 @@ static int cmd_hf_st_ndef(const char *Cmd) {
|
|||
int aREAD_NDEF_n = 0;
|
||||
param_gethex_to_eol("00b000001d", 0, aREAD_NDEF, sizeof(aREAD_NDEF), &aREAD_NDEF_n);
|
||||
res = ExchangeAPDU14a(aREAD_NDEF, aREAD_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
||||
if (res)
|
||||
if (res) {
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
|
||||
sw = get_sw(response, resplen);
|
||||
if (sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "reading NDEF file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -490,25 +523,23 @@ static int cmd_hf_st_protect(const char *Cmd) {
|
|||
if (enable_protection && disable_protection) {
|
||||
PrintAndLogEx(ERR, "Must specify either enable or disable protection, not both");
|
||||
return PM3_EINVARG;
|
||||
} else {
|
||||
if (enable_protection) {
|
||||
state[0] = 0x28;
|
||||
}
|
||||
if (disable_protection) {
|
||||
state[0] = 0x26;
|
||||
}
|
||||
}
|
||||
if (enable_protection) {
|
||||
state[0] = 0x28;
|
||||
}
|
||||
if (disable_protection) {
|
||||
state[0] = 0x26;
|
||||
}
|
||||
|
||||
if (read_protection && write_protection) {
|
||||
PrintAndLogEx(ERR, "Must specify either read or write protection, not both");
|
||||
return PM3_EINVARG;
|
||||
} else {
|
||||
if (read_protection) {
|
||||
state[2] = 0x01;
|
||||
}
|
||||
if (write_protection) {
|
||||
state[2] = 0x02;
|
||||
}
|
||||
}
|
||||
if (read_protection) {
|
||||
state[2] = 0x01;
|
||||
}
|
||||
if (write_protection) {
|
||||
state[2] = 0x02;
|
||||
}
|
||||
|
||||
if (pwdlen != 16) {
|
||||
|
@ -526,15 +557,20 @@ static int cmd_hf_st_protect(const char *Cmd) {
|
|||
int aSELECT_AID_n = 0;
|
||||
param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
|
||||
int res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
||||
if (res)
|
||||
if (res) {
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
|
||||
if (resplen < 2)
|
||||
if (resplen < 2) {
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
uint16_t sw = get_sw(response, resplen);
|
||||
if (sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "Selecting NDEF aid failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -546,12 +582,15 @@ static int cmd_hf_st_protect(const char *Cmd) {
|
|||
int aSELECT_FILE_NDEF_n = 0;
|
||||
param_gethex_to_eol("00a4000c020001", 0, aSELECT_FILE_NDEF, sizeof(aSELECT_FILE_NDEF), &aSELECT_FILE_NDEF_n);
|
||||
res = ExchangeAPDU14a(aSELECT_FILE_NDEF, aSELECT_FILE_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
||||
if (res)
|
||||
if (res) {
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
|
||||
sw = get_sw(response, resplen);
|
||||
if (sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "Selecting NDEF file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -562,12 +601,15 @@ static int cmd_hf_st_protect(const char *Cmd) {
|
|||
param_gethex_to_eol("0020000210", 0, aVERIFY, sizeof(aVERIFY), &aVERIFY_n);
|
||||
memcpy(aVERIFY + aVERIFY_n, pwd, pwdlen);
|
||||
res = ExchangeAPDU14a(aVERIFY, aVERIFY_n + pwdlen, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
||||
if (res)
|
||||
if (res) {
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
|
||||
sw = get_sw(response, resplen);
|
||||
if (sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "Verify password failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -578,12 +620,15 @@ static int cmd_hf_st_protect(const char *Cmd) {
|
|||
param_gethex_to_eol("00", 0, aPROTECT, sizeof(aPROTECT), &aPROTECT_n);
|
||||
memcpy(aPROTECT + aPROTECT_n, state, statelen);
|
||||
res = ExchangeAPDU14a(aPROTECT, aPROTECT_n + statelen, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
||||
if (res)
|
||||
if (res) {
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
|
||||
sw = get_sw(response, resplen);
|
||||
if (sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "changing protection failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -629,13 +674,12 @@ static int cmd_hf_st_pwd(const char *Cmd) {
|
|||
if (change_read_password && change_write_password) {
|
||||
PrintAndLogEx(ERR, "Must specify either read or write, not both");
|
||||
return PM3_EINVARG;
|
||||
} else {
|
||||
if (change_read_password) {
|
||||
changePwd[2] = 0x01;
|
||||
}
|
||||
if (change_write_password) {
|
||||
changePwd[2] = 0x02;
|
||||
}
|
||||
}
|
||||
if (change_read_password) {
|
||||
changePwd[2] = 0x01;
|
||||
}
|
||||
if (change_write_password) {
|
||||
changePwd[2] = 0x02;
|
||||
}
|
||||
|
||||
if (pwdlen != 16) {
|
||||
|
@ -657,15 +701,20 @@ static int cmd_hf_st_pwd(const char *Cmd) {
|
|||
int aSELECT_AID_n = 0;
|
||||
param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
|
||||
int res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
||||
if (res)
|
||||
if (res) {
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
|
||||
if (resplen < 2)
|
||||
if (resplen < 2) {
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
uint16_t sw = get_sw(response, resplen);
|
||||
if (sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "Selecting NDEF aid failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -677,12 +726,15 @@ static int cmd_hf_st_pwd(const char *Cmd) {
|
|||
int aSELECT_FILE_NDEF_n = 0;
|
||||
param_gethex_to_eol("00a4000c020001", 0, aSELECT_FILE_NDEF, sizeof(aSELECT_FILE_NDEF), &aSELECT_FILE_NDEF_n);
|
||||
res = ExchangeAPDU14a(aSELECT_FILE_NDEF, aSELECT_FILE_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
||||
if (res)
|
||||
if (res) {
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
|
||||
sw = get_sw(response, resplen);
|
||||
if (sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "Selecting NDEF file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -693,12 +745,15 @@ static int cmd_hf_st_pwd(const char *Cmd) {
|
|||
param_gethex_to_eol("0020000210", 0, aVERIFY, sizeof(aVERIFY), &aVERIFY_n);
|
||||
memcpy(aVERIFY + aVERIFY_n, pwd, pwdlen);
|
||||
res = ExchangeAPDU14a(aVERIFY, aVERIFY_n + pwdlen, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
||||
if (res)
|
||||
if (res) {
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
|
||||
sw = get_sw(response, resplen);
|
||||
if (sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "Verify password failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -711,12 +766,15 @@ static int cmd_hf_st_pwd(const char *Cmd) {
|
|||
memcpy(aCHG_PWD + aCHG_PWD_n, changePwd, changePwdlen);
|
||||
memcpy(aCHG_PWD + aCHG_PWD_n + changePwdlen, newpwd, newpwdlen);
|
||||
res = ExchangeAPDU14a(aCHG_PWD, aCHG_PWD_n + changePwdlen + newpwdlen, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
||||
if (res)
|
||||
if (res) {
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
|
||||
sw = get_sw(response, resplen);
|
||||
if (sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "password change failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, " %s password changed", ((changePwd[2] & 0x01) == 0x01) ? _YELLOW_("read") : _YELLOW_("write"));
|
||||
|
|
|
@ -351,7 +351,7 @@ static void map8to1(uint8_t *colormap, uint16_t width, uint16_t height, uint8_t
|
|||
static int read_bmp_rgb(uint8_t *bmp, const size_t bmpsize, uint8_t model_nr, uint8_t **black, uint8_t **red, char *filename, bool save_conversions) {
|
||||
BMP_HEADER *pbmpheader = (BMP_HEADER *)bmp;
|
||||
// check file is full color
|
||||
if (pbmpheader->bpp != 24) {
|
||||
if ((pbmpheader->bpp != 24) && (pbmpheader->bpp != 32)) {
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -400,6 +400,8 @@ static int read_bmp_rgb(uint8_t *bmp, const size_t bmpsize, uint8_t model_nr, ui
|
|||
chanB[X + (height - Y - 1) * width] = bmp[offset++];
|
||||
chanG[X + (height - Y - 1) * width] = bmp[offset++];
|
||||
chanR[X + (height - Y - 1) * width] = bmp[offset++];
|
||||
if (pbmpheader->bpp == 32) // Skip Alpha chan
|
||||
offset++;
|
||||
}
|
||||
// Skip line padding
|
||||
offset += width % 4;
|
||||
|
@ -436,6 +438,8 @@ static int read_bmp_rgb(uint8_t *bmp, const size_t bmpsize, uint8_t model_nr, ui
|
|||
bmp[offset++] = chanB[X + (height - Y - 1) * width] & 0xFF;
|
||||
bmp[offset++] = chanG[X + (height - Y - 1) * width] & 0xFF;
|
||||
bmp[offset++] = chanR[X + (height - Y - 1) * width] & 0xFF;
|
||||
if (pbmpheader->bpp == 32) // Fill Alpha chan
|
||||
bmp[offset++] = 0xFF;
|
||||
}
|
||||
// Skip line padding
|
||||
offset += width % 4;
|
||||
|
@ -500,6 +504,8 @@ static int read_bmp_rgb(uint8_t *bmp, const size_t bmpsize, uint8_t model_nr, ui
|
|||
bmp[offset++] = chanGrey[X + (height - Y - 1) * width] & 0xFF;
|
||||
bmp[offset++] = chanGrey[X + (height - Y - 1) * width] & 0xFF;
|
||||
bmp[offset++] = chanGrey[X + (height - Y - 1) * width] & 0xFF;
|
||||
if (pbmpheader->bpp == 32) // Fill Alpha chan
|
||||
bmp[offset++] = 0xFF;
|
||||
}
|
||||
// Skip line padding
|
||||
offset += width % 4;
|
||||
|
@ -536,7 +542,8 @@ static void read_black(uint32_t i, uint8_t *l, uint8_t model_nr, uint8_t *black)
|
|||
}
|
||||
}
|
||||
static void read_red(uint32_t i, uint8_t *l, uint8_t model_nr, uint8_t *red) {
|
||||
for (uint8_t j = 0; j < models[model_nr].len; j++) {
|
||||
// spurious warning with GCC10 (-Wstringop-overflow) when j is uint8_t, even if all len are < 128
|
||||
for (uint16_t j = 0; j < models[model_nr].len; j++) {
|
||||
if (model_nr == M1in54B) {
|
||||
//1.54B needs to flip the red picture data, other screens do not need to flip data
|
||||
l[3 + j] = ~red[i * models[model_nr].len + j];
|
||||
|
@ -693,11 +700,21 @@ static int start_drawing(uint8_t model_nr, uint8_t *black, uint8_t *red) {
|
|||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
if ((card.uidlen != 7) || (memcmp(card.uid, "WSDZ10m", 7) != 0)) {
|
||||
if ((card.uidlen != 7) || ((memcmp(card.uid, "FSTN10m", 7) != 0) && (memcmp(card.uid, "WSDZ10m", 7) != 0))) {
|
||||
PrintAndLogEx(WARNING, "Card doesn't look like Waveshare tag");
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
if (((model_nr != M1in54B) && (memcmp(card.uid, "FSTN10m", 7) == 0))) {
|
||||
PrintAndLogEx(WARNING, "Card is a Waveshare tag 1.54\", not %s", models[model_nr].desc);
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
if (((model_nr == M1in54B) && (memcmp(card.uid, "FSTN10m", 7) != 0))) {
|
||||
PrintAndLogEx(WARNING, "Card is not a Waveshare tag 1.54\", check your model number");
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
PrintAndLogEx(DEBUG, "model_nr = %d", model_nr);
|
||||
int ret;
|
||||
PrintAndLogEx(DEBUG, "Step0");
|
||||
|
@ -921,6 +938,7 @@ static int start_drawing(uint8_t model_nr, uint8_t *black, uint8_t *red) {
|
|||
msleep(200);
|
||||
}
|
||||
PrintAndLogEx(DEBUG, "Step11: Wait tag to be ready");
|
||||
PrintAndLogEx(INPLACE, "E-paper Reflashing, Waiting");
|
||||
if (model_nr == M2in13B || model_nr == M1in54B) { // Black, white and red screen refresh time is longer, wait first
|
||||
msleep(9000);
|
||||
} else if (model_nr == M7in5HD) {
|
||||
|
@ -950,7 +968,7 @@ static int start_drawing(uint8_t model_nr, uint8_t *black, uint8_t *red) {
|
|||
} else {
|
||||
fail_num++;
|
||||
PrintAndLogEx(INPLACE, "E-paper Reflashing, Waiting");
|
||||
msleep(100);
|
||||
msleep(400);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1048,11 +1066,13 @@ static int CmdHF14AWSLoadBmp(const char *Cmd) {
|
|||
return PM3_ESOFT;
|
||||
}
|
||||
} else if (depth == 32) {
|
||||
PrintAndLogEx(ERR, "Error, BMP color depth %i not supported. Remove alpha channel.", depth);
|
||||
free(bmp);
|
||||
return PM3_ESOFT;
|
||||
PrintAndLogEx(DEBUG, "BMP file is a RGBA, we will ignore the Alpha channel");
|
||||
if (read_bmp_rgb(bmp, bytes_read, model_nr, &black, &red, filename, save_conversions) != PM3_SUCCESS) {
|
||||
free(bmp);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
} else {
|
||||
PrintAndLogEx(ERR, "Error, BMP color depth %i not supported. Must be 1 (BW) or 24 (RGB)", depth);
|
||||
PrintAndLogEx(ERR, "Error, BMP color depth %i not supported. Must be 1 (BW), 24 (RGB) or 32 (RGBA)", depth);
|
||||
free(bmp);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "cmdhw.h"
|
||||
#include "cmddata.h"
|
||||
#include "commonutil.h"
|
||||
#include "pm3_cmd.h"
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
|
@ -516,6 +517,33 @@ static int CmdStatus(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int handle_tearoff(tearoff_params_t *params, bool verbose) {
|
||||
|
||||
if (params == NULL)
|
||||
return PM3_EINVARG;
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SET_TEAROFF, (uint8_t *)params, sizeof(tearoff_params_t));
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_SET_TEAROFF, &resp, 500) == false) {
|
||||
PrintAndLogEx(WARNING, "Tear-off command timeout.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
if (resp.status == PM3_SUCCESS) {
|
||||
if (params->delay_us > 0 && verbose)
|
||||
PrintAndLogEx(INFO, "Tear-off hook configured with delay of " _GREEN_("%i us"), params->delay_us);
|
||||
|
||||
if (params->on && verbose)
|
||||
PrintAndLogEx(INFO, "Tear-off hook " _GREEN_("enabled"));
|
||||
|
||||
if (params->off && verbose)
|
||||
PrintAndLogEx(INFO, "Tear-off hook " _RED_("disabled"));
|
||||
} else if (verbose)
|
||||
PrintAndLogEx(WARNING, "Tear-off command failed.");
|
||||
return resp.status;
|
||||
}
|
||||
|
||||
static int CmdTearoff(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hw tearoff",
|
||||
|
@ -536,11 +564,7 @@ static int CmdTearoff(const char *Cmd) {
|
|||
};
|
||||
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
struct {
|
||||
uint16_t delay_us;
|
||||
bool on;
|
||||
bool off;
|
||||
} PACKED params;
|
||||
tearoff_params_t params;
|
||||
int delay = arg_get_int_def(ctx, 1, -1);
|
||||
params.on = arg_get_lit(ctx, 2);
|
||||
params.off = arg_get_lit(ctx, 3);
|
||||
|
@ -562,29 +586,7 @@ static int CmdTearoff(const char *Cmd) {
|
|||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SET_TEAROFF, (uint8_t *)¶ms, sizeof(params));
|
||||
PacketResponseNG resp;
|
||||
|
||||
if (WaitForResponseTimeout(CMD_SET_TEAROFF, &resp, 500) == false) {
|
||||
PrintAndLogEx(WARNING, "Tear-off command timeout.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
if (resp.status == PM3_SUCCESS) {
|
||||
if (params.delay_us > 0)
|
||||
PrintAndLogEx(INFO, "Tear-off hook configured with delay of " _GREEN_("%i us"), params.delay_us);
|
||||
if (params.on && silent == false)
|
||||
PrintAndLogEx(INFO, "Tear-off hook " _GREEN_("enabled"));
|
||||
if (params.off && silent == false)
|
||||
PrintAndLogEx(INFO, "Tear-off hook " _RED_("disabled"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
if (silent == false)
|
||||
PrintAndLogEx(WARNING, "Tear-off command failed.");
|
||||
|
||||
return resp.status;
|
||||
return handle_tearoff(¶ms, !silent);
|
||||
}
|
||||
|
||||
static int CmdTia(const char *Cmd) {
|
||||
|
@ -679,6 +681,7 @@ static int CmdConnect(const char *Cmd) {
|
|||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"-------------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("Hardware") " -----------------------"},
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"connect", CmdConnect, AlwaysAvailable, "connect Proxmark3 to serial port"},
|
||||
{"dbg", CmdDbg, IfPm3Present, "Set Proxmark3 debug level"},
|
||||
|
@ -790,18 +793,18 @@ void pm3_version(bool verbose, bool oneliner) {
|
|||
|
||||
PrintAndLogEx(NORMAL, "\n [ " _YELLOW_("PROXMARK3") " ]");
|
||||
if (IfPm3Rdv4Fw() == false) {
|
||||
PrintAndLogEx(NORMAL, " firmware.........................%s", _GREEN_("PM3OTHER"));
|
||||
PrintAndLogEx(NORMAL, " firmware.................. %s", _YELLOW_("PM3OTHER"));
|
||||
if (IfPm3FpcUsartHost()) {
|
||||
PrintAndLogEx(NORMAL, " FPC USART for BT add-on..........%s", _GREEN_("present"));
|
||||
PrintAndLogEx(NORMAL, " FPC USART for BT add-on... %s", _GREEN_("present"));
|
||||
}
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL, " firmware.........................%s", _GREEN_("PM3RDV4"));
|
||||
PrintAndLogEx(NORMAL, " external flash...................%s", IfPm3Flash() ? _GREEN_("present") : _YELLOW_("absent"));
|
||||
PrintAndLogEx(NORMAL, " smartcard reader.................%s", IfPm3Smartcard() ? _GREEN_("present") : _YELLOW_("absent"));
|
||||
PrintAndLogEx(NORMAL, " FPC USART for BT add-on..........%s", IfPm3FpcUsartHost() ? _GREEN_("present") : _YELLOW_("absent"));
|
||||
PrintAndLogEx(NORMAL, " firmware.................. %s", _YELLOW_("PM3RDV4"));
|
||||
PrintAndLogEx(NORMAL, " external flash............ %s", IfPm3Flash() ? _GREEN_("present") : _YELLOW_("absent"));
|
||||
PrintAndLogEx(NORMAL, " smartcard reader.......... %s", IfPm3Smartcard() ? _GREEN_("present") : _YELLOW_("absent"));
|
||||
PrintAndLogEx(NORMAL, " FPC USART for BT add-on... %s", IfPm3FpcUsartHost() ? _GREEN_("present") : _YELLOW_("absent"));
|
||||
}
|
||||
if (IfPm3FpcUsartDevFromUsb()) {
|
||||
PrintAndLogEx(NORMAL, " FPC USART for developer..........%s", _GREEN_("present"));
|
||||
PrintAndLogEx(NORMAL, " FPC USART for developer... %s", _GREEN_("present"));
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
|
|
@ -12,9 +12,11 @@
|
|||
#define CMDHW_H__
|
||||
|
||||
#include "common.h"
|
||||
#include "pm3_cmd.h"
|
||||
|
||||
int CmdHW(const char *Cmd);
|
||||
|
||||
int handle_tearoff(tearoff_params_t *params, bool verbose);
|
||||
void pm3_version(bool verbose, bool oneliner);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "cmddata.h" // for `lf search`
|
||||
#include "cmdlfawid.h" // for awid menu
|
||||
#include "cmdlfem4x.h" // for em4x menu
|
||||
#include "cmdlfem4x05.h" // for em4x05 / 4x69
|
||||
#include "cmdlfem4x50.h" // for em4x50
|
||||
#include "cmdlfhid.h" // for hid menu
|
||||
#include "cmdlfhitag.h" // for hitag menu
|
||||
|
@ -112,7 +113,7 @@ static int usage_lf_read(void) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_lf_sim(void) {
|
||||
PrintAndLogEx(NORMAL, "Simulate low frequence tag from graphbuffer.");
|
||||
PrintAndLogEx(NORMAL, "Simulate low frequency tag from graphbuffer.");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf sim [h] <gap>");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h This help");
|
||||
|
@ -125,7 +126,7 @@ static int usage_lf_sim(void) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_lf_sniff(void) {
|
||||
PrintAndLogEx(NORMAL, "Sniff low frequence signal.");
|
||||
PrintAndLogEx(NORMAL, "Sniff low frequency signal.");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf sniff [h] [q] [s #samples] [@]");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h This help");
|
||||
|
@ -1347,7 +1348,7 @@ static bool CheckChipType(bool getDeviceData) {
|
|||
|
||||
//check for em4x05/em4x69 chips first
|
||||
uint32_t word = 0;
|
||||
if (EM4x05IsBlock0(&word)) {
|
||||
if (em4x05_isblock0(&word)) {
|
||||
PrintAndLogEx(SUCCESS, "Chipset detection: " _GREEN_("EM4x05 / EM4x69"));
|
||||
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf em 4x05`") " commands");
|
||||
retval = true;
|
||||
|
@ -1525,7 +1526,7 @@ out:
|
|||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"-----------", CmdHelp, AlwaysAvailable, "-------------- " _CYAN_("Direct") " --------------"},
|
||||
{"-----------", CmdHelp, AlwaysAvailable, "-------------- " _CYAN_("Low Frequency") " --------------"},
|
||||
{"awid", CmdLFAWID, AlwaysAvailable, "{ AWID RFIDs... }"},
|
||||
{"cotag", CmdLFCOTAG, AlwaysAvailable, "{ COTAG CHIPs... }"},
|
||||
{"destron", CmdLFDestron, AlwaysAvailable, "{ FDX-A Destron RFIDs... }"},
|
||||
|
|
|
@ -66,12 +66,12 @@ int demodDestron(bool verbose) {
|
|||
|
||||
uint8_t data[5] = {0};
|
||||
uint8_t parity_err = 0;
|
||||
for (int i=0; i < sizeof(data); i++) {
|
||||
for (int i = 0; i < sizeof(data); i++) {
|
||||
data[i] = bytebits_to_byte(bits + i * 8, 8);
|
||||
parity_err += oddparity8(data[i]);
|
||||
data[i] &= 0x7F;
|
||||
}
|
||||
if (errCnt > 0) {
|
||||
if (parity_err > 0) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Destron: parity errors: %d", parity_err);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
@ -113,11 +113,11 @@ static int CmdDestronClone(const char *Cmd) {
|
|||
CLIParserFree(ctx);
|
||||
|
||||
uint8_t data_ex[12 + 24] = {0}; // ManchesterEncode need extra room
|
||||
for (int i=0; i < datalen; i++) {
|
||||
for (int i = 0; i < datalen; i++) {
|
||||
data_ex[i + 1] = ~data [i] | (evenparity8(data[i]) << 7);
|
||||
}
|
||||
for (int i=0; i < 3; i++) {
|
||||
blocks[i+1] = manchesterEncode2Bytes((data_ex[i*2]<<8)+data_ex[i*2+1]);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
blocks[i + 1] = manchesterEncode2Bytes((data_ex[i * 2] << 8) + data_ex[i * 2 + 1]);
|
||||
}
|
||||
// inject preamble
|
||||
blocks[1] = (blocks[1] & 0xFFFF) | 0xAAE20000;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -16,10 +16,8 @@
|
|||
int CmdLFEM4X(const char *Cmd);
|
||||
|
||||
int demodEM410x(bool verbose);
|
||||
bool EM4x05IsBlock0(uint32_t *word);
|
||||
int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *word);
|
||||
|
||||
void printEM410x(uint32_t hi, uint64_t id);
|
||||
|
||||
int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo);
|
||||
int AskEm410xDemod(int clk, int invert, int maxErr, size_t maxLen, bool amplify, uint32_t *hi, uint64_t *lo, bool verbose);
|
||||
|
||||
|
|
2046
client/src/cmdlfem4x05.c
Normal file
2046
client/src/cmdlfem4x05.c
Normal file
File diff suppressed because it is too large
Load diff
79
client/src/cmdlfem4x05.h
Normal file
79
client/src/cmdlfem4x05.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
|
||||
// 2016, 2017 marshmellow, iceman
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Low frequency EM4x05 commands
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef CMDLFEM4X05_H__
|
||||
#define CMDLFEM4X05_H__
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define EM_SERIAL_BLOCK 1
|
||||
#define EM_CONFIG_BLOCK 4
|
||||
#define EM4305_PROT1_BLOCK 14
|
||||
#define EM4305_PROT2_BLOCK 15
|
||||
#define EM4469_PROT_BLOCK 3
|
||||
|
||||
// config blocks
|
||||
#define EM4305_DEFAULT_CONFIG_BLOCK (EM4x05_SET_BITRATE(32) | EM4x05_MODULATION_MANCHESTER | EM4x05_SET_NUM_BLOCKS(4) ) // ASK/MAN , data rate 32, 4 data blocks
|
||||
//#define EM4305_DEFAULT_CONFIG_BLOCK (EM4x05_SET_BITRATE(32) | EM4x05_MODULATION_BIPHASE | EM4x05_SET_NUM_BLOCKS(4) ) // ASK/BIPHASE , data rate 32, 4 data blocks
|
||||
|
||||
#define EM4305_EM_UNIQUE_CONFIG_BLOCK (EM4x05_SET_BITRATE(64) | EM4x05_MODULATION_MANCHESTER | EM4x05_SET_NUM_BLOCKS(2) ) // ASK/MAN, EM4x02/unique - data rate 64, 2 data blocks
|
||||
#define EM4305_PAXTON_CONFIG_BLOCK (EM4x05_SET_BITRATE(64) | EM4x05_MODULATION_MANCHESTER | EM4x05_SET_NUM_BLOCKS(2) ) // ASK/MAN, EM4x02/paxton - data rate 64, 2 data blocks
|
||||
#define EM4305_VISA2000_CONFIG_BLOCK (EM4x05_SET_BITRATE(64) | EM4x05_MODULATION_MANCHESTER | EM4x05_SET_NUM_BLOCKS(3) ) // ASK, data rate 64, 3 data blocks
|
||||
#define EM4305_VIKING_CONFIG_BLOCK (EM4x05_SET_BITRATE(32) | EM4x05_MODULATION_MANCHESTER | EM4x05_SET_NUM_BLOCKS(2) ) // ASK/MAN, data rate 32, 2 data blocks
|
||||
#define EM4305_NORALSY_CONFIG_BLOCK (EM4x05_SET_BITRATE(32) | EM4x05_MODULATION_MANCHESTER | EM4x05_SET_NUM_BLOCKS(3) ) // ASK, data rate 32, 3 data blocks
|
||||
#define EM4305_PRESCO_CONFIG_BLOCK (EM4x05_SET_BITRATE(32) | EM4x05_MODULATION_MANCHESTER | EM4x05_SET_NUM_BLOCKS(4) ) // ASK/MAN, data rate 32, 4 data blocks
|
||||
#define EM4305_SECURAKEY_CONFIG_BLOCK (EM4x05_SET_BITRATE(40) | EM4x05_MODULATION_MANCHESTER | EM4x05_SET_NUM_BLOCKS(3) ) // ASK/MAN, data rate 40, 3 data blocks
|
||||
|
||||
#define EM4305_HID_26_CONFIG_BLOCK (EM4x05_SET_BITRATE(50) | EM4x05_MODULATION_FSK2 | EM4x05_SET_NUM_BLOCKS(3) ) // FSK2a, hid 26 bit, data rate 50, 3 data blocks
|
||||
#define EM4305_PARADOX_CONFIG_BLOCK (EM4x05_SET_BITRATE(50) | EM4x05_MODULATION_FSK2 | EM4x05_SET_NUM_BLOCKS(3) ) // FSK2a, hid 26 bit, data rate 50, 3 data blocks
|
||||
#define EM4305_AWID_CONFIG_BLOCK (EM4x05_SET_BITRATE(50) | EM4x05_MODULATION_FSK2 | EM4x05_SET_NUM_BLOCKS(3) ) // FSK2a, hid 26 bit, data rate 50, 3 data blocks
|
||||
#define EM4305_PYRAMID_CONFIG_BLOCK (EM4x05_SET_BITRATE(50) | EM4x05_MODULATION_FSK2 | EM4x05_SET_NUM_BLOCKS(4) ) // FSK2a, Pyramid 26 bit, data rate 50, 4 data blocks
|
||||
#define EM4305_IOPROX_CONFIG_BLOCK (EM4x05_SET_BITRATE(64) | EM4x05_MODULATION_FSK2 | EM4x05_SET_NUM_BLOCKS(2) ) // FSK2a, data rate 64, 2 data blocks
|
||||
|
||||
#define EM4305_INDALA_64_CONFIG_BLOCK (EM4x05_SET_BITRATE(64) | EM4x05_MODULATION_PSK1 | EM4x05_PSK_RF_2 | EM4x05_SET_NUM_BLOCKS(2) ) // PSK1, indala 64 bit, psk carrier FC * 2, data rate 32, maxblock 2
|
||||
#define EM4305_INDALA_224_CONFIG_BLOCK (EM4x05_SET_BITRATE(64) | EM4x05_MODULATION_PSK1 | EM4x05_PSK_RF_2 | EM4x05_SET_NUM_BLOCKS(7) ) // PSK1, indala 224 bit, psk carrier FC * 2, data rate 32, maxblock 7
|
||||
#define EM4305_MOTOROLA_CONFIG_BLOCK (EM4x05_SET_BITRATE(32) | EM4x05_MODULATION_PSK1 | EM4x05_PSK_RF_2 | EM4x05_SET_NUM_BLOCKS(2) ) // PSK1, data rate 32, 2 data blocks
|
||||
#define EM4305_NEXWATCH_CONFIG_BLOCK (EM4x05_SET_BITRATE(64) | EM4x05_MODULATION_PSK1 | EM4x05_PSK_RF_2 | EM4x05_SET_NUM_BLOCKS(3) ) // PSK1 data rate 16, psk carrier FC * 2, 3 data blocks
|
||||
#define EM4305_KERI_CONFIG_BLOCK (EM4x05_SET_BITRATE(64) | EM4x05_MODULATION_PSK1 | EM4x05_PSK_RF_2 | EM4x05_SET_NUM_BLOCKS(2) ) // PSK1, 2 data blocks
|
||||
|
||||
#define EM4305_JABLOTRON_CONFIG_BLOCK (EM4x05_SET_BITRATE(64) | EM4x05_MODULATION_BIPHASE | EM4x05_SET_NUM_BLOCKS(2) ) // Biphase, data rate 64, 2 data blocks
|
||||
#define EM4305_GUARDPROXII_CONFIG_BLOCK (EM4x05_SET_BITRATE(64) | EM4x05_MODULATION_BIPHASE | EM4x05_SET_NUM_BLOCKS(3) ) // Biphase, data rate 64, Direct modulation, 3 data blocks
|
||||
#define EM4305_NEDAP_64_CONFIG_BLOCK (EM4x05_SET_BITRATE(64) | EM4x05_MODULATION_BIPHASE | EM4x05_SET_NUM_BLOCKS(2) ) // Biphase, data rate 64, 2 data blocks
|
||||
#define EM4305_NEDAP_128_CONFIG_BLOCK (EM4x05_SET_BITRATE(64) | EM4x05_MODULATION_BIPHASE | EM4x05_SET_NUM_BLOCKS(4) ) // Biphase, data rate 64, 4 data blocks
|
||||
|
||||
#define EM4305_PAC_CONFIG_BLOCK (EM4x05_SET_BITRATE(32) | EM4x05_MODULATION_NRZ | EM4x05_SET_NUM_BLOCKS(4) ) // NRZ, data rate 32, 4 data blocks
|
||||
#define EM4305_VERICHIP_CONFIG_BLOCK (EM4x05_SET_BITRATE(40) | EM4x05_MODULATION_NRZ | EM4x05_SET_NUM_BLOCKS(4) ) // NRZ, data rate 40, 4 data blocks
|
||||
|
||||
typedef enum {
|
||||
EM_UNKNOWN,
|
||||
EM_4205,
|
||||
EM_4305,
|
||||
EM_4X69,
|
||||
} em_tech_type_t;
|
||||
|
||||
int CmdLFEM4X05(const char *Cmd);
|
||||
|
||||
bool em4x05_isblock0(uint32_t *word);
|
||||
int em4x05_read_word_ext(uint8_t addr, uint32_t pwd, bool use_pwd, uint32_t *word);
|
||||
int em4x05_write_word_ext(uint8_t addr, uint32_t pwd, bool use_pwd, uint32_t data);
|
||||
int em4x05_clone_tag(uint32_t *blockdata, uint8_t numblocks, uint32_t pwd, bool use_pwd);
|
||||
|
||||
int CmdEM4x05Demod(const char *Cmd);
|
||||
int CmdEM4x05Dump(const char *Cmd);
|
||||
int CmdEM4x05Read(const char *Cmd);
|
||||
int CmdEM4x05Write(const char *Cmd);
|
||||
int CmdEM4x05Wipe(const char *Cmd);
|
||||
int CmdEM4x05Info(const char *Cmd);
|
||||
int CmdEM4x05Chk(const char *Cmd);
|
||||
int CmdEM4x05Unlock(const char *Cmd);
|
||||
int CmdEM4x05Sniff(const char *Cmd);
|
||||
int CmdEM4x05Brute(const char *Cmd);
|
||||
|
||||
#endif
|
|
@ -77,7 +77,7 @@ static int usage_lf_em4x50_dump(void) {
|
|||
PrintAndLogEx(NORMAL, "Usage: lf em 4x50_dump [h] [f <filename prefix>] [p <pwd>]");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h - this help");
|
||||
PrintAndLogEx(NORMAL, " f <filename prefix> - overide filename prefix (optional). Default is based on UID");
|
||||
PrintAndLogEx(NORMAL, " f <filename prefix> - override filename prefix (optional). Default is based on UID");
|
||||
PrintAndLogEx(NORMAL, " p <pwd> - password (hex) (optional)");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_dump"));
|
||||
|
@ -315,7 +315,7 @@ int CmdEM4x50Info(const char *Cmd) {
|
|||
SendCommandNG(CMD_LF_EM4X50_INFO, (uint8_t *)&etd, sizeof(etd));
|
||||
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
|
||||
if (!WaitForResponseTimeout(CMD_LF_EM4X50_INFO, &resp, TIMEOUT)) {
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
@ -388,11 +388,14 @@ int CmdEM4x50Write(const char *Cmd) {
|
|||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_LF_EM4X50_WRITE, (uint8_t *)&etd, sizeof(etd));
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
|
||||
if (!WaitForResponseTimeout(CMD_LF_EM4X50_WRITE, &resp, TIMEOUT)) {
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
if (resp.status == PM3_ETEAROFF)
|
||||
return PM3_SUCCESS;
|
||||
|
||||
bool isOK = (resp.status & STATUS_SUCCESS) >> 1;
|
||||
if (isOK == false) {
|
||||
PrintAndLogEx(FAILED, "writing " _RED_("failed"));
|
||||
|
@ -483,10 +486,14 @@ int CmdEM4x50WritePassword(const char *Cmd) {
|
|||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_LF_EM4X50_WRITE_PASSWORD, (uint8_t *)&etd, sizeof(etd));
|
||||
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
|
||||
if (!WaitForResponseTimeout(CMD_LF_EM4X50_WRITE_PASSWORD, &resp, TIMEOUT)) {
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
if (resp.status == PM3_ETEAROFF)
|
||||
return PM3_SUCCESS;
|
||||
|
||||
success = (bool)resp.status;
|
||||
|
||||
// get, prepare and print response
|
||||
|
@ -515,7 +522,7 @@ int em4x50_read(em4x50_data_t *etd, em4x50_word_t *out, bool verbose) {
|
|||
SendCommandNG(CMD_LF_EM4X50_READ, (uint8_t *)&edata, sizeof(edata));
|
||||
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
|
||||
if (!WaitForResponseTimeout(CMD_LF_EM4X50_READ, &resp, TIMEOUT)) {
|
||||
PrintAndLogEx(WARNING, "(em4x50) timeout while waiting for reply.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
@ -651,7 +658,7 @@ int CmdEM4x50Dump(const char *Cmd) {
|
|||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_LF_EM4X50_INFO, (uint8_t *)&etd, sizeof(etd));
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
|
||||
if (!WaitForResponseTimeout(CMD_LF_EM4X50_INFO, &resp, TIMEOUT)) {
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
@ -726,7 +733,7 @@ int CmdEM4x50Wipe(const char *Cmd) {
|
|||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_LF_EM4X50_WIPE, (uint8_t *)&etd, sizeof(etd));
|
||||
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2 * TIMEOUT)) {
|
||||
if (!WaitForResponseTimeout(CMD_LF_EM4X50_WIPE, &resp, 2 * TIMEOUT)) {
|
||||
PrintAndLogEx(WARNING, "\ntimeout while waiting for reply.\n");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
|
|
@ -470,7 +470,7 @@ const fdxbCountryMapping_t fdxbCountryMapping[] = {
|
|||
{ 0, "N/A" } // must be the last entry
|
||||
};
|
||||
|
||||
static const char* mapFDBX(uint16_t countryCode) {
|
||||
static const char *mapFDBX(uint16_t countryCode) {
|
||||
uint16_t i = 0;
|
||||
while (fdxbCountryMapping[i].code > 0) {
|
||||
if (countryCode == fdxbCountryMapping[i].code) {
|
||||
|
@ -572,8 +572,8 @@ int demodFDXB(bool verbose) {
|
|||
PrintAndLogEx(SUCCESS, " Animal bit set? %s", animalBit ? _YELLOW_("True") : "False");
|
||||
PrintAndLogEx(SUCCESS, " Data block? %s [value 0x%X]", dataBlockBit ? _YELLOW_("True") : "False", extended);
|
||||
PrintAndLogEx(SUCCESS, " RUDI bit? %s", rudiBit ? _YELLOW_("True") " (advanced transponder)" : "False");
|
||||
PrintAndLogEx(SUCCESS, " User Info? %u %s", userInfo, userInfo == 0 ? "(RFU)":"");
|
||||
PrintAndLogEx(SUCCESS, " Replacement No? %u %s", replacementNr, replacementNr == 0 ? "(RFU)":"");
|
||||
PrintAndLogEx(SUCCESS, " User Info? %u %s", userInfo, userInfo == 0 ? "(RFU)" : "");
|
||||
PrintAndLogEx(SUCCESS, " Replacement No? %u %s", replacementNr, replacementNr == 0 ? "(RFU)" : "");
|
||||
|
||||
uint8_t c[] = {0, 0};
|
||||
compute_crc(CRC_11784, raw, sizeof(raw), &c[0], &c[1]);
|
||||
|
|
|
@ -417,7 +417,7 @@ static int CmdHIDBrute(const char *Cmd) {
|
|||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
bool verbose = arg_get_lit(ctx, 1);
|
||||
|
||||
formatLen = sizeof(format);
|
||||
CLIGetStrWithReturn(ctx, 2, format, &formatLen);
|
||||
|
||||
format_idx = HIDFindCardFormat((char *) format);
|
||||
|
@ -433,8 +433,6 @@ static int CmdHIDBrute(const char *Cmd) {
|
|||
cn_hi.OEM = arg_get_int_def(ctx, 6, 0);
|
||||
delay = arg_get_int_def(ctx, 7, 1000);
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (arg_get_lit(ctx, 8) && arg_get_lit(ctx, 9)) {
|
||||
direction = 0;
|
||||
} else if (arg_get_lit(ctx, 8)) {
|
||||
|
@ -443,6 +441,8 @@ static int CmdHIDBrute(const char *Cmd) {
|
|||
direction = 2;
|
||||
}
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, "Wiegand format#.. %i", format_idx);
|
||||
PrintAndLogEx(INFO, "OEM#............. %u", cn_hi.OEM);
|
||||
|
@ -470,7 +470,7 @@ static int CmdHIDBrute(const char *Cmd) {
|
|||
cn_low = cn_hi;
|
||||
|
||||
// main loop
|
||||
// iceman: could add options for bruteforcing OEM, ISSUE or FC aswell..
|
||||
// iceman: could add options for bruteforcing OEM, ISSUE or FC as well..
|
||||
bool exitloop = false;
|
||||
bool fin_hi, fin_low;
|
||||
fin_hi = fin_low = false;
|
||||
|
|
|
@ -567,13 +567,9 @@ static int CmdIndalaSim(const char *Cmd) {
|
|||
|
||||
static int CmdIndalaClone(const char *Cmd) {
|
||||
|
||||
bool is_long_uid = false, got_cn = false, got_26 = false;
|
||||
bool is_t5555 = false;
|
||||
int32_t cardnumber;
|
||||
uint32_t blocks[8] = {0};
|
||||
uint8_t max = 0;
|
||||
uint8_t data[7 * 4];
|
||||
int datalen = 0;
|
||||
uint8_t fc = 0;
|
||||
uint16_t cn = 0;
|
||||
|
||||
|
@ -597,13 +593,16 @@ static int CmdIndalaClone(const char *Cmd) {
|
|||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
is_long_uid = arg_get_lit(ctx, 1);
|
||||
bool is_long_uid = arg_get_lit(ctx, 1);
|
||||
|
||||
// raw param
|
||||
int datalen = 0;
|
||||
uint8_t data[(7 * 4) + 1 ];
|
||||
CLIGetHexWithReturn(ctx, 3, data, &datalen);
|
||||
|
||||
is_t5555 = arg_get_lit(ctx, 4);
|
||||
bool is_t5555 = arg_get_lit(ctx, 4);
|
||||
|
||||
bool got_cn = false, got_26 = false;
|
||||
if (is_long_uid == false) {
|
||||
|
||||
// Heden param
|
||||
|
@ -618,11 +617,13 @@ static int CmdIndalaClone(const char *Cmd) {
|
|||
|
||||
CLIParserFree(ctx);
|
||||
|
||||
PrintAndLogEx(INFO, "Target chip " _YELLOW_("%s"), (is_t5555) ? "Q5/T5555" : "T55x7");
|
||||
|
||||
if (is_long_uid) {
|
||||
// 224 BIT UID
|
||||
// config for Indala (RF/32;PSK2 with RF/2;Maxblock=7)
|
||||
PrintAndLogEx(INFO, "Preparing to clone Indala 224bit tag");
|
||||
PrintAndLogEx(INFO, "RawID %s", sprint_hex(data, datalen));
|
||||
PrintAndLogEx(INFO, "Using raw " _GREEN_("%s"), sprint_hex_inrow(data, datalen));
|
||||
|
||||
if (is_t5555)
|
||||
blocks[0] = T5555_FIXED | T5555_SET_BITRATE(32) | T5555_MODULATION_PSK2 | (7 << T5555_MAXBLOCK_SHIFT);
|
||||
|
@ -675,7 +676,7 @@ static int CmdIndalaClone(const char *Cmd) {
|
|||
|
||||
// config for Indala 64 format (RF/32;PSK1 with RF/2;Maxblock=2)
|
||||
PrintAndLogEx(INFO, "Preparing to clone Indala 64bit tag");
|
||||
PrintAndLogEx(INFO, "RawID %s", sprint_hex(data, datalen));
|
||||
PrintAndLogEx(INFO, "Using raw " _GREEN_("%s"), sprint_hex_inrow(data, datalen));
|
||||
|
||||
if (is_t5555)
|
||||
blocks[0] = T5555_FIXED | T5555_SET_BITRATE(32) | T5555_MODULATION_PSK1 | (2 << T5555_MAXBLOCK_SHIFT);
|
||||
|
|
|
@ -8,23 +8,21 @@
|
|||
// PSK1, RF/128, RF/2, 64 bits long
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "cmdlfkeri.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "commonutil.h" // ARRAYLEN
|
||||
#include "commonutil.h" // ARRAYLEN
|
||||
#include "cmdparser.h" // command_t
|
||||
#include "cliparser.h"
|
||||
#include "comms.h"
|
||||
#include "ui.h"
|
||||
#include "cmddata.h"
|
||||
#include "cmdlf.h"
|
||||
#include "protocols.h" // for T55xx config register definitions
|
||||
#include "lfdemod.h" // preamble test
|
||||
#include "cmdlft55xx.h" // verifywrite
|
||||
#include "protocols.h" // for T55xx config register definitions
|
||||
#include "lfdemod.h" // preamble test
|
||||
#include "cmdlft55xx.h" // verifywrite
|
||||
#include "cmdlfem4x05.h" //
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
typedef enum {Scramble = 0, Descramble = 1} KeriMSScramble_t;
|
||||
|
@ -125,17 +123,6 @@ int demodKeri(bool verbose) {
|
|||
setDemodBuff(DemodBuffer, size, idx);
|
||||
setClockGrid(g_DemodClock, g_DemodStartIdx + (idx * g_DemodClock));
|
||||
|
||||
//got a good demod
|
||||
uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32);
|
||||
uint32_t raw2 = bytebits_to_byte(DemodBuffer + 32, 32);
|
||||
|
||||
//get internal id
|
||||
// uint32_t ID = bytebits_to_byte(DemodBuffer + 29, 32);
|
||||
// Due to the 3 sync bits being at the start of the capture
|
||||
// We can take the last 32bits as the internal ID.
|
||||
uint32_t ID = raw2;
|
||||
ID &= 0x7FFFFFFF;
|
||||
|
||||
/*
|
||||
000000000000000000000000000001XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX111
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^1###############################^^^
|
||||
|
@ -150,25 +137,40 @@ int demodKeri(bool verbose) {
|
|||
Might be a hash of FC & CN to generate Internal ID
|
||||
*/
|
||||
|
||||
PrintAndLogEx(SUCCESS, "KERI - Internal ID: " _GREEN_("%u") ", Raw: %08X%08X", ID, raw1, raw2);
|
||||
|
||||
/*
|
||||
Descramble Data.
|
||||
*/
|
||||
uint32_t fc = 0;
|
||||
uint32_t cardid = 0;
|
||||
|
||||
// Just need to the low 32 bits without the 111 trailer
|
||||
CmdKeriMSScramble(Descramble, &fc, &cardid, &raw2);
|
||||
|
||||
PrintAndLogEx(SUCCESS, "Descrambled MS - FC: " _GREEN_("%d") " Card: " _GREEN_("%d"), fc, cardid);
|
||||
//got a good demod
|
||||
uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32);
|
||||
uint32_t raw2 = bytebits_to_byte(DemodBuffer + 32, 32);
|
||||
|
||||
if (invert) {
|
||||
PrintAndLogEx(INFO, "Had to Invert - probably KERI");
|
||||
for (size_t i = 0; i < size; i++)
|
||||
DemodBuffer[i] ^= 1;
|
||||
|
||||
raw1 = bytebits_to_byte(DemodBuffer, 32);
|
||||
raw2 = bytebits_to_byte(DemodBuffer + 32, 32);
|
||||
|
||||
CmdPrintDemodBuff("x");
|
||||
}
|
||||
|
||||
//get internal id
|
||||
// uint32_t ID = bytebits_to_byte(DemodBuffer + 29, 32);
|
||||
// Due to the 3 sync bits being at the start of the capture
|
||||
// We can take the last 32bits as the internal ID.
|
||||
uint32_t ID = raw2;
|
||||
ID &= 0x7FFFFFFF;
|
||||
|
||||
PrintAndLogEx(SUCCESS, "KERI - Internal ID: " _GREEN_("%u") ", Raw: %08X%08X", ID, raw1, raw2);
|
||||
|
||||
// Just need to the low 32 bits without the 111 trailer
|
||||
CmdKeriMSScramble(Descramble, &fc, &cardid, &raw2);
|
||||
|
||||
PrintAndLogEx(SUCCESS, "Descrambled MS - FC: " _GREEN_("%d") " Card: " _GREEN_("%d"), fc, cardid);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -185,7 +187,7 @@ static int CmdKeriRead(const char *Cmd) {
|
|||
|
||||
static int CmdKeriClone(const char *Cmd) {
|
||||
|
||||
bool q5 = false;
|
||||
bool q5 = false, em = false;
|
||||
|
||||
uint8_t keritype[2] = {'i'}; // default to internalid
|
||||
int typeLen = 0;
|
||||
|
@ -207,7 +209,7 @@ static int CmdKeriClone(const char *Cmd) {
|
|||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "lf keri clone",
|
||||
"clone a KERI tag to a T55x7 or Q5/T5555 tag",
|
||||
"clone a KERI tag to a T55x7, Q5/T5555 or EM4305/4469 tag",
|
||||
"lf keri clone -t i --id 12345\n"
|
||||
"lf keri clone -t m --fc 6 --id 12345\n");
|
||||
|
||||
|
@ -217,20 +219,34 @@ static int CmdKeriClone(const char *Cmd) {
|
|||
arg_str0("t", "type", "<m|i>", "Type m - MS, i - Internal ID"),
|
||||
arg_int0(NULL, "fc", "<dec>", "Facility Code"),
|
||||
arg_int1(NULL, "id", "<dec>", "Keri ID"),
|
||||
arg_lit0(NULL, "em", "specify writing to EM4305/4469 tag"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
char cardtype[16] = {"T55x7"};
|
||||
if (arg_get_lit(ctx, 1)) {
|
||||
blocks[0] = T5555_FIXED | T5555_MODULATION_PSK1 | T5555_SET_BITRATE(32) | T5555_PSK_RF_2 | 2 << T5555_MAXBLOCK_SHIFT;
|
||||
snprintf(cardtype, sizeof(cardtype) ,"Q5/T5555");
|
||||
q5 = true;
|
||||
}
|
||||
if (arg_get_lit(ctx, 5)) {
|
||||
blocks[0] = EM4305_KERI_CONFIG_BLOCK;
|
||||
snprintf(cardtype, sizeof(cardtype) ,"EM4305/4469");
|
||||
em = true;
|
||||
}
|
||||
|
||||
typeLen = sizeof(keritype);
|
||||
CLIGetStrWithReturn(ctx, 2, keritype, &typeLen);
|
||||
|
||||
fc = arg_get_int_def(ctx, 3, 0);
|
||||
cid = arg_get_int_def(ctx, 4, 0);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (q5 && em) {
|
||||
PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
// Setup card data/build internal id
|
||||
switch (keritype[0]) {
|
||||
|
@ -249,14 +265,20 @@ static int CmdKeriClone(const char *Cmd) {
|
|||
// Prepare and write to card
|
||||
// 3 LSB is ONE
|
||||
uint64_t data = ((uint64_t)internalid << 3) + 7;
|
||||
PrintAndLogEx(INFO, "Preparing to clone KERI to " _YELLOW_("%s") " with Internal Id " _YELLOW_("%" PRIx32), (q5) ? "Q5/T5555" : "T55x7", internalid);
|
||||
PrintAndLogEx(INFO, "Preparing to clone KERI to " _YELLOW_("%s") " with Internal Id " _YELLOW_("%" PRIx32), cardtype, internalid);
|
||||
|
||||
blocks[1] = data >> 32;
|
||||
blocks[2] = data & 0xFFFFFFFF;
|
||||
|
||||
print_blocks(blocks, ARRAYLEN(blocks));
|
||||
|
||||
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
|
||||
int res;
|
||||
if (em) {
|
||||
res = em4x05_clone_tag(blocks, ARRAYLEN(blocks), 0, false);
|
||||
} else {
|
||||
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, "Done");
|
||||
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf keri read`") " to verify");
|
||||
return res;
|
||||
|
|
|
@ -156,26 +156,36 @@ static int CmdMotorolaClone(const char *Cmd) {
|
|||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "lf motorola clone",
|
||||
"Enables cloning of Motorola card with specified uid onto T55x7\n"
|
||||
"defaults to 64.",
|
||||
"lf motorola clone a0000000a0002021"
|
||||
"clone Motorola UID to T55x7 or Q5/T5555 tag\n"
|
||||
"defaults to 64 bit format",
|
||||
"lf motorola clone -r a0000000a0002021"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx1(NULL, NULL, "<uid (hex)>", NULL),
|
||||
arg_strx1("r", "raw", "<hex>", "raw bytes"),
|
||||
arg_lit0("q", "Q5", "optional - specify writing to Q5/T5555 tag"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
CLIGetHexWithReturn(ctx, 1, data, &datalen);
|
||||
bool is_t5555 = arg_get_lit(ctx, 2);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
//TODO add selection of chip for Q5 or T55x7
|
||||
// data[0] = T5555_FIXED | T5555_SET_BITRATE(32 | T5555_MODULATION_PSK1 | 2 << T5555_MAXBLOCK_SHIFT;
|
||||
|
||||
PrintAndLogEx(INFO, "Target chip " _YELLOW_("%s"), (is_t5555) ? "Q5/T5555" : "T55x7");
|
||||
|
||||
// config for Motorola 64 format (RF/32;PSK1 with RF/2; Maxblock=2)
|
||||
PrintAndLogEx(INFO, "Preparing to clone Motorola 64bit tag with RawID %s", sprint_hex(data, datalen));
|
||||
blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (2 << T55x7_MAXBLOCK_SHIFT);
|
||||
PrintAndLogEx(INFO, "Preparing to clone Motorola 64bit tag");
|
||||
PrintAndLogEx(INFO, "Using raw " _GREEN_("%s"), sprint_hex_inrow(data, datalen));
|
||||
|
||||
if (is_t5555)
|
||||
blocks[0] = T5555_FIXED | T5555_SET_BITRATE(32) | T5555_MODULATION_PSK1 | 2 << T5555_MAXBLOCK_SHIFT;
|
||||
else
|
||||
blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (2 << T55x7_MAXBLOCK_SHIFT);
|
||||
|
||||
|
||||
blocks[1] = bytes_to_num(data, 4);
|
||||
blocks[2] = bytes_to_num(data + 4, 4);
|
||||
|
||||
|
|
|
@ -186,7 +186,7 @@ static int usage_t55xx_dump(void) {
|
|||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " p <password> - OPTIONAL password 4bytes (8 hex symbols)");
|
||||
PrintAndLogEx(NORMAL, " o - OPTIONAL override, force pwd read despite danger to card");
|
||||
PrintAndLogEx(NORMAL, " f <prefix> - overide filename prefix (optional). Default is based on blk 0");
|
||||
PrintAndLogEx(NORMAL, " f <prefix> - override filename prefix (optional). Default is based on blk 0");
|
||||
print_usage_t55xx_downloadlink(T55XX_DLMODE_SINGLE, config.downlink_mode);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
|
|
|
@ -10,23 +10,23 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "cmdlfvisa2000.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "commonutil.h" // ARRAYLEN
|
||||
#include <stdio.h>
|
||||
#include "commonutil.h" // ARRAYLEN
|
||||
#include "common.h"
|
||||
#include "cmdparser.h" // command_t
|
||||
#include "cmdparser.h" // command_t
|
||||
#include "comms.h"
|
||||
#include "ui.h"
|
||||
#include "graph.h"
|
||||
#include "cmddata.h"
|
||||
#include "cmdlf.h"
|
||||
#include "protocols.h" // for T55xx config register definitions
|
||||
#include "lfdemod.h" // parityTest
|
||||
#include "protocols.h" // for T55xx config register definitions
|
||||
#include "lfdemod.h" // parityTest
|
||||
#include "cmdlft55xx.h" // write verify
|
||||
#include "cmdlfem4x05.h" //
|
||||
|
||||
#define BL0CK1 0x56495332
|
||||
|
||||
|
@ -39,10 +39,12 @@ static int usage_lf_visa2k_clone(void) {
|
|||
PrintAndLogEx(NORMAL, " h : This help");
|
||||
PrintAndLogEx(NORMAL, " <card ID> : Visa2k card ID");
|
||||
PrintAndLogEx(NORMAL, " <Q5> : specify writing to Q5/T5555 tag");
|
||||
PrintAndLogEx(NORMAL, " <em4305> : specify writing to EM4305/4469 tag");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf visa2000 clone 112233"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf visa2000 clone 112233 q5") " -- encode for Q5/T5555");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf visa2000 clone 112233 em4305") " -- encode for EM4305/4469");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -180,18 +182,38 @@ static int CmdVisa2kClone(const char *Cmd) {
|
|||
|
||||
id = param_get32ex(Cmd, 0, 0, 10);
|
||||
|
||||
//Q5
|
||||
char cardtype[16] = {"T55x7"};
|
||||
// Q5
|
||||
bool q5 = tolower(param_getchar(Cmd, 1)) == 'q';
|
||||
if (q5)
|
||||
if (q5) {
|
||||
blocks[0] = T5555_FIXED | T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(64) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT;
|
||||
snprintf(cardtype, sizeof(cardtype) ,"Q5/T5555");
|
||||
}
|
||||
|
||||
// EM4305
|
||||
bool em = tolower(param_getchar(Cmd, 1)) == 'e';
|
||||
if (em) {
|
||||
blocks[0] = EM4305_VISA2000_CONFIG_BLOCK;
|
||||
snprintf(cardtype, sizeof(cardtype) ,"EM4305/4469");
|
||||
}
|
||||
|
||||
if (q5 && em) {
|
||||
PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
blocks[2] = id;
|
||||
blocks[3] = (visa_parity(id) << 4) | visa_chksum(id);
|
||||
|
||||
PrintAndLogEx(INFO, "Preparing to clone Visa2000 to " _YELLOW_("%s") " with CardId: %"PRIu64, (q5) ? "Q5/T5555" : "T55x7", id);
|
||||
PrintAndLogEx(INFO, "Preparing to clone Visa2000 to " _YELLOW_("%s") " with CardId: %"PRIu64, cardtype, id);
|
||||
print_blocks(blocks, ARRAYLEN(blocks));
|
||||
|
||||
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
|
||||
int res;
|
||||
if (em) {
|
||||
res = em4x05_clone_tag(blocks, ARRAYLEN(blocks), 0, false);
|
||||
} else {
|
||||
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, "Done");
|
||||
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf visa2000 read`") " to verify");
|
||||
return res;
|
||||
|
|
|
@ -698,13 +698,12 @@ static int CmdSmartInfo(const char *Cmd) {
|
|||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SMART_ATR, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
|
||||
if (!WaitForResponseTimeout(CMD_SMART_ATR, &resp, 2500)) {
|
||||
if (!silent) PrintAndLogEx(WARNING, "smart card select failed");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
uint8_t isok = resp.oldarg[0] & 0xFF;
|
||||
if (!isok) {
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
if (!silent) PrintAndLogEx(WARNING, "smart card select failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
@ -771,13 +770,12 @@ static int CmdSmartReader(const char *Cmd) {
|
|||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SMART_ATR, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
|
||||
if (!WaitForResponseTimeout(CMD_SMART_ATR, &resp, 2500)) {
|
||||
if (!silent) PrintAndLogEx(WARNING, "smart card select failed");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
uint8_t isok = resp.oldarg[0] & 0xFF;
|
||||
if (!isok) {
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
if (!silent) PrintAndLogEx(WARNING, "smart card select failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
@ -791,14 +789,14 @@ static int CmdSmartReader(const char *Cmd) {
|
|||
static int CmdSmartSetClock(const char *Cmd) {
|
||||
uint8_t cmdp = 0;
|
||||
bool errors = false;
|
||||
uint8_t clock1 = 0;
|
||||
uint8_t new_clk = 0;
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
return usage_sm_setclock();
|
||||
case 'c':
|
||||
clock1 = param_get8ex(Cmd, cmdp + 1, 2, 10);
|
||||
if (clock1 > 2)
|
||||
new_clk = param_get8ex(Cmd, cmdp + 1, 2, 10);
|
||||
if (new_clk > 2)
|
||||
errors = true;
|
||||
|
||||
cmdp += 2;
|
||||
|
@ -813,21 +811,26 @@ static int CmdSmartSetClock(const char *Cmd) {
|
|||
//Validations
|
||||
if (errors || cmdp == 0) return usage_sm_setclock();
|
||||
|
||||
struct {
|
||||
uint32_t new_clk;
|
||||
} PACKED payload;
|
||||
|
||||
payload.new_clk = new_clk;
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_SMART_SETCLOCK, clock1, 0, 0, NULL, 0);
|
||||
SendCommandNG(CMD_SMART_SETCLOCK, (uint8_t*)&payload, sizeof(payload));
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
|
||||
if (!WaitForResponseTimeout(CMD_SMART_SETCLOCK, &resp, 2500)) {
|
||||
PrintAndLogEx(WARNING, "smart card select failed");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
uint8_t isok = resp.oldarg[0] & 0xFF;
|
||||
if (!isok) {
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
PrintAndLogEx(WARNING, "smart card set clock failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
switch (clock1) {
|
||||
switch (new_clk) {
|
||||
case 0:
|
||||
PrintAndLogEx(SUCCESS, "Clock changed to 16MHz giving 10800 baudrate");
|
||||
break;
|
||||
|
@ -1181,14 +1184,13 @@ bool smart_select(bool silent, smart_card_atr_t *atr) {
|
|||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SMART_ATR, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
|
||||
if (!WaitForResponseTimeout(CMD_SMART_ATR, &resp, 2500)) {
|
||||
|
||||
if (!silent) PrintAndLogEx(WARNING, "smart card select failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t isok = resp.oldarg[0] & 0xFF;
|
||||
if (!isok) {
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
if (!silent) PrintAndLogEx(WARNING, "smart card select failed");
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1435,7 +1435,7 @@ static int CmdEMVScan(const char *Cmd) {
|
|||
uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2;
|
||||
|
||||
uint8_t filename[FILE_PATH_SIZE] = {0};
|
||||
int filenamelen = 0;
|
||||
int filenamelen = sizeof(filename);
|
||||
CLIGetStrWithReturn(ctx, 12, filename, &filenamelen);
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
|
|
@ -494,6 +494,33 @@ int saveFileJSONex(const char *preferredName, JSONFileType ftype, uint8_t *data,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case jsfEM4x05: {
|
||||
JsonSaveStr(root, "FileType", "EM4205/EM4305");
|
||||
JsonSaveBufAsHexCompact(root, "$.Card.UID", data + (1 * 4), 4);
|
||||
JsonSaveBufAsHexCompact(root, "$.Card.Config", data + (4 * 4), 4);
|
||||
JsonSaveBufAsHexCompact(root, "$.Card.Protection1", data + (14 * 4), 4);
|
||||
JsonSaveBufAsHexCompact(root, "$.Card.Protection2", data + (15 * 4), 4);
|
||||
|
||||
for (size_t i = 0; i < (datalen / 4); i++) {
|
||||
char path[PATH_MAX_LENGTH] = {0};
|
||||
sprintf(path, "$.blocks.%zu", i);
|
||||
JsonSaveBufAsHexCompact(root, path, data + (i * 4), 4);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case jsfEM4x69: {
|
||||
JsonSaveStr(root, "FileType", "EM4469/EM4569");
|
||||
JsonSaveBufAsHexCompact(root, "$.Card.UID", data + (1 * 4), 4);
|
||||
JsonSaveBufAsHexCompact(root, "$.Card.Protection", data + (3 * 4), 4);
|
||||
JsonSaveBufAsHexCompact(root, "$.Card.Config", data + (4 * 4), 4);
|
||||
|
||||
for (size_t i = 0; i < (datalen / 4); i++) {
|
||||
char path[PATH_MAX_LENGTH] = {0};
|
||||
sprintf(path, "$.blocks.%zu", i);
|
||||
JsonSaveBufAsHexCompact(root, path, data + (i * 4), 4);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case jsfMfPlusKeys: {
|
||||
JsonSaveStr(root, "FileType", "mfp");
|
||||
JsonSaveBufAsHexCompact(root, "$.Card.UID", &data[0], 7);
|
||||
|
|
|
@ -64,6 +64,8 @@ typedef enum {
|
|||
jsfMfPlusKeys,
|
||||
jsfCustom,
|
||||
jsfMfDesfireKeys,
|
||||
jsfEM4x05,
|
||||
jsfEM4x69,
|
||||
} JSONFileType;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -59,6 +59,9 @@ extern "C" void InitGraphics(int argc, char **argv, char *script_cmds_file, char
|
|||
#ifdef Q_WS_X11
|
||||
if (getenv("DISPLAY") == NULL)
|
||||
return;
|
||||
#endif
|
||||
#if QT_VERSION >= 0x050100
|
||||
qunsetenv("SESSION_MANAGER");
|
||||
#endif
|
||||
main_loop_thread = new WorkerThread(script_cmds_file, script_cmd, stayInCommandLoop);
|
||||
gui = new ProxGuiQT(argc, argv, main_loop_thread);
|
||||
|
|
|
@ -502,7 +502,7 @@ static void set_my_user_directory(void) {
|
|||
// if not found, default to current directory
|
||||
if (my_user_directory == NULL) {
|
||||
my_user_directory = GetCurrentDir(_cwd_Buffer, sizeof(_cwd_Buffer));
|
||||
// change all slashs to / (windows should not care...
|
||||
// change all slashes to / (windows should not care...
|
||||
for (int i = 0; i < strlen(_cwd_Buffer); i++)
|
||||
if (_cwd_Buffer[i] == '\\') _cwd_Buffer[i] = '/';
|
||||
// my_user_directory = ".";
|
||||
|
@ -1044,7 +1044,7 @@ int main(int argc, char *argv[]) {
|
|||
InitGraphics(argc, argv, script_cmds_file, script_cmd, stayInCommandLoop);
|
||||
MainGraphics();
|
||||
# else
|
||||
// for *nix distro's, check enviroment variable to verify a display
|
||||
// for *nix distro's, check environment variable to verify a display
|
||||
char *display = getenv("DISPLAY");
|
||||
if (display && strlen(display) > 1) {
|
||||
InitGraphics(argc, argv, script_cmds_file, script_cmd, stayInCommandLoop);
|
||||
|
|
|
@ -36,7 +36,9 @@
|
|||
#include "fileutils.h" // searchfile
|
||||
#include "cmdlf.h" // lf_config
|
||||
#include "generator.h"
|
||||
#include "cmdlfem4x.h" // read 4305
|
||||
#include "cmdlfem4x05.h" // read 4305
|
||||
#include "cmdlfem4x50.h" // read 4350
|
||||
#include "em4x50.h" // 4x50 structs
|
||||
|
||||
static int returnToLuaWithError(lua_State *L, const char *fmt, ...) {
|
||||
char buffer[200];
|
||||
|
@ -1088,7 +1090,7 @@ static int l_T55xx_detect(lua_State *L) {
|
|||
return 2;
|
||||
}
|
||||
|
||||
//
|
||||
// 4305
|
||||
static int l_em4x05_read(lua_State *L) {
|
||||
|
||||
bool use_pwd = false;
|
||||
|
@ -1103,12 +1105,12 @@ static int l_em4x05_read(lua_State *L) {
|
|||
sscanf(p_addr, "%u", &addr);
|
||||
|
||||
// get password
|
||||
const char *p_pwd = luaL_checklstring(L, 2, &size);
|
||||
if (size == 0) {
|
||||
const char *p_pwd = luaL_checkstring(L, 2);
|
||||
if (p_pwd == NULL || strlen(p_pwd) == 0) {
|
||||
use_pwd = false;
|
||||
} else {
|
||||
if (size != 8)
|
||||
return returnToLuaWithError(L, "Wrong size of password, got %zu , expected 8", size);
|
||||
if (strlen(p_pwd) != 8)
|
||||
return returnToLuaWithError(L, "Wrong size of password, got %zu , expected 8", strlen(p_pwd));
|
||||
|
||||
sscanf(p_pwd, "%08x", &password);
|
||||
use_pwd = true;
|
||||
|
@ -1119,7 +1121,7 @@ static int l_em4x05_read(lua_State *L) {
|
|||
PrintAndLogEx(DEBUG, " Pwd %08X", password);
|
||||
|
||||
uint32_t word = 0;
|
||||
int res = EM4x05ReadWord_ext(addr, password, use_pwd, &word);
|
||||
int res = em4x05_read_word_ext(addr, password, use_pwd, &word);
|
||||
if (res != PM3_SUCCESS) {
|
||||
return returnToLuaWithError(L, "Failed to read EM4x05 data");
|
||||
}
|
||||
|
@ -1128,6 +1130,66 @@ static int l_em4x05_read(lua_State *L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
// 4350
|
||||
static int l_em4x50_read(lua_State *L) {
|
||||
|
||||
// get addr
|
||||
size_t size = 0;
|
||||
const char *p_addr = luaL_checklstring(L, 1, &size);
|
||||
uint32_t addr = 0;
|
||||
sscanf(p_addr, "%u", &addr);
|
||||
|
||||
if (addr > 31)
|
||||
return returnToLuaWithError(L, "Address out-of-range (0..31) got %u", addr);
|
||||
|
||||
// setting up structures
|
||||
em4x50_data_t etd;
|
||||
memset(&etd, 0x00, sizeof(em4x50_data_t));
|
||||
etd.addr_given = true;
|
||||
etd.address = addr & 0xFF;
|
||||
etd.newpwd_given = false;
|
||||
|
||||
// get password
|
||||
const char *p_pwd = luaL_checkstring(L, 2);
|
||||
if (p_pwd == NULL || strlen(p_pwd) == 0) {
|
||||
etd.pwd_given = false;
|
||||
} else {
|
||||
if (strlen(p_pwd) != 8)
|
||||
return returnToLuaWithError(L, "Wrong size of password, got %zu , expected 8", strlen(p_pwd));
|
||||
|
||||
uint32_t pwd = 0;
|
||||
sscanf(p_pwd, "%08x", &pwd);
|
||||
|
||||
PrintAndLogEx(DEBUG, " Pwd %08X", pwd);
|
||||
|
||||
etd.password[0] = pwd & 0xFF;
|
||||
etd.password[1] = (pwd >> 8) & 0xFF;
|
||||
etd.password[2] = (pwd >> 16) & 0xFF;
|
||||
etd.password[3] = (pwd >> 24) & 0xFF;
|
||||
etd.pwd_given = true;
|
||||
}
|
||||
|
||||
PrintAndLogEx(DEBUG, "Addr %u", etd.address);
|
||||
if (etd.pwd_given)
|
||||
PrintAndLogEx(DEBUG, " Pwd %s", sprint_hex(etd.password, sizeof(etd.password)));
|
||||
|
||||
em4x50_word_t words[EM4X50_NO_WORDS];
|
||||
|
||||
int res = em4x50_read(&etd, words, false);
|
||||
if (res != PM3_SUCCESS) {
|
||||
return returnToLuaWithError(L, "Failed to read EM4x50 data");
|
||||
}
|
||||
|
||||
uint32_t word = (
|
||||
words[etd.address].byte[0] << 24 |
|
||||
words[etd.address].byte[1] << 16 |
|
||||
words[etd.address].byte[2] << 8 |
|
||||
words[etd.address].byte[3]
|
||||
);
|
||||
lua_pushinteger(L, word);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//
|
||||
static int l_ndefparse(lua_State *L) {
|
||||
|
||||
|
@ -1320,6 +1382,7 @@ int set_pm3_libraries(lua_State *L) {
|
|||
{"ud", l_ud},
|
||||
{"rem", l_remark},
|
||||
{"em4x05_read", l_em4x05_read},
|
||||
{"em4x50_read", l_em4x50_read},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
|
@ -895,3 +895,40 @@ int hexstring_to_u96(uint32_t *hi2, uint32_t *hi, uint32_t *lo, const char *str)
|
|||
}
|
||||
return i - 1;
|
||||
}
|
||||
|
||||
inline uint32_t bitcount32(uint32_t a) {
|
||||
#if defined __GNUC__
|
||||
return __builtin_popcountl(a);
|
||||
#else
|
||||
a = a - ((a >> 1) & 0x55555555);
|
||||
a = (a & 0x33333333) + ((a >> 2) & 0x33333333);
|
||||
return (((a + (a >> 4)) & 0x0f0f0f0f) * 0x01010101) >> 24;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint64_t bitcount64(uint64_t a) {
|
||||
#if defined __GNUC__
|
||||
return __builtin_popcountll(a);
|
||||
#else
|
||||
PrintAndLogEx(FAILED, "Was not compiled with fct bitcount64");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint32_t leadingzeros32(uint32_t a) {
|
||||
#if defined __GNUC__
|
||||
return __builtin_clzl(a);
|
||||
#else
|
||||
PrintAndLogEx(FAILED, "Was not compiled with fct bitcount64");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint64_t leadingzeros64(uint64_t a) {
|
||||
#if defined __GNUC__
|
||||
return __builtin_clzll(a);
|
||||
#else
|
||||
PrintAndLogEx(FAILED, "Was not compiled with fct bitcount64");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -101,4 +101,9 @@ void strcreplace(char *buf, size_t len, char from, char to);
|
|||
char *str_dup(const char *src);
|
||||
char *str_ndup(const char *src, size_t len);
|
||||
int hexstring_to_u96(uint32_t *hi2, uint32_t *hi, uint32_t *lo, const char *str);
|
||||
|
||||
uint32_t bitcount32(uint32_t a);
|
||||
uint64_t bitcount64(uint64_t a);
|
||||
uint32_t leadingzeros32(uint32_t a);
|
||||
uint64_t leadingzeros64(uint64_t a);
|
||||
#endif
|
||||
|
|
|
@ -24,7 +24,7 @@ static struct lfsr {
|
|||
// * someone mentioned iv must be ODD.
|
||||
// Hack:
|
||||
// Now we have a special case with iv == 0
|
||||
// it sets b to 0 aswell to make sure we get a all zero keystream out
|
||||
// it sets b to 0 as well to make sure we get a all zero keystream out
|
||||
// which is used in the initialisation phase sending the IV
|
||||
//
|
||||
void legic_prng_init(uint8_t iv) {
|
||||
|
|
|
@ -269,7 +269,7 @@ See instructions above (method 1) for initial pairing.
|
|||
#### 5.3.1 Connecting rdv4.0 with Bluetooth on MacOS
|
||||
^[Top](#top)
|
||||
|
||||
With MacOS Mojave 10.14.5 you could experience some continuosly disconnecting and difficult to recconnect the device at the system wakeup, to avoid this problem do a PRAM reset before to add your Proxmark3 RDV4 Blue Shark:
|
||||
With MacOS Mojave 10.14.5 you could experience some continuously disconnecting and difficult to reconnect the device at the system wakeup, to avoid this problem do a PRAM reset before to add your Proxmark3 RDV4 Blue Shark:
|
||||
|
||||
1. Open a Terminal and execute this command: sudo rm -R /Library/Preferences/com.apple.Bluetooth.plist.
|
||||
2. Shut down your Mac.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<a id="Top"></a>
|
||||
# Command Cheat Sheet
|
||||
|
||||
|Generic|Low Frequence 125 kHz|High Frequence 13.56 MHz|
|
||||
|Generic|Low Frequency 125 kHz|High Frequency 13.56 MHz|
|
||||
|---|---|---|
|
||||
|[Generic](#Generic)|[T55XX](#T55XX)|[MIFARE](#MIFARE)|
|
||||
|[Data](#Data)|[HID Prox](#HID-Prox)|[iCLASS](#iCLASS)|
|
||||
|
@ -324,7 +324,7 @@ pm3 --> script run hf_mf_uidbruteforce -s 0x11223344556677 -e 0x11223344556679 -
|
|||
## Wiegand manipulation
|
||||
^[Top](#top)
|
||||
|
||||
List all available weigand formats in client
|
||||
List all available wiegand formats in client
|
||||
```
|
||||
pm3 --> wiegand list
|
||||
```
|
||||
|
@ -592,7 +592,7 @@ Options
|
|||
-k <key> The current six byte key with write access
|
||||
-n <key> The new key that will be written to the card
|
||||
-a <access> The new access bytes that will be written to the card
|
||||
-x Execute the commands aswell
|
||||
-x Execute the commands as well
|
||||
|
||||
pm3 --> script run hf_mf_format -k FFFFFFFFFFFF -n FFFFFFFFFFFF -x
|
||||
```
|
||||
|
|
|
@ -25,7 +25,7 @@ And then it fell into silence since it wasn't well documented how to use the cli
|
|||
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 specified which lead to a simpler implementation of the cliparser in the client source code while still unifiy all helptexts with the new colours support and a defined layout. As seen below, the simplicity and clearness.
|
||||
The aftermath was a design and layout specified which lead to a simpler implementation of the cliparser in the client source code while still unifying all helptexts with the new colours support and a defined layout. As seen below, the simplicity and clearness.
|
||||
|
||||

|
||||
|
||||
|
@ -203,11 +203,11 @@ CLIGetHexWithReturn(\<context\>, \<opt index\>, \<store variable\>, \<ptr to sto
|
|||
quick test : seems res_keylen == 0 when ok so not key len ???
|
||||
|
||||
**string option return**
|
||||
CLIGetStrWithReturn(\<context\>,\<opt index\>, \<unsigned char \*\>, \<int \*\>);
|
||||
CLIGetStrWithReturn(\<context\>,\<opt index\>, \<uint8_t \*\>, \<int \*\>);
|
||||
If failed to retrieve string, it will exit fct
|
||||
|
||||
uint8_t buffer[100];
|
||||
int slen = 0;
|
||||
int slen = sizeof(buffer); // <- slen MUST be the maximum number of characters that you want returned. e.g. Buffer Size
|
||||
CLIGetStrWithReturn(ctx, 1, buffer, &slen);
|
||||
|
||||
**string option**
|
||||
|
|
|
@ -92,7 +92,7 @@ About 1 us precision
|
|||
* `void StartCountUS(void)`
|
||||
* `uint32_t RAMFUNC GetCountUS(void)`
|
||||
|
||||
Use two chainer timers TC0 and TC1.
|
||||
Use two chained timers TC0 and TC1.
|
||||
TC0 runs at 1.5 MHz and TC1 is clocked when TC0 reaches 0xC000.
|
||||
|
||||
Maximal value: 0x7fffffff = 2147 s
|
||||
|
@ -110,13 +110,13 @@ About 1 cycle of 13.56 MHz? precision
|
|||
* `uint32_t RAMFUNC GetCountSspClk(void)`
|
||||
* `uint32_t RAMFUNC GetCountSspClkDelta(uint32_t start)` <= **TODO** could be used more often
|
||||
|
||||
Use two chainer timers TC0 and TC1.
|
||||
Use two chained timers TC0 and TC1.
|
||||
TC0 runs at SSP_CLK from FPGA (13.56 MHz?) and TC1 is clocked when TC0 loops.
|
||||
|
||||
Usage:
|
||||
|
||||
* for iso14443 commands to count field cycles
|
||||
* Also usable with FPGA in LF mode ?? cf `armsrc/legicrfsim.c` SSP Clock is clocked by the FPGA at 212 kHz (subcarrier frequency)
|
||||
* Also usable with FPGA in LF mode ?? cf `armsrc/legicrfsim.c` SSP Clock is clocked by the FPGA at 212 kHz (sub-carrier frequency)
|
||||
|
||||
Can't be used at the same time as CountUS or Ticks functions.
|
||||
|
||||
|
@ -133,7 +133,7 @@ cf `armsrc/ticks.c`
|
|||
* `void WaitMS(uint32_t ms)`
|
||||
* `void StopTicks(void)` <= **TODO** why a stop for this timer and not for CountUS / CountSspClk ?
|
||||
|
||||
Use two chainer timers TC0 and TC1.
|
||||
Use two chained timers TC0 and TC1.
|
||||
TC0 runs at 1.5 MHz and TC1 is clocked when TC0 loops.
|
||||
|
||||
Maximal value: 0xffffffff = 2863 s (but don't use high value with WaitTicks else you'll trigger WDT)
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
# Notes on Cloner gunes
|
||||
# Notes on Cloner guns
|
||||
|
||||
This document is based mostly on information posted on http://www.proxmark.org/forum/viewtopic.php?pid=39903#p39903
|
||||
|
||||
- [Notes on Cloner guns](#notes-on-cloner-guns)
|
||||
- [Blue and black cloners](#blue-and-black-cloners)
|
||||
- [White cloner (pre 2015)](#white-cloner-pre-2015)
|
||||
- [White cloner (after 2016)](#white-cloner-after-2016)
|
||||
- [White cloner (after 2016 D Quality)](#white-cloner-after-2016-d-quality)
|
||||
- [restore page1 data](#restore-page1-data)
|
||||
- [Restore page1 data](#restore-page1-data)
|
||||
- [Sniffing the comms](#sniffing-the-comms)
|
||||
|
||||
|
||||
|
@ -67,7 +68,7 @@ If t55xx write b 2 d 2D782308 1
|
|||
The T55x7 protocol uses a pwm based protocol for writing to tags. In order to make decoding easier try the new command as seen below instead. It will try to extract the data written.
|
||||
|
||||
```
|
||||
-- after threshold limit 20 is triggred, skip 10000 samples before collecting samples.
|
||||
-- after threshold limit 20 is triggered, skip 10000 samples before collecting samples.
|
||||
lf config s 10000 t 20
|
||||
lf t55xx sniff
|
||||
|
||||
|
|
|
@ -10,13 +10,13 @@ The client should autodetect color support when starting.
|
|||
|
||||
You can also use the command `pref show` to see and set your personal setting.
|
||||
|
||||
Why use colors in the Proxmark client? When evertyhing is white it is hard to extract the important information fast. You also need new-lines for extra space to be easier to read.
|
||||
Why use colors in the Proxmark client? When everything is white it is hard to extract the important information fast. You also need new-lines for extra space to be easier to read.
|
||||
We have gradually been introducing this color scheme into the client since we got decent color support on all systems: OSX, Linux, WSL, Proxspace.
|
||||
|
||||
|
||||
## style/color
|
||||
^[Top](#top)
|
||||
The following definition has be crystalized out from these experiments. Its not set in stone yet so take this document as a guideline for how to create unified system scheme.
|
||||
The following definition has be crystallized out from these experiments. Its not set in stone yet so take this document as a guideline for how to create unified system scheme.
|
||||
|
||||
### Definition
|
||||
^[Top](#top)
|
||||
|
|
|
@ -177,13 +177,13 @@ Check column "offline" for their availability.
|
|||
|`hf 15 info `|N |`Tag information`
|
||||
|`hf 15 sniff `|N |`Sniff ISO15693 traffic`
|
||||
|`hf 15 raw `|N |`Send raw hex data to tag`
|
||||
|`hf 15 read `|N |`Read a block`
|
||||
|`hf 15 rdbl `|N |`Read a block`
|
||||
|`hf 15 reader `|N |`Act like an ISO15693 reader`
|
||||
|`hf 15 readmulti `|N |`Reads multiple Blocks`
|
||||
|`hf 15 restore `|N |`Restore from file to all memory pages of an ISO15693 tag`
|
||||
|`hf 15 samples `|N |`Acquire Samples as Reader (enables carrier, sends inquiry)`
|
||||
|`hf 15 sim `|N |`Fake an ISO15693 tag`
|
||||
|`hf 15 write `|N |`Write a block`
|
||||
|`hf 15 wrbl `|N |`Write a block`
|
||||
|`hf 15 findafi `|N |`Brute force AFI of an ISO15693 tag`
|
||||
|`hf 15 writeafi `|N |`Writes the AFI on an ISO15693 tag`
|
||||
|`hf 15 writedsfid `|N |`Writes the DSFID on an ISO15693 tag`
|
||||
|
@ -233,7 +233,7 @@ Check column "offline" for their availability.
|
|||
|command |offline |description
|
||||
|------- |------- |-----------
|
||||
|`hf fido help `|Y |`This help.`
|
||||
|`hf fido info `|N |`List ISO 14443A history`
|
||||
|`hf fido list `|N |`List ISO 14443A history`
|
||||
|`hf fido info `|N |`Info about FIDO tag.`
|
||||
|`hf fido reg `|N |`FIDO U2F Registration Message.`
|
||||
|`hf fido auth `|N |`FIDO U2F Authentication Message.`
|
||||
|
@ -256,10 +256,10 @@ Check column "offline" for their availability.
|
|||
|`hf iclass restore `|N |`[options..] Restore a dump file onto a Picopass / iCLASS tag`
|
||||
|`hf iclass sniff `|N |` Eavesdrop Picopass / iCLASS communication`
|
||||
|`hf iclass wrbl `|N |`[options..] Write Picopass / iCLASS block`
|
||||
|`hf iclass chk `|Y |`[options..] Check keys`
|
||||
|`hf iclass autopwn `|N |`[options..] Automatic key recovery tool for iCLASS`
|
||||
|`hf iclass chk `|N |`[options..] Check keys`
|
||||
|`hf iclass loclass `|Y |`[options..] Use loclass to perform bruteforce reader attack`
|
||||
|`hf iclass lookup `|Y |`[options..] Uses authentication trace to check for key in dictionary file`
|
||||
|`hf iclass replay `|N |`<mac> Read Picopass / iCLASS tag via replay attack`
|
||||
|`hf iclass sim `|N |`[options..] Simulate iCLASS tag`
|
||||
|`hf iclass eload `|N |`[f <fn> ] Load Picopass / iCLASS dump file into emulator memory`
|
||||
|`hf iclass esave `|N |`[f <fn> ] Save emulator memory to file`
|
||||
|
@ -556,6 +556,19 @@ Check column "offline" for their availability.
|
|||
|`lf cotag read `|N |`Attempt to read and extract tag data`
|
||||
|
||||
|
||||
### lf destron
|
||||
|
||||
{ FDX-A Destron RFIDs... }
|
||||
|
||||
|command |offline |description
|
||||
|------- |------- |-----------
|
||||
|`lf destron help `|Y |`This help`
|
||||
|`lf destron demod `|Y |`Demodulate an Destron tag from the GraphBuffer`
|
||||
|`lf destron read `|N |`Attempt to read and extract tag data from the antenna`
|
||||
|`lf destron clone `|N |`Clone Destron tag to T55x7`
|
||||
|`lf destron sim `|N |`Simulate Destron tag`
|
||||
|
||||
|
||||
### lf em
|
||||
|
||||
{ EM4X CHIPs & RFIDs... }
|
||||
|
@ -570,12 +583,14 @@ Check column "offline" for their availability.
|
|||
|`lf em 410x_watch `|N |`watches for EM410x 125/134 kHz tags (option 'h' for 134)`
|
||||
|`lf em 410x_spoof `|N |`watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)`
|
||||
|`lf em 410x_clone `|N |`write EM410x UID to T55x7 or Q5/T5555 tag`
|
||||
|`lf em 4x05_chk `|N |`Check passwords from dictionary`
|
||||
|`lf em 4x05_demod `|Y |`demodulate a EM4x05/EM4x69 tag from the GraphBuffer`
|
||||
|`lf em 4x05_dump `|N |`dump EM4x05/EM4x69 tag`
|
||||
|`lf em 4x05_wipe `|N |`wipe EM4x05/EM4x69 tag`
|
||||
|`lf em 4x05_info `|N |`tag information EM4x05/EM4x69`
|
||||
|`lf em 4x05_read `|N |`read word data from EM4x05/EM4x69`
|
||||
|`lf em 4x05_write `|N |`write word data to EM4x05/EM4x69`
|
||||
|`lf em 4x05_unlock `|N |`execute tear off against EM4x05/EM4x69`
|
||||
|`lf em 4x50_dump `|N |`dump EM4x50 tag`
|
||||
|`lf em 4x50_info `|N |`tag information EM4x50`
|
||||
|`lf em 4x50_write `|N |`write word data to EM4x50`
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
- Get ATR|ATS
|
||||
- Get AID by PSE (`emv pse`)
|
||||
- Get AID by appliation list (`emv search`)
|
||||
- Get AID by application list (`emv search`)
|
||||
- Select application (`emv select`)
|
||||
- Format PDOL (look at next part)
|
||||
- Execute GPO (`emv gpo` this step and format PDOL)
|
||||
|
@ -27,7 +27,7 @@
|
|||
|
||||
- Get ATR|ATS
|
||||
- Get AID by PSE (`emv pse`)
|
||||
- Get AID by appliation list (`emv search`)
|
||||
- Get AID by application list (`emv search`)
|
||||
- Select application (`emv select`)
|
||||
- Format PDOL (look at next part)
|
||||
- Execute GPO (`emv gpo` this step and format PDOL)
|
||||
|
@ -62,7 +62,7 @@ It works for VISA(r) and Mastercard(r) transactions. It may work with other EMV
|
|||
^[Top](#top)
|
||||
|
||||
MSD - Magnetic Stripe mode
|
||||
VSDC - contact transacion
|
||||
VSDC - contact transaction
|
||||
qVSDC - contactless transaction
|
||||
|
||||
### Mastercard(r) transactions
|
||||
|
|
|
@ -34,7 +34,7 @@ LF analog path (MCP6294 opamp. This has a GBW of 10 MHz), all 'slow' signals.
|
|||
|
||||
|
||||
## FPGA
|
||||
Since the SPARTAN II is a old outdated FPGA, thus is very limited resource there was a need to split LF and HF functionality into two seperate FPGA images. Which are stored in ARM flash memory as bitstreams.
|
||||
Since the SPARTAN II is a old outdated FPGA, thus is very limited resource there was a need to split LF and HF functionality into two separate FPGA images. Which are stored in ARM flash memory as bitstreams.
|
||||
|
||||
We swap between these images by flashing fpga from ARM on the go. It takes about 1sec. Hence its usually a bad idea to program your device to continuously execute LF alt HF commands.
|
||||
|
||||
|
@ -43,7 +43,7 @@ The FPGA images is precompiled and located inside the /fpga folder.
|
|||
- fpga_lf.bit
|
||||
|
||||
There is very rarely changes to the images so there is no need to setup a fpga tool chain to compile it yourself.
|
||||
Since the FPGA is very old, the Xilinix WebPack ISE 10.1 is the last working tool chain. You can download this legacy development on xilinix and register for a free product installation id.
|
||||
Since the FPGA is very old, the Xilinx WebPack ISE 10.1 is the last working tool chain. You can download this legacy development on Xilinx and register for a free product installation id.
|
||||
Or use mine `11LTAJ5ZJK3PXTUBMF0C0J6C4` The package to download is about 7Gb and linux based. Though I recently managed to install it on WSL for Windows 10.
|
||||
|
||||
In order to save space, these fpga images are LZ4 compressed and included in the fullimage.elf file when compiling the ARM SRC. `make armsrc`
|
||||
|
@ -131,7 +131,7 @@ it into the memory of the FPGA. This gives some major advantages:
|
|||
|
||||
The FPGA has two main tasks. The first task is to demodulate the signal received from the ADC and relay
|
||||
this as a digital encoded signal to the ARM. Depending on the task this might be the demodulation of a
|
||||
100% Amplitude Shift Keying (ASK) signal from the reader or the load modulation of a card. The encodin
|
||||
100% Amplitude Shift Keying (ASK) signal from the reader or the load modulation of a card. The encoding
|
||||
schemes used to communicate the signal to the ARM are Modified Miller for the reader and Manchester
|
||||
encoding for the card signal.
|
||||
|
||||
|
@ -153,10 +153,10 @@ these samples. When the Proxmark is in sniffing mode this is done for both the M
|
|||
Miller at the same time. Whenever one of the decoding procedures returns a valid message, this message
|
||||
is stored in another buffer (BigBuf) and both decoding procedures are set to an un-synced state. The
|
||||
BigBuf is limited to the available memory on the ARM. The current firmware has 2 KB of memory
|
||||
reserved for traces (Besides the tracethe buffer also stores some temporary data that is needed in the
|
||||
reserved for traces (Besides the trace, the buffer also stores some temporary data that is needed in the
|
||||
processing). When the BigBuf buffer is full the function normally returns. A new function call from the
|
||||
client is needed to download the BigBuf contents to the computer. The BigBuf is especially useful for
|
||||
ptocol investigation. Every single message is stored in this buffer. When a card is emulated or when the
|
||||
protocol investigation. Every single message is stored in this buffer. When a card is emulated or when the
|
||||
Proxmark is used as a reader the BigBuf can be used to store status messages or protocol exceptions.
|
||||
|
||||
```
|
||||
|
@ -226,7 +226,7 @@ is the master). The ARM connects to the outside world over USB.
|
|||
|
||||
|
||||
## FPGA purpose
|
||||
Digtal signal processing.
|
||||
Digital signal processing.
|
||||
In short, apply low pass / hi pass filtering, peak detect, correlate signal meaning IQ pair collecting.
|
||||
|
||||
IQ means measure at In-phase and 90 phase shift later Quadrature-phase, with IQ samples you can plot the signal on a vector plan.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
This document is primarily intended for understanding `hf iclass loclass` and files used with it.
|
||||
|
||||
LOCLASS aim is to recoved the used masterkey for that specific reader configued in Elite mode / High Security mode.
|
||||
LOCLASS aim is to recover the used masterkey for that specific reader configured in Elite mode / High Security mode.
|
||||
|
||||
LOCLASS, is a two part attack. First is the online part where you gather needed information from the reader by presenting a carefully selected CSN and save the responses to file. For the first part you run `hf iclass sim 2` and take notice of the saved filename.
|
||||
|
||||
|
@ -23,4 +23,4 @@ This test mode uses two files.
|
|||
- `iclass_dump.bin`
|
||||
this is a sample file from `hf iclass sim 2`, with complete keytable recovery, using 128 carefully selected CSN and the file contains the MAC results from reader.
|
||||
- `iclass_key.bin`
|
||||
this is file shall contain the legacy masterkey, AA1 key. loclass uses it to verify that permution / reversing / generation of key is correct.
|
||||
this is file shall contain the legacy masterkey, AA1 key. loclass uses it to verify that permutation / reversing / generation of key is correct.
|
|
@ -267,7 +267,7 @@ Android compatible
|
|||
* some cards use a fix "08" or "18" in anticollision, no matter the block0. Including all 7b.
|
||||
* BCC:
|
||||
* some cards play blindly the block0 BCC byte, beware!
|
||||
* some cards compute a proper BCC in anticollision. Including all 7b comuting their BCC0 and BCC1.
|
||||
* some cards compute a proper BCC in anticollision. Including all 7b computing their BCC0 and BCC1.
|
||||
* ATS:
|
||||
* some cards don't reply to RATS
|
||||
* some reply with an ATS
|
||||
|
@ -363,7 +363,7 @@ Initial UID is AA55C396
|
|||
|
||||
### Identify
|
||||
|
||||
Only possible before personalisation.
|
||||
Only possible before personalization.
|
||||
|
||||
```
|
||||
hf 14a info
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
## Coverity Scan Config & Run
|
||||
Download the Coverity Scan Self-buld and install it.
|
||||
Download the Coverity Scan Self-build and install it.
|
||||
You will need to configure ARM-NON-EABI- Compiler for it to use:
|
||||
|
||||
Configure
|
||||
|
|
|
@ -13,7 +13,8 @@ At the moment both are maintained because they don't perfectly overlap yet.
|
|||
|
||||
| Feature | Makefile | CMake | Remarks |
|
||||
|-----|---|---|---|
|
||||
| verbose | V=1 | VERBOSE=1 | |
|
||||
| verbose | `V=1` | `VERBOSE=1` | |
|
||||
| debug build | `DEBUG=1` | `-DCMAKE_BUILD_TYPE=Debug` | client only |
|
||||
| warnings management | yes (1) | **no** | (1) cf Makefile.defs |
|
||||
| extra GCC warnings | GCCEXTRA=1 | **no** | |
|
||||
| extra Clang warnings | CLANGEXTRA=1 | **no** | only on host |
|
||||
|
@ -32,7 +33,7 @@ At the moment both are maintained because they don't perfectly overlap yet.
|
|||
| bzip2 detection | **none** | find_package, Cross:gitclone | |
|
||||
| dep cliparser | in_deps | in_deps | |
|
||||
| dep hardnested | in_deps | in_deps | |
|
||||
| hardn arch autodetect | `uname -m` =? 86 or amd64; `$(CC) -E -mavx512f`? +AVX512` | `CMAKE_SYSTEM_PROCESSOR` =? x86 or x86_64 or i686 or AMD64 (1) | (1) currently it always includes AVX512 on Intel arch |
|
||||
| hardn arch autodetect | `uname -m` =? 86 or amd64; `$(CC) -E -mavx512f`? +`AVX512` | `CMAKE_SYSTEM_PROCESSOR` =? x86 or x86_64 or i686 or AMD64 (1) | (1) currently it always includes AVX512 on Intel arch |
|
||||
| `cpu_arch` | yes | **no/auto?** | e.g. `cpu_arch=generic` for cross-compilation
|
||||
| dep jansson | sys / in_deps | sys / in_deps | |
|
||||
| jansson detection | pc | pc/find* | |
|
||||
|
|
|
@ -73,7 +73,7 @@ git clone https://github.com/RfidResearchGroup/proxmark3.git
|
|||
# Check ModemManager
|
||||
|
||||
### ⚠️ Very important ⚠️
|
||||
make sure ModemManager will not interfer, otherwise it could brick your Proxmark3!
|
||||
make sure ModemManager will not interfere, otherwise it could brick your Proxmark3!
|
||||
Read carefully [this page about ModemManager](ModemManager-Must-Be-Discarded.md) and follow its instructions.
|
||||
|
||||
# Check connection
|
||||
|
|
|
@ -8,7 +8,7 @@ ModemManager is pre-installed on many different Linux distributions, very probab
|
|||
It's intended to prepare and configure the mobile broadband (2G/3G/4G) devices, whether they are built-in or dongles.
|
||||
Some are serial, so when the Proxmark3 is plugged and a `/dev/ttyACM0` appears, ModemManager attempts to talk to it to see if it's a modem replying to AT commands.
|
||||
|
||||
Now imagine what happens when you're flashing your Proxmark3 and ModemManager suddently starts sending bytes to it at the same time...
|
||||
Now imagine what happens when you're flashing your Proxmark3 and ModemManager suddenly starts sending bytes to it at the same time...
|
||||
Yes it makes the flashing failing. And if it happens while you're flashing the bootloader, it will require a JTAG device to unbrick the Proxmark3.
|
||||
|
||||
ModemManager is a threat for the Proxmark3, but also for many other embedded devices, such as some Arduino platforms.
|
||||
|
@ -35,7 +35,7 @@ sudo systemctl disable ModemManager
|
|||
|
||||
# Solution 3: use filtering udev rules
|
||||
|
||||
If you *really* need ModemManager, e.g. for your 4G device, you'll have to use some filtering rules to make sure it doesn't interfer with the Proxmark3.
|
||||
If you *really* need ModemManager, e.g. for your 4G device, you'll have to use some filtering rules to make sure it doesn't interfere with the Proxmark3.
|
||||
|
||||
Once you have cloned the Proxmark3 repository, you can run `make udev` to install udev rules that will tell ModemManager to not look at your Proxmark3.
|
||||
|
||||
|
@ -89,7 +89,7 @@ sudo journalctl -f|grep "ModemManager.*\[filter\]"
|
|||
```
|
||||
Now plug in the Proxmark 3.
|
||||
|
||||
If ModemManager interfers, you'll get logs like this:
|
||||
If ModemManager interferes, you'll get logs like this:
|
||||
```
|
||||
ModemManager[xxxxx]: <debug> [filter] (tty/ttyACM0): port allowed: cdc-acm interface reported AT-capable
|
||||
```
|
||||
|
@ -108,7 +108,7 @@ sudo mmcli -G ERR
|
|||
|
||||
# I didn't read carefully this page and now my Proxmark3 is not responding
|
||||
|
||||
First of all, follow the instructions above to make sure ModemManager will not interfer with the Proxmark3 anymore.
|
||||
First of all, follow the instructions above to make sure ModemManager will not interfere with the Proxmark3 anymore.
|
||||
|
||||
Now there are two possibilities:
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ Always use the latest repository commits from *master* branch. There are always
|
|||
* [Troubles with running the Proxmark3 client](#troubles-with-running-the-proxmark3-client)
|
||||
* [libQt5Core.so.5 not found](#libQt5Coreso5-not-found)
|
||||
* [Target attribute is not supported on this machine](#target-attribute-is-not-supported-on-this-machine)
|
||||
* [Qt: Session management error:](#qt-session-management-error)
|
||||
|
||||
## `pm3` or `pm3-flash*` doesn't see my Proxmark
|
||||
|
||||
|
@ -65,7 +66,7 @@ Another possibility is if, when using the button for entering bootloader mode, t
|
|||
|
||||
### Determine if the bootloader was damaged or only the main OS image
|
||||
|
||||
Unplug, press the Proxmark3 button and keep it pressed when you plug it on USB. If the red LEDs show a "off/on/off/on" pattern, you're goot, you manually entered into the bootloader mode.
|
||||
Unplug, press the Proxmark3 button and keep it pressed when you plug it on USB. If the red LEDs show a "off/on/off/on" pattern, you're good, you manually entered into the bootloader mode.
|
||||
On new bootloaders, you can release the button. If the pattern disappears, you're on an older bootloader and you've to do it again and keep the button pressed during all the flashing operation.
|
||||
|
||||
Once in bootloader mode, flash the main image.
|
||||
|
@ -199,7 +200,7 @@ brew remove proxmark3
|
|||
brew reinstall proxmark3
|
||||
```
|
||||
|
||||
On Ubuntu 16.04 (xenial) you should either conside a later release or you can install a later toolchain.
|
||||
On Ubuntu 16.04 (xenial) you should either consider a later release or you can install a later toolchain.
|
||||
|
||||
|
||||
sample error output:
|
||||
|
@ -222,4 +223,16 @@ ticks.h:26:1: error: target attribute is not supported on this machine [-Werror=
|
|||
^
|
||||
```
|
||||
|
||||
## Qt Session management error
|
||||
If you get the message
|
||||
|
||||
```
|
||||
Qt: Session management error: None of the authentication protocols specified are supported
|
||||
``` when running the Proxmark3 client it might be because a a environment variable.
|
||||
|
||||
Solution:
|
||||
Try running the client without the SESSION_MANAGER environment variable.
|
||||
|
||||
```
|
||||
env -u SESSION_MANAGER ./pm3
|
||||
```
|
|
@ -150,7 +150,7 @@ Note that it may take a quite long time for a freshly plugged Proxmark3 to be vi
|
|||
Now you're ready to follow the [compilation instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md).
|
||||
|
||||
## Color text on windows 10
|
||||
In later versions of windows 10 you may be able to get color to work by setting this registery key
|
||||
In later versions of windows 10 you may be able to get color to work by setting this registry key
|
||||
```
|
||||
[HKEY_CURRENT_USER\Console]
|
||||
"VirtualTerminalLevel"=dword:00000001
|
||||
|
|
|
@ -25,7 +25,7 @@ Set all t55xx settings to defaults (will set all 4 at once)
|
|||
|
||||
To make sure you got the latest sim module firmware.
|
||||
|
||||
_Lastest version is v3.11_
|
||||
_Latest version is v3.11_
|
||||
|
||||
```
|
||||
[usb] pm3 --> hw status
|
||||
|
|
|
@ -190,7 +190,7 @@ Meanwhile, a fast transition to MIX frames can be done with:
|
|||
## Bootrom
|
||||
|
||||
Bootrom code will still use the old frame format to remain compatible with other repos supporting the old format and because it would hardly gain anything from the new format:
|
||||
* almost all frames convey 512b of payload, so difference in overhead is neglictible
|
||||
* almost all frames convey 512b of payload, so difference in overhead is negligible
|
||||
* bringing flash over usart sounds risky and would be terribly slow anyway (115200 bauds vs. 7M bauds).
|
||||
|
||||
`SendCommandBL` is the same as `SendCommandOLD` with a different name to be sure not to migrate it.
|
||||
|
|
|
@ -67,7 +67,7 @@ Dictionaries used by the client will be copied to
|
|||
Here you find the default dictionaries used for commands like `hf mf chk`, `hf mf fchk`, `lf t55xx chk`
|
||||
A dictionary file is a text based file with one key per line in hexdecimal form.
|
||||
The length of the key is decided by the Proxmark3 client for the different commands. All chars afterwards on line is ignored.
|
||||
if key isn't a hex number, the key is igonored.
|
||||
if key isn't a hex number, the key is ignored.
|
||||
|
||||
- t55xx, Mifare Ultralight/NTAG - uses 4 hexbytes (11223344)
|
||||
- Mifare classic uses 6 hexbytes (112233445566)
|
||||
|
|
|
@ -181,7 +181,7 @@ Install [this free app](https://play.google.com/store/apps/details?id=masar.bb)
|
|||
^[Top](#top)
|
||||
|
||||
You need to pair the proxmark3 in the Android settings.
|
||||
In the app choose your registred PM3 device as 'device A'.
|
||||
In the app choose your registered PM3 device as 'device A'.
|
||||
Select TCP server as 'Device B' and choose an unused port (e.g. 4321).
|
||||
Ensure 'Retransmission' is set to 'both ways'.
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ With `trace list` a table is shown which gives timing information, the src of th
|
|||
### Timing
|
||||
^[Top](#top)
|
||||
|
||||
The Start and the End coloumn lists timestamps when the transmission of the shown data started (time of first bit) and when it ended (end of last modulation).
|
||||
The Start and the End column lists timestamps when the transmission of the shown data started (time of first bit) and when it ended (end of last modulation).
|
||||
|
||||
The unit for this time information depends on the protocol in use:
|
||||
|
||||
|
@ -29,7 +29,7 @@ The unit for this time information depends on the protocol in use:
|
|||
* iClass, ISO15693, ISO18092 and FeliCa have no accurate timing information at the moment
|
||||
* For others timing is not available
|
||||
|
||||
By specifing the option ```f``` (e.g. ```trace list 14a f```) the frame delay times are shown. (So you don't have to do the math by your own).
|
||||
By specifying the option ```f``` (e.g. ```trace list 14a f```) the frame delay times are shown. (So you don't have to do the math by your own).
|
||||
|
||||
### Sources
|
||||
^[Top](#top)
|
||||
|
@ -39,7 +39,7 @@ If the data is marked as a response the source is shown as Tag. Otherwise it is
|
|||
### Data
|
||||
^[Top](#top)
|
||||
|
||||
This coloumn show the raw bytes trasmitted over the air. With option ```c``` CRC bytes are marked in square brackets.
|
||||
This column shows the raw bytes transmitted over the air. With option ```c``` CRC bytes are marked in square brackets.
|
||||
|
||||
### CRC
|
||||
^[Top](#top)
|
||||
|
|
|
@ -28,7 +28,7 @@ USART support is in `common/usart.c`.
|
|||
|
||||
There are mainly two ways to use this USART:
|
||||
* connect the host client to the Proxmark3 via this USART instead of USB-CDC, this is the `FPC_USART_HOST` option you can add to `PLATFORM_EXTRAS` in `Makefile.platform`. The most used way is through the BT add-on (blue shark) that we will cover later. Instead of BT add-on, we can also use e.g. a FTDI cable (mostly for internal development, it's much slower than USB-CDC anyway) or in the future other ways to connect the host such as a USART-to-Wi-Fi bridge.
|
||||
* connect "slave" devices to the Proxmark3 to add functionnalities. In such case, the host client will use USB-CDC and the USART will be use to, e.g. connect the Proxmark3 to various daughterboards. These is no such example of daughterboard as of today, except when we're talking to the BT add-on in its AT configuration mode.
|
||||
* connect "slave" devices to the Proxmark3 to add functionalities. In such case, the host client will use USB-CDC and the USART will be use to, e.g. connect the Proxmark3 to various daughterboards. These is no such example of daughterboard as of today, except when we're talking to the BT add-on in its AT configuration mode.
|
||||
|
||||
This USART can be reached from the host client (if connected via USB-CDC) through the following commands, available when you add `FPC_USART_DEV` to `PLATFORM_EXTRAS` in `Makefile.platform`:
|
||||
* `usart config`, to configure the baudrate and the parity of the Proxmark3 USART
|
||||
|
@ -63,7 +63,7 @@ The add-on acts as a bridge, between its UART and the BT communication channel,
|
|||
|
||||
The Bluetooth RFCOMM protocol provides an emulation of serial ports over the L2CAP protocol ([ref](https://www.amd.e-technik.uni-rostock.de/ma/gol/lectures/wirlec/bluetooth_info/rfcomm.html)).
|
||||
|
||||
As for USB-CDC, the real speed of the link is unrelated to serial baudrate notion. Litterature mentions a maximal value of 360kbps for some implementations, but the HC-06 Bluetooth module within the BT add-on is limited as the vast majority of similar devices to 128kbps.
|
||||
As for USB-CDC, the real speed of the link is unrelated to serial baudrate notion. Literature mentions a maximal value of 360kbps for some implementations, but the HC-06 Bluetooth module within the BT add-on is limited as the vast majority of similar devices to 128kbps.
|
||||
|
||||
### BT add-on baudrate
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ typedef struct {
|
|||
uint8_t addresses[4];
|
||||
uint8_t address;
|
||||
uint8_t word[4];
|
||||
} em4x50_data_t;
|
||||
} PACKED em4x50_data_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t byte[4];
|
||||
|
@ -60,6 +60,6 @@ typedef struct {
|
|||
bool cparity[8];
|
||||
bool stopparity;
|
||||
bool parity;
|
||||
} em4x50_word_t;
|
||||
} PACKED em4x50_word_t;
|
||||
|
||||
#endif /* EM4X50_H__ */
|
||||
|
|
|
@ -306,6 +306,7 @@ typedef struct {
|
|||
bool use_raw;
|
||||
bool use_elite;
|
||||
bool use_credit_key;
|
||||
bool use_replay;
|
||||
bool send_reply;
|
||||
bool do_auth;
|
||||
uint8_t blockno;
|
||||
|
@ -333,11 +334,15 @@ typedef struct {
|
|||
} PACKED iclass_writeblock_req_t;
|
||||
|
||||
// iCLASS dump data structure
|
||||
typedef struct {
|
||||
uint8_t blockno;
|
||||
uint8_t data[8];
|
||||
} PACKED iclass_restore_item_t;
|
||||
|
||||
typedef struct {
|
||||
iclass_auth_req_t req;
|
||||
uint8_t start_block;
|
||||
uint8_t end_block;
|
||||
uint8_t data[];
|
||||
uint8_t item_cnt;
|
||||
iclass_restore_item_t blocks[];
|
||||
} PACKED iclass_restore_req_t;
|
||||
|
||||
|
||||
|
@ -350,7 +355,7 @@ typedef struct {
|
|||
uint8_t mem_config; //[13]
|
||||
uint8_t eas; //[14]
|
||||
uint8_t fuses; //[15]
|
||||
} picopass_conf_block_t;
|
||||
} PACKED picopass_conf_block_t;
|
||||
|
||||
// iCLASS secure mode memory mapping
|
||||
typedef struct {
|
||||
|
@ -360,16 +365,22 @@ typedef struct {
|
|||
uint8_t key_d[8];
|
||||
uint8_t key_c[8];
|
||||
uint8_t app_issuer_area[8];
|
||||
} picopass_hdr;
|
||||
} PACKED picopass_hdr;
|
||||
|
||||
// iCLASS non-secure mode memory mapping
|
||||
typedef struct {
|
||||
uint8_t csn[8];
|
||||
picopass_conf_block_t conf;
|
||||
uint8_t app_issuer_area[8];
|
||||
} picopass_ns_hdr;
|
||||
} PACKED picopass_ns_hdr;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint16_t delay_us;
|
||||
bool on;
|
||||
bool off;
|
||||
} PACKED tearoff_params_t;
|
||||
|
||||
// For the bootloader
|
||||
#define CMD_DEVICE_INFO 0x0000
|
||||
//#define CMD_SETUP_WRITE 0x0001
|
||||
|
@ -485,9 +496,11 @@ typedef struct {
|
|||
#define CMD_LF_T55XX_RESET_READ 0x0216
|
||||
#define CMD_LF_PCF7931_READ 0x0217
|
||||
#define CMD_LF_PCF7931_WRITE 0x0223
|
||||
#define CMD_LF_EM4X_LOGIN 0x0229
|
||||
#define CMD_LF_EM4X_READWORD 0x0218
|
||||
#define CMD_LF_EM4X_WRITEWORD 0x0219
|
||||
#define CMD_LF_EM4X_PROTECTWORD 0x021B
|
||||
#define CMD_LF_EM4X_BF 0x022A
|
||||
#define CMD_LF_IO_WATCH 0x021A
|
||||
#define CMD_LF_EM410X_WATCH 0x021C
|
||||
#define CMD_LF_EM4X50_INFO 0x0240
|
||||
|
@ -559,12 +572,10 @@ typedef struct {
|
|||
|
||||
// iCLASS / Picopass
|
||||
#define CMD_HF_ICLASS_READCHECK 0x038F
|
||||
#define CMD_HF_ICLASS_CLONE 0x0390
|
||||
#define CMD_HF_ICLASS_DUMP 0x0391
|
||||
#define CMD_HF_ICLASS_SNIFF 0x0392
|
||||
#define CMD_HF_ICLASS_SIMULATE 0x0393
|
||||
#define CMD_HF_ICLASS_READER 0x0394
|
||||
#define CMD_HF_ICLASS_REPLAY 0x0395
|
||||
#define CMD_HF_ICLASS_READBL 0x0396
|
||||
#define CMD_HF_ICLASS_WRITEBL 0x0397
|
||||
#define CMD_HF_ICLASS_EML_MEMSET 0x0398
|
||||
|
|
|
@ -541,8 +541,8 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
|
|||
#define T55XX_WRITE_TIMEOUT 1500
|
||||
|
||||
// em4x05 & em4x69 chip configuration register definitions
|
||||
#define EM4x05_GET_BITRATE(x) (((x & 0x3F)*2)+2)
|
||||
#define EM4x05_SET_BITRATE(x) ((x-2)/2)
|
||||
#define EM4x05_GET_BITRATE(x) ((((x) & 0x3F) * 2) + 2)
|
||||
#define EM4x05_SET_BITRATE(x) (((x) - 2) / 2)
|
||||
#define EM4x05_MODULATION_NRZ 0x00000000
|
||||
#define EM4x05_MODULATION_MANCHESTER 0x00000040
|
||||
#define EM4x05_MODULATION_BIPHASE 0x00000080
|
||||
|
@ -557,15 +557,15 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
|
|||
#define EM4x05_PSK_RF_8 0x00000800
|
||||
#define EM4x05_MAXBLOCK_SHIFT 14
|
||||
#define EM4x05_FIRST_USER_BLOCK 5
|
||||
#define EM4x05_SET_NUM_BLOCKS(x) ((x+5-1)<<14) //# of blocks sent during default read mode
|
||||
#define EM4x05_GET_NUM_BLOCKS(x) (((x>>14) & 0xF)-5+1)
|
||||
#define EM4x05_READ_LOGIN_REQ 1<<18
|
||||
#define EM4x05_READ_HK_LOGIN_REQ 1<<19
|
||||
#define EM4x05_WRITE_LOGIN_REQ 1<<20
|
||||
#define EM4x05_WRITE_HK_LOGIN_REQ 1<<21
|
||||
#define EM4x05_READ_AFTER_WRITE 1<<22
|
||||
#define EM4x05_DISABLE_ALLOWED 1<<23
|
||||
#define EM4x05_READER_TALK_FIRST 1<<24
|
||||
#define EM4x05_SET_NUM_BLOCKS(x) (( (x) + 4) << 14) //# of blocks sent during default read mode
|
||||
#define EM4x05_GET_NUM_BLOCKS(x) ((( (x) >> 14) & 0xF) - 4)
|
||||
#define EM4x05_READ_LOGIN_REQ (1 << 18)
|
||||
#define EM4x05_READ_HK_LOGIN_REQ (1 << 19)
|
||||
#define EM4x05_WRITE_LOGIN_REQ (1 << 20)
|
||||
#define EM4x05_WRITE_HK_LOGIN_REQ (1 << 21)
|
||||
#define EM4x05_READ_AFTER_WRITE (1 << 22)
|
||||
#define EM4x05_DISABLE_ALLOWED (1 << 23)
|
||||
#define EM4x05_READER_TALK_FIRST (1 << 24)
|
||||
|
||||
|
||||
// FeliCa protocol
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
|
||||
|filename|description|
|
||||
|--------|-----------|
|
||||
|lf_sniff_blue_cloner_em4100.pm3 |Sniffing of blue cloner writing an EM4100 on T5577 and EM4305|
|
||||
|lf_sniff_ht2-BC3B8810-acg-reader.pm3 |Sniffing of Hitag2 being read by an HID ACG LF Multitag reader|
|
||||
|lf_sniff_ht2-BC3B8810-frosch-reader.pm3 |Sniffing of Hitag2 being read by a Frosch Hitag reader|
|
||||
|lf_sniff_ht2-BC3B8810-rfidler-reader.pm3 |Sniffing of Hitag2 being read by a RFIDler|
|
||||
|
|
108120
traces/lf_sniff_blue_cloner_em4100.pm3
Normal file
108120
traces/lf_sniff_blue_cloner_em4100.pm3
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue