textual, fixes to legic commands used. Needs testing

This commit is contained in:
iceman1001 2019-05-08 00:07:20 +02:00
parent 5b087a053c
commit 8ebd5e0579

View file

@ -84,12 +84,20 @@
as seen on this example: addr 0x05..0x08 & 0x0c must have been set to this values - otherwise kghCRC will not be created by a official reader (not accepted)
--]]
example = "Script create a clone-dump of a dump from a Legic Prime Tag"
author = "Mosci"
desc =
[[
copyright = ''
author = 'Mosci'
version = 'v1.0.1'
desc = [[
This is a script which create a clone-dump of a dump from a Legic Prime Tag (MIM256 or MIM1024)
(created with 'hf legic save my_dump.hex')
]]
example = [[
script run legic_clone -i my_dump.hex -o my_clone.hex -c f8
script run legic_clone -i my_dump.hex -d -s
]]
usage = [[
script run legic_clone -h -i <file> -o <file> -c <crc> -d -s -w
requiered arguments:
-i <input file> (file to read data from)
@ -103,45 +111,48 @@ optional arguments :
e.g.:
hint: using the CRC '00' will result in a plain dump ( -c 00 )
Examples :
script run legic_clone -i my_dump.hex -o my_clone.hex -c f8
script run legic_clone -i my_dump.hex -d -s
]]
local utils = require('utils')
local getopt = require('getopt')
local bxor = bit32.bxor
-- we need always 2 digits
function prepend_zero(s)
if (string.len(s)==1) then return "0" .. s
local function prepend_zero(s)
if (string.len(s) == 1) then
return '0' .. s
else
if (string.len(s)==0) then return "00"
else return s
if (string.len(s) == 0) then
return '00'
else
return s
end
end
end
---
-- This is only meant to be used when errors occur
function oops(err)
print("ERROR: ",err)
local function oops(err)
print('ERROR:', err)
core.clearCommandBuffer()
return nil, err
end
---
-- Usage help
function help()
local function help()
print(copyright)
print(author)
print(version)
print(desc)
print("Example usage")
print('Example usage')
print(example)
print(usage)
end
-- Check availability of file
function file_check(file_name)
local function file_check(file_name)
local file_found = io.open(file_name, "r")
if file_found==nil then
if not file_found then
file_found = false
else
file_found = true
@ -151,7 +162,7 @@ end
--- xor-wrapper
-- xor all from addr 0x22 (start counting from 1 => 23)
function xorme(hex, xor, index)
local function xorme(hex, xor, index)
if ( index >= 23 ) then
return ('%02x'):format(bxor( tonumber(hex,16) , tonumber(xor,16) ))
else
@ -160,7 +171,7 @@ function xorme(hex, xor, index)
end
-- read input-file into array
function getInputBytes(infile)
local function getInputBytes(infile)
local line
local bytes = {}
@ -183,7 +194,7 @@ function getInputBytes(infile)
end
-- write to file
function writeOutputBytes(bytes, outfile)
local function writeOutputBytes(bytes, outfile)
local line
local bcnt = 0
local fho,err = io.open(outfile,"w")
@ -210,7 +221,7 @@ function writeOutputBytes(bytes, outfile)
end
-- xore certain bytes
function xorBytes(inBytes, crc)
local function xorBytes(inBytes, crc)
local bytes = {}
for index = 1, #inBytes do
bytes[index] = xorme(inBytes[index], crc, index)
@ -229,27 +240,27 @@ end
function getSegmentData(bytes, start, index)
local raw, len, valid, last, wrp, wrc, rd, crc
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
segment[1] = string.sub(bytes[start+1],0,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
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)
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
segment[5] = tonumber(bytes[start+2])
-- 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
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
segment[8] = bytes[start+4]
@ -311,13 +322,13 @@ end
function displaySegments(bytes)
--display segment header(s)
start = 23
index="00"
index = '00'
--repeat until last-flag ist set to 1 or segment-index has reached 126
repeat
wrc=""
wrp=""
pld=""
wrc = ''
wrp = ''
pld = ''
Seg = getSegmentData(bytes, start, index)
KGH = CheckKgh(bytes, start, (start+tonumber(Seg[4],10)))
printSegment(Seg)
@ -328,7 +339,7 @@ function displaySegments(bytes)
-- length of wrc = wrc
for i=1, Seg[6] do
-- 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
print(wrc)
elseif (Seg[5] > 0) then
@ -336,7 +347,7 @@ function displaySegments(bytes)
-- length of wrp = (wrp-wrc)
for i=1, (Seg[5]-Seg[6]) do
-- 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
print(wrp)
end
@ -346,10 +357,12 @@ function displaySegments(bytes)
--length of payload = segment-len - segment-header - segment-crc - wrp -wrc
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
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
print(pld)
if (KGH) then print("'Kaba Group Header' detected"); end
if (KGH) then
print("'Kaba Group Header' detected")
end
start = start+Seg[4]
index = prepend_zero(tonumber(Seg[9])+1)
@ -424,17 +437,17 @@ function writeToTag(plainBytes)
WriteBytes = utils.input("enter number of bytes to write?", SegCrcs[#SegCrcs])
-- load file into pm3-buffer
cmd = 'hf legic load myLegicClone.hex'
cmd = 'hf legic eload myLegicClone.hex'
core.console(cmd)
-- write pm3-buffer to Tag
for i=0, WriteBytes do
if ( i<5 or i>6) then
cmd = ('hf legic write 0x%02x 0x01'):format(i)
cmd = ('hf legic write o %02x d 01'):format(i)
core.console(cmd)
elseif (i == 6) then
-- write DCF in reverse order (requires 'mosci-patch')
cmd = 'hf legic write 0x05 0x02'
cmd = 'hf legic write o 05 d 02'
core.console(cmd)
else
print("skipping byte 0x05 - will be written next step")
@ -455,19 +468,19 @@ function main(args)
-- parse arguments for the script
for o, a in getopt.getopt(args, 'hwsdc:i:o:') do
-- output file
if o == "o" then
if o == 'o' then
outfile = a
ofs = true
if (file_check(a)) then
local answer = utils.confirm("\nthe output-file "..a.." alredy exists!\nthis will delete the previous content!\ncontinue?")
if (answer==false) then return oops("quiting") end
local answer = utils.confirm('\nthe output-file '..a..' alredy exists!\nthis will delete the previous content!\ncontinue?')
if (answer==false) then return oops('quiting') end
end
end
-- input file
if o == "i" then
if o == 'i' then
infile = a
if (file_check(infile)==false) then
return oops("input file: "..infile.." not found")
return oops('input file: '..infile..' not found')
else
bytes = getInputBytes(infile)
oldcrc = bytes[5]
@ -477,21 +490,21 @@ function main(args)
i = i+1
end
-- new crc
if o == "c" then
if o == 'c' then
newcrc = a
ncs = true
end
-- display segments switch
if o == "d" then ds = true; end
if o == 'd' then ds = true; end
-- display summary switch
if o == "s" then ss = true; end
if o == 's' then ss = true; end
-- write to tag switch
if o == "w" then ws = true; end
if o == 'w' then ws = true; end
-- help
if o == "h" then return help() end
if o == 'h' then return help() end
end
if (not ifs) then return oops("option -i <input file> is required but missing") end
if (not ifs) then return oops('option -i <input file> is required but missing') end
-- bytes to plain
bytes = xorBytes(bytes, oldcrc)