Merge branch 'master' into purring-basilisk

Signed-off-by: JLitewski <hackhalotwo@gmail.com>
This commit is contained in:
JLitewski
2024-04-22 06:42:45 -04:00
committed by GitHub
50 changed files with 1544 additions and 1560 deletions
+1 -1
View File
@@ -98,7 +98,7 @@ jobs:
steps:
- name: WSL setup
uses: Vampire/setup-wsl@v2
uses: Vampire/setup-wsl@v3
with:
distribution: Ubuntu-22.04
update: "true"
+4 -5
View File
@@ -5,7 +5,6 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
## [unreleased][unreleased]
- Removed `save_restoreDB` - replaced by `buffer_savestate_t` implementation (@HACKhalo2)
- Removed `save_restoreGB` - replaced by `buffer_savestate_t` implementation (@HACKhalo2)
- Changed `hf mfp info` to identify Ev2 (@iceman1001)
- Updated Graph Markers implementation to include temporary markers and marker labels (@HACKhalo2)
- Updated to SWIG 4.2.1 (@iceman1001)
- Removed `data bin2hex` - replaced by `data num` (@iceman1001)
@@ -416,9 +415,9 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Changed `hf 15 sim` - now supports reader writes (@markus-oehme-pg40)
- Added `hf 15 eload` - specify memory image for ISO15693 simulation (@markus-oehme-pg40)
- Added `hf 15 sim --blocksize` - configure block size for simulation (@markus-oehme-pg40)
- Fixed buffer overflow in mfu ndef decode (@mwalker)
- Changed spiffs write/append to send in 8192 chunks to ensure its eraised (@mwalker)
- Fixed spiffs dump to ensure to fails correctly if no big_buff was allocated (@mwalker)
- Fixed buffer overflow in mfu ndef decode (@mwalker33)
- Changed spiffs write/append to send in 8192 chunks to ensure its eraised (@mwalker33)
- Fixed spiffs dump to ensure to fails correctly if no big_buff was allocated (@mwalker33)
- Change Client Makefile to respect global flags (@blshkv)
- Change Makefile, honors global CC values (@blshkv)
- Fixed bad memory handling in MifareSim device side (@iceman1001)
@@ -624,7 +623,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Fixed `hf fido` commands now works correctly (@merlokk)
- Moved / renamed `client/resource/fido2_defparams.json` -> `client/resource/hf_fido2_defparams.json` (@merlokk)
- Added `hf cipurse` commands to work with cipurse transport cards (@merlokk)
- Added `--gap` option to lf em 410x sim for more control over sim data (@mwalker)
- Added `--gap` option to lf em 410x sim for more control over sim data (@mwalker33)
- Changed `hf fido` - refactored load/save json objects (@iceman1001)
- Moved / renamed `fido2.json` -> `client/resource/fido2_defparams.json` (@iceman1001)
- Added openocd shikra support based on @ninjastyle82 patch to deprecated iceman fork (@iceman1001)
+8
View File
@@ -1364,6 +1364,14 @@ static void PacketReceived(PacketCommandNG *packet) {
SetTag15693Uid(payload->uid);
break;
}
case CMD_HF_ISO15693_CSETUID_V2: {
struct p {
uint8_t uid[8];
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
SetTag15693Uid_v2(payload->uid);
break;
}
case CMD_HF_ISO15693_SLIX_DISABLE_EAS: {
struct p {
uint8_t pwd[4];
+47 -12
View File
@@ -29,7 +29,8 @@
// FeliCa timings
// minimum time between the start bits of consecutive transfers from reader to tag: 6800 carrier (13.56MHz) cycles
#ifndef FELICA_REQUEST_GUARD_TIME
# define FELICA_REQUEST_GUARD_TIME (6800/16 + 1) // 426
//# define FELICA_REQUEST_GUARD_TIME (6800 / 16 + 1) // 426
# define FELICA_REQUEST_GUARD_TIME ((512 + 0 * 256) * 64 / 16 + 1)
#endif
// FRAME DELAY TIME 2672 carrier cycles
#ifndef FELICA_FRAME_DELAY_TIME
@@ -64,6 +65,11 @@ static uint32_t iso18092_get_timeout(void) {
#define FELICA_MAX_FRAME_SIZE 260
#endif
//structure to hold outgoing NFC frame
static uint8_t frameSpace[FELICA_MAX_FRAME_SIZE + 4];
@@ -122,38 +128,45 @@ static void shiftInByte(uint8_t bt) {
}
static void Process18092Byte(uint8_t bt) {
switch (FelicaFrame.state) {
case STATE_UNSYNCD: {
//almost any nonzero byte can be start of SYNC. SYNC should be preceded by zeros, but that is not always the case
// almost any nonzero byte can be start of SYNC. SYNC should be preceded by zeros, but that is not always the case
if (bt > 0) {
FelicaFrame.shiftReg = reflect8(bt);
FelicaFrame.state = STATE_TRYING_SYNC;
}
break;
}
case STATE_TRYING_SYNC: {
if (bt == 0) {
//desync
// desync
FelicaFrame.shiftReg = bt;
FelicaFrame.state = STATE_UNSYNCD;
} else {
for (uint8_t i = 0; i < 8; i++) {
if (FelicaFrame.shiftReg == SYNC_16BIT) {
//SYNC done!
// SYNC done!
FelicaFrame.state = STATE_GET_LENGTH;
FelicaFrame.framebytes[0] = 0xb2;
FelicaFrame.framebytes[1] = 0x4d;
FelicaFrame.byte_offset = i;
//shift in remaining byte, slowly...
// shift in remaining byte, slowly...
for (uint8_t j = i; j < 8; j++) {
FelicaFrame.framebytes[2] = (FelicaFrame.framebytes[2] << 1) + (bt & 1);
bt >>= 1;
}
FelicaFrame.posCnt = 2;
if (i == 0)
if (i == 0) {
break;
}
}
FelicaFrame.shiftReg = (FelicaFrame.shiftReg << 1) + (bt & 1);
bt >>= 1;
@@ -351,16 +364,21 @@ static void BuildFliteRdblk(const uint8_t *idm, uint8_t blocknum, const uint16_t
}
static void TransmitFor18092_AsReader(const uint8_t *frame, uint16_t len, const uint32_t *NYI_timing_NYI, uint8_t power, uint8_t highspeed) {
if (NYI_timing_NYI != NULL) {
Dbprintf("Error: TransmitFor18092_AsReader does not check or set parameter NYI_timing_NYI");
return;
}
uint16_t flags = FPGA_MAJOR_MODE_HF_ISO18092;
if (power)
if (power) {
flags |= FPGA_HF_ISO18092_FLAG_READER;
if (highspeed)
}
if (highspeed) {
flags |= FPGA_HF_ISO18092_FLAG_424K;
}
FpgaWriteConfWord(flags);
@@ -419,9 +437,13 @@ static void TransmitFor18092_AsReader(const uint8_t *frame, uint16_t len, const
// stop when button is pressed
// or return TRUE when command is captured
bool WaitForFelicaReply(uint16_t maxbytes) {
if (g_dbglevel >= DBG_DEBUG)
if (g_dbglevel >= DBG_DEBUG) {
Dbprintf("WaitForFelicaReply Start");
}
uint32_t c = 0;
// power, no modulation
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO18092 | FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD);
FelicaFrameReset();
@@ -433,12 +455,19 @@ bool WaitForFelicaReply(uint16_t maxbytes) {
uint32_t timeout = iso18092_get_timeout();
for (;;) {
WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
b = (uint8_t)(AT91C_BASE_SSC->SSC_RHR);
Process18092Byte(b);
if (FelicaFrame.state == STATE_FULL) {
felica_nexttransfertime = MAX(felica_nexttransfertime,
felica_nexttransfertime = MAX(
felica_nexttransfertime,
(GetCountSspClk() & 0xfffffff8) - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / 16 + FELICA_FRAME_DELAY_TIME);
LogTrace(
@@ -449,10 +478,15 @@ bool WaitForFelicaReply(uint16_t maxbytes) {
NULL,
false
);
if (g_dbglevel >= DBG_DEBUG) Dbprintf("All bytes received! STATE_FULL");
return true;
} else if (c++ > timeout && (FelicaFrame.state == STATE_UNSYNCD || FelicaFrame.state == STATE_TRYING_SYNC)) {
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Error: Timeout! STATE_UNSYNCD");
return false;
}
}
@@ -478,8 +512,9 @@ static void iso18092_setup(uint8_t fpga_minor_mode) {
// DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
FelicaFrameinit(BigBuf_malloc(FELICA_MAX_FRAME_SIZE));
felica_nexttransfertime = 2 * DELAY_ARM2AIR_AS_READER;
iso18092_set_timeout(2120); // 106 * 20ms maximum start-up time of card
felica_nexttransfertime = 2 * DELAY_ARM2AIR_AS_READER; // 418
// iso18092_set_timeout(2120); // 106 * 20ms maximum start-up time of card
iso18092_set_timeout(1060); // 106 * 10ms maximum start-up time of card
init_table(CRC_FELICA);
+356
View File
@@ -0,0 +1,356 @@
//-----------------------------------------------------------------------------
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// See LICENSE.txt for the text of the license.
//-----------------------------------------------------------------------------
// This coode has been converted from RFIDler source code to work with Proxmark3.
// https://github.com/AdamLaurie/RFIDler/blob/master/firmware/Pic32/RFIDler.X/src/hitag2crack.c
#include "hitag2_crack.h"
#include "hitag2_crypto.h"
#include "hitag2.h"
#include "proxmark3_arm.h"
#include "commonutil.h"
#include "dbprint.h"
#include "util.h"
#include "string.h"
#include "BigBuf.h"
#include "cmd.h"
const static uint8_t ERROR_RESPONSE[] = { 0xF4, 0x02, 0x88, 0x9C };
// #define READP0CMD "1100000111"
const static uint8_t read_p0_cmd[] = {1,1,0,0,0,0,0,1,1,1};
// hitag2crack_xor XORs the source with the pad to produce the target.
// source, target and pad are binarrays of length len.
static void hitag2crack_xor(uint8_t *target, const uint8_t *source, const uint8_t *pad, uint16_t len) {
for (uint16_t i = 0; i < len; i++) {
target[i] = source[i] ^ pad[i];
}
}
// hitag2crack_send_e_cmd replays the auth and sends the given encrypted
// command.
// responsestr is the hexstring of the response to the command;
// nrar is the 64 bit binarray of the nR aR pair;
// cmd is the binarray of the encrypted command to send;
// len is the length of the encrypted command.
static bool hitag2crack_send_e_cmd(uint8_t *resp, uint8_t *nrar, uint8_t *cmd, int len) {
memset(resp, 0, 4);
// Get UID
uint8_t uid[4];
if (ht2_read_uid(uid, false, false, true) != PM3_SUCCESS) {
return false;
}
// send nrar and receive (useless) encrypted page 3 value
uint8_t e_page3[4];
size_t n = 0;
if (ht2_tx_rx(nrar, 64, e_page3, &n, true, true) != PM3_SUCCESS) {
return false;
}
// send encrypted command
n = 0;
ht2_tx_rx(cmd, len, resp, &n, true, false);
if (n == 32) {
return true;
}
return false;
}
// hitag2crack_read_page uses the supplied key stream and nrar pair to read the
// given page, returning the response as a hexstring.
// responsestr is the returned hexstring;
// pagenum is the page number to read;
// nrar is the 64 bit binarray of the nR aR pair;
// keybits is the binarray of the key stream.
static bool hitag2crack_read_page(uint8_t *resp, uint8_t pagenum, uint8_t *nrar, uint8_t *keybits) {
if (pagenum > 7) {
return false;
}
// create cmd
uint8_t cmd[10];
memcpy(cmd, read_p0_cmd, sizeof(read_p0_cmd));
if (pagenum & 0x1) {
cmd[9] = !cmd[9];
cmd[4] = !cmd[4];
}
if (pagenum & 0x2) {
cmd[8] = !cmd[8];
cmd[3] = !cmd[3];
}
if (pagenum & 0x4) {
cmd[7] = !cmd[7];
cmd[2] = !cmd[2];
}
// encrypt command
uint8_t e_cmd[10] = {0};
hitag2crack_xor(e_cmd, cmd, keybits, 10);
// send encrypted command
uint8_t e_resp[4];
if (hitag2crack_send_e_cmd(e_resp, nrar, e_cmd, 10)) {
// check if it is valid OBS!
if (memcmp(e_resp, ERROR_RESPONSE, 4)) {
uint8_t e_response[32];
uint8_t response[32];
// convert to binarray
hex2binarray((char*)e_response, (char*)e_resp);
// decrypt response
hitag2crack_xor(response, e_response, keybits + 10, 32);
// convert to hexstring
binarray2hex(response, 32, resp);
return true;
}
}
return false;
}
// hitag2crack_test_e_p0cmd XORs the message (command + response) with the
// encrypted version to retrieve the key stream. It then uses this key stream
// to encrypt an extended version of the READP0CMD and tests if the response
// is valid.
// keybits is the returned binarray of the key stream;
// nrar is the 64 bit binarray of nR aR pair;
// e_cmd is the binarray of the encrypted command;
// uid is the binarray of the card UID;
// e_uid is the binarray of the encrypted version of the UID.
static bool hitag2crack_test_e_p0cmd(uint8_t *keybits, uint8_t *nrar, uint8_t *e_cmd, uint8_t *uid, uint8_t *e_uid) {
uint8_t cipherbits[42];
memcpy(cipherbits, e_cmd, 10); // copy encrypted cmd to cipherbits
memcpy(cipherbits + 10, e_uid, 32); // copy encrypted uid to cipherbits
uint8_t plainbits[42];
memcpy(plainbits, read_p0_cmd, sizeof(read_p0_cmd)); // copy cmd to plainbits
memcpy(plainbits + 10, uid, 32); // copy uid to plainbits
// xor the plainbits with the cipherbits to get keybits
hitag2crack_xor(keybits, plainbits, cipherbits, 42);
// create extended cmd -> 4 * READP0CMD = 40 bits
uint8_t ext_cmd[40];
memcpy(ext_cmd, read_p0_cmd, sizeof(read_p0_cmd));
memcpy(ext_cmd + 10, read_p0_cmd, sizeof(read_p0_cmd));
memcpy(ext_cmd + 20, read_p0_cmd, sizeof(read_p0_cmd));
memcpy(ext_cmd + 30, read_p0_cmd, sizeof(read_p0_cmd));
// xor extended cmd with keybits
uint8_t e_ext_cmd[40];
hitag2crack_xor(e_ext_cmd, ext_cmd, keybits, 40);
// send extended encrypted cmd
uint8_t resp[4];
if (hitag2crack_send_e_cmd(resp, nrar, e_ext_cmd, 40)) {
// test if it was valid
if (memcmp(resp, ERROR_RESPONSE, 4)) {
return true;
}
}
return false;
}
// hitag2crack_find_e_page0_cmd tries all bit-flipped combinations of the
// valid encrypted command and tests the results by attempting an extended
// command version of the command to see if that produces a valid response.
// keybits is the returned binarray of the recovered key stream;
// e_page0cmd is the returned binarray of the encrypted 'read page 0' command;
// e_firstcmd is the binarray of the first valid encrypted command found;
// nrar is the binarray of the 64 bit nR aR pair;
// uid is the binarray of the 32 bit UID.
static bool hitag2crack_find_e_page0_cmd(uint8_t *keybits, uint8_t *e_firstcmd, uint8_t *nrar, uint8_t *uid) {
// we're going to brute the missing 4 bits of the valid encrypted command
for (uint8_t a = 0; a < 2; a++) {
for (uint8_t b = 0; b < 2; b++) {
for (uint8_t c = 0; c < 2; c++) {
for (uint8_t d = 0; d < 2; d++) {
// create our guess by bit flipping the pattern of bits
// representing the inverted bit and the 3 page bits
// in both the non-inverted and inverted parts of the
// encrypted command.
uint8_t guess[10];
memcpy(guess, e_firstcmd, 10);
if (a) {
guess[5] = !guess[5];
guess[0] = !guess[0];
}
if (b) {
guess[7] = !guess[7];
guess[2] = !guess[2];
}
if (c) {
guess[8] = !guess[8];
guess[3] = !guess[3];
}
if (d) {
guess[9] = !guess[9];
guess[4] = !guess[4];
}
// try the guess
uint8_t resp[4];
if (hitag2crack_send_e_cmd(resp, nrar, guess, 10)) {
// check if it was valid
if (memcmp(resp, ERROR_RESPONSE, 4)) {
// convert response to binarray
uint8_t e_uid[32];
hex2binarray((char*)e_uid, (char*)resp);
// test if the guess was 'read page 0' command
if (hitag2crack_test_e_p0cmd(keybits, nrar, guess, uid, e_uid)) {
return true;
}
}
}
}
}
}
}
return false;
}
// hitag2crack_find_valid_e_cmd repeatedly replays the auth protocol each
// with a different sequential encrypted command value in order to find one
// that returns a valid response.
// e_cmd is the returned binarray of the valid encrypted command;
// nrar is the binarray of the 64 bit nR aR pair.
static bool hitag2crack_find_valid_e_cmd(uint8_t *e_cmd, uint8_t *nrar) {
// we're going to hold bits 5, 7, 8 and 9 and brute force the rest
// e.g. x x x x x 0 x 0 0 0
for (uint8_t a = 0; a < 2; a++) {
for (uint8_t b = 0; b < 2; b++) {
for (uint8_t c = 0; c < 2; c++) {
for (uint8_t d = 0; d < 2; d++) {
for (uint8_t e = 0; e < 2; e++) {
for (uint8_t g = 0; g < 2; g++) {
// build binarray
//uint8_t guess[10] = { a, b, c, d, e, 0, g, 0, 0, 0 };
uint8_t guess[10];
guess[0] = a;
guess[1] = b;
guess[2] = c;
guess[3] = d;
guess[4] = e;
guess[5] = 0;
guess[6] = g;
guess[7] = 0;
guess[8] = 0;
guess[9] = 0;
// send guess
uint8_t resp[4];
if (hitag2crack_send_e_cmd(resp, nrar, guess, sizeof(guess))) {
// check if it was valid
if (memcmp(resp, ERROR_RESPONSE, 4)) {
// return the guess as the encrypted command
memcpy(e_cmd, guess, 10);
return true;
}
}
}
}
}
}
}
}
return false;
}
// hitag2_crack implements the first crack algorithm described in the paper,
// Gone In 360 Seconds by Verdult, Garcia and Balasch.
// response is a multi-line text response containing the 8 pages of the cracked tag
// nrarhex is a string containing hex representations of the 32 bit nR and aR values
void ht2_crack(uint8_t *nrar_hex) {
clear_trace();
lf_hitag_crack_response_t packet;
memset((uint8_t*)&packet, 0x00, sizeof(lf_hitag_crack_response_t));
int res = PM3_SUCCESS;
// get uid as hexstring
uint8_t uid_hex[4];
if (ht2_read_uid(uid_hex, false, false, false) != PM3_SUCCESS) {
packet.status = -1;
res = PM3_EFAILED;
goto out;
}
// convert to binarray
uint8_t nrar[64] = {0};
hex2binarray_n((char*)nrar, (char*)nrar_hex, 8);
// find a valid encrypted command
uint8_t e_firstcmd[10];
if (hitag2crack_find_valid_e_cmd(e_firstcmd, nrar) == false) {
packet.status = -2;
res = PM3_EFAILED;
goto out;
}
// now we got a first encrypted command inside e_firstcmd
uint8_t uid[32];
hex2binarray_n((char*)uid, (char*)uid_hex, 4);
// find the 'read page 0' command and recover key stream
uint8_t keybits[42];
if (hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid) == false) {
packet.status = -3;
res = PM3_EFAILED;
goto out;
}
// read all pages using key stream
for (uint8_t i = 1; i < 8; i++) {
hitag2crack_read_page(packet.data + (i * 4), i, nrar, keybits);
}
// copy UID since we already have it...
memcpy(packet.data, uid_hex, 4);
packet.status = 1;
out:
reply_ng(CMD_LF_HITAG2_CRACK, res, (uint8_t*)&packet, sizeof(lf_hitag_crack_response_t));
}
+27
View File
@@ -0,0 +1,27 @@
//-----------------------------------------------------------------------------
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// See LICENSE.txt for the text of the license.
//-----------------------------------------------------------------------------
// Hitag2 crack implementeation
//-----------------------------------------------------------------------------
#ifndef _HITAG2_CRACK__H_
#define _HITAG2_CRACK__H_
#include <stdbool.h>
#include "common.h"
void ht2_crack(uint8_t *nrar_hex);
#endif
File diff suppressed because it is too large Load Diff
-42
View File
@@ -1,42 +0,0 @@
//-----------------------------------------------------------------------------
// Borrowed initially from https://github.com/factoritbv/hitag2hell
// and https://github.com/AdamLaurie/RFIDler/blob/master/firmware/Pic32/RFIDler.X/src/hitag2crack.c
// Copyright (C) Kevin Sheldrake <kev@headhacking.com>, Aug 2018
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// See LICENSE.txt for the text of the license.
//-----------------------------------------------------------------------------
// Definitions hitag2 attack functions
//-----------------------------------------------------------------------------
bool hitag2_crack(uint8_t *response, uint8_t *nrarhex);
bool hitag2crack_find_valid_e_cmd(uint8_t e_cmd[], uint8_t nrar[]);
bool hitag2crack_find_e_page0_cmd(uint8_t keybits[], uint8_t e_firstcmd[], uint8_t nrar[], uint8_t uid[]);
bool hitag2crack_test_e_p0cmd(uint8_t *keybits, uint8_t *nrar, uint8_t *e_cmd, uint8_t *uid, uint8_t *e_uid);
void hitag2crack_xor(uint8_t *target, const uint8_t *source, const uint8_t *pad, unsigned int len);
bool hitag2crack_read_page(uint8_t *responsestr, uint8_t pagenum, uint8_t *nrar, uint8_t *keybits);
bool hitag2crack_send_e_cmd(uint8_t *responsestr, uint8_t *nrar, uint8_t *cmd, int len);
bool hitag2crack_tx_rx(uint8_t *responsestr, uint8_t *msg, int len, int state, bool reset);
bool hitag2crack_rng_init(uint8_t *response, uint8_t *input);
bool hitag2crack_decrypt_hex(uint8_t *response, uint8_t *hex);
bool hitag2crack_decrypt_bin(uint8_t *response, uint8_t *e_binstr);
bool hitag2crack_encrypt_hex(uint8_t *response, uint8_t *hex);
bool hitag2crack_encrypt_bin(uint8_t *response, uint8_t *e_binstr);
bool hitag2_keystream(uint8_t *response, uint8_t *nrarhex);
bool hitag2crack_send_auth(uint8_t *nrar);
bool hitag2crack_consume_keystream(uint8_t *keybits, int kslen, int *ksoffset, uint8_t *nrar);
bool hitag2crack_extend_keystream(uint8_t *keybits, int *kslen, int ksoffset, uint8_t *nrar, uint8_t *uid);
bool hitag2_reader(uint8_t *response, uint8_t *key, bool interactive);
+54 -13
View File
@@ -2890,21 +2890,14 @@ void SetTag15693Uid(const uint8_t *uid) {
uint8_t cmd[4][9] = {
{ISO15_REQ_DATARATE_HIGH, ISO15693_WRITEBLOCK, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xE9, 0x8F},
{ISO15_REQ_DATARATE_HIGH, ISO15693_WRITEBLOCK, 0x3f, 0x69, 0x96, 0x00, 0x00, 0x8A, 0xBB},
{ISO15_REQ_DATARATE_HIGH, ISO15693_WRITEBLOCK, 0x38},
{ISO15_REQ_DATARATE_HIGH, ISO15693_WRITEBLOCK, 0x39}
// Command 3 : 02 21 38 u8u7u6u5 (where uX = uid byte X)
{ISO15_REQ_DATARATE_HIGH, ISO15693_WRITEBLOCK, 0x38, uid[7], uid[6], uid[5], uid[4]},
// Command 4 : 02 21 39 u4u3u2u1 (where uX = uid byte X)
{ISO15_REQ_DATARATE_HIGH, ISO15693_WRITEBLOCK, 0x39, uid[3], uid[2], uid[1], uid[0]}
};
// Command 3 : 02 21 38 u8u7u6u5 (where uX = uid byte X)
cmd[2][3] = uid[7];
cmd[2][4] = uid[6];
cmd[2][5] = uid[5];
cmd[2][6] = uid[4];
// Command 4 : 02 21 39 u4u3u2u1 (where uX = uid byte X)
cmd[3][3] = uid[3];
cmd[3][4] = uid[2];
cmd[3][5] = uid[1];
cmd[3][6] = uid[0];
AddCrc15(cmd[2], 7);
AddCrc15(cmd[3], 7);
@@ -2938,6 +2931,54 @@ void SetTag15693Uid(const uint8_t *uid) {
switch_off();
}
// Set the UID on Magic ISO15693 tag ( Gen2 ?)
// E0 00 09 - seem to be command
// 0x41, 0x40 - seem to be block referens
void SetTag15693Uid_v2(const uint8_t *uid) {
LED_A_ON();
uint8_t cmd[2][11] = {
// hf 15 raw -wac -d 02e00941 + uid first four bytes
{ISO15_REQ_DATARATE_HIGH, ISO15693_MAGIC_WRITE, 0x00, 0x09, 0x41, uid[7], uid[6], uid[5], uid[4], 0x00, 0x00},
// hf 15 raw -wac -d 02e00940 + uid last four bytes
{ISO15_REQ_DATARATE_HIGH, ISO15693_MAGIC_WRITE, 0x00, 0x09, 0x40, uid[3], uid[2], uid[1], uid[0], 0x00, 0x00}
};
AddCrc15(cmd[0], 9);
AddCrc15(cmd[1], 9);
uint8_t buf[ISO15693_MAX_RESPONSE_LENGTH] = {0x00};
uint32_t start_time = 0;
uint32_t eof_time = 0;
uint16_t recvlen = 0;
int res = PM3_SUCCESS;
for (int i = 0; i < 2; i++) {
res = SendDataTag(
cmd[i],
sizeof(cmd[i]),
(i == 0) ? true : false,
true,
buf,
sizeof(buf),
start_time,
ISO15693_READER_TIMEOUT_WRITE,
&eof_time,
&recvlen
);
start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
}
reply_ng(CMD_HF_ISO15693_CSETUID_V2, res, NULL, 0);
switch_off();
}
static void init_password_15693_Slix(uint8_t *buffer, const uint8_t *pwd, const uint8_t *rnd) {
memcpy(buffer, pwd, 4);
if (rnd) {
+1
View File
@@ -59,6 +59,7 @@ int SendDataTag(uint8_t *send, int sendlen, bool init, bool speed_fast, uint8_t
int SendDataTagEOF(uint8_t *recv, uint16_t max_recv_len, uint32_t start_time, uint16_t timeout, uint32_t *eof_time, bool fsk, bool recv_speed, uint16_t *resp_len);
void SetTag15693Uid(const uint8_t *uid);
void SetTag15693Uid_v2(const uint8_t *uid);
void WritePasswordSlixIso15693(const uint8_t *old_password, const uint8_t *new_password, uint8_t pwd_id);
void DisablePrivacySlixIso15693(const uint8_t *password);
+18 -9
View File
@@ -118,7 +118,9 @@ static size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) {
volatile uint8_t adc_val = AT91C_BASE_SSC->SSC_RHR;
if (g_logging) logSampleSimple(adc_val);
if (g_logging) {
logSampleSimple(adc_val);
}
// Only test field changes if state of adc values matter
if (wait == false) {
@@ -157,7 +159,10 @@ static size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) {
}
}
if (g_logging) logSampleSimple(0xFF);
if (g_logging) {
logSampleSimple(0xFF);
}
return 0;
}
@@ -210,16 +215,18 @@ void lf_init(bool reader, bool simulate, bool ledcontrol) {
sc->averaging = 0;
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc->divisor);
if (reader) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
} else {
if (simulate)
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC);
else
// Sniff
//FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE);
if (simulate) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC);
} else {
// Sniff
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC);
// FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE);
}
}
// Connect the A/D to the peak-detected low-frequency path.
@@ -261,7 +268,9 @@ void lf_init(bool reader, bool simulate, bool ledcontrol) {
uint32_t bufsize = 10000;
// use malloc
if (g_logging) initSampleBufferEx(&bufsize, true);
if (g_logging) {
initSampleBufferEx(&bufsize, true);
}
lf_sample_mean();
}
+11 -6
View File
@@ -246,12 +246,13 @@ void logSample(uint8_t sample, uint8_t decimation, uint8_t bits_per_sample, bool
**/
void LFSetupFPGAForADC(int divisor, bool reader_field) {
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
if ((divisor == 1) || (divisor < 0) || (divisor > 255))
if ((divisor == 1) || (divisor < 0) || (divisor > 255)) {
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_134); //~134kHz
else if (divisor == 0)
} else if (divisor == 0) {
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_125); //125kHz
else
} else {
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor);
}
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | (reader_field ? FPGA_LF_ADC_READER_FIELD : 0));
@@ -623,12 +624,14 @@ void doT55x7Acquisition(size_t sample_size, bool ledcontrol) {
// skip until first high samples begin to change
if (startFound || sample > T55xx_READ_LOWER_THRESHOLD + T55xx_READ_TOL) {
// if just found start - recover last sample
if (!startFound) {
if (startFound == false) {
dest[i++] = lastSample;
startFound = true;
}
// collect samples
dest[i++] = sample;
if (i < bufsize) {
dest[i++] = sample;
}
}
}
}
@@ -698,13 +701,15 @@ void doCotagAcquisition(void) {
firstlow = true;
}
++i;
if (sample > COTAG_ONE_THRESHOLD) {
dest[i] = 255;
++i;
} else if (sample < COTAG_ZERO_THRESHOLD) {
dest[i] = 0;
++i;
} else {
dest[i] = dest[i - 1];
++i;
}
}
}
+61 -18
View File
@@ -31,67 +31,110 @@ size_t nbytes(size_t nbits) {
}
//convert hex digit to integer
uint8_t hex2int(char hexchar) {
switch (hexchar) {
uint8_t hex2int(char x) {
switch (x) {
case '0':
return 0;
break;
case '1':
return 1;
break;
case '2':
return 2;
break;
case '3':
return 3;
break;
case '4':
return 4;
break;
case '5':
return 5;
break;
case '6':
return 6;
break;
case '7':
return 7;
break;
case '8':
return 8;
break;
case '9':
return 9;
break;
case 'a':
case 'A':
return 10;
break;
case 'b':
case 'B':
return 11;
break;
case 'c':
case 'C':
return 12;
break;
case 'd':
case 'D':
return 13;
break;
case 'e':
case 'E':
return 14;
break;
case 'f':
case 'F':
return 15;
break;
default:
return 0;
}
}
/*
The following methods comes from Rfidler sourcecode.
https://github.com/ApertureLabsLtd/RFIDler/blob/master/firmware/Pic32/RFIDler.X/src/
*/
// convert hex to sequence of 0/1 bit values
// returns number of bits converted
int hex2binarray(char *target, char *source) {
return hex2binarray_n(target, source, strlen(source));
}
int hex2binarray_n(char *target, char *source, int sourcelen) {
int count = 0;
// process 4 bits (1 hex digit) at a time
while (sourcelen--) {
char x = *(source++);
*(target++) = (x >> 7) & 1;
*(target++) = (x >> 6) & 1;
*(target++) = (x >> 5) & 1;
*(target++) = (x >> 4) & 1;
*(target++) = (x >> 3) & 1;
*(target++) = (x >> 2) & 1;
*(target++) = (x >> 1) & 1;
*(target++) = (x & 1);
count += 8;
}
return count;
}
int binarray2hex(const uint8_t *bs, int bs_len, uint8_t *hex) {
int count = 0;
int byte_index = 0;
// Clear output buffer
memset(hex, 0, bs_len >> 3);
for (int i = 0; i < bs_len; i++) {
// Set the appropriate bit in hex
if (bs[i] == 1) {
hex[byte_index] |= (1 << (7 - (count % 8)));
}
count++;
// Move to the next byte if 8 bits have been filled
if (count % 8 == 0) {
byte_index++;
}
}
return count;
}
void LEDsoff(void) {
LED_A_OFF();
LED_B_OFF();
+4 -1
View File
@@ -82,9 +82,12 @@
#endif
size_t nbytes(size_t nbits);
uint8_t hex2int(char hexchar);
int hex2binarray(char *target, char *source);
int hex2binarray_n(char *target, char *source, int sourcelen);
int binarray2hex(const uint8_t *bs, int bs_len, uint8_t *hex);
void LED(int led, int ms);
void LEDsoff(void);
void SpinOff(uint32_t pause);
+9 -46
View File
@@ -40,11 +40,7 @@ static bool TestKVV(void) {
bool res = memcmp(KeyKvv, kvv, CIPURSE_KVV_LENGTH) == 0;
if (res)
PrintAndLogEx(INFO, "kvv.............. " _GREEN_("passed"));
else
PrintAndLogEx(ERR, "kvv.............. " _RED_("fail"));
PrintAndLogEx(SUCCESS, "kvv.............. ( %s )", (res) ? _GREEN_("ok") : _RED_("fail"));
return res;
}
@@ -58,11 +54,7 @@ static bool TestISO9797M2(void) {
res = res && (FindISO9797M2PaddingDataLen(data, ddatalen) == 4);
if (res)
PrintAndLogEx(INFO, "ISO9797M2........ " _GREEN_("passed"));
else
PrintAndLogEx(ERR, "ISO9797M2........ " _RED_("fail"));
PrintAndLogEx(SUCCESS, "ISO9797M2........ ( %s )", (res) ? _GREEN_("ok") : _RED_("fail"));
return res;
}
@@ -92,11 +84,7 @@ static bool TestSMI(void) {
res = res && (CipurseCGetSMI(&ctx, false) == 0x88);
res = res && (CipurseCGetSMI(&ctx, true) == 0x89);
if (res)
PrintAndLogEx(INFO, "SMI.............. " _GREEN_("passed"));
else
PrintAndLogEx(ERR, "SMI.............. " _RED_("fail"));
PrintAndLogEx(SUCCESS, "SMI.............. ( %s )", (res) ? _GREEN_("ok") : _RED_("fail"));
return res;
}
@@ -115,15 +103,10 @@ static bool TestMIC(void) {
res = res && (CipurseCCheckMIC(TestData, 6, mic));
if (res)
PrintAndLogEx(INFO, "MIC.............. " _GREEN_("passed"));
else
PrintAndLogEx(ERR, "MIC.............. " _RED_("fail"));
PrintAndLogEx(SUCCESS, "MIC.............. ( %s )", (res) ? _GREEN_("ok") : _RED_("fail"));
return res;
}
static bool TestAuth(void) {
CipurseContext_t ctx = {0};
CipurseCClearContext(&ctx);
@@ -159,11 +142,7 @@ static bool TestAuth(void) {
uint8_t framekey[] = {0xCF, 0x6F, 0x3A, 0x47, 0xFC, 0xAC, 0x8D, 0x38, 0x25, 0x75, 0x8B, 0xFC, 0x8B, 0x61, 0x68, 0xF3};
res = res && (memcmp(ctx.frameKey, framekey, sizeof(framekey)) == 0);
if (res)
PrintAndLogEx(INFO, "Auth............. " _GREEN_("passed"));
else
PrintAndLogEx(ERR, "Auth............. " _RED_("fail"));
PrintAndLogEx(SUCCESS, "Auth............. ( %s )", (res) ? _GREEN_("ok") : _RED_("fail"));
return res;
}
@@ -211,11 +190,7 @@ static bool TestMAC(void) {
uint8_t framekey4[] = {0xA0, 0x65, 0x1A, 0x62, 0x56, 0x5D, 0xD7, 0xC9, 0x32, 0xAE, 0x1D, 0xE0, 0xCF, 0x8D, 0xC1, 0xB9};
res = res && (memcmp(ctx.frameKey, framekey4, sizeof(framekey4)) == 0);
if (res)
PrintAndLogEx(INFO, "channel MAC...... " _GREEN_("passed"));
else
PrintAndLogEx(ERR, "channel MAC...... " _RED_("fail"));
PrintAndLogEx(SUCCESS, "channel MAC...... ( %s )", (res) ? _GREEN_("ok") : _RED_("fail"));
return res;
}
@@ -259,11 +234,7 @@ static bool TestEncDec(void) {
res = res && (dstdatalen == 16);
res = res && (memcmp(dstdata, TestData, 16) == 0);
if (res)
PrintAndLogEx(INFO, "channel EncDec... " _GREEN_("passed"));
else
PrintAndLogEx(ERR, "channel EncDec... " _RED_("fail"));
PrintAndLogEx(SUCCESS, "channel EncDec... ( %s )", (res) ? _GREEN_("ok") : _RED_("fail"));
return res;
}
@@ -351,11 +322,7 @@ static bool TestAPDU(void) {
res = res && (memcmp(test6, dstdata, dstdatalen) == 0);
res = res && (sw == 0xccdd);
if (res)
PrintAndLogEx(INFO, "apdu............. " _GREEN_("passed"));
else
PrintAndLogEx(ERR, "apdu............. " _RED_("fail"));
PrintAndLogEx(SUCCESS, "apdu............. ( %s )", (res) ? _GREEN_("ok") : _RED_("fail"));
return res;
}
@@ -374,11 +341,7 @@ bool CIPURSETest(bool verbose) {
res = res && TestAPDU();
PrintAndLogEx(INFO, "---------------------------");
if (res)
PrintAndLogEx(SUCCESS, " Tests [ %s ]", _GREEN_("ok"));
else
PrintAndLogEx(FAILED, " Tests [ %s ]", _RED_("fail"));
PrintAndLogEx(SUCCESS, "Tests ( %s )", (res) ? _GREEN_("ok") : _RED_("fail"));
PrintAndLogEx(NORMAL, "");
return res;
}
+2 -15
View File
@@ -2769,7 +2769,7 @@ static int CmdAsn1Decoder(const char *Cmd) {
void *argtable[] = {
arg_param_begin,
arg_str0("d", NULL, "<hex>", "ASN1 encoded byte array"),
arg_lit0("t", "test", "perform selftest"),
arg_lit0("t", "test", "perform self test"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
@@ -2798,17 +2798,14 @@ static int CmdDiff(const char *Cmd) {
"data diff -w 4 -a hf-mfu-01020304.bin -b hf-mfu-04030201.bin\n"
"data diff -a fileA -b fileB\n"
"data diff -a fileA --eb\n"
// "data diff -a fileA --cb\n"
"data diff --fa fileA -b fileB\n"
"data diff --fa fileA --fb fileB\n"
// "data diff --ea --cb\n"
);
void *argtable[] = {
arg_param_begin,
arg_str0("a", NULL, "<fn>", "input file name A"),
arg_str0("b", NULL, "<fn>", "input file name B"),
// arg_lit0(NULL, "cb", "magic gen1 <hf mf csave>"),
arg_lit0(NULL, "eb", "emulator memory <hf mf esave>"),
arg_str0(NULL, "fa", "<fn>", "input spiffs file A"),
arg_str0(NULL, "fb", "<fn>", "input spiffs file B"),
@@ -2825,7 +2822,6 @@ static int CmdDiff(const char *Cmd) {
char filenameB[FILE_PATH_SIZE] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)filenameB, FILE_PATH_SIZE, &fnlenB);
// bool use_c = arg_get_lit(ctx, 3);
bool use_e = arg_get_lit(ctx, 3);
// SPIFFS filename A
@@ -2930,14 +2926,6 @@ static int CmdDiff(const char *Cmd) {
}
}
// dump magic card memory
/*
if (use_c) {
PrintAndLogEx(INFO, " To be implemented, feel free to contribute!");
return PM3_ENOTIMPL;
}
*/
size_t biggest = (datalenA > datalenB) ? datalenA : datalenB;
PrintAndLogEx(DEBUG, "data len: %zu A %zu B %zu", biggest, datalenA, datalenB);
@@ -2949,7 +2937,6 @@ static int CmdDiff(const char *Cmd) {
PrintAndLogEx(INFO, "inB null");
}
char hdr0[400] = {0};
int hdr_sln = (width * 4) + 2;
@@ -3395,7 +3382,7 @@ static int CmdAtrLookup(const char *Cmd) {
void *argtable[] = {
arg_param_begin,
arg_str0("d", NULL, "<hex>", "ASN1 encoded byte array"),
// arg_lit0("t", "test", "perform selftest"),
// arg_lit0("t", "test", "perform self test"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
+13 -3
View File
@@ -2735,11 +2735,14 @@ static int CmdHF15CSetUID(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 15 csetuid",
"Set UID for magic Chinese card (only works with such cards)\n",
"hf 15 csetuid -u E011223344556677");
"hf 15 csetuid -u E011223344556677 -> use gen1 command\n"
"hf 15 csetuid -u E011223344556677 --v2 -> use gen2 command"
);
void *argtable[] = {
arg_param_begin,
arg_str1("u", "uid", "<hex>", "UID, 8 hex bytes"),
arg_lit0("2", "v2", "Use gen2 magic command"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
@@ -2750,6 +2753,7 @@ static int CmdHF15CSetUID(const char *Cmd) {
int uidlen = 0;
CLIGetHexWithReturn(ctx, 1, payload.uid, &uidlen);
bool use_v2 = arg_get_lit(ctx, 2);
CLIParserFree(ctx);
if (uidlen != HF15_UID_LENGTH) {
@@ -2775,8 +2779,14 @@ static int CmdHF15CSetUID(const char *Cmd) {
PrintAndLogEx(INFO, "Writing...");
PacketResponseNG resp;
clearCommandBuffer();
SendCommandNG(CMD_HF_ISO15693_CSETUID, (uint8_t *)&payload, sizeof(payload));
if (WaitForResponseTimeout(CMD_HF_ISO15693_CSETUID, &resp, 2000) == false) {
uint16_t cmd = CMD_HF_ISO15693_CSETUID;
if (use_v2) {
cmd = CMD_HF_ISO15693_CSETUID_V2;
}
SendCommandNG(cmd, (uint8_t *)&payload, sizeof(payload));
if (WaitForResponseTimeout(cmd, &resp, 2000) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply");
DropField();
return PM3_ESOFT;
+2
View File
@@ -93,6 +93,8 @@ static int CmdHFCryptoRFSniff(const char *Cmd) {
clearCommandBuffer();
SendCommandNG(CMD_HF_ISO14443B_SNIFF, NULL, 0);
PacketResponseNG resp;
WaitForResponse(CMD_HF_ISO14443B_SNIFF, &resp);
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf cryptorf list") "` to view captured tracelog");
PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save -f hf_cryptorf_mytrace") "` to save tracelog for later analysing");
+8 -6
View File
@@ -2147,8 +2147,9 @@ static int CmdHFiClassDump(const char *Cmd) {
write_dump:
if (have_credit_key && pagemap != 0x01 && aa2_success == false)
if (have_credit_key && pagemap != 0x01 && aa2_success == false) {
PrintAndLogEx(INFO, "Reading AA2 failed. dumping AA1 data to file");
}
// print the dump
printIclassDumpContents(tag_data, 1, (bytes_got / 8), bytes_got, dense_output);
@@ -2852,8 +2853,8 @@ static int CmdHFiClass_loclass(const char *Cmd) {
void *argtable[] = {
arg_param_begin,
arg_str0("f", "file", "<fn>", "filename with nr/mac data from `hf iclass sim -t 2` "),
arg_lit0(NULL, "test", "Perform self-test"),
arg_lit0(NULL, "long", "Perform self-test, including long ones"),
arg_lit0(NULL, "test", "Perform self test"),
arg_lit0(NULL, "long", "Perform self test, including long ones"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
@@ -3776,9 +3777,10 @@ out:
static int CmdHFiClassLookUp(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf iclass lookup",
"Lookup keys takes some sniffed trace data and tries to verify what key was used against a dictionary file",
"This command take sniffed trace data and try to recovery a iCLASS Standard or iCLASS Elite key.",
"hf iclass lookup --csn 9655a400f8ff12e0 --epurse f0ffffffffffffff --macs 0000000089cb984b -f iclass_default_keys.dic\n"
"hf iclass lookup --csn 9655a400f8ff12e0 --epurse f0ffffffffffffff --macs 0000000089cb984b -f iclass_default_keys.dic --elite");
"hf iclass lookup --csn 9655a400f8ff12e0 --epurse f0ffffffffffffff --macs 0000000089cb984b -f iclass_default_keys.dic --elite"
);
void *argtable[] = {
arg_param_begin,
@@ -4628,9 +4630,9 @@ static int CmdHFiClassSAM(const char *Cmd) {
}
static command_t CommandTable[] = {
{"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"},
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"list", CmdHFiClassList, AlwaysAvailable, "List iclass history"},
// {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"},
{"-----------", CmdHelp, IfPm3Iclass, "------------------- " _CYAN_("Operations") " -------------------"},
// {"clone", CmdHFiClassClone, IfPm3Iclass, "Create a HID credential to Picopass / iCLASS tag"},
{"dump", CmdHFiClassDump, IfPm3Iclass, "Dump Picopass / iCLASS tag to file"},
+2 -2
View File
@@ -238,7 +238,7 @@ static void jooki_print(uint8_t *b64, uint8_t *result, bool verbose) {
static int jooki_selftest(void) {
PrintAndLogEx(INFO, "======== " _CYAN_("selftest") " ===========================================");
PrintAndLogEx(INFO, "======== " _CYAN_("self test") " ===========================================");
for (int i = 0; i < ARRAYLEN(jooks); i++) {
if (strlen(jooks[i].b64) == 0)
continue;
@@ -296,7 +296,7 @@ static int CmdHF14AJookiEncode(const char *Cmd) {
arg_param_begin,
arg_str0("u", "uid", "<hex>", "uid bytes"),
arg_lit0("r", NULL, "read uid from tag instead"),
arg_lit0("t", NULL, "selftest"),
arg_lit0("t", NULL, "self test"),
arg_lit0("v", "verbose", "verbose output"),
arg_lit0(NULL, "dragon", "figurine type"),
arg_lit0(NULL, "fox", "figurine type"),

Some files were not shown because too many files have changed in this diff Show More