Merge remote-tracking branch 'upstream/master' into hfmfdes-clang-warn

This commit is contained in:
Uli Heilmeier 2020-04-09 14:39:46 +02:00
commit c96af80e44
3 changed files with 94 additions and 81 deletions

View file

@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... 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] ## [unreleased][unreleased]
- Updated 'legic.lua' and 'legic_clone.lua' script - works with current command set (@Pizza_4u)
- Rewrote `hf mfdes` functions and added apdu debugging (@bkerler) - Rewrote `hf mfdes` functions and added apdu debugging (@bkerler)
- Add Mifare Desfire GetDFNames and improve HF MFDES Enum output (@bkerler) - Add Mifare Desfire GetDFNames and improve HF MFDES Enum output (@bkerler)
- Fix Mifare Desfire select appid handling (@bkerler) - Fix Mifare Desfire select appid handling (@bkerler)

View file

@ -62,6 +62,7 @@ static int CmdHelp(const char *Cmd);
*/ */
int DESFIRESendApdu(bool activate_field, bool leavefield_on, sAPDU apdu, uint8_t *result, int max_result_len, int *result_len, uint16_t *sw) { int DESFIRESendApdu(bool activate_field, bool leavefield_on, sAPDU apdu, uint8_t *result, int max_result_len, int *result_len, uint16_t *sw) {
*result_len = 0; *result_len = 0;
if (sw) *sw = 0; if (sw) *sw = 0;
@ -176,8 +177,8 @@ static desfire_cardtype_t getCardType(uint8_t major, uint8_t minor) {
//none //none
static int test_desfire_authenticate() { static int test_desfire_authenticate() {
uint8_t c = 0x00; uint8_t data[] = {0x00};
sAPDU apdu = {0x90, MFDES_AUTHENTICATE, 0x00, 0x00, 0x01, &c}; // 0x0A, KEY 0 sAPDU apdu = {0x90, MFDES_AUTHENTICATE, 0x00, 0x00, 0x01, data}; // 0x0A, KEY 0
int recv_len = 0; int recv_len = 0;
uint16_t sw = 0; uint16_t sw = 0;
return send_desfire_cmd(&apdu, false, NULL, &recv_len, &sw, 0); return send_desfire_cmd(&apdu, false, NULL, &recv_len, &sw, 0);
@ -185,8 +186,8 @@ static int test_desfire_authenticate() {
// none // none
static int test_desfire_authenticate_iso() { static int test_desfire_authenticate_iso() {
uint8_t c = 0x00; uint8_t data[] = {0x00};
sAPDU apdu = {0x90, MFDES_AUTHENTICATE_ISO, 0x00, 0x00, 0x01, &c}; // 0x1A, KEY 0 sAPDU apdu = {0x90, MFDES_AUTHENTICATE_ISO, 0x00, 0x00, 0x01, data}; // 0x1A, KEY 0
int recv_len = 0; int recv_len = 0;
uint16_t sw = 0; uint16_t sw = 0;
return send_desfire_cmd(&apdu, false, NULL, &recv_len, &sw, 0); return send_desfire_cmd(&apdu, false, NULL, &recv_len, &sw, 0);
@ -194,8 +195,8 @@ static int test_desfire_authenticate_iso() {
//none //none
static int test_desfire_authenticate_aes() { static int test_desfire_authenticate_aes() {
uint8_t c = 0x00; uint8_t data[] = {0x00};
sAPDU apdu = {0x90, MFDES_AUTHENTICATE_AES, 0x00, 0x00, 0x01, &c}; // 0xAA, KEY 0 sAPDU apdu = {0x90, MFDES_AUTHENTICATE_AES, 0x00, 0x00, 0x01, data}; // 0xAA, KEY 0
int recv_len = 0; int recv_len = 0;
uint16_t sw = 0; uint16_t sw = 0;
return send_desfire_cmd(&apdu, false, NULL, &recv_len, &sw, 0); return send_desfire_cmd(&apdu, false, NULL, &recv_len, &sw, 0);

View file

@ -91,14 +91,20 @@ CRC1 = crc8 over addr 0x00..0x03+0x07..0x0E (special 'gantner crc8')
CRC2 = MCD + MSB0..2+ addr 0x06 + addr 0x05 + addr 0x07 + Stamp (regular Master-Token-CRC) CRC2 = MCD + MSB0..2+ addr 0x06 + addr 0x05 + addr 0x07 + Stamp (regular Master-Token-CRC)
--]] --]]
--[[
Known issues; needs to be fixed:
* last byte in last segment is handled incorrectly when it is the last bytes on the card itself (MIM256: => byte 256)
--]]
example = "script run legic" example = "script run legic"
author = "Mosci" author = "Mosci, uhei"
version = "1.0.3" version = "1.0.4"
desc = desc =
[[ [[
This script helps you to read, create and modify Legic Prime Tags (MIM22, MIM256, MIM1024) This script helps you to read, create and modify Legic Prime Tags (MIM22, MIM256, MIM1024)
The virtual tag (and therefore the file to be saved) is always a MIM1024 tag.
it's kinda interactive with following commands in three categories: it's kinda interactive with following commands in three categories:
Data I/O Segment Manipulation Token-Data Data I/O Segment Manipulation Token-Data
@ -108,8 +114,8 @@ it's kinda interactive with following commands in three categories:
ed => edit Segment Data tk => toggle KGH-Flag ed => edit Segment Data tk => toggle KGH-Flag
File I/O rs => remove Segment File I/O rs => remove Segment
----------------- cc => check Segment-CRC ----------------- cc => check Segment-CRC
lf => load File ck => check KGH lf => load bin File ck => check KGH
sf => save File ds => dump Segments sf => save eml/bin File ds => dump Segments
xf => xor to File xf => xor to File
@ -128,8 +134,8 @@ it's kinda interactive with following commands in three categories:
without the need of changing anything - MCD,MSN,MCC will be read from the tag without the need of changing anything - MCD,MSN,MCC will be read from the tag
before and applied to the output. before and applied to the output.
lf: 'load file' - load a (xored) file from the local Filesystem into the 'virtual inTag' lf: 'load file' - load a (xored) binary file (*.bin) from the local Filesystem into the 'virtual inTag'
sf: 'save file' - saves the 'virtual inTag' to the local Filesystem (xored with Tag-MCC) sf: 'save file' - saves the 'virtual inTag' to the local Filesystem as eml and bin (xored with Tag-MCC)
xf: 'xor file' - saves the 'virtual inTag' to the local Filesystem (xored with choosen MCC - use '00' for plain values) xf: 'xor file' - saves the 'virtual inTag' to the local Filesystem (xored with choosen MCC - use '00' for plain values)
ct: 'copy tag' - copy the 'virtual Tag' to a second 'virtual TAG' - not usefull yet, but inernally needed ct: 'copy tag' - copy the 'virtual Tag' to a second 'virtual TAG' - not usefull yet, but inernally needed
@ -242,6 +248,16 @@ function istable(t)
return type(t) == 'table' return type(t) == 'table'
end end
---
-- To have two char string for a byte
local function padString(str)
if (#str == 1) then
return '0'..str
end
return str
end
--- ---
-- creates a 'deep copy' of a table (a=b only references) -- creates a 'deep copy' of a table (a=b only references)
function deepCopy(object) function deepCopy(object)
@ -387,15 +403,15 @@ end
function bytesToTag(bytes, tag) function bytesToTag(bytes, tag)
if istable(tag) == false then return oops("tag is no table in: bytesToTag ("..type(tag)..")") end if istable(tag) == false then return oops("tag is no table in: bytesToTag ("..type(tag)..")") end
tag.MCD =bytes[1]; tag.MCD =padString(bytes[1]);
tag.MSN0=bytes[2]; tag.MSN0=padString(bytes[2]);
tag.MSN1=bytes[3]; tag.MSN1=padString(bytes[3]);
tag.MSN2=bytes[4]; tag.MSN2=padString(bytes[4]);
tag.MCC =bytes[5]; tag.MCC =padString(bytes[5]);
tag.DCFl=bytes[6]; tag.DCFl=padString(bytes[6]);
tag.DCFh=bytes[7]; tag.DCFh=padString(bytes[7]);
tag.raw =bytes[8]; tag.raw =padString(bytes[8]);
tag.SSC =bytes[9]; tag.SSC =padString(bytes[9]);
tag.Type=getTokenType(tag.DCFl); tag.Type=getTokenType(tag.DCFl);
tag.OLE=bbit("0x"..tag.DCFl,7,1) tag.OLE=bbit("0x"..tag.DCFl,7,1)
tag.WRP=("%d"):format(bbit("0x"..bytes[8],0,4)) tag.WRP=("%d"):format(bbit("0x"..bytes[8],0,4))
@ -500,42 +516,26 @@ function tagToBytes(tag)
return bytes return bytes
end end
---
--- PM3 I/O --- --- PM3 I/O ---
---
-- read from pm3 into virtual-tag
function readFromPM3()
local tag, bytes, infile
infile="legic.temp"
-- core.console("hf legic reader")
-- core.console("hf legic esave "..infile)
core.console("hf legic dump o "..infile)
tag=readFile(infile..".bin")
return tag
end
local function padString(str)
if (#str == 1) then
return '0'..str
end
return str
end
---
-- write virtual Tag to real Tag -- write virtual Tag to real Tag
function writeToTag(tag) function writeToTag(tag)
local bytes local bytes
local filename = 'MylegicClone.hex'
local taglen = 22 local taglen = 22
if(utils.confirm(acred.."\nplace the (empty) Tag onto the PM3\nand confirm writing to this Tag: "..acoff) == false) then local writeDCF = false
if(utils.confirm(acred.."\nPlace the (empty) Tag onto the PM3\nand confirm writing to this Tag: "..acoff) == false) then
return return
end end
if(utils.confirm(acred.."\nShould the decremental field (DCF) be written?: "..acoff) == true) then
writeDCF = true
end
-- get used bytes / tag-len -- get used bytes / tag-len
if (istable(tag.SEG)) then if (istable(tag.SEG)) then
if (istable(tag.Bck)) then if (istable(tag.Bck)) then
for i=0, #tag.SEG do for i=0, #tag.SEG do
taglen = taglen + tag.SEG[i] . len + 5 taglen = taglen + tag.SEG[i] . len
end end
end end
local uid_old = tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2 local uid_old = tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2
@ -571,37 +571,32 @@ function writeToTag(tag)
bytes[22] = calcMtCrc(bytes) bytes[22] = calcMtCrc(bytes)
end end
if (bytes) then if (bytes) then
print("write temp-file '"..filename.."'") bytes = xorBytes(bytes,tag.MCC)
print(accyan)
writeFile(bytes, filename..".bin")
print(acoff)
end end
end end
-- write data to file -- write data to file
if (taglen > 0) then if (taglen > 0) then
WriteBytes = input(acyellow.."enter number of bytes to write?"..acoff, taglen) WriteBytes = input(acyellow.."enter number of bytes to write?"..acoff, taglen)
-- load file into pm3-buffer
if (type(filename) ~= "string") then
filename = input(acyellow.."filename to load to pm3-buffer?"..acoff, "legic.temp")
end
cmd = 'hf legic eload 2 '..filename
core.console(cmd)
-- write pm3-buffer to Tag -- write pm3-buffer to Tag
for i=0, WriteBytes do for i=1, WriteBytes do
if (i > 6) then if (i > 7) then
cmd = ("hf legic write o %x d %s "):format(i, padString(bytes[i])) cmd = ("hf legic wrbl o %02x d %s "):format(i-1, padString(bytes[i]))
print(acgreen..cmd..acoff) print(acgreen..cmd..acoff)
core.console(cmd) core.console(cmd)
core.clearCommandBuffer() core.clearCommandBuffer()
elseif (i == 7) then
if (writeDCF) then
-- write DCF in reverse order (requires 'mosci-patch')
cmd = ('hf legic wrbl o 05 d %s%s'):format(padString(bytes[i-1]), padString(bytes[i]))
print(acgreen..cmd..acoff)
core.console(cmd)
core.clearCommandBuffer()
else
print(acgreen.."skip byte 0x05-0x06 - DCF"..acoff)
end
elseif (i == 6) then elseif (i == 6) then
-- write DCF in reverse order (requires 'mosci-patch')
cmd = ('hf legic write o 05 d %s%s'):format(padString(bytes[i-1]), padString(bytes[i]))
print(acgreen..cmd..acoff)
core.console(cmd)
core.clearCommandBuffer()
elseif (i == 5) then
print(acgreen.."skip byte 0x05 - will be written next step"..acoff) print(acgreen.."skip byte 0x05 - will be written next step"..acoff)
else else
print(acgreen.."skip byte 0x00-0x04 - unwritable area"..acoff) print(acgreen.."skip byte 0x00-0x04 - unwritable area"..acoff)
@ -641,12 +636,12 @@ end
local function save_BIN(data, filename) local function save_BIN(data, filename)
local outfile local outfile
local counter = 1 local counter = 1
local ext = filename:match("^.+(%..+)$") or '' local ext = ".bin"
local fn = filename local fn = filename..ext
-- Make sure we don't overwrite a file -- Make sure we don't overwrite a file
while file_check(fn) do while file_check(fn) do
fn = filename:gsub(ext, tostring(counter)..ext) fn = filename..ext:gsub(ext, "-"..tostring(counter)..ext)
counter = counter + 1 counter = counter + 1
end end
@ -664,26 +659,27 @@ end
--- ---
-- write bytes to file -- write bytes to file
function writeFile(bytes, filename) function writeFile(bytes, filename)
if (filename ~= 'MylegicClone.hex') then local emlext = ".eml"
if (file_check(filename)) then if (filename ~= 'MyLegicClone') then
local answer = confirm("\nthe output-file "..filename.." already exists!\nthis will delete the previous content!\ncontinue?") if (file_check(filename..emlext)) then
local answer = confirm("\nthe output-file "..filename..emlext.." already exists!\nthis will delete the previous content!\ncontinue?")
if not answer then return print("user abort") end if not answer then return print("user abort") end
end end
end end
local line local line
local bcnt = 0 local bcnt = 0
local fho, err = io.open(filename, "w") local fho, err = io.open(filename..emlext, "w")
if err then if err then
return oops("OOps ... failed to open output-file ".. filename) return oops("OOps ... failed to open output-file ".. filename..emlext)
end end
bytes = xorBytes(bytes, bytes[5]) bytes = xorBytes(bytes, bytes[5])
for i = 1, #bytes do for i = 1, #bytes do
if (bcnt == 0) then if (bcnt == 0) then
line = bytes[i] line = padString(bytes[i])
elseif (bcnt <= 7) then elseif (bcnt <= 7) then
line = line.." "..bytes[i] line = line.." "..padString(bytes[i])
end end
if (bcnt == 7) then if (bcnt == 7) then
-- write line to new file -- write line to new file
@ -699,7 +695,7 @@ function writeFile(bytes, filename)
-- save binary -- save binary
local fn_bin, fn_bin_num = save_BIN(bytes, filename) local fn_bin, fn_bin_num = save_BIN(bytes, filename)
print("\nwrote "..acyellow..(#bytes * 3)..acoff.." bytes to " ..acyellow..filename..acoff) print("\nwrote "..acyellow..(#bytes * 3)..acoff.." bytes to " ..acyellow..filename..emlext..acoff)
if fn_bin and fn_bin_num then if fn_bin and fn_bin_num then
print("\nwrote "..acyellow..fn_bin_num..acoff.." bytes to BINARY file "..acyellow..fn_bin..acoff) print("\nwrote "..acyellow..fn_bin_num..acoff.." bytes to BINARY file "..acyellow..fn_bin..acoff)
@ -708,6 +704,21 @@ function writeFile(bytes, filename)
return true return true
end end
---
-- read from pm3 into virtual-tag
function readFromPM3()
local tag, bytes, infile
--infile="legic.temp"
infile=os.tmpname()
core.console("hf legic dump f "..infile)
tag=readFile(infile..".bin")
os.remove(infile)
os.remove(infile..".bin")
os.remove(infile..".eml")
os.remove(infile..".json")
return tag
end
--- Map related --- --- Map related ---
--- ---
-- make tagMap -- make tagMap
@ -2265,8 +2276,8 @@ function modifyHelp()
ed => edit Segment Data tk => toggle KGH-Flag ed => edit Segment Data tk => toggle KGH-Flag
File I/O rs => remove Segment File I/O rs => remove Segment
----------------- cc => check Segment-CRC ----------------- cc => check Segment-CRC
lf => load File ck => check KGH lf => load bin File ck => check KGH
sf => save File ds => dump Segments sf => save eml/bin File ds => dump Segments
xf => xor to File xf => xor to File
@ -2352,10 +2363,10 @@ function modifyMode()
-- save values of mainTAG to a file (xored with MCC of mainTAG) -- save values of mainTAG to a file (xored with MCC of mainTAG)
["sf"] = function(x) ["sf"] = function(x)
if istable(inTAG) then if istable(inTAG) then
outfile = input("enter filename:", "legic.temp") outfile = input("enter filename:", "hf-legic-"..inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2)
bytes = tagToBytes(inTAG) bytes = tagToBytes(inTAG)
--bytes=xorBytes(bytes, inTAG.MCC) --bytes=xorBytes(bytes, inTAG.MCC)
if bytes then if (bytes) then
writeFile(bytes, outfile) writeFile(bytes, outfile)
end end
end end
@ -2364,7 +2375,7 @@ function modifyMode()
-- save values of mainTAG to a file (xored with 'specific' MCC) -- save values of mainTAG to a file (xored with 'specific' MCC)
["xf"] = function(x) ["xf"] = function(x)
if istable(inTAG) then if istable(inTAG) then
outfile = input("enter filename:", "legic.temp") outfile = input("enter filename:", "hf-legic-"..inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2)
crc = input("enter new crc: ('00' for a plain dump)", inTAG.MCC) crc = input("enter new crc: ('00' for a plain dump)", inTAG.MCC)
print("obfuscate with: "..crc) print("obfuscate with: "..crc)
bytes=tagToBytes(inTAG) bytes=tagToBytes(inTAG)