Merge branch 'master' into dev_4x50_standalone

update
This commit is contained in:
tharexde 2021-02-12 23:21:49 +01:00
commit ac0ef23d5e
79 changed files with 2201 additions and 1396 deletions

View file

@ -4,6 +4,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
## [unreleased][unreleased]
- Added `LF_THAREXDE` standalone mode which simulates and reads EM4x50 cards (@tharexde)
- Added `hf jooki` commands (@iceman1001)
- Changed `wiegand encode` - format param is now optional, w/o it will try encode all formats (@iceman1001)
- Fix cppchecker warnings (@iceman1001)
- Added `trace list -t mf` - now can use external dictionary keys file
@ -132,6 +133,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Change, use system Whereami library if available (@doegox)
- Change, use system Zlib library if available (@doegox)
- Fix release version information (@doegox)
- Fix `lf gallagher read` - now correctly decodes card data
- Add support to `lf gallagher clone` and `lf gallagher sim` for writing specific card region, facility, card & issue numbers (@DarkMatterMatt)
## [ice coffee.4.9237][2020-05-21]
- Updated documentation (@doegox, @iceman1001)

View file

@ -191,7 +191,7 @@ void RunMod(void) {
read_successful = false;
break;
}
// We're skipping 14 blocks (56 bytes) here, as that "[...] has version/signature/counter data here" according to comments on hf_mfu_dumptoemulator
// We're skipping 14 blocks (56 bytes) here, as that "[...] has version/signature/counter data here" according to comments on data_mfu_bin2eml
// When converting a bin, it's almost all 0 other than one 0x0F byte, and functionality seems to be unaffected if that byte is set to 0x00.
emlSetMem_xt(dataout, 14 + i, 1, 4);
Dbhexdump(4, dataout, 0);

View file

