mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 05:43:48 -07:00
Merge branch 'master' into dev_4x50_standalone
update
This commit is contained in:
commit
ac0ef23d5e
79 changed files with 2201 additions and 1396 deletions
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
#include "crc16.h"
|
||||
|
||||
#ifdef WITH_LCD
|
||||
#include "LCD.h"
|
||||
#include "LCD_disabled.h"
|
||||
#endif
|
||||
|
||||
#ifdef WITH_SMARTCARD
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
//
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -474,6 +474,7 @@ SRCS = aiddesfire.c \
|
|||
cmdhffido.c \
|
||||
cmdhficlass.c \
|
||||
cmdhflegic.c \
|
||||
cmdhfjooki.c \
|
||||
cmdhflist.c \
|
||||
cmdhflto.c \
|
||||
cmdhfmf.c \
|
||||
|
|
|
@ -579,7 +579,7 @@ static SIMDExecInstr GetSIMDInstr(void) {
|
|||
instr = SIMD_MMX;
|
||||
else
|
||||
#endif
|
||||
instr = SIMD_NONE;
|
||||
instr = SIMD_NONE;
|
||||
|
||||
return instr;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
--[[
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
--[[
|
||||
|
|
|
@ -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
|
||||
|
||||
--[[
|
|
@ -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": ""
|
||||
},
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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... }"},
|
||||
|
|
|
@ -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}
|
||||
};
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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
518
client/src/cmdhfjooki.c
Normal 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
16
client/src/cmdhfjooki.h
Normal 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
|
|
@ -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"},
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
1215
client/src/cmdlf.c
1215
client/src/cmdlf.c
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
//------------------------------------
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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
4
pm3
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
# Commands specific to the Segger J-Link
|
||||
interface jlink
|
||||
transport select jtag
|
||||
adapter_khz 1000
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue