This commit is contained in:
iceman1001 2020-04-05 14:53:32 +02:00
commit 3a2723ac63

View file

@ -2,6 +2,7 @@ local utils = require('utils')
local cmds = require('commands') local cmds = require('commands')
local getopt = require('getopt') local getopt = require('getopt')
local ansicolors = require('ansicolors') local ansicolors = require('ansicolors')
--[[ --[[
script to create a clone-dump with new crc script to create a clone-dump with new crc
Author: mosci Author: mosci
@ -17,18 +18,15 @@ local ansicolors = require('ansicolors')
simplest usage: simplest usage:
read a valid legic tag with 'hf legic reader' read a valid legic tag with 'hf legic reader'
save the dump with 'hf legic dump o orig' save the dump with 'hf legic dump f orig'
place your 'empty' tag on the reader and run 'script run Legic_clone -i orig.bin -w' place your 'empty' tag on the reader and run 'script run legic_clone -i orig.bin -w'
you will see some output like: you will see some output like:
read 1024 bytes from orig.bin read 1024 bytes from orig.bin
place your empty tag onto the PM3 to read and display the MCD & MSN0..2 place your empty tag onto the PM3 to read and display the MCD & MSN0..2
the values will be shown below the values will be shown below
confirm when ready [y/n] ?y confirm when ready [y/n] ?y
#db# setting up legic card
#db# MIM 256 card found, reading card ...
#db# Card read, use 'hf legic decode' or
#db# 'data hexsamples 8' to view results
0b ad c0 de <- !! here you'll see the MCD & MSN of your empty tag, which has to be typed in manually as seen below !! 0b ad c0 de <- !! here you'll see the MCD & MSN of your empty tag, which has to be typed in manually as seen below !!
type in MCD as 2-digit value - e.g.: 00 (default: 79 ) type in MCD as 2-digit value - e.g.: 00 (default: 79 )
> 0b > 0b
@ -93,18 +91,18 @@ author = 'Mosci'
version = 'v1.0.2' version = 'v1.0.2'
desc = [[ desc = [[
This is a script which creates a clone-dump of a dump from a Legic Prime Tag (MIM256 or MIM1024) This is a script which creates a clone-dump of a dump from a Legic Prime Tag (MIM256 or MIM1024)
(created with 'hf legic dump f my_dump') Create a dump by running 'hf legic dump'.
]] ]]
example = [[ example = [[
script run legic_clone -i my_dump.bin -o my_clone.bin -c f8 script run legic_clone -i my_dump.bin -o my_clone.bin -c f8
script run legic_clone -i my_dump.bin -d -s script run legic_clone -i my_dump.bin -d -s
]] ]]
usage = [[ usage = [[
script run legic_clone -h -i <file> -o <file> -c <crc> -d -s -w script run legic_clone [-h] [-i <file>] [-o <file>] [-c <crc>] [-d] [-s] [-w]
]] ]]
arguments = [[ arguments = [[
required : required :
-i <input file> (file to read data from, must be in binary format (*.bin)) -i <input file> - file to read data from, must be in binary format (*.bin)
optional : optional :
-h - Help text -h - Help text
@ -112,7 +110,7 @@ optional :
-c <new-tag crc> - requires option -o to be given -c <new-tag crc> - requires option -o to be given
-d - Display content of found Segments -d - Display content of found Segments
-s - Display summary at the end -s - Display summary at the end
-w - write directly to Tag - a file myLegicClone.bin will be generated also -w - write directly to tag - a file hf-legic-UID-dump.bin will also be generated
e.g.: e.g.:
hint: using the CRC '00' will result in a plain dump ( -c 00 ) hint: using the CRC '00' will result in a plain dump ( -c 00 )
@ -139,23 +137,6 @@ local function oops(err)
core.clearCommandBuffer() core.clearCommandBuffer()
return nil, err return nil, err
end end
-- read LEGIC data
local function readlegicdata( offset, length, iv )
-- Read data
local command = Command:newMIX{
cmd = cmds.CMD_HF_LEGIC_READER
, arg1 = offset
, arg2 = length
, arg3 = iv
, data = nil
}
local result, err = command:sendMIX()
if not result then return oops(err) end
-- result is a packed data structure, data starts at offset 33
return result
end
--- ---
-- Usage help -- Usage help
local function help() local function help()
@ -170,23 +151,38 @@ local function help()
print(ansicolors.cyan..'Example usage'..ansicolors.reset) print(ansicolors.cyan..'Example usage'..ansicolors.reset)
print(example) print(example)
end end
-- read LEGIC data
local function readlegicdata(offset, length, iv)
-- Read data
local command = Command:newMIX{
cmd = cmds.CMD_HF_LEGIC_READER
, arg1 = offset
, arg2 = length
, arg3 = iv
, data = nil
}
local result, err = command:sendMIX()
if not result then return oops(err) end
-- result is a packed data structure, data starts at offset 33
return result
end
-- Check availability of file -- Check availability of file
local function file_check(file_name) local function file_check(file_name)
local file_found = io.open(file_name, "r") local exists = io.open(file_name, "r")
if not file_found then if not exists then
file_found = false exists = false
else else
file_found = true exists = true
end end
return file_found return exists
end end
--- xor-wrapper --- xor-wrapper
-- xor all from addr 0x22 (start counting from 1 => 23) -- xor all from addr 0x22 (start counting from 1 => 23)
local function xorme(hex, xor, index) local function xorme(hex, xor, index)
if ( index >= 23 ) then if ( index >= 23 ) then
return ('%02x'):format(bxor( tonumber(hex,16) , tonumber(xor,16) )) return ('%02x'):format(bxor( tonumber(hex, 16) , tonumber(xor, 16) ))
else else
return hex return hex
end end
@ -197,12 +193,12 @@ local function getInputBytes(infile)
local line local line
local bytes = {} local bytes = {}
local fhi,err = io.open(infile,"rb") local fhi,err = io.open(infile, "rb")
if err then print("OOps ... faild to read from file ".. infile); return false; end if err then print("OOps ... faild to read from file ".. infile); return false; end
str = fhi:read("*all") str = fhi:read("*all")
for c in (str or ''):gmatch'.' do for c in (str or ''):gmatch'.' do
bytes[#bytes+1] = ('%02x'):format(c:byte()) bytes[#bytes + 1] = ('%02x'):format(c:byte())
end end
fhi:close() fhi:close()
@ -213,11 +209,11 @@ end
-- write to file -- write to file
local function writeOutputBytes(bytes, outfile) local function writeOutputBytes(bytes, outfile)
local fho,err = io.open(outfile,"wb") local fho,err = io.open(outfile, "wb")
if err then print("OOps ... faild to open output-file ".. outfile); return false; end if err then print("OOps ... faild to open output-file ".. outfile); return false; end
for i = 1, #bytes do for i = 1, #bytes do
fho:write(string.char(tonumber(bytes[i],16))) fho:write(string.char(tonumber(bytes[i], 16)))
end end
fho:close() fho:close()
print("\nwrote ".. #bytes .." bytes to " .. outfile) print("\nwrote ".. #bytes .." bytes to " .. outfile)
@ -232,7 +228,7 @@ local function xorBytes(inBytes, crc)
end end
if (#inBytes == #bytes) then if (#inBytes == #bytes) then
-- replace crc -- replace crc
bytes[5] = string.sub(crc,-2) bytes[5] = string.sub(crc, -2)
return bytes return bytes
else else
print("error: byte-count missmatch") print("error: byte-count missmatch")
@ -241,63 +237,63 @@ local function xorBytes(inBytes, crc)
end end
-- get raw segment-data -- get raw segment-data
function getSegmentData(bytes, start, index) local function getSegmentData(bytes, start, index)
local raw, len, valid, last, wrp, wrc, rd, crc local raw, len, valid, last, wrp, wrc, rd, crc
local segment = {} local segment = {}
segment[0] = bytes[start]..' '..bytes[start+1]..' '..bytes[start+2]..' '..bytes[start+3] segment[0] = bytes[start]..' '..bytes[start + 1]..' '..bytes[start + 2]..' '..bytes[start + 3]
-- flag = high nibble of byte 1 -- flag = high nibble of byte 1
segment[1] = string.sub(bytes[start+1],0,1) segment[1] = string.sub(bytes[start + 1], 0, 1)
-- valid = bit 6 of byte 1 -- valid = bit 6 of byte 1
segment[2] = tonumber(bit32.extract('0x'..bytes[start+1],6,1),16) segment[2] = tonumber(bit32.extract('0x'..bytes[start + 1], 6, 1), 16)
-- last = bit 7 of byte 1 -- last = bit 7 of byte 1
segment[3] = tonumber(bit32.extract('0x'..bytes[start+1],7,1),16) segment[3] = tonumber(bit32.extract('0x'..bytes[start + 1], 7, 1), 16)
-- len = (byte 0)+(bit0-3 of byte 1) -- len = (byte 0)+(bit0-3 of byte 1)
segment[4] = tonumber(('%03x'):format(tonumber(bit32.extract('0x'..bytes[start+1],0,3),16)..tonumber(bytes[start],16)),16) segment[4] = tonumber(('%03x'):format(tonumber(bit32.extract('0x'..bytes[start + 1], 0, 3), 16)..tonumber(bytes[start], 16)), 16)
-- wrp (write proteted) = byte 2 -- wrp (write proteted) = byte 2
segment[5] = tonumber(bytes[start+2]) segment[5] = tonumber(bytes[start + 2])
-- wrc (write control) - bit 4-6 of byte 3 -- wrc (write control) - bit 4-6 of byte 3
segment[6] = tonumber(bit32.extract('0x'..bytes[start+3],4,3),16) segment[6] = tonumber(bit32.extract('0x'..bytes[start + 3], 4, 3), 16)
-- rd (read disabled) - bit 7 of byte 3 -- rd (read disabled) - bit 7 of byte 3
segment[7] = tonumber(bit32.extract('0x'..bytes[start+3],7,1),16) segment[7] = tonumber(bit32.extract('0x'..bytes[start + 3], 7, 1), 16)
-- crc byte 4 -- crc byte 4
segment[8] = bytes[start+4] segment[8] = bytes[start + 4]
-- segment index -- segment index
segment[9] = index segment[9] = index
-- # crc-byte -- # crc-byte
segment[10] = start+4 segment[10] = start + 4
return segment return segment
end end
--- Kaba Group Header --- Kaba Group Header
-- checks if a segment does have a kghCRC -- checks if a segment does have a kghCRC
-- returns boolean false if no kgh has being detected or the kghCRC if a kgh was detected -- returns boolean false if no kgh has being detected or the kghCRC if a kgh was detected
function CheckKgh(bytes, segStart, segEnd) local function CheckKgh(bytes, segStart, segEnd)
if (bytes[8]=='9f' and bytes[9]=='ff' and bytes[13]=='11') then if (bytes[8] == '9f' and bytes[9] == 'ff' and bytes[13] == '11') then
local i local i
local data = {} local data = {}
segStart = tonumber(segStart, 10) segStart = tonumber(segStart, 10)
segEnd = tonumber(segEnd, 10) segEnd = tonumber(segEnd, 10)
local dataLen = segEnd-segStart-5 local dataLen = segEnd - segStart - 5
--- gather creadentials for verify --- gather creadentials for verify
local WRP = bytes[(segStart+2)] local WRP = bytes[(segStart + 2)]
local WRC = ("%02x"):format(tonumber(bit32.extract("0x"..bytes[segStart+3],4,3),16)) local WRC = ("%02x"):format(tonumber(bit32.extract("0x"..bytes[segStart+3], 4, 3), 16))
local RD = ("%02x"):format(tonumber(bit32.extract("0x"..bytes[segStart+3],7,1),16)) local RD = ("%02x"):format(tonumber(bit32.extract("0x"..bytes[segStart+3], 7, 1), 16))
local XX = "00" local XX = "00"
cmd = bytes[1]..bytes[2]..bytes[3]..bytes[4]..WRP..WRC..RD..XX cmd = bytes[1]..bytes[2]..bytes[3]..bytes[4]..WRP..WRC..RD..XX
for i = (segStart+5), (segStart+5+dataLen-2) do for i = (segStart + 5), (segStart + 5 + dataLen - 2) do
cmd = cmd..bytes[i] cmd = cmd..bytes[i]
end end
local KGH = ("%02x"):format(utils.Crc8Legic(cmd)) local KGH = ("%02x"):format(utils.Crc8Legic(cmd))
if (KGH == bytes[segEnd-1]) then if (KGH == bytes[segEnd - 1]) then
return KGH return KGH
else else
return false return false
@ -308,12 +304,12 @@ function CheckKgh(bytes, segStart, segEnd)
end end
-- get only the addresses of segemnt-crc's and the length of bytes -- get only the addresses of segemnt-crc's and the length of bytes
function getSegmentCrcBytes(bytes) local function getSegmentCrcBytes(bytes)
local start = 23 local start = 23
local index = 0 local index = 0
local crcbytes = {} local crcbytes = {}
repeat repeat
seg = getSegmentData(bytes,start,index) seg = getSegmentData(bytes, start, index)
crcbytes[index] = seg[10] crcbytes[index] = seg[10]
start = start + seg[4] start = start + seg[4]
index = index + 1 index = index + 1
@ -323,7 +319,7 @@ function getSegmentCrcBytes(bytes)
end end
-- print segment-data (hf legic info like) -- print segment-data (hf legic info like)
function displaySegments(bytes) local function displaySegments(bytes)
--display segment header(s) --display segment header(s)
start = 23 start = 23
index = '00' index = '00'
@ -334,24 +330,24 @@ function displaySegments(bytes)
wrp = '' wrp = ''
pld = '' pld = ''
Seg = getSegmentData(bytes, start, index) Seg = getSegmentData(bytes, start, index)
KGH = CheckKgh(bytes, start, (start+tonumber(Seg[4],10))) KGH = CheckKgh(bytes, start, (start + tonumber(Seg[4], 10)))
printSegment(Seg) printSegment(Seg)
-- wrc -- wrc
if (Seg[6] > 0) then if (Seg[6] > 0) then
print("WRC protected area:") print("WRC protected area:")
-- length of wrc = wrc -- length of wrc = wrc
for i=1, Seg[6] do for i = 1, Seg[6] do
-- starts at (segment-start + segment-header + segment-crc)-1 -- starts at (segment-start + segment-header + segment-crc)-1
wrc = wrc..bytes[(start+4+1+i)-1]..' ' wrc = wrc..bytes[(start + 4 + 1 + i) - 1]..' '
end end
print(wrc) print(wrc)
elseif (Seg[5] > 0) then elseif (Seg[5] > 0) then
print("Remaining write protected area:") print("Remaining write protected area:")
-- length of wrp = (wrp-wrc) -- length of wrp = (wrp-wrc)
for i=1, (Seg[5]-Seg[6]) do for i = 1, (Seg[5] - Seg[6]) do
-- starts at (segment-start + segment-header + segment-crc + wrc)-1 -- starts at (segment-start + segment-header + segment-crc + wrc)-1
wrp = wrp..bytes[(start+4+1+Seg[6]+i)-1]..' ' wrp = wrp..bytes[(start + 4 + 1 + Seg[6] + i) - 1]..' '
end end
print(wrp) print(wrp)
end end
@ -359,22 +355,22 @@ function displaySegments(bytes)
-- payload -- payload
print("Remaining segment payload:") print("Remaining segment payload:")
--length of payload = segment-len - segment-header - segment-crc - wrp -wrc --length of payload = segment-len - segment-header - segment-crc - wrp -wrc
for i=1, (Seg[4]-4-1-Seg[5]-Seg[6]) do for i = 1, (Seg[4] - 4 - 1 - Seg[5] - Seg[6]) do
-- starts at (segment-start + segment-header + segment-crc + segment-wrp + segemnt-wrc)-1 -- starts at (segment-start + segment-header + segment-crc + segment-wrp + segemnt-wrc)-1
pld = pld..bytes[(start+4+1+Seg[5]+Seg[6]+i)-1]..' ' pld = pld..bytes[(start + 4 + 1 + Seg[5] + Seg[6] + i) - 1]..' '
end end
print(pld) print(pld)
if (KGH) then if (KGH) then
print("'Kaba Group Header' detected") print(ansicolors.yellow.."'Kaba Group Header' detected"..ansicolors.reset)
end end
start = start+Seg[4] start = start + Seg[4]
index = prepend_zero(tonumber(Seg[9])+1) index = prepend_zero(tonumber(Seg[9]) + 1)
until (Seg[3] == 1 or tonumber(Seg[9]) == 126 ) until (Seg[3] == 1 or tonumber(Seg[9]) == 126 )
end end
-- print Segment values -- print Segment values
function printSegment(SegmentData) local function printSegment(SegmentData)
res = "\nSegment "..SegmentData[9]..": " res = "\nSegment "..SegmentData[9]..": "
res = res.. "raw header="..SegmentData[0]..", " res = res.. "raw header="..SegmentData[0]..", "
res = res.. "flag="..SegmentData[1].." (valid="..SegmentData[2].." last="..SegmentData[3].."), " res = res.. "flag="..SegmentData[1].." (valid="..SegmentData[2].." last="..SegmentData[3].."), "
@ -387,18 +383,19 @@ function printSegment(SegmentData)
end end
-- write clone-data to tag -- write clone-data to tag
function writeToTag(plainBytes) local function writeToTag(plainBytes)
local SegCrcs = {} local SegCrcs = {}
local output local output
local readbytes local readbytes
if(utils.confirm("\nplace your empty tag onto the PM3 to restore the data of the input file\nthe CRCs will be calculated as needed\n confirm when ready") == false) then if (utils.confirm("\nplace your empty tag onto the PM3 to restore the data of the input file\nthe CRCs will be calculated as needed\n confirm when ready") == false) then
return return
end end
readbytes = readlegicdata(0, 4, 0x55) readbytes = readlegicdata(0, 4, 0x55)
-- gather MCD & MSN from new Tag - this must be enterd manually -- gather MCD & MSN from new Tag - this must be enterd manually
print("\nthese are the MCD MSN0 MSN1 MSN2 from the Tag that has being read:") print("\nthese are the MCD MSN0 MSN1 MSN2 from the Tag that has being read:")
-- readbytes is a usbcommandOLD package, hence 32 bytes offset until data.
plainBytes[1] = ('%02x'):format(readbytes:byte(33)) plainBytes[1] = ('%02x'):format(readbytes:byte(33))
plainBytes[2] = ('%02x'):format(readbytes:byte(34)) plainBytes[2] = ('%02x'):format(readbytes:byte(34))
plainBytes[3] = ('%02x'):format(readbytes:byte(35)) plainBytes[3] = ('%02x'):format(readbytes:byte(35))
@ -411,19 +408,19 @@ function writeToTag(plainBytes)
-- calculate crc8 over MCD & MSN -- calculate crc8 over MCD & MSN
cmd = MCD..MSN0..MSN1..MSN2 cmd = MCD..MSN0..MSN1..MSN2
MCC = ("%02x"):format(utils.Crc8Legic(cmd)) MCC = ("%02x"):format(utils.Crc8Legic(cmd))
print("MCD:"..MCD..", MSN:"..MSN0.." "..MSN1.." "..MSN2..", MCC:"..MCC) print("MCD:"..ansicolors.green..MCD..ansicolors.reset..", MSN:"..ansicolors.green..MSN0.." "..MSN1.." "..MSN2..ansicolors.reset..", MCC:"..MCC)
-- calculate new Segment-CRC for each valid segment -- calculate new Segment-CRC for each valid segment
SegCrcs = getSegmentCrcBytes(plainBytes) SegCrcs = getSegmentCrcBytes(plainBytes)
for i=0, (#SegCrcs-1) do for i = 0, (#SegCrcs - 1) do
-- SegCrcs[i]-4 = address of first byte of segmentHeader (low byte segment-length) -- SegCrcs[i]-4 = address of first byte of segmentHeader (low byte segment-length)
segLen = tonumber(("%1x"):format(tonumber(bit32.extract("0x"..plainBytes[(SegCrcs[i]-3)],0,3),16))..("%02x"):format(tonumber(plainBytes[SegCrcs[i]-4],16)),16) segLen = tonumber(("%1x"):format(tonumber(bit32.extract("0x"..plainBytes[(SegCrcs[i] - 3)], 0, 3), 16))..("%02x"):format(tonumber(plainBytes[SegCrcs[i] - 4], 16)), 16)
segStart = (SegCrcs[i]-4) segStart = (SegCrcs[i] - 4)
segEnd = (SegCrcs[i]-4+segLen) segEnd = (SegCrcs[i] - 4 + segLen)
KGH = CheckKgh(plainBytes,segStart,segEnd) KGH = CheckKgh(plainBytes, segStart, segEnd)
if (KGH) then if (KGH) then
print("'Kaba Group Header' detected - re-calculate...") print("'Kaba Group Header' detected - re-calculate...")
end end
cmd = MCD..MSN0..MSN1..MSN2..plainBytes[SegCrcs[i]-4]..plainBytes[SegCrcs[i]-3]..plainBytes[SegCrcs[i]-2]..plainBytes[SegCrcs[i]-1] cmd = MCD..MSN0..MSN1..MSN2..plainBytes[SegCrcs[i]-4]..plainBytes[SegCrcs[i]-3]..plainBytes[SegCrcs[i]-2]..plainBytes[SegCrcs[i]-1]
plainBytes[SegCrcs[i]] = ("%02x"):format(utils.Crc8Legic(cmd)) plainBytes[SegCrcs[i]] = ("%02x"):format(utils.Crc8Legic(cmd))
end end
@ -439,15 +436,15 @@ function writeToTag(plainBytes)
bytes = xorBytes(plainBytes, MCC) bytes = xorBytes(plainBytes, MCC)
-- write data to file -- write data to file
if (writeOutputBytes(bytes, "myLegicClone.bin")) then if (writeOutputBytes(bytes, "hf-legic-UID-dump.bin")) then
-- write pm3-buffer to Tag -- write pm3-buffer to Tag
cmd = ('hf legic restore f myLegicClone') cmd = ('hf legic restore f hf-legic-UID-dump')
core.console(cmd) core.console(cmd)
end end
end end
-- main function -- main function
function main(args) local function main(args)
-- some variables -- some variables
local i = 0 local i = 0
local oldcrc, newcrc, infile, outfile local oldcrc, newcrc, infile, outfile
@ -462,21 +459,20 @@ function main(args)
ofs = true ofs = true
if (file_check(a)) then if (file_check(a)) then
local answer = utils.confirm('\nthe output-file '..a..' already exists!\nthis will delete the previous content!\ncontinue?') local answer = utils.confirm('\nthe output-file '..a..' already exists!\nthis will delete the previous content!\ncontinue?')
if (answer==false) then return oops('quiting') end if (answer == false) then return oops('quiting') end
end end
end end
-- input file -- input file
if o == 'i' then if o == 'i' then
infile = a infile = a
if (file_check(infile)==false) then if (file_check(infile) == false) then return oops('input file: '..infile..' not found') end
return oops('input file: '..infile..' not found')
else bytes = getInputBytes(infile)
bytes = getInputBytes(infile) oldcrc = bytes[5]
oldcrc = bytes[5] ifs = true
ifs = true if (bytes == false) then return oops('couldnt get input bytes') end
if (bytes == false) then return oops('couldnt get input bytes') end
end i = i + 1
i = i+1
end end
-- new crc -- new crc
if o == 'c' then if o == 'c' then
@ -514,13 +510,15 @@ function main(args)
-- information -- information
res = "\n+-------------------------------------------- Summary -------------------------------------------+" res = "\n+-------------------------------------------- Summary -------------------------------------------+"
res = res .."\ncreated clone_dump from\n\t"..infile.." crc: "..oldcrc.."\ndump_file:" res = res .."\ncreated clone_dump from\n\t"..infile.." crc: "..oldcrc.."\ndump_file:"
res = res .."\n\t"..outfile.." crc: "..string.sub(newcrc,-2) res = res .."\n\t"..outfile.." crc: "..string.sub(newcrc, -2)
res = res .."\nyou may load the new file with: hf legic eload "..outfile res = res .."\nyou may load the new file with:"
res = res ..ansicolors.yellow.."hf legic eload f "..outfile..ansicolors.reset
res = res .."\n\nif you don't write to tag immediately ('-w' switch) you will need to recalculate each segmentCRC" res = res .."\n\nif you don't write to tag immediately ('-w' switch) you will need to recalculate each segmentCRC"
res = res .."\nafter writing this dump to a tag!" res = res .."\nafter writing this dump to a tag!"
res = res .."\n\na segmentCRC gets calculated over MCD,MSN0..3,Segment-Header0..3" res = res .."\n\na segmentCRC gets calculated over MCD,MSN0..3, Segment-Header0..3"
res = res .."\ne.g. (based on Segment00 of the data from "..infile.."):" res = res .."\ne.g. (based on Segment00 of the data from "..infile.."):"
res = res .."\nhf legic crc d "..bytes[1]..bytes[2]..bytes[3]..bytes[4]..bytes[23]..bytes[24]..bytes[25]..bytes[26].." u "..newcrc.." c 8" res = res .."\n"
res = res ..ansicolors.yellow.."hf legic crc d "..bytes[1]..bytes[2]..bytes[3]..bytes[4]..bytes[23]..bytes[24]..bytes[25]..bytes[26].." u "..newcrc.." c 8"..ansicolors.reset
-- this can not be calculated without knowing the new MCD, MSN0..2 -- this can not be calculated without knowing the new MCD, MSN0..2
print(res) print(res)
end end
@ -535,7 +533,7 @@ function main(args)
end end
-- write to tag -- write to tag
if (ws and ( #bytes == 1024 or #bytes == 256)) then if (ws and ( #bytes == 1024 or #bytes == 256)) then
writeToTag(bytes) writeToTag(bytes)
end end
end end