mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 13:23:51 -07:00
ADD: get a updated script from @icsom
This commit is contained in:
parent
1f3d5401a6
commit
4e8fa8b448
1 changed files with 600 additions and 47 deletions
|
@ -11,31 +11,72 @@
|
||||||
+----+----+----+----+----+----+----+----+
|
+----+----+----+----+----+----+----+----+
|
||||||
0x20|UID1|UID2|kghC|
|
0x20|UID1|UID2|kghC|
|
||||||
+----+----+----+
|
+----+----+----+
|
||||||
|
MCD = Manufacturer ID
|
||||||
|
MSN = Manufacturer SerialNumber
|
||||||
|
60 ea = DCF Low + DCF high
|
||||||
|
9f = raw byte which holds the bits for OLE,WRP,WRC,RD
|
||||||
|
ff = unknown but important
|
||||||
|
00 = unimportant
|
||||||
|
11 = unknown but important
|
||||||
|
Bck = header-backup-area
|
||||||
|
00 00 = Year (00 = 2000) & Week (not important)
|
||||||
|
Seg = Segment Header
|
||||||
|
SegC = Crc8 over the Segment Header
|
||||||
|
Stp = Stamp (could be more as 4 - up to 7)
|
||||||
|
UID = dec User-ID for online-Mapping
|
||||||
|
kghC = crc8 over MCD + MSN0..MSN2 + UID
|
||||||
|
|
||||||
|
|
||||||
|
(example) Legic-Cash on MIM256/1024 tag' (37 bytes)
|
||||||
|
+----+----+----+----+----+----+----+----+
|
||||||
|
0x00|Seg0|Seg1|Seg2|Seg3|SegC|STP0|STP1|STP2|
|
||||||
|
+----+----+----+----+----+----+----+----+
|
||||||
|
0x08|STP3|STP4|STP5|STP6| 01 |CURh|CURl|LIMh|
|
||||||
|
+----+----+----+----+----+----+----+----+
|
||||||
|
0x10|LIMm|LIMl|CHKh|CHKl|BALh|BALm|BALl|LRBh|
|
||||||
|
+----+----+----+----+----+----+----+----+
|
||||||
|
0x18|LRBm|LRBl|CHKh|CHKl|SHDh|SHDm|SHDl|LRSh|
|
||||||
|
+----+----+----+----+----+----+----+----+
|
||||||
|
0x20|LRSm|LRSl| CV |CHKh|CHKl|
|
||||||
|
+----+----+----+----+----+
|
||||||
|
STP = Stamp (seems to be always 7 bytes)
|
||||||
|
01 = unknown but important
|
||||||
|
CUR = currency in HEX (ISO 4217)
|
||||||
|
LIM = Cash-Limit
|
||||||
|
CHK = crc16 over byte-addr 0x05..0x12
|
||||||
|
BAL = Balance
|
||||||
|
LRB = ID of the reader that changed the balance
|
||||||
|
CHK = crc16 over BAL + LRB
|
||||||
|
SHD = shadow Balance
|
||||||
|
LRS = ID of the reader that changed the shadow balance (?? should be always the same as LRB)
|
||||||
|
CV = Counter value for transactions
|
||||||
|
CHK = crc16 over SHD + LRS + CV
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
example = "script run legic"
|
example = "script run legic"
|
||||||
author = "Mosci"
|
author = "Mosci"
|
||||||
version = "1.0"
|
version = "1.0.1"
|
||||||
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)
|
||||||
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 File I/O
|
Data I/O Segment Manipulation Token-Data
|
||||||
------------------ -------------------- ---------------
|
----------------- -------------------- -----------------
|
||||||
rt => read Tag ds => dump Segments lf => load File
|
rt => read Tag as => add Segment mt => make Token
|
||||||
wt => write Tag as => add Segment sf => save File
|
wt => write Tag es => edit Segment Header et => edit Token data
|
||||||
es => edit Segment xf => xor File
|
ct => copy io Tag ed => edit Segment Data tk => toggle KGH-Flag
|
||||||
ct => copy io Tag ed => edit Data
|
|
||||||
tc => copy oi Tag rs => remove Segment
|
tc => copy oi Tag rs => remove Segment
|
||||||
di => dump inTag cc => check Segment-CRC
|
cc => check Segment-CRC File I/O
|
||||||
do => dump outTag ck => check KGH
|
di => dump inTag ck => check KGH -----------------
|
||||||
tk => toggle KGH-Flag
|
do => dump outTag lf => load File
|
||||||
mt => make Token
|
ds => dump Segments sf => save File
|
||||||
q => quit et => edit Token h => this Help
|
lc => dump Legic-Cash xf => xor to File
|
||||||
|
d3p => dump 3rd Party Cash
|
||||||
|
r3p => raw 3rd Party Cash
|
||||||
|
|
||||||
|
|
||||||
Data I/O
|
|
||||||
rt: 'read tag' - reads a tag placed near to the PM3
|
rt: 'read tag' - reads a tag placed near to the PM3
|
||||||
wt: 'write tag' - writes the content of the 'virtual inTag' to a tag placed near to th PM3
|
wt: 'write tag' - writes the content of the 'virtual inTag' to a tag placed near to th PM3
|
||||||
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
|
||||||
|
@ -44,9 +85,6 @@ it's kinda interactive with following commands in three categories:
|
||||||
tc: 'copy tag' - copy the 'second virtual Tag' to 'virtual TAG' - not usefull yet, but inernally needed
|
tc: 'copy tag' - copy the 'second virtual Tag' to 'virtual TAG' - not usefull yet, but inernally needed
|
||||||
di: 'dump inTag' - shows the current content of the 'virtual Tag'
|
di: 'dump inTag' - shows the current content of the 'virtual Tag'
|
||||||
do: 'dump outTag' - shows the current content of the 'virtual outTag'
|
do: 'dump outTag' - shows the current content of the 'virtual outTag'
|
||||||
|
|
||||||
Segment Manipulation
|
|
||||||
(all manipulations happens only in the 'virtual inTAG' - they need to be written with 'wt' to take effect)
|
|
||||||
ds: 'dump Segments' - will show the content of a selected Segment
|
ds: 'dump Segments' - will show the content of a selected Segment
|
||||||
as: 'add Segment' - will add a 'empty' Segment to the inTag
|
as: 'add Segment' - will add a 'empty' Segment to the inTag
|
||||||
es: 'edit Segment' - edit the Segment-Header of a selected Segment (len, WRP, WRC, RD, valid)
|
es: 'edit Segment' - edit the Segment-Header of a selected Segment (len, WRP, WRC, RD, valid)
|
||||||
|
@ -60,14 +98,16 @@ it's kinda interactive with following commands in three categories:
|
||||||
'Kaba Group Header CRC calculation'
|
'Kaba Group Header CRC calculation'
|
||||||
tk: 'toggle KGH' - toglle the (script-internal) flag for kgh-calculation for a segment
|
tk: 'toggle KGH' - toglle the (script-internal) flag for kgh-calculation for a segment
|
||||||
xc: 'etra c' - show string that was used to calculate the kgh-crc of a segment
|
xc: 'etra c' - show string that was used to calculate the kgh-crc of a segment
|
||||||
|
dlc: 'dump Legic-Cash' - show balance and checksums of a legic-Cash Segment
|
||||||
Input/Output
|
d3p: 'dump 3rd Party' - show balance, history and checksums of a (yet) unknown 3rd Party Cash-Segment
|
||||||
|
r3p: 'raw 3rd Party' - show balance, history and checksums of a (yet) unknown 3rd Party Cash-Segment
|
||||||
|
e3p: 'edit 3rd Party' - edit Data in 3rd Party Cash Segment
|
||||||
lf: 'load file' - load a (xored) file from the local Filesystem into the 'virtual inTag'
|
lf: 'load file' - load a (xored) file 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 (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)
|
||||||
|
|
||||||
]]
|
]]
|
||||||
|
currentTag="inTAG"
|
||||||
---
|
---
|
||||||
-- requirements
|
-- requirements
|
||||||
local utils = require('utils')
|
local utils = require('utils')
|
||||||
|
@ -80,6 +120,15 @@ local bbit = bit32.extract
|
||||||
local input = utils.input
|
local input = utils.input
|
||||||
local confirm = utils.confirm
|
local confirm = utils.confirm
|
||||||
|
|
||||||
|
---
|
||||||
|
-- curency-codes for Legic-Cash-Segments (ISO 4217)
|
||||||
|
local currency = {
|
||||||
|
["03d2"]="EUR",
|
||||||
|
["0348"]="USD",
|
||||||
|
["033A"]="GBP",
|
||||||
|
["02F4"]="CHF"
|
||||||
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
function oops(err)
|
function oops(err)
|
||||||
|
@ -450,7 +499,7 @@ function makeToken()
|
||||||
-- edit token-data
|
-- edit token-data
|
||||||
function editTag(tag)
|
function editTag(tag)
|
||||||
-- for simulation it makes sense to edit everything
|
-- for simulation it makes sense to edit everything
|
||||||
local edit_sim="MCD MSN0 MSN2 MSN2 MCC DCFl DCFh WRP WRC RD"
|
local edit_sim="MCD MSN0 MSN1 MSN2 MCC DCFl DCFh WRP WRC RD"
|
||||||
-- on real tags it makes only sense to edit DCF, WRP, WRC, RD
|
-- on real tags it makes only sense to edit DCF, WRP, WRC, RD
|
||||||
local edit_real="DCFl DCFh WRP WRC RD"
|
local edit_real="DCFl DCFh WRP WRC RD"
|
||||||
if (confirm("do you want to edit non-writeable values (e.g. for simulation)?")) then
|
if (confirm("do you want to edit non-writeable values (e.g. for simulation)?")) then
|
||||||
|
@ -731,7 +780,7 @@ function dumpSegment(tag, index)
|
||||||
|
|
||||||
-- WRC protected
|
-- WRC protected
|
||||||
if (tag.SEG[i].WRC>0) then
|
if (tag.SEG[i].WRC>0) then
|
||||||
res = res .."\nWRC protected area (Stamp):\n"
|
res = res .."\nWRC protected area:\n"
|
||||||
for i2=dp, tag.SEG[i].WRC-1 do
|
for i2=dp, tag.SEG[i].WRC-1 do
|
||||||
res = res..tag.SEG[i].data[dp].." "
|
res = res..tag.SEG[i].data[dp].." "
|
||||||
dp=dp+1
|
dp=dp+1
|
||||||
|
@ -739,9 +788,9 @@ function dumpSegment(tag, index)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- WRP mprotected
|
-- WRP mprotected
|
||||||
if (tag.SEG[i].WRP>tag.SEG[i].WRC) then
|
if ((tag.SEG[i].WRP-tag.SEG[i].WRC)>0) then
|
||||||
res = res .."\nRemaining write protected area (Stamp):\n"
|
res = res .."\nRemaining write protected area:\n"
|
||||||
for i2=dp, tag.SEG[i].WRP-tag.SEG[i].WRC-1 do
|
for i2=dp, (tag.SEG[i].WRP-tag.SEG[i].WRC)-1 do
|
||||||
res = res..tag.SEG[i].data[dp].." "
|
res = res..tag.SEG[i].data[dp].." "
|
||||||
dp=dp+1
|
dp=dp+1
|
||||||
end
|
end
|
||||||
|
@ -787,10 +836,13 @@ end
|
||||||
---
|
---
|
||||||
-- edit Segment Data
|
-- edit Segment Data
|
||||||
function editSegmentData(data)
|
function editSegmentData(data)
|
||||||
|
local lc=check4LegicCash(data)
|
||||||
|
io.write("\n")
|
||||||
if (istable(data)) then
|
if (istable(data)) then
|
||||||
for i=0, #data-1 do
|
for i=0, #data-1 do
|
||||||
data[i]=input("Data"..i..": ", data[i])
|
data[i]=input("Data"..i..": ", data[i])
|
||||||
end
|
end
|
||||||
|
if (lc) then data=fixLegicCash(data) end
|
||||||
return data
|
return data
|
||||||
else
|
else
|
||||||
print("no Segment-Data found")
|
print("no Segment-Data found")
|
||||||
|
@ -876,6 +928,183 @@ function delSegment(tag, index)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- return bytes 'sstrat' to 'send' from a table
|
||||||
|
function dumpTable(tab, header, tstart, tend)
|
||||||
|
res=""
|
||||||
|
for i=tstart, tend do
|
||||||
|
res=res..tab[i].." "
|
||||||
|
end
|
||||||
|
if (string.len(header)==0) then return res
|
||||||
|
else return (header.." #"..(tend-tstart+1).."\n"..res) end
|
||||||
|
end
|
||||||
|
|
||||||
|
function dump3rdPartyCash1(tag , seg)
|
||||||
|
local uid=tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2
|
||||||
|
local stamp=tag.SEG[seg].data[0].." "..tag.SEG[seg].data[1].." "..tag.SEG[seg].data[2]
|
||||||
|
local datastamp=tag.SEG[seg].data[20].." "..tag.SEG[seg].data[21].." "..tag.SEG[seg].data[22]
|
||||||
|
local balance=tonumber(tag.SEG[seg].data[32]..tag.SEG[seg].data[33] ,16)
|
||||||
|
local balancecrc=utils.Crc8Legic(uid..tag.SEG[seg].data[32]..tag.SEG[seg].data[33])
|
||||||
|
local mirror=tonumber(tag.SEG[seg].data[35]..tag.SEG[seg].data[36] ,16)
|
||||||
|
local mirrorcrc=utils.Crc8Legic(uid..tag.SEG[seg].data[35]..tag.SEG[seg].data[36])
|
||||||
|
local lastbal0=tonumber(tag.SEG[seg].data[39]..tag.SEG[seg].data[40] ,16)
|
||||||
|
local lastbal1=tonumber(tag.SEG[seg].data[41]..tag.SEG[seg].data[42] ,16)
|
||||||
|
local lastbal2=tonumber(tag.SEG[seg].data[43]..tag.SEG[seg].data[44] ,16)
|
||||||
|
|
||||||
|
test=""
|
||||||
|
-- display decoded/known stuff
|
||||||
|
print("\n------------------------------")
|
||||||
|
print("Tag-ID:\t\t "..uid)
|
||||||
|
print("Stamp:\t\t "..stamp)
|
||||||
|
print("UID-Mapping: \t\t"..("%06d"):format(tonumber(tag.SEG[seg].data[46]..tag.SEG[seg].data[47]..tag.SEG[seg].data[48], 16)))
|
||||||
|
print("------------------------------")
|
||||||
|
print("checksum 1:\t\t "..tag.SEG[seg].data[31].." ("..compareCrc(utils.Crc8Legic(uid..dumpTable(tag.SEG[seg].data, "", 19, 30)), tag.SEG[seg].data[31])..")")
|
||||||
|
print("checksum 2:\t\t "..tag.SEG[seg].data[34].." ("..compareCrc(utils.Crc8Legic(uid..dumpTable(tag.SEG[seg].data, "", 32, 33)), tag.SEG[seg].data[34])..")")
|
||||||
|
print("checksum 3:\t\t "..tag.SEG[seg].data[37].." ("..compareCrc(utils.Crc8Legic(uid..dumpTable(tag.SEG[seg].data, "", 35, 36)), tag.SEG[seg].data[37])..")")
|
||||||
|
|
||||||
|
print("checksum 4:\t\t "..tag.SEG[seg].data[55].." ("..compareCrc(utils.Crc8Legic(uid..dumpTable(tag.SEG[seg].data, "", 46, 54)), tag.SEG[seg].data[55])..")")
|
||||||
|
print("checksum 5:\t\t "..tag.SEG[seg].data[62].." ("..compareCrc(utils.Crc8Legic(uid..dumpTable(tag.SEG[seg].data, "", 56, 61)), tag.SEG[seg].data[62])..")")
|
||||||
|
print("checksum 6:\t\t "..tag.SEG[seg].data[73].." ("..compareCrc(utils.Crc8Legic(uid..dumpTable(tag.SEG[seg].data, "", 63, 72)), tag.SEG[seg].data[73])..")")
|
||||||
|
print("checksum 7:\t\t "..tag.SEG[seg].data[89].." ("..compareCrc(utils.Crc8Legic(uid..dumpTable(tag.SEG[seg].data, "", 74, 88)), tag.SEG[seg].data[89])..")")
|
||||||
|
print("------------------------------")
|
||||||
|
print(string.format("Balance:\t\t %3.2f", balance/100).." ".."("..compareCrc(balancecrc, tag.SEG[seg].data[34])..")")
|
||||||
|
print(string.format("Shadow:\t\t\t %3.2f", mirror/100).." ".."("..compareCrc(balancecrc, tag.SEG[seg].data[37])..")")
|
||||||
|
print("------------------------------")
|
||||||
|
print(string.format("History 1:\t\t %3.2f", lastbal0/100))
|
||||||
|
print(string.format("History 2:\t\t %3.2f", lastbal1/100))
|
||||||
|
print(string.format("History 3:\t\t %3.2f", lastbal2/100))
|
||||||
|
print("------------------------------\n")
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- compare two bytes
|
||||||
|
function compareCrc(calc, guess)
|
||||||
|
calc=("%02x"):format(calc)
|
||||||
|
if (calc==guess) then return "valid"
|
||||||
|
else return "error "..calc.."!="..guess end
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- compare 4 bytes
|
||||||
|
function compareCrc16(calc, guess)
|
||||||
|
calc=("%04x"):format(calc)
|
||||||
|
if (calc==guess) then return "valid"
|
||||||
|
else return "error "..calc.."!="..guess end
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- repair / fix (yet known) crc's of a '3rd Party Cash-Segment'
|
||||||
|
-- not all bytes know until yet !!
|
||||||
|
function fix3rdPartyCash1(uid, data)
|
||||||
|
if(#data==95) then
|
||||||
|
-- checksum 1
|
||||||
|
data[31]=("%02x"):format(utils.Crc8Legic(uid..dumpTable(data, "", 19, 30)))
|
||||||
|
-- checksum 2
|
||||||
|
data[34]=("%02x"):format(utils.Crc8Legic(uid..data[32]..data[33]))
|
||||||
|
-- checksum 3
|
||||||
|
data[37]=("%02x"):format(utils.Crc8Legic(uid..data[35]..data[36]))
|
||||||
|
-- checksum 4
|
||||||
|
data[55]=("%02x"):format(utils.Crc8Legic(uid..dumpTable(data, "", 46, 54)))
|
||||||
|
-- checksum 5
|
||||||
|
data[62]=("%02x"):format(utils.Crc8Legic(uid..dumpTable(data, "", 56, 61)))
|
||||||
|
-- checksum 6
|
||||||
|
data[73]=("%02x"):format(utils.Crc8Legic(uid..dumpTable(data, "", 63, 72)))
|
||||||
|
-- checksum 7
|
||||||
|
data[89]=("%02x"):format(utils.Crc8Legic(uid..dumpTable(data, "", 74, 88)))
|
||||||
|
return data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- edit uid 3rd party cash
|
||||||
|
function edit3rdUid(mapid, uid, data)
|
||||||
|
mapid=("%06x"):format(tonumber(mapid, 10))
|
||||||
|
data[46]=string.sub(mapid, 0 ,2)
|
||||||
|
data[47]=string.sub(mapid, 3 ,4)
|
||||||
|
data[48]=string.sub(mapid, 5 ,6)
|
||||||
|
return fix3rdPartyCash1(uid, data)
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- edit balance 3rd party cash
|
||||||
|
function edit3rdCash(new_cash, uid, data)
|
||||||
|
new_cash=("%04x"):format(new_cash)
|
||||||
|
data[32]=string.sub(new_cash, 0,2)
|
||||||
|
data[33]=string.sub(new_cash, 3,4)
|
||||||
|
data[34]=("%02x"):format(utils.Crc8Legic(uid..new_cash))
|
||||||
|
data[35]=string.sub(new_cash, 0,2)
|
||||||
|
data[36]=string.sub(new_cash, 3,4)
|
||||||
|
data[37]=("%02x"):format(utils.Crc8Legic(uid..new_cash))
|
||||||
|
data[39]=string.sub(new_cash, 0,2)
|
||||||
|
data[40]=string.sub(new_cash, 3,4)
|
||||||
|
data[41]='00'
|
||||||
|
data[42]='00'
|
||||||
|
data[43]='00'
|
||||||
|
data[44]='00'
|
||||||
|
return fix3rdPartyCash1(uid, data)
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- repair / fix crc's of a 'Legic-Cash-Segment'
|
||||||
|
function fixLegicCash(data)
|
||||||
|
if(#data==32 and data[7]=="01") then
|
||||||
|
local crc1, crc2, crc3
|
||||||
|
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)))
|
||||||
|
data[13]=string.sub(crc1, 0, 2)
|
||||||
|
data[14]=string.sub(crc1, 3, 4)
|
||||||
|
data[21]=string.sub(crc2, 0, 2)
|
||||||
|
data[22]=string.sub(crc2, 3, 4)
|
||||||
|
data[30]=string.sub(crc3, 0, 2)
|
||||||
|
data[31]=string.sub(crc3, 3, 4)
|
||||||
|
return data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- chack for signature of a '3rd Party Cash-Segment'
|
||||||
|
-- not all bytes know until yet !!
|
||||||
|
function check43rdPartyCash1(uid, data)
|
||||||
|
if(#data==95) then
|
||||||
|
-- too explicit checking will avoid fixing ;-)
|
||||||
|
if (compareCrc(utils.Crc8Legic(uid..dumpTable(data, "", 19, 30)), data[31])=="valid") then
|
||||||
|
--if (compareCrc(utils.Crc8Legic(uid..data[32]..data[33]), data[34])=="valid") then
|
||||||
|
--if (compareCrc(utils.Crc8Legic(uid..data[35]..data[36]), data[37])=="valid") then
|
||||||
|
--if (compareCrc(utils.Crc8Legic(uid..dumpTable(data, "", 56, 61)), data[62])=="valid") then
|
||||||
|
--if (compareCrc(utils.Crc8Legic(uid..dumpTable(data, "", 74, 88)), data[89])=="valid") then
|
||||||
|
io.write("3rd Party Cash-Segment detected ")
|
||||||
|
return true
|
||||||
|
--end
|
||||||
|
--end
|
||||||
|
--end
|
||||||
|
--end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- chack for signature of a 'Legic-Cash-Segment'
|
||||||
|
function check4LegicCash(data)
|
||||||
|
if(#data==32) then
|
||||||
|
local stamp_len=(#data-25)
|
||||||
|
local stamp=""
|
||||||
|
for i=0, stamp_len-1 do
|
||||||
|
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
|
||||||
|
io.write("Legic-Cash Segment detected ")
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
---
|
---
|
||||||
-- calculate Master-Token crc
|
-- calculate Master-Token crc
|
||||||
function calcMtCrc(bytes)
|
function calcMtCrc(bytes)
|
||||||
|
@ -986,31 +1215,41 @@ end
|
||||||
function modifyHelp()
|
function modifyHelp()
|
||||||
local t=[[
|
local t=[[
|
||||||
|
|
||||||
Data I/O Segment Manipulation File I/O
|
Data I/O Segment Manipulation Token-Data
|
||||||
------------------ -------------------- ------------------
|
----------------- -------------------- -----------------
|
||||||
rt => read Tag ds => dump Segments lf => load File
|
rt => read Tag as => add Segment mt => make Token
|
||||||
wt => write Tag as => add Segment sf => save File
|
wt => write Tag es => edit Segment Header et => edit Token data
|
||||||
es => edit Segment xf => xor to File
|
ct => copy io Tag ed => edit Segment Data tk => toggle KGH-Flag
|
||||||
ct => copy io Tag ed => edit Data
|
|
||||||
tc => copy oi Tag rs => remove Segment
|
tc => copy oi Tag rs => remove Segment
|
||||||
cc => check Segment-CRC
|
tt => toggle Tag cc => check Segment-CRC File I/O
|
||||||
di => dump inTag ck => check KGH
|
di => dump inTag ck => check KGH -----------------
|
||||||
do => dump outTag tk => toggle KGH-Flag
|
do => dump outTag e3p => edit 3rd Party Cash lf => load File
|
||||||
mt => make Token
|
ds => dump Segment sf => save File
|
||||||
q => quit et => edit Token h => this Help
|
dlc => dump Legic-Cash xf => xor to File
|
||||||
|
d3p => dump 3rd Party Cash
|
||||||
|
r3p => raw 3rd Party Cash
|
||||||
|
|
||||||
|
|
||||||
|
q => quit
|
||||||
]]
|
]]
|
||||||
return t
|
return t
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
-- modify Tag (interactive)
|
-- modify Tag (interactive)
|
||||||
function modifyMode()
|
function modifyMode()
|
||||||
local i, outTAG, inTAG, outfile, infile, sel, segment, bytes, outbytes
|
local i, backupTAG, outTAG, inTAG, outfile, infile, sel, segment, bytes, outbytes
|
||||||
|
|
||||||
actions = {
|
actions = {
|
||||||
["h"] = function(x)
|
["h"] = function(x)
|
||||||
print(modifyHelp().."\n".."tags im Memory:"..(istable(inTAG) and " inTAG" or "")..(istable(outTAG) and " outTAG" or ""))
|
print(" Version: "..version);
|
||||||
|
print(modifyHelp().."\n".."tags im Memory: "..(istable(inTAG) and ((currentTag=='inTAG') and "*mainTAG" or "mainTAG") or "").." "..(istable(backupTAG) and ((currentTag=='backupTAG') and "*backupTAG" or "backupTAG") or ""))
|
||||||
end,
|
end,
|
||||||
["rt"] = function(x) inTAG=readFromPM3(); actions.di() end,
|
["rt"] = function(x)
|
||||||
|
inTAG=readFromPM3();
|
||||||
|
--actions.di()
|
||||||
|
end,
|
||||||
["wt"] = function(x)
|
["wt"] = function(x)
|
||||||
if(istable(inTAG.SEG)) then
|
if(istable(inTAG.SEG)) then
|
||||||
local taglen=22
|
local taglen=22
|
||||||
|
@ -1019,6 +1258,8 @@ function modifyMode()
|
||||||
taglen=taglen+inTAG.SEG[i].len+5
|
taglen=taglen+inTAG.SEG[i].len+5
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local uid_old=inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2
|
||||||
-- read new tag (output tag)
|
-- read new tag (output tag)
|
||||||
outTAG=readFromPM3()
|
outTAG=readFromPM3()
|
||||||
outbytes=tagToBytes(outTAG)
|
outbytes=tagToBytes(outTAG)
|
||||||
|
@ -1032,6 +1273,14 @@ function modifyMode()
|
||||||
if(istable(inTAG.Bck)) then
|
if(istable(inTAG.Bck)) then
|
||||||
checkAllSegCrc(inTAG)
|
checkAllSegCrc(inTAG)
|
||||||
checkAllKghCrc(inTAG)
|
checkAllKghCrc(inTAG)
|
||||||
|
local uid_new=inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2
|
||||||
|
for i=0, #inTAG.SEG do
|
||||||
|
if (check43rdPartyCash1(uid_old, inTAG.SEG[i].data)) then
|
||||||
|
io.write(" - fixing known checksums ... ")
|
||||||
|
inTAG.SEG[i].data=fix3rdPartyCash1(uid_new, inTAG.SEG[i].data)
|
||||||
|
io.write(" done\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
--get bytes from ready outTAG
|
--get bytes from ready outTAG
|
||||||
bytes=tagToBytes(inTAG)
|
bytes=tagToBytes(inTAG)
|
||||||
|
@ -1044,13 +1293,28 @@ function modifyMode()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
---
|
||||||
|
-- switich and copy virtual tags
|
||||||
|
|
||||||
["ct"] = function(x)
|
["ct"] = function(x)
|
||||||
print("copy virtual input-TAG to output-TAG")
|
print("copy mainTAG to backupTAG")
|
||||||
outTAG=inTAG
|
outTAG=deepCopy(inTAG)
|
||||||
|
backupTAG=deepCopy(inTAG)
|
||||||
end,
|
end,
|
||||||
["tc"] = function(x)
|
["tc"] = function(x)
|
||||||
print("copy virtual output-TAG to input-TAG")
|
print("copy backupTAG to mainTAG")
|
||||||
inTAG=outTAG
|
inTAG=deepCopy(backupTAG)
|
||||||
|
end,
|
||||||
|
["tt"] = function(x)
|
||||||
|
print("toggle to "..((currentTag=='inTAG') and "backupTAG" or "mainTAG"))
|
||||||
|
if(currentTag=="inTAG") then
|
||||||
|
outTAG=deepCopy(inTAG)
|
||||||
|
inTAG=deepCopy(backupTAG)
|
||||||
|
currentTag='backupTAG'
|
||||||
|
else
|
||||||
|
inTAG=deepCopy(outTAG)
|
||||||
|
currentTag='inTAG'
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
["lf"] = function(x)
|
["lf"] = function(x)
|
||||||
if (file_check(x)) then filename=x
|
if (file_check(x)) then filename=x
|
||||||
|
@ -1079,8 +1343,25 @@ function modifyMode()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
["di"] = function(x) if (istable(inTAG)) then print("\n"..dumpTag(inTAG).."\n") end end,
|
["di"] = function(x)
|
||||||
["do"] = function(x) if (istable(outTAG)) then print("\n"..dumpTag(outTAG).."\n") end end,
|
if (istable(inTAG)) then
|
||||||
|
local uid=inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2
|
||||||
|
if(istable(inTAG.SEG[0])) then
|
||||||
|
for i=0, #inTAG.SEG do
|
||||||
|
if(check43rdPartyCash1(uid, inTAG.SEG[i].data)) then
|
||||||
|
io.write("in Segment index: "..inTAG.SEG[i].index.."\n")
|
||||||
|
elseif(check4LegicCash(inTAG.SEG[i].data)) then
|
||||||
|
io.write("in Segment index: "..inTAG.SEG[i].index.."\n")
|
||||||
|
lc=true;
|
||||||
|
lci=inTAG.SEG[i].index;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
print("\n"..dumpTag(inTAG).."\n")
|
||||||
|
if (lc) then actions["dlc"](lci) end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
["do"] = function(x) if (istable(backupTAG)) then print("\n"..dumpTag(backupTAG).."\n") end end,
|
||||||
["ds"] = function(x)
|
["ds"] = function(x)
|
||||||
if (type(x)=="string" and string.len(x)>0) then sel=tonumber(x,10)
|
if (type(x)=="string" and string.len(x)>0) then sel=tonumber(x,10)
|
||||||
else sel=selectSegment(inTAG) end
|
else sel=selectSegment(inTAG) end
|
||||||
|
@ -1145,6 +1426,8 @@ function modifyMode()
|
||||||
print(("%02x"):format(utils.Crc8Legic(x)))
|
print(("%02x"):format(utils.Crc8Legic(x)))
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
["xb"] = function(x)
|
||||||
|
end,
|
||||||
["xc"] = function(x)
|
["xc"] = function(x)
|
||||||
if (istable(inTAG) and istable(inTAG.SEG[0])) then
|
if (istable(inTAG) and istable(inTAG.SEG[0])) then
|
||||||
if (type(x)=="string" and string.len(x)>0) then sel=tonumber(x,10)
|
if (type(x)=="string" and string.len(x)>0) then sel=tonumber(x,10)
|
||||||
|
@ -1152,26 +1435,277 @@ function modifyMode()
|
||||||
print("k "..kghCrcCredentials(inTAG, sel))
|
print("k "..kghCrcCredentials(inTAG, sel))
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
["dlc"] = function(x)
|
||||||
|
local uid=inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2
|
||||||
|
-- if segment index was user defined
|
||||||
|
if (type(x)=="string" and string.len(x)>0) then
|
||||||
|
x=tonumber(x,10)
|
||||||
|
print(string.format("User-Selected Index %02d", x))
|
||||||
|
-- or try to find match
|
||||||
|
else x=autoSelectSegment(inTAG, "legiccash") end
|
||||||
|
local uid=inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2
|
||||||
|
if (istable(inTAG.SEG[x])) then
|
||||||
|
io.write("in Segment "..inTAG.SEG[x].index.." :\n")
|
||||||
|
print("--------------------------------\n\tLegic-Cash Values\n--------------------------------")
|
||||||
|
local limit, curr, balance, rid, tcv
|
||||||
|
-- currency of balance & limit
|
||||||
|
curr=currency[inTAG.SEG[x].data[8]..inTAG.SEG[x].data[9]]
|
||||||
|
-- maximum balance
|
||||||
|
limit=string.format("%4.2f", tonumber(inTAG.SEG[x].data[10]..inTAG.SEG[x].data[11]..inTAG.SEG[x].data[12], 16)/100)
|
||||||
|
-- current balance
|
||||||
|
balance=string.format("%4.2f", tonumber(inTAG.SEG[x].data[15]..inTAG.SEG[x].data[16]..inTAG.SEG[x].data[17], 16)/100)
|
||||||
|
-- reader-id who wrote last transaction
|
||||||
|
rid=tonumber(inTAG.SEG[x].data[18]..inTAG.SEG[x].data[19]..inTAG.SEG[x].data[20], 16)
|
||||||
|
-- transaction counter value
|
||||||
|
tcv=tonumber(inTAG.SEG[x].data[29], 16)
|
||||||
|
print("Currency:\t\t "..curr)
|
||||||
|
print("Limit:\t\t\t "..limit)
|
||||||
|
print("Balance:\t\t "..balance)
|
||||||
|
print("Transaction Counter:\t "..tcv)
|
||||||
|
print("Reader-ID:\t\t "..rid.."\n--------------------------------\n")
|
||||||
|
end
|
||||||
|
--end
|
||||||
|
end,
|
||||||
|
["df"] = function(x)
|
||||||
|
actions["lf"](x)
|
||||||
|
res=""
|
||||||
|
for i=0, #inTAG.SEG[1].data do
|
||||||
|
res=res..inTAG.SEG[1].data[i]
|
||||||
|
end
|
||||||
|
print(res)
|
||||||
|
end,
|
||||||
|
["d3p"] = function(x)
|
||||||
|
local uid=inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2
|
||||||
|
-- if segment index was user defined
|
||||||
|
if (type(x)=="string" and string.len(x)>0) then
|
||||||
|
x=tonumber(x,10)
|
||||||
|
print(string.format("User-Selected Index %02d", x))
|
||||||
|
-- or try to find match
|
||||||
|
else x=autoSelectSegment(inTAG, "3rdparty") end
|
||||||
|
|
||||||
|
if (istable(inTAG) and istable(inTAG.SEG[x]) and inTAG.SEG[x].len == 100) then
|
||||||
|
uid=inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2
|
||||||
|
if (check43rdPartyCash1(uid, inTAG.SEG[x].data)) then
|
||||||
|
dump3rdPartyCash1(inTAG, x)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
["r3p"] = function(x)
|
||||||
|
local uid=inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2
|
||||||
|
-- if segment index was user defined
|
||||||
|
if (type(x)=="string" and string.len(x)>0) then
|
||||||
|
x=tonumber(x,10)
|
||||||
|
print(string.format("User-Selected Index %02d", x))
|
||||||
|
-- or try to find match
|
||||||
|
else x=autoSelectSegment(inTAG, "3rdparty") end
|
||||||
|
local uid=inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2
|
||||||
|
if (istable(inTAG.SEG[x])) then
|
||||||
|
print("\n\t\tStamp : "..dumpTable(inTAG.SEG[x].data, "", 0 , 2))
|
||||||
|
print("\t\tBlock 0: "..dumpTable(inTAG.SEG[x].data, "", 3 , 18))
|
||||||
|
print()
|
||||||
|
print("\t\tBlock 1: "..dumpTable(inTAG.SEG[x].data, "", 19, 30))
|
||||||
|
print("checksum 1: Tag-ID .. Block 1 => LegicCrc8 = "..inTAG.SEG[x].data[31].." ("..compareCrc(utils.Crc8Legic(uid..dumpTable(inTAG.SEG[x].data, "", 19, 30)), inTAG.SEG[x].data[31])..")")
|
||||||
|
print()
|
||||||
|
print("\t\tBlock 2: "..dumpTable(inTAG.SEG[x].data, "", 32, 33))
|
||||||
|
print("checksum 2: Block 2 => LegicCrc8 = "..inTAG.SEG[x].data[34].." ("..compareCrc(utils.Crc8Legic(uid..dumpTable(inTAG.SEG[x].data, "", 32, 33)), inTAG.SEG[x].data[34])..")")
|
||||||
|
print()
|
||||||
|
print("\t\tBlock 3: "..dumpTable(inTAG.SEG[x].data, "", 35, 36))
|
||||||
|
print("checksum 3: Block 3 => LegicCrc8 = "..inTAG.SEG[x].data[37].." ("..compareCrc(utils.Crc8Legic(uid..dumpTable(inTAG.SEG[x].data, "", 35, 36)), inTAG.SEG[x].data[37])..")")
|
||||||
|
print()
|
||||||
|
print("\t\tyet unknown: "..inTAG.SEG[x].data[38])
|
||||||
|
print()
|
||||||
|
print("\t\tHisatory 1: "..dumpTable(inTAG.SEG[x].data, "", 39, 40))
|
||||||
|
print("\t\tHisatory 2: "..dumpTable(inTAG.SEG[x].data, "", 41, 42))
|
||||||
|
print("\t\tHisatory 3: "..dumpTable(inTAG.SEG[x].data, "", 43, 44))
|
||||||
|
print()
|
||||||
|
print("\t\tyet unknown: "..inTAG.SEG[x].data[45])
|
||||||
|
print()
|
||||||
|
print("\t\tKGH-UID HEX: "..dumpTable(inTAG.SEG[x].data, "", 46, 48))
|
||||||
|
print("\t\tBlock 4: "..dumpTable(inTAG.SEG[x].data, "", 49, 54))
|
||||||
|
print("checksum 4: Tag-ID .. KGH-UID .. Block 4 => LegicCrc8 = "..inTAG.SEG[x].data[55].." ("..compareCrc(utils.Crc8Legic(uid..dumpTable(inTAG.SEG[x].data, "", 46, 54)), inTAG.SEG[x].data[55])..")")
|
||||||
|
print()
|
||||||
|
print("\t\tBlock 5: "..dumpTable(inTAG.SEG[x].data, "", 56, 61))
|
||||||
|
print("checksum 5: Tag-ID .. Block 5 => LegicCrc8 = "..inTAG.SEG[x].data[62].." ("..compareCrc(utils.Crc8Legic(uid..dumpTable(inTAG.SEG[x].data, "", 56, 61)), inTAG.SEG[x].data[62])..")")
|
||||||
|
print()
|
||||||
|
print("\t\tBlock 6: "..dumpTable(inTAG.SEG[x].data, "", 63, 72))
|
||||||
|
print("checksum 6: Tag-ID .. Block 6 => LegicCrc8 = "..inTAG.SEG[x].data[73].." ("..compareCrc(utils.Crc8Legic(uid..dumpTable(inTAG.SEG[x].data, "", 63, 72)), inTAG.SEG[x].data[73])..")")
|
||||||
|
print()
|
||||||
|
print("\t\tBlock 7: "..dumpTable(inTAG.SEG[x].data, "", 74, 88))
|
||||||
|
print("checksum 7: Tag-ID .. Block 7 => LegicCrc8 = "..inTAG.SEG[x].data[89].." ("..compareCrc(utils.Crc8Legic(uid..dumpTable(inTAG.SEG[x].data, "", 74, 88)), inTAG.SEG[x].data[89])..")")
|
||||||
|
print()
|
||||||
|
print("\t\tBlock 8: "..dumpTable(inTAG.SEG[x].data, "", 90, 94))
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
["e3p"] = function(x)
|
||||||
|
local uid=inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2
|
||||||
|
-- if segment index was user defined
|
||||||
|
if (type(x)=="string" and string.len(x)>0) then
|
||||||
|
x=tonumber(x,10)
|
||||||
|
print(string.format("User-Selected Index %02d", x))
|
||||||
|
-- or try to find match
|
||||||
|
else x=autoSelectSegment(inTAG, "3rdparty") end
|
||||||
|
|
||||||
|
if (istable(inTAG) and istable(inTAG.SEG[x]) and inTAG.SEG[x].len == 100) then
|
||||||
|
--if (check43rdPartyCash1(uid, inTAG.SEG[x].data)) then
|
||||||
|
-- change Balance
|
||||||
|
if (confirm("\nedit Balance?")) then
|
||||||
|
local new_cash=input("enter new Balance without comma or currency", "100")
|
||||||
|
inTAG.SEG[x].data=edit3rdCash(new_cash, uid, inTAG.SEG[x].data)
|
||||||
|
end
|
||||||
|
-- change User-ID (used for online-account-mapping)
|
||||||
|
if (confirm("\nedit UserID-Mapping?")) then
|
||||||
|
local new_mapid=input("enter new UserID (6-digit value)", "012345")
|
||||||
|
inTAG.SEG[x].data=edit3rdUid(new_mapid, uid, inTAG.SEG[x].data)
|
||||||
|
end
|
||||||
|
if (confirm("\nedit Stamp?")) then
|
||||||
|
local new_stamp=input("enter new Stamp", getSegmentStamp(inTAG.SEG[x]))
|
||||||
|
inTAG.SEG[x].data=editStamp(new_stamp, uid, inTAG.SEG[x].data)
|
||||||
|
new_stamp=getSegmentStamp(inTAG.SEG[x], 'true')
|
||||||
|
print("stamp_bytes: "..#new_stamp)
|
||||||
|
-- replace stamp in 'block 1' also
|
||||||
|
io.write("editing stamp in Block 1 also ")
|
||||||
|
for i=20, (20+#new_stamp-1) do
|
||||||
|
inTAG.SEG[x].data[i]=new_stamp[i-19]
|
||||||
|
io.write(".");
|
||||||
|
end
|
||||||
|
print(" done")
|
||||||
|
-- fix known checksums
|
||||||
|
inTAG.SEG[x].data=fix3rdPartyCash1(uid, inTAG.SEG[x].data)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- print out new settings
|
||||||
|
dump3rdPartyCash1(inTAG, x)
|
||||||
|
--end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
["gs"] = function(x)
|
||||||
|
if(type(x)=="string" and string.len(x)>=2) then x=tonumber(x, 10)
|
||||||
|
else x=selectSegment(inTAG) end
|
||||||
|
local stamp=getSegmentStamp(inTAG.SEG[x])
|
||||||
|
print("Stamp : "..stamp)
|
||||||
|
stamp=str2bytes(stamp)
|
||||||
|
print("lenght: "..#stamp)
|
||||||
|
end,
|
||||||
|
["c6"] = function(x) local crc16=string.format("%4.04x", utils.Crc16(x))
|
||||||
|
print(string.sub(crc16, 0,2).." "..string.sub(crc16, 3,4))
|
||||||
|
end,
|
||||||
["cc"] = function(x) if (istable(inTAG)) then checkAllSegCrc(inTAG) end end,
|
["cc"] = function(x) if (istable(inTAG)) then checkAllSegCrc(inTAG) end end,
|
||||||
|
["cb"] = function(x)
|
||||||
|
if (istable(inTAG)) then
|
||||||
|
print("purge BackupArea")
|
||||||
|
inTAG=clearBackupArea(inTAG)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
["f3p"] = function(x)
|
||||||
|
if(type(x)=="string" and string.len(x)>=2) then x=tonumber(x, 10)
|
||||||
|
else x=selectSegment(inTAG) end
|
||||||
|
if (istable(inTAG.SEG[x])) then
|
||||||
|
local uid=inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2
|
||||||
|
inTAG.SEG[x].data=fix3rdPartyCash1(uid, inTAG.SEG[x].data)
|
||||||
|
end
|
||||||
|
end,
|
||||||
["ck"] = function(x) if (istable(inTAG)) then checkAllKghCrc(inTAG) end end,
|
["ck"] = function(x) if (istable(inTAG)) then checkAllKghCrc(inTAG) end end,
|
||||||
}
|
}
|
||||||
print("modify-modus! enter 'h' for help or 'q' to quit")
|
print("modify-modus! enter 'h' for help or 'q' to quit")
|
||||||
repeat
|
repeat
|
||||||
ic=input("Legic command? ('h' for help - 'q' for quit)", "h")
|
ic=input("Legic command? ('h' for help - 'q' for quit)", "h")
|
||||||
-- command actions
|
-- command actions
|
||||||
if (type(actions[string.lower(string.sub(ic,0,1))])=='function') then
|
if (type(actions[string.lower(string.sub(ic,0,3))])=='function') then
|
||||||
actions[string.lower(string.sub(ic,0,1))](string.sub(ic,3))
|
actions[string.lower(string.sub(ic,0,3))](string.sub(ic,5))
|
||||||
elseif (type(actions[string.lower(string.sub(ic,0,2))])=='function') then
|
elseif (type(actions[string.lower(string.sub(ic,0,2))])=='function') then
|
||||||
actions[string.lower(string.sub(ic,0,2))](string.sub(ic,4))
|
actions[string.lower(string.sub(ic,0,2))](string.sub(ic,4))
|
||||||
|
elseif (type(actions[string.lower(string.sub(ic,0,1))])=='function') then
|
||||||
|
actions[string.lower(string.sub(ic,0,1))](string.sub(ic,3))
|
||||||
else actions.h('') end
|
else actions.h('') end
|
||||||
until (string.sub(ic,0,1)=="q")
|
until (string.sub(ic,0,1)=="q")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function clearBackupArea(tag)
|
||||||
|
for i=1, #tag.Bck do
|
||||||
|
tag.Bck[i]='00'
|
||||||
|
end
|
||||||
|
return tag
|
||||||
|
end
|
||||||
|
|
||||||
|
function getSegmentStamp(seg, bytes)
|
||||||
|
local stamp=""
|
||||||
|
local stamp_len=7
|
||||||
|
--- the 'real' stamp on MIM is not really easy to tell for me since the 'data-block' covers stamp0..stampn+data0..datan
|
||||||
|
-- there a no stamps longer than 7 bytes & they are write-protected by default , and I have not seen user-credntials
|
||||||
|
-- with stamps smaller 3 bytes (except: Master-Token)
|
||||||
|
-- WRP -> Read/Write Protection
|
||||||
|
-- WRC -> Read/Write Condition
|
||||||
|
-- RD depends on WRC - if WRC > 0 and RD=1: only reader with matching #WRC of Stamp-bytes in thier Database have Read-Access to the Tag
|
||||||
|
if (seg.WRP<7) then stamp_len=(seg.WRP) end
|
||||||
|
for i=1, (stamp_len) do
|
||||||
|
stamp=stamp..seg.data[i-1]
|
||||||
|
end
|
||||||
|
if (bytes) then
|
||||||
|
stamp=str2bytes(stamp)
|
||||||
|
return stamp
|
||||||
|
else return stamp end
|
||||||
|
end
|
||||||
|
|
||||||
|
function str2bytes(s)
|
||||||
|
local res={}
|
||||||
|
if (string.len(s)%2~=0) then return print("stamp should be a even hexstring e.g.: deadbeef or 0badc0de") end
|
||||||
|
for i=1, string.len(s), 2 do
|
||||||
|
table.insert(res, string.sub(s,i,(i+1)))
|
||||||
|
end
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
function editStamp(new_stamp, uid, data)
|
||||||
|
local stamp=str2bytes(new_stamp)
|
||||||
|
for i=0, #stamp-1 do
|
||||||
|
data[i]=stamp[i+1]
|
||||||
|
end
|
||||||
|
-- now fill in stamp
|
||||||
|
for i=0, (string.len(new_stamp)/2)-1 do
|
||||||
|
data[i]=stamp[i+1]
|
||||||
|
end
|
||||||
|
return fix3rdPartyCash1(uid, data)
|
||||||
|
end
|
||||||
|
|
||||||
|
function autoSelectSegment(tag, s)
|
||||||
|
local uid=tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2
|
||||||
|
local x=#tag.SEG+1
|
||||||
|
local res = false
|
||||||
|
io.write("autoSelect ")
|
||||||
|
--- search for desired segment-type
|
||||||
|
-- 3rd Party Segment
|
||||||
|
if (s=="3rdparty") then
|
||||||
|
repeat
|
||||||
|
io.write(". ")
|
||||||
|
x=x-1
|
||||||
|
res=check43rdPartyCash1(uid, tag.SEG[x].data)
|
||||||
|
until ( res or x==0 )
|
||||||
|
end
|
||||||
|
-- Legic-Cash Segment
|
||||||
|
if (s=="legiccash") then
|
||||||
|
repeat
|
||||||
|
io.write(". ")
|
||||||
|
x=x-1
|
||||||
|
res=check4LegicCash(tag.SEG[x].data)
|
||||||
|
until ( res or x==0 )
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- segment found
|
||||||
|
if (res) then
|
||||||
|
io.write("\nautoselected Index: "..string.format("%02d", x).."\n")
|
||||||
|
return x
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- nothing found
|
||||||
|
io.write("no Segment found\n")
|
||||||
|
return -1
|
||||||
|
end
|
||||||
|
|
||||||
--- main function
|
--- main function
|
||||||
function main(args)
|
function main(args)
|
||||||
if (#args == 0 ) then modifyMode() end
|
if (#args == 0 ) then modifyMode() end
|
||||||
--- variables
|
--- variables
|
||||||
local inTAG, outTAG, outfile, interactive, crc, ofs, cfs, dfs
|
local inTAG, backupTAG, outTAG, outfile, interactive, crc, ofs, cfs, dfs
|
||||||
-- just a spacer for better readability
|
-- just a spacer for better readability
|
||||||
print()
|
print()
|
||||||
--- parse arguments
|
--- parse arguments
|
||||||
|
@ -1222,5 +1756,24 @@ function main(args)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Creates a complete/deep copy of the data
|
||||||
|
function deepCopy(object)
|
||||||
|
local lookup_table = {}
|
||||||
|
local function _copy(object)
|
||||||
|
if type(object) ~= "table" then
|
||||||
|
return object
|
||||||
|
elseif lookup_table[object] then
|
||||||
|
return lookup_table[object]
|
||||||
|
end
|
||||||
|
local new_table = {}
|
||||||
|
lookup_table[object] = new_table
|
||||||
|
for index, value in pairs(object) do
|
||||||
|
new_table[_copy(index)] = _copy(value)
|
||||||
|
end
|
||||||
|
return setmetatable(new_table, getmetatable(object))
|
||||||
|
end
|
||||||
|
return _copy(object)
|
||||||
|
end
|
||||||
|
|
||||||
--- start
|
--- start
|
||||||
main(args)
|
main(args)
|
Loading…
Add table
Add a link
Reference in a new issue