@ -52,8 +52,8 @@ static void fill_buff(uint8_t bit) {
static void construct_EM410x_emul(uint64_t id) {
int i, j;
int binary[4] = {0,0,0,0};
int parity[4] = {0,0,0,0};
int binary[4] = {0, 0, 0, 0};
int parity[4] = {0, 0, 0, 0};
buflen = 0;
for (i = 0; i < 9; i++)

View file

@ -100,8 +100,8 @@ static void fill_buff(uint8_t bit) {
static void construct_EM410x_emul(uint64_t id) {
int i, j;
int binary[4] = {0,0,0,0};
int parity[4] = {0,0,0,0};
int binary[4] = {0, 0, 0, 0};
int parity[4] = {0, 0, 0, 0};
buflen = 0;
for (i = 0; i < 9; i++)

View file

@ -67,8 +67,8 @@ static void fill_buff(uint8_t bit) {
static void construct_EM410x_emul(uint64_t id) {
int i, j;
int binary[4] = {0,0,0,0};
int parity[4] = {0,0,0,0};
int binary[4] = {0, 0, 0, 0};
int parity[4] = {0, 0, 0, 0};
buflen = 0;
for (i = 0; i < 9; i++)

View file

@ -50,7 +50,7 @@
#include "crc16.h"
#ifdef WITH_LCD
#include "LCD.h"
#include "LCD_disabled.h"
#endif
#ifdef WITH_SMARTCARD

View file

@ -1489,7 +1489,7 @@ bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr *hdr, uint
memcpy(cmd_check + 1, payload->key, 8);
} else {
uint8_t div_key[8] = {0};
if (payload->use_raw)
memcpy(div_key, payload->key, 8);
@ -1885,7 +1885,7 @@ void iClass_WriteBlock(uint8_t *msg) {
res = false;
switch_off();
if (payload->req.send_reply)
reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_ETEAROFF, (uint8_t*)&res, sizeof(uint8_t));
reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_ETEAROFF, (uint8_t *)&res, sizeof(uint8_t));
return;
} else {
@ -1927,7 +1927,7 @@ out:
switch_off();
if (payload->req.send_reply)
reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_SUCCESS, (uint8_t*)&res, sizeof(uint8_t));
reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_SUCCESS, (uint8_t *)&res, sizeof(uint8_t));
}
void iClass_Restore(iclass_restore_req_t *msg) {

View file

@ -916,18 +916,25 @@ bool GetIso14443aCommandFromReader(uint8_t *received, uint8_t *par, int *len) {
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
(void)b;
uint16_t check = 0;
uint8_t flip = 0;
uint16_t checker = 0;
for (;;) {
if (check == 4000) {
// if (BUTTON_PRESS() || data_available())
WDT_HIT();
if (flip == 2) {
if (data_available())
return false;
flip = 0;
}
if (checker >= 4000) {
if (BUTTON_PRESS())
return false;
check = 0;
WDT_HIT();
flip++;
checker = 0;
}
++check;
++checker;
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
@ -1335,7 +1342,6 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data, uint8_t
LED_A_ON();
// main loop
//for (;;) {
bool finished = false;
bool button_pushed = BUTTON_PRESS();
while (!button_pushed && !finished) {

View file

@ -1009,7 +1009,7 @@ void CmdFSKsimTAGEx(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t cl
WDT_HIT();
Dbprintf("Simulating with fcHigh: %d, fcLow: %d, clk: %d, STT: %d, n: %d", fchigh, fclow, clk, separator, n);
Dbprintf("FSK simulating with rf/%d, fc high %d, fc low %d, STT %d, n %d", clk, fchigh, fclow, separator, n);
if (ledcontrol) LED_A_ON();
SimulateTagLowFrequencyEx(n, 0, ledcontrol, numcycles);
@ -1122,10 +1122,10 @@ void CmdASKsimTAG(uint8_t encoding, uint8_t invert, uint8_t separator, uint8_t c
WDT_HIT();
Dbprintf("Simulating with clk: %d, invert: %d, encoding: %s (%d), separator: %d, n: %d"
Dbprintf("ASK simulating with rf/%d, invert %d, encoding %s (%d), separator %d, n %d"
, clk
, invert
, (encoding == 2) ? "BI" : (encoding == 1) ? "ASK" : "RAW"
, (encoding == 2) ? "ASK/BI" : (encoding == 1) ? "ASK/MAN" : "RAW/MAN"
, encoding
, separator
, n
@ -1176,7 +1176,7 @@ void CmdPSKsimTAG(uint8_t carrier, uint8_t invert, uint8_t clk, uint16_t size, u
WDT_HIT();
Dbprintf("Simulating with Carrier: %d, clk: %d, invert: %d, n: %d", carrier, clk, invert, n);
Dbprintf("PSK simulating with rf/%d, fc/%d, invert %d, n %d", clk, carrier, invert, n);
if (ledcontrol) LED_A_ON();
SimulateTagLowFrequency(n, 0, ledcontrol);
@ -1220,7 +1220,7 @@ void CmdNRZsimTAG(uint8_t invert, uint8_t separator, uint8_t clk, uint16_t size,
WDT_HIT();
Dbprintf("Simulating with clk: %d, invert: %d, separator: %d, n: %d"
Dbprintf("NRZ simulating with rf/%d, invert %d, separator %d, n %d"
, clk
, invert
, separator
@ -1251,20 +1251,13 @@ int lf_hid_watch(int findone, uint32_t *high, uint32_t *low) {
BigBuf_Clear_keep_EM();
int res = PM3_SUCCESS;
uint16_t interval = 0;
while (BUTTON_PRESS() == false) {
for (;;) {
WDT_HIT();
// cancel w usb command.
if (interval == 4000) {
if (data_available()) {
res = PM3_EOPABORTED;
break;
}
interval = 0;
} else {
interval++;
if (data_available() || BUTTON_PRESS()) {
res = PM3_EOPABORTED;
break;
}
DoAcquisition_default(-1, false);
@ -1360,20 +1353,13 @@ int lf_awid_watch(int findone, uint32_t *high, uint32_t *low) {
LFSetupFPGAForADC(LF_DIVISOR_125, true);
int res = PM3_SUCCESS;
uint16_t interval = 0;
while (BUTTON_PRESS() == false) {
for (;;) {
WDT_HIT();
// cancel w usb command.
if (interval == 4000) {
if (data_available()) {
res = PM3_EOPABORTED;
break;
}
interval = 0;
} else {
interval++;
if (data_available() || BUTTON_PRESS()) {
res = PM3_EOPABORTED;
break;
}
DoAcquisition_default(-1, false);
@ -1465,19 +1451,12 @@ int lf_em410x_watch(int findone, uint32_t *high, uint64_t *low) {
LFSetupFPGAForADC(LF_DIVISOR_125, true);
int res = PM3_SUCCESS;
uint16_t interval = 0;
while (BUTTON_PRESS() == false) {
for (;;) {
WDT_HIT();
// cancel w usb command.
if (interval == 4000) {
if (data_available()) {
res = PM3_EOPABORTED;
break;
}
interval = 0;
} else {
interval++;
if (data_available() || BUTTON_PRESS()) {
res = PM3_EOPABORTED;
break;
}
DoAcquisition_default(-1, false);
@ -1541,20 +1520,13 @@ int lf_io_watch(int findone, uint32_t *high, uint32_t *low) {
LFSetupFPGAForADC(LF_DIVISOR_125, true);
int res = PM3_SUCCESS;
uint16_t interval = 0;
while (BUTTON_PRESS() == false) {
for (;;) {
WDT_HIT();
// cancel w usb command.
if (interval == 4000) {
if (data_available()) {
res = PM3_EOPABORTED;
break;
}
interval = 0;
} else {
interval++;
if (data_available() || BUTTON_PRESS()) {
res = PM3_EOPABORTED;
break;
}
DoAcquisition_default(-1, false);

View file

@ -73,11 +73,11 @@ void printSamples(void) {
void setSamplingConfig(sample_config *sc) {
// decimation (1-8) how many bits of adc sample value to save
if (sc->decimation > 0 && sc->decimation < 8)
if (sc->decimation > 0 && sc->decimation < 9)
config.decimation = sc->decimation;
// bits per sample (1-8)
if (sc->bits_per_sample > 0 && sc->bits_per_sample < 8)
if (sc->bits_per_sample > 0 && sc->bits_per_sample < 9)
config.bits_per_sample = sc->bits_per_sample;
//

View file

@ -68,7 +68,7 @@ uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data) {
// send X byte basic commands
int mifare_sendcmd(uint8_t cmd, uint8_t *data, uint8_t data_size, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing) {
uint8_t dcmd[data_size + 3];
dcmd[0] = cmd;
if (data_size > 0)

View file

@ -242,6 +242,7 @@ set (TARGET_SOURCES
${PM3_ROOT}/client/src/cmdhffelica.c
${PM3_ROOT}/client/src/cmdhffido.c
${PM3_ROOT}/client/src/cmdhficlass.c
${PM3_ROOT}/client/src/cmdhfjooki.c
${PM3_ROOT}/client/src/cmdhflegic.c
${PM3_ROOT}/client/src/cmdhflist.c
${PM3_ROOT}/client/src/cmdhflto.c

View file

@ -474,6 +474,7 @@ SRCS = aiddesfire.c \
cmdhffido.c \
cmdhficlass.c \
cmdhflegic.c \
cmdhfjooki.c \
cmdhflist.c \
cmdhflto.c \
cmdhfmf.c \

View file

@ -579,7 +579,7 @@ static SIMDExecInstr GetSIMDInstr(void) {
instr = SIMD_MMX;
else
#endif
instr = SIMD_NONE;
instr = SIMD_NONE;
return instr;
}

View file

@ -1283,4 +1283,13 @@ AABAFFCC7612
17D071403C20
#
534F4C415249
534f4c303232
534f4c303232
#
# Nespresso, smart card
# key-gen algo, these keys are for one card
ff9a84635bd2
6f30126ee7e4
6039abb101bb
f1a1239a4487
#
b882fd4a9f78

View file

@ -6,7 +6,7 @@ local ansicolors = require('ansicolors')
copyright = ''
author = 'Martin Holst Swende'
version = 'v1.0.2'
version = 'v1.0.3'
desc = [[
This script takes a dumpfile from 'hf mf dump' and converts it to a format that can be used
by the emulator
@ -46,7 +46,7 @@ end
---
-- This is only meant to be used when errors occur
local function oops(err)
print('ERROR:', err)
print('[!!] ERROR:', err)
core.clearCommandBuffer()
return nil, err
end
@ -134,7 +134,7 @@ local function main(args)
outfile:write(dumpdata:lower())
io.close(outfile)
print(('Wrote an emulator-dump to the file %s'):format(output))
print(('[+] Wrote an emulator-dump to the file %s'):format(output))
end

View file

@ -7,7 +7,7 @@ local ansicolors = require('ansicolors')
copyright = ''
author = 'Martin Holst Swende'
version = 'v1.0.2'
version = 'v1.0.3'
desc =[[
This script takes a dumpfile and produces a html based dump, which is a
bit more easily analyzed.
@ -45,7 +45,7 @@ end
---
-- This is only meant to be used when errors occur
local function oops(err)
print('ERROR:', err)
print('[!!] ERROR:', err)
core.clearCommandBuffer()
return nil, err
end
@ -76,7 +76,7 @@ local function main(args)
local filename, err = dumplib.convert_bin_to_html(input,output, 16)
if err then return oops(err) end
print(('Wrote a HTML dump to the file %s'):format(filename))
print(('[+] Wrote a HTML dump to the file %s'):format(filename))
end
--[[

View file

@ -5,7 +5,7 @@ local ansicolors = require('ansicolors')
copyright = ''
author = 'Iceman'
version = 'v1.0.2'
version = 'v1.0.3'
desc =[[
This script takes an dumpfile in EML (ASCII) format and converts it to the PM3 dumpbin file to be used with `hf mf restore`
]]
@ -40,7 +40,7 @@ end
---
-- This is only meant to be used when errors occur
local function oops(err)
print('ERROR:', err)
print('[!!] ERROR:', err)
core.clearCommandBuffer()
return nil, err
end
@ -82,7 +82,7 @@ local function main(args)
local filename, err = dumplib.convert_eml_to_bin(input,output)
if err then return oops(err) end
ExitMsg(('Wrote a BIN dump to the file %s'):format(filename))
ExitMsg(('[+] Wrote a BIN dump to the file %s'):format(filename))
end
main(args)

View file

@ -7,7 +7,7 @@ local ansicolors = require('ansicolors')
copyright = ''
author = 'Martin Holst Swende'
version = 'v1.0.2'
version = 'v1.0.3'
desc = [[
This script takes a dumpfile on EML (ASCII) format and produces a html based dump, which is a
bit more easily analyzed.
@ -44,7 +44,7 @@ end
---
-- This is only meant to be used when errors occur
local function oops(err)
print('ERROR:', err)
print('[!!] ERROR:', err)
core.clearCommandBuffer()
return nil, err
end
@ -75,7 +75,7 @@ local function main(args)
local filename, err = dumplib.convert_eml_to_html(input,output)
if err then return oops(err) end
print(('Wrote a HTML dump to the file %s'):format(filename))
print(('[+] Wrote a HTML dump to the file %s'):format(filename))
end
--[[

View file

@ -6,16 +6,16 @@ local ansicolors = require('ansicolors')
copyright = ''
author = "Martin Holst Swende \n @Marshmellow \n @iceman"
version = 'v1.0.2'
version = 'v1.0.4'
desc =[[
This script takes a dumpfile from 'hf mfu dump' and converts it to a format that can be used
by the emulator
]]
example = [[
script run hf_mfu_dumptoemulator -i dumpdata-foobar.bin
script run data_mfu_bin2eml -i dumpdata-foobar.bin
]]
usage = [[
script run hf_mfu_dumptoemulator [-i <file>] [-o <file>]
script run data_mfu_bin2eml [-i <file>] [-o <file>]
]]
arguments = [[
-h This help
@ -43,7 +43,7 @@ end
---
-- This is only meant to be used when errors occur
local function oops(err)
print('ERROR:', err)
print('[!!] ERROR:', err)
core.clearCommandBuffer()
return nil, err
end
@ -133,7 +133,7 @@ local function main(args)
outfile:write(dumpdata:lower())
io.close(outfile)
print(('Wrote an emulator-dump to the file %s'):format(output))
print(('[+] Wrote an emulator-dump to the file %s'):format(output))
end
--[[

View file

@ -4749,14 +4749,14 @@
"application": "Security and Access Control",
"company": "PEC (New Zealand) Ltd.",
"mad": "0x4811",
"service_provider": "Cardax",
"service_provider": "Cardax / Gallagher",
"system_integrator": ""
},
{
"application": "Security and Access Control",
"company": "PEC (New Zealand) Ltd.",
"mad": "0x4812",
"service_provider": "Cardax",
"service_provider": "Cardax / Gallagher",
"system_integrator": ""
},
{

View file

@ -13,6 +13,7 @@
#include <string.h>
#include <ctype.h> // tolower
#include <math.h>
#include <inttypes.h> // PRIx64 macro
#include "commonutil.h" // reflect...
#include "comms.h" // clearCommandBuffer
#include "cmdparser.h" // command_t
@ -550,6 +551,13 @@ static int CmdAnalyseA(const char *Cmd) {
PrintAndLogEx(FAILED, "Error parsing bytes");
return PM3_EINVARG;
}
uint64_t key = 0;
res = mfc_algo_touch_one(data, 0, 0, &key);
if (res == PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, "KEY A | %012" PRIx64, key);
}
CLIParserFree(ctx);
return PM3_SUCCESS;

View file

@ -25,6 +25,7 @@
#include "cmdhfemrtd.h" // eMRTD
#include "cmdhflegic.h" // LEGIC
#include "cmdhficlass.h" // ICLASS
#include "cmdhfjooki.h" // MFU based Jooki
#include "cmdhfmf.h" // CLASSIC
#include "cmdhfmfu.h" // ULTRALIGHT/NTAG etc
#include "cmdhfmfp.h" // Mifare Plus
@ -397,6 +398,7 @@ static command_t CommandTable[] = {
{"emrtd", CmdHFeMRTD, AlwaysAvailable, "{ Machine Readable Travel Document... }"},
{"felica", CmdHFFelica, AlwaysAvailable, "{ ISO18092 / FeliCa RFIDs... }"},
{"fido", CmdHFFido, AlwaysAvailable, "{ FIDO and FIDO2 authenticators... }"},
{"jooki", CmdHF_Jooki, AlwaysAvailable, "{ Jooki RFIDs... }"},
{"iclass", CmdHFiClass, AlwaysAvailable, "{ ICLASS RFIDs... }"},
{"legic", CmdHFLegic, AlwaysAvailable, "{ LEGIC RFIDs... }"},
{"lto", CmdHFLTO, AlwaysAvailable, "{ LTO Cartridge Memory RFIDs... }"},

View file

@ -1422,7 +1422,8 @@ typedef enum {
MTDESFIRE = 4,
MTPLUS = 8,
MTULTRALIGHT = 16,
MTOTHER = 32
HID_SEOS = 32,
MTOTHER = 64
} nxp_mifare_type_t;
// Based on NXP AN10833 Rev 3.6 and NXP AN10834 Rev 4.1
@ -1525,11 +1526,17 @@ static int detect_nxp_card(uint8_t sak, uint16_t atqa, uint64_t select_status) {
type |= MTPLUS;
}
} else {
printTag("MIFARE Plus EV1 2K/4K in SL3");
printTag("MIFARE Plus S 2K/4K in SL3");
printTag("MIFARE Plus X 2K/4K in SL3");
printTag("MIFARE Plus SE 1K");
type |= MTPLUS;
if ((atqa & 0x0001) == 0x0001) {
printTag("HID SEOS (smartmx / javacard)");
type |= HID_SEOS;
} else {
printTag("MIFARE Plus EV1 2K/4K in SL3");
printTag("MIFARE Plus S 2K/4K in SL3");
printTag("MIFARE Plus X 2K/4K in SL3");
printTag("MIFARE Plus SE 1K");
type |= MTPLUS;
}
}
printTag("NTAG 4xx");
@ -1634,6 +1641,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
bool isMifarePlus = false;
bool isMifareUltralight = false;
bool isST = false;
bool isEMV = false;
int nxptype = MTNONE;
if (card.uidlen <= 4) {
@ -2048,6 +2056,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
if (verbose) PrintAndLogEx(SUCCESS, "----------------------------------------------------");
found = true;
isEMV = true;
}
}
@ -2097,15 +2106,18 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
if (isMifareUltralight)
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfu info`"));
if (isMifarePlus && isMagic == 0)
if (isMifarePlus && isMagic == 0 && isEMV == false)
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfp info`"));
if (isMifareDESFire && isMagic == 0)
if (isMifareDESFire && isMagic == 0 && isEMV == false)
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfdes info`"));
if (isST)
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf st info`"));
if (isEMV)
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`emv search -s`"));
PrintAndLogEx(NORMAL, "");
DropField();
return select_status;
@ -2309,7 +2321,7 @@ static command_t CommandTable[] = {
{"raw", CmdHF14ACmdRaw, IfPm3Iso14443a, "Send raw hex data to tag"},
{"antifuzz", CmdHF14AAntiFuzz, IfPm3Iso14443a, "Fuzzing the anticollision phase. Warning! Readers may react strange"},
{"config", CmdHf14AConfig, IfPm3Iso14443a, "Configure 14a settings (use with caution)"},
{"apdufind", CmdHf14AFindapdu, IfPm3Iso14443a, "Enuerate APDUs - CLA/INS/P1P2"},
{"apdufind", CmdHf14AFindapdu, IfPm3Iso14443a, "Enumerate APDUs - CLA/INS/P1P2"},
{NULL, NULL, NULL, NULL}
};

View file

@ -202,7 +202,7 @@ static bool wait_cmd_14b(bool verbose, bool is_select) {
(crc) ? _GREEN_("ok") : _RED_("fail")
);
} else if (len == 0) {
PrintAndLogEx(INFO, "no response from tag");
PrintAndLogEx(INFO, "no response from tag");
} else {
PrintAndLogEx(SUCCESS, "%s", sprint_hex(data, len));
}

View file

@ -1338,19 +1338,26 @@ static int emrtd_print_ef_dg1_info(uint8_t *data, size_t datalen) {
// Determine and print the document type
if (mrz[0] == 'I' && mrz[1] == 'P') {
td_variant = 1;
PrintAndLogEx(SUCCESS, "Document Type.........: " _YELLOW_("Passport Card"));
} else if (mrz[0] == 'I') {
td_variant = 1;
PrintAndLogEx(SUCCESS, "Document Type.........: " _YELLOW_("ID Card"));
} else if (mrz[0] == 'P') {
td_variant = 3;
PrintAndLogEx(SUCCESS, "Document Type.........: " _YELLOW_("Passport"));
} else if (mrz[0] == 'A') {
PrintAndLogEx(SUCCESS, "Document Type.........: " _YELLOW_("German Residency Permit"));
} else {
td_variant = 1;
PrintAndLogEx(SUCCESS, "Document Type.........: " _YELLOW_("Unknown"));
PrintAndLogEx(INFO, "Assuming ID-style MRZ.");
}
if (mrzlen == 90) {
td_variant = 1;
} else if (mrzlen == 88) {
td_variant = 3;
} else {
PrintAndLogEx(ERR, "MRZ length (%zu) is wrong.", mrzlen);
return PM3_ESOFT;
}
PrintAndLogEx(SUCCESS, "Document Form Factor..: " _YELLOW_("TD%i"), td_variant);
// Print the MRZ

518
client/src/cmdhfjooki.c Normal file
View file

@ -0,0 +1,518 @@
//-----------------------------------------------------------------------------
// Ultralight Code (c) 2021 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.
//-----------------------------------------------------------------------------
// High frequency MIFARE ULTRALIGHT / Jooki commands
//-----------------------------------------------------------------------------
#include "cmdhfjooki.h"
#include <ctype.h>
#include <string.h> // memset
#include "commonutil.h" // ARRAYLEN
#include "ui.h" // PrintAndLog
#include "cmdparser.h"
#include "generator.h"
#include "base64.h"
#include "mifare/ndef.h" // print decode ndef
#include "mifare/mifarehost.h" // mfemlsetmem_xt
#include "cliparser.h"
#include "cmdhfmfu.h"
#include "cmdmain.h"
#include "fileutils.h" // convert_mfu..
static int CmdHelp(const char *Cmd);
typedef struct {
uint8_t uid[7];
const char b64[17];
uint8_t tagtype;
} PACKED jooki_t;
// sample set for selftest.
jooki_t jooks[] = {
{ {0x04, 0xDA, 0xB7, 0x6A, 0xE7, 0x4C, 0x80}, "ruxow8lnn88uyeX+", 0x00},
{ {0x04, 0xf0, 0x22, 0xc2, 0x33, 0x5e, 0x80}, "\0" , 0x00},
{ {0x04, 0x8C, 0xEC, 0xDA, 0xF0, 0x4A, 0x80}, "ONrsVf7jX6IaSNV6", 0x01},
{ {0x04, 0x92, 0xA7, 0x6A, 0xE7, 0x4C, 0x81}, "Hjjpcx/mZwuveTF+", 0x02},
{ {0x04, 0xD0, 0xB0, 0x3A, 0xD3, 0x63, 0x80}, "\0", 0x02},
{ {0x04, 0x96, 0x42, 0xDA, 0xF0, 0x4A, 0x80}, "vEWy0WO9wZNEzEok", 0x03},
{ {0x04, 0x33, 0xb5, 0x62, 0x39, 0x4d, 0x80}, "\0", 0x03},
{ {0x04, 0x17, 0xB7, 0x3A, 0xD3, 0x63, 0x81}, "f0axEma+g2WnLGAm", 0x05},
{ {0x04, 0x84, 0x27, 0x6A, 0xE7, 0x4C, 0x80}, "VZB/OLBwOiM5Mpnp", 0x05},
{ {0x04, 0x28, 0xF4, 0xDA, 0xF0, 0x4A, 0x81}, "7WzlgEzqLgwTnWNy", 0x05},
};
const char *jooks_figures[] = {"Dragon", "Fox", "Ghost", "Knight", "?", "Whale"};
const uint8_t jooki_secret[] = {0x20, 0x20, 0x20, 0x6D, 0x24, 0x0B, 0xEB, 0x94, 0x2C, 0x80, 0x45, 0x16};
const uint8_t NFC_SECRET[] = { 0x03, 0x9c, 0x25, 0x6f, 0xb9, 0x2e, 0xe8, 0x08, 0x09, 0x83, 0xd9, 0x33, 0x56};
#define JOOKI_UID_LEN 7
#define JOOKI_IV_LEN 4
#define JOOKI_B64_LEN (16 + 1)
#define JOOKI_PLAIN_LEN 12
static int jooki_encode(uint8_t *iv, uint8_t tagtype, uint8_t *uid, uint8_t *out) {
if (out == NULL) {
PrintAndLogEx(ERR, "(encode jooki) base64ndef param is NULL");
return PM3_EINVARG;
}
out[0] = 0x00;
if (iv == NULL || uid == NULL) {
PrintAndLogEx(ERR, "(encode jooki) iv or uid param is NULL");
return PM3_EINVARG;
}
uint8_t d[JOOKI_PLAIN_LEN] = {iv[0], iv[1],iv[2], iv[3], tagtype, uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6]};
uint8_t enc[JOOKI_PLAIN_LEN] = {0};
for (uint8_t i = 0; i < JOOKI_PLAIN_LEN; i++) {
if (i < 3)
enc[i] = d[i] ^ NFC_SECRET[i];
else
enc[i] = d[i] ^ NFC_SECRET[i] ^ d[i % 3];
}
PrintAndLogEx(DEBUG, "encoded result.... %s", sprint_hex(enc, sizeof(enc)));
size_t b64len = 0;
uint8_t b64[20];
memset(b64, 0, 20);
mbedtls_base64_encode(b64, sizeof(b64), &b64len, (const unsigned char*)enc, sizeof(enc));
memcpy(out, b64, b64len);
return PM3_SUCCESS;
}
static int jooki_decode(uint8_t *b64, uint8_t *result) {
uint8_t ndef[JOOKI_PLAIN_LEN] = {0};
size_t outputlen = 0;
mbedtls_base64_decode(ndef, sizeof(ndef), &outputlen, (const unsigned char*)b64, 16);
PrintAndLogEx(DEBUG, "(decode_jooki) raw encoded... " _GREEN_("%s"), sprint_hex(ndef, sizeof(ndef)));
for (uint8_t i = 0; i < JOOKI_PLAIN_LEN; i++) {
if (i < 3)
result[i] = ndef[i] ^ NFC_SECRET[i];
else
result[i] = ndef[i] ^ NFC_SECRET[i] ^ ndef[i % 3] ^ NFC_SECRET[i % 3];
}
PrintAndLogEx(DEBUG, "(decode_jooki) plain......... %s", sprint_hex(result, sizeof(ndef)));
return PM3_SUCCESS;
}
static int jooki_create_ndef(uint8_t *b64ndef, uint8_t *ndefrecord) {
// sample of url: https://s.jooki.rocks/s/?s=ONrsVf7jX6IaSNV6
if (ndefrecord == NULL) {
PrintAndLogEx(ERR, "(jooki_create_ndef) ndefrecord param is NULL");
return PM3_EINVARG;
}
memcpy(ndefrecord,
"\x01\x03\xa0\x0c\x34\x03\x29\xd1"
"\x01\x25\x55\x04\x73\x2e\x6a\x6f"
"\x6f\x6b\x69\x2e\x72\x6f\x63\x6b"
"\x73\x2f\x73\x2f\x3f\x73\x3d", 31);
memcpy(ndefrecord + 31, b64ndef, 16);
memcpy(ndefrecord + 47, "\x0a\xFE\x00\x00\x00", 5);
return PM3_SUCCESS;
}
static void jooki_printEx(uint8_t *b64, uint8_t *iv, uint8_t tt, uint8_t *uid, bool verbose) {
PrintAndLogEx(INFO, "Encoded URL.. %s ( %s )", sprint_hex(b64, 12), b64);
PrintAndLogEx(INFO, "Figurine..... %02x - " _GREEN_("%s"), tt, jooks_figures[tt]);
PrintAndLogEx(INFO, "iv........... %s", sprint_hex(iv, JOOKI_IV_LEN));
PrintAndLogEx(INFO, "uid.......... %s", sprint_hex(uid, JOOKI_UID_LEN));
uint8_t ndefmsg[52] = {0};
jooki_create_ndef(b64, ndefmsg);
PrintAndLogEx(INFO, "NDEF raw..... %s", sprint_hex_inrow(ndefmsg, sizeof(ndefmsg)));
if (verbose) {
int res = NDEFRecordsDecodeAndPrint(ndefmsg, sizeof(ndefmsg));
if (res != PM3_SUCCESS) {
NDEFDecodeAndPrint(ndefmsg, sizeof(ndefmsg), verbose);
}
}
}
static void jooki_print(uint8_t *b64, uint8_t *result, bool verbose) {
if (b64 == NULL || result == NULL)
return;
uint8_t iv[JOOKI_IV_LEN] = {0};
uint8_t uid[JOOKI_UID_LEN] = {0};
memcpy(iv, result, sizeof(iv));
uint8_t tt = result[4];
memcpy(uid, result + 5, sizeof(uid));
jooki_printEx(b64, iv, tt, uid, verbose);
}
static int jooki_selftest(void) {
PrintAndLogEx(INFO, "======== " _CYAN_("selftest") " ===========================================");
for (int i = 0; i < ARRAYLEN(jooks); i++) {
if (strlen(jooks[i].b64) == 0)
continue;
uint8_t iv[JOOKI_IV_LEN] = {0};
uint8_t uid[JOOKI_UID_LEN] = {0};
uint8_t result[JOOKI_PLAIN_LEN] = {0};
jooki_decode((uint8_t*)jooks[i].b64, result);
memcpy(iv, result, 4);
uint8_t tt = result[4];
memcpy(uid, result + 5, sizeof(uid));
bool tt_ok = (tt == jooks[i].tagtype);
bool uid_ok = (memcmp(uid, jooks[i].uid, sizeof(uid)) == 0);
PrintAndLogEx(INFO, "Encoded URL.. %s ( %s )", sprint_hex((const uint8_t*)jooks[i].b64, 12), jooks[i].b64);
PrintAndLogEx(INFO, "Figurine..... %02x - " _GREEN_("%s") " ( %s )", tt, jooks_figures[tt], tt_ok ? _GREEN_("ok") : _RED_("fail"));
PrintAndLogEx(INFO, "iv........... %s", sprint_hex(iv, sizeof(iv)));
PrintAndLogEx(INFO, "uid.......... %s ( %s )", sprint_hex(uid, sizeof(uid)), uid_ok ? _GREEN_("ok") : _RED_("fail"));
uint8_t b64[JOOKI_B64_LEN] = {0};
memset(b64, 0, sizeof(b64));
jooki_encode(iv, tt, uid, b64);
uint8_t ndefmsg[52] = {0};
jooki_create_ndef(b64, ndefmsg);
PrintAndLogEx(INFO, "NDEF raw .... %s", sprint_hex(ndefmsg, sizeof(ndefmsg)));
int status = NDEFRecordsDecodeAndPrint(ndefmsg, sizeof(ndefmsg));
if ( status != PM3_SUCCESS) {
status = NDEFDecodeAndPrint(ndefmsg, sizeof(ndefmsg), true);
}
PrintAndLogEx(INFO, "==================================================================");
}
return PM3_SUCCESS;
}
static int CmdHF14AJookiEncode(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf jooki encode",
"Encode a Jooki token to base64 NDEF URI format",
"hf jooki encode -t --> selftest\n"
"hf jooki encode -r --dragon --> read uid from tag and use for encoding\n"
"hf jooki encode --uid 04010203040506 --dragon"
);
void *argtable[] = {
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("v", "verbose", "verbose output"),
arg_lit0(NULL, "dragon", "tag type"),
arg_lit0(NULL, "fox", "tag type"),
arg_lit0(NULL, "ghost", "tag type"),
arg_lit0(NULL, "knight", "tag type"),
arg_lit0(NULL, "whale", "tag type"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int ulen = 0;
uint8_t uid[JOOKI_UID_LEN] = {0x00};
memset(uid, 0x0, sizeof(uid));
int res = CLIParamHexToBuf(arg_get_str(ctx, 1), uid, sizeof(uid), &ulen);
if (res) {
CLIParserFree(ctx);
return PM3_EINVARG;
}
bool use_tag = arg_get_lit(ctx, 2);
bool selftest = arg_get_lit(ctx, 3);
bool verbose = arg_get_lit(ctx, 4);
bool tt_dragon = arg_get_lit(ctx, 5);
bool tt_fox = arg_get_lit(ctx, 6);
bool tt_ghost = arg_get_lit(ctx, 7);
bool tt_knight = arg_get_lit(ctx, 8);
bool tt_whale = arg_get_lit(ctx, 9);
CLIParserFree(ctx);
if (selftest) {
return jooki_selftest();
}
if ((tt_dragon + tt_fox + tt_ghost + tt_knight + tt_whale) > 1) {
PrintAndLogEx(ERR, "Select one tag type");
return PM3_EINVARG;
}
uint8_t tt = 0;
if (tt_fox)
tt = 1;
if (tt_ghost)
tt = 2;
if (tt_knight)
tt = 3;
if (tt_whale)
tt = 5;
uint8_t iv[JOOKI_IV_LEN] = {0x80, 0x77, 0x51, 1};
if (use_tag) {
res = ul_read_uid(uid);
if (res != PM3_SUCCESS) {
return res;
}
} else {
if (ulen != JOOKI_UID_LEN) {
PrintAndLogEx(ERR, "Wrong length of UID, expect %u, got %d", JOOKI_UID_LEN, ulen);
return PM3_EINVARG;
}
}
uint8_t b64[JOOKI_B64_LEN] = {0};
memset(b64, 0, sizeof(b64));
jooki_encode(iv, tt, uid, b64);
jooki_printEx(b64, iv, tt, uid, verbose);
return PM3_SUCCESS;
}
static int CmdHF14AJookiDecode(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf jooki decode",
"Decode a base64-encode Jooki token in NDEF URI format",
"hf jooki decode -d 7WzlgEzqLgwTnWNy"
);
void *argtable[] = {
arg_param_begin,
arg_str1("d", "data", "<base64>", "base64 url parameter"),
arg_lit0("v", "verbose", "verbose output"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int dlen = 16;
uint8_t b64[JOOKI_B64_LEN] = {0x00};
memset(b64, 0x0, sizeof(b64));
CLIGetStrWithReturn(ctx, 1, b64, &dlen);
bool verbose = arg_get_lit(ctx, 2);
CLIParserFree(ctx);
uint8_t result[JOOKI_PLAIN_LEN] = {0};
int res = jooki_decode(b64, result);
if (res == PM3_SUCCESS) {
jooki_print(b64, result, verbose);
}
return PM3_SUCCESS;
}
static int CmdHF14AJookiSim(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf jooki sim",
"Simulate a Jooki token. Either `hf mfu eload` before or use `-d` param",
"hf jooki sim --> using eload before\n"
"hf jooki sim -d 7WzlgEzqLgwTnWNy"
);
void *argtable[] = {
arg_param_begin,
arg_str0("d", "data", "<base64>", "base64 url parameter"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int dlen = 16;
uint8_t b64[JOOKI_B64_LEN] = {0x00};
memset(b64, 0x0, sizeof(b64));
CLIGetStrWithReturn(ctx, 1, b64, &dlen);
CLIParserFree(ctx);
uint8_t result[JOOKI_PLAIN_LEN] = {0};
int res = jooki_decode(b64, result);
if (res != PM3_SUCCESS) {
return res;
}
jooki_print(b64, result, false);
// hf mfu sim...
uint8_t *data = calloc(144, sizeof(uint8_t));
// copy UID from base64 url parameter
memcpy(data, result + 5, 3);
// bbc0
data[3] = 0x88 ^ data[0] ^ data[1] ^ data[2];
memcpy(data + (1*4), result + 8, 4);
// bbc1
data[8] = data[4] ^ data[5] ^ data[6] ^ data[7];
// copy NDEF magic firs, skip BBC1
memcpy(data + (2*4) + 1, "\x48\x00\x00\xE1\x10\x12\x00", 7);
// copy raw NDEF
jooki_create_ndef(b64, data + (4 * 4));
// convert plain or old mfu format to new format
size_t datalen = 144;
res = convert_mfu_dump_format(&data, &datalen, true);
if (res != PM3_SUCCESS) {
PrintAndLogEx(FAILED, "Failed convert on load to new Ultralight/NTAG format");
free(data);
return res;
}
mfu_dump_t *mfu_dump = (mfu_dump_t *)data;
memcpy(mfu_dump->version, "\x00\x04\x04\x02\x01\x00\x0F\x03", 8);
mfu_dump->counter_tearing[2][3] = 0xBD;
mfu_dump->pages = 0x2c;
printMFUdumpEx(mfu_dump, mfu_dump->pages + 1, 0);
// upload to emulator memory
PrintAndLogEx(INFO, "Uploading to emulator memory");
PrintAndLogEx(INFO, "." NOLF);
// fast push mode
conn.block_after_ACK = true;
uint8_t blockwidth = 4, counter = 0, blockno = 0;
while (datalen) {
if (datalen == blockwidth) {
// Disable fast mode on last packet
conn.block_after_ACK = false;
}
if (mfEmlSetMem_xt(data + counter, blockno, 1, blockwidth) != PM3_SUCCESS) {
PrintAndLogEx(FAILED, "Cant set emul block: %3d", blockno);
free(data);
return PM3_ESOFT;
}
PrintAndLogEx(NORMAL, "." NOLF);
fflush(stdout);
blockno++;
counter += blockwidth;
datalen -= blockwidth;
}
PrintAndLogEx(NORMAL, "\n");
struct {
uint8_t tagtype;
uint8_t flags;
uint8_t uid[10];
uint8_t exitAfter;
} PACKED payload;
// NTAG, 7 byte UID in eloaded data.
payload.tagtype = 7;
payload.flags = FLAG_7B_UID_IN_DATA;
payload.exitAfter = 0;
clearCommandBuffer();
SendCommandNG(CMD_HF_ISO14443A_SIMULATE, (uint8_t *)&payload, sizeof(payload));
PacketResponseNG resp;
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " or pm3-button to abort simulation");
for (;;) {
if (kbd_enter_pressed()) {
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
PrintAndLogEx(DEBUG, "User aborted");
break;
}
if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == 0)
continue;
if (resp.status != PM3_SUCCESS)
break;
}
free(data);
PrintAndLogEx(INFO, "Done");
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf 14a list") "` to view trace log" );
return PM3_SUCCESS;
}
static int CmdHF14AJookiWrite(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf jooki write",
"Write a Jooki token to a Ultralight or NTAG tag",
"hf jooki write -d xxxxxxxx -> where x is raw NDEF from encode command"
);
void *argtable[] = {
arg_param_begin,
arg_str1("d", "data", "<hex>", "bytes"),
arg_str0("p", "pwd", "<hex>", "password for authentication (EV1/NTAG 4 bytes)"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
int dlen = 0;
uint8_t data[52] = {0x00};
memset(data, 0x0, sizeof(data));
int res = CLIParamHexToBuf(arg_get_str(ctx, 1), data, sizeof(data), &dlen);
if (res) {
CLIParserFree(ctx);
PrintAndLogEx(FAILED, "Error parsing bytes");
return PM3_EINVARG;
}
int plen = 0;
uint8_t pwd[4] = {0x00};
CLIGetHexWithReturn(ctx, 2, pwd, &plen);
CLIParserFree(ctx);
if (dlen != 52) {
PrintAndLogEx(ERR, "Wrong data length. Expected 52 got %d", dlen);
return PM3_EINVARG;
}
bool has_pwd = false;
if (plen == 4) {
has_pwd = true;
}
// 0 - no authentication
// 2 - pwd (4 bytes)
uint8_t keytype = 0, blockno = 4, i = 0;
while ((i * 4) < dlen) {
uint8_t cmddata[8] = {0};
memcpy(cmddata, data + (i * 4), 4);
if (has_pwd) {
memcpy(cmddata + 4, pwd, 4);
keytype = 2;
}
clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, blockno, keytype, 0, cmddata, sizeof(cmddata));
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
uint8_t isOK = resp.oldarg[0] & 0xff;
PrintAndLogEx(SUCCESS, "Write block %d ( %s )", blockno, isOK ? _GREEN_("ok") : _RED_("fail"));
} else {
PrintAndLogEx(WARNING, "Command execute timeout");
}
blockno++;
i++;
}
return PM3_SUCCESS;
}
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"encode", CmdHF14AJookiEncode, AlwaysAvailable, "Encode Jooki token"},
{"decode", CmdHF14AJookiDecode, AlwaysAvailable, "Decode Jooki token"},
{"sim", CmdHF14AJookiSim, IfPm3Iso14443a, "Simulate Jooki token"},
{"write", CmdHF14AJookiWrite, IfPm3Iso14443a, "Write a Jooki token"},
{NULL, NULL, NULL, NULL}
};
static int CmdHelp(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
CmdsHelp(CommandTable);
return PM3_SUCCESS;
}
int CmdHF_Jooki(const char *Cmd) {
clearCommandBuffer();
return CmdsParse(CommandTable, Cmd);
}

16
client/src/cmdhfjooki.h Normal file
View file

@ -0,0 +1,16 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2021 iceman1001
//
// 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.
//-----------------------------------------------------------------------------
// High frequency ISO14443A / MFU / Jooki commands
//-----------------------------------------------------------------------------
#ifndef CMDHFJOOKI_H__
#define CMDHFJOOKI_H__
#include "common.h"
int CmdHF_Jooki(const char *Cmd);
#endif

View file

@ -3983,6 +3983,63 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) {
return PM3_SUCCESS;
}
static int CmdHF14ADesBruteApps(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfdes bruteaid",
"Recover AIDs by bruteforce.\n"
"WARNING: This command takes a long time",
"hf mfdes bruteaid -> Search all apps\n"
"hf mfdes bruteaid -s F0000F -i 16 -> Search MAD range manually");
void *argtable[] = {
arg_param_begin,
arg_strx0("s", "start", "<hex>", "Starting App ID as hex bytes (3 bytes,big endian)"),
arg_strx0("e", "end", "<hex>", "Last App ID as hex bytes (3 bytes,big endian)"),
arg_int0("i", "step", "<dec>", "Increment step when bruteforcing (decimal integer)"),
arg_lit0("m", "mad", "Only bruteforce the MAD range"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
uint8_t startAid[3] = {0};
uint8_t endAid[3] = {0xFF, 0xFF, 0xFF};
int startLen = 0;
int endLen = 0;
CLIGetHexWithReturn(ctx, 1, startAid, &startLen);
CLIGetHexWithReturn(ctx, 2, endAid, &endLen);
uint32_t idIncrement = arg_get_int_def(ctx, 3, 1);
bool mad = arg_get_lit(ctx, 4);
CLIParserFree(ctx);
// TODO: We need to check the tag version, EV1 should stop after 26 apps are found
if (mad) {
idIncrement = 0x10;
startAid[0] = 0xF0;
startAid[1] = 0x00;
startAid[2] = 0x0F;
}
uint32_t idStart = le24toh(startAid);
uint32_t idEnd = le24toh(endAid);
PrintAndLogEx(INFO, "Enumerating through all AIDs manually, this will take a while!");
for (uint32_t id = idStart; id <= idEnd && id >= idStart; id += idIncrement) {
if (kbd_enter_pressed()) break;
int progress = ((id - idStart) * 100) / ((idEnd - idStart));
PrintAndLogEx(INPLACE, "Progress: %d %%, current AID: %06X", progress, id);
uint8_t appId[3] = {0};
htole24(id, appId);
sAPDU apdu = {0x90, MFDES_SELECT_APPLICATION, 0x00, 0x00, 0x03, appId}; //0x5a
uint16_t sw = 0;
uint8_t data[255 * 5] = {0x00};
uint32_t resplen = 0;
DESFIRESendApdu(!tag->rf_field_on, true, apdu, data, sizeof(data), &resplen, &sw);
if (sw == status(MFDES_S_OPERATION_OK)) {
printf("\33[2K\r"); // clear current line before printing
PrintAndLogEx(SUCCESS, "Got new APPID %06X", id);
}
}
PrintAndLogEx(SUCCESS, "Done");
DropFieldDesfire();
return PM3_SUCCESS;
}
static int CmdHF14ADesChangeKey(const char *Cmd) {
//DropFieldDesfire();
// NR DESC KEYLENGHT
@ -4924,6 +4981,7 @@ static command_t CommandTable[] = {
// {"ndef", CmdHF14aDesNDEF, IfPm3Iso14443a, "Prints NDEF records from card"},
// {"mad", CmdHF14aDesMAD, IfPm3Iso14443a, "Prints MAD records from card"},
{"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("AID") " -----------------------"},
{"bruteaid", CmdHF14ADesBruteApps, IfPm3Iso14443a, "Recover AIDs by bruteforce"},
{"createaid", CmdHF14ADesCreateApp, IfPm3Iso14443a, "Create Application ID"},
{"deleteaid", CmdHF14ADesDeleteApp, IfPm3Iso14443a, "Delete Application ID"},
{"selectaid", CmdHF14ADesSelectApp, IfPm3Iso14443a, "Select Application ID"},

View file

@ -115,6 +115,36 @@ static char *getUlev1CardSizeStr(uint8_t fsize) {
return buf;
}
int ul_read_uid(uint8_t *uid) {
if (uid == NULL) {
PrintAndLogEx(WARNING, "NUll parameter UID");
return PM3_ESOFT;
}
// read uid from tag
clearCommandBuffer();
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_RATS, 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
if (select_status == 0) {
PrintAndLogEx(WARNING, "iso14443a card select failed");
return PM3_ESOFT;
}
if (card.uidlen != 7) {
PrintAndLogEx(WARNING, "Wrong sized UID, expected 7bytes got %d", card.uidlen);
return PM3_ESOFT;
}
memcpy(uid, card.uid, 7);
return PM3_SUCCESS;
}
static void ul_switch_on_field(void) {
clearCommandBuffer();
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0);
@ -1102,7 +1132,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
CLIParserFree(ctx);
if (ak_len) {
if (ak_len != 16 && ak_len != 8) {
if (ak_len != 16 && ak_len != 4) {
PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n");
return PM3_EINVARG;
}
@ -2253,7 +2283,7 @@ static int CmdHF14AMfUeLoad(const char *Cmd) {
CLIExecWithReturn(ctx, Cmd, argtable, false);
CLIParserFree(ctx);
PrintAndLogEx(HINT, "Hint: See " _YELLOW_("`script run hf_mfu_dumptoemulator`") " to convert the .bin to .eml");
PrintAndLogEx(HINT, "Hint: See " _YELLOW_("`script run data_mfu_bin2eml`") " to convert the .bin to .eml");
return CmdHF14AMfELoad(Cmd);
}
//
@ -2264,7 +2294,8 @@ static int CmdHF14AMfUSim(const char *Cmd) {
CLIParserInit(&ctx, "hf mfu sim",
"Simulate MIFARE Ultralight family type based upon\n"
"ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n"
"from emulator memory. See `hf mfu eload` first",
"from emulator memory. See `hf mfu eload` first. \n"
"See `hf 14a sim -h` to see available types. You want 2 or 7 usually.",
"hf mfu sim -t 2 --uid 1122344556677 -> MIFARE Ultralight\n"
"hf mfu sim -t 7 --uid 1122344556677 -n 5 -> AMIIBO (NTAG 215), pack 0x8080"
);
@ -2598,7 +2629,7 @@ static int CmdHF14AMfUGenDiverseKeys(const char *Cmd) {
void *argtable[] = {
arg_param_begin,
arg_str0("u", "uid", "<hex>", "4|7 hex byte UID"),
arg_str0("u", "uid", "<hex>", "<4|7> hex byte UID"),
arg_lit0("r", NULL, "read UID from tag"),
arg_param_end
};
@ -2636,6 +2667,11 @@ static int CmdHF14AMfUGenDiverseKeys(const char *Cmd) {
}
ulen = card.uidlen;
memcpy(uid, card.uid, card.uidlen);
} else {
if (ulen != 4 && ulen != 7) {
PrintAndLogEx(ERR, "Must supply 4 or 7 hex byte uid");
return PM3_EINVARG;
}
}
uint8_t iv[8] = { 0x00 };
@ -2757,34 +2793,18 @@ static int CmdHF14AMfUPwdGen(const char *Cmd) {
if (selftest)
return generator_selftest();
if (u_len != 7) {
PrintAndLogEx(WARNING, "Key must be 7 hex bytes");
return PM3_EINVARG;
}
if (use_tag) {
// read uid from tag
clearCommandBuffer();
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_RATS, 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));
int res = ul_read_uid(uid);
if (res != PM3_SUCCESS) {
return res;
}
uint64_t select_status = resp.oldarg[0];
// 0: couldn't read
// 1: OK with ATS
// 2: OK, no ATS
// 3: proprietary Anticollision
if (select_status == 0) {
PrintAndLogEx(WARNING, "iso14443a card select failed");
return PM3_ESOFT;
} else {
if (u_len != 7) {
PrintAndLogEx(WARNING, "Key must be 7 hex bytes");
return PM3_EINVARG;
}
if (card.uidlen != 7) {
PrintAndLogEx(WARNING, "Wrong sized UID, expected 7bytes got %d", card.uidlen);
return PM3_ESOFT;
}
memcpy(uid, card.uid, sizeof(uid));
}
PrintAndLogEx(INFO, "---------------------------------");
@ -3539,7 +3559,27 @@ static int CmdHF14MfuNDEF(const char *Cmd) {
}
DropField();
status = NDEFDecodeAndPrint(records, (size_t)maxsize, true);
status = NDEFRecordsDecodeAndPrint(records, (size_t)maxsize);
if ( status != PM3_SUCCESS) {
status = NDEFDecodeAndPrint(records, (size_t)maxsize, true);
}
char *jooki = strstr((char*)records, "s.jooki.rocks/s/?s=");
if (jooki) {
jooki += 17;
while(jooki) {
if ((*jooki) != '=')
jooki++;
else {
jooki++;
char s[17] = {0};
strncpy(s, jooki, 16);
PrintAndLogEx(HINT, "Use `" _YELLOW_("hf jooki decode -d %s") "` to decode", s);
break;
}
}
}
free(records);
return status;
}

View file

@ -23,6 +23,7 @@ typedef struct {
uint32_t GetHF14AMfU_Type(void);
int ul_print_type(uint32_t tagtype, uint8_t spaces);
void printMFUdumpEx(mfu_dump_t *card, uint16_t pages, uint8_t startpage);
int ul_read_uid(uint8_t *uid);
int CmdHFMFUltra(const char *Cmd);

View file

@ -88,7 +88,8 @@ static void lookupChipID(uint32_t iChipID, uint32_t mem_used) {
sprintf(asBuff, "AT91SAM7S16 Rev A");
break;
}
PrintAndLogEx(NORMAL, " --= uC: %s", asBuff);
PrintAndLogEx(NORMAL, " --= uC: " _YELLOW_("%s"), asBuff);
switch ((iChipID & 0xE0) >> 5) {
case 1:
sprintf(asBuff, "ARM946ES");
@ -104,84 +105,7 @@ static void lookupChipID(uint32_t iChipID, uint32_t mem_used) {
break;
}
PrintAndLogEx(NORMAL, " --= Embedded Processor: %s", asBuff);
switch ((iChipID & 0xF00) >> 8) {
case 0:
mem_avail = 0;
break;
case 1:
mem_avail = 8;
break;
case 2:
mem_avail = 16;
break;
case 3:
mem_avail = 32;
break;
case 5:
mem_avail = 64;
break;
case 7:
mem_avail = 128;
break;
case 9:
mem_avail = 256;
break;
case 10:
mem_avail = 512;
break;
case 12:
mem_avail = 1024;
break;
case 14:
mem_avail = 2048;
break;
}
uint32_t mem_left = 0;
if (mem_avail > 0)
mem_left = (mem_avail * 1024) - mem_used;
PrintAndLogEx(NORMAL, " --= Nonvolatile Program Memory Size: %uK bytes, Used: %u bytes (%2.0f%%) Free: %u bytes (%2.0f%%)",
mem_avail,
mem_used,
mem_avail == 0 ? 0.0f : (float)mem_used / (mem_avail * 1024) * 100,
mem_left,
mem_avail == 0 ? 0.0f : (float)mem_left / (mem_avail * 1024) * 100
);
switch ((iChipID & 0xF000) >> 12) {
case 0:
sprintf(asBuff, "None");
break;
case 1:
sprintf(asBuff, "8K bytes");
break;
case 2:
sprintf(asBuff, "16K bytes");
break;
case 3:
sprintf(asBuff, "32K bytes");
break;
case 5:
sprintf(asBuff, "64K bytes");
break;
case 7:
sprintf(asBuff, "128K bytes");
break;
case 9:
sprintf(asBuff, "256K bytes");
break;
case 10:
sprintf(asBuff, "512K bytes");
break;
case 12:
sprintf(asBuff, "1024K bytes");
break;
case 14:
sprintf(asBuff, "2048K bytes");
break;
}
PrintAndLogEx(NORMAL, " --= Second Nonvolatile Program Memory Size: %s", asBuff);
switch ((iChipID & 0xF0000) >> 16) {
case 1:
sprintf(asBuff, "1K bytes");
@ -229,7 +153,8 @@ static void lookupChipID(uint32_t iChipID, uint32_t mem_used) {
sprintf(asBuff, "512K bytes");
break;
}
PrintAndLogEx(NORMAL, " --= Internal SRAM Size: %s", asBuff);
PrintAndLogEx(NORMAL, " --= Internal SRAM size: %s", asBuff);
switch ((iChipID & 0xFF00000) >> 20) {
case 0x19:
sprintf(asBuff, "AT91SAM9xx Series");
@ -289,7 +214,8 @@ static void lookupChipID(uint32_t iChipID, uint32_t mem_used) {
sprintf(asBuff, "AT75Cxx Series");
break;
}
PrintAndLogEx(NORMAL, " --= Architecture Identifier: %s", asBuff);
PrintAndLogEx(NORMAL, " --= Architecture identifier: %s", asBuff);
switch ((iChipID & 0x70000000) >> 28) {
case 0:
sprintf(asBuff, "ROM");
@ -307,7 +233,78 @@ static void lookupChipID(uint32_t iChipID, uint32_t mem_used) {
sprintf(asBuff, "SRAM emulating ROM");
break;
}
PrintAndLogEx(NORMAL, " --= Nonvolatile Program Memory Type: %s", asBuff);
switch ((iChipID & 0xF00) >> 8) {
case 0:
mem_avail = 0;
break;
case 1:
mem_avail = 8;
break;
case 2:
mem_avail = 16;
break;
case 3:
mem_avail = 32;
break;
case 5:
mem_avail = 64;
break;
case 7:
mem_avail = 128;
break;
case 9:
mem_avail = 256;
break;
case 10:
mem_avail = 512;
break;
case 12:
mem_avail = 1024;
break;
case 14:
mem_avail = 2048;
break;
}
PrintAndLogEx(NORMAL, " --= Nonvolatile program memory: " _YELLOW_("%uK") " bytes %s ( " _YELLOW_("%2.0f%%") " used )"
, mem_avail
, asBuff
, mem_avail == 0 ? 0.0f : (float)mem_used / (mem_avail * 1024) * 100
);
switch ((iChipID & 0xF000) >> 12) {
case 0:
sprintf(asBuff, "None");
break;
case 1:
sprintf(asBuff, "8K bytes");
break;
case 2:
sprintf(asBuff, "16K bytes");
break;
case 3:
sprintf(asBuff, "32K bytes");
break;
case 5:
sprintf(asBuff, "64K bytes");
break;
case 7:
sprintf(asBuff, "128K bytes");
break;
case 9:
sprintf(asBuff, "256K bytes");
break;
case 10:
sprintf(asBuff, "512K bytes");
break;
case 12:
sprintf(asBuff, "1024K bytes");
break;
case 14:
sprintf(asBuff, "2048K bytes");
break;
}
PrintAndLogEx(NORMAL, " --= Second nonvolatile program memory size: %s", asBuff);
}
static int CmdDbg(const char *Cmd) {

File diff suppressed because it is too large Load diff

View file

@ -36,5 +36,6 @@ int lf_read(bool verbose, uint32_t samples);
int lf_sniff(bool verbose, uint32_t samples);
int lf_config(sample_config *config);
int lf_getconfig(sample_config *config);
int lfsim_upload_gb(void);
int lfsim_wait_check(uint32_t cmd);
#endif

View file

@ -129,10 +129,7 @@ static int CmdAWIDWatch(const char *Cmd) {
PrintAndLogEx(INFO, "Press pm3-button to stop reading cards");
clearCommandBuffer();
SendCommandNG(CMD_LF_AWID_WATCH, NULL, 0);
PacketResponseNG resp;
WaitForResponse(CMD_LF_AWID_WATCH, &resp);
PrintAndLogEx(INFO, "Done");
return resp.status;
return lfsim_wait_check(CMD_LF_AWID_WATCH);
}
//by marshmellow
@ -438,8 +435,7 @@ static int CmdAWIDSim(const char *Cmd) {
return PM3_ESOFT;
}
PrintAndLogEx(SUCCESS, "Simulating AWID %u -- FC: " _YELLOW_("%u") " CN: " _YELLOW_("%u"), fmtlen, fc, cn);
PrintAndLogEx(SUCCESS, "Press pm3-button to abort simulation or run another command");
PrintAndLogEx(SUCCESS, "Simulating "_YELLOW_("AWID %u") " -- FC: " _YELLOW_("%u") " CN: " _YELLOW_("%u"), fmtlen, fc, cn);
// AWID uses: FSK2a fcHigh: 10, fcLow: 8, clk: 50, invert: 1
// arg1 --- fcHigh<<8 + fcLow
@ -456,13 +452,7 @@ static int CmdAWIDSim(const char *Cmd) {
SendCommandNG(CMD_LF_FSK_SIMULATE, (uint8_t *)payload, sizeof(lf_fsksim_t) + sizeof(bs));
free(payload);
PacketResponseNG resp;
WaitForResponse(CMD_LF_FSK_SIMULATE, &resp);
PrintAndLogEx(INFO, "Done");
if (resp.status != PM3_EOPABORTED)
return resp.status;
return PM3_SUCCESS;
return lfsim_wait_check(CMD_LF_FSK_SIMULATE);
}
static int CmdAWIDBrute(const char *Cmd) {
@ -630,7 +620,7 @@ int getAWIDBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *bits) {
if (bitLen != 88)
return PM3_ESOFT;
PrintAndLogEx(SUCCESS, "awid raw bits:\n %s \n", sprint_bin(bits, bitLen));
PrintAndLogEx(DEBUG, "awid raw bits:\n %s \n", sprint_bin(bits, bitLen));
return PM3_SUCCESS;
}

View file

@ -286,14 +286,10 @@ static int CmdEM410xWatch(const char *Cmd) {
CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIParserFree(ctx);
PrintAndLogEx(SUCCESS, "Watching for EM410x cards - place tag on antenna");
PrintAndLogEx(INFO, "Press pm3-button to stop reading cards");
PrintAndLogEx(SUCCESS, "Watching for EM410x cards - place tag on Proxmark3 antenna");
clearCommandBuffer();
SendCommandNG(CMD_LF_EM410X_WATCH, NULL, 0);
PacketResponseNG resp;
WaitForResponse(CMD_LF_EM410X_WATCH, &resp);
PrintAndLogEx(INFO, "Done");
return resp.status;
return lfsim_wait_check(CMD_LF_EM410X_WATCH);
}
//by marshmellow
@ -320,11 +316,11 @@ static int CmdEM410xDemod(const char *Cmd) {
void *argtable[] = {
arg_param_begin,
arg_u64_0(NULL, "clk", "<dec>", "optional - clock (default autodetect)"),
arg_u64_0(NULL, "err", "<dec>", "optional - maximum allowed errors (default 100)"),
arg_u64_0(NULL, "len", "<dec>", "optional - maximum length"),
arg_lit0("i", "invert", "optional - invert output"),
arg_lit0("a", "amp", "optional - amplify signal"),
arg_u64_0(NULL, "clk", "<dec>", "clock (default autodetect)"),
arg_u64_0(NULL, "err", "<dec>", "maximum allowed errors (default 100)"),
arg_u64_0(NULL, "len", "<dec>", "maximum length"),
arg_lit0("i", "invert", "invert output"),
arg_lit0("a", "amp", "amplify signal"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -359,12 +355,13 @@ static int CmdEM410xReader(const char *Cmd) {
void *argtable[] = {
arg_param_begin,
arg_u64_0(NULL, "clk", "<dec>", "optional - clock (default autodetect)"),
arg_u64_0(NULL, "err", "<dec>", "optional - maximum allowed errors (default 100)"),
arg_u64_0(NULL, "len", "<dec>", "optional - maximum length"),
arg_lit0("i", "invert", "optional - invert output"),
arg_lit0("a", "amp", "optional - amplify signal"),
arg_lit0("@", NULL, "optional - continuous reader mode"),
arg_u64_0(NULL, "clk", "<dec>", "clock (default autodetect)"),
arg_u64_0(NULL, "err", "<dec>", "maximum allowed errors (default 100)"),
arg_u64_0(NULL, "len", "<dec>", "maximum length"),
arg_lit0("i", "invert", "invert output"),
arg_lit0("a", "amp", "amplify signal"),
arg_lit0("b", NULL, "break on first found"),
arg_lit0("@", NULL, "continuous reader mode"),
arg_lit0("v", "verbose", "verbose output"),
arg_param_end
};
@ -375,8 +372,9 @@ static int CmdEM410xReader(const char *Cmd) {
size_t max_len = arg_get_u32_def(ctx, 3, 0);
bool invert = arg_get_lit(ctx, 4);
bool amplify = arg_get_lit(ctx, 5);
bool cm = arg_get_lit(ctx, 6);
bool verbose = arg_get_lit(ctx, 7);
bool break_first = arg_get_lit(ctx, 6);
bool cm = arg_get_lit(ctx, 7);
bool verbose = arg_get_lit(ctx, 8);
CLIParserFree(ctx);
if (cm) {
@ -388,6 +386,10 @@ static int CmdEM410xReader(const char *Cmd) {
uint64_t lo = 0;
lf_read(false, 12288);
AskEm410xDemod(clk, invert, max_err, max_len, amplify, &hi, &lo, verbose);
if (break_first && g_em410xid != 0) {
break;
}
} while (cm && !kbd_enter_pressed());
return PM3_SUCCESS;
@ -406,8 +408,8 @@ static int CmdEM410xSim(const char *Cmd) {
void *argtable[] = {
arg_param_begin,
arg_u64_0(NULL, "clk", "<dec>", "optional - clock [32|64] (default 64)"),
arg_str1("i", "id", "<hex>", "ID number (5 hex bytes)"),
arg_u64_0(NULL, "clk", "<dec>", "<32|64> clock (default 64)"),
arg_str1(NULL, "id", "<hex>", "ID number (5 hex bytes)"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
@ -425,11 +427,8 @@ static int CmdEM410xSim(const char *Cmd) {
}
PrintAndLogEx(SUCCESS, "Starting simulating UID "_YELLOW_("%s")" clock: "_YELLOW_("%d"), sprint_hex_inrow(uid, sizeof(uid)), clk);
PrintAndLogEx(SUCCESS, "Press pm3-button to abort simulation");
em410x_construct_emul_graph(uid, clk);
CmdLFSim("0"); // 240 start_gap.
CmdLFSim("");
return PM3_SUCCESS;
}
@ -445,8 +444,8 @@ static int CmdEM410xBrute(const char *Cmd) {
void *argtable[] = {
arg_param_begin,
arg_u64_1(NULL, "clk", "<dec>", "optional - clock [32|64] (default 64)"),
arg_u64_1(NULL, "delay", "<dec>", "optional - pause delay in milliseconds between UIDs simulation (default 1000ms)"),
arg_u64_0(NULL, "clk", "<dec>", "<32|64> clock (default 64)"),
arg_u64_0(NULL, "delay", "<dec>", "pause delay in milliseconds between UIDs simulation (default 1000ms)"),
arg_str1("f", "file", "<hex>", "file with UIDs in HEX format, one per line"),
arg_param_end
};
@ -536,13 +535,14 @@ static int CmdEM410xBrute(const char *Cmd) {
uint8_t testuid[5];
for (uint32_t c = 0; c < uidcnt; ++c) {
if (kbd_enter_pressed()) {
PrintAndLogEx(WARNING, "\nAborted via keyboard!\n");
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
PrintAndLogEx(INFO, "Aborted via keyboard!\n");
free(uidblock);
return PM3_EOPABORTED;
}
memcpy(testuid, uidblock + 5 * c, 5);
PrintAndLogEx(INFO, "Bruteforce %d / %d: simulating UID " _YELLOW_("%s")
PrintAndLogEx(INFO, "Bruteforce %d / %u: simulating UID " _YELLOW_("%s")
, c + 1
, uidcnt
, sprint_hex_inrow(testuid, sizeof(testuid))
@ -550,9 +550,25 @@ static int CmdEM410xBrute(const char *Cmd) {
em410x_construct_emul_graph(testuid, clk);
CmdLFSim("0"); //240 start_gap.
lfsim_upload_gb();
msleep(delay);
struct p {
uint16_t len;
uint16_t gap;
} PACKED payload;
payload.len = GraphTraceLen;
payload.gap = 0;
clearCommandBuffer();
SendCommandNG(CMD_LF_SIMULATE, (uint8_t *)&payload, sizeof(payload));
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_LF_SIMULATE, &resp, delay)) {
if (resp.status == PM3_EOPABORTED) {
PrintAndLogEx(INFO, "Button pressed, user aborted");
break;
}
}
}
free(uidblock);
return PM3_SUCCESS;
@ -575,9 +591,10 @@ static int CmdEM410xSpoof(const char *Cmd) {
CLIParserFree(ctx);
// loops if the captured ID was in XL-format.
CmdEM410xReader("-@");
PrintAndLogEx(SUCCESS, "# Replaying captured ID: "_YELLOW_("%010" PRIx64), g_em410xid);
CmdLFaskSim("");
g_em410xid = 0;
CmdEM410xReader("-b@");
PrintAndLogEx(SUCCESS, "Replaying captured ID "_YELLOW_("%010" PRIx64), g_em410xid);
CmdLFSim("");
return PM3_SUCCESS;
}
@ -585,15 +602,15 @@ static int CmdEM410xClone(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf em 410x clone",
"Writes EM410x ID to a T55x7 or Q5/T5555 tag",
"lf em 410x clone --uid 0F0368568B -> write id to T55x7 tag\n"
"lf em 410x clone --uid 0F0368568B --q5 -> write id to Q5/T5555 tag"
"lf em 410x clone --id 0F0368568B -> write id to T55x7 tag\n"
"lf em 410x clone --id 0F0368568B --q5 -> write id to Q5/T5555 tag"
);
void *argtable[] = {
arg_param_begin,
arg_u64_0(NULL, "clk", "<dec>", "optional - clock <16|32|40|64> (default 64)"),
arg_str1("u", "uid", "<hex>", "ID number (5 hex bytes)"),
arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
arg_u64_0(NULL, "clk", "<dec>", "<16|32|40|64> clock (default 64)"),
arg_str1(NULL, "id", "<hex>", "ID number (5 hex bytes)"),
arg_lit0(NULL, "q5", "specify writing to Q5/T5555 tag"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);

View file

@ -29,8 +29,7 @@
static int CmdHelp(const char *Cmd);
static void descramble(uint8_t *arr, uint8_t len) {
static void scramble(uint8_t *arr, uint8_t len) {
uint8_t lut[] = {
0xa3, 0xb0, 0x80, 0xc6, 0xb2, 0xf4, 0x5c, 0x6c, 0x81, 0xf1, 0xbb, 0xeb, 0x55, 0x67, 0x3c, 0x05,
0x1a, 0x0e, 0x61, 0xf6, 0x22, 0xce, 0xaa, 0x8f, 0xbd, 0x3b, 0x1f, 0x5e, 0x44, 0x04, 0x51, 0x2e,
@ -55,6 +54,31 @@ static void descramble(uint8_t *arr, uint8_t len) {
}
}
static void descramble(uint8_t *arr, uint8_t len) {
uint8_t lut[] = {
0x2f, 0x6e, 0xdd, 0xdf, 0x1d, 0x0f, 0xb0, 0x76, 0xad, 0xaf, 0x7f, 0xbb, 0x77, 0x85, 0x11, 0x6d,
0xf4, 0xd2, 0x84, 0x42, 0xeb, 0xf7, 0x34, 0x55, 0x4a, 0x3a, 0x10, 0x71, 0xe7, 0xa1, 0x62, 0x1a,
0x3e, 0x4c, 0x14, 0xd3, 0x5e, 0xb2, 0x7d, 0x56, 0xbc, 0x27, 0x82, 0x60, 0xe3, 0xae, 0x1f, 0x9b,
0xaa, 0x2b, 0x95, 0x49, 0x73, 0xe1, 0x92, 0x79, 0x91, 0x38, 0x6c, 0x19, 0x0e, 0xa9, 0xe2, 0x8d,
0x66, 0xc7, 0x5a, 0xf5, 0x1c, 0x80, 0x99, 0xbe, 0x4e, 0x41, 0xf0, 0xe8, 0xa6, 0x20, 0xab, 0x87,
0xc8, 0x1e, 0xa0, 0x59, 0x7b, 0x0c, 0xc3, 0x3c, 0x61, 0xcc, 0x40, 0x9e, 0x06, 0x52, 0x1b, 0x32,
0x8c, 0x12, 0x93, 0xbf, 0xef, 0x3b, 0x25, 0x0d, 0xc2, 0x88, 0xd1, 0xe0, 0x07, 0x2d, 0x70, 0xc6,
0x29, 0x6a, 0x4d, 0x47, 0x26, 0xa3, 0xe4, 0x8b, 0xf6, 0x97, 0x2c, 0x5d, 0x3d, 0xd7, 0x96, 0x28,
0x02, 0x08, 0x30, 0xa7, 0x22, 0xc9, 0x65, 0xf8, 0xb7, 0xb4, 0x8a, 0xca, 0xb9, 0xf2, 0xd0, 0x17,
0xff, 0x46, 0xfb, 0x9a, 0xba, 0x8f, 0xb6, 0x69, 0x68, 0x8e, 0x21, 0x6f, 0xc4, 0xcb, 0xb3, 0xce,
0x51, 0xd4, 0x81, 0x00, 0x2e, 0x9c, 0x74, 0x63, 0x45, 0xd9, 0x16, 0x35, 0x5f, 0xed, 0x78, 0x9f,
0x01, 0x48, 0x04, 0xc1, 0x33, 0xd6, 0x4f, 0x94, 0xde, 0x31, 0x9d, 0x0a, 0xac, 0x18, 0x4b, 0xcd,
0x98, 0xb8, 0x37, 0xa2, 0x83, 0xec, 0x03, 0xd8, 0xda, 0xe5, 0x7a, 0x6b, 0x53, 0xd5, 0x15, 0xa4,
0x43, 0xe9, 0x90, 0x67, 0x58, 0xc0, 0xa5, 0xfa, 0x2a, 0xb1, 0x75, 0x50, 0x39, 0x5c, 0xe6, 0xdc,
0x89, 0xfc, 0xcf, 0xfe, 0xf9, 0x57, 0x54, 0x64, 0xa8, 0xee, 0x23, 0x0b, 0xf1, 0xea, 0xfd, 0xdb,
0xbd, 0x09, 0xb5, 0x5b, 0x05, 0x86, 0x13, 0xf3, 0x24, 0xc5, 0x3f, 0x44, 0x72, 0x7c, 0x7e, 0x36
};
for (int i = 0; i < len; i++) {
arr[i] = lut[arr[i]];
}
}
//see ASK/MAN Demod for what args are accepted
int demodGallagher(bool verbose) {
(void) verbose; // unused so far
@ -81,7 +105,7 @@ int demodGallagher(bool verbose) {
setDemodBuff(DemodBuffer, 96, ans);
setClockGrid(g_DemodClock, g_DemodStartIdx + (ans * g_DemodClock));
//got a good demod
// got a good demod
uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32);
uint32_t raw2 = bytebits_to_byte(DemodBuffer + 32, 32);
uint32_t raw3 = bytebits_to_byte(DemodBuffer + 64, 32);
@ -89,34 +113,30 @@ int demodGallagher(bool verbose) {
// bytes
uint8_t arr[8] = {0};
for (int i = 0, pos = 0; i < ARRAYLEN(arr); i++) {
pos = (i * 8) + i;
pos = 16 + (9 * i);
arr[i] = bytebits_to_byte(DemodBuffer + pos, 8);
PrintAndLogEx(NORMAL, "%d -" NOLF, pos);
}
PrintAndLogEx(NORMAL, "");
// crc
uint8_t crc = bytebits_to_byte(DemodBuffer + 72, 8);
uint8_t crc = bytebits_to_byte(DemodBuffer + 16 + (9 * 8), 8);
uint8_t calc_crc = CRC8Cardx(arr, ARRAYLEN(arr));
PrintAndLogEx(INFO, " Before: %s", sprint_hex(arr, 8));
descramble(arr, ARRAYLEN(arr));
PrintAndLogEx(INFO, " After : %s", sprint_hex(arr, 8));
// 4bit region code
uint8_t rc = (arr[3] & 0x0E) >> 1;
uint8_t rc = (arr[3] & 0x1E) >> 1;
// 16bit FC
uint16_t fc = (arr[5] & 0x0F) << 12 | arr[1] << 4 | ((arr[7] >> 4) & 0x0F);
// 24bit CN
uint32_t cn = arr[0] << 16 | (arr[4] & 0x1F) << 11 | arr[2] << 3 | (arr[3] & 0xE0) >> 4;
uint32_t cn = arr[0] << 16 | (arr[4] & 0x1F) << 11 | arr[2] << 3 | (arr[3] & 0xE0) >> 5;
// 4bit issue level
uint8_t il = arr[7] & 0x0F;
PrintAndLogEx(SUCCESS, "GALLAGHER - Region: " _GREEN_("%u") " FC: " _GREEN_("%u") " CN: " _GREEN_("%u") " Issue Level: " _GREEN_("%u"), rc, fc, cn, il);
PrintAndLogEx(SUCCESS, " Printed: " _GREEN_("%C%u"), rc + 0x40, fc);
PrintAndLogEx(SUCCESS, " Displayed: " _GREEN_("%C%u"), rc + 'A', fc);
PrintAndLogEx(SUCCESS, " Raw: %08X%08X%08X", raw1, raw2, raw3);
PrintAndLogEx(SUCCESS, " CRC: %02X - %02X (%s)", crc, calc_crc, (crc == calc_crc) ? "ok" : "fail");
return PM3_SUCCESS;
@ -165,6 +185,78 @@ static int CmdGallagherReader(const char *Cmd) {
return PM3_SUCCESS;
}
static bool isValidGallagherParams(int8_t rc, int32_t fc, int32_t cn, int8_t il) {
bool isValid = true;
// if one is set, all must be set
if (rc < 0 || fc < 0 || cn < 0 || il < 0) {
PrintAndLogEx(FAILED, "If rc/fc/cn/il is specified, all must be set");
isValid = false;
}
// validate input
if (rc > 0x0f) {
PrintAndLogEx(FAILED, "Region code must be less than 16 (4 bits)");
isValid = false;
}
if (fc > 0xffff) {
PrintAndLogEx(FAILED, "Facility code must be less than 65536 (2 bytes)");
isValid = false;
}
if (cn > 0xffffff) {
PrintAndLogEx(FAILED, "Card number must be less than 16777216 (3 bytes)");
isValid = false;
}
if (il > 0x0f) {
PrintAndLogEx(FAILED, "Issue level must be less than 16 (4 bits)");
isValid = false;
}
return isValid;
}
static void setBitsInBlocks(uint32_t *blocks, uint8_t *pos, uint32_t data, uint8_t data_len) {
for (int i = data_len - 1; i >= 0; i--) {
uint8_t blk = *pos / 32;
uint8_t bitPos = 31 - *pos % 32; // fill from left
uint8_t bit = (data >> i) & 1;
blocks[blk] |= bit << bitPos;
(*pos)++;
}
}
static void createBlocks(uint32_t *blocks, uint8_t rc, uint16_t fc, uint32_t cn, uint8_t il) {
// put data into the correct places (Gallagher obfuscation)
uint8_t arr[8] = {0};
arr[0] = (cn & 0xffffff) >> 16;
arr[1] = (fc & 0xfff) >> 4;
arr[2] = (cn & 0x7ff) >> 3;
arr[3] = (cn & 0x7) << 5 | (rc & 0xf) << 1;
arr[4] = (cn & 0xffff) >> 11;
arr[5] = (fc & 0xffff) >> 12;
arr[6] = 0;
arr[7] = (fc & 0xf) << 4 | (il & 0xf);
// more obfuscation
scramble(arr, ARRAYLEN(arr));
blocks[0] = blocks[1] = blocks[2] = 0;
uint8_t pos = 0;
// magic prefix
setBitsInBlocks(blocks, &pos, 0x7fea, 16);
for (int i = 0; i < ARRAYLEN(arr); i++) {
// data byte
setBitsInBlocks(blocks, &pos, arr[i], 8);
// every byte is followed by a bit which is the inverse of the last bit
setBitsInBlocks(blocks, &pos, !(arr[i] & 0x1), 1);
}
// checksum
uint8_t crc = CRC8Cardx(arr, ARRAYLEN(arr));
setBitsInBlocks(blocks, &pos, crc, 8);
}
static int CmdGallagherClone(const char *Cmd) {
CLIParserContext *ctx;
@ -172,14 +264,19 @@ static int CmdGallagherClone(const char *Cmd) {
"clone a GALLAGHER tag to a T55x7, Q5/T5555 or EM4305/4469 tag.",
"lf gallagher clone --raw 0FFD5461A9DA1346B2D1AC32\n"
"lf gallagher clone --q5 --raw 0FFD5461A9DA1346B2D1AC32 -> encode for Q5/T5555 tag\n"
"lf gallagher clone --em --raw 0FFD5461A9DA1346B2D1AC32 -> encode for EM4305/4469"
"lf gallagher clone --em --raw 0FFD5461A9DA1346B2D1AC32 -> encode for EM4305/4469\n"
"lf gallagher clone --rc 0 --fc 9876 --cn 1234 --il 1"
);
void *argtable[] = {
arg_param_begin,
arg_str1("r", "raw", "<hex>", "raw hex data. 12 bytes max"),
arg_str0("r", "raw", "<hex>", "raw hex data. 12 bytes max"),
arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"),
arg_int0(NULL, "rc", "<decimal>", "Region code. 4 bits max"),
arg_int0(NULL, "fc", "<decimal>", "Facility code. 2 bytes max"),
arg_int0(NULL, "cn", "<decimal>", "Card number. 3 bytes max"),
arg_int0(NULL, "il", "<decimal>", "Issue level. 4 bits max"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
@ -187,19 +284,51 @@ static int CmdGallagherClone(const char *Cmd) {
int raw_len = 0;
// skip first block, 3*4 = 12 bytes left
uint8_t raw[12] = {0};
CLIGetHexWithReturn(ctx, 1, raw, &raw_len);
int res = CLIParamHexToBuf(arg_get_str(ctx, 1), raw, sizeof raw, &raw_len);
if (res) {
CLIParserFree(ctx);
return PM3_EINVARG;
}
bool q5 = arg_get_lit(ctx, 2);
bool em = arg_get_lit(ctx, 3);
int16_t region_code = arg_get_int_def(ctx, 4, -1);
int32_t facility_code = arg_get_int_def(ctx, 5, -1);
uint64_t card_number = arg_get_int_def(ctx, 6, -1);
uint32_t issue_level = arg_get_int_def(ctx, 7, -1);
CLIParserFree(ctx);
bool use_raw = raw_len > 0;
if (q5 && em) {
PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
return PM3_EINVARG;
}
if (region_code == -1 && facility_code == -1 && card_number == -1 && issue_level == -1) {
if (!use_raw) {
PrintAndLogEx(FAILED, "Must specify either raw data to clone, or rc/fc/cn/il");
return PM3_EINVARG;
}
} else {
// --raw and --rc/fc/cn/il are mutually exclusive
if (use_raw) {
PrintAndLogEx(FAILED, "Can't specify both raw and rc/fc/cn/il at the same time");
return PM3_EINVARG;
}
if (!isValidGallagherParams(region_code, facility_code, card_number, issue_level)) {
return PM3_EINVARG;
}
}
uint32_t blocks[4];
for (uint8_t i = 1; i < ARRAYLEN(blocks); i++) {
blocks[i] = bytes_to_num(raw + ((i - 1) * 4), sizeof(uint32_t));
if (use_raw) {
for (uint8_t i = 1; i < ARRAYLEN(blocks); i++) {
blocks[i] = bytes_to_num(raw + ((i - 1) * 4), sizeof(uint32_t));
}
} else {
// fill blocks 1 to 3 with Gallagher data
createBlocks(blocks + 1, region_code, facility_code, card_number, issue_level);
}
//Pac - compat mode, NRZ, data rate 40, 3 data blocks
@ -217,10 +346,10 @@ static int CmdGallagherClone(const char *Cmd) {
snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
}
PrintAndLogEx(INFO, "Preparing to clone Gallagher to " _YELLOW_("%s") " with raw hex", cardtype);
PrintAndLogEx(INFO, "Preparing to clone Gallagher to " _YELLOW_("%s") " from %s.",
cardtype, use_raw ? "raw hex" : "specified data");
print_blocks(blocks, ARRAYLEN(blocks));
int res;
if (em) {
res = em4x05_clone_tag(blocks, ARRAYLEN(blocks), 0, false);
} else {
@ -237,21 +366,69 @@ static int CmdGallagherSim(const char *Cmd) {
CLIParserInit(&ctx, "lf gallagher sim",
"Enables simulation of GALLAGHER card with specified card number.\n"
"Simulation runs until the button is pressed or another USB command is issued.\n",
"lf gallagher sim --raw 0FFD5461A9DA1346B2D1AC32"
"lf gallagher sim --raw 0FFD5461A9DA1346B2D1AC32\n"
"lf gallagher sim --rc 0 --fc 9876 --cn 1234 --il 1"
);
void *argtable[] = {
arg_param_begin,
arg_str1("r", "raw", "<hex>", "raw hex data. 12 bytes max"),
arg_str0("r", "raw", "<hex>", "raw hex data. 12 bytes max"),
arg_int0(NULL, "rc", "<decimal>", "Region code. 4 bits max"),
arg_int0(NULL, "fc", "<decimal>", "Facility code. 2 bytes max"),
arg_int0(NULL, "cn", "<decimal>", "Card number. 3 bytes max"),
arg_int0(NULL, "il", "<decimal>", "Issue level. 4 bits max"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int raw_len = 0;
// skip first block, 3*4 = 12 bytes left
uint8_t raw[12] = {0};
CLIGetHexWithReturn(ctx, 1, raw, &raw_len);
int res = CLIParamHexToBuf(arg_get_str(ctx, 1), raw, sizeof raw, &raw_len);
if (res) {
CLIParserFree(ctx);
return PM3_EINVARG;
}
int16_t region_code = arg_get_int_def(ctx, 2, -1);
int32_t facility_code = arg_get_int_def(ctx, 3, -1);
uint64_t card_number = arg_get_int_def(ctx, 4, -1);
uint32_t issue_level = arg_get_int_def(ctx, 5, -1);
CLIParserFree(ctx);
bool use_raw = raw_len > 0;
if (region_code == -1 && facility_code == -1 && card_number == -1 && issue_level == -1) {
if (!use_raw) {
PrintAndLogEx(FAILED, "Must specify either raw data to clone, or rc/fc/cn/il");
return PM3_EINVARG;
}
} else {
// --raw and --rc/fc/cn/il are mutually exclusive
if (use_raw) {
PrintAndLogEx(FAILED, "Can't specify both raw and rc/fc/cn/il at the same time");
return PM3_EINVARG;
}
if (!isValidGallagherParams(region_code, facility_code, card_number, issue_level)) {
return PM3_EINVARG;
}
}
if (!use_raw) {
// generate Gallagher data
uint32_t blocks[3];
createBlocks(blocks, region_code, facility_code, card_number, issue_level);
// convert to the normal 'raw' format
for (int i = 0; i < ARRAYLEN(blocks); i++) {
raw[(4 * i) + 0] = (blocks[i] >> 24) & 0xff;
raw[(4 * i) + 1] = (blocks[i] >> 16) & 0xff;
raw[(4 * i) + 2] = (blocks[i] >> 8) & 0xff;
raw[(4 * i) + 3] = (blocks[i]) & 0xff;
}
}
// ASK/MAN sim.
PrintAndLogEx(SUCCESS, "Simulating Gallagher - raw " _YELLOW_("%s"), sprint_hex_inrow(raw, sizeof(raw)));
@ -269,14 +446,7 @@ static int CmdGallagherSim(const char *Cmd) {
SendCommandNG(CMD_LF_ASK_SIMULATE, (uint8_t *)payload, sizeof(lf_asksim_t) + sizeof(bs));
free(payload);
PacketResponseNG resp;
WaitForResponse(CMD_LF_ASK_SIMULATE, &resp);
PrintAndLogEx(INFO, "Done");
if (resp.status != PM3_EOPABORTED)
return resp.status;
return PM3_SUCCESS;
return lfsim_wait_check(CMD_LF_ASK_SIMULATE);
}
static command_t CommandTable[] = {

View file

@ -25,12 +25,12 @@
#include <inttypes.h>
#include "cmdparser.h" // command_t
#include "comms.h"
#include "commonutil.h" // ARRAYLEN
#include "commonutil.h" // ARRAYLEN
#include "cliparser.h"
#include "ui.h"
#include "graph.h"
#include "cmddata.h" //for g_debugMode, demodbuff cmds
#include "cmdlf.h" // lf_read
#include "cmddata.h" // g_debugMode, demodbuff cmds
#include "cmdlf.h" // lf_read, lfsim_wait_check
#include "util_posix.h"
#include "lfdemod.h"
#include "wiegand_formats.h"
@ -58,7 +58,7 @@ static int sendTry(uint8_t format_idx, wiegand_card_t *card, uint32_t delay, boo
wiegand_message_t packed;
memset(&packed, 0, sizeof(wiegand_message_t));
if (HIDPack(format_idx, card, &packed) == false) {
if (HIDPack(format_idx, card, &packed, true) == false) {
PrintAndLogEx(WARNING, "The card data could not be encoded in the selected format.");
return PM3_ESOFT;
}
@ -223,10 +223,7 @@ static int CmdHIDWatch(const char *Cmd) {
PrintAndLogEx(INFO, "Press pm3-button to stop reading cards");
clearCommandBuffer();
SendCommandNG(CMD_LF_HID_WATCH, NULL, 0);
PacketResponseNG resp;
WaitForResponse(CMD_LF_HID_WATCH, &resp);
PrintAndLogEx(INFO, "Done");
return resp.status;
return lfsim_wait_check(CMD_LF_HID_WATCH);
}
static int CmdHIDSim(const char *Cmd) {
@ -287,7 +284,7 @@ static int CmdHIDSim(const char *Cmd) {
packed.Mid = mid;
packed.Bot = bot;
} else {
if (HIDPack(format_idx, &card, &packed) == false) {
if (HIDPack(format_idx, &card, &packed, true) == false) {
PrintAndLogEx(WARNING, "The card data could not be encoded in the selected format.");
return PM3_ESOFT;
}
@ -300,8 +297,6 @@ static int CmdHIDSim(const char *Cmd) {
PrintAndLogEx(INFO, "Simulating HID tag using raw " _GREEN_("%s"), raw);
}
PrintAndLogEx(INFO, "Press pm3-button to abort simulation");
lf_hidsim_t payload;
payload.hi2 = packed.Top;
payload.hi = packed.Mid;
@ -310,13 +305,7 @@ static int CmdHIDSim(const char *Cmd) {
clearCommandBuffer();
SendCommandNG(CMD_LF_HID_SIMULATE, (uint8_t *)&payload, sizeof(payload));
PacketResponseNG resp;
WaitForResponse(CMD_LF_HID_SIMULATE, &resp);
PrintAndLogEx(INFO, "Done");
if (resp.status != PM3_EOPABORTED)
return resp.status;
return PM3_SUCCESS;
return lfsim_wait_check(CMD_LF_HID_SIMULATE);
}
static int CmdHIDClone(const char *Cmd) {
@ -401,7 +390,7 @@ static int CmdHIDClone(const char *Cmd) {
packed.Mid = mid;
packed.Bot = bot;
} else {
if (HIDPack(format_idx, &card, &packed) == false) {
if (HIDPack(format_idx, &card, &packed, true) == false) {
PrintAndLogEx(WARNING, "The card data could not be encoded in the selected format.");
return PM3_ESOFT;
}

View file

@ -544,7 +544,8 @@ static int CmdIndalaSim(const char *Cmd) {
// raw param
int raw_len = 0;
uint8_t raw[(7 * 4) + 1 ];
uint8_t raw[(7 * 4) + 1];
memset(raw, 0, sizeof(raw));
CLIGetHexWithReturn(ctx, 1, raw, &raw_len);
bool is_long_uid = (raw_len == 28);
@ -569,15 +570,21 @@ static int CmdIndalaSim(const char *Cmd) {
uint8_t bs[224];
memset(bs, 0x00, sizeof(bs));
uint8_t counter = 223;
for (uint8_t i = 0; i < raw_len; i++) {
uint8_t counter = 0;
for (int8_t i = 0; i < raw_len; i++) {
uint8_t tmp = raw[i];
for (uint8_t j = 0; j < 8; j++) {
bs[counter--] = tmp & 1;
tmp >>= 1;
}
bs[counter++] = (tmp >> 7) & 1;
bs[counter++] = (tmp >> 6) & 1;
bs[counter++] = (tmp >> 5) & 1;
bs[counter++] = (tmp >> 4) & 1;
bs[counter++] = (tmp >> 3) & 1;
bs[counter++] = (tmp >> 2) & 1;
bs[counter++] = (tmp >> 1) & 1;
bs[counter++] = tmp & 1;
}
// a0 00 00 00 bd 98 9a 11
// indala PSK
// It has to send either 64bits (8bytes) or 224bits (28bytes). Zero padding needed if not.
// lf simpsk 1 c 32 r 2 d 0102030405060708
@ -593,10 +600,10 @@ static int CmdIndalaSim(const char *Cmd) {
payload->carrier = 2;
payload->invert = 0;
payload->clock = 32;
memcpy(payload->data, bs, sizeof(bs));
memcpy(payload->data, bs, raw_len * 8);
clearCommandBuffer();
SendCommandNG(CMD_LF_PSK_SIMULATE, (uint8_t *)payload, sizeof(lf_psksim_t) + sizeof(bs));
SendCommandNG(CMD_LF_PSK_SIMULATE, (uint8_t *)payload, sizeof(lf_psksim_t) + (raw_len * 8));
free(payload);
PacketResponseNG resp;

View file

@ -50,10 +50,7 @@ static int CmdIOProxWatch(const char *Cmd) {
PrintAndLogEx(INFO, "Press pm3-button to stop reading cards");
clearCommandBuffer();
SendCommandNG(CMD_LF_IO_WATCH, NULL, 0);
PacketResponseNG resp;
WaitForResponse(CMD_LF_IO_WATCH, &resp);
PrintAndLogEx(INFO, "Done");
return resp.status;
return lfsim_wait_check(CMD_LF_IO_WATCH);
}
//IO-Prox demod - FSK RF/64 with preamble of 000000001

View file

@ -98,7 +98,7 @@ static void arg_add_t55xx_downloadlink(void *at[], uint8_t *idx, uint8_t show, u
at[n++] = arg_lit0(NULL, "r3", r3);
if (show == T55XX_DLMODE_ALL) {
char *r4 = (char *)calloc(50, sizeof(uint8_t));
char *r4 = (char *)calloc(56, sizeof(uint8_t));
sprintf(r4, "try all downlink modes %s", (dl_mode_def == 4) ? "(def)" : "");
at[n++] = arg_lit0(NULL, "all", r4);
}
@ -106,7 +106,6 @@ static void arg_add_t55xx_downloadlink(void *at[], uint8_t *idx, uint8_t show, u
*idx = n;
}
static int usage_t55xx_config(void) {
PrintAndLogEx(NORMAL, "Usage: lf t55xx config [c <blk0>] [d <demodulation>] [i [0/1]] [o <offset>] [Q5 [0/1]] [ST [0/1]]");
PrintAndLogEx(NORMAL, "Options:");
@ -236,48 +235,6 @@ static int usage_t55xx_restore(void) {
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
static int usage_t55xx_detect(void) {
PrintAndLogEx(NORMAL, "Usage: lf t55xx detect [1] [r <mode>] [p <password>]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " 1 - if set, use Graphbuffer otherwise read data from tag.");
PrintAndLogEx(NORMAL, " p <password - OPTIONAL password (8 hex characters)");
print_usage_t55xx_downloadlink(T55XX_DLMODE_ALL, T55XX_DLMODE_ALL);
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx detect"));
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx detect 1"));
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx detect p 11223344"));
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
static int usage_t55xx_wakup(void) {
PrintAndLogEx(NORMAL, "Usage: lf t55xx wakeup [h] [r <mode>] p <password>");
PrintAndLogEx(NORMAL, "This commands sends the Answer-On-Request command and leaves the readerfield ON afterwards.");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h - this help");
PrintAndLogEx(NORMAL, " p <password> - password 4bytes (8 hex symbols)");
print_usage_t55xx_downloadlink(T55XX_DLMODE_SINGLE, config.downlink_mode);
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx wakeup p 11223344") " - send wakeup password");
return PM3_SUCCESS;
}
static int usage_t55xx_dangerraw(void) {
PrintAndLogEx(NORMAL, "This command allows to emit arbitrary raw commands on T5577 and cut the field after arbitrary duration.");
PrintAndLogEx(NORMAL, _RED_("WARNING:") " this may lock definitively the tag in an unusable state!");
PrintAndLogEx(NORMAL, "Uncontrolled usage can easily write an invalid configuration, activate lock bits,");
PrintAndLogEx(NORMAL, "OTP bit, password protection bit, deactivate test-mode, lock your card forever.");
PrintAndLogEx(NORMAL, "Uncontrolled usage is known to the State of California to cause cancer.");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf t55xx dangerraw [h] [b <bitstream> t <timing>]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h - This help");
PrintAndLogEx(NORMAL, " b <bitstream> - raw bitstream");
PrintAndLogEx(NORMAL, " t <timing> - time in microseconds before dropping the field");
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
static int usage_t55xx_clonehelp(void) {
PrintAndLogEx(NORMAL, "For cloning specific techs on T55xx tags, see commands available in corresponding LF sub-menus, e.g.:");
@ -915,66 +872,156 @@ static void T55xx_Print_DownlinkMode(uint8_t downlink_mode) {
PrintAndLogEx(NORMAL, msg);
}
// Define prototype to call from within detect.
static int CmdT55xxWakeUp(const char *Cmd);
static int CmdT55xxWakeUp(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf t55xx wakeup",
"This commands sends the Answer-On-Request command and leaves the readerfield ON afterwards",
"lf t55xx wakeup -p 11223344 --> send wakeup with password\n"
);
// 1 (help) + 2 (two user specified params) + (5 T55XX_DLMODE_SINGLE)
void *argtable[3 + 5] = {
arg_param_begin,
arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
arg_lit0("v", "verbose", "verbose output"),
};
uint8_t idx = 3;
arg_add_t55xx_downloadlink(argtable, &idx, T55XX_DLMODE_SINGLE, config.downlink_mode);
CLIExecWithReturn(ctx, Cmd, argtable, true);
uint32_t password = 0;
int res = arg_get_u32_hexstr_def_nlen(ctx, 2, 0, &password, 4, true);
if (res == 0 || res == 2) {
PrintAndLogEx(ERR, "Password should be 4 hex bytes");
CLIParserFree(ctx);
return PM3_EINVARG;
}
bool verbose = arg_get_lit(ctx, 2);
bool r0 = arg_get_lit(ctx, 3);
bool r1 = arg_get_lit(ctx, 4);
bool r2 = arg_get_lit(ctx, 5);
bool r3 = arg_get_lit(ctx, 6);
CLIParserFree(ctx);
if ((r0 + r1 + r2 + r3) > 1) {
PrintAndLogEx(FAILED, "Error multiple downlink encoding");
return PM3_EINVARG;
}
uint8_t downlink_mode = config.downlink_mode;
if (r0)
downlink_mode = refFixedBit;
else if (r1)
downlink_mode = refLongLeading;
else if (r2)
downlink_mode = refLeading0;
else if (r3)
downlink_mode = ref1of4;
struct p {
uint32_t password;
uint8_t flags;
} PACKED payload;
payload.password = password;
payload.flags = (downlink_mode << 3);
clearCommandBuffer();
SendCommandNG(CMD_LF_T55XX_WAKEUP, (uint8_t *)&payload, sizeof(payload));
if (WaitForResponseTimeout(CMD_LF_T55XX_WAKEUP, NULL, 1000) == false) {
PrintAndLogEx(WARNING, "command execution time out");
return PM3_ETIMEOUT;
}
if (verbose)
PrintAndLogEx(SUCCESS, "Wake up command sent. Try read now");
return PM3_SUCCESS;
}
static int CmdT55xxDetect(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf t55xx detect",
"Try detecting the tag modulation from reading the configuration block",
"lf t55xx detect\n"
"lf t55xx detect -1\n"
"lf t55xx detect -p 11223344\n"
);
// 1 (help) + 2 (two user specified params) + (6 T55XX_DLMODE_ALL)
void *argtable[3 + 6] = {
arg_param_begin,
arg_lit0("1", NULL, "extract using data from graphbuffer"),
arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
};
uint8_t idx = 3;
arg_add_t55xx_downloadlink(argtable, &idx, T55XX_DLMODE_ALL, config.downlink_mode);
CLIExecWithReturn(ctx, Cmd, argtable, true);
bool use_gb = arg_get_lit(ctx, 1);
bool errors = false;
bool useGB = false;
bool usepwd = false;
uint64_t password = -1;
uint32_t tmp_pwd = 0;
int res = arg_get_u32_hexstr_def_nlen(ctx, 2, 0, &tmp_pwd, 4, true);
if (res == 0 || res == 2) {
PrintAndLogEx(ERR, "Password should be 4 hex bytes");
CLIParserFree(ctx);
return PM3_EINVARG;
}
if (res == 1) {
usepwd = true;
password = tmp_pwd;
}
bool r0 = arg_get_lit(ctx, 3);
bool r1 = arg_get_lit(ctx, 4);
bool r2 = arg_get_lit(ctx, 5);
bool r3 = arg_get_lit(ctx, 6);
bool ra = arg_get_lit(ctx, 7);
CLIParserFree(ctx);
if ((r0 + r1 + r2 + r3 + ra) > 1) {
PrintAndLogEx(FAILED, "Error multiple downlink encoding");
return PM3_EINVARG;
}
bool try_all_dl_modes = false;
uint8_t downlink_mode = config.downlink_mode;
if (r0)
downlink_mode = refFixedBit;
else if (r1)
downlink_mode = refLongLeading;
else if (r2)
downlink_mode = refLeading0;
else if (r3)
downlink_mode = ref1of4;
if (ra)
try_all_dl_modes = true;
bool try_with_pwd = false;
bool try_all_dl_modes = true;
bool found = false;
bool usewake = false;
uint64_t password = -1;
uint8_t cmdp = 0;
uint8_t downlink_mode = 0;
char wakecmd[20] = { 0x00 };
struct timespec sleepperiod;
// Setup the 90ms time value to sleep for after the wake, to allow delay init to complete (~70ms)
struct timespec sleepperiod;
sleepperiod.tv_sec = 0;
sleepperiod.tv_nsec = 90000000;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_t55xx_detect();
case 'p':
password = param_get32ex(Cmd, cmdp + 1, 0, 16);
sprintf(wakecmd, "p %08x q", (uint32_t)(password & 0xFFFFFFFF));
usepwd = true;
cmdp += 2;
break;
case '1':
useGB = true;
cmdp++;
break;
case 'r':
downlink_mode = param_get8ex(Cmd, cmdp + 1, 0, 10);
if (downlink_mode <= 3) try_all_dl_modes = false; // User selected ONLY 1 so honor.
if (downlink_mode == 4) try_all_dl_modes = true;
if (downlink_mode > 3) downlink_mode = 0;
cmdp += 2;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
}
if (errors) return usage_t55xx_detect();
// detect called so clear data blocks
T55x7_ClearAllBlockData();
// sanity check.
if (SanityOfflineCheck(useGB) != PM3_SUCCESS)
if (SanityOfflineCheck(use_gb) != PM3_SUCCESS)
return PM3_ESOFT;
if (useGB == false) {
if (use_gb == false) {
char wakecmd[20] = { 0x00 };
sprintf(wakecmd, "-p %08" PRIx64, password);
// do ... while not found and not yet tried with wake (for AOR or Init Delay)
do {
// do ... while to check without password then loop back if password supplied
@ -987,7 +1034,7 @@ static int CmdT55xxDetect(const char *Cmd) {
if (try_with_pwd)
CmdT55xxWakeUp(wakecmd);
else
CmdT55xxWakeUp("q");
CmdT55xxWakeUp("");
// sleep 90 ms
nanosleep(&sleepperiod, &sleepperiod);
}
@ -999,7 +1046,6 @@ static int CmdT55xxDetect(const char *Cmd) {
continue;
found = true;
break;
}
} else {
@ -1008,7 +1054,7 @@ static int CmdT55xxDetect(const char *Cmd) {
if (try_with_pwd)
CmdT55xxWakeUp(wakecmd);
else
CmdT55xxWakeUp("q");
CmdT55xxWakeUp("");
// sleep 90 ms
nanosleep(&sleepperiod, &sleepperiod);
}
@ -1019,7 +1065,7 @@ static int CmdT55xxDetect(const char *Cmd) {
}
// toggle so we loop back if not found and try with pwd
if (!found && usepwd)
if (found == false && usepwd)
try_with_pwd = !try_with_pwd;
// force exit as detect block has been found
@ -1029,7 +1075,7 @@ static int CmdT55xxDetect(const char *Cmd) {
} while (try_with_pwd);
// Toggle so we loop back and try with wakeup.
usewake = !usewake;
} while (!found && usewake);
} while (found == false && usewake);
} else {
found = t55xxTryDetectModulation(downlink_mode, T55XX_PrintConfig);
}
@ -1553,63 +1599,6 @@ int printConfiguration(t55xx_conf_block_t b) {
return PM3_SUCCESS;
}
static int CmdT55xxWakeUp(const char *Cmd) {
uint32_t password = 0;
uint8_t cmdp = 0;
bool errors = false;
uint8_t downlink_mode = config.downlink_mode;
bool quiet = false;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_t55xx_wakup();
case 'p':
password = param_get32ex(Cmd, cmdp + 1, 0, 16);
cmdp += 2;
break;
case 'r':
downlink_mode = param_get8ex(Cmd, cmdp + 1, 0, 10);
if (downlink_mode > 3)
downlink_mode = 0;
cmdp += 2;
break;
case 'q':
quiet = true;
cmdp++;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
}
if (errors) return usage_t55xx_wakup();
struct p {
uint32_t password;
uint8_t flags;
} PACKED payload;
payload.password = password;
payload.flags = (downlink_mode & 3) << 3;
clearCommandBuffer();
SendCommandNG(CMD_LF_T55XX_WAKEUP, (uint8_t *)&payload, sizeof(payload));
if (!WaitForResponseTimeout(CMD_LF_T55XX_WAKEUP, NULL, 1000)) {
PrintAndLogEx(WARNING, "command execution time out");
return PM3_ETIMEOUT;
}
if (!quiet)
PrintAndLogEx(SUCCESS, "Wake up command sent. Try read now");
return PM3_SUCCESS;
}
static int CmdT55xxWriteBlock(const char *Cmd) {
uint8_t block = 0xFF; // default to invalid block
uint32_t data = 0; // default to blank Block
@ -1695,59 +1684,48 @@ static int CmdT55xxWriteBlock(const char *Cmd) {
}
static int CmdT55xxDangerousRaw(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf t55xx dangerraw",
"This command allows to emit arbitrary raw commands on T5577 and cut the field after arbitrary duration.\n"
"Uncontrolled usage can easily write an invalid configuration, activate lock bits,\n"
"OTP bit, password protection bit, deactivate test-mode, lock your card forever.\n"
_RED_("WARNING:") _CYAN_(" this may lock definitively the tag in an unusable state!"),
"lf t55xx dangerraw -d 01000000000000010000100000000100000000 -t 3200\n"
);
void *argtable[] = {
arg_param_begin,
arg_str1("d", "data", NULL, "raw bit string"),
arg_int1("t", "time", "<us>", "<0 - 200000> time in microseconds before dropping the field"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
// supports only default downlink mode
t55xx_test_block_t ng;
ng.time = 0;
ng.bitlen = 0;
memset(ng.data, 0x00, sizeof(ng.data));
bool errors = false;
uint8_t cmdp = 0;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_t55xx_dangerraw();
case 't':
ng.time = param_get32ex(Cmd, cmdp + 1, 0, 10);
if (ng.time == 0 || ng.time > 200000) {
PrintAndLogEx(ERR, "Timing off 1..200000 limits, got %i", ng.time);
errors = true;
break;
}
cmdp += 2;
break;
case 'b': {
uint32_t n = param_getlength(Cmd, cmdp + 1);
if (n > 128) {
PrintAndLogEx(ERR, "Bitstream too long, max 128 bits, got %i", n);
errors = true;
break;
}
for (uint8_t i = 0; i < n; i++) {
char c = param_getchar_indx(Cmd, i, cmdp + 1);
if (c == '0')
ng.data[i] = 0;
else if (c == '1')
ng.data[i] = 1;
else {
PrintAndLogEx(ERR, "Unknown bit char '%c'", c);
errors = true;
break;
}
}
ng.bitlen = n;
cmdp += 2;
break;
}
default:
PrintAndLogEx(ERR, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
int bin_len = 127;
uint8_t bin[128] = {0};
CLIGetStrWithReturn(ctx, 1, bin, &bin_len);
ng.time = arg_get_int_def(ctx, 2, 0);
CLIParserFree(ctx);
if (ng.time == 0 || ng.time > 200000) {
PrintAndLogEx(ERR, "Timing off 1..200000 limits, got %i", ng.time);
return PM3_EINVARG;
}
if (errors || ng.bitlen == 0 || ng.time == 0) {
return usage_t55xx_dangerraw();
int bs_len = binstring2binarray(ng.data, (char *)bin, bin_len);
if (bs_len == 0) {
return PM3_EINVARG;
}
ng.bitlen = bs_len;
PacketResponseNG resp;
clearCommandBuffer();
SendCommandNG(CMD_LF_T55XX_DANGERRAW, (uint8_t *)&ng, sizeof(ng));
@ -2868,8 +2846,8 @@ static int CmdT55xxWipe(const char *Cmd) {
"lf t55xx wipe -p 11223344 -> wipes a T55x7 tag, config block 0x000880E0, using pwd"
);
// 4 + (5 or 6)
void *argtable[9] = {
// 1 (help) + 3 (three user specified params) + (5 T55XX_DLMODE_SINGLE)
void *argtable[4 + 5] = {
arg_param_begin,
arg_str0("c", "cfg", "<hex>", "configuration block0 (4 hex bytes)"),
arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
@ -2895,9 +2873,10 @@ static int CmdT55xxWipe(const char *Cmd) {
res = arg_get_u32_hexstr_def(ctx, 2, 0x51243648, &password);
if (res) {
usepwd = true;
}
if (usepwd && res == 2)
PrintAndLogEx(WARNING, "Password should be 4 bytes, using default pwd");
if (res == 2) {
PrintAndLogEx(WARNING, "Password should be 4 bytes, using default pwd");
}
bool Q5 = arg_get_lit(ctx, 3);
@ -2978,11 +2957,14 @@ static int CmdT55xxChkPwds(const char *Cmd) {
"lf t55xx chk --em aa11223344 -> try known pwdgen algo from some cloners based on EM4100 ID"
);
// Calculate size of argtable accordingly:
// 1 (help) + 3 (three user specified params) + ( 5 or 6 T55XX_DLMODE)
// 4 + (T55XX_DLMODE_xxx 5)
// 4 + (T55XX_DLMODE_ALL 6) == 10
void *argtable[10] = {
/*
Calculate size of argtable accordingly:
1 (help) + 3 (three user specified params) + ( 5 or 6 T55XX_DLMODE)
start index to call arg_add_t55xx_downloadlink() is 4 (1 + 3) given the above sample
*/
// 1 (help) + 3 (three user specified params) + (6 T55XX_DLMODE_ALL)
void *argtable[4 + 6] = {
arg_param_begin,
arg_lit0("m", "fm", "use dictionary from flash memory (RDV4)"),
arg_str0("f", "file", "<filename>", "file name"),
@ -2998,7 +2980,7 @@ static int CmdT55xxChkPwds(const char *Cmd) {
char filename[FILE_PATH_SIZE] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)filename, sizeof(filename), &fnlen);
// White cloner password based on EM4100 ID
// White cloner password based on EM4100 ID
bool use_calc_password = false;
uint32_t card_password = 0x00;
uint64_t cardid = 0;
@ -3105,7 +3087,7 @@ static int CmdT55xxChkPwds(const char *Cmd) {
}
// to try each downlink mode for each password
int dl_mode;
int dl_mode;
// try calculated password
if (use_calc_password) {
@ -3198,6 +3180,7 @@ static int CmdT55xxBruteForce(const char *Cmd) {
"lf t55xx bruteforce --r2 -s aaaaaa77 -e aaaaaa99\n"
);
// 1 (help) + 2 (two user specified params) + (6 T55XX_DLMODE_ALL)
void *argtable[3 + 6] = {
arg_param_begin,
arg_str1("s", "start", "<hex>", "search start password (4 hex bytes)"),
@ -3324,8 +3307,8 @@ static int CmdT55xxRecoverPW(const char *Cmd) {
"lf t55xx recoverpw -p 11223344 --r3\n"
);
// 2 + (5 or 6)
void *argtable[8] = {
// 1 (help) + 1 (one user specified params) + (6 T55XX_DLMODE_ALL)
void *argtable[2 + 6] = {
arg_param_begin,
arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
};
@ -3564,8 +3547,8 @@ static int CmdT55xxDetectPage1(const char *Cmd) {
"lf t55xx p1detect -p 11223344 --r3\n"
);
// 2 + (5 or 6)
void *argtable[7] = {
// 1 (help) + 2 (two user specified params) + (5 T55XX_DLMODE_SINGLE)
void *argtable[3 + 5] = {
arg_param_begin,
arg_lit0("1", NULL, "extract using data from graphbuffer"),
arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
@ -3662,6 +3645,7 @@ static int CmdT55xxSetDeviceConfig(const char *Cmd) {
"lf t55xx deviceconfig -a 55 -b 14 -c 21 -d 30 -> default EM4305"
);
// 1 (help) + 9 (nine user specified params) + (5 T55XX_DLMODE_SINGLE)
void *argtable[10 + 5] = {
arg_param_begin,
arg_int0("a", NULL, "<8..255>", "Set start gap"),
@ -3772,7 +3756,7 @@ static int CmdT55xxProtect(const char *Cmd) {
"lf t55xx protect -p 11223344 -n 00000000 -> use pwd 11223344, sets new pwd 00000000"
);
// 4 + (5 or 6)
// 1 (help) + 3 (three user specified params) + (5 T55XX_DLMODE_SINGLE)
void *argtable[4 + 5] = {
arg_param_begin,
arg_lit0("o", "override", "override safety check"),
@ -3927,10 +3911,10 @@ static int CmdT55xxSniff(const char *Cmd) {
uint8_t width1 = 0;
uint8_t width0 = 0;
if (opt_width0 > -1)
if (opt_width0 > -1)
width0 = (uint8_t)opt_width0 & 0xFF;
if (opt_width1 > -1)
if (opt_width1 > -1)
width1 = (uint8_t)opt_width1 & 0xFF;

View file

@ -133,7 +133,7 @@ static uint16_t printHexLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trac
return ret;
}
static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles, bool markCRCBytes, uint32_t *prev_eot, bool use_us,
static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles, bool markCRCBytes, uint32_t *prev_eot, bool use_us,
const uint64_t *mfDicKeys, uint32_t mfDicKeysCount) {
// sanity check
if (is_last_record(tracepos, traceLen)) {

View file

@ -60,6 +60,7 @@ int CmdWiegandEncode(const char *Cmd) {
arg_u64_0(NULL, "issue", "<dec>", "issue level"),
arg_u64_0(NULL, "oem", "<dec>", "OEM code"),
arg_str0("w", "wiegand", "<format>", "see `wiegand list` for available formats"),
arg_lit0(NULL, "pre", "add HID preamble to wiegand"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -75,6 +76,7 @@ int CmdWiegandEncode(const char *Cmd) {
int len = 0;
char format[16] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t *)format, sizeof(format), &len);
bool preamble = arg_get_lit(ctx, 6);
CLIParserFree(ctx);
int idx = -1;
@ -89,14 +91,14 @@ int CmdWiegandEncode(const char *Cmd) {
if (idx != -1) {
wiegand_message_t packed;
memset(&packed, 0, sizeof(wiegand_message_t));
if (HIDPack(idx, &data, &packed) == false) {
if (HIDPack(idx, &data, &packed, preamble) == false) {
PrintAndLogEx(WARNING, "The card data could not be encoded in the selected format.");
return PM3_ESOFT;
}
print_wiegand_code(&packed);
} else {
// try all formats and print only the ones that work.
HIDPackTryAll(&data);
HIDPackTryAll(&data, preamble);
}
return PM3_SUCCESS;
}

View file

@ -77,6 +77,44 @@ struct wave_info_t {
} PACKED audio_data;
} PACKED;
/**
* @brief detects if file is of a supported filetype based on extension
* @param filename
* @return o
*/
DumpFileType_t getfiletype(const char *filename) {
// assume unknown file is BINARY
DumpFileType_t o = BIN;
if (filename == NULL) {
return o;
}
size_t len = strlen(filename);
if (len > 4) {
// check if valid file extension and attempt to load data
char s[FILE_PATH_SIZE];
memset(s, 0, sizeof(s));
memcpy(s, filename, len);
str_lower(s);
if (str_endswith(s, "bin")) {
o = BIN;
} else if (str_endswith(s, "eml")) {
o = EML;
} else if (str_endswith(s, "json")) {
o = JSON;
} else if (str_endswith(s, "dic")) {
o = DICTIONARY;
} else {
// mfd, trc, trace is binary
o = BIN;
// log is text
// .pm3 is text values of signal data
}
}
return o;
}
/**
* @brief checks if a file exists
* @param filename

View file

@ -272,4 +272,11 @@ mfu_df_e detect_mfu_dump_format(uint8_t **dump, size_t *dumplen, bool verbose);
int searchAndList(const char *pm3dir, const char *ext);
int searchFile(char **foundpath, const char *pm3dir, const char *searchname, const char *suffix, bool silent);
/**
* @brief detects if file is of a supported filetype based on extension
* @param filename
* @return
*/
DumpFileType_t getfiletype(const char *filename);
#endif // FILEUTILS_H

View file

@ -352,7 +352,6 @@ bool fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, int *firstClockEdge) {
if (*rf1 == 0) {
PrintAndLogEx(DEBUG, "DEBUG: Clock detect error");
return false;
}
return true;

View file

@ -806,13 +806,29 @@ int binarraytohex(char *target, const size_t targetlen, char *source, size_t src
// convert binary array to human readable binary
void binarraytobinstring(char *target, char *source, int length) {
int i;
for (i = 0 ; i < length ; ++i)
for (int i = 0 ; i < length; ++i)
*(target++) = *(source++) + '0';
*target = '\0';
}
int binstring2binarray(uint8_t *target, char *source, int length) {
int count = 0;
char *start = source;
while (length--) {
char x = *(source++);
// convert from binary value
if (x >= '0' && x <= '1')
x -= '0';
else {
PrintAndLogEx(WARNING, "(binstring2binarray) discovered unknown character %c %d at idx %d of %s", x, x, (int16_t)(source - start), start);
return 0;
}
*(target++) = x;
count++;
}
return count;
}
// return parity bit required to match type
uint8_t GetParity(uint8_t *bits, uint8_t type, int length) {
int x;

View file

@ -83,6 +83,8 @@ int hextobinarray(char *target, char *source);
int hextobinstring(char *target, char *source);
int binarraytohex(char *target, const size_t targetlen, char *source, size_t srclen);
void binarraytobinstring(char *target, char *source, int length);
int binstring2binarray(uint8_t *target, char *source, int length);
uint8_t GetParity(uint8_t *bits, uint8_t type, int length);
void wiegand_add_parity(uint8_t *target, uint8_t *source, uint8_t length);
void wiegand_add_parity_swapped(uint8_t *target, uint8_t *source, uint8_t length);

View file

@ -12,7 +12,7 @@
#include "commonutil.h"
static bool Pack_H10301(wiegand_card_t *card, wiegand_message_t *packed) {
static bool Pack_H10301(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0xFF) return false; // Can't encode FC.
@ -25,7 +25,9 @@ static bool Pack_H10301(wiegand_card_t *card, wiegand_message_t *packed) {
packed->Bot |= (card->FacilityCode & 0xFF) << 17;
packed->Bot |= oddparity32((packed->Bot >> 1) & 0xFFF) & 1;
packed->Bot |= (evenparity32((packed->Bot >> 13) & 0xFFF) & 1) << 25;
return add_HID_header(packed);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_H10301(wiegand_message_t *packed, wiegand_card_t *card) {
@ -40,7 +42,7 @@ static bool Unpack_H10301(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
static bool Pack_Tecom27(wiegand_card_t *card, wiegand_message_t *packed) {
static bool Pack_Tecom27(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0x7FF) return false; // Can't encode FC.
@ -51,7 +53,9 @@ static bool Pack_Tecom27(wiegand_card_t *card, wiegand_message_t *packed) {
packed->Length = 27;
set_nonlinear_field(packed, card->FacilityCode, 10, (uint8_t[]) {15, 19, 24, 23, 22, 18, 6, 10, 14, 3, 2});
set_nonlinear_field(packed, card->CardNumber, 16, (uint8_t[]) {0, 1, 13, 12, 9, 26, 20, 16, 17, 21, 25, 7, 8, 11, 4, 5});
return add_HID_header(packed);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_Tecom27(wiegand_message_t *packed, wiegand_card_t *card) {
@ -64,7 +68,7 @@ static bool Unpack_Tecom27(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
static bool Pack_2804W(wiegand_card_t *card, wiegand_message_t *packed) {
static bool Pack_2804W(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0x0FF) return false; // Can't encode FC.
@ -84,7 +88,9 @@ static bool Pack_2804W(wiegand_card_t *card, wiegand_message_t *packed) {
set_bit_by_position(packed,
oddparity32(get_linear_field(packed, 0, 27))
, 27);
return add_HID_header(packed);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_2804W(wiegand_message_t *packed, wiegand_card_t *card) {
@ -101,7 +107,7 @@ static bool Unpack_2804W(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
static bool Pack_ATSW30(wiegand_card_t *card, wiegand_message_t *packed) {
static bool Pack_ATSW30(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0xFFF) return false; // Can't encode FC.
@ -118,7 +124,9 @@ static bool Pack_ATSW30(wiegand_card_t *card, wiegand_message_t *packed) {
set_bit_by_position(packed,
oddparity32(get_linear_field(packed, 13, 16))
, 29);
return add_HID_header(packed);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_ATSW30(wiegand_message_t *packed, wiegand_card_t *card) {
@ -134,7 +142,7 @@ static bool Unpack_ATSW30(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
static bool Pack_ADT31(wiegand_card_t *card, wiegand_message_t *packed) {
static bool Pack_ADT31(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0x0F) return false; // Can't encode FC.
@ -146,7 +154,9 @@ static bool Pack_ADT31(wiegand_card_t *card, wiegand_message_t *packed) {
set_linear_field(packed, card->FacilityCode, 1, 4);
set_linear_field(packed, card->CardNumber, 5, 23);
// Parity not known, but 4 bits are unused.
return add_HID_header(packed);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_ADT31(wiegand_message_t *packed, wiegand_card_t *card) {
@ -158,7 +168,7 @@ static bool Unpack_ADT31(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
static bool Pack_Kastle(wiegand_card_t *card, wiegand_message_t *packed) {
static bool Pack_Kastle(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0x00FF) return false; // Can't encode FC.
@ -173,7 +183,9 @@ static bool Pack_Kastle(wiegand_card_t *card, wiegand_message_t *packed) {
set_linear_field(packed, card->CardNumber, 15, 16);
set_bit_by_position(packed, evenparity32(get_linear_field(packed, 1, 16)), 0);
set_bit_by_position(packed, oddparity32(get_linear_field(packed, 14, 17)), 31);
return add_HID_header(packed);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_Kastle(wiegand_message_t *packed, wiegand_card_t *card) {
@ -191,7 +203,7 @@ static bool Unpack_Kastle(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
static bool Pack_Kantech(wiegand_card_t *card, wiegand_message_t *packed) {
static bool Pack_Kantech(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0xFF) return false; // Can't encode FC.
@ -202,7 +214,9 @@ static bool Pack_Kantech(wiegand_card_t *card, wiegand_message_t *packed) {
packed->Length = 32;
set_linear_field(packed, card->FacilityCode, 7, 8);
set_linear_field(packed, card->CardNumber, 15, 16);
return add_HID_header(packed);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_Kantech(wiegand_message_t *packed, wiegand_card_t *card) {
@ -214,7 +228,7 @@ static bool Unpack_Kantech(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
static bool Pack_D10202(wiegand_card_t *card, wiegand_message_t *packed) {
static bool Pack_D10202(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0x007F) return false; // Can't encode FC.
@ -227,7 +241,9 @@ static bool Pack_D10202(wiegand_card_t *card, wiegand_message_t *packed) {
set_linear_field(packed, card->CardNumber, 8, 24);
set_bit_by_position(packed, evenparity32(get_linear_field(packed, 1, 16)), 0);
set_bit_by_position(packed, oddparity32(get_linear_field(packed, 16, 16)), 32);
return add_HID_header(packed);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_D10202(wiegand_message_t *packed, wiegand_card_t *card) {
@ -243,7 +259,7 @@ static bool Unpack_D10202(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
static bool Pack_H10306(wiegand_card_t *card, wiegand_message_t *packed) {
static bool Pack_H10306(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0xFFFF) return false; // Can't encode FC.
@ -257,7 +273,9 @@ static bool Pack_H10306(wiegand_card_t *card, wiegand_message_t *packed) {
packed->Mid |= (card->FacilityCode & 0x8000) >> 15;
packed->Mid |= (evenparity32((packed->Mid & 0x00000001) ^ (packed->Bot & 0xFFFE0000)) & 1) << 1;
packed->Bot |= (oddparity32(packed->Bot & 0x0001FFFE) & 1);
return add_HID_header(packed);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_H10306(wiegand_message_t *packed, wiegand_card_t *card) {
@ -275,7 +293,7 @@ static bool Unpack_H10306(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
static bool Pack_N10002(wiegand_card_t *card, wiegand_message_t *packed) {
static bool Pack_N10002(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0xFF) return false; // Can't encode FC.
@ -286,7 +304,9 @@ static bool Pack_N10002(wiegand_card_t *card, wiegand_message_t *packed) {
packed->Length = 34; // Set number of bits
set_linear_field(packed, card->FacilityCode, 9, 8);
set_linear_field(packed, card->CardNumber, 17, 16);
return add_HID_header(packed);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_N10002(wiegand_message_t *packed, wiegand_card_t *card) {
@ -299,7 +319,7 @@ static bool Unpack_N10002(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
static bool Pack_C1k35s(wiegand_card_t *card, wiegand_message_t *packed) {
static bool Pack_C1k35s(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0xFFF) return false; // Can't encode FC.
@ -314,7 +334,9 @@ static bool Pack_C1k35s(wiegand_card_t *card, wiegand_message_t *packed) {
packed->Mid |= (evenparity32((packed->Mid & 0x00000001) ^ (packed->Bot & 0xB6DB6DB6)) & 1) << 1;
packed->Bot |= (oddparity32((packed->Mid & 0x00000003) ^ (packed->Bot & 0x6DB6DB6C)) & 1);
packed->Mid |= (oddparity32((packed->Mid & 0x00000003) ^ (packed->Bot & 0xFFFFFFFF)) & 1) << 2;
return add_HID_header(packed);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_C1k35s(wiegand_message_t *packed, wiegand_card_t *card) {
@ -331,7 +353,7 @@ static bool Unpack_C1k35s(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
static bool Pack_H10320(wiegand_card_t *card, wiegand_message_t *packed) {
static bool Pack_H10320(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0) return false; // Can't encode FC. (none in this format)
@ -356,7 +378,9 @@ static bool Pack_H10320(wiegand_card_t *card, wiegand_message_t *packed) {
set_bit_by_position(packed, evenparity32(
get_nonlinear_field(packed, 8, (uint8_t[]) {3, 7, 11, 15, 19, 23, 29, 31})
), 35);
return add_HID_header(packed);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_H10320(wiegand_message_t *packed, wiegand_card_t *card) {
@ -383,7 +407,7 @@ static bool Unpack_H10320(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
static bool Pack_S12906(wiegand_card_t *card, wiegand_message_t *packed) {
static bool Pack_S12906(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0xFF) return false; // Can't encode FC.
@ -397,7 +421,9 @@ static bool Pack_S12906(wiegand_card_t *card, wiegand_message_t *packed) {
set_linear_field(packed, card->CardNumber, 11, 24);
set_bit_by_position(packed, oddparity32(get_linear_field(packed, 1, 17)), 0);
set_bit_by_position(packed, oddparity32(get_linear_field(packed, 17, 18)), 35);
return add_HID_header(packed);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_S12906(wiegand_message_t *packed, wiegand_card_t *card) {
@ -414,7 +440,7 @@ static bool Unpack_S12906(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
static bool Pack_Sie36(wiegand_card_t *card, wiegand_message_t *packed) {
static bool Pack_Sie36(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0x0003FFFF) return false; // Can't encode FC.
@ -431,7 +457,9 @@ static bool Pack_Sie36(wiegand_card_t *card, wiegand_message_t *packed) {
set_bit_by_position(packed,
evenparity32(get_nonlinear_field(packed, 23, (uint8_t[]) {1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23, 25, 26, 28, 29, 31, 32, 34}))
, 35);
return add_HID_header(packed);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_Sie36(wiegand_message_t *packed, wiegand_card_t *card) {
@ -447,7 +475,7 @@ static bool Unpack_Sie36(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
static bool Pack_C15001(wiegand_card_t *card, wiegand_message_t *packed) {
static bool Pack_C15001(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0x000000FF) return false; // Can't encode FC.
@ -461,7 +489,9 @@ static bool Pack_C15001(wiegand_card_t *card, wiegand_message_t *packed) {
set_linear_field(packed, card->CardNumber, 19, 16);
set_bit_by_position(packed, evenparity32(get_linear_field(packed, 1, 17)), 0);
set_bit_by_position(packed, oddparity32(get_linear_field(packed, 18, 17)), 35);
return add_HID_header(packed);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_C15001(wiegand_message_t *packed, wiegand_card_t *card) {
@ -478,7 +508,7 @@ static bool Unpack_C15001(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
static bool Pack_H10302(wiegand_card_t *card, wiegand_message_t *packed) {
static bool Pack_H10302(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0) return false; // Can't encode FC. (none in this format)
@ -490,7 +520,9 @@ static bool Pack_H10302(wiegand_card_t *card, wiegand_message_t *packed) {
set_linear_field(packed, card->CardNumber, 1, 35);
set_bit_by_position(packed, evenparity32(get_linear_field(packed, 1, 18)), 0);
set_bit_by_position(packed, oddparity32(get_linear_field(packed, 18, 18)), 36);
return add_HID_header(packed);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_H10302(wiegand_message_t *packed, wiegand_card_t *card) {
@ -505,7 +537,7 @@ static bool Unpack_H10302(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
static bool Pack_H10304(wiegand_card_t *card, wiegand_message_t *packed) {
static bool Pack_H10304(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0x0000FFFF) return false; // Can't encode FC.
@ -520,7 +552,9 @@ static bool Pack_H10304(wiegand_card_t *card, wiegand_message_t *packed) {
set_bit_by_position(packed, evenparity32(get_linear_field(packed, 1, 18)), 0);
set_bit_by_position(packed, oddparity32(get_linear_field(packed, 18, 18)), 36);
return add_HID_header(packed);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_H10304(wiegand_message_t *packed, wiegand_card_t *card) {
@ -536,7 +570,7 @@ static bool Unpack_H10304(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
static bool Pack_HGeneric37(wiegand_card_t *card, wiegand_message_t *packed) {
static bool Pack_HGeneric37(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0) return false; // Not used in this format
@ -553,25 +587,24 @@ static bool Pack_HGeneric37(wiegand_card_t *card, wiegand_message_t *packed) {
// even1
set_bit_by_position(packed,
evenparity32(
get_nonlinear_field(packed, 8, (uint8_t[]) {4, 8, 12, 16, 20, 24, 28, 32})
)
get_nonlinear_field(packed, 8, (uint8_t[]) {4, 8, 12, 16, 20, 24, 28, 32}))
, 0
);
// odd1
set_bit_by_position(packed,
oddparity32(
get_nonlinear_field(packed, 8, (uint8_t[]) {6, 10, 14, 18, 22, 26, 30, 34})
)
get_nonlinear_field(packed, 8, (uint8_t[]) {6, 10, 14, 18, 22, 26, 30, 34}))
, 2
);
// even2
set_bit_by_position(packed,
evenparity32(
get_nonlinear_field(packed, 8, (uint8_t[]) {7, 11, 15, 19, 23, 27, 31, 35})
)
get_nonlinear_field(packed, 8, (uint8_t[]) {7, 11, 15, 19, 23, 27, 31, 35}))
, 3
);
return add_HID_header(packed);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_HGeneric37(wiegand_message_t *packed, wiegand_card_t *card) {
@ -589,7 +622,7 @@ static bool Unpack_HGeneric37(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
static bool Pack_MDI37(wiegand_card_t *card, wiegand_message_t *packed) {
static bool Pack_MDI37(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0x0000F) return false; // Can't encode FC.
@ -604,7 +637,9 @@ static bool Pack_MDI37(wiegand_card_t *card, wiegand_message_t *packed) {
set_bit_by_position(packed, evenparity32(get_linear_field(packed, 1, 18)), 0);
set_bit_by_position(packed, oddparity32(get_linear_field(packed, 18, 18)), 36);
return add_HID_header(packed);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_MDI37(wiegand_message_t *packed, wiegand_card_t *card) {
@ -622,7 +657,7 @@ static bool Unpack_MDI37(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
static bool Pack_P10001(wiegand_card_t *card, wiegand_message_t *packed) {
static bool Pack_P10001(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
@ -641,7 +676,9 @@ static bool Pack_P10001(wiegand_card_t *card, wiegand_message_t *packed) {
get_linear_field(packed, 16, 8) ^
get_linear_field(packed, 24, 8)
, 32, 8);
return add_HID_header(packed);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_P10001(wiegand_message_t *packed, wiegand_card_t *card) {
@ -661,7 +698,7 @@ static bool Unpack_P10001(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
static bool Pack_C1k48s(wiegand_card_t *card, wiegand_message_t *packed) {
static bool Pack_C1k48s(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
@ -677,7 +714,9 @@ static bool Pack_C1k48s(wiegand_card_t *card, wiegand_message_t *packed) {
packed->Mid |= (evenparity32((packed->Mid & 0x00001B6D) ^ (packed->Bot & 0xB6DB6DB6)) & 1) << 14;
packed->Bot |= (oddparity32((packed->Mid & 0x000036DB) ^ (packed->Bot & 0x6DB6DB6C)) & 1);
packed->Mid |= (oddparity32((packed->Mid & 0x00007FFF) ^ (packed->Bot & 0xFFFFFFFF)) & 1) << 15;
return add_HID_header(packed);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_C1k48s(wiegand_message_t *packed, wiegand_card_t *card) {
@ -694,7 +733,7 @@ static bool Unpack_C1k48s(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
static bool Pack_CasiRusco40(wiegand_card_t *card, wiegand_message_t *packed) {
static bool Pack_CasiRusco40(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
@ -706,7 +745,9 @@ static bool Pack_CasiRusco40(wiegand_card_t *card, wiegand_message_t *packed) {
packed->Length = 40; // Set number of bits
set_linear_field(packed, card->CardNumber, 1, 38);
return add_HID_header(packed);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_CasiRusco40(wiegand_message_t *packed, wiegand_card_t *card) {
@ -718,7 +759,7 @@ static bool Unpack_CasiRusco40(wiegand_message_t *packed, wiegand_card_t *card)
return true;
}
static bool Pack_Optus(wiegand_card_t *card, wiegand_message_t *packed) {
static bool Pack_Optus(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
@ -731,7 +772,9 @@ static bool Pack_Optus(wiegand_card_t *card, wiegand_message_t *packed) {
set_linear_field(packed, card->CardNumber, 1, 16);
set_linear_field(packed, card->FacilityCode, 22, 11);
return add_HID_header(packed);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_Optus(wiegand_message_t *packed, wiegand_card_t *card) {
@ -744,7 +787,7 @@ static bool Unpack_Optus(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
static bool Pack_Smartpass(wiegand_card_t *card, wiegand_message_t *packed) {
static bool Pack_Smartpass(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
@ -758,7 +801,9 @@ static bool Pack_Smartpass(wiegand_card_t *card, wiegand_message_t *packed) {
set_linear_field(packed, card->FacilityCode, 1, 13);
set_linear_field(packed, card->IssueLevel, 14, 3);
set_linear_field(packed, card->CardNumber, 17, 16);
return add_HID_header(packed);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_Smartpass(wiegand_message_t *packed, wiegand_card_t *card) {
@ -772,7 +817,7 @@ static bool Unpack_Smartpass(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
static bool Pack_bqt(wiegand_card_t *card, wiegand_message_t *packed) {
static bool Pack_bqt(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
@ -793,7 +838,9 @@ static bool Pack_bqt(wiegand_card_t *card, wiegand_message_t *packed) {
oddparity32(get_linear_field(packed, 17, 16))
, 33);
return add_HID_header(packed);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_bqt(wiegand_message_t *packed, wiegand_card_t *card) {
@ -920,16 +967,16 @@ int HIDFindCardFormat(const char *format) {
return -1;
}
bool HIDPack(int format_idx, wiegand_card_t *card, wiegand_message_t *packed) {
bool HIDPack(int format_idx, wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
if (format_idx < 0 || format_idx >= ARRAYLEN(FormatTable))
return false;
return FormatTable[format_idx].Pack(card, packed);
return FormatTable[format_idx].Pack(card, packed, preamble);
}
void HIDPackTryAll(wiegand_card_t *card) {
void HIDPackTryAll(wiegand_card_t *card, bool preamble) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "%-10s %-30s --> Encoded wiegand", "Name", "Description");
@ -939,7 +986,7 @@ void HIDPackTryAll(wiegand_card_t *card) {
int i = 0;
while (FormatTable[i].Name) {
memset(&packed, 0, sizeof(wiegand_message_t));
bool res = FormatTable[i].Pack(card, &packed);
bool res = FormatTable[i].Pack(card, &packed, preamble);
if (res) {
cardformat_t fmt = HIDGetCardFormat(i);
print_desc_wiegand(&fmt, &packed);

View file

@ -33,7 +33,7 @@ typedef struct {
// Structure for defined Wiegand card formats available for packing/unpacking
typedef struct {
const char *Name;
bool (*Pack)(wiegand_card_t *card, wiegand_message_t *packed);
bool (*Pack)(wiegand_card_t *card, wiegand_message_t *packed, bool preamble);
bool (*Unpack)(wiegand_message_t *packed, wiegand_card_t *card);
const char *Descrp;
cardformatdescriptor_t Fields;
@ -42,9 +42,9 @@ typedef struct {
void HIDListFormats(void);
int HIDFindCardFormat(const char *format);
cardformat_t HIDGetCardFormat(int idx);
bool HIDPack(int format_idx, wiegand_card_t *card, wiegand_message_t *packed);
bool HIDPack(int format_idx, wiegand_card_t *card, wiegand_message_t *packed, bool preamble);
bool HIDTryUnpack(wiegand_message_t *packed, bool ignore_parity);
void HIDPackTryAll(wiegand_card_t *card);
void HIDPackTryAll(wiegand_card_t *card, bool preamble);
void print_wiegand_code(wiegand_message_t *packed);
void print_desc_wiegand(cardformat_t *fmt, wiegand_message_t *packed);
#endif

View file

@ -121,10 +121,10 @@ bool set_nonlinear_field(wiegand_message_t *data, uint64_t value, uint8_t numBit
}
static uint8_t get_length_from_header(wiegand_message_t *data) {
/**
* detect if message has "preamble" / "sentinel bit"
*
*/
/**
* detect if message has "preamble" / "sentinel bit"
*
*/
uint8_t len = 0;

View file

@ -126,10 +126,10 @@ uint32_t CRC8Legic(uint8_t *buff, size_t size) {
crc_update2(&crc, buff[i], 8);
return reflect8(crc_finish(&crc));
}
// width=8 poly=0x107, init=0x2C refin=true refout=true xorout=0x0000 check=0 name="CRC-8/CARDX"
// width=8 poly=0x7, init=0x2C refin=false refout=false xorout=0x0000 check=0 name="CRC-8/CARDX"
uint32_t CRC8Cardx(uint8_t *buff, size_t size) {
crc_t crc;
crc_init_ref(&crc, 8, 0x107, 0x2C, 0, true, true);
crc_init_ref(&crc, 8, 0x7, 0x2C, 0, false, false);
for (size_t i = 0; i < size; ++i)
crc_update2(&crc, buff[i], 8);
return crc_finish(&crc);

View file

@ -465,7 +465,6 @@ int mfdes_kdf_input_gallagher(uint8_t *uid, uint8_t uidLen, uint8_t keyNo, uint3
return PM3_SUCCESS;
}
int mfc_generate4b_nuid(uint8_t *uid, uint8_t *nuid) {
uint16_t crc;
uint8_t b1, b2;
@ -481,6 +480,21 @@ int mfc_generate4b_nuid(uint8_t *uid, uint8_t *nuid) {
return PM3_SUCCESS;
}
int mfc_algo_touch_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key) {
if (uid == NULL) return PM3_EINVARG;
if (key == NULL) return PM3_EINVARG;
*key = (
(uint64_t)(uid[1] ^ uid[2] ^ uid[3]) << 40 |
(uint64_t)uid[1] << 32 |
(uint64_t)uid[2] << 24 |
(uint64_t)(((uid[0] + uid[1] + uid[2] + uid[3]) % 0x100) ^ uid[3]) << 16 |
(uint64_t)0 << 8 |
(uint64_t)0
);
return PM3_SUCCESS;
}
//------------------------------------
// Self tests
//------------------------------------

View file

@ -43,6 +43,8 @@ int mfc_algo_sky_all(uint8_t *uid, uint8_t *keys);
int mfc_generate4b_nuid(uint8_t *uid, uint8_t *nuid);
int mfc_algo_touch_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key);
uint32_t lf_t55xx_white_pwdgen(uint32_t id);
int mfdes_kdf_input_gallagher(uint8_t *uid, uint8_t uidLen, uint8_t keyNo, uint32_t aid, uint8_t *kdfInputOut, uint8_t *kdfInputLen);

View file

@ -23,7 +23,7 @@ char *iso15693_sprintUID(char *dest, uint8_t *uid) {
sprintf(dest, "%02X %02X %02X %02X %02X %02X %02X %02X",
uid[7], uid[6], uid[5], uid[4],
uid[3], uid[2], uid[1], uid[0]
);
);
}
return dest;
}

View file

@ -332,9 +332,9 @@ pm3 --> hf mfu info
Clone MIFARE Ultralight EV1 Sequence
```
pm3 --> hf mfu dump -k FFFFFFFF
pm3 --> script run hf_mfu_dumptoemulator -i hf-mfu-XXXX-dump.bin -o hf-mfu-XXXX-dump.eml
pm3 --> script run data_mfu_bin2eml -i hf-mfu-XXXX-dump.bin -o hf-mfu-XXXX-dump.eml
pm3 --> hf mfu eload -u -f hf-mfu-XXXX-dump.eml
pm3 --> hf mfu sim -t 7 -f hf-mfu-XXXX-dump.eml
pm3 --> hf mfu sim -t 7
```
Bruteforce MIFARE Classic card numbers from 11223344 to 11223346

View file

@ -55,10 +55,14 @@ It will also add the `-h --help` option automatic.
-h --help : help
--cn : card number
--fn : facility number
--q5 : target is lf q5 card
--q5 : target is LF T5555/Q5 card
--em : target is LF EM4305/4469 card
--raw : raw data
-d --data : hex data supplied
-f --file : filename supplied
-k --key : key supplied
-n --keyno : key number to use
-p --pwd : password supplied
-v --verbose : flag when output should provide more information, not considered debug.
-1 --buffer : use the sample buffer

View file

@ -93,14 +93,6 @@ hf mf gen3uid
hf mf gen3blk
hf mf gen3freeze
hf mf ice
lf config
lf cmdread
lf read
lf sim
lf simask
lf simfsk
lf simpsk
lf sniff
lf em 410x
lf em 4x05
lf em 4x50
@ -111,15 +103,11 @@ lf hitag writer
lf hitag dump
lf hitag cc
lf t55xx config
lf t55xx dangerraw
lf t55xx detect
lf t55xx dump
lf t55xx info
lf t55xx read
lf t55xx resetread
lf t55xx restore
lf t55xx trace
lf t55xx wakeup
lf t55xx write
lf t55xx special
script run

View file

@ -433,6 +433,7 @@ Check column "offline" for their availability.
|`hf mfdes getuid `|N |`Get random uid`
|`hf mfdes info `|N |`Tag information`
|`hf mfdes list `|Y |`List DESFire (ISO 14443A) history`
|`hf mfdes bruteaid `|N |`Recover AIDs by bruteforce`
|`hf mfdes createaid `|N |`Create Application ID`
|`hf mfdes deleteaid `|N |`Delete Application ID`
|`hf mfdes selectaid `|N |`Select Application ID`
@ -534,13 +535,13 @@ Check column "offline" for their availability.
|------- |------- |-----------
|`lf help `|Y |`This help`
|`lf config `|N |`Get/Set config for LF sampling, bit/sample, decimation, frequency`
|`lf cmdread `|N |`Modulate LF reader field to send command before read (all periods in microseconds)`
|`lf cmdread `|N |`Modulate LF reader field to send command before read`
|`lf read `|N |`Read LF tag`
|`lf search `|Y |`Read and Search for valid known tag (in offline mode it you can load first then search)`
|`lf sim `|N |`Simulate LF tag from buffer with optional GAP (in microseconds)`
|`lf simask `|N |`Simulate LF ASK tag from demodbuffer or input`
|`lf simfsk `|N |`Simulate LF FSK tag from demodbuffer or input`
|`lf simpsk `|N |`Simulate LF PSK tag from demodbuffer or input`
|`lf search `|Y |`Read and Search for valid known tag`
|`lf sim `|N |`Simulate LF tag from buffer`
|`lf simask `|N |`Simulate ASK tag`
|`lf simfsk `|N |`Simulate FSK tag`
|`lf simpsk `|N |`Simulate PSK tag`
|`lf simbidir `|N |`Simulate LF tag (with bidirectional data transmission between reader and tag)`
|`lf sniff `|N |`Sniff LF traffic between reader and tag`
|`lf tune `|N |`Continuously measure LF antenna tuning`

View file

@ -8,7 +8,7 @@ The RDV4 repository contains helper scripts for JTAG flashing.
* Get OpenOCD, e.g.: `apt-get install openocd`
* Create `tools/jtag_openocd/openocd_configuration` by copying [`tools/jtag_openocd/openocd_configuration.sample`](/tools/jtag_openocd/openocd_configuration.sample)
* Tune it to fit your JTAG tool: adapt `CONFIG_IF` to refer to the `interface-*.cfg` file corresponding to your JTAG tool. By default `openocd_configuration.sample` is set up to work with the J-Link.
* Tune it to fit your JTAG tool: adapt `CONFIG_IF` to refer to your JTAG tool. `openocd_configuration.sample` contains several examples and is set up by default to work with the J-Link.
* Wire the Proxmark3 to the JTAG tool. How to do it depends on the tool. See below for examples. **Warning:** don't plug the Proxmark3 on USB if the tool delivers already the voltage to the Proxmark3, which is most probably the case.
* Then just run
@ -25,7 +25,7 @@ For advanced usages there are also `openocd_flash_dump.sh` for dumping the conte
The RDV4 JTAG header is quite smaller compared to other Proxmark3 platforms.
If you're using a J-Link, there is a [convenient adapter](https://github.com/RfidResearchGroup/proxmark3/wiki/Tools#jtag-adapter) made by Proxgrind.
You can also make yours with some 1.27mm headers (look for `1.27mm header` on Aliexpress) or Pogo pins.
You can also make yours with some 1.27mm headers (look for `1.27mm header` on Aliexpress) or Pogo pins or buy an already made clip, e.g. search `dykb clamp` on Aliexpress and take a 1.27mm single-row 6P version.
## JLink pinout

4
pm3
View file

@ -148,7 +148,7 @@ function get_pm3_list_Windows {
fi
# Normal SERIAL PORTS (COM)
for DEV in $(wmic /locale:ms_409 path Win32_SerialPort Where "PNPDeviceID LIKE '%VID_9AC4&PID_4B8F%'" Get DeviceID 2>/dev/null | awk -b '/^COM/{print $1}'); do
for DEV in $(wmic /locale:ms_409 path Win32_SerialPort Where "PNPDeviceID LIKE '%VID_9AC4&PID_4B8F%' Or PNPDeviceID LIKE '%VID_2D2D&PID_504D%'" Get DeviceID 2>/dev/null | awk -b '/^COM/{print $1}'); do
DEV=${DEV/ */}
PM3LIST+=("$DEV")
if [ ${#PM3LIST[*]} -ge "$N" ]; then
@ -192,7 +192,7 @@ function get_pm3_list_WSL {
fi
# Normal SERIAL PORTS (COM)
for DEV in $($PSHEXE -command "Get-CimInstance -ClassName Win32_serialport | Where-Object PNPDeviceID -like '*VID_9AC4&PID_4B8F*' | Select DeviceID" 2>/dev/null | sed -nr 's#^COM([0-9]+)\b#/dev/ttyS\1#p'); do
for DEV in $($PSHEXE -command "Get-CimInstance -ClassName Win32_serialport | Where-Object {\$_.PNPDeviceID -like '*VID_9AC4&PID_4B8F*' -or \$_.PNPDeviceID -like '*VID_2D2D&PID_504D*'} | Select DeviceID" 2>/dev/null | sed -nr 's#^COM([0-9]+)\b#/dev/ttyS\1#p'); do
# ttyS counterpart takes some more time to appear
if [ -e "$DEV" ]; then
PM3LIST+=("$DEV")

View file

@ -18,3 +18,13 @@ get_xorsearch:
# unzzip-big XORSearch_V1_11_2.zip
# linux
# gunzip XORSearch_V1_11_2.zip
# Python impl of NDEF FORUM 1-5 protocol
get_nfcpy:
$(MKDIR) nfcpy
$(GIT) https://github.com/nfcpy/nfcpy.git
# Python tool to create, modify and print NDEF records
get_ndeftool:
$(MKDIR) ndeftool
$(GIT) https://github.com/nfcpy/ndeftool.git

View file

@ -254,7 +254,8 @@ int discoverDevices(unsigned int profile_selected, uint32_t device_types_selecte
if (verbose) printf("%14s: %s\n", "Device Type", (device_type & CL_DEVICE_TYPE_GPU) ? "GPU" : (device_type & CL_DEVICE_TYPE_CPU) ? "CPU" : "Other");
(*cd_ctx)[platform_idx].device[device_idx].selected = plat_dev_enabled(global_device_id, dev_sel, dev_cnt, (unsigned int) device_type, device_types_selected);
if ((*cd_ctx)[platform_idx].selected == false)(*cd_ctx)[platform_idx].device[device_idx].selected = false;
else (*cd_ctx)[platform_idx].device[device_idx].selected = plat_dev_enabled(global_device_id, dev_sel, dev_cnt, (unsigned int) device_type, device_types_selected);
global_device_id++;
if ((*cd_ctx)[platform_idx].device[device_idx].selected)(*selected_devices_cnt)++;
continue;

View file

@ -28,3 +28,7 @@ gdb_memory_map enable
sam7x.cpu configure -work-area-virt 0 -work-area-phys 0x00200000 -work-area-size 0x10000 -work-area-backup 0
flash bank sam7x.flash.0 at91sam7 0 0 0 0 sam7x.cpu 0 0 0 0 0 0 0 18432
flash bank sam7x.flash.1 at91sam7 0 0 0 0 sam7x.cpu 1 0 0 0 0 0 0 18432
transport select jtag
# Since some 0.10.0 versions, "adapter_khz" is deprecated in favor of "adapter speed" but there are also some 0.10.0 not recognizing "adapter speed" so we'll stick to "adapter_khz" for now...
# adapter speed 1000
adapter_khz 1000

View file

@ -1,8 +0,0 @@
# Commands specific to the Olimex ARM-USB-OCD Dongle
interface ft2232
ft2232_device_desc "Olimex OpenOCD JTAG"
ft2232_layout "olimex-jtag"
ft2232_vid_pid 0x15BA 0x0003
jtag_speed 2
jtag_nsrst_delay 200
jtag_ntrst_delay 200

View file

@ -1,10 +0,0 @@
# Commands specific to the Bus Blaster
interface ftdi
ftdi_device_desc "Dual RS232-HS"
ftdi_vid_pid 0x0403 0x6010
ftdi_layout_init 0x0c08 0x0f1b
ftdi_layout_signal nTRST -data 0x0100 -noe 0x0400
ftdi_layout_signal nSRST -data 0x0200 -noe 0x0800
adapter_khz 1000

View file

@ -1,10 +1,8 @@
# Commands specific to the BusPirate
interface buspirate
buspirate_port /dev/ttyUSB0
adapter_khz 1000
# Communication speed
buspirate_speed normal # or fast
source [find interface/buspirate.cfg]
buspirate_port /dev/ttyUSB0
# Voltage regulator: enabled = 1 or disabled = 0
buspirate_vreg 1

View file

@ -11,13 +11,4 @@
# Black <> GND
# Red <> 3.3 (don't connect if C232HM-EDSL-0! power via USB instead)
interface ftdi
#ftdi_device_desc "C232HM-DDHSL-0"
#ftdi_device_desc "C232HM-EDHSL-0"
ftdi_vid_pid 0x0403 0x6014
ftdi_layout_init 0x0008 0x400b
ftdi_layout_signal LED -ndata 0x4000
transport select jtag
adapter_khz 1000
source [find interface/ftdi/c232hm.cfg]

View file

@ -1,4 +0,0 @@
# Commands specific to the Segger J-Link
interface jlink
transport select jtag
adapter_khz 1000

View file

@ -1,8 +0,0 @@
# Commands specific to the Amontec JTAGKey
interface ft2232
ft2232_device_desc "Amontec JTAGkey A"
ft2232_layout jtagkey
ft2232_vid_pid 0x0403 0xcff8
jtag_khz 200
jtag_nsrst_delay 200
jtag_ntrst_delay 200

View file

@ -12,26 +12,7 @@
# 6 <> GND
# 1 <> 3.3
interface bcm2835gpio
# This file is meant for first versions of Raspberry Pi
# You can check yours with:
# dd if=/proc/device-tree/soc/ranges bs=4 skip=1 count=1 2>/dev/null|xxd -p
# if it returns 20000000, you're fine
# if it returns 3F000000, use interface-raspberrypi2.cfg
bcm2835gpio_peripheral_base 0x20000000
# Transition delay calculation: SPEED_COEFF/khz - SPEED_OFFSET
# These depend on system clock, calibrated for stock 700MHz
# bcm2835gpio_speed SPEED_COEFF SPEED_OFFSET
bcm2835gpio_speed_coeffs 113714 28
# Each of the JTAG lines need a gpio number set: tck tms tdi tdo
# Header pin numbers: 23 22 19 21
bcm2835gpio_jtag_nums 11 25 10 9
source [find interface/raspberrypi-native.cfg]
bcm2835gpio_srst_num 18
reset_config srst_only srst_push_pull
transport select jtag
adapter_khz 1000

View file

@ -12,26 +12,7 @@
# 6 <> GND
# 1 <> 3.3
interface bcm2835gpio
# This file is meant for recent versions of Raspberry Pi
# You can check yours with:
# dd if=/proc/device-tree/soc/ranges bs=4 skip=1 count=1 2>/dev/null|xxd -p
# if it returns 20000000, use interface-raspberrypi.cfg
# if it returns 3F000000, you're fine
bcm2835gpio_peripheral_base 0x3F000000
# Transition delay calculation: SPEED_COEFF/khz - SPEED_OFFSET
# These depend on system clock, calibrated for stock 700MHz
# bcm2835gpio_speed SPEED_COEFF SPEED_OFFSET
bcm2835gpio_speed_coeffs 146203 36
# Each of the JTAG lines need a gpio number set: tck tms tdi tdo
# Header pin numbers: 23 22 19 21
bcm2835gpio_jtag_nums 11 25 10 9
source [find interface/raspberrypi2-native.cfg]
bcm2835gpio_srst_num 18
reset_config srst_only srst_push_pull
transport select jtag
adapter_khz 1000

View file

@ -1,6 +0,0 @@
# Commands specific to the Shikra
interface ftdi
transport select jtag
ftdi_vid_pid 0x0403 0x6014
ftdi_layout_init 0x0c08 0x0f1b
adapter_khz 2000

View file

@ -1,7 +0,0 @@
# Commands specific to the Wiggler
interface parport
parport_port 0x378
parport_cable wiggler
jtag_speed 0
jtag_nsrst_delay 200
jtag_ntrst_delay 200

View file

@ -1,7 +1,34 @@
CONFIG_GEN=general.cfg
CONFIG_CHIP=chip-at91sam7s.cfg
CONFIG_BOARD=board-at91sam7s.cfg
IMAGE=../../recovery/proxmark3_recovery.bin
DUMP="dump_$(date +'%Y%m%d-%H%M%S').bin"
# Example using Segger Jlink:
CONFIG_IF=interface-jlink.cfg
# One can use openocd-provided interfaces or local interface files
# Here are a few examples
# Segger Jlink:
CONFIG_IF=interface/jlink.cfg
# Raspberry Pi models Pi1, Pi2 and Pi Zero (read interface-raspberrypi.cfg for pinout)
#CONFIG_IF=interface-raspberrypi.cfg
# Raspberry Pi models 2+ and above (read interface-raspberrypi2.cfg for pinout)
#CONFIG_IF=interface-raspberrypi2.cfg
# DP BusBlaster:
#CONFIG_IF=interface/ftdi/dp_busblaster.cfg
# BusPirate:
#CONFIG_IF=interface-buspirate.cfg
# C232HM-DDHSL-0 and C232HM-EDSL-0 (beware! read interface-c232hm.cfg instructions)
#CONFIG_IF=interface-c232hm.cfg
# Olimex ARM-USB-OCD Dongle:
#CONFIG_IF=interface/ftdi/olimex-arm-usb-ocd.cfg
# Amontec JTAGKey:
#CONFIG_IF=interface/ftdi/jtagkey.cfg
# Wiggler:
#CONFIG_IF=interface/parport.cfg

View file

@ -7,4 +7,4 @@ if [ -e "$DUMP" ]; then
echo "$DUMP exists already. Abort!"
exit 1
fi
openocd -f $CONFIG_GEN -f $CONFIG_IF -f $CONFIG_CHIP -c "init;halt;dump_image $DUMP 0x100000 0x80000;exit"
openocd -f $CONFIG_GEN -f $CONFIG_IF -f $CONFIG_BOARD -c "init;halt;dump_image $DUMP 0x100000 0x80000;exit"

View file

@ -7,4 +7,4 @@ if [ ! -e "$IMAGE" ]; then
echo "$IMAGE missing. Abort!"
exit 1
fi
openocd -f $CONFIG_GEN -f $CONFIG_IF -f $CONFIG_CHIP -c "init;halt;flash erase_sector 0 0 15;flash erase_sector 1 0 15;flash write_image $IMAGE 0x100000;exit"
openocd -f $CONFIG_GEN -f $CONFIG_IF -f $CONFIG_BOARD -c "init;halt;flash erase_sector 0 0 15;flash erase_sector 1 0 15;flash write_image $IMAGE 0x100000;exit"

View file

@ -6,4 +6,4 @@ cd $(dirname "$0")
echo "*********************************************"
echo "Connect to OpenOCD via: telnet localhost $(awk '/^telnet_port/{print$2}' $CONFIG_GEN)"
echo "*********************************************"
openocd -f $CONFIG_GEN -f $CONFIG_IF -f $CONFIG_CHIP
openocd -f $CONFIG_GEN -f $CONFIG_IF -f $CONFIG_BOARD

View file

@ -343,6 +343,8 @@ while true; do
if ! CheckExecute "reveng -g test" "$CLIENTBIN -c 'reveng -g abda202c'" "CRC-16/ISO-IEC-14443-3-A"; then break; fi
if ! CheckExecute "reveng -w test" "$CLIENTBIN -c 'reveng -w 8 -s 01020304e3 010204039d'" "CRC-8/SMBUS"; then break; fi
if ! CheckExecute "mfu pwdgen test" "$CLIENTBIN -c 'hf mfu pwdgen -t'" "Selftest OK"; then break; fi
if ! CheckExecute "mfu keygen test" "$CLIENTBIN -c 'hf mfu keygen --uid 11223344556677'" "80 B1 C2 71 D8 A0"; then break; fi
if ! CheckExecute "jooki encode test" "$CLIENTBIN -c 'hf jooki encode -t'" "04 28 F4 DA F0 4A 81 ( ok )"; then break; fi
if ! CheckExecute "trace load/list 14a" "$CLIENTBIN -c 'trace load -f traces/hf_14a_mfu.trace; trace list -1 -t 14a;'" "READBLOCK(8)"; then break; fi
if ! CheckExecute "trace load/list x" "$CLIENTBIN -c 'trace load -f traces/hf_14a_mfu.trace; trace list -x1 -t 14a;'" "0.0101840425"; then break; fi
@ -382,7 +384,7 @@ while true; do
"temperature 95.2 F / 35.1 C"; then break; fi
if ! CheckExecute slow "lf T55 gallagher test" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_gallagher.pm3; lf search -1'" "GALLAGHER ID found"; then break; fi
if ! CheckExecute slow "lf T55 gallagher test2" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_gallagher.pm3; lf gallagher demod'" \
"GALLAGHER - Region: 0 FC: 27865 CN: 682758 Issue Level: 13"; then break; fi
"GALLAGHER - Region: 1 FC: 16640 CN: 201 Issue Level: 1"; then break; fi
if ! CheckExecute slow "lf T55 gproxii test" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_gproxii.pm3; lf search -1'" "Guardall G-Prox II ID found"; then break; fi
if ! CheckExecute slow "lf T55 gproxii test2" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_gproxii.pm3; lf gproxii demod'" \
"G-Prox-II - len: 26 FC: 123 Card: 11223, Raw: f98c7038c63356c7ac26398c"; then break; fi