2020-04-05 20:18:07 +08:00
local utils = require ( ' utils ' )
local cmds = require ( ' commands ' )
local getopt = require ( ' getopt ' )
local ansicolors = require ( ' ansicolors ' )
2020-04-05 20:53:32 +08:00
2020-04-05 20:18:07 +08:00
--[[
2020-04-05 23:02:41 +08:00
script to create a clone - dump with new crc
2020-04-05 20:18:07 +08:00
Author : mosci
2020-04-05 23:02:41 +08:00
my Fork : https : // github.com / icsom / proxmark3.git
2020-04-05 20:18:07 +08:00
1. read tag - dump , xor byte 22. . end with byte 0x05 of the inputfile
2. write to outfile
3. set byte 0x05 to newcrc
4. until byte 0x21 plain like in inputfile
5. from 0x22. . end xored with newcrc
6. calculate new crc on each segment ( needs to know the new MCD & MSN0 .. 2 )
2020-04-05 23:02:41 +08:00
simplest usage :
2020-04-16 15:01:14 +08:00
Dump a legic tag with ' hf legic dump '
2020-04-05 23:02:41 +08:00
place your ' empty ' tag on the reader and run
2020-09-23 07:35:27 +08:00
' script run hf_legic_clone -i orig.bin -w '
2020-04-05 23:02:41 +08:00
you will see some output like :
2020-04-05 20:18:07 +08:00
read 1024 bytes from orig.bin
place your empty tag onto the PM3 to read and display the MCD & MSN0 .. 2
the values will be shown below
confirm when ready [ y / n ] ? y
2020-04-05 20:53:32 +08:00
2020-04-05 20:18:07 +08:00
0 b 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 )
> 0 b
type in MSN0 as 2 - digit value - e.g . : 01 ( default : 28 )
> ad
type in MSN1 as 2 - digit value - e.g . : 02 ( default : d1 )
> c0
type in MSN2 as 2 - digit value - e.g . : 03 ( default : 43 )
> de
MCD : 0 b , MSN : ad c0 de , MCC : 79 <- this crc is calculated from the MCD & MSN and must match the one on yout empty tag
wrote 1024 bytes to myLegicClone.hex
enter number of bytes to write ? ( default : 86 )
loaded 1024 samples
# db # setting up legic card
# db # MIM 256 card found , writing 0x00 - 0x01 ...
# db # write successful
...
# db # setting up legic card
# db # MIM 256 card found , writing 0x56 - 0x01 ...
# db # write successful
proxmark3 >
the default value ( number of bytes to write ) is calculated over all valid segments and should be ok - just hit enter , wait until write has finished
and your clone should be ready ( except there has to be a additional KGH - CRC to be calculated - which credentials are unknown until yet )
the ' -w ' switch will only work with my fork - it needs the binary legic_crc8 which is not part of the proxmark3 - master - branch
also the ability to write DCF is not possible with the proxmark3 - master - branch
but creating dumpfile - clone files will be possible ( without valid segment - crc - this has to done manually with )
( example ) Legic - Prime Layout with ' Kaba Group Header '
+----+----+----+----+----+----+----+----+
0x00 | MCD | MSN0 | MSN1 | MSN2 | MCC | 60 | ea | 9 f |
+----+----+----+----+----+----+----+----+
0x08 | ff | 00 | 00 | 00 | 11 | Bck0 | Bck1 | Bck2 |
+----+----+----+----+----+----+----+----+
0x10 | Bck3 | Bck4 | Bck5 | BCC | 00 | 00 | Seg0 | Seg1 |
+----+----+----+----+----+----+----+----+
0x18 | Seg2 | Seg3 | SegC | Stp0 | Stp1 | Stp2 | Stp3 | UID0 |
+----+----+----+----+----+----+----+----+
0x20 | UID1 | UID2 | kghC |
+----+----+----+
MCD = ManufacturerID ( 1 Byte )
MSN0 .. 2 = ManufactureSerialNumber ( 3 Byte )
MCC = CRC ( 1 Byte ) calculated over MCD , MSN0 .. 2
DCF = DecrementalField ( 2 Byte ) ' credential ' ( enduser - Tag ) seems to have always DCF - low = 0x60 DCF - high = 0xea
Bck0 .. 5 = Backup ( 6 Byte ) Bck0 ' dirty-flag ' , Bck1 .. 5 SegmentHeader - Backup
BCC = BackupCRC ( 1 Byte ) CRC calculated over Bck1 .. 5
Seg0 .. 3 = SegmentHeader ( on MIM 4 Byte )
SegC = SegmentCRC ( 1 Byte ) calculated over MCD , MSN0 .. 2 , Seg0 .. 3
Stp0 .. n = Stamp0 ... ( variable length ) length = Segment - Len - UserData - 1
UID0 .. n = UserDater ( variable length - with KGH hex 0x00 - 0x63 / dec 0 - 99 ) length = Segment - Len - WRP - WRC - 1
kghC = KabaGroupHeader ( 1 Byte + addr 0x0c must be 0x11 )
as seen on this example : addr 0x05. .0 x08 & 0x0c must have been set to this values - otherwise kghCRC will not be created by a official reader ( not accepted )
--]]
copyright = ' '
author = ' Mosci '
version = ' v1.0.2 '
desc = [ [
2020-04-05 23:02:41 +08:00
This is a script which creates a clone - dump of a dump from a LEGIC Prime Tag ( MIM256 or MIM1024 )
Create a dump by running ` hf legic dump ` .
2020-04-05 20:18:07 +08:00
] ]
example = [ [
2020-09-23 07:35:27 +08:00
script run hf_legic_clone - i my_dump.bin - o my_clone.bin - c f8
script run hf_legic_clone - i my_dump.bin - d - s
2020-04-05 20:18:07 +08:00
] ]
usage = [ [
2020-09-23 07:35:27 +08:00
script run hf_legic_clone [ - h ] [ - i < file > ] [ - o < file > ] [ - c < crc > ] [ - d ] [ - s ] [ - w ]
2020-04-05 20:18:07 +08:00
] ]
arguments = [ [
required :
2020-04-05 20:53:32 +08:00
- i < input file > - file to read data from , must be in binary format ( * . bin )
2020-04-05 20:18:07 +08:00
optional :
- h - Help text
- o < output file > - requires option - c to be given
- c < new - tag crc > - requires option - o to be given
- d - Display content of found Segments
- s - Display summary at the end
2020-04-05 20:53:32 +08:00
- w - write directly to tag - a file hf - legic - UID - dump.bin will also be generated
2020-04-05 20:18:07 +08:00
e.g . :
hint : using the CRC ' 00 ' will result in a plain dump ( - c 00 )
] ]
2020-04-05 23:02:41 +08:00
local DEBUG = true
2020-04-05 20:18:07 +08:00
local bxor = bit32.bxor
2020-04-05 23:02:41 +08:00
---
-- This is only meant to be used when errors occur
local function dbg ( args )
if not DEBUG then return end
if type ( args ) == ' table ' then
local i = 1
while args [ i ] do
dbg ( args [ i ] )
i = i + 1
end
else
print ( ' ### ' , args )
end
end
2020-04-05 20:18:07 +08:00
-- we need always 2 digits
local function prepend_zero ( s )
2020-04-05 23:02:41 +08:00
if s == nil then return ' .. ' end
if ( # s == 1 ) then
2020-04-05 20:18:07 +08:00
return ' 0 ' .. s
else
2020-04-05 23:02:41 +08:00
if ( # s == 0 ) then
2020-04-05 20:18:07 +08:00
return ' 00 '
else
return s
end
end
end
---
-- This is only meant to be used when errors occur
local function oops ( err )
print ( ' ERROR: ' , err )
core.clearCommandBuffer ( )
return nil , err
end
---
-- Usage help
local function help ( )
print ( copyright )
print ( author )
print ( version )
print ( desc )
print ( ansicolors.cyan .. ' Usage ' .. ansicolors.reset )
print ( usage )
print ( ansicolors.cyan .. ' Arguments ' .. ansicolors.reset )
print ( arguments )
print ( ansicolors.cyan .. ' Example usage ' .. ansicolors.reset )
print ( example )
end
2020-04-05 20:53:32 +08:00
-- 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
2020-04-05 20:18:07 +08:00
-- Check availability of file
local function file_check ( file_name )
2020-04-05 20:53:32 +08:00
local exists = io.open ( file_name , " r " )
if not exists then
exists = false
2020-04-05 20:18:07 +08:00
else
2020-04-05 20:53:32 +08:00
exists = true
2020-04-05 20:18:07 +08:00
end
2020-04-05 20:53:32 +08:00
return exists
2020-04-05 20:18:07 +08:00
end
--- xor-wrapper
-- xor all from addr 0x22 (start counting from 1 => 23)
local function xorme ( hex , xor , index )
if ( index >= 23 ) then
2020-04-05 20:53:32 +08:00
return ( ' %02x ' ) : format ( bxor ( tonumber ( hex , 16 ) , tonumber ( xor , 16 ) ) )
2020-04-05 20:18:07 +08:00
else
return hex
end
end
-- read input-file into array
local function getInputBytes ( infile )
local bytes = { }
2020-04-05 23:02:41 +08:00
local f = io.open ( infile , " rb " )
if f == nil then print ( " OOps ... failed to read from file " .. infile ) ; return false ; end
2020-04-05 20:18:07 +08:00
2020-04-05 23:02:41 +08:00
local str = f : read ( " *all " )
f : close ( )
2020-04-05 20:18:07 +08:00
for c in ( str or ' ' ) : gmatch ' . ' do
2020-04-05 20:53:32 +08:00
bytes [ # bytes + 1 ] = ( ' %02x ' ) : format ( c : byte ( ) )
2020-04-05 20:18:07 +08:00
end
2020-04-05 23:02:41 +08:00
print ( " \n read " .. # bytes .. " bytes from " .. ansicolors.yellow .. infile .. ansicolors.reset )
2020-04-05 20:18:07 +08:00
return bytes
end
-- write to file
local function writeOutputBytes ( bytes , outfile )
2020-04-05 20:53:32 +08:00
local fho , err = io.open ( outfile , " wb " )
2020-04-05 20:18:07 +08:00
if err then print ( " OOps ... faild to open output-file " .. outfile ) ; return false ; end
for i = 1 , # bytes do
2020-04-05 20:53:32 +08:00
fho : write ( string.char ( tonumber ( bytes [ i ] , 16 ) ) )
2020-04-05 20:18:07 +08:00
end
fho : close ( )
print ( " \n wrote " .. # bytes .. " bytes to " .. outfile )
return true
end
-- xore certain bytes
local function xorBytes ( inBytes , crc )
local bytes = { }
for index = 1 , # inBytes do
bytes [ index ] = xorme ( inBytes [ index ] , crc , index )
end
if ( # inBytes == # bytes ) then
-- replace crc
2020-04-05 20:53:32 +08:00
bytes [ 5 ] = string.sub ( crc , - 2 )
2020-04-05 20:18:07 +08:00
return bytes
else
print ( " error: byte-count missmatch " )
return false
end
end
-- get raw segment-data
2020-04-05 20:53:32 +08:00
local function getSegmentData ( bytes , start , index )
2020-04-05 20:18:07 +08:00
local raw , len , valid , last , wrp , wrc , rd , crc
local segment = { }
2020-04-05 20:53:32 +08:00
segment [ 0 ] = bytes [ start ] .. ' ' .. bytes [ start + 1 ] .. ' ' .. bytes [ start + 2 ] .. ' ' .. bytes [ start + 3 ]
2020-04-05 20:18:07 +08:00
-- flag = high nibble of byte 1
2020-04-05 20:53:32 +08:00
segment [ 1 ] = string.sub ( bytes [ start + 1 ] , 0 , 1 )
2020-04-05 20:18:07 +08:00
-- valid = bit 6 of byte 1
2020-04-05 20:53:32 +08:00
segment [ 2 ] = tonumber ( bit32.extract ( ' 0x ' .. bytes [ start + 1 ] , 6 , 1 ) , 16 )
2020-04-05 20:18:07 +08:00
-- last = bit 7 of byte 1
2020-04-05 20:53:32 +08:00
segment [ 3 ] = tonumber ( bit32.extract ( ' 0x ' .. bytes [ start + 1 ] , 7 , 1 ) , 16 )
2020-04-05 20:18:07 +08:00
-- len = (byte 0)+(bit0-3 of byte 1)
2020-04-05 20:53:32 +08:00
segment [ 4 ] = tonumber ( ( ' %03x ' ) : format ( tonumber ( bit32.extract ( ' 0x ' .. bytes [ start + 1 ] , 0 , 3 ) , 16 ) .. tonumber ( bytes [ start ] , 16 ) ) , 16 )
2020-04-05 20:18:07 +08:00
-- wrp (write proteted) = byte 2
2020-04-05 20:53:32 +08:00
segment [ 5 ] = tonumber ( bytes [ start + 2 ] )
2020-04-05 20:18:07 +08:00
-- wrc (write control) - bit 4-6 of byte 3
2020-04-05 20:53:32 +08:00
segment [ 6 ] = tonumber ( bit32.extract ( ' 0x ' .. bytes [ start + 3 ] , 4 , 3 ) , 16 )
2020-04-05 20:18:07 +08:00
-- rd (read disabled) - bit 7 of byte 3
2020-04-05 20:53:32 +08:00
segment [ 7 ] = tonumber ( bit32.extract ( ' 0x ' .. bytes [ start + 3 ] , 7 , 1 ) , 16 )
2020-04-05 20:18:07 +08:00
-- crc byte 4
2020-04-05 20:53:32 +08:00
segment [ 8 ] = bytes [ start + 4 ]
2020-04-05 20:18:07 +08:00
-- segment index
segment [ 9 ] = index
-- # crc-byte
2020-04-05 20:53:32 +08:00
segment [ 10 ] = start + 4
2020-04-05 20:18:07 +08:00
return segment
end
--- Kaba Group Header
-- 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
2020-04-05 20:53:32 +08:00
local function CheckKgh ( bytes , segStart , segEnd )
if ( bytes [ 8 ] == ' 9f ' and bytes [ 9 ] == ' ff ' and bytes [ 13 ] == ' 11 ' ) then
2020-04-05 20:18:07 +08:00
local i
local data = { }
segStart = tonumber ( segStart , 10 )
segEnd = tonumber ( segEnd , 10 )
2020-04-05 20:53:32 +08:00
local dataLen = segEnd - segStart - 5
2020-04-05 20:18:07 +08:00
--- gather creadentials for verify
2020-04-05 20:53:32 +08:00
local WRP = bytes [ ( segStart + 2 ) ]
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 ) )
2020-04-05 20:18:07 +08:00
local XX = " 00 "
cmd = bytes [ 1 ] .. bytes [ 2 ] .. bytes [ 3 ] .. bytes [ 4 ] .. WRP .. WRC .. RD .. XX
2020-04-05 20:53:32 +08:00
for i = ( segStart + 5 ) , ( segStart + 5 + dataLen - 2 ) do
2020-04-05 20:18:07 +08:00
cmd = cmd .. bytes [ i ]
end
local KGH = ( " %02x " ) : format ( utils.Crc8Legic ( cmd ) )
2020-04-05 20:53:32 +08:00
if ( KGH == bytes [ segEnd - 1 ] ) then
2020-04-05 20:18:07 +08:00
return KGH
else
return false
end
else
return false
end
end
-- get only the addresses of segemnt-crc's and the length of bytes
2020-04-05 20:53:32 +08:00
local function getSegmentCrcBytes ( bytes )
2020-04-05 20:18:07 +08:00
local start = 23
local index = 0
local crcbytes = { }
repeat
2020-04-05 20:53:32 +08:00
seg = getSegmentData ( bytes , start , index )
2020-04-05 20:18:07 +08:00
crcbytes [ index ] = seg [ 10 ]
start = start + seg [ 4 ]
index = index + 1
until ( seg [ 3 ] == 1 or tonumber ( seg [ 9 ] ) == 126 )
crcbytes [ index ] = start
return crcbytes
end
2020-04-05 23:02:41 +08:00
-- print Segment values
local function printSegment ( SegmentData )
res = " \n Segment " .. SegmentData [ 9 ] .. " : "
res = res .. " raw header= " .. SegmentData [ 0 ] .. " , "
res = res .. " flag= " .. SegmentData [ 1 ] .. " (valid= " .. SegmentData [ 2 ] .. " last= " .. SegmentData [ 3 ] .. " ), "
res = res .. " len= " .. ( " %04d " ) : format ( SegmentData [ 4 ] ) .. " , "
res = res .. " WRP= " .. prepend_zero ( SegmentData [ 5 ] ) .. " , "
res = res .. " WRC= " .. prepend_zero ( SegmentData [ 6 ] ) .. " , "
res = res .. " RD= " .. SegmentData [ 7 ] .. " , "
res = res .. " crc= " .. SegmentData [ 8 ]
print ( res )
end
2020-04-05 20:18:07 +08:00
-- print segment-data (hf legic info like)
2020-04-05 20:53:32 +08:00
local function displaySegments ( bytes )
2020-04-05 23:02:41 +08:00
2020-04-05 20:18:07 +08:00
--display segment header(s)
start = 23
index = ' 00 '
--repeat until last-flag ist set to 1 or segment-index has reached 126
repeat
wrc = ' '
wrp = ' '
pld = ' '
Seg = getSegmentData ( bytes , start , index )
2020-04-05 23:02:41 +08:00
if Seg == nil then return OOps ( " segment is nil " ) end
2020-04-16 15:01:14 +08:00
2020-04-05 20:53:32 +08:00
KGH = CheckKgh ( bytes , start , ( start + tonumber ( Seg [ 4 ] , 10 ) ) )
2020-04-05 23:02:41 +08:00
2020-04-05 20:18:07 +08:00
printSegment ( Seg )
-- wrc
if ( Seg [ 6 ] > 0 ) then
print ( " WRC protected area: " )
-- length of wrc = wrc
2020-04-05 20:53:32 +08:00
for i = 1 , Seg [ 6 ] do
2020-04-05 20:18:07 +08:00
-- starts at (segment-start + segment-header + segment-crc)-1
2020-04-05 20:53:32 +08:00
wrc = wrc .. bytes [ ( start + 4 + 1 + i ) - 1 ] .. ' '
2020-04-05 20:18:07 +08:00
end
print ( wrc )
elseif ( Seg [ 5 ] > 0 ) then
print ( " Remaining write protected area: " )
-- length of wrp = (wrp-wrc)
2020-04-05 20:53:32 +08:00
for i = 1 , ( Seg [ 5 ] - Seg [ 6 ] ) do
2020-04-05 20:18:07 +08:00
-- starts at (segment-start + segment-header + segment-crc + wrc)-1
2020-04-05 20:53:32 +08:00
wrp = wrp .. bytes [ ( start + 4 + 1 + Seg [ 6 ] + i ) - 1 ] .. ' '
2020-04-05 20:18:07 +08:00
end
print ( wrp )
end
-- payload
print ( " Remaining segment payload: " )
--length of payload = segment-len - segment-header - segment-crc - wrp -wrc
2020-04-05 20:53:32 +08:00
for i = 1 , ( Seg [ 4 ] - 4 - 1 - Seg [ 5 ] - Seg [ 6 ] ) do
2020-04-05 20:18:07 +08:00
-- starts at (segment-start + segment-header + segment-crc + segment-wrp + segemnt-wrc)-1
2020-04-05 20:53:32 +08:00
pld = pld .. bytes [ ( start + 4 + 1 + Seg [ 5 ] + Seg [ 6 ] + i ) - 1 ] .. ' '
2020-04-05 20:18:07 +08:00
end
print ( pld )
if ( KGH ) then
2020-04-05 20:53:32 +08:00
print ( ansicolors.yellow .. " 'Kaba Group Header' detected " .. ansicolors.reset )
2020-04-05 20:18:07 +08:00
end
2020-04-05 20:53:32 +08:00
start = start + Seg [ 4 ]
index = prepend_zero ( tonumber ( Seg [ 9 ] ) + 1 )
2020-04-05 20:18:07 +08:00
until ( Seg [ 3 ] == 1 or tonumber ( Seg [ 9 ] ) == 126 )
end
-- write clone-data to tag
2020-04-05 20:53:32 +08:00
local function writeToTag ( plainBytes )
2020-04-05 20:18:07 +08:00
local SegCrcs = { }
local output
local readbytes
2020-04-05 20:53:32 +08:00
if ( utils.confirm ( " \n place your empty tag onto the PM3 to restore the data of the input file \n the CRCs will be calculated as needed \n confirm when ready " ) == false ) then
return
end
2020-04-05 20:18:07 +08:00
readbytes = readlegicdata ( 0 , 4 , 0x55 )
-- gather MCD & MSN from new Tag - this must be enterd manually
print ( " \n these are the MCD MSN0 MSN1 MSN2 from the Tag that has being read: " )
2020-04-05 20:53:32 +08:00
-- readbytes is a usbcommandOLD package, hence 32 bytes offset until data.
2020-04-05 20:18:07 +08:00
plainBytes [ 1 ] = ( ' %02x ' ) : format ( readbytes : byte ( 33 ) )
plainBytes [ 2 ] = ( ' %02x ' ) : format ( readbytes : byte ( 34 ) )
plainBytes [ 3 ] = ( ' %02x ' ) : format ( readbytes : byte ( 35 ) )
plainBytes [ 4 ] = ( ' %02x ' ) : format ( readbytes : byte ( 36 ) )
MCD = plainBytes [ 1 ]
MSN0 = plainBytes [ 2 ]
MSN1 = plainBytes [ 3 ]
MSN2 = plainBytes [ 4 ]
-- calculate crc8 over MCD & MSN
cmd = MCD .. MSN0 .. MSN1 .. MSN2
MCC = ( " %02x " ) : format ( utils.Crc8Legic ( cmd ) )
2020-04-05 20:53:32 +08:00
print ( " MCD: " .. ansicolors.green .. MCD .. ansicolors.reset .. " , MSN: " .. ansicolors.green .. MSN0 .. " " .. MSN1 .. " " .. MSN2 .. ansicolors.reset .. " , MCC: " .. MCC )
2020-04-05 20:18:07 +08:00
-- calculate new Segment-CRC for each valid segment
SegCrcs = getSegmentCrcBytes ( plainBytes )
2020-04-05 20:53:32 +08:00
for i = 0 , ( # SegCrcs - 1 ) do
-- 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 )
segStart = ( SegCrcs [ i ] - 4 )
segEnd = ( SegCrcs [ i ] - 4 + segLen )
KGH = CheckKgh ( plainBytes , segStart , segEnd )
if ( KGH ) then
print ( " 'Kaba Group Header' detected - re-calculate... " )
end
2020-04-05 20:18:07 +08:00
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 ) )
end
-- apply MCD & MSN to plain data
plainBytes [ 1 ] = MCD
plainBytes [ 2 ] = MSN0
plainBytes [ 3 ] = MSN1
plainBytes [ 4 ] = MSN2
plainBytes [ 5 ] = MCC
-- prepare plainBytes for writing (xor plain data with new MCC)
bytes = xorBytes ( plainBytes , MCC )
-- write data to file
2020-04-05 20:53:32 +08:00
if ( writeOutputBytes ( bytes , " hf-legic-UID-dump.bin " ) ) then
2020-04-05 20:18:07 +08:00
-- write pm3-buffer to Tag
2020-04-05 20:53:32 +08:00
cmd = ( ' hf legic restore f hf-legic-UID-dump ' )
2020-04-05 20:18:07 +08:00
core.console ( cmd )
end
end
-- main function
2020-04-05 20:53:32 +08:00
local function main ( args )
2020-04-05 20:18:07 +08:00
-- some variables
local i = 0
local oldcrc , newcrc , infile , outfile
local bytes = { }
local segments = { }
-- parse arguments for the script
for o , a in getopt.getopt ( args , ' hwsdc:i:o: ' ) do
-- output file
if o == ' o ' then
outfile = a
ofs = true
if ( file_check ( a ) ) then
local answer = utils.confirm ( ' \n the output-file ' .. a .. ' already exists! \n this will delete the previous content! \n continue? ' )
2020-04-05 20:53:32 +08:00
if ( answer == false ) then return oops ( ' quiting ' ) end
2020-04-05 20:18:07 +08:00
end
end
-- input file
if o == ' i ' then
infile = a
2020-04-05 20:53:32 +08:00
if ( file_check ( infile ) == false ) then return oops ( ' input file: ' .. infile .. ' not found ' ) end
bytes = getInputBytes ( infile )
oldcrc = bytes [ 5 ]
ifs = true
2020-04-05 23:02:41 +08:00
if ( bytes == false ) then return oops ( ' couldnt read file ' ) end
2020-04-05 20:53:32 +08:00
i = i + 1
2020-04-05 20:18:07 +08:00
end
-- new crc
if o == ' c ' then
newcrc = a : lower ( )
ncs = true
end
-- display segments switch
if o == ' d ' then ds = true ; end
-- display summary switch
if o == ' s ' then ss = true ; end
-- write to tag switch
if o == ' w ' then ws = true ; end
-- help
if o == ' h ' then return help ( ) end
end
2020-04-05 23:02:41 +08:00
if ( not ifs ) then return oops ( ' option -i <input file> is required ' ) end
2020-04-05 20:18:07 +08:00
-- bytes to plain
bytes = xorBytes ( bytes , oldcrc )
-- show segments (works only on plain bytes)
if ( ds ) then
print ( " +------------------------------------------- Segments -------------------------------------------+ " )
displaySegments ( bytes ) ;
end
if ( ofs and ncs ) then
-- xor bytes with new crc
newBytes = xorBytes ( bytes , newcrc )
-- write output
if ( writeOutputBytes ( newBytes , outfile ) ) then
-- show summary if requested
if ( ss ) then
-- information
res = " \n +-------------------------------------------- Summary -------------------------------------------+ "
res = res .. " \n created clone_dump from \n \t " .. infile .. " crc: " .. oldcrc .. " \n dump_file: "
2020-04-05 20:53:32 +08:00
res = res .. " \n \t " .. outfile .. " crc: " .. string.sub ( newcrc , - 2 )
res = res .. " \n you may load the new file with: "
res = res .. ansicolors.yellow .. " hf legic eload f " .. outfile .. ansicolors.reset
2020-04-05 20:18:07 +08:00
res = res .. " \n \n if you don't write to tag immediately ('-w' switch) you will need to recalculate each segmentCRC "
res = res .. " \n after writing this dump to a tag! "
2020-04-05 20:53:32 +08:00
res = res .. " \n \n a segmentCRC gets calculated over MCD,MSN0..3, Segment-Header0..3 "
2020-04-05 20:18:07 +08:00
res = res .. " \n e.g. (based on Segment00 of the data from " .. infile .. " ): "
2020-04-05 20:53:32 +08:00
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
2020-04-05 20:18:07 +08:00
-- this can not be calculated without knowing the new MCD, MSN0..2
print ( res )
end
end
else
if ( ss ) then
-- show why the output-file was not written
print ( " \n new file not written - some arguments are missing .. " )
print ( " output file: " .. ( ofs and outfile or " not given " ) )
print ( " new crc: " .. ( ncs and newcrc or " not given " ) )
end
end
-- write to tag
if ( ws and ( # bytes == 1024 or # bytes == 256 ) ) then
2020-04-05 20:53:32 +08:00
writeToTag ( bytes )
2020-04-05 20:18:07 +08:00
end
end
-- call main with arguments
main ( args )