mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-11-10 17:49:32 +08:00
Merge branch 'RfidResearchGroup:master' into master
This commit is contained in:
commit
78f2d9b958
17 changed files with 377 additions and 209 deletions
|
@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file.
|
|||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- Fixed `pm3-flash-all` shell script now correctly identify the if running on outdated bootloader (@iceman1001)
|
||||
- Fixed `hf 15693/iclass sniff` trace timings (@nvx)
|
||||
- Fix LegicCash segment handling in `hf_legic.lua` script (@jmichelp)
|
||||
- Fixed `trace list` - now handles marking of crc bytes w color a bit better (@iceman1001)
|
||||
- Changed `hf mfu pwdgen -r` - now generates pwd/pack for Philips Sonicare, thanks @ckuenzi, @atc1441 (@iceman1001)
|
||||
- Changed `hf mfu info` - now detects Philips Sonicare devices (@iceman1001)
|
||||
- Fixed truncated FPGA upload due to incorrect integer size variable (@d18c7db)
|
||||
- Changed `usart btfactory` - handles the new BT board with version "BT SPP V3.0" (@iceman1001)
|
||||
- Changed `hf mf eview --sk` - now can extract keys and save to file (@iceman1001)
|
||||
|
|
|
@ -1736,14 +1736,19 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string, bool icla
|
|||
// no need to try decoding reader data if the tag is sending
|
||||
if (!tag_is_active) {
|
||||
|
||||
if (Handle15693SampleFromReader((sniffdata & 0x02) >> 1, &dreader)) {
|
||||
int extra_8s = 1;
|
||||
if (Handle15693SampleFromReader((sniffdata & 0x02) >> 1, &dreader) ||
|
||||
(++extra_8s && Handle15693SampleFromReader(sniffdata & 0x01, &dreader))) {
|
||||
|
||||
uint32_t eof_time = dma_start_time + (samples * 16) + 8 - DELAY_READER_TO_ARM_SNIFF; // end of EOF
|
||||
if (dreader.byteCount > 0) {
|
||||
// sof/eof_times are in ssp_clk, which is 13.56MHz / 4
|
||||
// not sure where the extra +8's on the EOF time comes from though, if someone knows update this comment
|
||||
uint32_t eof_time = dma_start_time + (samples * 16) + (extra_8s * 8) - DELAY_READER_TO_ARM_SNIFF; // end of EOF
|
||||
uint32_t sof_time = eof_time
|
||||
- dreader.byteCount * (dreader.Coding == CODING_1_OUT_OF_4 ? 128 * 16 : 2048 * 16) // time for byte transfers
|
||||
- 32 * 16 // time for SOF transfer
|
||||
- 16 * 16; // time for EOF transfer
|
||||
- dreader.byteCount * (dreader.Coding == CODING_1_OUT_OF_4 ? 1024 : 16384) // time for byte transfers
|
||||
- 256 // time for SOF transfer (1024/fc / 4)
|
||||
- 128; // time for EOF transfer (512/fc / 4)
|
||||
// sof/eof_times * 4 here to bring from ssp_clk freq to RF carrier freq
|
||||
LogTrace_ISO15693(dreader.output, dreader.byteCount, (sof_time * 4), (eof_time * 4), NULL, true);
|
||||
|
||||
if (!iclass) { // Those flags don't exist in iClass
|
||||
|
@ -1751,52 +1756,38 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string, bool icla
|
|||
expect_fast_answer = dreader.output[0] & ISO15_REQ_DATARATE_HIGH;
|
||||
}
|
||||
}
|
||||
|
||||
// And ready to receive another command.
|
||||
//DecodeReaderReset(&dreader); // already reseted
|
||||
DecodeTagReset(&dtag);
|
||||
DecodeTagFSKReset(&dtagfsk);
|
||||
reader_is_active = false;
|
||||
expect_tag_answer = true;
|
||||
} else if (Handle15693SampleFromReader(sniffdata & 0x01, &dreader)) {
|
||||
|
||||
uint32_t eof_time = dma_start_time + (samples * 16) + 16 - DELAY_READER_TO_ARM_SNIFF; // end of EOF
|
||||
if (dreader.byteCount > 0) {
|
||||
uint32_t sof_time = eof_time
|
||||
- dreader.byteCount * (dreader.Coding == CODING_1_OUT_OF_4 ? 128 * 16 : 2048 * 16) // time for byte transfers
|
||||
- 32 * 16 // time for SOF transfer
|
||||
- 16 * 16; // time for EOF transfer
|
||||
LogTrace_ISO15693(dreader.output, dreader.byteCount, (sof_time * 4), (eof_time * 4), NULL, true);
|
||||
if (!iclass) { // Those flags don't exist in iClass
|
||||
expect_fsk_answer = dreader.output[0] & ISO15_REQ_SUBCARRIER_TWO;
|
||||
expect_fast_answer = dreader.output[0] & ISO15_REQ_DATARATE_HIGH;
|
||||
}
|
||||
}
|
||||
// And ready to receive another command
|
||||
//DecodeReaderReset(&dreader); // already reseted
|
||||
DecodeTagReset(&dtag);
|
||||
DecodeTagFSKReset(&dtagfsk);
|
||||
reader_is_active = false;
|
||||
expect_tag_answer = true;
|
||||
} else {
|
||||
reader_is_active = (dreader.state >= STATE_READER_RECEIVE_DATA_1_OUT_OF_4);
|
||||
}
|
||||
}
|
||||
|
||||
if (!reader_is_active && expect_tag_answer) { // no need to try decoding tag data if the reader is currently sending or no answer expected yet
|
||||
// no need to try decoding tag data if the reader is currently sending or no answer expected yet
|
||||
if (!reader_is_active && expect_tag_answer) {
|
||||
|
||||
if (!expect_fsk_answer) {
|
||||
// single subcarrier tag response
|
||||
if (Handle15693SamplesFromTag((sniffdata >> 4) << 2, &dtag, expect_fast_answer)) {
|
||||
|
||||
// sof/eof_times are in ssp_clk, which is 13.56MHz / 4
|
||||
uint32_t eof_time = dma_start_time + (samples * 16) - DELAY_TAG_TO_ARM_SNIFF; // end of EOF
|
||||
if (dtag.lastBit == SOF_PART2) {
|
||||
eof_time -= (8 * 16); // needed 8 additional samples to confirm single SOF (iCLASS)
|
||||
}
|
||||
uint32_t sof_time = eof_time
|
||||
- dtag.len * 8 * 8 * 16 // time for byte transfers
|
||||
- (32 * 16) // time for SOF transfer
|
||||
- (dtag.lastBit != SOF_PART2 ? (32 * 16) : 0); // time for EOF transfer
|
||||
- dtag.len * 1024 // time for byte transfers (4096/fc / 4)
|
||||
- 512 // time for SOF transfer (2048/fc / 4)
|
||||
- (dtag.lastBit != SOF_PART2 ? 512 : 0); // time for EOF transfer (2048/fc / 4)
|
||||
|
||||
// sof/eof_times * 4 here to bring from ssp_clk freq to RF carrier freq
|
||||
LogTrace_ISO15693(dtag.output, dtag.len, (sof_time * 4), (eof_time * 4), NULL, false);
|
||||
|
||||
// And ready to receive another response.
|
||||
DecodeTagReset(&dtag);
|
||||
DecodeTagFSKReset(&dtagfsk);
|
||||
|
@ -1807,26 +1798,23 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string, bool icla
|
|||
tag_is_active = (dtag.state >= STATE_TAG_RECEIVING_DATA);
|
||||
}
|
||||
} else {
|
||||
// dual subcarrier tag response
|
||||
if (FREQ_IS_0((sniffdata >> 2) & 0x3)) // tolerate 1 00
|
||||
sniffdata = sniffdata_prev;
|
||||
|
||||
if (Handle15693FSKSamplesFromTag((sniffdata >> 2) & 0x3, &dtagfsk, expect_fast_answer)) {
|
||||
expect_fsk_answer = false;
|
||||
} else {
|
||||
tag_is_active = (dtagfsk.state >= STATE_FSK_RECEIVING_DATA_484);
|
||||
}
|
||||
if (!expect_fsk_answer) {
|
||||
// FSK answer no more expected: switch back to ASK
|
||||
if (dtagfsk.len > 0) {
|
||||
// sof/eof_times are in ssp_clk, which is 13.56MHz / 4
|
||||
uint32_t eof_time = dma_start_time + (samples * 16) - DELAY_TAG_TO_ARM_SNIFF; // end of EOF
|
||||
if (dtagfsk.lastBit == SOF) {
|
||||
eof_time -= (8 * 16); // needed 8 additional samples to confirm single SOF (iCLASS)
|
||||
}
|
||||
uint32_t sof_time = eof_time
|
||||
- dtagfsk.len * 8 * 8 * 16 // time for byte transfers
|
||||
- (32 * 16) // time for SOF transfer
|
||||
- (dtagfsk.lastBit != SOF ? (32 * 16) : 0); // time for EOF transfer
|
||||
- dtagfsk.len * 1016 // time for byte transfers (4064/fc / 4) - FSK is slightly different
|
||||
- 512 // time for SOF transfer (2048/fc / 4)
|
||||
- (dtagfsk.lastBit != SOF ? 512 : 0); // time for EOF transfer (2048/fc / 4)
|
||||
|
||||
// sof/eof_times * 4 here to bring from ssp_clk freq to RF carrier freq
|
||||
LogTrace_ISO15693(dtagfsk.output, dtagfsk.len, (sof_time * 4), (eof_time * 4), NULL, false);
|
||||
}
|
||||
|
||||
|
@ -1834,6 +1822,10 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string, bool icla
|
|||
DecodeReaderReset(&dreader);
|
||||
expect_tag_answer = false;
|
||||
tag_is_active = false;
|
||||
// FSK answer no more expected: switch back to ASK
|
||||
expect_fsk_answer = false;
|
||||
} else {
|
||||
tag_is_active = (dtagfsk.state >= STATE_FSK_RECEIVING_DATA_484);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# Mifare Ultralight Default Keys
|
||||
# Mifare Ultralight C Default Keys
|
||||
# -- iceman fork version --
|
||||
# -- contribute to this list, sharing is caring --
|
||||
#
|
||||
|
|
|
@ -221,7 +221,7 @@ end
|
|||
---
|
||||
-- curency-codes for Legic-Cash-Segments (ISO 4217)
|
||||
local currency = {
|
||||
["03d2"]="EUR",
|
||||
["03D2"]="EUR",
|
||||
["0348"]="USD",
|
||||
["033A"]="GBP",
|
||||
["02F4"]="CHF"
|
||||
|
@ -1447,7 +1447,10 @@ function dumpLegicCash(tag, x)
|
|||
print("--------------------------------\n\tLegic-Cash Values\n--------------------------------")
|
||||
local limit, curr, balance, rid, tcv
|
||||
-- currency of balance & limit
|
||||
curr=currency[tag.SEG[x].data[8]..tag.SEG[x].data[9]]
|
||||
curr=string.upper(tag.SEG[x].data[8]..tag.SEG[x].data[9])
|
||||
if currency[curr] ~= nil then
|
||||
curr = currency[curr]
|
||||
end
|
||||
-- maximum balance
|
||||
limit=string.format("%4.2f", tonumber(tag.SEG[x].data[10]..tag.SEG[x].data[11]..tag.SEG[x].data[12], 16)/100)
|
||||
-- current balance
|
||||
|
@ -1784,17 +1787,17 @@ end
|
|||
|
||||
---
|
||||
-- edit Segment Data
|
||||
function editSegmentData(data)
|
||||
function editSegmentData(data, uid)
|
||||
io.write("\n")
|
||||
if istable(data) == false then print("no Segment-Data found") end
|
||||
|
||||
local lc = check4LegicCash(data)
|
||||
local lc = check4LegicCash(data, uid)
|
||||
|
||||
for i=0, #data-1 do
|
||||
data[i]=input(accyan.."Data"..i..acoff..": ", data[i])
|
||||
end
|
||||
if (lc) then
|
||||
data = fixLegicCash(data)
|
||||
data = fixLegicCash(data, uid)
|
||||
end
|
||||
return data
|
||||
end
|
||||
|
@ -1917,7 +1920,7 @@ function autoSelectSegment(tag, s)
|
|||
repeat
|
||||
io.write(". ")
|
||||
x=x-1
|
||||
res=check4LegicCash(tag.SEG[x].data)
|
||||
res=check4LegicCash(tag.SEG[x].data, uid)
|
||||
until ( res or x==0 )
|
||||
end
|
||||
---
|
||||
|
@ -2011,7 +2014,7 @@ end
|
|||
|
||||
---
|
||||
-- edit Legic Cash
|
||||
function editLegicCash(data)
|
||||
function editLegicCash(data, uid)
|
||||
local limit, curr, balance, rid, tcv
|
||||
-- currency of balance & limit
|
||||
curr=currency[data[8]..data[9]]
|
||||
|
@ -2064,12 +2067,12 @@ function editLegicCash(data)
|
|||
data[20]=string.sub(rid, 5, 6)
|
||||
end
|
||||
|
||||
return fixLegicCash(data)
|
||||
return fixLegicCash(data, uid)
|
||||
end
|
||||
|
||||
---
|
||||
-- chack for signature of a 'Legic-Cash-Segment'
|
||||
function check4LegicCash(data)
|
||||
function check4LegicCash(data, uid)
|
||||
if(#data==32) then
|
||||
local stamp_len=(#data-25)
|
||||
local stamp=""
|
||||
|
@ -2077,9 +2080,9 @@ function check4LegicCash(data)
|
|||
stamp=stamp..data[i].." "
|
||||
end
|
||||
if (data[7]=="01") then
|
||||
if (("%04x"):format(utils.Crc16(dumpTable(data, "", 0, 12))) == data[13]..data[14]) then
|
||||
if (("%04x"):format(utils.Crc16(dumpTable(data, "", 15, 20))) == data[21]..data[22]) then
|
||||
if (("%04x"):format(utils.Crc16(dumpTable(data, "", 23, 29))) == data[30]..data[31]) then
|
||||
if (("%04x"):format(utils.Crc16Legic(dumpTable(data, "", 0, 12), uid)) == data[13]..data[14]) then
|
||||
if (("%04x"):format(utils.Crc16Legic(dumpTable(data, "", 15, 20), uid)) == data[21]..data[22]) then
|
||||
if (("%04x"):format(utils.Crc16Legic(dumpTable(data, "", 23, 29), uid)) == data[30]..data[31]) then
|
||||
io.write(accyan.."Legic-Cash Segment detected "..acoff)
|
||||
return true
|
||||
end
|
||||
|
@ -2156,7 +2159,7 @@ end
|
|||
|
||||
---
|
||||
-- repair / fix crc's of a 'Legic-Cash-Segment'
|
||||
function fixLegicCash(data)
|
||||
function fixLegicCash(data, uid)
|
||||
if(#data==32 and data[7]=="01") then
|
||||
local crc1, crc2, crc3
|
||||
-- set shadow-balance equal to balance
|
||||
|
@ -2168,9 +2171,9 @@ function fixLegicCash(data)
|
|||
data[27]=data[19]
|
||||
data[28]=data[20]
|
||||
-- calculate all crc's
|
||||
crc1=("%04x"):format(utils.Crc16(dumpTable(data, "", 0, 12)))
|
||||
crc2=("%04x"):format(utils.Crc16(dumpTable(data, "", 15, 20)))
|
||||
crc3=("%04x"):format(utils.Crc16(dumpTable(data, "", 23, 29)))
|
||||
crc1=("%04x"):format(utils.Crc16Legic(dumpTable(data, "", 0, 12), uid))
|
||||
crc2=("%04x"):format(utils.Crc16Legic(dumpTable(data, "", 15, 20), uid))
|
||||
crc3=("%04x"):format(utils.Crc16Legic(dumpTable(data, "", 23, 29), uid))
|
||||
-- set crc's
|
||||
data[13]=string.sub(crc1, 1, 2)
|
||||
data[14]=string.sub(crc1, 3, 4)
|
||||
|
@ -2413,7 +2416,7 @@ function modifyMode()
|
|||
for i=0, #inTAG.SEG do
|
||||
if(check43rdPartyCash1(uid, inTAG.SEG[i].data)) then
|
||||
io.write(accyan.."in Segment index: "..inTAG.SEG[i].index ..acoff.. "\n")
|
||||
elseif(check4LegicCash(inTAG.SEG[i].data)) then
|
||||
elseif(check4LegicCash(inTAG.SEG[i].data, uid)) then
|
||||
io.write(accyan.."in Segment index: "..inTAG.SEG[i].index..acoff.."\n")
|
||||
lc=true;
|
||||
lci=inTAG.SEG[i].index;
|
||||
|
@ -2520,7 +2523,8 @@ function modifyMode()
|
|||
if (type(x)=="string" and string.len(x)>0) then sel=tonumber(x,10)
|
||||
else sel=selectSegment(inTAG) end
|
||||
if (istable(inTAG.SEG[sel])) then
|
||||
inTAG.SEG[sel].data=editSegmentData(inTAG.SEG[sel].data)
|
||||
local uid = inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2
|
||||
inTAG.SEG[sel].data=editSegmentData(inTAG.SEG[sel].data, uid)
|
||||
end
|
||||
end,
|
||||
---
|
||||
|
@ -2587,13 +2591,15 @@ function modifyMode()
|
|||
else
|
||||
x = selectSegment(inTAG)
|
||||
end
|
||||
inTAG.SEG[x].data=fixLegicCash(inTAG.SEG[x].data)
|
||||
local uid=inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2
|
||||
inTAG.SEG[x].data=fixLegicCash(inTAG.SEG[x].data, uid)
|
||||
end,
|
||||
---
|
||||
-- edit legic-cash values fixLegicCash(data)
|
||||
-- edit legic-cash values fixLegicCash(data, uid)
|
||||
["elc"] = function(x)
|
||||
x=autoSelectSegment(inTAG, "legiccash")
|
||||
inTAG.SEG[x].data=editLegicCash(inTAG.SEG[x].data)
|
||||
local uid=inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2
|
||||
inTAG.SEG[x].data=editLegicCash(inTAG.SEG[x].data, uid)
|
||||
end,
|
||||
---
|
||||
-- dump legic-cash human-readable
|
||||
|
|
|
@ -70,7 +70,7 @@ static uint8_t *gs_mfuc_key = NULL;
|
|||
|
||||
uint8_t iso14443A_CRC_check(bool isResponse, uint8_t *d, uint8_t n) {
|
||||
if (n < 3) return 2;
|
||||
if (isResponse && (n < 6)) return 2;
|
||||
if (isResponse && (n == 5)) return 2;
|
||||
if (d[1] == 0x50 &&
|
||||
d[0] >= ISO14443A_CMD_ANTICOLL_OR_SELECT &&
|
||||
d[0] <= ISO14443A_CMD_ANTICOLL_OR_SELECT_3) {
|
||||
|
|
|
@ -207,7 +207,7 @@ static char GetFormatFromSector(uint8_t sectors) {
|
|||
}
|
||||
}
|
||||
|
||||
static bool mfc_value(const uint8_t *d, int32_t *val) {
|
||||
bool mfc_value(const uint8_t *d, int32_t *val) {
|
||||
// values
|
||||
int32_t a = (int32_t)MemLeToUint4byte(d);
|
||||
uint32_t a_inv = MemLeToUint4byte(d + 4);
|
||||
|
@ -225,7 +225,7 @@ static bool mfc_value(const uint8_t *d, int32_t *val) {
|
|||
return val_checks;
|
||||
}
|
||||
|
||||
static void mf_print_block_one(uint8_t blockno, uint8_t *d, bool verbose) {
|
||||
void mf_print_block_one(uint8_t blockno, uint8_t *d, bool verbose) {
|
||||
if (blockno == 0) {
|
||||
PrintAndLogEx(INFO, "%3d | " _RED_("%s"), blockno, sprint_hex_ascii(d, MFBLOCK_SIZE));
|
||||
} else if (mfIsSectorTrailer(blockno)) {
|
||||
|
@ -389,7 +389,7 @@ static void mf_print_values(uint16_t n, uint8_t *d) {
|
|||
}
|
||||
*/
|
||||
|
||||
static void mf_print_sector_hdr(uint8_t sector) {
|
||||
void mf_print_sector_hdr(uint8_t sector) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, " # | sector " _GREEN_("%02d") " / " _GREEN_("0x%02X") " | ascii", sector, sector);
|
||||
PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------");
|
||||
|
|
|
@ -34,6 +34,11 @@ void showSectorTable(sector_t *k_sector, size_t k_sectors_cnt);
|
|||
void readerAttack(sector_t *k_sector, size_t k_sectors_cnt, nonces_t data, bool setEmulatorMem, bool verbose);
|
||||
void printKeyTable(size_t sectorscnt, sector_t *e_sector);
|
||||
void printKeyTableEx(size_t sectorscnt, sector_t *e_sector, uint8_t start_sector);
|
||||
// void printKeyTableEx(size_t sectorscnt, sector_t *e_sector, uint8_t start_sector, bool singel_sector);
|
||||
|
||||
bool mfc_value(const uint8_t *d, int32_t *val);
|
||||
void mf_print_sector_hdr(uint8_t sector);
|
||||
void mf_print_block_one(uint8_t blockno, uint8_t *d, bool verbose);
|
||||
|
||||
int mfc_ev1_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signature, int signature_len);
|
||||
#endif
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "fileutils.h"
|
||||
#include "protocols.h"
|
||||
#include "crypto/libpcrypto.h"
|
||||
#include "cmdhfmf.h" // printblock, header
|
||||
|
||||
static const uint8_t DefaultKey[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
static uint16_t CardAddresses[] = {0x9000, 0x9001, 0x9002, 0x9003, 0x9004, 0xA000, 0xA001, 0xA080, 0xA081, 0xC000, 0xC001};
|
||||
|
@ -172,7 +173,7 @@ static int plus_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signature
|
|||
const ecdsa_publickey_t nxp_plus_public_keys[] = {
|
||||
{"MIFARE Plus EV1", "044409ADC42F91A8394066BA83D872FB1D16803734E911170412DDF8BAD1A4DADFD0416291AFE1C748253925DA39A5F39A1C557FFACD34C62E"},
|
||||
{"MIFARE Plus Ev_x", "04BB49AE4447E6B1B6D21C098C1538B594A11A4A1DBF3D5E673DEACDEB3CC512D1C08AFA1A2768CE20A200BACD2DC7804CD7523A0131ABF607"},
|
||||
{"MIFARE Plus Trojka", "040F732E0EA7DF2B38F791BF89425BF7DCDF3EE4D976669E3831F324FF15751BD52AFF1782F72FF2731EEAD5F63ABE7D126E03C856FFB942AF"}
|
||||
{"MIFARE Plus Troika", "040F732E0EA7DF2B38F791BF89425BF7DCDF3EE4D976669E3831F324FF15751BD52AFF1782F72FF2731EEAD5F63ABE7D126E03C856FFB942AF"}
|
||||
};
|
||||
|
||||
uint8_t i;
|
||||
|
@ -766,25 +767,25 @@ static int CmdHFMFPRdbl(const char *Cmd) {
|
|||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
uint8_t sector = mfSectorNum(blockn);
|
||||
mf_print_sector_hdr(sector);
|
||||
|
||||
int indx = blockn;
|
||||
for (int i = 0; i < blocksCount; i++) {
|
||||
PrintAndLogEx(INFO, "data[%03d]: %s", indx, sprint_hex(&data[1 + i * 16], 16));
|
||||
mf_print_block_one(indx, data + 1 + (i * MFBLOCK_SIZE), verbose);
|
||||
indx++;
|
||||
if (mfIsSectorTrailer(indx) && i != blocksCount - 1) {
|
||||
PrintAndLogEx(INFO, "data[%03d]: ------------------- trailer -------------------", indx);
|
||||
indx++;
|
||||
}
|
||||
|
||||
if (memcmp(&data[(blocksCount * 16) + 1], mac, 8)) {
|
||||
PrintAndLogEx(WARNING, "WARNING: mac not equal...");
|
||||
PrintAndLogEx(WARNING, "MAC card... " _YELLOW_("%s"), sprint_hex_inrow(&data[1 + (blocksCount * MFBLOCK_SIZE)], 8));
|
||||
PrintAndLogEx(WARNING, "MAC reader... " _YELLOW_("%s"), sprint_hex_inrow(mac, sizeof(mac)));
|
||||
} else {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, "MAC... " _YELLOW_("%s"), sprint_hex_inrow(&data[1 + (blocksCount * MFBLOCK_SIZE)], 8));
|
||||
}
|
||||
}
|
||||
|
||||
if (memcmp(&data[blocksCount * 16 + 1], mac, 8)) {
|
||||
PrintAndLogEx(WARNING, "WARNING: mac not equal...");
|
||||
PrintAndLogEx(WARNING, "MAC card: %s", sprint_hex(&data[blocksCount * 16 + 1], 8));
|
||||
PrintAndLogEx(WARNING, "MAC reader: %s", sprint_hex(mac, 8));
|
||||
} else {
|
||||
if (verbose)
|
||||
PrintAndLogEx(INFO, "MAC: %s", sprint_hex(&data[blocksCount * 16 + 1], 8));
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -849,8 +850,12 @@ static int CmdHFMFPRdsc(const char *Cmd) {
|
|||
uint8_t data[250] = {0};
|
||||
int datalen = 0;
|
||||
uint8_t mac[8] = {0};
|
||||
for (int n = mfFirstBlockOfSector(sectorNum); n < mfFirstBlockOfSector(sectorNum) + mfNumBlocksPerSector(sectorNum); n++) {
|
||||
res = MFPReadBlock(&mf4session, plain, n & 0xff, 1, false, true, data, sizeof(data), &datalen, mac);
|
||||
|
||||
mf_print_sector_hdr(sectorNum);
|
||||
|
||||
for (int blockno = mfFirstBlockOfSector(sectorNum); blockno < mfFirstBlockOfSector(sectorNum) + mfNumBlocksPerSector(sectorNum); blockno++) {
|
||||
|
||||
res = MFPReadBlock(&mf4session, plain, blockno & 0xff, 1, false, true, data, sizeof(data), &datalen, mac);
|
||||
if (res) {
|
||||
PrintAndLogEx(ERR, "Read error: %d", res);
|
||||
DropField();
|
||||
|
@ -862,25 +867,27 @@ static int CmdHFMFPRdsc(const char *Cmd) {
|
|||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
if (datalen != 1 + 16 + 8 + 2) {
|
||||
|
||||
if (datalen != 1 + MFBLOCK_SIZE + 8 + 2) {
|
||||
PrintAndLogEx(ERR, "Error return length:%d", datalen);
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "data[%03d]: %s", n, sprint_hex(&data[1], 16));
|
||||
mf_print_block_one(blockno, data + 1, verbose);
|
||||
|
||||
if (memcmp(&data[1 + 16], mac, 8)) {
|
||||
PrintAndLogEx(WARNING, "WARNING: mac on block %d not equal...", n);
|
||||
PrintAndLogEx(WARNING, "MAC card: %s", sprint_hex(&data[1 + 16], 8));
|
||||
PrintAndLogEx(WARNING, "MAC reader: %s", sprint_hex(mac, 8));
|
||||
PrintAndLogEx(WARNING, "WARNING: mac on block %d not equal...", blockno);
|
||||
PrintAndLogEx(WARNING, "MAC card... " _YELLOW_("%s"), sprint_hex_inrow(&data[1 + MFBLOCK_SIZE], 8));
|
||||
PrintAndLogEx(WARNING, "MAC reader... " _YELLOW_("%s"), sprint_hex_inrow(mac, sizeof(mac)));
|
||||
} else {
|
||||
if (verbose)
|
||||
PrintAndLogEx(INFO, "MAC: %s", sprint_hex(&data[1 + 16], 8));
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, "MAC... " _YELLOW_("%s"), sprint_hex_inrow(&data[1 + MFBLOCK_SIZE], 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
DropField();
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -993,7 +1000,7 @@ static int CmdHFMFPWrbl(const char *Cmd) {
|
|||
#define AES_KEY_LEN 16
|
||||
#define MAX_KEYS_LIST_LEN 1024
|
||||
|
||||
static int MFPKeyCheck(uint8_t startSector, uint8_t endSector, uint8_t startKeyAB, uint8_t endKeyAB,
|
||||
static int plus_key_check(uint8_t startSector, uint8_t endSector, uint8_t startKeyAB, uint8_t endKeyAB,
|
||||
uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN], size_t keyListLen, uint8_t foundKeys[2][64][AES_KEY_LEN + 1],
|
||||
bool verbose) {
|
||||
int res;
|
||||
|
@ -1097,16 +1104,12 @@ static void Fill2bPattern(uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN], uint3
|
|||
}
|
||||
|
||||
static int CmdHFMFPChk(const char *Cmd) {
|
||||
int res;
|
||||
uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN] = {{0}};
|
||||
uint32_t keyListLen = 0;
|
||||
uint8_t foundKeys[2][64][AES_KEY_LEN + 1] = {{{0}}};
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfp chk",
|
||||
"Checks keys on MIFARE Plus card",
|
||||
"hf mfp chk -k 000102030405060708090a0b0c0d0e0f -> check key on sector 0 as key A and B\n"
|
||||
"hf mfp chk -s 2 -a -> check default key list on sector 2, key A\n"
|
||||
"hf mfp chk -s 2 -a -> check default key list on sector 2, only key A\n"
|
||||
"hf mfp chk -d mfp_default_keys -s0 -e6 -> check keys from dictionary against sectors 0-6\n"
|
||||
"hf mfp chk --pattern1b -j keys -> check all 1-byte keys pattern and save found keys to json\n"
|
||||
"hf mfp chk --pattern2b --startp2b FA00 -> check all 2-byte keys pattern. Start from key FA00FA00...FA00");
|
||||
|
@ -1133,6 +1136,10 @@ static int CmdHFMFPChk(const char *Cmd) {
|
|||
uint8_t startSector = arg_get_int_def(ctx, 3, 0);
|
||||
uint8_t endSector = arg_get_int_def(ctx, 4, 0);
|
||||
|
||||
uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN] = {{0}};
|
||||
uint32_t keyListLen = 0;
|
||||
uint8_t foundKeys[2][64][AES_KEY_LEN + 1] = {{{0}}};
|
||||
|
||||
uint8_t vkey[16] = {0};
|
||||
int vkeylen = 0;
|
||||
CLIGetHexWithReturn(ctx, 5, vkey, &vkeylen);
|
||||
|
@ -1201,10 +1208,10 @@ static int CmdHFMFPChk(const char *Cmd) {
|
|||
|
||||
uint8_t startKeyAB = 0;
|
||||
uint8_t endKeyAB = 1;
|
||||
if (keyA && !keyB)
|
||||
if (keyA && (keyB == false))
|
||||
endKeyAB = 0;
|
||||
|
||||
if (!keyA && keyB)
|
||||
if ((keyA == false) && keyB)
|
||||
startKeyAB = 1;
|
||||
|
||||
if (endSector < startSector)
|
||||
|
@ -1212,8 +1219,9 @@ static int CmdHFMFPChk(const char *Cmd) {
|
|||
|
||||
// 1-byte pattern search mode
|
||||
if (pattern1b) {
|
||||
for (int i = 0; i < 0x100; i++)
|
||||
for (int i = 0; i < 0x100; i++) {
|
||||
memset(keyList[i], i, 16);
|
||||
}
|
||||
|
||||
keyListLen = 0x100;
|
||||
}
|
||||
|
@ -1222,6 +1230,8 @@ static int CmdHFMFPChk(const char *Cmd) {
|
|||
if (pattern2b)
|
||||
Fill2bPattern(keyList, &keyListLen, &startPattern);
|
||||
|
||||
int res = PM3_SUCCESS;
|
||||
|
||||
// dictionary mode
|
||||
size_t endFilePosition = 0;
|
||||
if (dict_filenamelen) {
|
||||
|
@ -1236,8 +1246,9 @@ static int CmdHFMFPChk(const char *Cmd) {
|
|||
|
||||
if (keyListLen == 0) {
|
||||
for (int i = 0; i < g_mifare_plus_default_keys_len; i++) {
|
||||
if (hex_to_bytes(g_mifare_plus_default_keys[i], keyList[keyListLen], 16) != 16)
|
||||
if (hex_to_bytes(g_mifare_plus_default_keys[i], keyList[keyListLen], 16) != 16) {
|
||||
break;
|
||||
}
|
||||
|
||||
keyListLen++;
|
||||
}
|
||||
|
@ -1250,21 +1261,26 @@ static int CmdHFMFPChk(const char *Cmd) {
|
|||
PrintAndLogEx(INFO, "Loaded " _YELLOW_("%"PRIu32) " keys", keyListLen);
|
||||
}
|
||||
|
||||
if (verbose == false)
|
||||
if (verbose == false) {
|
||||
PrintAndLogEx(INFO, "Search keys");
|
||||
}
|
||||
|
||||
while (true) {
|
||||
res = MFPKeyCheck(startSector, endSector, startKeyAB, endKeyAB, keyList, keyListLen, foundKeys, verbose);
|
||||
if (res == PM3_EOPABORTED)
|
||||
res = plus_key_check(startSector, endSector, startKeyAB, endKeyAB, keyList, keyListLen, foundKeys, verbose);
|
||||
if (res == PM3_EOPABORTED) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (pattern2b && startPattern < 0x10000) {
|
||||
if (verbose == false)
|
||||
if (verbose == false) {
|
||||
PrintAndLogEx(NORMAL, "p" NOLF);
|
||||
}
|
||||
|
||||
keyListLen = 0;
|
||||
Fill2bPattern(keyList, &keyListLen, &startPattern);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dict_filenamelen && endFilePosition) {
|
||||
if (verbose == false)
|
||||
PrintAndLogEx(NORMAL, "d" NOLF);
|
||||
|
@ -1274,6 +1290,7 @@ static int CmdHFMFPChk(const char *Cmd) {
|
|||
if (res == PM3_SUCCESS && endFilePosition) {
|
||||
keyListLen = keycnt;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
@ -1282,26 +1299,38 @@ static int CmdHFMFPChk(const char *Cmd) {
|
|||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
// print result
|
||||
char strA[46 + 1] = {0};
|
||||
char strB[46 + 1] = {0};
|
||||
|
||||
bool printedHeader = false;
|
||||
for (uint8_t sector = startSector; sector <= endSector; sector++) {
|
||||
if (foundKeys[0][sector][0] || foundKeys[1][sector][0]) {
|
||||
if (!printedHeader) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "-------+--------------------------------+---------------------------------");
|
||||
PrintAndLogEx(INFO, "|sector| key A | key B |");
|
||||
PrintAndLogEx(INFO, "|------+--------------------------------+--------------------------------|");
|
||||
printedHeader = true;
|
||||
}
|
||||
PrintAndLogEx(INFO, "| %02d |%32s|%32s|",
|
||||
sector,
|
||||
(foundKeys[0][sector][0] == 0) ? "------ " : sprint_hex_inrow(&foundKeys[0][sector][1], AES_KEY_LEN),
|
||||
(foundKeys[1][sector][0] == 0) ? "------ " : sprint_hex_inrow(&foundKeys[1][sector][1], AES_KEY_LEN));
|
||||
for (uint8_t s = startSector; s <= endSector; s++) {
|
||||
if (printedHeader == false) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "-----+----------------------------------+----------------------------------");
|
||||
PrintAndLogEx(INFO, " Sec | key A | key B");
|
||||
PrintAndLogEx(INFO, "-----+----------------------------------+----------------------------------");
|
||||
printedHeader = true;
|
||||
}
|
||||
|
||||
if (foundKeys[0][s][0]) {
|
||||
snprintf(strA, sizeof(strA), _GREEN_("%s"), sprint_hex_inrow(&foundKeys[0][s][1], AES_KEY_LEN));
|
||||
} else {
|
||||
snprintf(strA, sizeof(strA), _RED_("%s"), "--------------------------------");
|
||||
}
|
||||
|
||||
if (foundKeys[1][s][0]) {
|
||||
snprintf(strB, sizeof(strB), _GREEN_("%s"), sprint_hex_inrow(&foundKeys[1][s][1], AES_KEY_LEN));
|
||||
} else {
|
||||
snprintf(strB, sizeof(strB), _RED_("%s"), "--------------------------------");
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, " " _YELLOW_("%03d") " | %s | %s", s, strA, strB);
|
||||
}
|
||||
if (!printedHeader)
|
||||
|
||||
if (printedHeader == false)
|
||||
PrintAndLogEx(INFO, "No keys found(");
|
||||
else
|
||||
PrintAndLogEx(INFO, "'------+--------------------------------+--------------------------------'\n");
|
||||
PrintAndLogEx(INFO, "-----+----------------------------------+----------------------------------\n");
|
||||
|
||||
// save keys to json
|
||||
if ((jsonnamelen > 0) && printedHeader) {
|
||||
|
@ -1581,7 +1610,7 @@ int CmdHFMFPNDEFRead(const char *Cmd) {
|
|||
}
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
if (!datalen) {
|
||||
if (datalen == 0) {
|
||||
PrintAndLogEx(ERR, "no NDEF data");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
@ -1595,8 +1624,20 @@ int CmdHFMFPNDEFRead(const char *Cmd) {
|
|||
if (fnlen != 0) {
|
||||
saveFile(filename, ".bin", data, datalen);
|
||||
}
|
||||
NDEFDecodeAndPrint(data, datalen, verbose);
|
||||
PrintAndLogEx(HINT, "Try " _YELLOW_("`hf mfp ndefread -vv`") " for more details");
|
||||
|
||||
res = NDEFDecodeAndPrint(data, datalen, verbose);
|
||||
if (res != PM3_SUCCESS) {
|
||||
PrintAndLogEx(INFO, "Trying to parse NDEF records w/o NDEF header");
|
||||
res = NDEFRecordsDecodeAndPrint(data, datalen, verbose);
|
||||
}
|
||||
|
||||
if (verbose == false) {
|
||||
PrintAndLogEx(HINT, "Try " _YELLOW_("`hf mfp ndefread -v`") " for more details");
|
||||
} else {
|
||||
if (verbose2 == false) {
|
||||
PrintAndLogEx(HINT, "Try " _YELLOW_("`hf mfp ndefread -vv`") " for more details");
|
||||
}
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -1305,10 +1305,10 @@ typedef struct {
|
|||
} mfu_otp_identify_t;
|
||||
|
||||
static mfu_otp_identify_t mfu_otp_ident_table[] = {
|
||||
{ "SALTO", 12, 4, "534C544F", ul_c_otpgenA, NULL },
|
||||
// { "SAFLOK", 12, 4, NULL, ul_c_otpgenB, NULL },
|
||||
// { "VINGCARD", 12, 4, NULL, ul_c_otpgenC, NULL },
|
||||
// { "DORMA KABA", 12, 4, NULL, ul_c_otpgenD, NULL },
|
||||
{ "SALTO tag", 12, 4, "534C544F", ul_c_otpgenA, NULL },
|
||||
// { "SAFLOK tag", 12, 4, NULL, ul_c_otpgenB, NULL },
|
||||
// { "VINGCARD tag", 12, 4, NULL, ul_c_otpgenC, NULL },
|
||||
// { "DORMA KABA tag", 12, 4, NULL, ul_c_otpgenD, NULL },
|
||||
{ NULL, 0, 0, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -1391,6 +1391,18 @@ static mfu_identify_t mfu_ident_table[] = {
|
|||
"hf mfu dump -k %08x"
|
||||
},
|
||||
*/
|
||||
{
|
||||
"Philips Toothbrush", "0004040201010F03",
|
||||
16, 20, "0310D1010C55027068696C6970732E636F6DFE00",
|
||||
ul_ev1_pwdgen_def, ul_ev1_packgen_def,
|
||||
"hf mfu pwdgen -r"
|
||||
},
|
||||
{
|
||||
"Philips Toothbrush", "0004040201010F03",
|
||||
16, 36, "0320D1011C55027068696C6970732E636F6D2F6E6663627275736868656164746170FE00",
|
||||
ul_ev1_pwdgen_def, ul_ev1_packgen_def,
|
||||
"hf mfu pwdgen -r"
|
||||
},
|
||||
{NULL, NULL, 0, 0, NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
@ -1412,7 +1424,7 @@ static mfu_identify_t *mfu_match_fingerprint(uint8_t *version, uint8_t *data) {
|
|||
uint8_t mtmp[40] = {0};
|
||||
param_gethex_to_eol(mfu_ident_table[i].match, 0, mtmp, sizeof(mtmp), &ml);
|
||||
|
||||
bool m2 = (memcmp(mtmp, data + mfu_ident_table[i].mpos, mfu_ident_table[i].mlen) == 0);
|
||||
bool m2 = (memcmp(mtmp, data + mfu_ident_table[i].mpos, mfu_ident_table[i].mlen) == 0);
|
||||
if (m2) {
|
||||
PrintAndLogEx(DEBUG, "(fingerprint) found %s", mfu_ident_table[i].desc);
|
||||
return &mfu_ident_table[i];
|
||||
|
@ -1815,6 +1827,8 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
|
|||
else
|
||||
locked = true;
|
||||
|
||||
mfu_fingerprint(tagtype, has_auth_key, authkeyptr, ak_len);
|
||||
|
||||
if ((tagtype & MAGIC)) {
|
||||
//just read key
|
||||
uint8_t ulc_deskey[16] = {0x00};
|
||||
|
@ -3581,6 +3595,8 @@ static int CmdHF14AMfUPwdGen(const char *Cmd) {
|
|||
if (selftest)
|
||||
return generator_selftest();
|
||||
|
||||
uint8_t philips_mfg[10] = {0};
|
||||
|
||||
if (use_tag) {
|
||||
// read uid from tag
|
||||
int res = ul_read_uid(uid);
|
||||
|
@ -3588,6 +3604,19 @@ static int CmdHF14AMfUPwdGen(const char *Cmd) {
|
|||
return res;
|
||||
}
|
||||
|
||||
iso14a_card_select_t card;
|
||||
if (ul_select(&card)) {
|
||||
// Philips toothbrush needs page 0x21-0x23
|
||||
uint8_t data[16] = {0x00};
|
||||
int status = ul_read(0x21, data, sizeof(data));
|
||||
if (status == -1) {
|
||||
PrintAndLogEx(DEBUG, "Error: tag didn't answer to READ");
|
||||
} else if (status == 16) {
|
||||
memcpy(philips_mfg, data + 2, sizeof(philips_mfg));
|
||||
}
|
||||
DropField();
|
||||
}
|
||||
|
||||
} else {
|
||||
if (u_len != 7) {
|
||||
PrintAndLogEx(WARNING, "Key must be 7 hex bytes");
|
||||
|
@ -3595,24 +3624,28 @@ static int CmdHF14AMfUPwdGen(const char *Cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "------------------.---------------");
|
||||
PrintAndLogEx(INFO, "------------------.------------------");
|
||||
PrintAndLogEx(INFO, " Using UID 4b: " _YELLOW_("%s"), sprint_hex(uid, 4));
|
||||
PrintAndLogEx(INFO, " Using UID 7b: " _YELLOW_("%s"), sprint_hex(uid, 7));
|
||||
PrintAndLogEx(INFO, "----------------------------------");
|
||||
PrintAndLogEx(INFO, " algo | pwd | pack");
|
||||
PrintAndLogEx(INFO, "-----------------+----------+-----");
|
||||
PrintAndLogEx(INFO, " Transport EV1 | %08X | %04X", ul_ev1_pwdgenA(uid), ul_ev1_packgenA(uid));
|
||||
PrintAndLogEx(INFO, " Amiibo | %08X | %04X", ul_ev1_pwdgenB(uid), ul_ev1_packgenB(uid));
|
||||
PrintAndLogEx(INFO, " Lego Dimension | %08X | %04X", ul_ev1_pwdgenC(uid), ul_ev1_packgenC(uid));
|
||||
PrintAndLogEx(INFO, " XYZ 3D printer | %08X | %04X", ul_ev1_pwdgenD(uid), ul_ev1_packgenD(uid));
|
||||
PrintAndLogEx(INFO, " Xiaomi purifier | %08X | %04X", ul_ev1_pwdgenE(uid), ul_ev1_packgenE(uid));
|
||||
PrintAndLogEx(INFO, " NTAG tools | %08X | %04X", ul_ev1_pwdgenF(uid), ul_ev1_packgen_def(uid));
|
||||
PrintAndLogEx(INFO, "-----------------+----------+-----");
|
||||
PrintAndLogEx(INFO, "-------------------------------------");
|
||||
PrintAndLogEx(INFO, " algo | pwd | pack");
|
||||
PrintAndLogEx(INFO, "--------------------+----------+-----");
|
||||
PrintAndLogEx(INFO, " Transport EV1 | %08X | %04X", ul_ev1_pwdgenA(uid), ul_ev1_packgenA(uid));
|
||||
PrintAndLogEx(INFO, " Amiibo | %08X | %04X", ul_ev1_pwdgenB(uid), ul_ev1_packgenB(uid));
|
||||
PrintAndLogEx(INFO, " Lego Dimension | %08X | %04X", ul_ev1_pwdgenC(uid), ul_ev1_packgenC(uid));
|
||||
PrintAndLogEx(INFO, " XYZ 3D printer | %08X | %04X", ul_ev1_pwdgenD(uid), ul_ev1_packgenD(uid));
|
||||
PrintAndLogEx(INFO, " Xiaomi purifier | %08X | %04X", ul_ev1_pwdgenE(uid), ul_ev1_packgenE(uid));
|
||||
PrintAndLogEx(INFO, " NTAG tools | %08X | %04X", ul_ev1_pwdgenF(uid), ul_ev1_packgen_def(uid));
|
||||
if (philips_mfg[0] != 0) {
|
||||
PrintAndLogEx(INFO, " Philips Toothbrush | %08X | %04X", ul_ev1_pwdgenG(uid, philips_mfg), ul_ev1_packgenG(uid, philips_mfg));
|
||||
}
|
||||
PrintAndLogEx(INFO, "--------------------+----------+-----");
|
||||
PrintAndLogEx(INFO, " Vingcard algo");
|
||||
PrintAndLogEx(INFO, " Saflok algo");
|
||||
PrintAndLogEx(INFO, " SALTO algo");
|
||||
PrintAndLogEx(INFO, " Dorma Kaba algo");
|
||||
PrintAndLogEx(INFO, "----------------------------------");
|
||||
PrintAndLogEx(INFO, " STiD algo");
|
||||
PrintAndLogEx(INFO, "-------------------------------------");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -570,8 +570,12 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
|||
//1 CRC-command, CRC ok
|
||||
//2 Not crc-command
|
||||
|
||||
//--- Draw the data column
|
||||
char line[18][160] = {{0}};
|
||||
// Draw the data column
|
||||
#define TRACE_MAX_LINES 36
|
||||
// number of hex bytes to be printed per row (16 data + 2 crc)
|
||||
#define TRACE_MAX_HEX_BYTES 18
|
||||
|
||||
char line[TRACE_MAX_LINES][160] = {{0}};
|
||||
|
||||
if (data_len == 0) {
|
||||
if (protocol == ICLASS && duration == 2048) {
|
||||
|
@ -582,9 +586,10 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
|||
snprintf(line[0], sizeof(line[0]), "<empty trace - possible error>");
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t partialbytebuff = 0;
|
||||
uint8_t offset = 0;
|
||||
for (int j = 0; j < data_len && j / 18 < 18; j++) {
|
||||
for (int j = 0; j < data_len && (j / TRACE_MAX_HEX_BYTES) < TRACE_MAX_HEX_BYTES; j++) {
|
||||
uint8_t parityBits = parityBytes[j >> 3];
|
||||
if (protocol != LEGIC
|
||||
&& protocol != ISO_14443B
|
||||
|
@ -602,11 +607,14 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
|||
&& (oddparity8(frame[j]) != ((parityBits >> (7 - (j & 0x0007))) & 0x01))) {
|
||||
|
||||
snprintf(line[j / 18] + ((j % 18) * 4), 120, "%02x! ", frame[j]);
|
||||
|
||||
} else if (protocol == ICLASS && hdr->isResponse == false) {
|
||||
|
||||
uint8_t parity = 0;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
parity ^= ((frame[0] >> i) & 1);
|
||||
}
|
||||
|
||||
if (parity == ((frame[0] >> 7) & 1)) {
|
||||
snprintf(line[j / 18] + ((j % 18) * 4), 120, "%02x ", frame[j]);
|
||||
} else {
|
||||
|
@ -631,10 +639,8 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
|||
|
||||
}
|
||||
|
||||
|
||||
uint8_t crc_format_string_offset = 0;
|
||||
if (markCRCBytes && data_len > 2) {
|
||||
//CRC-command
|
||||
// CRC-command
|
||||
if (((protocol == PROTO_HITAG1) || (protocol == PROTO_HITAGS)) && (data_len > 1)) {
|
||||
// Note that UID REQUEST response has no CRC, but we don't know
|
||||
// if the response we see is a UID
|
||||
|
@ -647,36 +653,42 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
|||
|
||||
if (crcStatus == 0 || crcStatus == 1) {
|
||||
|
||||
char *pos1 = line[(data_len - 2) / 18];
|
||||
pos1 += (((data_len - 2) % 18) * 4) - 1;
|
||||
char *pos1 = line[(data_len - 2) / TRACE_MAX_HEX_BYTES];
|
||||
pos1 += (((data_len - 2) % TRACE_MAX_HEX_BYTES) * 4) - 1;
|
||||
|
||||
(*(pos1 + 6 + 1)) = '\0';
|
||||
|
||||
char *cb_str = str_dup(pos1 + 1);
|
||||
|
||||
if (hdr->isResponse) {
|
||||
if (g_session.supports_colors) {
|
||||
if (crcStatus == 0) {
|
||||
snprintf(pos1, 24, " " _RED_("%s") " ", cb_str);
|
||||
} else {
|
||||
snprintf(pos1, 24, " " _GREEN_("%s") " ", cb_str);
|
||||
}
|
||||
crc_format_string_offset = 9;
|
||||
if (g_session.supports_colors) {
|
||||
if (crcStatus == 0) {
|
||||
snprintf(pos1, 24, AEND " " _RED_("%s"), cb_str);
|
||||
} else {
|
||||
snprintf(pos1, 9, "[%s]", cb_str);
|
||||
snprintf(pos1, 24, AEND " " _GREEN_("%s"), cb_str);
|
||||
}
|
||||
} else {
|
||||
snprintf(pos1, 9, "[%s]", cb_str);
|
||||
}
|
||||
|
||||
// odd case of second crc byte is alone in a new line
|
||||
if (strlen(cb_str) < 5) {
|
||||
|
||||
free(cb_str);
|
||||
|
||||
pos1 = line[((data_len - 2) / TRACE_MAX_HEX_BYTES) + 1];
|
||||
cb_str = str_dup(pos1);
|
||||
|
||||
if (g_session.supports_colors) {
|
||||
if (crcStatus == 0) {
|
||||
snprintf(pos1, 24, AEND " " _RED_("%s") " ", cb_str);
|
||||
snprintf(pos1, 24, _RED_("%s"), cb_str);
|
||||
} else {
|
||||
snprintf(pos1, 24, AEND " " _GREEN_("%s") " ", cb_str);
|
||||
snprintf(pos1, 24, _GREEN_("%s"), cb_str);
|
||||
}
|
||||
crc_format_string_offset = 13;
|
||||
} else {
|
||||
snprintf(pos1, 9, "[%s]", cb_str);
|
||||
}
|
||||
}
|
||||
|
||||
free(cb_str);
|
||||
}
|
||||
}
|
||||
|
@ -688,8 +700,8 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
|||
|
||||
// mark short bytes (less than 8 Bit + Parity)
|
||||
if (protocol == ISO_14443A ||
|
||||
protocol == PROTO_MIFARE ||
|
||||
protocol == THINFILM) {
|
||||
protocol == PROTO_MIFARE ||
|
||||
protocol == THINFILM) {
|
||||
|
||||
// approximated with 128 * (9 * data_len);
|
||||
uint16_t bitime = 1056 + 32;
|
||||
|
@ -791,8 +803,14 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
|||
}
|
||||
}
|
||||
|
||||
int num_lines = MIN((data_len - 1) / 18 + 1, 18);
|
||||
int str_padder = 72;
|
||||
int num_lines = MIN((data_len - 1) / TRACE_MAX_HEX_BYTES + 1, TRACE_MAX_HEX_BYTES);
|
||||
|
||||
for (int j = 0; j < num_lines ; j++) {
|
||||
|
||||
bool last_line = (j == num_lines - 1);
|
||||
str_padder = 72;
|
||||
|
||||
if (j == 0) {
|
||||
|
||||
uint32_t time1 = hdr->timestamp - first_hdr->timestamp;
|
||||
|
@ -802,25 +820,30 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
|||
time2 = duration;
|
||||
}
|
||||
|
||||
// ansi codes addes extra chars that needs to be taken in consideration.
|
||||
if (last_line && (memcmp(crc, "\x20\x20\x20\x20", 4) != 0) && g_session.supports_colors && markCRCBytes) {
|
||||
str_padder = 85;
|
||||
}
|
||||
|
||||
if (hdr->isResponse) {
|
||||
// tag row
|
||||
if (use_us) {
|
||||
PrintAndLogEx(NORMAL, " %10.1f | %10.1f | Tag |%-*s | %s| %s",
|
||||
(float)time1 / 13.56,
|
||||
(float)time2 / 13.56,
|
||||
72 + crc_format_string_offset,
|
||||
str_padder,
|
||||
line[j],
|
||||
(j == num_lines - 1) ? crc : " ",
|
||||
(j == num_lines - 1) ? explanation : ""
|
||||
(last_line) ? crc : " ",
|
||||
(last_line) ? explanation : ""
|
||||
);
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL, " %10u | %10u | Tag |%-*s | %s| %s",
|
||||
time1,
|
||||
time2,
|
||||
72 + crc_format_string_offset,
|
||||
str_padder,
|
||||
line[j],
|
||||
(j == num_lines - 1) ? crc : " ",
|
||||
(j == num_lines - 1) ? explanation : ""
|
||||
(last_line) ? crc : " ",
|
||||
(last_line) ? explanation : ""
|
||||
);
|
||||
}
|
||||
} else {
|
||||
|
@ -830,41 +853,51 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
|||
_YELLOW_(" %10.1f") " | " _YELLOW_("%10.1f") " | " _YELLOW_("Rdr") " |" _YELLOW_("%-*s")" | " _YELLOW_("%s") "| " _YELLOW_("%s"),
|
||||
(float)time1 / 13.56,
|
||||
(float)time2 / 13.56,
|
||||
72 + crc_format_string_offset,
|
||||
str_padder,
|
||||
line[j],
|
||||
(j == num_lines - 1) ? crc : " ",
|
||||
(j == num_lines - 1) ? explanation : ""
|
||||
(last_line) ? crc : " ",
|
||||
(last_line) ? explanation : ""
|
||||
);
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL,
|
||||
_YELLOW_(" %10u") " | " _YELLOW_("%10u") " | " _YELLOW_("Rdr") " |" _YELLOW_("%-*s")" | " _YELLOW_("%s") "| " _YELLOW_("%s"),
|
||||
time1,
|
||||
time2,
|
||||
72 + crc_format_string_offset,
|
||||
str_padder,
|
||||
line[j],
|
||||
(j == num_lines - 1) ? crc : " ",
|
||||
(j == num_lines - 1) ? explanation : ""
|
||||
(last_line) ? crc : " ",
|
||||
(last_line) ? explanation : ""
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
if (last_line && (memcmp(crc, "\x20\x20\x20\x20", 4) != 0) && g_session.supports_colors && markCRCBytes) {
|
||||
str_padder = 85;
|
||||
// odd case of multiline, and last single byte on empty row has been colorised...
|
||||
if (strlen(line[j]) < 14) {
|
||||
str_padder = 81;
|
||||
}
|
||||
}
|
||||
|
||||
if (hdr->isResponse) {
|
||||
PrintAndLogEx(NORMAL, " | | |%-*s | %s| %s",
|
||||
72 + crc_format_string_offset,
|
||||
str_padder,
|
||||
line[j],
|
||||
(j == num_lines - 1) ? crc : " ",
|
||||
(j == num_lines - 1) ? explanation : ""
|
||||
last_line ? crc : " ",
|
||||
last_line ? explanation : ""
|
||||
);
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL, " | | |" _YELLOW_("%-*s")" | " _YELLOW_("%s") "| " _YELLOW_("%s"),
|
||||
72 + crc_format_string_offset,
|
||||
str_padder,
|
||||
line[j],
|
||||
(j == num_lines - 1) ? crc : " ",
|
||||
(j == num_lines - 1) ? explanation : ""
|
||||
last_line ? crc : " ",
|
||||
last_line ? explanation : ""
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -875,8 +908,10 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
|||
memset(explanation, 0x00, sizeof(explanation));
|
||||
annotateIso14443a(explanation, sizeof(explanation), mfData, mfDataLen, hdr->isResponse);
|
||||
uint8_t crcc = iso14443A_CRC_check(hdr->isResponse, mfData, mfDataLen);
|
||||
|
||||
//iceman: colorise crc bytes here will need a refactor of code from above.
|
||||
PrintAndLogEx(NORMAL, " | | * |%-*s | %-4s| %s",
|
||||
72 + crc_format_string_offset,
|
||||
str_padder,
|
||||
sprint_hex_inrow_spaces(mfData, mfDataLen, 2),
|
||||
(crcc == 0 ? _RED_(" !! ") : (crcc == 1 ? _GREEN_(" ok ") : " ")),
|
||||
explanation);
|
||||
|
|
|
@ -1075,10 +1075,11 @@ static int ndefRecordDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen, b
|
|||
return res;
|
||||
|
||||
ndefPrintHeader(&NDEFHeader, verbose);
|
||||
PrintAndLogEx(INFO, "");
|
||||
PrintAndLogEx(INFO, _CYAN_("Payload info"));
|
||||
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, "");
|
||||
PrintAndLogEx(INFO, _CYAN_("Payload info"));
|
||||
|
||||
if (NDEFHeader.TypeLen) {
|
||||
PrintAndLogEx(INFO, "Type data");
|
||||
print_buffer(NDEFHeader.Type, NDEFHeader.TypeLen, 1);
|
||||
|
@ -1229,7 +1230,9 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) {
|
|||
break;
|
||||
}
|
||||
case 0xFE: {
|
||||
PrintAndLogEx(SUCCESS, "NDEF Terminator detected");
|
||||
if (verbose) {
|
||||
PrintAndLogEx(SUCCESS, "NDEF Terminator detected");
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
default: {
|
||||
|
|
|
@ -250,16 +250,13 @@ main_loop(char *script_cmds_file, char *script_cmd, bool stayInCommandLoop) {
|
|||
if (g_session.incognito) {
|
||||
PrintAndLogEx(INFO, "No history will be recorded");
|
||||
} else {
|
||||
bool loaded_history = false;
|
||||
if (searchHomeFilePath(&g_session.history_path, NULL, PROXHISTORY, true) != PM3_SUCCESS) {
|
||||
g_session.history_path = NULL;
|
||||
} else {
|
||||
loaded_history = (pm3line_load_history(g_session.history_path) == PM3_SUCCESS);
|
||||
}
|
||||
if (loaded_history) {
|
||||
pm3line_install_signals();
|
||||
} else {
|
||||
PrintAndLogEx(ERR, "No history will be recorded");
|
||||
} else {
|
||||
if (pm3line_load_history(g_session.history_path) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(INFO, "No previous history could be loaded");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,10 +42,14 @@ void init_table(CrcType_t crctype) {
|
|||
case CRC_15693:
|
||||
case CRC_ICLASS:
|
||||
case CRC_CRYPTORF:
|
||||
case CRC_KERMIT:
|
||||
generate_table(CRC16_POLY_CCITT, true);
|
||||
break;
|
||||
case CRC_FELICA:
|
||||
case CRC_XMODEM:
|
||||
case CRC_CCITT:
|
||||
case CRC_11784:
|
||||
case CRC_PHILIPS:
|
||||
generate_table(CRC16_POLY_CCITT, false);
|
||||
break;
|
||||
case CRC_LEGIC:
|
||||
|
@ -54,15 +58,6 @@ void init_table(CrcType_t crctype) {
|
|||
case CRC_LEGIC_16:
|
||||
generate_table(CRC16_POLY_LEGIC_16, true);
|
||||
break;
|
||||
case CRC_CCITT:
|
||||
generate_table(CRC16_POLY_CCITT, false);
|
||||
break;
|
||||
case CRC_KERMIT:
|
||||
generate_table(CRC16_POLY_CCITT, true);
|
||||
break;
|
||||
case CRC_11784:
|
||||
generate_table(CRC16_POLY_CCITT, false);
|
||||
break;
|
||||
case CRC_NONE:
|
||||
crc_table_init = false;
|
||||
current_crc_type = CRC_NONE;
|
||||
|
@ -210,6 +205,9 @@ void compute_crc(CrcType_t ct, const uint8_t *d, size_t n, uint8_t *first, uint8
|
|||
case CRC_LEGIC_16:
|
||||
// TODO
|
||||
return;
|
||||
case CRC_PHILIPS:
|
||||
crc = crc16_philips(d, n);
|
||||
break;
|
||||
case CRC_NONE:
|
||||
return;
|
||||
}
|
||||
|
@ -244,6 +242,8 @@ uint16_t Crc16ex(CrcType_t ct, const uint8_t *d, size_t n) {
|
|||
case CRC_LEGIC_16:
|
||||
// TODO
|
||||
return 0;
|
||||
case CRC_PHILIPS:
|
||||
return crc16_philips(d, n);
|
||||
case CRC_NONE:
|
||||
default:
|
||||
break;
|
||||
|
@ -290,6 +290,8 @@ bool check_crc(CrcType_t ct, const uint8_t *d, size_t n) {
|
|||
case CRC_LEGIC_16:
|
||||
// TODO
|
||||
return false;
|
||||
case CRC_PHILIPS:
|
||||
return (crc16_philips(d, n) == 0);
|
||||
case CRC_NONE:
|
||||
default:
|
||||
break;
|
||||
|
@ -350,3 +352,6 @@ uint16_t crc16_legic(uint8_t const *d, size_t n, uint8_t uidcrc) {
|
|||
return crc16_fast(d, n, initial, true, false);
|
||||
}
|
||||
|
||||
uint16_t crc16_philips(uint8_t const *d, size_t n) {
|
||||
return crc16_fast(d, n, 0x49A3, false, false);
|
||||
}
|
|
@ -42,6 +42,7 @@ typedef enum {
|
|||
CRC_KERMIT,
|
||||
CRC_XMODEM,
|
||||
CRC_CRYPTORF,
|
||||
CRC_PHILIPS,
|
||||
} CrcType_t;
|
||||
|
||||
uint16_t update_crc16_ex(uint16_t crc, uint8_t c, uint16_t polynomial);
|
||||
|
@ -78,6 +79,9 @@ uint16_t crc16_iclass(uint8_t const *d, size_t n);
|
|||
// ie: uidcrc = 0x78 then initial_value == 0x7878
|
||||
uint16_t crc16_legic(uint8_t const *d, size_t n, uint8_t uidcrc);
|
||||
|
||||
// Calculate CRC-16/ Philips.
|
||||
uint16_t crc16_philips(uint8_t const *d, size_t n);
|
||||
|
||||
// table implementation
|
||||
void init_table(CrcType_t crctype);
|
||||
void reset_table(void);
|
||||
|
|
|
@ -195,6 +195,20 @@ uint32_t ul_ev1_pwdgenF(const uint8_t *uid) {
|
|||
return pwd;
|
||||
}
|
||||
|
||||
// Solution from @atc1441
|
||||
// https://gist.github.com/atc1441/41af75048e4c22af1f5f0d4c1d94bb56
|
||||
// Philips Sonicare toothbrush NFC head
|
||||
uint32_t ul_ev1_pwdgenG(const uint8_t *uid, const uint8_t *mfg) {
|
||||
|
||||
init_table(CRC_PHILIPS);
|
||||
// UID
|
||||
uint32_t crc1 = crc16_philips(uid, 7);
|
||||
// MFG string
|
||||
uint32_t crc2 = crc16_fast(mfg, 10, crc1, false, false);
|
||||
|
||||
return (BSWAP_16(crc2) << 16 | BSWAP_16(crc1));
|
||||
}
|
||||
|
||||
// pack generation for algo 1-3
|
||||
uint16_t ul_ev1_packgenA(const uint8_t *uid) {
|
||||
uint16_t pack = (uid[0] ^ uid[1] ^ uid[2]) << 8 | (uid[2] ^ 8);
|
||||
|
@ -224,13 +238,26 @@ uint16_t ul_ev1_packgenD(const uint8_t *uid) {
|
|||
p ^= 0x5555;
|
||||
return BSWAP_16(p & 0xFFFF);
|
||||
}
|
||||
|
||||
uint16_t ul_ev1_packgenE(const uint8_t *uid) {
|
||||
|
||||
uint32_t pwd = ul_ev1_pwdgenE(uid);
|
||||
return (0xAD << 8 | ((pwd >> 24) & 0xFF));
|
||||
}
|
||||
|
||||
uint16_t ul_ev1_packgenG(const uint8_t *uid, const uint8_t *mfg) {
|
||||
init_table(CRC_PHILIPS);
|
||||
// UID
|
||||
uint32_t crc1 = crc16_philips(uid, 7);
|
||||
// MFG string
|
||||
uint32_t crc2 = crc16_fast(mfg, 10, crc1, false, false);
|
||||
// PWD
|
||||
uint32_t pwd = (BSWAP_16(crc2) << 16 | BSWAP_16(crc1));
|
||||
|
||||
uint8_t pb[4];
|
||||
num_to_bytes(pwd, 4, pb);
|
||||
return BSWAP_16(crc16_fast(pb, 4, crc2, false, false));
|
||||
}
|
||||
|
||||
|
||||
// default shims
|
||||
uint32_t ul_ev1_pwdgen_def(const uint8_t *uid) {
|
||||
|
@ -556,7 +583,7 @@ int mfc_algo_touch_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *
|
|||
|
||||
int generator_selftest(void) {
|
||||
#ifndef ON_DEVICE
|
||||
#define NUM_OF_TEST 8
|
||||
#define NUM_OF_TEST 9
|
||||
|
||||
PrintAndLogEx(INFO, "PWD / KEY generator selftest");
|
||||
PrintAndLogEx(INFO, "----------------------------");
|
||||
|
@ -606,18 +633,27 @@ int generator_selftest(void) {
|
|||
testresult++;
|
||||
PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid6, 7), pwd6, success ? "OK" : "->A9C4C3C0<--");
|
||||
|
||||
uint8_t uid7[] = {0x04, 0x0D, 0x4B, 0x5A, 0xC5, 0x71, 0x81};
|
||||
uint8_t mfg[] = {0x32, 0x31, 0x30, 0x36, 0x32, 0x38, 0x20, 0x35, 0x32, 0x4D};
|
||||
uint32_t pwd7 = ul_ev1_pwdgenG(uid7, mfg);
|
||||
success = (pwd7 == 0xFBCFACC1);
|
||||
if (success)
|
||||
testresult++;
|
||||
PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid7, 7), pwd7, success ? "OK" : "->FBCFACC1<--");
|
||||
|
||||
|
||||
// uint8_t uid5[] = {0x11, 0x22, 0x33, 0x44};
|
||||
// uint64_t key1 = mfc_algo_a(uid5);
|
||||
// success = (key1 == 0xD1E2AA68E39A);
|
||||
// PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %"PRIx64" - %s", sprint_hex(uid5, 4), key1, success ? "OK" : "->D1E2AA68E39A<--");
|
||||
|
||||
uint8_t uid7[] = {0x74, 0x57, 0xCA, 0xA9};
|
||||
uint64_t key7 = 0;
|
||||
mfc_algo_sky_one(uid7, 15, 0, &key7);
|
||||
success = (key7 == 0x82c7e64bc565);
|
||||
uint8_t uid8[] = {0x74, 0x57, 0xCA, 0xA9};
|
||||
uint64_t key8 = 0;
|
||||
mfc_algo_sky_one(uid8, 15, 0, &key8);
|
||||
success = (key8 == 0x82c7e64bc565);
|
||||
if (success)
|
||||
testresult++;
|
||||
PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %"PRIx64" - %s", sprint_hex(uid7, 4), key7, success ? "OK" : "->82C7E64BC565<--");
|
||||
PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %"PRIx64" - %s", sprint_hex(uid8, 4), key8, success ? "OK" : "->82C7E64BC565<--");
|
||||
|
||||
|
||||
uint32_t lf_id = lf_t55xx_white_pwdgen(0x00000080);
|
||||
|
|
|
@ -28,6 +28,7 @@ uint32_t ul_ev1_pwdgenC(const uint8_t *uid);
|
|||
uint32_t ul_ev1_pwdgenD(const uint8_t *uid);
|
||||
uint32_t ul_ev1_pwdgenE(const uint8_t *uid);
|
||||
uint32_t ul_ev1_pwdgenF(const uint8_t *uid);
|
||||
uint32_t ul_ev1_pwdgenG(const uint8_t *uid, const uint8_t *mfg);
|
||||
|
||||
uint16_t ul_ev1_packgen_def(const uint8_t *uid);
|
||||
uint16_t ul_ev1_packgenA(const uint8_t *uid);
|
||||
|
@ -35,6 +36,7 @@ uint16_t ul_ev1_packgenB(const uint8_t *uid);
|
|||
uint16_t ul_ev1_packgenC(const uint8_t *uid);
|
||||
uint16_t ul_ev1_packgenD(const uint8_t *uid);
|
||||
uint16_t ul_ev1_packgenE(const uint8_t *uid);
|
||||
uint16_t ul_ev1_packgenG(const uint8_t *uid, const uint8_t *mfg);
|
||||
|
||||
uint32_t ul_c_otpgenA(const uint8_t *uid);
|
||||
|
||||
|
|
7
pm3
7
pm3
|
@ -144,7 +144,8 @@ function get_pm3_list_Windows {
|
|||
DEV=${DEV/ */}
|
||||
#prevent soft bricking when using pm3-flash-all on an outdated bootloader
|
||||
if [ $(basename -- "$0") = "pm3-flash-all" ]; then
|
||||
if [ ! $(wmic /locale:ms_409 path Win32_SerialPort Where "DeviceID='$DEV'" Get PNPDeviceID 2>/dev/null | awk -b '/^USB/{print $1}') = "USB\VID_9AC4&PID_4B8F\ICEMAN" ]; then
|
||||
line=$(wmic /locale:ms_409 path Win32_SerialPort Where "DeviceID='$DEV'" Get PNPDeviceID 2>/dev/null | awk -b '/^USB/{print $1}');
|
||||
if [[ ! $line =~ ^"USB\VID_9AC4&PID_4B8F\ICEMAN" ]]; then
|
||||
echo -e "\033[0;31m[!] Using pm3-flash-all on an oudated bootloader, use pm3-flash-bootrom first!"
|
||||
exit 1
|
||||
fi
|
||||
|
@ -189,9 +190,11 @@ function get_pm3_list_WSL {
|
|||
DEV=$(echo $DEV | sed -nr 's#^COM([0-9]+)\b#/dev/ttyS\1#p')
|
||||
# ttyS counterpart takes some more time to appear
|
||||
if [ -e "$DEV" ]; then
|
||||
|
||||
#prevent soft bricking when using pm3-flash-all on an outdated bootloader
|
||||
if [ $(basename -- "$0") = "pm3-flash-all" ]; then
|
||||
if [ ! $($PSHEXE -command "Get-CimInstance -ClassName Win32_serialport | Where-Object {\$_.DeviceID -eq '$_comport'} | Select -expandproperty PNPDeviceID" 2>/dev/null | tr -dc '[:print:]') = "USB\VID_9AC4&PID_4B8F\ICEMAN" ]; then
|
||||
line=$($PSHEXE -command "Get-CimInstance -ClassName Win32_serialport | Where-Object {\$_.DeviceID -eq '$_comport'} | Select -expandproperty PNPDeviceID" 2>/dev/null | tr -dc '[:print:]');
|
||||
if [[ ! $line =~ ^"USB\VID_9AC4&PID_4B8F\ICEMAN" ]]; then
|
||||
echo -e "\033[0;31m[!] Using pm3-flash-all on an oudated bootloader, use pm3-flash-bootrom first!"
|
||||
exit 1
|
||||
fi
|
||||
|
|
Loading…
Reference in a new issue