lua: fix mix of spaces & tabs
This commit is contained in:
@@ -9,14 +9,14 @@ desc =
|
|||||||
This is a script to allow raw 1444a commands to be sent and received.
|
This is a script to allow raw 1444a commands to be sent and received.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-o do not connect - use this only if you previously used -p to stay connected
|
-o do not connect - use this only if you previously used -p to stay connected
|
||||||
-r do not read response
|
-r do not read response
|
||||||
-c calculate and append CRC
|
-c calculate and append CRC
|
||||||
-p stay connected - dont inactivate the field
|
-p stay connected - dont inactivate the field
|
||||||
-x <payload> Data to send (NO SPACES!)
|
-x <payload> Data to send (NO SPACES!)
|
||||||
-d Debug flag
|
-d Debug flag
|
||||||
-t Topaz mode
|
-t Topaz mode
|
||||||
-3 ISO14443-4 (use RATS)
|
-3 ISO14443-4 (use RATS)
|
||||||
|
|
||||||
Examples :
|
Examples :
|
||||||
|
|
||||||
@@ -51,73 +51,73 @@ local DEBUG = false -- the debug flag
|
|||||||
---
|
---
|
||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
local function dbg(args)
|
local function dbg(args)
|
||||||
if DEBUG then
|
if DEBUG then
|
||||||
print("###", args)
|
print("###", args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- The main entry point
|
-- The main entry point
|
||||||
function main(args)
|
function main(args)
|
||||||
|
|
||||||
if args == nil or #args == 0 then return help() end
|
if args == nil or #args == 0 then return help() end
|
||||||
|
|
||||||
local ignore_response = false
|
local ignore_response = false
|
||||||
local append_crc = false
|
local append_crc = false
|
||||||
local stayconnected = false
|
local stayconnected = false
|
||||||
local payload = nil
|
local payload = nil
|
||||||
local doconnect = true
|
local doconnect = true
|
||||||
local topaz_mode = false
|
local topaz_mode = false
|
||||||
local no_rats = false
|
local no_rats = false
|
||||||
|
|
||||||
-- Read the parameters
|
-- Read the parameters
|
||||||
for o, a in getopt.getopt(args, 'orcpx:dt3') do
|
for o, a in getopt.getopt(args, 'orcpx:dt3') do
|
||||||
if o == "o" then doconnect = false end
|
if o == "o" then doconnect = false end
|
||||||
if o == "r" then ignore_response = true end
|
if o == "r" then ignore_response = true end
|
||||||
if o == "c" then append_crc = true end
|
if o == "c" then append_crc = true end
|
||||||
if o == "p" then stayconnected = true end
|
if o == "p" then stayconnected = true end
|
||||||
if o == "x" then payload = a end
|
if o == "x" then payload = a end
|
||||||
if o == "d" then DEBUG = true end
|
if o == "d" then DEBUG = true end
|
||||||
if o == "t" then topaz_mode = true end
|
if o == "t" then topaz_mode = true end
|
||||||
if o == "3" then no_rats = true end
|
if o == "3" then no_rats = true end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- First of all, connect
|
-- First of all, connect
|
||||||
if doconnect then
|
if doconnect then
|
||||||
dbg("doconnect")
|
dbg("doconnect")
|
||||||
-- We reuse the connect functionality from a
|
-- We reuse the connect functionality from a
|
||||||
-- common library
|
-- common library
|
||||||
info, err = lib14a.read(true, no_rats)
|
info, err = lib14a.read(true, no_rats)
|
||||||
|
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
print(("Connected to card, uid = %s"):format(info.uid))
|
print(("Connected to card, uid = %s"):format(info.uid))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- The actual raw payload, if any
|
-- The actual raw payload, if any
|
||||||
if payload then
|
if payload then
|
||||||
res,err = sendRaw(payload,{ignore_response = ignore_response, topaz_mode = topaz_mode, append_crc = append_crc})
|
res,err = sendRaw(payload,{ignore_response = ignore_response, topaz_mode = topaz_mode, append_crc = append_crc})
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
|
|
||||||
if not ignoreresponse then
|
if not ignoreresponse then
|
||||||
-- Display the returned data
|
-- Display the returned data
|
||||||
showdata(res)
|
showdata(res)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- And, perhaps disconnect?
|
-- And, perhaps disconnect?
|
||||||
if not stayconnected then
|
if not stayconnected then
|
||||||
disconnect()
|
disconnect()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Picks out and displays the data read from a tag
|
--- Picks out and displays the data read from a tag
|
||||||
@@ -127,61 +127,61 @@ end
|
|||||||
-- and displays the data
|
-- and displays the data
|
||||||
-- @param usbpacket the data received from the device
|
-- @param usbpacket the data received from the device
|
||||||
function showdata(usbpacket)
|
function showdata(usbpacket)
|
||||||
local cmd_response = Command.parse(usbpacket)
|
local cmd_response = Command.parse(usbpacket)
|
||||||
local len = tonumber(cmd_response.arg1) *2
|
local len = tonumber(cmd_response.arg1) *2
|
||||||
--print("data length:",len)
|
--print("data length:",len)
|
||||||
local data = string.sub(tostring(cmd_response.data), 0, len);
|
local data = string.sub(tostring(cmd_response.data), 0, len);
|
||||||
print("<< ",data)
|
print("<< ",data)
|
||||||
--print("----------------")
|
--print("----------------")
|
||||||
end
|
end
|
||||||
|
|
||||||
function sendRaw(rawdata, options)
|
function sendRaw(rawdata, options)
|
||||||
print(">> ", rawdata)
|
print(">> ", rawdata)
|
||||||
|
|
||||||
local flags = lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT + lib14a.ISO14A_COMMAND.ISO14A_RAW
|
local flags = lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT + lib14a.ISO14A_COMMAND.ISO14A_RAW
|
||||||
|
|
||||||
if options.topaz_mode then
|
if options.topaz_mode then
|
||||||
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_TOPAZMODE
|
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_TOPAZMODE
|
||||||
end
|
end
|
||||||
if options.append_crc then
|
if options.append_crc then
|
||||||
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC
|
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC
|
||||||
end
|
end
|
||||||
|
|
||||||
local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a,
|
local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a,
|
||||||
arg1 = flags, -- Send raw
|
arg1 = flags, -- Send raw
|
||||||
-- arg2 contains the length, which is half the length
|
-- arg2 contains the length, which is half the length
|
||||||
-- of the ASCII-string rawdata
|
-- of the ASCII-string rawdata
|
||||||
arg2 = string.len(rawdata)/2,
|
arg2 = string.len(rawdata)/2,
|
||||||
data = rawdata}
|
data = rawdata}
|
||||||
return lib14a.sendToDevice(command, options.ignore_response)
|
return lib14a.sendToDevice(command, options.ignore_response)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Sends an instruction to do nothing, only disconnect
|
-- Sends an instruction to do nothing, only disconnect
|
||||||
function disconnect()
|
function disconnect()
|
||||||
local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, arg1 = 0, }
|
local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, arg1 = 0,}
|
||||||
-- We can ignore the response here, no ACK is returned for this command
|
-- We can ignore the response here, no ACK is returned for this command
|
||||||
-- Check /armsrc/iso14443a.c, ReaderIso14443a() for details
|
-- Check /armsrc/iso14443a.c, ReaderIso14443a() for details
|
||||||
return lib14a.sendToDevice(command,true)
|
return lib14a.sendToDevice(command,true)
|
||||||
end
|
end
|
||||||
|
|
||||||
-------------------------
|
-------------------------
|
||||||
-- Testing
|
-- Testing
|
||||||
-------------------------
|
-------------------------
|
||||||
function selftest()
|
function selftest()
|
||||||
DEBUG = true
|
DEBUG = true
|
||||||
dbg("Performing test")
|
dbg("Performing test")
|
||||||
main()
|
main()
|
||||||
main("-p")
|
main("-p")
|
||||||
main(" -o -x 6000F57b -p")
|
main(" -o -x 6000F57b -p")
|
||||||
main("-o")
|
main("-o")
|
||||||
main("-x 6000F57b")
|
main("-x 6000F57b")
|
||||||
dbg("Tests done")
|
dbg("Tests done")
|
||||||
end
|
end
|
||||||
-- Flip the switch here to perform a sanity check.
|
-- Flip the switch here to perform a sanity check.
|
||||||
-- It read a nonce in two different ways, as specified in the usage-section
|
-- It read a nonce in two different ways, as specified in the usage-section
|
||||||
if "--test"==args then
|
if "--test"==args then
|
||||||
selftest()
|
selftest()
|
||||||
else
|
else
|
||||||
-- Call the main
|
-- Call the main
|
||||||
main(args)
|
main(args)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,87 +1,87 @@
|
|||||||
--[[
|
--[[
|
||||||
script to create a clone-dump with new crc
|
script to create a clone-dump with new crc
|
||||||
Author: mosci
|
Author: mosci
|
||||||
my Fork: https://github.com/icsom/proxmark3.git
|
my Fork: https://github.com/icsom/proxmark3.git
|
||||||
Upstream: https://github.com/Proxmark/proxmark3.git
|
Upstream: https://github.com/Proxmark/proxmark3.git
|
||||||
|
|
||||||
1. read tag-dump, xor byte 22..end with byte 0x05 of the inputfile
|
1. read tag-dump, xor byte 22..end with byte 0x05 of the inputfile
|
||||||
2. write to outfile
|
2. write to outfile
|
||||||
3. set byte 0x05 to newcrc
|
3. set byte 0x05 to newcrc
|
||||||
4. until byte 0x21 plain like in inputfile
|
4. until byte 0x21 plain like in inputfile
|
||||||
5. from 0x22..end xored with newcrc
|
5. from 0x22..end xored with newcrc
|
||||||
6. calculate new crc on each segment (needs to know the new MCD & MSN0..2)
|
6. calculate new crc on each segment (needs to know the new MCD & MSN0..2)
|
||||||
|
|
||||||
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 save orig.hex'
|
save the dump with 'hf legic save orig.hex'
|
||||||
place your 'empty' tag on the reader and run 'script run Legic_clone -i orig.hex -w'
|
place your 'empty' tag on the reader and run 'script run Legic_clone -i orig.hex -w'
|
||||||
you will see some output like:
|
you will see some output like:
|
||||||
read 1024 bytes from legic_dumps/j_0000.hex
|
read 1024 bytes from legic_dumps/j_0000.hex
|
||||||
|
|
||||||
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 whnen ready [y/n] ?y
|
confirm whnen ready [y/n] ?y
|
||||||
#db# setting up legic card
|
#db# setting up legic card
|
||||||
#db# MIM 256 card found, reading card ...
|
#db# MIM 256 card found, reading card ...
|
||||||
#db# Card read, use 'hf legic decode' or
|
#db# Card read, use 'hf legic decode' or
|
||||||
#db# 'data hexsamples 8' to view results
|
#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
|
||||||
type in MSN0 as 2-digit value - e.g.: 01 (default: 28 )
|
type in MSN0 as 2-digit value - e.g.: 01 (default: 28 )
|
||||||
> ad
|
> ad
|
||||||
type in MSN1 as 2-digit value - e.g.: 02 (default: d1 )
|
type in MSN1 as 2-digit value - e.g.: 02 (default: d1 )
|
||||||
> c0
|
> c0
|
||||||
type in MSN2 as 2-digit value - e.g.: 03 (default: 43 )
|
type in MSN2 as 2-digit value - e.g.: 03 (default: 43 )
|
||||||
> de
|
> de
|
||||||
MCD:0b, MSN:ad c0 de, MCC:79 <- this crc is calculated from the MCD & MSN and must match the one on yout empty tag
|
MCD:0b, 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
|
wrote 1024 bytes to myLegicClone.hex
|
||||||
enter number of bytes to write? (default: 86 )
|
enter number of bytes to write? (default: 86 )
|
||||||
|
|
||||||
loaded 1024 samples
|
loaded 1024 samples
|
||||||
#db# setting up legic card
|
#db# setting up legic card
|
||||||
#db# MIM 256 card found, writing 0x00 - 0x01 ...
|
#db# MIM 256 card found, writing 0x00 - 0x01 ...
|
||||||
#db# write successful
|
#db# write successful
|
||||||
...
|
...
|
||||||
#db# setting up legic card
|
#db# setting up legic card
|
||||||
#db# MIM 256 card found, writing 0x56 - 0x01 ...
|
#db# MIM 256 card found, writing 0x56 - 0x01 ...
|
||||||
#db# write successful
|
#db# write successful
|
||||||
proxmark3>
|
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
|
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)
|
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
|
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
|
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)
|
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'
|
(example) Legic-Prime Layout with 'Kaba Group Header'
|
||||||
+----+----+----+----+----+----+----+----+
|
+----+----+----+----+----+----+----+----+
|
||||||
0x00|MCD |MSN0|MSN1|MSN2|MCC | 60 | ea | 9f |
|
0x00|MCD |MSN0|MSN1|MSN2|MCC | 60 | ea | 9f |
|
||||||
+----+----+----+----+----+----+----+----+
|
+----+----+----+----+----+----+----+----+
|
||||||
0x08| ff | 00 | 00 | 00 | 11 |Bck0|Bck1|Bck2|
|
0x08| ff | 00 | 00 | 00 | 11 |Bck0|Bck1|Bck2|
|
||||||
+----+----+----+----+----+----+----+----+
|
+----+----+----+----+----+----+----+----+
|
||||||
0x10|Bck3|Bck4|Bck5|BCC | 00 | 00 |Seg0|Seg1|
|
0x10|Bck3|Bck4|Bck5|BCC | 00 | 00 |Seg0|Seg1|
|
||||||
+----+----+----+----+----+----+----+----+
|
+----+----+----+----+----+----+----+----+
|
||||||
0x18|Seg2|Seg3|SegC|Stp0|Stp1|Stp2|Stp3|UID0|
|
0x18|Seg2|Seg3|SegC|Stp0|Stp1|Stp2|Stp3|UID0|
|
||||||
+----+----+----+----+----+----+----+----+
|
+----+----+----+----+----+----+----+----+
|
||||||
0x20|UID1|UID2|kghC|
|
0x20|UID1|UID2|kghC|
|
||||||
+----+----+----+
|
+----+----+----+
|
||||||
|
|
||||||
MCD= ManufacturerID (1 Byte)
|
MCD= ManufacturerID (1 Byte)
|
||||||
MSN0..2= ManufactureSerialNumber (3 Byte)
|
MSN0..2= ManufactureSerialNumber (3 Byte)
|
||||||
MCC= CRC (1 Byte) calculated over MCD,MSN0..2
|
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
|
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
|
Bck0..5= Backup (6 Byte) Bck0 'dirty-flag', Bck1..5 SegmentHeader-Backup
|
||||||
BCC= BackupCRC (1 Byte) CRC calculated over Bck1..5
|
BCC= BackupCRC (1 Byte) CRC calculated over Bck1..5
|
||||||
Seg0..3= SegmentHeader (on MIM 4 Byte )
|
Seg0..3= SegmentHeader (on MIM 4 Byte )
|
||||||
SegC= SegmentCRC (1 Byte) calculated over MCD,MSN0..2,Seg0..3
|
SegC= SegmentCRC (1 Byte) calculated over MCD,MSN0..2,Seg0..3
|
||||||
Stp0..n= Stamp0... (variable length) length = Segment-Len - UserData - 1
|
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
|
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)
|
kghC= KabaGroupHeader (1 Byte + addr 0x0c must be 0x11)
|
||||||
as seen on ths example: addr 0x05..0x08 & 0x0c must have been set to this values - otherwise kghCRC will not be created by a official reader (not accepted)
|
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"
|
example = "Script create a clone-dump of a dump from a Legic Prime Tag"
|
||||||
@@ -91,22 +91,22 @@ desc =
|
|||||||
This is a script which create a clone-dump of a dump from a Legic Prime Tag (MIM256 or MIM1024)
|
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')
|
(created with 'hf legic save my_dump.hex')
|
||||||
requiered arguments:
|
requiered arguments:
|
||||||
-i <input file> (file to read data from)
|
-i <input file> (file to read data from)
|
||||||
|
|
||||||
optional arguments :
|
optional arguments :
|
||||||
-h - Help text
|
-h - Help text
|
||||||
-o <output file> - requieres option -c to be given
|
-o <output file> - requieres option -c to be given
|
||||||
-c <new-tag crc> - requieres option -o to be given
|
-c <new-tag crc> - requieres 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.hex wille be generated also
|
-w - write directly to Tag - a file myLegicClone.hex wille be generated also
|
||||||
|
|
||||||
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 )
|
||||||
|
|
||||||
Examples :
|
Examples :
|
||||||
script run legic_clone -i my_dump.hex -o my_clone.hex -c f8
|
script run legic_clone -i my_dump.hex -o my_clone.hex -c f8
|
||||||
script run legic_clone -i my_dump.hex -d -s
|
script run legic_clone -i my_dump.hex -d -s
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local utils = require('utils')
|
local utils = require('utils')
|
||||||
@@ -115,27 +115,27 @@ local bxor = bit32.bxor
|
|||||||
|
|
||||||
-- we need always 2 digits
|
-- we need always 2 digits
|
||||||
function prepend_zero(s)
|
function prepend_zero(s)
|
||||||
if (string.len(s)==1) then return "0" .. s
|
if (string.len(s)==1) then return "0" .. s
|
||||||
else
|
else
|
||||||
if (string.len(s)==0) then return "00"
|
if (string.len(s)==0) then return "00"
|
||||||
else return s
|
else return s
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
-- 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)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
return nil, err
|
return nil, err
|
||||||
end
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
function help()
|
function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check availability of file
|
-- Check availability of file
|
||||||
@@ -152,113 +152,113 @@ 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)
|
||||||
function xorme(hex, xor, index)
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
-- read input-file into array
|
-- read input-file into array
|
||||||
function getInputBytes(infile)
|
function getInputBytes(infile)
|
||||||
local line
|
local line
|
||||||
local bytes = {}
|
local bytes = {}
|
||||||
|
|
||||||
local fhi,err = io.open(infile)
|
local fhi,err = io.open(infile)
|
||||||
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
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
line = fhi:read()
|
line = fhi:read()
|
||||||
if line == nil then break end
|
if line == nil then break end
|
||||||
|
|
||||||
for byte in line:gmatch("%w+") do
|
for byte in line:gmatch("%w+") do
|
||||||
table.insert(bytes, byte)
|
table.insert(bytes, byte)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
fhi:close()
|
fhi:close()
|
||||||
|
|
||||||
print("\nread ".. #bytes .." bytes from ".. infile)
|
print("\nread ".. #bytes .." bytes from ".. infile)
|
||||||
return bytes
|
return bytes
|
||||||
end
|
end
|
||||||
|
|
||||||
-- write to file
|
-- write to file
|
||||||
function writeOutputBytes(bytes, outfile)
|
function writeOutputBytes(bytes, outfile)
|
||||||
local line
|
local line
|
||||||
local bcnt=0
|
local bcnt=0
|
||||||
local fho,err = io.open(outfile,"w")
|
local fho,err = io.open(outfile,"w")
|
||||||
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
|
||||||
if (bcnt == 0) then
|
if (bcnt == 0) then
|
||||||
line=bytes[i]
|
line=bytes[i]
|
||||||
elseif (bcnt <= 7) then
|
elseif (bcnt <= 7) then
|
||||||
line=line.." "..bytes[i]
|
line=line.." "..bytes[i]
|
||||||
end
|
end
|
||||||
if (bcnt == 7) then
|
if (bcnt == 7) then
|
||||||
-- write line to new file
|
-- write line to new file
|
||||||
fho:write(line.."\n")
|
fho:write(line.."\n")
|
||||||
-- reset counter & line
|
-- reset counter & line
|
||||||
bcnt=-1
|
bcnt=-1
|
||||||
line=""
|
line=""
|
||||||
end
|
end
|
||||||
bcnt=bcnt+1
|
bcnt=bcnt+1
|
||||||
end
|
end
|
||||||
fho:close()
|
fho:close()
|
||||||
print("\nwrote ".. #bytes .." bytes to " .. outfile)
|
print("\nwrote ".. #bytes .." bytes to " .. outfile)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- xore certain bytes
|
-- xore certain bytes
|
||||||
function xorBytes(inBytes, crc)
|
function xorBytes(inBytes, crc)
|
||||||
local bytes = {}
|
local bytes = {}
|
||||||
for index = 1, #inBytes do
|
for index = 1, #inBytes do
|
||||||
bytes[index] = xorme(inBytes[index], crc, index)
|
bytes[index] = xorme(inBytes[index], crc, index)
|
||||||
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")
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- get raw segment-data
|
-- get raw segment-data
|
||||||
function getSegmentData(bytes, start, index)
|
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
|
||||||
|
|
||||||
@@ -294,109 +294,109 @@ 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)
|
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
|
||||||
until (seg[3] == 1 or tonumber(seg[9]) == 126 )
|
until (seg[3] == 1 or tonumber(seg[9]) == 126 )
|
||||||
crcbytes[index] = start
|
crcbytes[index] = start
|
||||||
return crcbytes
|
return crcbytes
|
||||||
end
|
end
|
||||||
|
|
||||||
-- print segment-data (hf legic decode like)
|
-- print segment-data (hf legic decode like)
|
||||||
function displaySegments(bytes)
|
function displaySegments(bytes)
|
||||||
--display segment header(s)
|
--display segment header(s)
|
||||||
start=23
|
start=23
|
||||||
index="00"
|
index="00"
|
||||||
|
|
||||||
--repeat until last-flag ist set to 1 or segment-index has reached 126
|
--repeat until last-flag ist set to 1 or segment-index has reached 126
|
||||||
repeat
|
repeat
|
||||||
wrc=""
|
wrc=""
|
||||||
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
|
||||||
|
|
||||||
-- 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 print("'Kaba Group Header' detected"); end
|
if (KGH) then print("'Kaba Group Header' detected"); 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)
|
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].."), "
|
||||||
res = res.. "len="..("%04d"):format(SegmentData[4])..", "
|
res = res.. "len="..("%04d"):format(SegmentData[4])..", "
|
||||||
res = res.. "WRP="..prepend_zero(SegmentData[5])..", "
|
res = res.. "WRP="..prepend_zero(SegmentData[5])..", "
|
||||||
res = res.. "WRC="..prepend_zero(SegmentData[6])..", "
|
res = res.. "WRC="..prepend_zero(SegmentData[6])..", "
|
||||||
res = res.. "RD="..SegmentData[7]..", "
|
res = res.. "RD="..SegmentData[7]..", "
|
||||||
res = res.. "crc="..SegmentData[8]
|
res = res.. "crc="..SegmentData[8]
|
||||||
print(res)
|
print(res)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- write clone-data to tag
|
-- write clone-data to tag
|
||||||
function writeToTag(plainBytes)
|
function writeToTag(plainBytes)
|
||||||
local SegCrcs = {}
|
local SegCrcs = {}
|
||||||
if(utils.confirm("\nplace your empty tag onto the PM3 to read and display the MCD & MSN0..2\nthe values will be shown below\n confirm when ready") == false) then
|
if(utils.confirm("\nplace your empty tag onto the PM3 to read and display the MCD & MSN0..2\nthe values will be shown below\n confirm when ready") == false) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- gather MCD & MSN from new Tag - this must be enterd manually
|
-- gather MCD & MSN from new Tag - this must be enterd manually
|
||||||
cmd = 'hf legic read 0x00 0x04'
|
cmd = 'hf legic read 0x00 0x04'
|
||||||
core.console(cmd)
|
core.console(cmd)
|
||||||
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:")
|
||||||
cmd = 'data hexsamples 4'
|
cmd = 'data hexsamples 4'
|
||||||
core.console(cmd)
|
core.console(cmd)
|
||||||
print("^^ use this values as input for the following answers (one 2-digit-value per question/answer):")
|
print("^^ use this values as input for the following answers (one 2-digit-value per question/answer):")
|
||||||
-- enter MCD & MSN (in hex)
|
-- enter MCD & MSN (in hex)
|
||||||
MCD = utils.input("type in MCD as 2-digit value - e.g.: 00", plainBytes[1])
|
MCD = utils.input("type in MCD as 2-digit value - e.g.: 00", plainBytes[1])
|
||||||
MSN0 = utils.input("type in MSN0 as 2-digit value - e.g.: 01", plainBytes[2])
|
MSN0 = utils.input("type in MSN0 as 2-digit value - e.g.: 01", plainBytes[2])
|
||||||
MSN1 = utils.input("type in MSN1 as 2-digit value - e.g.: 02", plainBytes[3])
|
MSN1 = utils.input("type in MSN1 as 2-digit value - e.g.: 02", plainBytes[3])
|
||||||
MSN2 = utils.input("type in MSN2 as 2-digit value - e.g.: 03", plainBytes[4])
|
MSN2 = utils.input("type in MSN2 as 2-digit value - e.g.: 03", plainBytes[4])
|
||||||
|
|
||||||
-- 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:"..MCD..", MSN:"..MSN0.." "..MSN1.." "..MSN2..", 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)
|
||||||
@@ -405,136 +405,136 @@ function writeToTag(plainBytes)
|
|||||||
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
|
||||||
|
|
||||||
-- apply MCD & MSN to plain data
|
-- apply MCD & MSN to plain data
|
||||||
plainBytes[1] = MCD
|
plainBytes[1] = MCD
|
||||||
plainBytes[2] = MSN0
|
plainBytes[2] = MSN0
|
||||||
plainBytes[3] = MSN1
|
plainBytes[3] = MSN1
|
||||||
plainBytes[4] = MSN2
|
plainBytes[4] = MSN2
|
||||||
plainBytes[5] = MCC
|
plainBytes[5] = MCC
|
||||||
|
|
||||||
-- prepare plainBytes for writing (xor plain data with new MCC)
|
-- prepare plainBytes for writing (xor plain data with new MCC)
|
||||||
bytes = xorBytes(plainBytes, MCC)
|
bytes = xorBytes(plainBytes, MCC)
|
||||||
|
|
||||||
-- write data to file
|
-- write data to file
|
||||||
if (writeOutputBytes(bytes, "myLegicClone.hex")) then
|
if (writeOutputBytes(bytes, "myLegicClone.hex")) then
|
||||||
WriteBytes = utils.input("enter number of bytes to write?", SegCrcs[#SegCrcs])
|
WriteBytes = utils.input("enter number of bytes to write?", SegCrcs[#SegCrcs])
|
||||||
|
|
||||||
-- load file into pm3-buffer
|
-- load file into pm3-buffer
|
||||||
cmd = 'hf legic load myLegicClone.hex'
|
cmd = 'hf legic load myLegicClone.hex'
|
||||||
core.console(cmd)
|
core.console(cmd)
|
||||||
|
|
||||||
-- write pm3-buffer to Tag
|
-- write pm3-buffer to Tag
|
||||||
for i=0, WriteBytes do
|
for i=0, WriteBytes do
|
||||||
if ( i<5 or i>6) then
|
if ( i<5 or i>6) then
|
||||||
cmd = ('hf legic write 0x%02x 0x01'):format(i)
|
cmd = ('hf legic write 0x%02x 0x01'):format(i)
|
||||||
core.console(cmd)
|
core.console(cmd)
|
||||||
elseif (i == 6) then
|
elseif (i == 6) then
|
||||||
-- write DCF in reverse order (requires 'mosci-patch')
|
-- write DCF in reverse order (requires 'mosci-patch')
|
||||||
cmd = 'hf legic write 0x05 0x02'
|
cmd = 'hf legic write 0x05 0x02'
|
||||||
core.console(cmd)
|
core.console(cmd)
|
||||||
else
|
else
|
||||||
print("skipping byte 0x05 - will be written next step")
|
print("skipping byte 0x05 - will be written next step")
|
||||||
end
|
end
|
||||||
utils.Sleep(0.2)
|
utils.Sleep(0.2)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- main function
|
-- main function
|
||||||
function main(args)
|
function main(args)
|
||||||
-- some variables
|
-- some variables
|
||||||
local i=0
|
local i=0
|
||||||
local oldcrc, newcrc, infile, outfile
|
local oldcrc, newcrc, infile, outfile
|
||||||
local bytes = {}
|
local bytes = {}
|
||||||
local segments = {}
|
local segments = {}
|
||||||
|
|
||||||
-- parse arguments for the script
|
-- parse arguments for the script
|
||||||
for o, a in getopt.getopt(args, 'hwsdc:i:o:') do
|
for o, a in getopt.getopt(args, 'hwsdc:i:o:') do
|
||||||
-- output file
|
-- output file
|
||||||
if o == "o" then
|
if o == "o" then
|
||||||
outfile = a
|
outfile = a
|
||||||
ofs = true
|
ofs = true
|
||||||
if (file_check(a)) then
|
if (file_check(a)) then
|
||||||
local answer = utils.confirm("\nthe output-file "..a.." alredy exists!\nthis will delete the previous content!\ncontinue?")
|
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
|
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")
|
return oops("input file: "..infile.." not found")
|
||||||
else
|
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
|
end
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
-- new crc
|
-- new crc
|
||||||
if o == "c" then
|
if o == "c" then
|
||||||
newcrc = a
|
newcrc = a
|
||||||
ncs = true
|
ncs = true
|
||||||
end
|
end
|
||||||
-- display segments switch
|
-- display segments switch
|
||||||
if o == "d" then ds = true; end
|
if o == "d" then ds = true; end
|
||||||
-- display summary switch
|
-- display summary switch
|
||||||
if o == "s" then ss = true; end
|
if o == "s" then ss = true; end
|
||||||
-- write to tag switch
|
-- write to tag switch
|
||||||
if o == "w" then ws = true; end
|
if o == "w" then ws = true; end
|
||||||
-- help
|
-- help
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
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 to plain
|
||||||
bytes = xorBytes(bytes, oldcrc)
|
bytes = xorBytes(bytes, oldcrc)
|
||||||
|
|
||||||
-- show segments (works only on plain bytes)
|
-- show segments (works only on plain bytes)
|
||||||
if (ds) then
|
if (ds) then
|
||||||
print("+------------------------------------------- Segments -------------------------------------------+")
|
print("+------------------------------------------- Segments -------------------------------------------+")
|
||||||
displaySegments(bytes);
|
displaySegments(bytes);
|
||||||
end
|
end
|
||||||
|
|
||||||
if (ofs and ncs) then
|
if (ofs and ncs) then
|
||||||
-- xor bytes with new crc
|
-- xor bytes with new crc
|
||||||
newBytes = xorBytes(bytes, newcrc)
|
newBytes = xorBytes(bytes, newcrc)
|
||||||
-- write output
|
-- write output
|
||||||
if (writeOutputBytes(newBytes, outfile)) then
|
if (writeOutputBytes(newBytes, outfile)) then
|
||||||
-- show summary if requested
|
-- show summary if requested
|
||||||
if (ss) then
|
if (ss) then
|
||||||
-- 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 load "..outfile
|
res = res .."\nyou may load the new file with: hf legic load "..outfile
|
||||||
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 crc8 "..bytes[1]..bytes[2]..bytes[3]..bytes[4]..bytes[23]..bytes[24]..bytes[25]..bytes[26]
|
res = res .."\nhf legic crc8 "..bytes[1]..bytes[2]..bytes[3]..bytes[4]..bytes[23]..bytes[24]..bytes[25]..bytes[26]
|
||||||
-- 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
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if (ss) then
|
if (ss) then
|
||||||
-- show why the output-file was not written
|
-- show why the output-file was not written
|
||||||
print("\nnew file not written - some arguments are missing ..")
|
print("\nnew file not written - some arguments are missing ..")
|
||||||
print("output file: ".. (ofs and outfile or "not given"))
|
print("output file: ".. (ofs and outfile or "not given"))
|
||||||
print("new crc: ".. (ncs and newcrc or "not given"))
|
print("new crc: ".. (ncs and newcrc or "not given"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- write to tag
|
-- write to tag
|
||||||
if (ws and #bytes == 1024) then
|
if (ws and #bytes == 1024) then
|
||||||
writeToTag(bytes)
|
writeToTag(bytes)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- call main with arguments
|
-- call main with arguments
|
||||||
|
|||||||
@@ -88,10 +88,10 @@ local function emulate_amiibo (amiibo_data)
|
|||||||
local simCmd = Command:new{cmd = cmds.CMD_SIMULATE_TAG_ISO_14443a, arg1 = 7, arg2 = uid_first, arg3 = uid_second}
|
local simCmd = Command:new{cmd = cmds.CMD_SIMULATE_TAG_ISO_14443a, arg1 = 7, arg2 = uid_first, arg3 = uid_second}
|
||||||
local _, err = reader.sendToDevice(simCmd)
|
local _, err = reader.sendToDevice(simCmd)
|
||||||
if err then
|
if err then
|
||||||
print('Failed to start simulator', err)
|
print('Failed to start simulator', err)
|
||||||
return
|
return
|
||||||
else
|
else
|
||||||
print('Starting simulator')
|
print('Starting simulator')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ usage = [[
|
|||||||
script run brutesim -r rfid_tag -f facility_code -b base_card_number -c count -t timeout -d direction
|
script run brutesim -r rfid_tag -f facility_code -b base_card_number -c count -t timeout -d direction
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h this help
|
-h this help
|
||||||
-r *see below RFID Tag: the RFID tag to emulate
|
-r *see below RFID Tag: the RFID tag to emulate
|
||||||
pyramid
|
pyramid
|
||||||
awid
|
awid
|
||||||
fdx
|
fdx
|
||||||
@@ -50,11 +50,11 @@ Arguments:
|
|||||||
14a
|
14a
|
||||||
hid
|
hid
|
||||||
|
|
||||||
-f 0-999 facility code (dfx: country id, 14a: type)
|
-f 0-999 facility code (dfx: country id, 14a: type)
|
||||||
-b 0-65535 base card number to start from
|
-b 0-65535 base card number to start from
|
||||||
-c 1-65536 number of cards to try
|
-c 1-65536 number of cards to try
|
||||||
-t .0-99999, pause timeout between cards (use the word 'pause' to wait for user input)
|
-t .0-99999, pause timeout between cards (use the word 'pause' to wait for user input)
|
||||||
-d up, down direction to move through card numbers
|
-d up, down direction to move through card numbers
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local DEBUG = true
|
local DEBUG = true
|
||||||
@@ -65,236 +65,236 @@ local lshift = bit32.lshift
|
|||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
local function dbg(args)
|
local function dbg(args)
|
||||||
if type(args) == "table" then
|
if type(args) == "table" then
|
||||||
local i = 1
|
local i = 1
|
||||||
while args[i] do
|
while args[i] do
|
||||||
dbg(args[i])
|
dbg(args[i])
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print("###", args)
|
print("###", args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
return nil,err
|
return nil,err
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(copyright)
|
print(copyright)
|
||||||
print(author)
|
print(author)
|
||||||
print(version)
|
print(version)
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- Exit message
|
-- Exit message
|
||||||
function exitMsg(msg)
|
function exitMsg(msg)
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print(msg)
|
print(msg)
|
||||||
print()
|
print()
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- Check if a string is empty
|
-- Check if a string is empty
|
||||||
local function isempty(s)
|
local function isempty(s)
|
||||||
return s == nil or s == ''
|
return s == nil or s == ''
|
||||||
end
|
end
|
||||||
|
|
||||||
-- The code below was blatantly stolen from Brian Redbeard's lf_bulk_program.lua script
|
-- The code below was blatantly stolen from Brian Redbeard's lf_bulk_program.lua script
|
||||||
local function toBits(num, bits)
|
local function toBits(num, bits)
|
||||||
bits = bits or math.max(1, select(2, math.frexp(num)))
|
bits = bits or math.max(1, select(2, math.frexp(num)))
|
||||||
local t = {}
|
local t = {}
|
||||||
for b = bits, 1, -1 do
|
for b = bits, 1, -1 do
|
||||||
t[b] = math.fmod(num, 2)
|
t[b] = math.fmod(num, 2)
|
||||||
num = math.floor((num - t[b]) / 2)
|
num = math.floor((num - t[b]) / 2)
|
||||||
end
|
end
|
||||||
return table.concat(t)
|
return table.concat(t)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- check for parity in bit-string.
|
-- check for parity in bit-string.
|
||||||
local function evenparity(s)
|
local function evenparity(s)
|
||||||
local _, count = string.gsub(s, "1", "")
|
local _, count = string.gsub(s, "1", "")
|
||||||
local p = count % 2
|
local p = count % 2
|
||||||
if (p == 0) then
|
if (p == 0) then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- calcs hex for HID
|
-- calcs hex for HID
|
||||||
local function cardHex(i, f)
|
local function cardHex(i, f)
|
||||||
fac = lshift(f, 16)
|
fac = lshift(f, 16)
|
||||||
id = bor(i, fac)
|
id = bor(i, fac)
|
||||||
stream = toBits(id, 26)
|
stream = toBits(id, 26)
|
||||||
high = evenparity(string.sub(stream, 0, 12)) and 1 or 0
|
high = evenparity(string.sub(stream, 0, 12)) and 1 or 0
|
||||||
low = not evenparity(string.sub(stream, 13)) and 1 or 0
|
low = not evenparity(string.sub(stream, 13)) and 1 or 0
|
||||||
bits = bor(lshift(id, 1), low)
|
bits = bor(lshift(id, 1), low)
|
||||||
bits = bor(bits, lshift(high, 25))
|
bits = bor(bits, lshift(high, 25))
|
||||||
preamble = bor(0, lshift(1, 5))
|
preamble = bor(0, lshift(1, 5))
|
||||||
bits = bor(bits, lshift(1, 26))
|
bits = bor(bits, lshift(1, 26))
|
||||||
return ("%04x%08x"):format(preamble, bits)
|
return ("%04x%08x"):format(preamble, bits)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print()
|
print()
|
||||||
|
|
||||||
if #args == 0 then return help() end
|
if #args == 0 then return help() end
|
||||||
|
|
||||||
for o, a in getopt.getopt(args, 'r:f:b:c:t:d:h') do -- Populate command like arguments
|
for o, a in getopt.getopt(args, 'r:f:b:c:t:d:h') do -- Populate command like arguments
|
||||||
if o == 'r' then rfidtag = a end
|
if o == 'r' then rfidtag = a end
|
||||||
if o == 'f' then facility = a end
|
if o == 'f' then facility = a end
|
||||||
if o == 'b' then baseid = a end
|
if o == 'b' then baseid = a end
|
||||||
if o == 'c' then count = a end
|
if o == 'c' then count = a end
|
||||||
if o == 't' then timeout = a end
|
if o == 't' then timeout = a end
|
||||||
if o == 'd' then direction = a end
|
if o == 'd' then direction = a end
|
||||||
if o == 'h' then return print(usage) end
|
if o == 'h' then return print(usage) end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check to see if -r argument was passed
|
-- Check to see if -r argument was passed
|
||||||
if isempty(rfidtag) then
|
if isempty(rfidtag) then
|
||||||
print("You must supply the flag -r (rfid tag)")
|
print("You must supply the flag -r (rfid tag)")
|
||||||
print(usage)
|
print(usage)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check what RFID Tag we are using
|
-- Check what RFID Tag we are using
|
||||||
if rfidtag == 'pyramid' then
|
if rfidtag == 'pyramid' then
|
||||||
consolecommand = 'lf pyramid sim' -- set the console command
|
consolecommand = 'lf pyramid sim' -- set the console command
|
||||||
rfidtagname = 'Farpointe/Pyramid' -- set the display name
|
rfidtagname = 'Farpointe/Pyramid' -- set the display name
|
||||||
facilityrequired = 1 -- set if FC is required
|
facilityrequired = 1 -- set if FC is required
|
||||||
elseif rfidtag == 'awid' then
|
elseif rfidtag == 'awid' then
|
||||||
consolecommand = 'lf awid sim'
|
consolecommand = 'lf awid sim'
|
||||||
rfidtagname = 'AWID'
|
rfidtagname = 'AWID'
|
||||||
facilityrequired = 1
|
facilityrequired = 1
|
||||||
elseif rfidtag == 'fdx' then -- I'm not sure why you would need to bruteforce this ¯\_(ツ)_/¯
|
elseif rfidtag == 'fdx' then -- I'm not sure why you would need to bruteforce this ¯\_(ツ)_/¯
|
||||||
consolecommand = 'lf fdx sim'
|
consolecommand = 'lf fdx sim'
|
||||||
rfidtagname = 'FDX-B'
|
rfidtagname = 'FDX-B'
|
||||||
facilityrequired = 1
|
facilityrequired = 1
|
||||||
elseif rfidtag == 'jablotron' then
|
elseif rfidtag == 'jablotron' then
|
||||||
consolecommand = 'lf jablotron sim'
|
consolecommand = 'lf jablotron sim'
|
||||||
rfidtagname = 'Jablotron'
|
rfidtagname = 'Jablotron'
|
||||||
facilityrequired = 0
|
facilityrequired = 0
|
||||||
elseif rfidtag == 'noralsy' then
|
elseif rfidtag == 'noralsy' then
|
||||||
consolecommand = 'lf noralsy sim'
|
consolecommand = 'lf noralsy sim'
|
||||||
rfidtagname = 'Noralsy'
|
rfidtagname = 'Noralsy'
|
||||||
facilityrequired = 0
|
facilityrequired = 0
|
||||||
elseif rfidtag == 'presco' then
|
elseif rfidtag == 'presco' then
|
||||||
consolecommand = 'lf presco sim d'
|
consolecommand = 'lf presco sim d'
|
||||||
rfidtagname = 'Presco'
|
rfidtagname = 'Presco'
|
||||||
facilityrequired = 0
|
facilityrequired = 0
|
||||||
elseif rfidtag == 'visa2000' then
|
elseif rfidtag == 'visa2000' then
|
||||||
consolecommand = 'lf visa2000 sim'
|
consolecommand = 'lf visa2000 sim'
|
||||||
rfidtagname = 'Visa2000'
|
rfidtagname = 'Visa2000'
|
||||||
facilityrequired = 0
|
facilityrequired = 0
|
||||||
elseif rfidtag == '14a' then
|
elseif rfidtag == '14a' then
|
||||||
consolecommand = 'hf 14a sim'
|
consolecommand = 'hf 14a sim'
|
||||||
if facility == "1" then rfidtagname = 'MIFARE Classic' -- Here we use the -f option to read the 14a type instead of the facility code
|
if facility == "1" then rfidtagname = 'MIFARE Classic' -- Here we use the -f option to read the 14a type instead of the facility code
|
||||||
elseif facility == "2" then rfidtagname = 'MIFARE Ultralight'
|
elseif facility == "2" then rfidtagname = 'MIFARE Ultralight'
|
||||||
elseif facility == "3" then rfidtagname = 'MIFARE Desfire'
|
elseif facility == "3" then rfidtagname = 'MIFARE Desfire'
|
||||||
elseif facility == "4" then rfidtagname = 'ISO/IEC 14443-4'
|
elseif facility == "4" then rfidtagname = 'ISO/IEC 14443-4'
|
||||||
elseif facility == "5" then rfidtagname = 'MIFARE Tnp3xxx'
|
elseif facility == "5" then rfidtagname = 'MIFARE Tnp3xxx'
|
||||||
else
|
else
|
||||||
print("Invalid 14a type (-f) supplied. Must be 1-5")
|
print("Invalid 14a type (-f) supplied. Must be 1-5")
|
||||||
print(usage)
|
print(usage)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
facilityrequired = 0 -- Disable the FC required check, as we used it for type instead of FC
|
facilityrequired = 0 -- Disable the FC required check, as we used it for type instead of FC
|
||||||
elseif rfidtag == 'hid' then
|
elseif rfidtag == 'hid' then
|
||||||
consolecommand = 'lf hid sim'
|
consolecommand = 'lf hid sim'
|
||||||
rfidtagname = 'HID'
|
rfidtagname = 'HID'
|
||||||
facilityrequired = 1
|
facilityrequired = 1
|
||||||
else -- Display error and exit out if bad RFID tag was supplied
|
else -- Display error and exit out if bad RFID tag was supplied
|
||||||
print("Invalid rfid tag (-r) supplied")
|
print("Invalid rfid tag (-r) supplied")
|
||||||
print(usage)
|
print(usage)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if isempty(baseid) then -- Display error and exit out if no starting id is set
|
if isempty(baseid) then -- Display error and exit out if no starting id is set
|
||||||
print("You must supply the flag -b (base id)")
|
print("You must supply the flag -b (base id)")
|
||||||
print(usage)
|
print(usage)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if isempty(count) then -- Display error and exit out of no count is set
|
if isempty(count) then -- Display error and exit out of no count is set
|
||||||
print("You must supply the flag -c (count)")
|
print("You must supply the flag -c (count)")
|
||||||
print(usage)
|
print(usage)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if facilityrequired == 1 then -- If FC is required
|
if facilityrequired == 1 then -- If FC is required
|
||||||
facilitymessage = " - Facility Code: " -- Add FC to status message
|
facilitymessage = " - Facility Code: " -- Add FC to status message
|
||||||
if isempty(facility) then -- If FC was left blank, display warning and set FC to 0
|
if isempty(facility) then -- If FC was left blank, display warning and set FC to 0
|
||||||
print("Using 0 for the facility code as -f was not supplied")
|
print("Using 0 for the facility code as -f was not supplied")
|
||||||
facility = 0
|
facility = 0
|
||||||
end
|
end
|
||||||
else -- If FC is not required
|
else -- If FC is not required
|
||||||
facility = "" -- Clear FC
|
facility = "" -- Clear FC
|
||||||
facilitymessage = "" -- Remove FC from status message
|
facilitymessage = "" -- Remove FC from status message
|
||||||
end
|
end
|
||||||
|
|
||||||
if isempty(timeout) then -- If timeout was not supplied, show warning and set timeout to 0
|
if isempty(timeout) then -- If timeout was not supplied, show warning and set timeout to 0
|
||||||
print("Using 0 for the timeout as -t was not supplied")
|
print("Using 0 for the timeout as -t was not supplied")
|
||||||
timeout = 0
|
timeout = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
if isempty(direction) then -- If direction was not supplied, show warning and set direction to down
|
if isempty(direction) then -- If direction was not supplied, show warning and set direction to down
|
||||||
print("Using down for direction as -d was not supplied")
|
print("Using down for direction as -d was not supplied")
|
||||||
direction = 'down'
|
direction = 'down'
|
||||||
end
|
end
|
||||||
|
|
||||||
if tonumber(count) < 1 then
|
if tonumber(count) < 1 then
|
||||||
print("Count -c must be set to 1 or higher")
|
print("Count -c must be set to 1 or higher")
|
||||||
return
|
return
|
||||||
else
|
else
|
||||||
count = count -1 -- Make our count accurate by removing 1, because math
|
count = count -1 -- Make our count accurate by removing 1, because math
|
||||||
end
|
end
|
||||||
|
|
||||||
if direction == 'down' then -- If counting down, set up our for loop to count down
|
if direction == 'down' then -- If counting down, set up our for loop to count down
|
||||||
endid = baseid - count
|
endid = baseid - count
|
||||||
fordirection = -1
|
fordirection = -1
|
||||||
elseif direction == 'up' then -- If counting up, set our for loop to count up
|
elseif direction == 'up' then -- If counting up, set our for loop to count up
|
||||||
endid = baseid + count
|
endid = baseid + count
|
||||||
fordirection = 1
|
fordirection = 1
|
||||||
else -- If invalid direction was set, show warning and set up our for loop to count down
|
else -- If invalid direction was set, show warning and set up our for loop to count down
|
||||||
print("Invalid direction (-d) supplied, using down")
|
print("Invalid direction (-d) supplied, using down")
|
||||||
endid = baseid - count
|
endid = baseid - count
|
||||||
fordirection = -1
|
fordirection = -1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- display status message
|
-- display status message
|
||||||
print("")
|
print("")
|
||||||
print("BruteForcing "..rfidtagname..""..facilitymessage..""..facility.." - CardNumber Start: "..baseid.." - CardNumber End: "..endid.." - TimeOut: "..timeout)
|
print("BruteForcing "..rfidtagname..""..facilitymessage..""..facility.." - CardNumber Start: "..baseid.." - CardNumber End: "..endid.." - TimeOut: "..timeout)
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
-- loop through for each count (-c)
|
-- loop through for each count (-c)
|
||||||
for cardnum = baseid, endid, fordirection do
|
for cardnum = baseid, endid, fordirection do
|
||||||
|
|
||||||
-- If rfid tag is set to HID, convert card to HEX using the stolen code above
|
-- If rfid tag is set to HID, convert card to HEX using the stolen code above
|
||||||
if rfidtag == 'hid' then cardnum = cardHex(cardnum, facility) end
|
if rfidtag == 'hid' then cardnum = cardHex(cardnum, facility) end
|
||||||
|
|
||||||
-- send command to proxmark
|
-- send command to proxmark
|
||||||
core.console(consolecommand..' '..facility..' '..cardnum)
|
core.console(consolecommand..' '..facility..' '..cardnum)
|
||||||
|
|
||||||
if timeout == 'pause' then
|
if timeout == 'pause' then
|
||||||
print("Press enter to continue ...")
|
print("Press enter to continue ...")
|
||||||
io.read()
|
io.read()
|
||||||
else
|
else
|
||||||
os.execute("sleep "..timeout.."")
|
os.execute("sleep "..timeout.."")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ping the proxmark to stop emulation and see if its still responding
|
-- ping the proxmark to stop emulation and see if its still responding
|
||||||
core.console('hw ping')
|
core.console('hw ping')
|
||||||
end
|
end
|
||||||
|
|
||||||
main(args)
|
main(args)
|
||||||
@@ -11,18 +11,18 @@ This script calculates mifare keys based on uid diversification for DI.
|
|||||||
Algo not found by me.
|
Algo not found by me.
|
||||||
]]
|
]]
|
||||||
example = [[
|
example = [[
|
||||||
-- if called without, it reads tag uid
|
-- if called without, it reads tag uid
|
||||||
script run calc_di
|
script run calc_di
|
||||||
|
|
||||||
--
|
--
|
||||||
script run calc_di -u 11223344556677
|
script run calc_di -u 11223344556677
|
||||||
]]
|
]]
|
||||||
usage = [[
|
usage = [[
|
||||||
script run calc_di -h -u <uid>
|
script run calc_di -h -u <uid>
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h : this help
|
-h : this help
|
||||||
-u <UID> : UID
|
-u <UID> : UID
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local DEBUG = true
|
local DEBUG = true
|
||||||
@@ -34,143 +34,143 @@ local bxor = bit32.bxor
|
|||||||
local function dbg(args)
|
local function dbg(args)
|
||||||
if not DEBUG then return end
|
if not DEBUG then return end
|
||||||
if type(args) == "table" then
|
if type(args) == "table" then
|
||||||
local i = 1
|
local i = 1
|
||||||
while args[i] do
|
while args[i] do
|
||||||
dbg(args[i])
|
dbg(args[i])
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print("###", args)
|
print("###", args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
return nil,err
|
return nil,err
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(copyright)
|
print(copyright)
|
||||||
print(author)
|
print(author)
|
||||||
print(version)
|
print(version)
|
||||||
print(desc)
|
print(desc)
|
||||||
print('Example usage')
|
print('Example usage')
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Exit message
|
-- Exit message
|
||||||
local function exitMsg(msg)
|
local function exitMsg(msg)
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print(msg)
|
print(msg)
|
||||||
print()
|
print()
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- dumps all keys to file
|
-- dumps all keys to file
|
||||||
local function dumptofile(keys)
|
local function dumptofile(keys)
|
||||||
dbg('dumping keys to file')
|
dbg('dumping keys to file')
|
||||||
|
|
||||||
if utils.confirm('Do you wish to save the keys to dumpfile?') then
|
if utils.confirm('Do you wish to save the keys to dumpfile?') then
|
||||||
local destination = utils.input('Select a filename to store to', 'dumpkeys.bin')
|
local destination = utils.input('Select a filename to store to', 'dumpkeys.bin')
|
||||||
local file = io.open(destination, 'wb')
|
local file = io.open(destination, 'wb')
|
||||||
if file == nil then
|
if file == nil then
|
||||||
print('Could not write to file ', destination)
|
print('Could not write to file ', destination)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Mifare Mini has 5 sectors,
|
-- Mifare Mini has 5 sectors,
|
||||||
local key_a = ''
|
local key_a = ''
|
||||||
local key_b = ''
|
local key_b = ''
|
||||||
|
|
||||||
for sector = 0, #keys do
|
for sector = 0, #keys do
|
||||||
local keyA, keyB = unpack(keys[sector])
|
local keyA, keyB = unpack(keys[sector])
|
||||||
key_a = key_a .. bin.pack('H', keyA);
|
key_a = key_a .. bin.pack('H', keyA);
|
||||||
key_b = key_b .. bin.pack('H', keyB);
|
key_b = key_b .. bin.pack('H', keyB);
|
||||||
end
|
end
|
||||||
file:write(key_a)
|
file:write(key_a)
|
||||||
file:write(key_b)
|
file:write(key_b)
|
||||||
file:close()
|
file:close()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- create key
|
-- create key
|
||||||
local function keygen(uid)
|
local function keygen(uid)
|
||||||
local data = MIS..uid..BAR
|
local data = MIS..uid..BAR
|
||||||
local hash = utils.ConvertAsciiToBytes(utils.Sha1Hex(data))
|
local hash = utils.ConvertAsciiToBytes(utils.Sha1Hex(data))
|
||||||
return string.format("%02X%02X%02X%02X%02X%02X",
|
return string.format("%02X%02X%02X%02X%02X%02X",
|
||||||
hash[3+1],
|
hash[3+1],
|
||||||
hash[2+1],
|
hash[2+1],
|
||||||
hash[1+1],
|
hash[1+1],
|
||||||
hash[0+1],
|
hash[0+1],
|
||||||
hash[7+1],
|
hash[7+1],
|
||||||
hash[6+1]
|
hash[6+1]
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- print keys
|
-- print keys
|
||||||
local function printKeys(keys)
|
local function printKeys(keys)
|
||||||
print('|---|----------------|---|----------------|---|')
|
print('|---|----------------|---|----------------|---|')
|
||||||
print('|sec|key A |res|key B |res|')
|
print('|sec|key A |res|key B |res|')
|
||||||
print('|---|----------------|---|----------------|---|')
|
print('|---|----------------|---|----------------|---|')
|
||||||
for sector = 0, #keys do
|
for sector = 0, #keys do
|
||||||
local keyA, keyB = unpack(keys[sector])
|
local keyA, keyB = unpack(keys[sector])
|
||||||
print(('|%03d| %s | %s | %s | %s |'):format(sector, keyA, 1, keyB, 1))
|
print(('|%03d| %s | %s | %s | %s |'):format(sector, keyA, 1, keyB, 1))
|
||||||
end
|
end
|
||||||
print('|---|----------------|---|----------------|---|')
|
print('|---|----------------|---|----------------|---|')
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- createfull set of keys
|
-- createfull set of keys
|
||||||
local function createKeys(uid)
|
local function createKeys(uid)
|
||||||
local key = keygen(uid)
|
local key = keygen(uid)
|
||||||
local k = {}
|
local k = {}
|
||||||
for i = 0,4 do
|
for i = 0,4 do
|
||||||
k[i] = { key, key }
|
k[i] = { key, key }
|
||||||
end
|
end
|
||||||
return k
|
return k
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- main
|
-- main
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
print( string.rep('==', 30) )
|
print( string.rep('==', 30) )
|
||||||
print()
|
print()
|
||||||
|
|
||||||
local uid
|
local uid
|
||||||
local useUID = false
|
local useUID = false
|
||||||
|
|
||||||
-- Arguments for the script
|
-- Arguments for the script
|
||||||
for o, a in getopt.getopt(args, 'hu:') do
|
for o, a in getopt.getopt(args, 'hu:') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
if o == "u" then uid = a; useUID = true end
|
if o == "u" then uid = a; useUID = true end
|
||||||
end
|
end
|
||||||
|
|
||||||
if useUID then
|
if useUID then
|
||||||
-- uid string checks if supplied
|
-- uid string checks if supplied
|
||||||
if uid == nil then return oops('empty uid string') end
|
if uid == nil then return oops('empty uid string') end
|
||||||
if #uid == 0 then return oops('empty uid string') end
|
if #uid == 0 then return oops('empty uid string') end
|
||||||
if #uid ~= 14 then return oops('uid wrong length. Should be 7 hex bytes') end
|
if #uid ~= 14 then return oops('uid wrong length. Should be 7 hex bytes') end
|
||||||
else
|
else
|
||||||
-- GET TAG UID
|
-- GET TAG UID
|
||||||
local tag, err = lib14a.read(false, true)
|
local tag, err = lib14a.read(false, true)
|
||||||
if not tag then return oops(err) end
|
if not tag then return oops(err) end
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
-- simple tag check
|
-- simple tag check
|
||||||
if 0x09 ~= tag.sak then
|
if 0x09 ~= tag.sak then
|
||||||
if 0x4400 ~= tag.atqa then
|
if 0x4400 ~= tag.atqa then
|
||||||
return oops(('[fail] found tag %s :: looking for Mifare Mini 0.3k'):format(tag.name))
|
return oops(('[fail] found tag %s :: looking for Mifare Mini 0.3k'):format(tag.name))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
uid = tag.uid
|
uid = tag.uid
|
||||||
end
|
end
|
||||||
|
|
||||||
print('|UID|', uid)
|
print('|UID|', uid)
|
||||||
|
|
||||||
local keys, err = createKeys( uid )
|
local keys, err = createKeys( uid )
|
||||||
printKeys( keys )
|
printKeys( keys )
|
||||||
dumptofile( keys )
|
dumptofile( keys )
|
||||||
end
|
end
|
||||||
|
|
||||||
main(args)
|
main(args)
|
||||||
@@ -12,17 +12,17 @@ Algo not found by me.
|
|||||||
]]
|
]]
|
||||||
example =[[
|
example =[[
|
||||||
-- if called without, it reads tag uid
|
-- if called without, it reads tag uid
|
||||||
script run calc_ev1_it
|
script run calc_ev1_it
|
||||||
|
|
||||||
--
|
--
|
||||||
script run calc_ev1_it -u 11223344556677
|
script run calc_ev1_it -u 11223344556677
|
||||||
]]
|
]]
|
||||||
usage = [[
|
usage = [[
|
||||||
script run calc_ev1_it -h -u <uid> "
|
script run calc_ev1_it -h -u <uid> "
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h : this help
|
-h : this help
|
||||||
-u <UID> : UID
|
-u <UID> : UID
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local DEBUG = true
|
local DEBUG = true
|
||||||
@@ -30,149 +30,149 @@ local bxor = bit32.bxor
|
|||||||
---
|
---
|
||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
local function dbg(args)
|
local function dbg(args)
|
||||||
if not DEBUG then return end
|
if not DEBUG then return end
|
||||||
|
|
||||||
if type(args) == "table" then
|
if type(args) == "table" then
|
||||||
local i = 1
|
local i = 1
|
||||||
while args[i] do
|
while args[i] do
|
||||||
dbg(args[i])
|
dbg(args[i])
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print("###", args)
|
print("###", args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
return nil,err
|
return nil,err
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(copyright)
|
print(copyright)
|
||||||
print(author)
|
print(author)
|
||||||
print(version)
|
print(version)
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- Exit message
|
-- Exit message
|
||||||
function exitMsg(msg)
|
function exitMsg(msg)
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print(msg)
|
print(msg)
|
||||||
print()
|
print()
|
||||||
end
|
end
|
||||||
|
|
||||||
local _xortable = {
|
local _xortable = {
|
||||||
--[[ position, 4byte xor
|
--[[ position, 4byte xor
|
||||||
--]]
|
--]]
|
||||||
{"00","4f2711c1"},
|
{"00","4f2711c1"},
|
||||||
{"01","07D7BB83"},
|
{"01","07D7BB83"},
|
||||||
{"02","9636EF07"},
|
{"02","9636EF07"},
|
||||||
{"03","B5F4460E"},
|
{"03","B5F4460E"},
|
||||||
{"04","F271141C"},
|
{"04","F271141C"},
|
||||||
{"05","7D7BB038"},
|
{"05","7D7BB038"},
|
||||||
{"06","636EF871"},
|
{"06","636EF871"},
|
||||||
{"07","5F4468E3"},
|
{"07","5F4468E3"},
|
||||||
{"08","271149C7"},
|
{"08","271149C7"},
|
||||||
{"09","D7BB0B8F"},
|
{"09","D7BB0B8F"},
|
||||||
{"0A","36EF8F1E"},
|
{"0A","36EF8F1E"},
|
||||||
{"0B","F446863D"},
|
{"0B","F446863D"},
|
||||||
{"0C","7114947A"},
|
{"0C","7114947A"},
|
||||||
{"0D","7BB0B0F5"},
|
{"0D","7BB0B0F5"},
|
||||||
{"0E","6EF8F9EB"},
|
{"0E","6EF8F9EB"},
|
||||||
{"0F","44686BD7"},
|
{"0F","44686BD7"},
|
||||||
{"10","11494fAF"},
|
{"10","11494fAF"},
|
||||||
{"11","BB0B075F"},
|
{"11","BB0B075F"},
|
||||||
{"12","EF8F96BE"},
|
{"12","EF8F96BE"},
|
||||||
{"13","4686B57C"},
|
{"13","4686B57C"},
|
||||||
{"14","1494F2F9"},
|
{"14","1494F2F9"},
|
||||||
{"15","B0B07DF3"},
|
{"15","B0B07DF3"},
|
||||||
{"16","F8F963E6"},
|
{"16","F8F963E6"},
|
||||||
{"17","686B5FCC"},
|
{"17","686B5FCC"},
|
||||||
{"18","494F2799"},
|
{"18","494F2799"},
|
||||||
{"19","0B07D733"},
|
{"19","0B07D733"},
|
||||||
{"1A","8F963667"},
|
{"1A","8F963667"},
|
||||||
{"1B","86B5F4CE"},
|
{"1B","86B5F4CE"},
|
||||||
{"1C","94F2719C"},
|
{"1C","94F2719C"},
|
||||||
{"1D","B07D7B38"},
|
{"1D","B07D7B38"},
|
||||||
{"1E","F9636E70"},
|
{"1E","F9636E70"},
|
||||||
{"1F","6B5F44E0"},
|
{"1F","6B5F44E0"},
|
||||||
}
|
}
|
||||||
|
|
||||||
local function findEntryByUid( uid )
|
local function findEntryByUid( uid )
|
||||||
|
|
||||||
-- xor UID4,UID5,UID6,UID7
|
-- xor UID4,UID5,UID6,UID7
|
||||||
-- mod 0x20 (dec 32)
|
-- mod 0x20 (dec 32)
|
||||||
local pos = (bxor(uid[4], uid[5], uid[6], uid[7])) % 32
|
local pos = (bxor(uid[4], uid[5], uid[6], uid[7])) % 32
|
||||||
|
|
||||||
-- convert to hexstring
|
-- convert to hexstring
|
||||||
pos = string.format('%02X', pos)
|
pos = string.format('%02X', pos)
|
||||||
|
|
||||||
for k, v in pairs(_xortable) do
|
for k, v in pairs(_xortable) do
|
||||||
if ( v[1] == pos ) then
|
if ( v[1] == pos ) then
|
||||||
return utils.ConvertHexToBytes(v[2])
|
return utils.ConvertHexToBytes(v[2])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- create pwd
|
-- create pwd
|
||||||
local function pwdgen(uid)
|
local function pwdgen(uid)
|
||||||
-- PWD CALC
|
-- PWD CALC
|
||||||
-- PWD0 = T0 xor B xor C xor D
|
-- PWD0 = T0 xor B xor C xor D
|
||||||
-- PWD1 = T1 xor A xor C xor E
|
-- PWD1 = T1 xor A xor C xor E
|
||||||
-- PWD2 = T2 xor A xor B xor F
|
-- PWD2 = T2 xor A xor B xor F
|
||||||
-- PWD3 = T3 xor G
|
-- PWD3 = T3 xor G
|
||||||
local uidbytes = utils.ConvertHexToBytes(uid)
|
local uidbytes = utils.ConvertHexToBytes(uid)
|
||||||
local entry = findEntryByUid(uidbytes)
|
local entry = findEntryByUid(uidbytes)
|
||||||
if entry == nil then return nil, "Can't find a xor entry" end
|
if entry == nil then return nil, "Can't find a xor entry" end
|
||||||
|
|
||||||
local pwd0 = bxor( entry[1], uidbytes[2], uidbytes[3], uidbytes[4])
|
local pwd0 = bxor( entry[1], uidbytes[2], uidbytes[3], uidbytes[4])
|
||||||
local pwd1 = bxor( entry[2], uidbytes[1], uidbytes[3], uidbytes[5])
|
local pwd1 = bxor( entry[2], uidbytes[1], uidbytes[3], uidbytes[5])
|
||||||
local pwd2 = bxor( entry[3], uidbytes[1], uidbytes[2], uidbytes[6])
|
local pwd2 = bxor( entry[3], uidbytes[1], uidbytes[2], uidbytes[6])
|
||||||
local pwd3 = bxor( entry[4], uidbytes[7])
|
local pwd3 = bxor( entry[4], uidbytes[7])
|
||||||
return string.format('%02X%02X%02X%02X', pwd0, pwd1, pwd2, pwd3)
|
return string.format('%02X%02X%02X%02X', pwd0, pwd1, pwd2, pwd3)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- main
|
-- main
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print()
|
print()
|
||||||
|
|
||||||
local uid = '04111211121110'
|
local uid = '04111211121110'
|
||||||
local useUID = false
|
local useUID = false
|
||||||
|
|
||||||
-- Arguments for the script
|
-- Arguments for the script
|
||||||
for o, a in getopt.getopt(args, 'hu:') do
|
for o, a in getopt.getopt(args, 'hu:') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
if o == "u" then uid = a; useUID = true end
|
if o == "u" then uid = a; useUID = true end
|
||||||
end
|
end
|
||||||
|
|
||||||
if useUID then
|
if useUID then
|
||||||
-- uid string checks
|
-- uid string checks
|
||||||
if uid == nil then return oops('empty uid string') end
|
if uid == nil then return oops('empty uid string') end
|
||||||
if #uid == 0 then return oops('empty uid string') end
|
if #uid == 0 then return oops('empty uid string') end
|
||||||
if #uid ~= 14 then return oops('uid wrong length. Should be 7 hex bytes') end
|
if #uid ~= 14 then return oops('uid wrong length. Should be 7 hex bytes') end
|
||||||
else
|
else
|
||||||
-- GET TAG UID
|
-- GET TAG UID
|
||||||
local tag, err = lib14a.read(false, true)
|
local tag, err = lib14a.read(false, true)
|
||||||
if not tag then return oops(err) end
|
if not tag then return oops(err) end
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
uid = tag.uid
|
uid = tag.uid
|
||||||
end
|
end
|
||||||
|
|
||||||
print('UID | '..uid)
|
print('UID | '..uid)
|
||||||
local pwd, err = pwdgen(uid)
|
local pwd, err = pwdgen(uid)
|
||||||
if not pwd then return ooops(err) end
|
if not pwd then return ooops(err) end
|
||||||
|
|
||||||
print(string.format('PWD | %s', pwd))
|
print(string.format('PWD | %s', pwd))
|
||||||
end
|
end
|
||||||
|
|
||||||
main(args)
|
main(args)
|
||||||
@@ -10,188 +10,188 @@ This script calculates mifare keys based on uid diversification for mizip.
|
|||||||
Algo not found by me.
|
Algo not found by me.
|
||||||
]]
|
]]
|
||||||
example = [[
|
example = [[
|
||||||
-- if called without, it reads tag uid
|
-- if called without, it reads tag uid
|
||||||
script run calc_mizip
|
script run calc_mizip
|
||||||
|
|
||||||
--
|
--
|
||||||
script run calc_mizip -u 11223344
|
script run calc_mizip -u 11223344
|
||||||
]]
|
]]
|
||||||
usage = [[
|
usage = [[
|
||||||
script run calc_mizip -h -u <uid>
|
script run calc_mizip -h -u <uid>
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h : this help
|
-h : this help
|
||||||
-u <UID> : UID
|
-u <UID> : UID
|
||||||
]]
|
]]
|
||||||
local DEBUG = true
|
local DEBUG = true
|
||||||
local bxor = bit32.bxor
|
local bxor = bit32.bxor
|
||||||
local _xortable = {
|
local _xortable = {
|
||||||
--[[ sector key A/B, 6byte xor
|
--[[ sector key A/B, 6byte xor
|
||||||
--]]
|
--]]
|
||||||
{1, "09125a2589e5", "F12C8453D821"},
|
{1, "09125a2589e5", "F12C8453D821"},
|
||||||
{2, "AB75C937922F", "73E799FE3241"},
|
{2, "AB75C937922F", "73E799FE3241"},
|
||||||
{3, "E27241AF2C09", "AA4D137656AE"},
|
{3, "E27241AF2C09", "AA4D137656AE"},
|
||||||
{4, "317AB72F4490", "B01327272DFD"},
|
{4, "317AB72F4490", "B01327272DFD"},
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
local function dbg(args)
|
local function dbg(args)
|
||||||
if not DEBUG then return end
|
if not DEBUG then return end
|
||||||
if type(args) == "table" then
|
if type(args) == "table" then
|
||||||
local i = 1
|
local i = 1
|
||||||
while args[i] do
|
while args[i] do
|
||||||
dbg(args[i])
|
dbg(args[i])
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print("###", args)
|
print("###", args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
return nil,err
|
return nil,err
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(copyright)
|
print(copyright)
|
||||||
print(author)
|
print(author)
|
||||||
print(version)
|
print(version)
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- Exit message
|
-- Exit message
|
||||||
local function exitMsg(msg)
|
local function exitMsg(msg)
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print(msg)
|
print(msg)
|
||||||
print()
|
print()
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- dumps all keys to file
|
-- dumps all keys to file
|
||||||
local function dumptofile(keys)
|
local function dumptofile(keys)
|
||||||
dbg('dumping keys to file')
|
dbg('dumping keys to file')
|
||||||
|
|
||||||
if utils.confirm('Do you wish to save the keys to dumpfile?') then
|
if utils.confirm('Do you wish to save the keys to dumpfile?') then
|
||||||
local destination = utils.input('Select a filename to store to', 'dumpkeys.bin')
|
local destination = utils.input('Select a filename to store to', 'dumpkeys.bin')
|
||||||
local file = io.open(destination, 'wb')
|
local file = io.open(destination, 'wb')
|
||||||
if file == nil then
|
if file == nil then
|
||||||
print('Could not write to file ', destination)
|
print('Could not write to file ', destination)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Mifare Mini has 5 sectors,
|
-- Mifare Mini has 5 sectors,
|
||||||
local key_a = ''
|
local key_a = ''
|
||||||
local key_b = ''
|
local key_b = ''
|
||||||
|
|
||||||
for sector = 0, #keys do
|
for sector = 0, #keys do
|
||||||
local keyA, keyB = unpack(keys[sector])
|
local keyA, keyB = unpack(keys[sector])
|
||||||
key_a = key_a .. bin.pack('H', keyA);
|
key_a = key_a .. bin.pack('H', keyA);
|
||||||
key_b = key_b .. bin.pack('H', keyB);
|
key_b = key_b .. bin.pack('H', keyB);
|
||||||
end
|
end
|
||||||
file:write(key_a)
|
file:write(key_a)
|
||||||
file:write(key_b)
|
file:write(key_b)
|
||||||
file:close()
|
file:close()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- key bytes to string
|
-- key bytes to string
|
||||||
local function keyStr(p1, p2, p3, p4, p5, p6)
|
local function keyStr(p1, p2, p3, p4, p5, p6)
|
||||||
return string.format('%02X%02X%02X%02X%02X%02X',p1, p2, p3, p4, p5, p6)
|
return string.format('%02X%02X%02X%02X%02X%02X',p1, p2, p3, p4, p5, p6)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- create key
|
-- create key
|
||||||
local function calckey(uid, xorkey, keytype)
|
local function calckey(uid, xorkey, keytype)
|
||||||
local p1,p2,p3,p4,p5,p6
|
local p1,p2,p3,p4,p5,p6
|
||||||
if keytype == 'A' then
|
if keytype == 'A' then
|
||||||
p1 = bxor( uid[1], xorkey[1])
|
p1 = bxor( uid[1], xorkey[1])
|
||||||
p2 = bxor( uid[2], xorkey[2])
|
p2 = bxor( uid[2], xorkey[2])
|
||||||
p3 = bxor( uid[3], xorkey[3])
|
p3 = bxor( uid[3], xorkey[3])
|
||||||
p4 = bxor( uid[4], xorkey[4])
|
p4 = bxor( uid[4], xorkey[4])
|
||||||
p5 = bxor( uid[1], xorkey[5])
|
p5 = bxor( uid[1], xorkey[5])
|
||||||
p6 = bxor( uid[2], xorkey[6])
|
p6 = bxor( uid[2], xorkey[6])
|
||||||
else
|
else
|
||||||
p1 = bxor( uid[3], xorkey[1])
|
p1 = bxor( uid[3], xorkey[1])
|
||||||
p2 = bxor( uid[4], xorkey[2])
|
p2 = bxor( uid[4], xorkey[2])
|
||||||
p3 = bxor( uid[1], xorkey[3])
|
p3 = bxor( uid[1], xorkey[3])
|
||||||
p4 = bxor( uid[2], xorkey[4])
|
p4 = bxor( uid[2], xorkey[4])
|
||||||
p5 = bxor( uid[3], xorkey[5])
|
p5 = bxor( uid[3], xorkey[5])
|
||||||
p6 = bxor( uid[4], xorkey[6])
|
p6 = bxor( uid[4], xorkey[6])
|
||||||
end
|
end
|
||||||
return keyStr(p1,p2,p3,p4,p5,p6)
|
return keyStr(p1,p2,p3,p4,p5,p6)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- print keys
|
-- print keys
|
||||||
local function printKeys(keys)
|
local function printKeys(keys)
|
||||||
print('|---|----------------|---|----------------|---|')
|
print('|---|----------------|---|----------------|---|')
|
||||||
print('|sec|key A |res|key B |res|')
|
print('|sec|key A |res|key B |res|')
|
||||||
print('|---|----------------|---|----------------|---|')
|
print('|---|----------------|---|----------------|---|')
|
||||||
for sector = 0, #keys do
|
for sector = 0, #keys do
|
||||||
local keyA, keyB = unpack(keys[sector])
|
local keyA, keyB = unpack(keys[sector])
|
||||||
print(('|%03d| %s | %s | %s | %s |'):format(sector, keyA, 1, keyB, 1))
|
print(('|%03d| %s | %s | %s | %s |'):format(sector, keyA, 1, keyB, 1))
|
||||||
end
|
end
|
||||||
print('|---|----------------|---|----------------|---|')
|
print('|---|----------------|---|----------------|---|')
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- create a full set of keys
|
-- create a full set of keys
|
||||||
local function createKeys(uid)
|
local function createKeys(uid)
|
||||||
local uidbytes = utils.ConvertHexToBytes(uid)
|
local uidbytes = utils.ConvertHexToBytes(uid)
|
||||||
|
|
||||||
local k = {}
|
local k = {}
|
||||||
k[0] = { keyStr(0xA0,0xA1,0xA2,0xA3,0xA4,0xA5), keyStr(0xB4,0xC1,0x32,0x43,0x9e,0xef) }
|
k[0] = { keyStr(0xA0,0xA1,0xA2,0xA3,0xA4,0xA5), keyStr(0xB4,0xC1,0x32,0x43,0x9e,0xef) }
|
||||||
|
|
||||||
for _, v in pairs(_xortable) do
|
for _, v in pairs(_xortable) do
|
||||||
local keyA = calckey(uidbytes, utils.ConvertHexToBytes(v[2]), 'A')
|
local keyA = calckey(uidbytes, utils.ConvertHexToBytes(v[2]), 'A')
|
||||||
local keyB = calckey(uidbytes, utils.ConvertHexToBytes(v[3]), 'B')
|
local keyB = calckey(uidbytes, utils.ConvertHexToBytes(v[3]), 'B')
|
||||||
k[v[1]] = { keyA, keyB }
|
k[v[1]] = { keyA, keyB }
|
||||||
end
|
end
|
||||||
return k
|
return k
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- main
|
-- main
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
print( string.rep('==', 30) )
|
print( string.rep('==', 30) )
|
||||||
print()
|
print()
|
||||||
|
|
||||||
local uid = '11223344'
|
local uid = '11223344'
|
||||||
local useUID = false
|
local useUID = false
|
||||||
|
|
||||||
-- Arguments for the script
|
-- Arguments for the script
|
||||||
for o, a in getopt.getopt(args, 'hu:') do
|
for o, a in getopt.getopt(args, 'hu:') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
if o == "u" then uid = a ; useUID = true end
|
if o == "u" then uid = a ; useUID = true end
|
||||||
end
|
end
|
||||||
|
|
||||||
if useUID then
|
if useUID then
|
||||||
-- uid string checks
|
-- uid string checks
|
||||||
if uid == nil then return oops('empty uid string') end
|
if uid == nil then return oops('empty uid string') end
|
||||||
if #uid == 0 then return oops('empty uid string') end
|
if #uid == 0 then return oops('empty uid string') end
|
||||||
if #uid ~= 8 then return oops('uid wrong length. Should be 4 hex bytes') end
|
if #uid ~= 8 then return oops('uid wrong length. Should be 4 hex bytes') end
|
||||||
else
|
else
|
||||||
-- GET TAG UID
|
-- GET TAG UID
|
||||||
local tag, err = lib14a.read(false, true)
|
local tag, err = lib14a.read(false, true)
|
||||||
if not tag then return oops(err) end
|
if not tag then return oops(err) end
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
-- simple tag check
|
-- simple tag check
|
||||||
if 0x09 ~= tag.sak then
|
if 0x09 ~= tag.sak then
|
||||||
if 0x4400 ~= tag.atqa then
|
if 0x4400 ~= tag.atqa then
|
||||||
return oops(('[fail] found tag %s :: looking for Mifare Mini 0.3k'):format(tag.name))
|
return oops(('[fail] found tag %s :: looking for Mifare Mini 0.3k'):format(tag.name))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
uid = tag.uid
|
uid = tag.uid
|
||||||
end
|
end
|
||||||
|
|
||||||
print('|UID|', uid)
|
print('|UID|', uid)
|
||||||
|
|
||||||
local keys, err = createKeys( uid )
|
local keys, err = createKeys( uid )
|
||||||
printKeys( keys )
|
printKeys( keys )
|
||||||
dumptofile( keys )
|
dumptofile( keys )
|
||||||
end
|
end
|
||||||
|
|
||||||
main(args)
|
main(args)
|
||||||
@@ -11,10 +11,10 @@ desc =
|
|||||||
This is a script to communicate with a CALYSPO / 14443b tag using the '14b raw' commands
|
This is a script to communicate with a CALYSPO / 14443b tag using the '14b raw' commands
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-b 123
|
-b 123
|
||||||
Examples :
|
Examples :
|
||||||
script run f -b 11223344
|
script run f -b 11223344
|
||||||
script run f
|
script run f
|
||||||
|
|
||||||
Examples :
|
Examples :
|
||||||
|
|
||||||
@@ -36,48 +36,48 @@ device-side.
|
|||||||
---
|
---
|
||||||
--
|
--
|
||||||
local function calypso_switch_on_field()
|
local function calypso_switch_on_field()
|
||||||
local flags = lib14b.ISO14B_COMMAND.ISO14B_CONNECT
|
local flags = lib14b.ISO14B_COMMAND.ISO14B_CONNECT
|
||||||
local c = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND, arg1 = flags}
|
local c = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND, arg1 = flags}
|
||||||
return lib14b.sendToDevice(c, true)
|
return lib14b.sendToDevice(c, true)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Disconnect (poweroff) the antenna forcing a disconnect of a 14b tag.
|
-- Disconnect (poweroff) the antenna forcing a disconnect of a 14b tag.
|
||||||
local function calypso_switch_off_field()
|
local function calypso_switch_off_field()
|
||||||
local flags = lib14b.ISO14B_COMMAND.ISO14B_DISCONNECT
|
local flags = lib14b.ISO14B_COMMAND.ISO14B_DISCONNECT
|
||||||
local c = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND, arg1 = flags}
|
local c = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND, arg1 = flags}
|
||||||
return lib14b.sendToDevice(c, true)
|
return lib14b.sendToDevice(c, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function calypso_parse(result)
|
local function calypso_parse(result)
|
||||||
local r = Command.parse(result)
|
local r = Command.parse(result)
|
||||||
local len = r.arg2 * 2
|
local len = r.arg2 * 2
|
||||||
r.data = string.sub(r.data, 0, len);
|
r.data = string.sub(r.data, 0, len);
|
||||||
print('GOT:', r.data)
|
print('GOT:', r.data)
|
||||||
if r.arg1 == 0 then
|
if r.arg1 == 0 then
|
||||||
return r, nil
|
return r, nil
|
||||||
end
|
end
|
||||||
return nil,nil
|
return nil,nil
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
local function dbg(args)
|
local function dbg(args)
|
||||||
if DEBUG then
|
if DEBUG then
|
||||||
print("###", args)
|
print("###", args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print("ERROR: ", err)
|
print("ERROR: ", err)
|
||||||
calypso_switch_off_field()
|
calypso_switch_off_field()
|
||||||
return nil, err
|
return nil, err
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- helper function, give current count of items in lua-table.
|
-- helper function, give current count of items in lua-table.
|
||||||
@@ -116,50 +116,50 @@ end
|
|||||||
-- if it reads the response, it converts it to a lua object "Command" first and the Data is cut to correct length.
|
-- if it reads the response, it converts it to a lua object "Command" first and the Data is cut to correct length.
|
||||||
local function calypso_send_cmd_raw(data, ignoreresponse )
|
local function calypso_send_cmd_raw(data, ignoreresponse )
|
||||||
|
|
||||||
local command, flags, result, err
|
local command, flags, result, err
|
||||||
flags = lib14b.ISO14B_COMMAND.ISO14B_RAW +
|
flags = lib14b.ISO14B_COMMAND.ISO14B_RAW +
|
||||||
lib14b.ISO14B_COMMAND.ISO14B_APPEND_CRC
|
lib14b.ISO14B_COMMAND.ISO14B_APPEND_CRC
|
||||||
|
|
||||||
data = data or "00"
|
data = data or "00"
|
||||||
|
|
||||||
command = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND,
|
command = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND,
|
||||||
arg1 = flags,
|
arg1 = flags,
|
||||||
arg2 = #data/2, -- LEN of data, half the length of the ASCII-string hex string
|
arg2 = #data/2, -- LEN of data, half the length of the ASCII-string hex string
|
||||||
arg3 = 0,
|
arg3 = 0,
|
||||||
data = data} -- data bytes (commands etc)
|
data = data} -- data bytes (commands etc)
|
||||||
result, err = lib14b.sendToDevice(command, false)
|
result, err = lib14b.sendToDevice(command, false)
|
||||||
|
|
||||||
if ignoreresponse then return response, err end
|
if ignoreresponse then return response, err end
|
||||||
|
|
||||||
if result then
|
if result then
|
||||||
local r = calypso_parse(result)
|
local r = calypso_parse(result)
|
||||||
return r, nil
|
return r, nil
|
||||||
end
|
end
|
||||||
return respone, err
|
return respone, err
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- calypso_card_num : Reads card number from ATR and
|
-- calypso_card_num : Reads card number from ATR and
|
||||||
-- writes it in the tree in decimal format.
|
-- writes it in the tree in decimal format.
|
||||||
local function calypso_card_num(card)
|
local function calypso_card_num(card)
|
||||||
if not card then return end
|
if not card then return end
|
||||||
local card_num = tonumber( card.uid:sub(1,8),16 )
|
local card_num = tonumber( card.uid:sub(1,8),16 )
|
||||||
print('Card UID', card.uid)
|
print('Card UID', card.uid)
|
||||||
print('Card Number', card_num)
|
print('Card Number', card_num)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- analyse CALYPSO apdu status bytes.
|
-- analyse CALYPSO apdu status bytes.
|
||||||
local function calypso_apdu_status(apdu)
|
local function calypso_apdu_status(apdu)
|
||||||
-- last two is CRC
|
-- last two is CRC
|
||||||
-- next two is APDU status bytes.
|
-- next two is APDU status bytes.
|
||||||
local status = false
|
local status = false
|
||||||
local mess = 'FAIL'
|
local mess = 'FAIL'
|
||||||
local sw = apdu:sub( #apdu-7, #apdu-4)
|
local sw = apdu:sub( #apdu-7, #apdu-4)
|
||||||
desc, err = iso7816.tostring(sw)
|
desc, err = iso7816.tostring(sw)
|
||||||
print ('SW', sw, desc, err )
|
print ('SW', sw, desc, err )
|
||||||
|
|
||||||
status = ( sw == '9000' )
|
status = ( sw == '9000' )
|
||||||
|
|
||||||
return status
|
return status
|
||||||
end
|
end
|
||||||
|
|
||||||
local _calypso_cmds = {
|
local _calypso_cmds = {
|
||||||
@@ -174,9 +174,9 @@ local _calypso_cmds = {
|
|||||||
-- can be seen as directories
|
-- can be seen as directories
|
||||||
-- 0x38
|
-- 0x38
|
||||||
-- 0xNN id
|
-- 0xNN id
|
||||||
-- ["01.Select ICC file"] = '0294 a4 080004 3f00 0002',
|
-- ["01.Select ICC file"] = '0294 a4 080004 3f00 0002',
|
||||||
|
|
||||||
-- EF Elementary File
|
-- EF Elementary File
|
||||||
-- EF1 Pin file
|
-- EF1 Pin file
|
||||||
-- EF2 Key file
|
-- EF2 Key file
|
||||||
-- Grey Lock file
|
-- Grey Lock file
|
||||||
@@ -185,92 +185,92 @@ local _calypso_cmds = {
|
|||||||
-- Electronic Transaction log file
|
-- Electronic Transaction log file
|
||||||
|
|
||||||
|
|
||||||
--["01.Select ICC file"] = '0294 a4 00 0002 3f00',
|
--["01.Select ICC file"] = '0294 a4 00 0002 3f00',
|
||||||
["01.Select ICC file"] = '0294 a4 080004 3f00 0002',
|
["01.Select ICC file"] = '0294 a4 080004 3f00 0002',
|
||||||
["02.ICC"] = '0394 b2 01 041d',
|
["02.ICC"] = '0394 b2 01 041d',
|
||||||
["03.Select EnvHol file"] = '0294 a4 080004 2000 2001',
|
["03.Select EnvHol file"] = '0294 a4 080004 2000 2001',
|
||||||
["04.EnvHol1"] = '0394 b2 01 041d',
|
["04.EnvHol1"] = '0394 b2 01 041d',
|
||||||
["05.Select EvLog file"] = '0294 a4 080004 2000 2010',
|
["05.Select EvLog file"] = '0294 a4 080004 2000 2010',
|
||||||
["06.EvLog1"] = '0394 b2 01 041d',
|
["06.EvLog1"] = '0394 b2 01 041d',
|
||||||
["07.EvLog2"] = '0294 b2 02 041d',
|
["07.EvLog2"] = '0294 b2 02 041d',
|
||||||
["08.EvLog3"] = '0394 b2 03 041d',
|
["08.EvLog3"] = '0394 b2 03 041d',
|
||||||
["09.Select ConList file"] ='0294 a4 080004 2000 2050',
|
["09.Select ConList file"]= '0294 a4 080004 2000 2050',
|
||||||
["10.ConList"] = '0394 b2 01 041d',
|
["10.ConList"] = '0394 b2 01 041d',
|
||||||
["11.Select Contra file"] = '0294 a4 080004 2000 2020',
|
["11.Select Contra file"] = '0294 a4 080004 2000 2020',
|
||||||
["12.Contra1"] = '0394 b2 01 041d',
|
["12.Contra1"] = '0394 b2 01 041d',
|
||||||
["13.Contra2"] = '0294 b2 02 041d',
|
["13.Contra2"] = '0294 b2 02 041d',
|
||||||
["14.Contra3"] = '0394 b2 03 041d',
|
["14.Contra3"] = '0394 b2 03 041d',
|
||||||
["15.Contra4"] = '0294 b2 04 041d',
|
["15.Contra4"] = '0294 b2 04 041d',
|
||||||
["16.Select Counter file"]= '0394 a4 080004 2000 2069',
|
["16.Select Counter file"]= '0394 a4 080004 2000 2069',
|
||||||
["17.Counter"] = '0294 b2 01 041d',
|
["17.Counter"] = '0294 b2 01 041d',
|
||||||
["18.Select SpecEv file"]= '0394 a4 080004 2000 2040',
|
["18.Select SpecEv file"] = '0394 a4 080004 2000 2040',
|
||||||
["19.SpecEv1"] = '0294 b2 01 041d',
|
["19.SpecEv1"] = '0294 b2 01 041d',
|
||||||
}
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
-- The main entry point
|
-- The main entry point
|
||||||
function main(args)
|
function main(args)
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print()
|
print()
|
||||||
|
|
||||||
local data, apdu, flags, uid, cid, result, err, card
|
local data, apdu, flags, uid, cid, result, err, card
|
||||||
-- Read the parameters
|
-- Read the parameters
|
||||||
for o, a in getopt.getopt(args, 'h') do
|
for o, a in getopt.getopt(args, 'h') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
end
|
end
|
||||||
|
|
||||||
calypso_switch_on_field()
|
calypso_switch_on_field()
|
||||||
|
|
||||||
-- Select 14b tag.
|
-- Select 14b tag.
|
||||||
card, err = lib14b.waitFor14443b()
|
card, err = lib14b.waitFor14443b()
|
||||||
if not card then return oops(err) end
|
if not card then return oops(err) end
|
||||||
|
|
||||||
calypso_card_num(card)
|
calypso_card_num(card)
|
||||||
cid = card.cid
|
cid = card.cid
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
NAME VALUE APDU_POS
|
NAME VALUE APDU_POS
|
||||||
PCB 0x0A 0
|
PCB 0x0A 0
|
||||||
CID 0x00 1
|
CID 0x00 1
|
||||||
CLA 0x94 2
|
CLA 0x94 2
|
||||||
SELECT FILE 0xA4 3
|
SELECT FILE 0xA4 3
|
||||||
READ FILE 0xB2 3
|
READ FILE 0xB2 3
|
||||||
P1 4
|
P1 4
|
||||||
P2 5
|
P2 5
|
||||||
LEN_
|
LEN_
|
||||||
0 1 2 3 4 5 6 7
|
0 1 2 3 4 5 6 7
|
||||||
apdu = '02 94 a4 08 00 04 3f 00 00 02' --select ICC file
|
apdu = '02 94 a4 08 00 04 3f 00 00 02' --select ICC file
|
||||||
DF_NAME = "1TIC.ICA"
|
DF_NAME = "1TIC.ICA"
|
||||||
--]]
|
--]]
|
||||||
--for i = 1,10 do
|
--for i = 1,10 do
|
||||||
--result, err = calypso_send_cmd_raw('0294a40800043f000002',false) --select ICC file
|
--result, err = calypso_send_cmd_raw('0294a40800043f000002',false) --select ICC file
|
||||||
for i, apdu in spairs(_calypso_cmds) do
|
for i, apdu in spairs(_calypso_cmds) do
|
||||||
print('>>', i )
|
print('>>', i )
|
||||||
apdu = apdu:gsub("%s+","")
|
apdu = apdu:gsub("%s+","")
|
||||||
result, err = calypso_send_cmd_raw(apdu , false)
|
result, err = calypso_send_cmd_raw(apdu , false)
|
||||||
if result then
|
if result then
|
||||||
calypso_apdu_status(result.data)
|
calypso_apdu_status(result.data)
|
||||||
print('<<', result.data )
|
print('<<', result.data )
|
||||||
else
|
else
|
||||||
print('<< no answer')
|
print('<< no answer')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
calypso_switch_off_field()
|
calypso_switch_off_field()
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- a simple selftest function, tries to convert
|
-- a simple selftest function, tries to convert
|
||||||
function selftest()
|
function selftest()
|
||||||
DEBUG = true
|
DEBUG = true
|
||||||
dbg("Performing test")
|
dbg("Performing test")
|
||||||
dbg("Tests done")
|
dbg("Tests done")
|
||||||
end
|
end
|
||||||
-- Flip the switch here to perform a sanity check.
|
-- Flip the switch here to perform a sanity check.
|
||||||
-- It read a nonce in two different ways, as specified in the usage-section
|
-- It read a nonce in two different ways, as specified in the usage-section
|
||||||
if "--test"==args then
|
if "--test"==args then
|
||||||
selftest()
|
selftest()
|
||||||
else
|
else
|
||||||
-- Call the main
|
-- Call the main
|
||||||
main(args)
|
main(args)
|
||||||
end
|
end
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
print("This is how a cmd-line interface could be implemented\nPrint 'exit' to exit.\n")
|
print("This is how a cmd-line interface could be implemented\nPrint 'exit' to exit.\n")
|
||||||
local answer
|
local answer
|
||||||
repeat
|
repeat
|
||||||
io.write("$>")
|
io.write("$>")
|
||||||
io.flush()
|
io.flush()
|
||||||
answer=io.read()
|
answer=io.read()
|
||||||
if answer ~= 'exit' then
|
if answer ~= 'exit' then
|
||||||
local func = assert(loadstring("return " .. answer))
|
local func = assert(loadstring("return " .. answer))
|
||||||
io.write("\n"..tostring(func() or "").."\n");
|
io.write("\n"..tostring(func() or "").."\n");
|
||||||
end--]]
|
end--]]
|
||||||
until answer=="exit"
|
until answer=="exit"
|
||||||
print("Bye\n");
|
print("Bye\n");
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ local json = require('dkjson')
|
|||||||
local toys = require('default_toys_di')
|
local toys = require('default_toys_di')
|
||||||
|
|
||||||
example =[[
|
example =[[
|
||||||
script run didump
|
script run didump
|
||||||
script run didump -t
|
script run didump -t
|
||||||
script run didump -r
|
script run didump -r
|
||||||
]]
|
]]
|
||||||
author = "Iceman"
|
author = "Iceman"
|
||||||
usage = "script run didump -h -t"
|
usage = "script run didump -h -t"
|
||||||
@@ -18,9 +18,9 @@ desc = [[
|
|||||||
This is a script to dump and decrypt the data of a specific type of Mifare Mini token.
|
This is a script to dump and decrypt the data of a specific type of Mifare Mini token.
|
||||||
The dump is decrypted. If a raw dump is wanted, use the -r parameter
|
The dump is decrypted. If a raw dump is wanted, use the -r parameter
|
||||||
Arguments:
|
Arguments:
|
||||||
-h : this help
|
-h : this help
|
||||||
-r : raw
|
-r : raw
|
||||||
-t : selftest
|
-t : selftest
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local band=bit32.band
|
local band=bit32.band
|
||||||
@@ -44,46 +44,46 @@ local CHECKSUM_OFFSET = 12; -- +1???
|
|||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
local function dbg(args)
|
local function dbg(args)
|
||||||
if not DEBUG then return end
|
if not DEBUG then return end
|
||||||
if type(args) == "table" then
|
if type(args) == "table" then
|
||||||
local i = 1
|
local i = 1
|
||||||
while args[i] do
|
while args[i] do
|
||||||
print("###", args[i])
|
print("###", args[i])
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print("###", args)
|
print("###", args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
--
|
--
|
||||||
local function print_info(tagdata)
|
local function print_info(tagdata)
|
||||||
--got table with data.
|
--got table with data.
|
||||||
local h = tagdata[2]:sub(1,8)
|
local h = tagdata[2]:sub(1,8)
|
||||||
local t = tostring( tonumber( h, 16 ) )
|
local t = tostring( tonumber( h, 16 ) )
|
||||||
local item = toys.Find(t)
|
local item = toys.Find(t)
|
||||||
print( ("Modelid : %s , %s, v.%s.0"):format(t, item[3], item[2]))
|
print( ("Modelid : %s , %s, v.%s.0"):format(t, item[3], item[2]))
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Get checksum,
|
-- Get checksum,
|
||||||
-- called: data is string (32 hex digits)
|
-- called: data is string (32 hex digits)
|
||||||
-- returns: number
|
-- returns: number
|
||||||
local function getChecksum(data)
|
local function getChecksum(data)
|
||||||
local chksum = data:sub(25,32)
|
local chksum = data:sub(25,32)
|
||||||
return tonumber(chksum,16)
|
return tonumber(chksum,16)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- calculate checksum
|
-- calculate checksum
|
||||||
@@ -91,8 +91,8 @@ end
|
|||||||
-- returns: number
|
-- returns: number
|
||||||
local function calculateChecksum(data)
|
local function calculateChecksum(data)
|
||||||
|
|
||||||
-- Generate table
|
-- Generate table
|
||||||
local _tbl = {}
|
local _tbl = {}
|
||||||
_tbl[0] = { 0x0 }
|
_tbl[0] = { 0x0 }
|
||||||
_tbl[1] = { 0x77073096 }
|
_tbl[1] = { 0x77073096 }
|
||||||
_tbl[2] = { 0xEE0E612C }
|
_tbl[2] = { 0xEE0E612C }
|
||||||
@@ -351,186 +351,186 @@ _tbl[254] = { 0x5A05DF1B }
|
|||||||
_tbl[255] = { 0x2D02EF8D }
|
_tbl[255] = { 0x2D02EF8D }
|
||||||
|
|
||||||
|
|
||||||
-- Calculate it
|
-- Calculate it
|
||||||
local ret = 0
|
local ret = 0
|
||||||
for i,item in pairs(data) do
|
for i,item in pairs(data) do
|
||||||
local tmp = band(ret, 0xFF)
|
local tmp = band(ret, 0xFF)
|
||||||
local index = band( bxor(tmp, item), 0xFF)
|
local index = band( bxor(tmp, item), 0xFF)
|
||||||
ret = bxor(rsh(ret,8), _tbl[index][1])
|
ret = bxor(rsh(ret,8), _tbl[index][1])
|
||||||
end
|
end
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- update checksum
|
-- update checksum
|
||||||
-- called: data is string, ( >= 24 hex digits )
|
-- called: data is string, ( >= 24 hex digits )
|
||||||
-- returns: string, (data concat new checksum)
|
-- returns: string, (data concat new checksum)
|
||||||
local function updateChecksum(data)
|
local function updateChecksum(data)
|
||||||
local part = data:sub(1,24)
|
local part = data:sub(1,24)
|
||||||
local chksum = calculateChecksum( utils.ConvertHexToBytes(part))
|
local chksum = calculateChecksum( utils.ConvertHexToBytes(part))
|
||||||
return string.format("%s%X", part, chksum)
|
return string.format("%s%X", part, chksum)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- receives the answer from deviceside, used with a readblock command
|
-- receives the answer from deviceside, used with a readblock command
|
||||||
local function waitCmd()
|
local function waitCmd()
|
||||||
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
|
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
|
||||||
if response then
|
if response then
|
||||||
local count,cmd,arg0 = bin.unpack('LL',response)
|
local count,cmd,arg0 = bin.unpack('LL',response)
|
||||||
if(arg0==1) then
|
if(arg0==1) then
|
||||||
local count,arg1,arg2,data = bin.unpack('LLH511',response,count)
|
local count,arg1,arg2,data = bin.unpack('LLH511',response,count)
|
||||||
return data:sub(1,32)
|
return data:sub(1,32)
|
||||||
else
|
else
|
||||||
return nil, "Couldn't read block.."
|
return nil, "Couldn't read block.."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return nil, "No response from device"
|
return nil, "No response from device"
|
||||||
end
|
end
|
||||||
|
|
||||||
local function keygen(uid)
|
local function keygen(uid)
|
||||||
local data = MIS..uid..BAR
|
local data = MIS..uid..BAR
|
||||||
local hash = utils.ConvertAsciiToBytes(utils.Sha1Hex(data))
|
local hash = utils.ConvertAsciiToBytes(utils.Sha1Hex(data))
|
||||||
return string.format("%02X%02X%02X%02X%02X%02X",
|
return string.format("%02X%02X%02X%02X%02X%02X",
|
||||||
hash[3+1],
|
hash[3+1],
|
||||||
hash[2+1],
|
hash[2+1],
|
||||||
hash[1+1],
|
hash[1+1],
|
||||||
hash[0+1],
|
hash[0+1],
|
||||||
hash[7+1],
|
hash[7+1],
|
||||||
hash[6+1]
|
hash[6+1]
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- encode 'table' into a json formatted string
|
--- encode 'table' into a json formatted string
|
||||||
--
|
--
|
||||||
local function convert_to_json( obj )
|
local function convert_to_json( obj )
|
||||||
if type(obj) == "table" then
|
if type(obj) == "table" then
|
||||||
return json.encode (obj, { indent = true })
|
return json.encode (obj, { indent = true })
|
||||||
end
|
end
|
||||||
return oops('[fail] input object must be a lua-TABLE')
|
return oops('[fail] input object must be a lua-TABLE')
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- Save
|
-- Save
|
||||||
local function save_json(filename, data)
|
local function save_json(filename, data)
|
||||||
jsondata = convert_to_json(data)
|
jsondata = convert_to_json(data)
|
||||||
filename = filename or 'dumpdata.json'
|
filename = filename or 'dumpdata.json'
|
||||||
local f = io.open(filename, "w")
|
local f = io.open(filename, "w")
|
||||||
if not f then return oops(string.format("Could not write to file %s", tostring(filename))) end
|
if not f then return oops(string.format("Could not write to file %s", tostring(filename))) end
|
||||||
f:write(jsondata)
|
f:write(jsondata)
|
||||||
io.close(f)
|
io.close(f)
|
||||||
return filename
|
return filename
|
||||||
end
|
end
|
||||||
--- loads a json formatted text file with
|
--- loads a json formatted text file with
|
||||||
--
|
--
|
||||||
-- @param filename the file containing the json-dump (defaults to dumpdata.json)
|
-- @param filename the file containing the json-dump (defaults to dumpdata.json)
|
||||||
local function load_json(filename)
|
local function load_json(filename)
|
||||||
filename = filename or 'dumpdata.json'
|
filename = filename or 'dumpdata.json'
|
||||||
local f = io.open(filename, "rb")
|
local f = io.open(filename, "rb")
|
||||||
if not f then return oops(string.format("Could not read file %s", tostring(filename))) end
|
if not f then return oops(string.format("Could not read file %s", tostring(filename))) end
|
||||||
|
|
||||||
-- Read file
|
-- Read file
|
||||||
local t = f:read("*all")
|
local t = f:read("*all")
|
||||||
io.close(f)
|
io.close(f)
|
||||||
|
|
||||||
local obj, pos, err = json.decode(t, 1, nil)
|
local obj, pos, err = json.decode(t, 1, nil)
|
||||||
if err then return oops(string.format("importing json file failed. %s", err)) end
|
if err then return oops(string.format("importing json file failed. %s", err)) end
|
||||||
|
|
||||||
dbg(string.format('loaded file %s', input))
|
dbg(string.format('loaded file %s', input))
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
-- local len, hex = bin.unpack( ("H%d"):format(#t), t)
|
-- local len, hex = bin.unpack( ("H%d"):format(#t), t)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Generate encryption key
|
-- Generate encryption key
|
||||||
local function create_key(uid)
|
local function create_key(uid)
|
||||||
local key = ''
|
local key = ''
|
||||||
local sha = utils.Sha1Hex( FOO..BAR..uid )
|
local sha = utils.Sha1Hex( FOO..BAR..uid )
|
||||||
sha = utils.ConvertBytesToHex( utils.ConvertAsciiToBytes(sha:sub(1,16)) )
|
sha = utils.ConvertBytesToHex( utils.ConvertAsciiToBytes(sha:sub(1,16)) )
|
||||||
key = utils.SwapEndiannessStr( sha:sub(1,8) , 32 )
|
key = utils.SwapEndiannessStr( sha:sub(1,8) , 32 )
|
||||||
key = key..utils.SwapEndiannessStr( sha:sub(9,16), 32 )
|
key = key..utils.SwapEndiannessStr( sha:sub(9,16), 32 )
|
||||||
key = key..utils.SwapEndiannessStr( sha:sub(17,24), 32 )
|
key = key..utils.SwapEndiannessStr( sha:sub(17,24), 32 )
|
||||||
key = key..utils.SwapEndiannessStr( sha:sub(25,32), 32 )
|
key = key..utils.SwapEndiannessStr( sha:sub(25,32), 32 )
|
||||||
return key
|
return key
|
||||||
end
|
end
|
||||||
--- reads all blocks from tag
|
--- reads all blocks from tag
|
||||||
--
|
--
|
||||||
local function readtag(mfkey, aeskey )
|
local function readtag(mfkey, aeskey )
|
||||||
|
|
||||||
local tagdata = {}
|
local tagdata = {}
|
||||||
|
|
||||||
for blockNo = 0, numBlocks-1 do
|
for blockNo = 0, numBlocks-1 do
|
||||||
|
|
||||||
if core.ukbhit() then
|
if core.ukbhit() then
|
||||||
print("[fail] aborted by user")
|
print("[fail] aborted by user")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
-- read block from tag.
|
-- read block from tag.
|
||||||
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blockNo ,arg2 = 0,arg3 = 0, data = mfkey}
|
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blockNo ,arg2 = 0,arg3 = 0, data = mfkey}
|
||||||
local err = core.SendCommand(cmd:getBytes())
|
local err = core.SendCommand(cmd:getBytes())
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
local blockdata, err = waitCmd()
|
local blockdata, err = waitCmd()
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
|
|
||||||
-- rules:
|
-- rules:
|
||||||
-- the following blocks is NOT encrypted
|
-- the following blocks is NOT encrypted
|
||||||
-- block 0 (manufacturing) and 18
|
-- block 0 (manufacturing) and 18
|
||||||
-- block with all zeros
|
-- block with all zeros
|
||||||
-- sector trailor
|
-- sector trailor
|
||||||
if blockNo == 0 or blockNo == 18 then
|
if blockNo == 0 or blockNo == 18 then
|
||||||
|
|
||||||
elseif blockNo%4 ~= 3 then
|
elseif blockNo%4 ~= 3 then
|
||||||
|
|
||||||
if not string.find(blockdata, '^0+$') then
|
if not string.find(blockdata, '^0+$') then
|
||||||
if aeskey then
|
if aeskey then
|
||||||
local decrypted, err = core.aes128_decrypt_ecb(aeskey, blockdata)
|
local decrypted, err = core.aes128_decrypt_ecb(aeskey, blockdata)
|
||||||
if err then dbg(err) end
|
if err then dbg(err) end
|
||||||
blockdata = utils.ConvertAsciiToHex(decrypted)
|
blockdata = utils.ConvertAsciiToHex(decrypted)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
-- Sectorblocks, not encrypted, but we add our known key to it since it is normally zeros.
|
-- Sectorblocks, not encrypted, but we add our known key to it since it is normally zeros.
|
||||||
blockdata = mfkey..blockdata:sub(13,20)..mfkey
|
blockdata = mfkey..blockdata:sub(13,20)..mfkey
|
||||||
--dbg(blockdata:sub(13,20))
|
--dbg(blockdata:sub(13,20))
|
||||||
end
|
end
|
||||||
table.insert(tagdata, blockdata)
|
table.insert(tagdata, blockdata)
|
||||||
end
|
end
|
||||||
return tagdata
|
return tagdata
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- simple selftest of functionality
|
-- simple selftest of functionality
|
||||||
local function selftest()
|
local function selftest()
|
||||||
local testdata = '000F42430D0A14000001D11F'..'5D738517'
|
local testdata = '000F42430D0A14000001D11F'..'5D738517'
|
||||||
local chksum = getChecksum(testdata)
|
local chksum = getChecksum(testdata)
|
||||||
local calc = calculateChecksum( utils.ConvertHexToBytes(testdata:sub(1,24)))
|
local calc = calculateChecksum( utils.ConvertHexToBytes(testdata:sub(1,24)))
|
||||||
print ( testdata:sub(1,24) )
|
print ( testdata:sub(1,24) )
|
||||||
print ( ('%x - %x'):format(chksum, calc))
|
print ( ('%x - %x'):format(chksum, calc))
|
||||||
|
|
||||||
local isValid = false
|
local isValid = false
|
||||||
local validStr = "FAIL"
|
local validStr = "FAIL"
|
||||||
if calc == chksum then
|
if calc == chksum then
|
||||||
isValid = true
|
isValid = true
|
||||||
validStr = "OK"
|
validStr = "OK"
|
||||||
end
|
end
|
||||||
local newtestdata = updateChecksum(testdata)
|
local newtestdata = updateChecksum(testdata)
|
||||||
local revalidated = "FAIL"
|
local revalidated = "FAIL"
|
||||||
if newtestdata == testdata then
|
if newtestdata == testdata then
|
||||||
revalidated = "OK"
|
revalidated = "OK"
|
||||||
end
|
end
|
||||||
print ('TESTDATA :: '..testdata)
|
print ('TESTDATA :: '..testdata)
|
||||||
print ('DATA :: '..testdata:sub(1,24))
|
print ('DATA :: '..testdata:sub(1,24))
|
||||||
print (('VALID CHKSUM :: %s'):format(validStr ))
|
print (('VALID CHKSUM :: %s'):format(validStr ))
|
||||||
print (('UPDATE CHKSUM :: %s'):format(revalidated))
|
print (('UPDATE CHKSUM :: %s'):format(revalidated))
|
||||||
|
|
||||||
local testkey = keygen('0456263a873a80')
|
local testkey = keygen('0456263a873a80')
|
||||||
print ('TEST KEY :: '..testkey)
|
print ('TEST KEY :: '..testkey)
|
||||||
print ('VALID KEY :: 29564af75805')
|
print ('VALID KEY :: 29564af75805')
|
||||||
end
|
end
|
||||||
local function setdevicedebug( status )
|
local function setdevicedebug( status )
|
||||||
local c = 'hf mf dbg '
|
local c = 'hf mf dbg '
|
||||||
if status then
|
if status then
|
||||||
c = c..'1'
|
c = c..'1'
|
||||||
else
|
else
|
||||||
c = c..'0'
|
c = c..'0'
|
||||||
end
|
end
|
||||||
core.console(c)
|
core.console(c)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- The main entry point
|
-- The main entry point
|
||||||
@@ -539,60 +539,60 @@ end
|
|||||||
-- -v validate
|
-- -v validate
|
||||||
function main(args)
|
function main(args)
|
||||||
|
|
||||||
local cmd, tag, err, blockNo, mfkey
|
local cmd, tag, err, blockNo, mfkey
|
||||||
local shall_validate = false
|
local shall_validate = false
|
||||||
local shall_dec = false
|
local shall_dec = false
|
||||||
local shall_enc = false
|
local shall_enc = false
|
||||||
local blocks = {}
|
local blocks = {}
|
||||||
local aeskey = ''
|
local aeskey = ''
|
||||||
local input = ''
|
local input = ''
|
||||||
|
|
||||||
-- Read the parameters
|
-- Read the parameters
|
||||||
for o, a in getopt.getopt(args, 'htdevi:') do
|
for o, a in getopt.getopt(args, 'htdevi:') do
|
||||||
if o == "h" then help() return end
|
if o == "h" then help() return end
|
||||||
if o == "t" then return selftest() end
|
if o == "t" then return selftest() end
|
||||||
if o == "d" then shall_dec = true end
|
if o == "d" then shall_dec = true end
|
||||||
if o == "e" then shall_enc = true end
|
if o == "e" then shall_enc = true end
|
||||||
if o == "v" then shall_validate = true end
|
if o == "v" then shall_validate = true end
|
||||||
if o == "i" then input = load_json(a) end
|
if o == "i" then input = load_json(a) end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Turn off Debug
|
-- Turn off Debug
|
||||||
setdevicedebug(false)
|
setdevicedebug(false)
|
||||||
|
|
||||||
-- GET TAG UID
|
-- GET TAG UID
|
||||||
tag, err = lib14a.read(false, true)
|
tag, err = lib14a.read(false, true)
|
||||||
if not tag then return oops(err) end
|
if not tag then return oops(err) end
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
-- simple tag check
|
-- simple tag check
|
||||||
if 0x09 ~= tag.sak then
|
if 0x09 ~= tag.sak then
|
||||||
if 0x4400 ~= tag.atqa then
|
if 0x4400 ~= tag.atqa then
|
||||||
return oops(('[fail] found tag %s :: looking for Mifare Mini 0.3k'):format(tag.name))
|
return oops(('[fail] found tag %s :: looking for Mifare Mini 0.3k'):format(tag.name))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
dbg ('[ok] found '..tag.name)
|
dbg ('[ok] found '..tag.name)
|
||||||
|
|
||||||
-- tag key
|
-- tag key
|
||||||
mfkey = keygen(tag.uid)
|
mfkey = keygen(tag.uid)
|
||||||
dbg('[ok] using mf keyA : '.. mfkey)
|
dbg('[ok] using mf keyA : '.. mfkey)
|
||||||
|
|
||||||
-- AES key
|
-- AES key
|
||||||
aeskey = create_key(tag.uid)
|
aeskey = create_key(tag.uid)
|
||||||
dbg('[ok] using AES key : '.. aeskey)
|
dbg('[ok] using AES key : '.. aeskey)
|
||||||
|
|
||||||
-- read tag data, complete, enc/dec
|
-- read tag data, complete, enc/dec
|
||||||
tagdata = readtag(mfkey, aeskey)
|
tagdata = readtag(mfkey, aeskey)
|
||||||
dbg('[ok] read card data')
|
dbg('[ok] read card data')
|
||||||
|
|
||||||
-- show information?
|
-- show information?
|
||||||
print_info(tagdata)
|
print_info(tagdata)
|
||||||
|
|
||||||
-- save
|
-- save
|
||||||
res = save_json(nil, tagdata)
|
res = save_json(nil, tagdata)
|
||||||
if not res then return oops('[fail] saving json file') end
|
if not res then return oops('[fail] saving json file') end
|
||||||
|
|
||||||
dbg('[ok] read card data')
|
dbg('[ok] read card data')
|
||||||
end
|
end
|
||||||
|
|
||||||
main(args)
|
main(args)
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ This script takes a dumpfile from 'hf mfu dump' and converts it to a format that
|
|||||||
by the emulator
|
by the emulator
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h This help
|
-h This help
|
||||||
-i <file> Specifies the dump-file (input). If omitted, 'dumpdata.bin' is used
|
-i <file> Specifies the dump-file (input). If omitted, 'dumpdata.bin' is used
|
||||||
-o <filename> Specifies the output file. If omitted, <uid>.eml is used.
|
-o <filename> Specifies the output file. If omitted, <uid>.eml is used.
|
||||||
|
|
||||||
]]
|
]]
|
||||||
local DEBUG = false
|
local DEBUG = false
|
||||||
@@ -23,105 +23,105 @@ local DEBUG = false
|
|||||||
---
|
---
|
||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
local function dbg(args)
|
local function dbg(args)
|
||||||
if not DEBUG then return end
|
if not DEBUG then return end
|
||||||
|
|
||||||
if type(args) == 'table' then
|
if type(args) == 'table' then
|
||||||
local i = 1
|
local i = 1
|
||||||
while result[i] do
|
while result[i] do
|
||||||
dbg(result[i])
|
dbg(result[i])
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print('###', args)
|
print('###', args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print('ERROR: ',err)
|
print('ERROR: ',err)
|
||||||
return nil,err
|
return nil,err
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
function help()
|
function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print(author)
|
print(author)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function convert_to_ascii(hexdata)
|
local function convert_to_ascii(hexdata)
|
||||||
if string.len(hexdata) % 8 ~= 0 then
|
if string.len(hexdata) % 8 ~= 0 then
|
||||||
return oops(("Bad data, length should be a multiple of 8 (was %d)"):format(string.len(hexdata)))
|
return oops(("Bad data, length should be a multiple of 8 (was %d)"):format(string.len(hexdata)))
|
||||||
end
|
end
|
||||||
|
|
||||||
local js,i = "[";
|
local js,i = "[";
|
||||||
for i = 1, string.len(hexdata),8 do
|
for i = 1, string.len(hexdata),8 do
|
||||||
js = js .."'" ..string.sub(hexdata,i,i+7).."',\n"
|
js = js .."'" ..string.sub(hexdata,i,i+7).."',\n"
|
||||||
end
|
end
|
||||||
js = js .. "]"
|
js = js .. "]"
|
||||||
return js
|
return js
|
||||||
end
|
end
|
||||||
|
|
||||||
local function readdump(infile)
|
local function readdump(infile)
|
||||||
t = infile:read("*all")
|
t = infile:read("*all")
|
||||||
len = string.len(t)
|
len = string.len(t)
|
||||||
local len,hex = bin.unpack(("H%d"):format(len),t)
|
local len,hex = bin.unpack(("H%d"):format(len),t)
|
||||||
return hex
|
return hex
|
||||||
end
|
end
|
||||||
|
|
||||||
local function convert_to_emulform(hexdata)
|
local function convert_to_emulform(hexdata)
|
||||||
if string.len(hexdata) % 8 ~= 0 then
|
if string.len(hexdata) % 8 ~= 0 then
|
||||||
return oops(("Bad data, length should be a multiple of 8 (was %d)"):format(string.len(hexdata)))
|
return oops(("Bad data, length should be a multiple of 8 (was %d)"):format(string.len(hexdata)))
|
||||||
end
|
end
|
||||||
local ascii,i = "";
|
local ascii,i = "";
|
||||||
for i = 1, string.len(hexdata), 8 do
|
for i = 1, string.len(hexdata), 8 do
|
||||||
ascii = ascii..string.sub(hexdata, i, i+7).."\n"
|
ascii = ascii..string.sub(hexdata, i, i+7).."\n"
|
||||||
end
|
end
|
||||||
return string.sub(ascii, 1, -2)
|
return string.sub(ascii, 1, -2)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
local input = "dumpdata.bin"
|
local input = "dumpdata.bin"
|
||||||
local output
|
local output
|
||||||
|
|
||||||
for o, a in getopt.getopt(args, 'i:o:h') do
|
for o, a in getopt.getopt(args, 'i:o:h') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
if o == "i" then input = a end
|
if o == "i" then input = a end
|
||||||
if o == "o" then output = a end
|
if o == "o" then output = a end
|
||||||
end
|
end
|
||||||
-- Validate the parameters
|
-- Validate the parameters
|
||||||
|
|
||||||
local infile = io.open(input, "rb")
|
local infile = io.open(input, "rb")
|
||||||
if infile == nil then
|
if infile == nil then
|
||||||
return oops("Could not read file ", input)
|
return oops("Could not read file ", input)
|
||||||
end
|
end
|
||||||
local dumpdata = readdump(infile)
|
local dumpdata = readdump(infile)
|
||||||
-- The hex-data is now in ascii-format,
|
-- The hex-data is now in ascii-format,
|
||||||
|
|
||||||
-- But first, check the uid
|
-- But first, check the uid
|
||||||
-- lua uses start index and endindex, not count.
|
-- lua uses start index and endindex, not count.
|
||||||
-- UID is 3three skip bcc0 then 4bytes.
|
-- UID is 3three skip bcc0 then 4bytes.
|
||||||
-- 1 lua is one-index.
|
-- 1 lua is one-index.
|
||||||
-- 1 + 96 (48*2) new dump format has version/signature/counter data here
|
-- 1 + 96 (48*2) new dump format has version/signature/counter data here
|
||||||
-- 97,98,99,100,101,102 UID first three bytes
|
-- 97,98,99,100,101,102 UID first three bytes
|
||||||
-- 103,104 bcc0
|
-- 103,104 bcc0
|
||||||
-- 105--- UID last four bytes
|
-- 105--- UID last four bytes
|
||||||
local uid = string.sub(dumpdata, 97, 97+5)..string.sub(dumpdata, 97+8, 97+8+7)
|
local uid = string.sub(dumpdata, 97, 97+5)..string.sub(dumpdata, 97+8, 97+8+7)
|
||||||
output = output or (uid .. ".eml")
|
output = output or (uid .. ".eml")
|
||||||
|
|
||||||
-- Format some linebreaks
|
-- Format some linebreaks
|
||||||
dumpdata = convert_to_emulform(dumpdata)
|
dumpdata = convert_to_emulform(dumpdata)
|
||||||
|
|
||||||
local outfile = io.open(output, "w")
|
local outfile = io.open(output, "w")
|
||||||
if outfile == nil then
|
if outfile == nil then
|
||||||
return oops("Could not write to file ", output)
|
return oops("Could not write to file ", output)
|
||||||
end
|
end
|
||||||
|
|
||||||
outfile:write(dumpdata:lower())
|
outfile:write(dumpdata:lower())
|
||||||
io.close(outfile)
|
io.close(outfile)
|
||||||
print(("Wrote an emulator-dump to the file %s"):format(output))
|
print(("Wrote an emulator-dump to the file %s"):format(output))
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ This script takes a dumpfile from 'hf mf dump' and converts it to a format that
|
|||||||
by the emulator
|
by the emulator
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h This help
|
-h This help
|
||||||
-i <file> Specifies the dump-file (input). If omitted, 'dumpdata.bin' is used
|
-i <file> Specifies the dump-file (input). If omitted, 'dumpdata.bin' is used
|
||||||
-o <filename> Specifies the output file. If omitted, <uid>.eml is used.
|
-o <filename> Specifies the output file. If omitted, <uid>.eml is used.
|
||||||
|
|
||||||
]]
|
]]
|
||||||
local DEBUG = false
|
local DEBUG = false
|
||||||
@@ -24,98 +24,98 @@ local DEBUG = false
|
|||||||
---
|
---
|
||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
local function dbg(args)
|
local function dbg(args)
|
||||||
if not DEBUG then return end
|
if not DEBUG then return end
|
||||||
|
|
||||||
if type(args) == 'table' then
|
if type(args) == 'table' then
|
||||||
local i = 1
|
local i = 1
|
||||||
while result[i] do
|
while result[i] do
|
||||||
dbg(result[i])
|
dbg(result[i])
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print('###', args)
|
print('###', args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print('ERROR: ',err)
|
print('ERROR: ',err)
|
||||||
return nil,err
|
return nil,err
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
function help()
|
function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print(author)
|
print(author)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function convert_to_ascii(hexdata)
|
local function convert_to_ascii(hexdata)
|
||||||
if string.len(hexdata) % 32 ~= 0 then
|
if string.len(hexdata) % 32 ~= 0 then
|
||||||
return oops(("Bad data, length should be a multiple of 32 (was %d)"):format(string.len(hexdata)))
|
return oops(("Bad data, length should be a multiple of 32 (was %d)"):format(string.len(hexdata)))
|
||||||
end
|
end
|
||||||
|
|
||||||
local js,i = "[";
|
local js,i = "[";
|
||||||
for i = 1, string.len(hexdata),32 do
|
for i = 1, string.len(hexdata),32 do
|
||||||
js = js .."'" ..string.sub(hexdata,i,i+31).."',\n"
|
js = js .."'" ..string.sub(hexdata,i,i+31).."',\n"
|
||||||
end
|
end
|
||||||
js = js .. "]"
|
js = js .. "]"
|
||||||
return js
|
return js
|
||||||
end
|
end
|
||||||
|
|
||||||
local function readdump(infile)
|
local function readdump(infile)
|
||||||
t = infile:read("*all")
|
t = infile:read("*all")
|
||||||
len = string.len(t)
|
len = string.len(t)
|
||||||
local len,hex = bin.unpack(("H%d"):format(len),t)
|
local len,hex = bin.unpack(("H%d"):format(len),t)
|
||||||
return hex
|
return hex
|
||||||
end
|
end
|
||||||
|
|
||||||
local function convert_to_emulform(hexdata)
|
local function convert_to_emulform(hexdata)
|
||||||
if string.len(hexdata) % 32 ~= 0 then
|
if string.len(hexdata) % 32 ~= 0 then
|
||||||
return oops(("Bad data, length should be a multiple of 32 (was %d)"):format(string.len(hexdata)))
|
return oops(("Bad data, length should be a multiple of 32 (was %d)"):format(string.len(hexdata)))
|
||||||
end
|
end
|
||||||
local ascii,i = "";
|
local ascii,i = "";
|
||||||
for i = 1, string.len(hexdata),32 do
|
for i = 1, string.len(hexdata),32 do
|
||||||
ascii = ascii..string.sub(hexdata,i,i+31).."\n"
|
ascii = ascii..string.sub(hexdata,i,i+31).."\n"
|
||||||
end
|
end
|
||||||
return string.sub(ascii, 1, -2)
|
return string.sub(ascii, 1, -2)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
local input = "dumpdata.bin"
|
local input = "dumpdata.bin"
|
||||||
local output
|
local output
|
||||||
|
|
||||||
for o, a in getopt.getopt(args, 'i:o:h') do
|
for o, a in getopt.getopt(args, 'i:o:h') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
if o == "i" then input = a end
|
if o == "i" then input = a end
|
||||||
if o == "o" then output = a end
|
if o == "o" then output = a end
|
||||||
end
|
end
|
||||||
-- Validate the parameters
|
-- Validate the parameters
|
||||||
|
|
||||||
local infile = io.open(input, "rb")
|
local infile = io.open(input, "rb")
|
||||||
if infile == nil then
|
if infile == nil then
|
||||||
return oops("Could not read file ", input)
|
return oops("Could not read file ", input)
|
||||||
end
|
end
|
||||||
local dumpdata = readdump(infile)
|
local dumpdata = readdump(infile)
|
||||||
-- The hex-data is now in ascii-format,
|
-- The hex-data is now in ascii-format,
|
||||||
|
|
||||||
-- But first, check the uid
|
-- But first, check the uid
|
||||||
local uid = string.sub(dumpdata,1,8)
|
local uid = string.sub(dumpdata,1,8)
|
||||||
output = output or (uid .. ".eml")
|
output = output or (uid .. ".eml")
|
||||||
|
|
||||||
-- Format some linebreaks
|
-- Format some linebreaks
|
||||||
dumpdata = convert_to_emulform(dumpdata)
|
dumpdata = convert_to_emulform(dumpdata)
|
||||||
|
|
||||||
local outfile = io.open(output, "w")
|
local outfile = io.open(output, "w")
|
||||||
if outfile == nil then
|
if outfile == nil then
|
||||||
return oops("Could not write to file ", output)
|
return oops("Could not write to file ", output)
|
||||||
end
|
end
|
||||||
|
|
||||||
outfile:write(dumpdata:lower())
|
outfile:write(dumpdata:lower())
|
||||||
io.close(outfile)
|
io.close(outfile)
|
||||||
print(("Wrote an emulator-dump to the file %s"):format(output))
|
print(("Wrote an emulator-dump to the file %s"):format(output))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,70 +8,70 @@ desc =
|
|||||||
This script calculates many checksums (CRC) over the provided hex input.
|
This script calculates many checksums (CRC) over the provided hex input.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-b data in hex
|
-b data in hex
|
||||||
-w bitwidth of the CRC family of algorithm. <optional> defaults to all known CRC presets.
|
-w bitwidth of the CRC family of algorithm. <optional> defaults to all known CRC presets.
|
||||||
Examples :
|
Examples :
|
||||||
script run e -b 010203040506070809
|
script run e -b 010203040506070809
|
||||||
script run e -b 010203040506070809 -w 16
|
script run e -b 010203040506070809 -w 16
|
||||||
]]
|
]]
|
||||||
|
|
||||||
---
|
---
|
||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
function dbg(args)
|
function dbg(args)
|
||||||
if DEBUG then
|
if DEBUG then
|
||||||
print("###", args)
|
print("###", args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- 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)
|
||||||
print("[!] ERROR: ",err)
|
print("[!] ERROR: ",err)
|
||||||
return nil,err
|
return nil,err
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
function help()
|
function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- The main entry point
|
-- The main entry point
|
||||||
function main(args)
|
function main(args)
|
||||||
|
|
||||||
local data
|
local data
|
||||||
local width = 0
|
local width = 0
|
||||||
|
|
||||||
-- Read the parameters
|
-- Read the parameters
|
||||||
for o, a in getopt.getopt(args, 'hb:w:') do
|
for o, a in getopt.getopt(args, 'hb:w:') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
if o == "b" then data = a end
|
if o == "b" then data = a end
|
||||||
if o == "w" then width = a end
|
if o == "w" then width = a end
|
||||||
end
|
end
|
||||||
|
|
||||||
data = data or '01020304'
|
data = data or '01020304'
|
||||||
width = width or 0
|
width = width or 0
|
||||||
|
|
||||||
print( string.rep('-',60) )
|
print( string.rep('-',60) )
|
||||||
print('Bit width of CRC | '..width)
|
print('Bit width of CRC | '..width)
|
||||||
print('Bytes | '..data)
|
print('Bytes | '..data)
|
||||||
print('')
|
print('')
|
||||||
print( ('%-20s| %-16s| %s'):format('Model','CRC', 'CRC reverse','bigEnd', 'bigEnd','little','little'))
|
print( ('%-20s| %-16s| %s'):format('Model','CRC', 'CRC reverse','bigEnd', 'bigEnd','little','little'))
|
||||||
print( string.rep('-',60) )
|
print( string.rep('-',60) )
|
||||||
local lists, err = core.reveng_models(width)
|
local lists, err = core.reveng_models(width)
|
||||||
if lists == nil then return oops(err) end
|
if lists == nil then return oops(err) end
|
||||||
|
|
||||||
for _,i in pairs(lists) do
|
for _,i in pairs(lists) do
|
||||||
if string.len(i) > 1 then
|
if string.len(i) > 1 then
|
||||||
local a1 = core.reveng_runmodel(i, data, false, '0')
|
local a1 = core.reveng_runmodel(i, data, false, '0')
|
||||||
local a2 = core.reveng_runmodel(i, data, true, '0')
|
local a2 = core.reveng_runmodel(i, data, true, '0')
|
||||||
local a3 = core.reveng_runmodel(i, data, false, 'b')
|
local a3 = core.reveng_runmodel(i, data, false, 'b')
|
||||||
local a4 = core.reveng_runmodel(i, data, false, 'B')
|
local a4 = core.reveng_runmodel(i, data, false, 'B')
|
||||||
local a5 = core.reveng_runmodel(i, data, false, 'l')
|
local a5 = core.reveng_runmodel(i, data, false, 'l')
|
||||||
local a6 = core.reveng_runmodel(i, data, false, 'L')
|
local a6 = core.reveng_runmodel(i, data, false, 'L')
|
||||||
print( ('%-20s| %-16s| %-16s| %-16s| %-16s| %-16s| %-16s'):format(i, a1:upper(), a2:upper(),a3:upper(),a4:upper(),a5:upper(),a6:upper() ) )
|
print( ('%-20s| %-16s| %-16s| %-16s| %-16s| %-16s| %-16s'):format(i, a1:upper(), a2:upper(),a3:upper(),a4:upper(),a5:upper(),a6:upper() ) )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
main(args)
|
main(args)
|
||||||
@@ -3,9 +3,9 @@ local bin = require('bin')
|
|||||||
local dumplib = require('html_dumplib')
|
local dumplib = require('html_dumplib')
|
||||||
|
|
||||||
example =[[
|
example =[[
|
||||||
1. script run emul2dump
|
1. script run emul2dump
|
||||||
2. script run emul2dump -i myfile.eml
|
2. script run emul2dump -i myfile.eml
|
||||||
3. script run emul2dump -i myfile.eml -o myfile.bin
|
3. script run emul2dump -i myfile.eml -o myfile.bin
|
||||||
]]
|
]]
|
||||||
author = "Iceman"
|
author = "Iceman"
|
||||||
usage = "script run emul2dump [-i <file>] [-o <file>]"
|
usage = "script run emul2dump [-i <file>] [-o <file>]"
|
||||||
@@ -13,48 +13,48 @@ desc =[[
|
|||||||
This script takes an dumpfile on EML (ASCII) format and converts it to the PM3 dumpbin file to be used with "hf mf restore"
|
This script takes an dumpfile on EML (ASCII) format and converts it to the PM3 dumpbin file to be used with "hf mf restore"
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h This help
|
-h This help
|
||||||
-i <filename> Specifies the dump-file (input). If omitted, 'dumpdata.eml' is used
|
-i <filename> Specifies the dump-file (input). If omitted, 'dumpdata.eml' is used
|
||||||
-o <filename> Specifies the output file. If omitted, <currdate>.bin is used.
|
-o <filename> Specifies the output file. If omitted, <currdate>.bin is used.
|
||||||
]]
|
]]
|
||||||
|
|
||||||
---
|
---
|
||||||
-- 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)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
function help()
|
function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- Exit message
|
-- Exit message
|
||||||
function ExitMsg(msg)
|
function ExitMsg(msg)
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print(msg)
|
print(msg)
|
||||||
print()
|
print()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
local input = "dumpdata.eml"
|
local input = "dumpdata.eml"
|
||||||
local output = os.date("%Y-%m-%d_%H%M%S.bin");
|
local output = os.date("%Y-%m-%d_%H%M%S.bin");
|
||||||
|
|
||||||
-- Arguments for the script
|
-- Arguments for the script
|
||||||
for o, a in getopt.getopt(args, 'hi:o:') do
|
for o, a in getopt.getopt(args, 'hi:o:') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
if o == "i" then input = a end
|
if o == "i" then input = a end
|
||||||
if o == "o" then output = a end
|
if o == "o" then output = a end
|
||||||
end
|
end
|
||||||
|
|
||||||
local filename, err = dumplib.convert_eml_to_bin(input,output)
|
local filename, err = dumplib.convert_eml_to_bin(input,output)
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
|
|
||||||
ExitMsg(("Wrote a BIN dump to the file %s"):format(filename))
|
ExitMsg(("Wrote a BIN dump to the file %s"):format(filename))
|
||||||
end
|
end
|
||||||
|
|
||||||
main(args)
|
main(args)
|
||||||
@@ -12,9 +12,9 @@ This script takes a dumpfile on EML (ASCII) format and produces a html based dum
|
|||||||
bit more easily analyzed.
|
bit more easily analyzed.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h This help
|
-h This help
|
||||||
-i <file> Specifies the dump-file (input). If omitted, 'dumpdata.eml' is used
|
-i <file> Specifies the dump-file (input). If omitted, 'dumpdata.eml' is used
|
||||||
-o <filename> Speciies the output file. If omitted, <curdate>.html is used.
|
-o <filename> Speciies the output file. If omitted, <curdate>.html is used.
|
||||||
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
@@ -25,38 +25,38 @@ Arguments:
|
|||||||
---
|
---
|
||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
function dbg(args)
|
function dbg(args)
|
||||||
if DEBUG then
|
if DEBUG then
|
||||||
print("###", args)
|
print("###", args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- 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)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
function help()
|
function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
local input = "dumpdata.eml"
|
local input = "dumpdata.eml"
|
||||||
local output = os.date("%Y-%m-%d_%H%M%S.html");
|
local output = os.date("%Y-%m-%d_%H%M%S.html");
|
||||||
for o, a in getopt.getopt(args, 'i:o:h') do
|
for o, a in getopt.getopt(args, 'i:o:h') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
if o == "i" then input = a end
|
if o == "i" then input = a end
|
||||||
if o == "o" then output = a end
|
if o == "o" then output = a end
|
||||||
end
|
end
|
||||||
local filename, err = dumplib.convert_eml_to_html(input,output)
|
local filename, err = dumplib.convert_eml_to_html(input,output)
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
|
|
||||||
print(("Wrote a HTML dump to the file %s"):format(filename))
|
print(("Wrote a HTML dump to the file %s"):format(filename))
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ local utils = require('utils')
|
|||||||
|
|
||||||
example = [[
|
example = [[
|
||||||
-- generate commands
|
-- generate commands
|
||||||
1. script run formatMifare
|
1. script run formatMifare
|
||||||
|
|
||||||
-- generate command, replacing key with new key.
|
-- generate command, replacing key with new key.
|
||||||
2. script run formatMifare -k aabbccddeeff -n 112233445566 -a FF0780
|
2. script run formatMifare -k aabbccddeeff -n 112233445566 -a FF0780
|
||||||
|
|
||||||
-- generate commands and excute them against card.
|
-- generate commands and excute them against card.
|
||||||
3. script run formatMifare -x
|
3. script run formatMifare -x
|
||||||
]]
|
]]
|
||||||
copyright = ''
|
copyright = ''
|
||||||
version = ''
|
version = ''
|
||||||
@@ -32,11 +32,11 @@ The script will skip the manufactoring block 0.
|
|||||||
|
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h - this help
|
-h - this help
|
||||||
-k <key> - the current six byte key with write access
|
-k <key> - the current six byte key with write access
|
||||||
-n <key> - the new key that will be written to the card
|
-n <key> - the new key that will be written to the card
|
||||||
-a <access> - the new access bytes that will be written to the card
|
-a <access> - the new access bytes that will be written to the card
|
||||||
-x - execute the commands aswell.
|
-x - execute the commands aswell.
|
||||||
]]
|
]]
|
||||||
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
|
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
|
||||||
local DEBUG = true -- the debug flag
|
local DEBUG = true -- the debug flag
|
||||||
@@ -46,171 +46,171 @@ local numSectors = 16
|
|||||||
---
|
---
|
||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
function dbg(args)
|
function dbg(args)
|
||||||
if not DEBUG then
|
if not DEBUG then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if type(args) == "table" then
|
if type(args) == "table" then
|
||||||
local i = 1
|
local i = 1
|
||||||
while result[i] do
|
while result[i] do
|
||||||
dbg(result[i])
|
dbg(result[i])
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print("###", args)
|
print("###", args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- 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)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
function help()
|
function help()
|
||||||
print(copyright)
|
print(copyright)
|
||||||
print(author)
|
print(author)
|
||||||
print(version)
|
print(version)
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- Exit message
|
-- Exit message
|
||||||
function ExitMsg(msg)
|
function ExitMsg(msg)
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print(msg)
|
print(msg)
|
||||||
print()
|
print()
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- Read information from a card
|
-- Read information from a card
|
||||||
function GetCardInfo()
|
function GetCardInfo()
|
||||||
result, err = lib14a.read(false, true)
|
result, err = lib14a.read(false, true)
|
||||||
if not result then
|
if not result then
|
||||||
print(err)
|
print(err)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
print(("Found: %s"):format(result.name))
|
print(("Found: %s"):format(result.name))
|
||||||
|
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
if 0x18 == result.sak then -- NXP MIFARE Classic 4k | Plus 4k
|
if 0x18 == result.sak then -- NXP MIFARE Classic 4k | Plus 4k
|
||||||
-- IFARE Classic 4K offers 4096 bytes split into forty sectors,
|
-- IFARE Classic 4K offers 4096 bytes split into forty sectors,
|
||||||
-- of which 32 are same size as in the 1K with eight more that are quadruple size sectors.
|
-- of which 32 are same size as in the 1K with eight more that are quadruple size sectors.
|
||||||
numSectors = 40
|
numSectors = 40
|
||||||
elseif 0x08 == result.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k
|
elseif 0x08 == result.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k
|
||||||
-- 1K offers 1024 bytes of data storage, split into 16 sector
|
-- 1K offers 1024 bytes of data storage, split into 16 sector
|
||||||
numSectors = 16
|
numSectors = 16
|
||||||
elseif 0x09 == result.sak then -- NXP MIFARE Mini 0.3k
|
elseif 0x09 == result.sak then -- NXP MIFARE Mini 0.3k
|
||||||
-- MIFARE Classic mini offers 320 bytes split into five sectors.
|
-- MIFARE Classic mini offers 320 bytes split into five sectors.
|
||||||
numSectors = 5
|
numSectors = 5
|
||||||
elseif 0x10 == result.sak then -- NXP MIFARE Plus 2k
|
elseif 0x10 == result.sak then -- NXP MIFARE Plus 2k
|
||||||
numSectors = 32
|
numSectors = 32
|
||||||
elseif 0x01 == result.sak then -- NXP MIFARE TNP3xxx 1K
|
elseif 0x01 == result.sak then -- NXP MIFARE TNP3xxx 1K
|
||||||
numSectors = 16
|
numSectors = 16
|
||||||
else
|
else
|
||||||
print("I don't know how many sectors there are on this type of card, defaulting to 16")
|
print("I don't know how many sectors there are on this type of card, defaulting to 16")
|
||||||
end
|
end
|
||||||
--[[
|
--[[
|
||||||
The mifare Classic 1k card has 16 sectors of 4 data blocks each.
|
The mifare Classic 1k card has 16 sectors of 4 data blocks each.
|
||||||
The first 32 sectors of a mifare Classic 4k card consists of 4 data blocks and the remaining
|
The first 32 sectors of a mifare Classic 4k card consists of 4 data blocks and the remaining
|
||||||
8 sectors consist of 16 data blocks.
|
8 sectors consist of 16 data blocks.
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
-- Defaults to 16 * 4 = 64 - 1 = 63
|
-- Defaults to 16 * 4 = 64 - 1 = 63
|
||||||
numBlocks = numSectors * 4 - 1
|
numBlocks = numSectors * 4 - 1
|
||||||
|
|
||||||
if numSectors > 32 then
|
if numSectors > 32 then
|
||||||
numBlocks = 32*4+ (numSectors-32)*16 -1
|
numBlocks = 32*4+ (numSectors-32)*16 -1
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print()
|
print()
|
||||||
|
|
||||||
local OldKey, NewKey, Accessbytes
|
local OldKey, NewKey, Accessbytes
|
||||||
local x = false
|
local x = false
|
||||||
|
|
||||||
-- Arguments for the script
|
-- Arguments for the script
|
||||||
for o, a in getopt.getopt(args, 'hk:n:a:x') do
|
for o, a in getopt.getopt(args, 'hk:n:a:x') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
if o == "k" then OldKey = a end
|
if o == "k" then OldKey = a end
|
||||||
if o == "n" then NewKey = a end
|
if o == "n" then NewKey = a end
|
||||||
if o == "a" then Accessbytes = a end
|
if o == "a" then Accessbytes = a end
|
||||||
if o == "x" then x = true end
|
if o == "x" then x = true end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- validate input args.
|
-- validate input args.
|
||||||
OldKey = OldKey or 'FFFFFFFFFFFF'
|
OldKey = OldKey or 'FFFFFFFFFFFF'
|
||||||
if #(OldKey) ~= 12 then
|
if #(OldKey) ~= 12 then
|
||||||
return oops( string.format('Wrong length of write key (was %d) expected 12', #OldKey))
|
return oops( string.format('Wrong length of write key (was %d) expected 12', #OldKey))
|
||||||
end
|
end
|
||||||
|
|
||||||
NewKey = NewKey or 'FFFFFFFFFFFF'
|
NewKey = NewKey or 'FFFFFFFFFFFF'
|
||||||
if #(NewKey) ~= 12 then
|
if #(NewKey) ~= 12 then
|
||||||
return oops( string.format('Wrong length of new key (was %d) expected 12', #NewKey))
|
return oops( string.format('Wrong length of new key (was %d) expected 12', #NewKey))
|
||||||
end
|
end
|
||||||
|
|
||||||
--Accessbytes = Accessbytes or '787788'
|
--Accessbytes = Accessbytes or '787788'
|
||||||
Accessbytes = Accessbytes or 'FF0780'
|
Accessbytes = Accessbytes or 'FF0780'
|
||||||
if #(Accessbytes) ~= 6 then
|
if #(Accessbytes) ~= 6 then
|
||||||
return oops( string.format('Wrong length of accessbytes (was %d) expected 12', #Accessbytes))
|
return oops( string.format('Wrong length of accessbytes (was %d) expected 12', #Accessbytes))
|
||||||
end
|
end
|
||||||
|
|
||||||
GetCardInfo()
|
GetCardInfo()
|
||||||
|
|
||||||
-- Show info
|
-- Show info
|
||||||
print( string.format('Estimating number of blocks: %d', numBlocks))
|
print( string.format('Estimating number of blocks: %d', numBlocks))
|
||||||
print( string.format('Old key: %s', OldKey))
|
print( string.format('Old key: %s', OldKey))
|
||||||
print( string.format('New key: %s', NewKey))
|
print( string.format('New key: %s', NewKey))
|
||||||
print( string.format('New Access: %s', Accessbytes))
|
print( string.format('New Access: %s', Accessbytes))
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
|
|
||||||
-- Set new block data
|
-- Set new block data
|
||||||
local EMPTY_BL = string.rep('00',16)
|
local EMPTY_BL = string.rep('00',16)
|
||||||
local EMPTY_SECTORTRAIL = string.format('%s%s%s%s',NewKey,Accessbytes,'00',NewKey)
|
local EMPTY_SECTORTRAIL = string.format('%s%s%s%s',NewKey,Accessbytes,'00',NewKey)
|
||||||
|
|
||||||
dbg( string.format('New sector-trailer : %s',EMPTY_SECTORTRAIL))
|
dbg( string.format('New sector-trailer : %s',EMPTY_SECTORTRAIL))
|
||||||
dbg( string.format('New emptyblock: %s',EMPTY_BL))
|
dbg( string.format('New emptyblock: %s',EMPTY_BL))
|
||||||
dbg('')
|
dbg('')
|
||||||
|
|
||||||
if x then
|
if x then
|
||||||
print('[Warning] you have used the EXECUTE parameter, which means this will run these commands against card.')
|
print('[Warning] you have used the EXECUTE parameter, which means this will run these commands against card.')
|
||||||
end
|
end
|
||||||
-- Ask
|
-- Ask
|
||||||
local dialogResult = utils.confirm("Do you want to erase this card")
|
local dialogResult = utils.confirm("Do you want to erase this card")
|
||||||
if dialogResult == false then
|
if dialogResult == false then
|
||||||
return ExitMsg('Quiting it is then. Your wish is my command...')
|
return ExitMsg('Quiting it is then. Your wish is my command...')
|
||||||
end
|
end
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
|
|
||||||
-- main loop
|
-- main loop
|
||||||
for block=0,numBlocks,1 do
|
for block=0,numBlocks,1 do
|
||||||
|
|
||||||
local reminder = (block+1) % 4
|
local reminder = (block+1) % 4
|
||||||
local cmd
|
local cmd
|
||||||
if reminder == 0 then
|
if reminder == 0 then
|
||||||
cmd = CmdString:format(block, OldKey , EMPTY_SECTORTRAIL)
|
cmd = CmdString:format(block, OldKey , EMPTY_SECTORTRAIL)
|
||||||
else
|
else
|
||||||
cmd = CmdString:format(block, OldKey , EMPTY_BL)
|
cmd = CmdString:format(block, OldKey , EMPTY_BL)
|
||||||
end
|
end
|
||||||
|
|
||||||
if block ~= 0 then
|
if block ~= 0 then
|
||||||
print(cmd)
|
print(cmd)
|
||||||
if x then core.console(cmd) end
|
if x then core.console(cmd) end
|
||||||
end
|
end
|
||||||
|
|
||||||
if core.ukbhit() then
|
if core.ukbhit() then
|
||||||
print("aborted by user")
|
print("aborted by user")
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
main(args)
|
main(args)
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
local reader = require('hf_reader')
|
local reader = require('hf_reader')
|
||||||
|
|
||||||
local function main(args)
|
local function main(args)
|
||||||
print("WORK IN PROGRESS - not expected to be functional yet")
|
print("WORK IN PROGRESS - not expected to be functional yet")
|
||||||
info, err = reader.waitForTag()
|
info, err = reader.waitForTag()
|
||||||
|
|
||||||
if err then
|
if err then
|
||||||
print(err)
|
print(err)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local k,v
|
local k,v
|
||||||
print("Tag info")
|
print("Tag info")
|
||||||
for k,v in pairs(info) do
|
for k,v in pairs(info) do
|
||||||
print(string.format(" %s : %s", tostring(k), tostring(v)))
|
print(string.format(" %s : %s", tostring(k), tostring(v)))
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
main(args)
|
main(args)
|
||||||
@@ -12,9 +12,9 @@ This script takes a dumpfile and produces a html based dump, which is a
|
|||||||
bit more easily analyzed.
|
bit more easily analyzed.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h This help
|
-h This help
|
||||||
-i <file> Specifies the dump-file (input). If omitted, 'dumpdata.bin' is used
|
-i <file> Specifies the dump-file (input). If omitted, 'dumpdata.bin' is used
|
||||||
-o <filename> Speciies the output file. If omitted, <curtime>.html is used.
|
-o <filename> Speciies the output file. If omitted, <curtime>.html is used.
|
||||||
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
@@ -25,36 +25,36 @@ Arguments:
|
|||||||
---
|
---
|
||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
function dbg(args)
|
function dbg(args)
|
||||||
if DEBUG then
|
if DEBUG then
|
||||||
print("###", args)
|
print("###", args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- 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)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
function help()
|
function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
local input = "dumpdata.bin"
|
local input = "dumpdata.bin"
|
||||||
local output = os.date("%Y-%m-%d_%H%M%S.html");
|
local output = os.date("%Y-%m-%d_%H%M%S.html");
|
||||||
for o, a in getopt.getopt(args, 'i:o:h') do
|
for o, a in getopt.getopt(args, 'i:o:h') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
if o == "i" then input = a end
|
if o == "i" then input = a end
|
||||||
if o == "o" then output = a end
|
if o == "o" then output = a end
|
||||||
end
|
end
|
||||||
local filename, err = dumplib.convert_bin_to_html(input,output,16)
|
local filename, err = dumplib.convert_bin_to_html(input,output,16)
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
|
|
||||||
print(("Wrote a HTML dump to the file %s"):format(filename))
|
print(("Wrote a HTML dump to the file %s"):format(filename))
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
|
|||||||
@@ -12,19 +12,19 @@ Remember the UID ->MUST<- start with 0xE0
|
|||||||
]]
|
]]
|
||||||
example = [[
|
example = [[
|
||||||
|
|
||||||
-- ISO15693 slix magic tag
|
-- ISO15693 slix magic tag
|
||||||
|
|
||||||
script run iso15_magic -u E004013344556677
|
script run iso15_magic -u E004013344556677
|
||||||
|
|
||||||
script run iso15_magic -u E004013344556677 -a
|
script run iso15_magic -u E004013344556677 -a
|
||||||
]]
|
]]
|
||||||
usage = [[
|
usage = [[
|
||||||
script run iso15_magic -h -u <uid>
|
script run iso15_magic -h -u <uid>
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h : this help
|
-h : this help
|
||||||
-u <UID> : UID (16 hexsymbols)
|
-u <UID> : UID (16 hexsymbols)
|
||||||
-a : use offical pm3 repo ISO15 commands instead of iceman fork.
|
-a : use offical pm3 repo ISO15 commands instead of iceman fork.
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local DEBUG = true
|
local DEBUG = true
|
||||||
@@ -33,86 +33,86 @@ local DEBUG = true
|
|||||||
local function dbg(args)
|
local function dbg(args)
|
||||||
if not DEBUG then return end
|
if not DEBUG then return end
|
||||||
if type(args) == "table" then
|
if type(args) == "table" then
|
||||||
local i = 1
|
local i = 1
|
||||||
while args[i] do
|
while args[i] do
|
||||||
dbg(args[i])
|
dbg(args[i])
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print("###", args)
|
print("###", args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
return nil, err
|
return nil, err
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(copyright)
|
print(copyright)
|
||||||
print(author)
|
print(author)
|
||||||
print(version)
|
print(version)
|
||||||
print(desc)
|
print(desc)
|
||||||
print('Example usage')
|
print('Example usage')
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
--- Set UID on magic command enabled on a ICEMAN based REPO
|
--- Set UID on magic command enabled on a ICEMAN based REPO
|
||||||
local function magicUID_iceman(b0, b1)
|
local function magicUID_iceman(b0, b1)
|
||||||
print('Using backdoor Magic tag function')
|
print('Using backdoor Magic tag function')
|
||||||
core.console("hf 15 raw -2 -c 02213E00000000")
|
core.console("hf 15 raw -2 -c 02213E00000000")
|
||||||
core.console("hf 15 raw -2 -c 02213F69960000")
|
core.console("hf 15 raw -2 -c 02213F69960000")
|
||||||
core.console("hf 15 raw -2 -c 022138"..b1)
|
core.console("hf 15 raw -2 -c 022138"..b1)
|
||||||
core.console("hf 15 raw -2 -c 022139"..b0)
|
core.console("hf 15 raw -2 -c 022139"..b0)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
--- Set UID on magic command enabled, OFFICAL REPO
|
--- Set UID on magic command enabled, OFFICAL REPO
|
||||||
local function magicUID_offical(b0, b1)
|
local function magicUID_offical(b0, b1)
|
||||||
print('Using backdoor Magic tag function OFFICAL REPO')
|
print('Using backdoor Magic tag function OFFICAL REPO')
|
||||||
core.console("hf 15 cmd raw -c 02213E00000000")
|
core.console("hf 15 cmd raw -c 02213E00000000")
|
||||||
core.console("hf 15 cmd raw -c 02213F69960000")
|
core.console("hf 15 cmd raw -c 02213F69960000")
|
||||||
core.console("hf 15 cmd raw -c 022138"..b1)
|
core.console("hf 15 cmd raw -c 022138"..b1)
|
||||||
core.console("hf 15 cmd raw -c 022139"..b0)
|
core.console("hf 15 cmd raw -c 022139"..b0)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- The main entry point
|
-- The main entry point
|
||||||
function main(args)
|
function main(args)
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print()
|
print()
|
||||||
|
|
||||||
local uid = 'E004013344556677'
|
local uid = 'E004013344556677'
|
||||||
local use_iceman = true
|
local use_iceman = true
|
||||||
|
|
||||||
-- Read the parameters
|
-- Read the parameters
|
||||||
for o, a in getopt.getopt(args, 'hu:a') do
|
for o, a in getopt.getopt(args, 'hu:a') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
if o == "u" then uid = a end
|
if o == "u" then uid = a end
|
||||||
if o == "a" then use_iceman = false end
|
if o == "a" then use_iceman = false end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- uid string checks
|
-- uid string checks
|
||||||
if uid == nil then return oops('empty uid string') end
|
if uid == nil then return oops('empty uid string') end
|
||||||
if #uid == 0 then return oops('empty uid string') end
|
if #uid == 0 then return oops('empty uid string') end
|
||||||
if #uid ~= 16 then return oops('uid wrong length. Should be 8 hex bytes') end
|
if #uid ~= 16 then return oops('uid wrong length. Should be 8 hex bytes') end
|
||||||
|
|
||||||
local bytes = utils.ConvertHexToBytes(uid)
|
local bytes = utils.ConvertHexToBytes(uid)
|
||||||
|
|
||||||
local block0 = string.format('%02X%02X%02X%02X', bytes[4], bytes[3], bytes[2], bytes[1])
|
local block0 = string.format('%02X%02X%02X%02X', bytes[4], bytes[3], bytes[2], bytes[1])
|
||||||
local block1 = string.format('%02X%02X%02X%02X', bytes[8], bytes[7], bytes[6], bytes[5])
|
local block1 = string.format('%02X%02X%02X%02X', bytes[8], bytes[7], bytes[6], bytes[5])
|
||||||
|
|
||||||
print('new UID | '..uid)
|
print('new UID | '..uid)
|
||||||
|
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
if use_iceman then
|
if use_iceman then
|
||||||
magicUID_iceman(block0, block1)
|
magicUID_iceman(block0, block1)
|
||||||
else
|
else
|
||||||
magicUID_offical(block0, block1)
|
magicUID_offical(block0, block1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
main(args)
|
main(args)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -7,10 +7,10 @@ This is a script which writes value 0x01 to bytes from position 0x07 until 0xFF
|
|||||||
(created with 'hf legic save my_dump.hex')
|
(created with 'hf legic save my_dump.hex')
|
||||||
|
|
||||||
optional arguments :
|
optional arguments :
|
||||||
-h - Help text
|
-h - Help text
|
||||||
|
|
||||||
Examples :
|
Examples :
|
||||||
script run legic_buffer2card
|
script run legic_buffer2card
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local utils = require('utils')
|
local utils = require('utils')
|
||||||
@@ -18,37 +18,37 @@ local getopt = require('getopt')
|
|||||||
---
|
---
|
||||||
-- 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)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
return nil, err
|
return nil, err
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
function help()
|
function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- simple loop-write from 0x07 to 0xff
|
-- simple loop-write from 0x07 to 0xff
|
||||||
function main()
|
function main()
|
||||||
|
|
||||||
-- parse arguments for the script
|
-- parse arguments for the script
|
||||||
for o, a in getopt.getopt(args, 'h') do
|
for o, a in getopt.getopt(args, 'h') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
end
|
end
|
||||||
|
|
||||||
local cmd = ''
|
local cmd = ''
|
||||||
local i
|
local i
|
||||||
for i = 7, 255 do
|
for i = 7, 255 do
|
||||||
cmd = ('hf legic write 0x%02x 0x01'):format(i)
|
cmd = ('hf legic write 0x%02x 0x01'):format(i)
|
||||||
print(cmd)
|
print(cmd)
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
core.console(cmd)
|
core.console(cmd)
|
||||||
|
|
||||||
-- got a 'cmd-buffer overflow' on my mac - so just wait a little
|
-- got a 'cmd-buffer overflow' on my mac - so just wait a little
|
||||||
-- works without that pause on my linux-box
|
-- works without that pause on my linux-box
|
||||||
utils.Sleep(0.1)
|
utils.Sleep(0.1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -12,17 +12,17 @@ Perform bulk enrollment of 26 bit H10301 style RFID Tags
|
|||||||
For more info, check the comments in the code
|
For more info, check the comments in the code
|
||||||
]]
|
]]
|
||||||
example = [[
|
example = [[
|
||||||
--
|
--
|
||||||
script run lf_bulk.lua -f 1 -b 1000 -c 10
|
script run lf_bulk.lua -f 1 -b 1000 -c 10
|
||||||
]]
|
]]
|
||||||
usage = [[
|
usage = [[
|
||||||
script run lf_bulk.lua -f facility -b base_id_num -c count
|
script run lf_bulk.lua -f facility -b base_id_num -c count
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h : this help
|
-h : this help
|
||||||
-f : facility id
|
-f : facility id
|
||||||
-b : starting card id
|
-b : starting card id
|
||||||
-c : count, number of cards to make
|
-c : count, number of cards to make
|
||||||
]]
|
]]
|
||||||
local DEBUG = true
|
local DEBUG = true
|
||||||
--local bxor = bit32.bxor
|
--local bxor = bit32.bxor
|
||||||
@@ -33,38 +33,38 @@ local lshift = bit32.lshift
|
|||||||
local function dbg(args)
|
local function dbg(args)
|
||||||
if not DEBUG then return end
|
if not DEBUG then return end
|
||||||
if type(args) == "table" then
|
if type(args) == "table" then
|
||||||
local i = 1
|
local i = 1
|
||||||
while args[i] do
|
while args[i] do
|
||||||
dbg(args[i])
|
dbg(args[i])
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print("###", args)
|
print("###", args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
return nil,err
|
return nil,err
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(copyright)
|
print(copyright)
|
||||||
print(author)
|
print(author)
|
||||||
print(version)
|
print(version)
|
||||||
print(desc)
|
print(desc)
|
||||||
print('Example usage')
|
print('Example usage')
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Exit message
|
-- Exit message
|
||||||
local function exitMsg(msg)
|
local function exitMsg(msg)
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print(msg)
|
print(msg)
|
||||||
print()
|
print()
|
||||||
end
|
end
|
||||||
--[[Implement a function to simply visualize the bitstream in a text format
|
--[[Implement a function to simply visualize the bitstream in a text format
|
||||||
--This is especially helpful for troubleshooting bitwise math issues]]--
|
--This is especially helpful for troubleshooting bitwise math issues]]--
|
||||||
@@ -86,17 +86,17 @@ end
|
|||||||
default to this and so counting some ones is good enough for me
|
default to this and so counting some ones is good enough for me
|
||||||
]]--
|
]]--
|
||||||
local function evenparity(s)
|
local function evenparity(s)
|
||||||
local _, count = string.gsub(s, "1", "")
|
local _, count = string.gsub(s, "1", "")
|
||||||
local p = count % 2
|
local p = count % 2
|
||||||
if (p == 0) then
|
if (p == 0) then
|
||||||
return false
|
return false
|
||||||
else
|
else
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function isempty(s)
|
local function isempty(s)
|
||||||
return s == nil or s == ''
|
return s == nil or s == ''
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
@@ -105,89 +105,89 @@ end
|
|||||||
hex. This should be easy enough to extend to non 26bit formats
|
hex. This should be easy enough to extend to non 26bit formats
|
||||||
]]--
|
]]--
|
||||||
local function cardHex(i, f)
|
local function cardHex(i, f)
|
||||||
fac = lshift(f, 16)
|
fac = lshift(f, 16)
|
||||||
id = bor(i, fac)
|
id = bor(i, fac)
|
||||||
stream = toBits(id, 24)
|
stream = toBits(id, 24)
|
||||||
|
|
||||||
--As the function defaults to even parity and returns a boolean,
|
--As the function defaults to even parity and returns a boolean,
|
||||||
--perform a 'not' function to get odd parity
|
--perform a 'not' function to get odd parity
|
||||||
high = evenparity(string.sub(stream,1,12)) and 1 or 0
|
high = evenparity(string.sub(stream,1,12)) and 1 or 0
|
||||||
low = not evenparity(string.sub(stream,13)) and 1 or 0
|
low = not evenparity(string.sub(stream,13)) and 1 or 0
|
||||||
bits = bor( lshift(id, 1), low)
|
bits = bor( lshift(id, 1), low)
|
||||||
bits = bor( bits, lshift(high, 25))
|
bits = bor( bits, lshift(high, 25))
|
||||||
|
|
||||||
--Since the lua library bit32 is (obviously) 32 bits and we need to
|
--Since the lua library bit32 is (obviously) 32 bits and we need to
|
||||||
--encode 36 bits to properly do a 26 bit tag with the preamble we need
|
--encode 36 bits to properly do a 26 bit tag with the preamble we need
|
||||||
--to create a higher order and lower order component which we will
|
--to create a higher order and lower order component which we will
|
||||||
--then assemble in the return. The math above defines the proper
|
--then assemble in the return. The math above defines the proper
|
||||||
--encoding as per HID/Weigand/etc. These bit flips are due to the
|
--encoding as per HID/Weigand/etc. These bit flips are due to the
|
||||||
--format length check on bit 38 (cmdlfhid.c:64) and
|
--format length check on bit 38 (cmdlfhid.c:64) and
|
||||||
--bit 31 (cmdlfhid.c:66).
|
--bit 31 (cmdlfhid.c:66).
|
||||||
preamble = bor(0, lshift(1, 5))
|
preamble = bor(0, lshift(1, 5))
|
||||||
bits = bor(bits, lshift(1, 26))
|
bits = bor(bits, lshift(1, 26))
|
||||||
|
|
||||||
return ("%04x%08x"):format(preamble, bits)
|
return ("%04x%08x"):format(preamble, bits)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- main
|
-- main
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print()
|
print()
|
||||||
|
|
||||||
if #args == 0 then return help() end
|
if #args == 0 then return help() end
|
||||||
|
|
||||||
--I really wish a better getopt function would be brought in supporting
|
--I really wish a better getopt function would be brought in supporting
|
||||||
--long arguments, but it seems this library was chosen for BSD style
|
--long arguments, but it seems this library was chosen for BSD style
|
||||||
--compatibility
|
--compatibility
|
||||||
for o, a in getopt.getopt(args, 'f:b:c:h') do
|
for o, a in getopt.getopt(args, 'f:b:c:h') do
|
||||||
if o == 'h' then return help() end
|
if o == 'h' then return help() end
|
||||||
if o == 'f' then
|
if o == 'f' then
|
||||||
if isempty(a) then
|
if isempty(a) then
|
||||||
print("You did not supply a facility code, using 0")
|
print("You did not supply a facility code, using 0")
|
||||||
facility = 0
|
facility = 0
|
||||||
else
|
else
|
||||||
facility = a
|
facility = a
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if o == 'b' then
|
if o == 'b' then
|
||||||
if isempty(a) then return oops("You must supply the flag -b (base id)") end
|
if isempty(a) then return oops("You must supply the flag -b (base id)") end
|
||||||
baseid = a
|
baseid = a
|
||||||
end
|
end
|
||||||
if o == 'c' then
|
if o == 'c' then
|
||||||
if isempty(a) then return oops("You must supply the flag -c (count)") end
|
if isempty(a) then return oops("You must supply the flag -c (count)") end
|
||||||
count = a
|
count = a
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--Due to my earlier complaints about how this specific getopt library
|
--Due to my earlier complaints about how this specific getopt library
|
||||||
--works, specifying ":" does not enforce supplying a value, thus we
|
--works, specifying ":" does not enforce supplying a value, thus we
|
||||||
--need to do these checks all over again.
|
--need to do these checks all over again.
|
||||||
if isempty(baseid) then return oops("You must supply the flag -b (base id)") end
|
if isempty(baseid) then return oops("You must supply the flag -b (base id)") end
|
||||||
if isempty(count) then return oops("You must supply the flag -c (count)") end
|
if isempty(count) then return oops("You must supply the flag -c (count)") end
|
||||||
|
|
||||||
--If the facility ID is non specified, ensure we code it as zero
|
--If the facility ID is non specified, ensure we code it as zero
|
||||||
if isempty(facility) then
|
if isempty(facility) then
|
||||||
print("Using 0 for the facility code as -f was not supplied")
|
print("Using 0 for the facility code as -f was not supplied")
|
||||||
facility = 0
|
facility = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
--The next baseid + count function presents a logic/UX conflict
|
--The next baseid + count function presents a logic/UX conflict
|
||||||
--where users specifying -c 1 (count = 1) would try to program two
|
--where users specifying -c 1 (count = 1) would try to program two
|
||||||
--tags. This makes it so that -c 0 & -c 1 both code one tag, and all
|
--tags. This makes it so that -c 0 & -c 1 both code one tag, and all
|
||||||
--other values encode the expected amount.
|
--other values encode the expected amount.
|
||||||
if tonumber(count) > 0 then count = count - 1 end
|
if tonumber(count) > 0 then count = count - 1 end
|
||||||
|
|
||||||
endid = baseid + count
|
endid = baseid + count
|
||||||
|
|
||||||
for cardnum = baseid, endid do
|
for cardnum = baseid, endid do
|
||||||
local card = cardHex(cardnum, facility)
|
local card = cardHex(cardnum, facility)
|
||||||
print("Press enter to program card "..cardnum..":"..facility.." (hex: "..card..")")
|
print("Press enter to program card "..cardnum..":"..facility.." (hex: "..card..")")
|
||||||
--This would be better with "press any key", but we'll take what we can get.
|
--This would be better with "press any key", but we'll take what we can get.
|
||||||
io.read()
|
io.read()
|
||||||
core.console( ('lf hid clone %s'):format(card) )
|
core.console( ('lf hid clone %s'):format(card) )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
main(args)
|
main(args)
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
--[[
|
--[[
|
||||||
This is an example of Lua-scripting within proxmark3. This is a lua-side
|
This is an example of Lua-scripting within proxmark3. This is a lua-side
|
||||||
implementation of hf mf chk
|
implementation of hf mf chk
|
||||||
|
|
||||||
This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||||
at your option, any later version. See the LICENSE.txt file for the text of
|
at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
the license.
|
the license.
|
||||||
|
|
||||||
Copyright (C) 2013 m h swende <martin at swende.se>
|
Copyright (C) 2013 m h swende <martin at swende.se>
|
||||||
--]]
|
--]]
|
||||||
-- Loads the commands-library
|
-- Loads the commands-library
|
||||||
local cmds = require('commands')
|
local cmds = require('commands')
|
||||||
@@ -19,7 +19,7 @@ local getopt = require('getopt')
|
|||||||
local utils = require('utils')
|
local utils = require('utils')
|
||||||
|
|
||||||
example =[[
|
example =[[
|
||||||
script run mfkeys
|
script run mfkeys
|
||||||
]]
|
]]
|
||||||
author = "Holiman"
|
author = "Holiman"
|
||||||
usage = "script run mfkeys"
|
usage = "script run mfkeys"
|
||||||
@@ -29,108 +29,108 @@ If you want to add more, just put them inside /lualibs/mf_default_keys.lua\n"):f
|
|||||||
[[
|
[[
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h : this help
|
-h : this help
|
||||||
-p : print keys
|
-p : print keys
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local TIMEOUT = 10000 -- 10 seconds
|
local TIMEOUT = 10000 -- 10 seconds
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print('ERROR: ',err)
|
print('ERROR: ',err)
|
||||||
return nil,err
|
return nil,err
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- waits for answer from pm3 device
|
-- waits for answer from pm3 device
|
||||||
local function checkCommand(command)
|
local function checkCommand(command)
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
local usb = command:getBytes()
|
local usb = command:getBytes()
|
||||||
core.SendCommand(usb)
|
core.SendCommand(usb)
|
||||||
local result = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT)
|
local result = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT)
|
||||||
if result then
|
if result then
|
||||||
local count, cmd, arg0 = bin.unpack('LL',result)
|
local count, cmd, arg0 = bin.unpack('LL',result)
|
||||||
if(arg0==1) then
|
if(arg0==1) then
|
||||||
local count, arg1, arg2, data = bin.unpack('LLH511',result,count)
|
local count, arg1, arg2, data = bin.unpack('LLH511',result,count)
|
||||||
key = data:sub(1,12)
|
key = data:sub(1,12)
|
||||||
return key
|
return key
|
||||||
else
|
else
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print("Timeout while waiting for response. Increase TIMEOUT in mfkeys.lua to wait longer")
|
print("Timeout while waiting for response. Increase TIMEOUT in mfkeys.lua to wait longer")
|
||||||
return nil, "Timeout while waiting for device to respond"
|
return nil, "Timeout while waiting for device to respond"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function checkBlock(blockno, testkeys, keytype)
|
local function checkBlock(blockno, testkeys, keytype)
|
||||||
|
|
||||||
-- The command data is only 512 bytes, each key is 6 bytes, meaning that we can send max 85 keys in one go.
|
-- The command data is only 512 bytes, each key is 6 bytes, meaning that we can send max 85 keys in one go.
|
||||||
-- If there's more, we need to split it up
|
-- If there's more, we need to split it up
|
||||||
local arg1 = bit32.bor(bit32.lshift(keytype, 8), blockno)
|
local arg1 = bit32.bor(bit32.lshift(keytype, 8), blockno)
|
||||||
|
|
||||||
local start, remaining = 1, #testkeys
|
local start, remaining = 1, #testkeys
|
||||||
local chunksize = remaining
|
local chunksize = remaining
|
||||||
if remaining > 85 then chunksize = 85 end
|
if remaining > 85 then chunksize = 85 end
|
||||||
local n = chunksize
|
local n = chunksize
|
||||||
|
|
||||||
while remaining > 0 do
|
while remaining > 0 do
|
||||||
--print('start', start, 'chunksize', chunksize, 'testkeys kvar', remaining, 'N-index=', n)
|
--print('start', start, 'chunksize', chunksize, 'testkeys kvar', remaining, 'N-index=', n)
|
||||||
|
|
||||||
local d1 = table.concat(testkeys, "", start, n)
|
local d1 = table.concat(testkeys, "", start, n)
|
||||||
|
|
||||||
print(("Testing block %d, keytype %d, with %d keys"):format(blockno, keytype, chunksize))
|
print(("Testing block %d, keytype %d, with %d keys"):format(blockno, keytype, chunksize))
|
||||||
local command = Command:new{cmd = cmds.CMD_MIFARE_CHKKEYS,
|
local command = Command:new{cmd = cmds.CMD_MIFARE_CHKKEYS,
|
||||||
arg1 = arg1,
|
arg1 = arg1,
|
||||||
arg2 = 0,
|
arg2 = 0,
|
||||||
arg3 = chunksize,
|
arg3 = chunksize,
|
||||||
data = d1}
|
data = d1}
|
||||||
local status = checkCommand(command)
|
local status = checkCommand(command)
|
||||||
if status then return status, blockno end
|
if status then return status, blockno end
|
||||||
start = start + chunksize
|
start = start + chunksize
|
||||||
remaining = remaining - chunksize
|
remaining = remaining - chunksize
|
||||||
|
|
||||||
if remaining < 85 then chunksize = remaining end
|
if remaining < 85 then chunksize = remaining end
|
||||||
n = n + chunksize
|
n = n + chunksize
|
||||||
end
|
end
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
-- A function to display the results
|
-- A function to display the results
|
||||||
local function display_results(keys)
|
local function display_results(keys)
|
||||||
local sector, keyA, keyB, succA, succB
|
local sector, keyA, keyB, succA, succB
|
||||||
print('')
|
print('')
|
||||||
print('|---|----------------|---|----------------|---|')
|
print('|---|----------------|---|----------------|---|')
|
||||||
print('|sec|key A |res|key B |res|')
|
print('|sec|key A |res|key B |res|')
|
||||||
print('|---|----------------|---|----------------|---|')
|
print('|---|----------------|---|----------------|---|')
|
||||||
|
|
||||||
for sector = 0, #keys do
|
for sector = 0, #keys do
|
||||||
succA, succB, keyA, keyB = unpack(keys[sector])
|
succA, succB, keyA, keyB = unpack(keys[sector])
|
||||||
print(('|%03d| %s | %s | %s | %s |'):format(sector, keyA, succA, keyB, succB))
|
print(('|%03d| %s | %s | %s | %s |'):format(sector, keyA, succA, keyB, succB))
|
||||||
end
|
end
|
||||||
print('|---|----------------|---|----------------|---|')
|
print('|---|----------------|---|----------------|---|')
|
||||||
end
|
end
|
||||||
-- A little helper to place an item first in the list
|
-- A little helper to place an item first in the list
|
||||||
local function placeFirst(akey, list)
|
local function placeFirst(akey, list)
|
||||||
akey = akey:lower()
|
akey = akey:lower()
|
||||||
if list[1] == akey then
|
if list[1] == akey then
|
||||||
-- Already at pole position
|
-- Already at pole position
|
||||||
return list
|
return list
|
||||||
end
|
end
|
||||||
local result = {akey}
|
local result = {akey}
|
||||||
--print(("Putting '%s' first"):format(akey))
|
--print(("Putting '%s' first"):format(akey))
|
||||||
for i,v in ipairs(list) do
|
for i,v in ipairs(list) do
|
||||||
if v ~= akey then
|
if v ~= akey then
|
||||||
result[#result+1] = v
|
result[#result+1] = v
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
--[[
|
--[[
|
||||||
The mifare Classic 1k card has 16 sectors of 4 data blocks each.
|
The mifare Classic 1k card has 16 sectors of 4 data blocks each.
|
||||||
@@ -139,137 +139,137 @@ The first 32 sectors of a mifare Classic 4k card consists of 4 data blocks and t
|
|||||||
--]]
|
--]]
|
||||||
local function get_blockno(s)
|
local function get_blockno(s)
|
||||||
|
|
||||||
local b, sector
|
local b, sector
|
||||||
|
|
||||||
if type(s) == 'string' then
|
if type(s) == 'string' then
|
||||||
sector = tonumber(s)
|
sector = tonumber(s)
|
||||||
else
|
else
|
||||||
sector = s
|
sector = s
|
||||||
end
|
end
|
||||||
|
|
||||||
if sector < 32 then
|
if sector < 32 then
|
||||||
b = sector * 4
|
b = sector * 4
|
||||||
else
|
else
|
||||||
b = 32 * 4 + (sector - 32) * 16
|
b = 32 * 4 + (sector - 32) * 16
|
||||||
end
|
end
|
||||||
return ('%02x'):format(b)
|
return ('%02x'):format(b)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- dumps all keys to file
|
-- dumps all keys to file
|
||||||
local function dumptofile(keys)
|
local function dumptofile(keys)
|
||||||
if utils.confirm('Do you wish to save the keys to dumpfile?') then
|
if utils.confirm('Do you wish to save the keys to dumpfile?') then
|
||||||
local destination = utils.input('Select a filename to store to', 'dumpkeys.bin')
|
local destination = utils.input('Select a filename to store to', 'dumpkeys.bin')
|
||||||
local file = io.open(destination, 'wb')
|
local file = io.open(destination, 'wb')
|
||||||
if file == nil then
|
if file == nil then
|
||||||
print('Could not write to file ', destination)
|
print('Could not write to file ', destination)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local key_a = ''
|
local key_a = ''
|
||||||
local key_b = ''
|
local key_b = ''
|
||||||
|
|
||||||
--for sector,_ in pairs(keys) do
|
--for sector,_ in pairs(keys) do
|
||||||
for sector = 0, #keys do
|
for sector = 0, #keys do
|
||||||
local succA, succB, keyA, keyB = unpack(keys[sector])
|
local succA, succB, keyA, keyB = unpack(keys[sector])
|
||||||
key_a = key_a .. bin.pack('H', keyA);
|
key_a = key_a .. bin.pack('H', keyA);
|
||||||
key_b = key_b .. bin.pack('H', keyB);
|
key_b = key_b .. bin.pack('H', keyB);
|
||||||
end
|
end
|
||||||
file:write(key_a)
|
file:write(key_a)
|
||||||
file:write(key_b)
|
file:write(key_b)
|
||||||
file:close()
|
file:close()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local function printkeys()
|
local function printkeys()
|
||||||
for i=1, #keylist do
|
for i=1, #keylist do
|
||||||
print(i, keylist[i])
|
print(i, keylist[i])
|
||||||
end
|
end
|
||||||
print ('Number of keys: '..#keylist)
|
print ('Number of keys: '..#keylist)
|
||||||
end
|
end
|
||||||
local function perform_check(numsectors)
|
local function perform_check(numsectors)
|
||||||
|
|
||||||
local keyType = 0 -- A=0, B=1
|
local keyType = 0 -- A=0, B=1
|
||||||
|
|
||||||
-- empty list of found keys
|
-- empty list of found keys
|
||||||
local keys = {}
|
local keys = {}
|
||||||
for i = 0, numsectors-1 do
|
for i = 0, numsectors-1 do
|
||||||
keys[i] = {0,0,'',''}
|
keys[i] = {0,0,'',''}
|
||||||
end
|
end
|
||||||
|
|
||||||
for sector = 0, #keys do
|
for sector = 0, #keys do
|
||||||
-- Check if user aborted
|
-- Check if user aborted
|
||||||
if core.ukbhit() then
|
if core.ukbhit() then
|
||||||
print('Aborted by user')
|
print('Aborted by user')
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
||||||
local targetblock = tonumber(get_blockno(sector), 16)
|
local targetblock = tonumber(get_blockno(sector), 16)
|
||||||
|
|
||||||
local succA, succB, keyA, keyB = unpack(keys[sector])
|
local succA, succB, keyA, keyB = unpack(keys[sector])
|
||||||
|
|
||||||
local keyA = checkBlock(targetblock, keylist, 0)
|
local keyA = checkBlock(targetblock, keylist, 0)
|
||||||
if keyA then succA = 1; keylist = placeFirst(keyA, keylist) end
|
if keyA then succA = 1; keylist = placeFirst(keyA, keylist) end
|
||||||
keyA = keyA or '------------'
|
keyA = keyA or '------------'
|
||||||
|
|
||||||
local keyB = checkBlock(targetblock, keylist, 1)
|
local keyB = checkBlock(targetblock, keylist, 1)
|
||||||
if keyB then succB = 1; keylist = placeFirst(keyB, keylist) end
|
if keyB then succB = 1; keylist = placeFirst(keyB, keylist) end
|
||||||
keyB = keyB or '------------'
|
keyB = keyB or '------------'
|
||||||
|
|
||||||
keys[sector] = {succA, succB, keyA, keyB}
|
keys[sector] = {succA, succB, keyA, keyB}
|
||||||
end
|
end
|
||||||
|
|
||||||
display_results(keys)
|
display_results(keys)
|
||||||
|
|
||||||
-- save to dumpkeys.bin
|
-- save to dumpkeys.bin
|
||||||
dumptofile(keys)
|
dumptofile(keys)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- shows tag information
|
-- shows tag information
|
||||||
local function taginfo(tag)
|
local function taginfo(tag)
|
||||||
|
|
||||||
local sectors = 16
|
local sectors = 16
|
||||||
-- Show tag info
|
-- Show tag info
|
||||||
print((' Found tag %s'):format(tag.name))
|
print((' Found tag %s'):format(tag.name))
|
||||||
|
|
||||||
if 0x18 == tag.sak then --NXP MIFARE Classic 4k | Plus 4k
|
if 0x18 == tag.sak then --NXP MIFARE Classic 4k | Plus 4k
|
||||||
-- MIFARE Classic 4K offers 4096 bytes split into forty sectors,
|
-- MIFARE Classic 4K offers 4096 bytes split into forty sectors,
|
||||||
-- of which 32 are same size as in the 1K with eight more that are quadruple size sectors.
|
-- of which 32 are same size as in the 1K with eight more that are quadruple size sectors.
|
||||||
sectors = 40
|
sectors = 40
|
||||||
elseif 0x08 == tag.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k
|
elseif 0x08 == tag.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k
|
||||||
-- 1K offers 1024 bytes of data storage, split into 16 sector
|
-- 1K offers 1024 bytes of data storage, split into 16 sector
|
||||||
sectors = 16
|
sectors = 16
|
||||||
elseif 0x09 == tag.sak then -- NXP MIFARE Mini 0.3k
|
elseif 0x09 == tag.sak then -- NXP MIFARE Mini 0.3k
|
||||||
-- MIFARE Classic mini offers 320 bytes split into five sectors.
|
-- MIFARE Classic mini offers 320 bytes split into five sectors.
|
||||||
sectors = 5
|
sectors = 5
|
||||||
elseif 0x10 == tag.sak then-- "NXP MIFARE Plus 2k"
|
elseif 0x10 == tag.sak then-- "NXP MIFARE Plus 2k"
|
||||||
sectors = 32
|
sectors = 32
|
||||||
else
|
else
|
||||||
print("I don't know how many sectors there are on this type of card, defaulting to 16")
|
print("I don't know how many sectors there are on this type of card, defaulting to 16")
|
||||||
end
|
end
|
||||||
return sectors
|
return sectors
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- The main entry point
|
-- The main entry point
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
local start_time = os.time()
|
local start_time = os.time()
|
||||||
local numSectors = 16
|
local numSectors = 16
|
||||||
|
|
||||||
-- Arguments for the script
|
-- Arguments for the script
|
||||||
for o, a in getopt.getopt(args, 'hp') do
|
for o, a in getopt.getopt(args, 'hp') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
if o == "p" then return printkeys() end
|
if o == "p" then return printkeys() end
|
||||||
end
|
end
|
||||||
-- identify tag
|
-- identify tag
|
||||||
tag, err = lib14a.read(false, true)
|
tag, err = lib14a.read(false, true)
|
||||||
if not tag then return oops(err) end
|
if not tag then return oops(err) end
|
||||||
|
|
||||||
-- detect sectors and print taginfo
|
-- detect sectors and print taginfo
|
||||||
numsectors = taginfo(tag)
|
numsectors = taginfo(tag)
|
||||||
|
|
||||||
perform_check(numsectors)
|
perform_check(numsectors)
|
||||||
|
|
||||||
local end_time = os.time()
|
local end_time = os.time()
|
||||||
print('mfkeys - Total execution time: '..os.difftime(end_time, start_time)..' sec')
|
print('mfkeys - Total execution time: '..os.difftime(end_time, start_time)..' sec')
|
||||||
end
|
end
|
||||||
|
|
||||||
main( args)
|
main( args)
|
||||||
@@ -11,8 +11,8 @@ usage = [[
|
|||||||
script run mifare_access -h -a <access bytes>
|
script run mifare_access -h -a <access bytes>
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h : this help
|
-h : this help
|
||||||
-a <access bytes> : 4 bytes ACCESS CONDITIONS
|
-a <access bytes> : 4 bytes ACCESS CONDITIONS
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local DEBUG = true
|
local DEBUG = true
|
||||||
@@ -25,30 +25,30 @@ local rshift = bit32.rshift
|
|||||||
local function dbg(args)
|
local function dbg(args)
|
||||||
if not DEBUG then return end
|
if not DEBUG then return end
|
||||||
if type(args) == "table" then
|
if type(args) == "table" then
|
||||||
local i = 1
|
local i = 1
|
||||||
while args[i] do
|
while args[i] do
|
||||||
dbg(args[i])
|
dbg(args[i])
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print("###", args)
|
print("###", args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
return nil, err
|
return nil, err
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(copyright)
|
print(copyright)
|
||||||
print(author)
|
print(author)
|
||||||
print(version)
|
print(version)
|
||||||
print(desc)
|
print(desc)
|
||||||
print('Example usage')
|
print('Example usage')
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
|
|
||||||
local access_condition_sector_trailer = {}
|
local access_condition_sector_trailer = {}
|
||||||
@@ -73,58 +73,58 @@ access_condition_data_block[0x7] = {'never','never','never','never'}
|
|||||||
|
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print()
|
print()
|
||||||
|
|
||||||
local access = ''
|
local access = ''
|
||||||
|
|
||||||
-- Read the parameters
|
-- Read the parameters
|
||||||
for o, a in getopt.getopt(args, 'ha:') do
|
for o, a in getopt.getopt(args, 'ha:') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
if o == "a" then access = a end
|
if o == "a" then access = a end
|
||||||
end
|
end
|
||||||
|
|
||||||
if access == nil then return oops('empty ACCESS CONDITIONS') end
|
if access == nil then return oops('empty ACCESS CONDITIONS') end
|
||||||
if #access == 0 then return oops('empty ACCESS CONDITIONS') end
|
if #access == 0 then return oops('empty ACCESS CONDITIONS') end
|
||||||
if #access ~= 8 then return oops("Wrong length. Should be 4 hex bytes ACCESS CONDITIONS (e.g. 7F0F0869)") end
|
if #access ~= 8 then return oops("Wrong length. Should be 4 hex bytes ACCESS CONDITIONS (e.g. 7F0F0869)") end
|
||||||
|
|
||||||
local c2_b = tonumber(string.sub(access, 1, 1), 16)
|
local c2_b = tonumber(string.sub(access, 1, 1), 16)
|
||||||
local c1_b = tonumber(string.sub(access, 2, 2), 16)
|
local c1_b = tonumber(string.sub(access, 2, 2), 16)
|
||||||
local c1 = tonumber(string.sub(access, 3, 3), 16)
|
local c1 = tonumber(string.sub(access, 3, 3), 16)
|
||||||
local c3_b = tonumber(string.sub(access, 4, 4), 16)
|
local c3_b = tonumber(string.sub(access, 4, 4), 16)
|
||||||
local c3 = tonumber(string.sub(access, 5, 5), 16)
|
local c3 = tonumber(string.sub(access, 5, 5), 16)
|
||||||
local c2 = tonumber(string.sub(access, 6, 6), 16)
|
local c2 = tonumber(string.sub(access, 6, 6), 16)
|
||||||
local gpb = string.sub(access, 7, 8)
|
local gpb = string.sub(access, 7, 8)
|
||||||
|
|
||||||
if bxor(c1, c1_b) ~= 0xF then print("!!! bitflip in c1") end
|
if bxor(c1, c1_b) ~= 0xF then print("!!! bitflip in c1") end
|
||||||
if bxor(c2, c2_b) ~= 0xF then print("!!! bitflip in c2") end
|
if bxor(c2, c2_b) ~= 0xF then print("!!! bitflip in c2") end
|
||||||
if bxor(c3, c3_b) ~= 0xF then print("!!! bitflip in c3") end
|
if bxor(c3, c3_b) ~= 0xF then print("!!! bitflip in c3") end
|
||||||
|
|
||||||
local ab = c1 * 256 + c2 * 16 + c3
|
local ab = c1 * 256 + c2 * 16 + c3
|
||||||
|
|
||||||
for block = 0,3 do
|
for block = 0,3 do
|
||||||
print("--> block "..block)
|
print("--> block "..block)
|
||||||
-- mask bits for block
|
-- mask bits for block
|
||||||
local abi = band(rshift(ab, block), 0x111)
|
local abi = band(rshift(ab, block), 0x111)
|
||||||
-- compress bits
|
-- compress bits
|
||||||
abi = band(abi + rshift(abi, 3) + rshift(abi, 6),7)
|
abi = band(abi + rshift(abi, 3) + rshift(abi, 6),7)
|
||||||
-- print(abi)
|
-- print(abi)
|
||||||
if block == 3 then
|
if block == 3 then
|
||||||
print(" KEYSECXA read: "..access_condition_sector_trailer[abi][1])
|
print(" KEYSECXA read: "..access_condition_sector_trailer[abi][1])
|
||||||
print(" KEYSECXA write: "..access_condition_sector_trailer[abi][2])
|
print(" KEYSECXA write: "..access_condition_sector_trailer[abi][2])
|
||||||
print(" ACCESS COND. read: "..access_condition_sector_trailer[abi][3])
|
print(" ACCESS COND. read: "..access_condition_sector_trailer[abi][3])
|
||||||
print("ACCESS COND. write: "..access_condition_sector_trailer[abi][4])
|
print("ACCESS COND. write: "..access_condition_sector_trailer[abi][4])
|
||||||
print(" KEYSECXB read: "..access_condition_sector_trailer[abi][5])
|
print(" KEYSECXB read: "..access_condition_sector_trailer[abi][5])
|
||||||
print(" KEYSECXB write: "..access_condition_sector_trailer[abi][6])
|
print(" KEYSECXB write: "..access_condition_sector_trailer[abi][6])
|
||||||
else
|
else
|
||||||
print(" read: "..access_condition_data_block[abi][1])
|
print(" read: "..access_condition_data_block[abi][1])
|
||||||
print(" write: "..access_condition_data_block[abi][2])
|
print(" write: "..access_condition_data_block[abi][2])
|
||||||
print(" inc: "..access_condition_data_block[abi][3])
|
print(" inc: "..access_condition_data_block[abi][3])
|
||||||
print("decr, transfer, restore: "..access_condition_data_block[abi][4])
|
print("decr, transfer, restore: "..access_condition_data_block[abi][4])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
print("GPB: "..gpb)
|
print("GPB: "..gpb)
|
||||||
end
|
end
|
||||||
main(args)
|
main(args)
|
||||||
|
|||||||
@@ -12,16 +12,16 @@ This is a script which automates cracking and dumping mifare classic cards. It s
|
|||||||
place by the device.
|
place by the device.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h this help
|
-h this help
|
||||||
-d debug logging on
|
-d debug logging on
|
||||||
-k known key for Sector 0 , keytype A
|
-k known key for Sector 0 , keytype A
|
||||||
|
|
||||||
|
|
||||||
Output files from this operation:
|
Output files from this operation:
|
||||||
<uid>.eml - emulator file
|
<uid>.eml - emulator file
|
||||||
<uid>.html - html file containing card data
|
<uid>.html - html file containing card data
|
||||||
dumpkeys.bin - keys are dumped here. OBS! This file is volatile, as other commands overwrite it sometimes.
|
dumpkeys.bin - keys are dumped here. OBS! This file is volatile, as other commands overwrite it sometimes.
|
||||||
dumpdata.bin - card data in binary form. OBS! This file is volatile, as other commands (hf mf dump) overwrite it.
|
dumpdata.bin - card data in binary form. OBS! This file is volatile, as other commands (hf mf dump) overwrite it.
|
||||||
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
@@ -32,182 +32,182 @@ local DEBUG = false
|
|||||||
---
|
---
|
||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
local function dbg(args)
|
local function dbg(args)
|
||||||
if not DEBUG then return end
|
if not DEBUG then return end
|
||||||
|
|
||||||
if type(args) == 'table' then
|
if type(args) == 'table' then
|
||||||
local i = 1
|
local i = 1
|
||||||
while result[i] do
|
while result[i] do
|
||||||
dbg(result[i])
|
dbg(result[i])
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print('###', args)
|
print('###', args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
return nil,err
|
return nil,err
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Waits for a mifare card to be placed within the vicinity of the reader.
|
-- Waits for a mifare card to be placed within the vicinity of the reader.
|
||||||
-- @return if successfull: an table containing card info
|
-- @return if successfull: an table containing card info
|
||||||
-- @return if unsuccessfull : nil, error
|
-- @return if unsuccessfull : nil, error
|
||||||
local function wait_for_mifare()
|
local function wait_for_mifare()
|
||||||
while not core.ukbhit() do
|
while not core.ukbhit() do
|
||||||
res, err = lib14a.read()
|
res, err = lib14a.read()
|
||||||
if res then return res end
|
if res then return res end
|
||||||
-- err means that there was no response from card
|
-- err means that there was no response from card
|
||||||
end
|
end
|
||||||
return nil, "Aborted by user"
|
return nil, "Aborted by user"
|
||||||
end
|
end
|
||||||
|
|
||||||
local function nested(key,sak)
|
local function nested(key,sak)
|
||||||
local typ = 1
|
local typ = 1
|
||||||
if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k | Ev1 4k
|
if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k | Ev1 4k
|
||||||
typ = 4
|
typ = 4
|
||||||
elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k | Ev1 1K
|
elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k | Ev1 1K
|
||||||
typ = 1
|
typ = 1
|
||||||
elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k
|
elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k
|
||||||
typ = 0
|
typ = 0
|
||||||
elseif 0x10 == sak then-- "NXP MIFARE Plus 2k"
|
elseif 0x10 == sak then-- "NXP MIFARE Plus 2k"
|
||||||
typ = 2
|
typ = 2
|
||||||
elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K"
|
elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K"
|
||||||
typ = 1
|
typ = 1
|
||||||
else
|
else
|
||||||
print("I don't know how many sectors there are on this type of card, defaulting to 16")
|
print("I don't know how many sectors there are on this type of card, defaulting to 16")
|
||||||
end
|
end
|
||||||
local cmd = string.format("hf mf nested %d 0 A %s d", typ, key)
|
local cmd = string.format("hf mf nested %d 0 A %s d", typ, key)
|
||||||
core.console(cmd)
|
core.console(cmd)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function dump(uid, numsectors)
|
local function dump(uid, numsectors)
|
||||||
dbg('dumping tag memory')
|
dbg('dumping tag memory')
|
||||||
|
|
||||||
local typ = 1
|
local typ = 1
|
||||||
if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k | Ev1 4k
|
if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k | Ev1 4k
|
||||||
typ = 4
|
typ = 4
|
||||||
elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k | Ev1 1K
|
elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k | Ev1 1K
|
||||||
typ = 1
|
typ = 1
|
||||||
elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k
|
elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k
|
||||||
typ = 0
|
typ = 0
|
||||||
elseif 0x10 == sak then-- "NXP MIFARE Plus 2k"
|
elseif 0x10 == sak then-- "NXP MIFARE Plus 2k"
|
||||||
typ = 2
|
typ = 2
|
||||||
elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K"
|
elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K"
|
||||||
typ = 1
|
typ = 1
|
||||||
end
|
end
|
||||||
|
|
||||||
if utils.confirm('Do you wish to create a memory dump of tag?') then
|
if utils.confirm('Do you wish to create a memory dump of tag?') then
|
||||||
|
|
||||||
local dumpfile = 'hf-mf-'..uid..'-data.bin'
|
local dumpfile = 'hf-mf-'..uid..'-data.bin'
|
||||||
|
|
||||||
local dmp = ('hf mf dump %s f %s'):format(typ, dumpfile)
|
local dmp = ('hf mf dump %s f %s'):format(typ, dumpfile)
|
||||||
core.console(dmp)
|
core.console(dmp)
|
||||||
|
|
||||||
-- Save the global args, those are *our* arguments
|
-- Save the global args, those are *our* arguments
|
||||||
local myargs = args
|
local myargs = args
|
||||||
-- Set the arguments for htmldump script
|
-- Set the arguments for htmldump script
|
||||||
args =('-i %s -o %s.html'):format(dumpfile, uid)
|
args =('-i %s -o %s.html'):format(dumpfile, uid)
|
||||||
-- call it
|
-- call it
|
||||||
require('htmldump')
|
require('htmldump')
|
||||||
|
|
||||||
-- dump to emulator
|
-- dump to emulator
|
||||||
args =('-i %s -o %s.eml'):format(dumpfile, uid)
|
args =('-i %s -o %s.eml'):format(dumpfile, uid)
|
||||||
require('dumptoemul')
|
require('dumptoemul')
|
||||||
|
|
||||||
-- Set back args. Not that it's used, just for the karma...
|
-- Set back args. Not that it's used, just for the karma...
|
||||||
args = myargs
|
args = myargs
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- performs a test if tag nonce uses weak or hardend prng
|
-- performs a test if tag nonce uses weak or hardend prng
|
||||||
local function perform_prng_test()
|
local function perform_prng_test()
|
||||||
local isweak = core.detect_prng()
|
local isweak = core.detect_prng()
|
||||||
if isweak == 1 then
|
if isweak == 1 then
|
||||||
dbg('PRNG detection : WEAK nonce detected')
|
dbg('PRNG detection : WEAK nonce detected')
|
||||||
elseif isweak == 0 then
|
elseif isweak == 0 then
|
||||||
dbg('PRNG detection : HARDEND nonce detected')
|
dbg('PRNG detection : HARDEND nonce detected')
|
||||||
else
|
else
|
||||||
dbg('PRNG detection : failed')
|
dbg('PRNG detection : failed')
|
||||||
end
|
end
|
||||||
return isweak
|
return isweak
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- The main entry point
|
-- The main entry point
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
local verbose, exit, res, uid, err, _, sak
|
local verbose, exit, res, uid, err, _, sak
|
||||||
local seen_uids = {}
|
local seen_uids = {}
|
||||||
local key = ''
|
local key = ''
|
||||||
local print_message = true
|
local print_message = true
|
||||||
-- Read the parameters
|
-- Read the parameters
|
||||||
for o, a in getopt.getopt(args, 'hdk:') do
|
for o, a in getopt.getopt(args, 'hdk:') do
|
||||||
if o == "h" then help() return end
|
if o == "h" then help() return end
|
||||||
if o == "d" then DEBUG = true end
|
if o == "d" then DEBUG = true end
|
||||||
if o == 'k' then key = a end
|
if o == 'k' then key = a end
|
||||||
end
|
end
|
||||||
|
|
||||||
while not exit do
|
while not exit do
|
||||||
if print_message then
|
if print_message then
|
||||||
print("Waiting for card or press any key to stop")
|
print("Waiting for card or press any key to stop")
|
||||||
print_message = false
|
print_message = false
|
||||||
end
|
end
|
||||||
res, err = wait_for_mifare()
|
res, err = wait_for_mifare()
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
-- Seen already?
|
-- Seen already?
|
||||||
uid = res.uid
|
uid = res.uid
|
||||||
sak = res.sak
|
sak = res.sak
|
||||||
|
|
||||||
if not seen_uids[uid] then
|
if not seen_uids[uid] then
|
||||||
-- Store it
|
-- Store it
|
||||||
seen_uids[uid] = uid
|
seen_uids[uid] = uid
|
||||||
|
|
||||||
-- check if PRNG is WEAK
|
-- check if PRNG is WEAK
|
||||||
if perform_prng_test() == 1 then
|
if perform_prng_test() == 1 then
|
||||||
print("Card found, commencing crack on UID", uid)
|
print("Card found, commencing crack on UID", uid)
|
||||||
|
|
||||||
if #key == 12 then
|
if #key == 12 then
|
||||||
print("Using key: "..key);
|
print("Using key: "..key);
|
||||||
else
|
else
|
||||||
-- Crack it
|
-- Crack it
|
||||||
local cnt
|
local cnt
|
||||||
err, res = core.mfDarkside()
|
err, res = core.mfDarkside()
|
||||||
if err == -1 then return oops("Button pressed. Aborted.")
|
if err == -1 then return oops("Button pressed. Aborted.")
|
||||||
elseif err == -2 then return oops("Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests).")
|
elseif err == -2 then return oops("Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests).")
|
||||||
elseif err == -3 then return oops("Card is not vulnerable to Darkside attack (its random number generator is not predictable).")
|
elseif err == -3 then return oops("Card is not vulnerable to Darkside attack (its random number generator is not predictable).")
|
||||||
elseif err == -4 then return oops([[
|
elseif err == -4 then return oops([[
|
||||||
Card is not vulnerable to Darkside attack (its random number generator seems to be based on the wellknown
|
Card is not vulnerable to Darkside attack (its random number generator seems to be based on the wellknown
|
||||||
generating polynomial with 16 effective bits only, but shows unexpected behaviour.]])
|
generating polynomial with 16 effective bits only, but shows unexpected behaviour.]])
|
||||||
elseif err == -5 then return oops("Aborted via keyboard.")
|
elseif err == -5 then return oops("Aborted via keyboard.")
|
||||||
end
|
end
|
||||||
-- The key is actually 8 bytes, so a
|
-- The key is actually 8 bytes, so a
|
||||||
-- 6-byte key is sent as 00XXXXXX
|
-- 6-byte key is sent as 00XXXXXX
|
||||||
-- This means we unpack it as first
|
-- This means we unpack it as first
|
||||||
-- two bytes, then six bytes actual key data
|
-- two bytes, then six bytes actual key data
|
||||||
-- We can discard first and second return values
|
-- We can discard first and second return values
|
||||||
_,_,key = bin.unpack("H2H6",res)
|
_,_,key = bin.unpack("H2H6",res)
|
||||||
print("Found valid key: "..key);
|
print("Found valid key: "..key);
|
||||||
end
|
end
|
||||||
-- Use nested attack
|
-- Use nested attack
|
||||||
nested(key, sak)
|
nested(key, sak)
|
||||||
-- Dump info
|
-- Dump info
|
||||||
dump(uid, sak)
|
dump(uid, sak)
|
||||||
|
|
||||||
if #key == 12 then exit = true end
|
if #key == 12 then exit = true end
|
||||||
else
|
else
|
||||||
print("Card found, darkside attack useless PRNG hardend on UID", uid)
|
print("Card found, darkside attack useless PRNG hardend on UID", uid)
|
||||||
end
|
end
|
||||||
print_message = true
|
print_message = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Call the main
|
-- Call the main
|
||||||
|
|||||||
@@ -9,15 +9,15 @@ desc =
|
|||||||
[[
|
[[
|
||||||
Purpose: Lua script to communicate with the Mifare Plus EV1, including personalization (setting the keys) and proximity check. Manually edit the file to add to the commands you can send the card.
|
Purpose: Lua script to communicate with the Mifare Plus EV1, including personalization (setting the keys) and proximity check. Manually edit the file to add to the commands you can send the card.
|
||||||
Please read the NXP manual before running this script to prevent making irreversible changes. Also note:
|
Please read the NXP manual before running this script to prevent making irreversible changes. Also note:
|
||||||
- The Mifare Plus must start in SL0 for personalization. Card can then be moved to SL1 or SL3.
|
- The Mifare Plus must start in SL0 for personalization. Card can then be moved to SL1 or SL3.
|
||||||
- The keys are hardcoded in the script to "00...". Unless you change this, only use this script for testing purposes.
|
- The keys are hardcoded in the script to "00...". Unless you change this, only use this script for testing purposes.
|
||||||
- Make sure you choose your card size correctly (2kB or 4kB).
|
- Make sure you choose your card size correctly (2kB or 4kB).
|
||||||
Small changes can be to made this script to communicate with the Mifare Plus S, X, or SE.
|
Small changes can be to made this script to communicate with the Mifare Plus S, X, or SE.
|
||||||
]]
|
]]
|
||||||
usage = [[
|
usage = [[
|
||||||
script run mifareplus -h
|
script run mifareplus -h
|
||||||
Arguments:
|
Arguments:
|
||||||
-h : this help
|
-h : this help
|
||||||
]]
|
]]
|
||||||
|
|
||||||
|
|
||||||
@@ -41,261 +41,261 @@ READPLAINNOMACUNMACED = '0336'
|
|||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print('ERROR: ',err)
|
print('ERROR: ',err)
|
||||||
return nil, err
|
return nil, err
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(copyright)
|
print(copyright)
|
||||||
print(author)
|
print(author)
|
||||||
print(version)
|
print(version)
|
||||||
print(desc)
|
print(desc)
|
||||||
print('Example usage')
|
print('Example usage')
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Used to send raw data to the firmware to subsequently forward the data to the card.
|
-- Used to send raw data to the firmware to subsequently forward the data to the card.
|
||||||
local function sendRaw(rawdata, crc, power)
|
local function sendRaw(rawdata, crc, power)
|
||||||
print(("<sent>: %s"):format(rawdata))
|
print(("<sent>: %s"):format(rawdata))
|
||||||
|
|
||||||
local flags = lib14a.ISO14A_COMMAND.ISO14A_RAW
|
local flags = lib14a.ISO14A_COMMAND.ISO14A_RAW
|
||||||
if crc then
|
if crc then
|
||||||
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC
|
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC
|
||||||
end
|
end
|
||||||
if power then
|
if power then
|
||||||
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT
|
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT
|
||||||
end
|
end
|
||||||
|
|
||||||
local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a,
|
local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a,
|
||||||
arg1 = flags, -- Send raw
|
arg1 = flags, -- Send raw
|
||||||
arg2 = string.len(rawdata) / 2, -- arg2 contains the length, which is half the length of the ASCII-string rawdata
|
arg2 = string.len(rawdata) / 2, -- arg2 contains the length, which is half the length of the ASCII-string rawdata
|
||||||
data = rawdata}
|
data = rawdata}
|
||||||
local ignore_response = false
|
local ignore_response = false
|
||||||
local result, err = lib14a.sendToDevice(command, ignore_response)
|
local result, err = lib14a.sendToDevice(command, ignore_response)
|
||||||
if result then
|
if result then
|
||||||
--unpack the first 4 parts of the result as longs, and the last as an extremely long string to later be cut down based on arg1, the number of bytes returned
|
--unpack the first 4 parts of the result as longs, and the last as an extremely long string to later be cut down based on arg1, the number of bytes returned
|
||||||
local count,cmd,arg1,arg2,arg3,data = bin.unpack('LLLLH512',result)
|
local count,cmd,arg1,arg2,arg3,data = bin.unpack('LLLLH512',result)
|
||||||
|
|
||||||
returned_bytes = string.sub(data, 1, arg1 * 2)
|
returned_bytes = string.sub(data, 1, arg1 * 2)
|
||||||
if #returned_bytes > 0 then
|
if #returned_bytes > 0 then
|
||||||
print(("<recvd>: %s"):format(returned_bytes)) -- need to multiply by 2 because the hex digits are actually two bytes when they are strings
|
print(("<recvd>: %s"):format(returned_bytes)) -- need to multiply by 2 because the hex digits are actually two bytes when they are strings
|
||||||
return returned_bytes
|
return returned_bytes
|
||||||
else
|
else
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
oops("Error sending the card raw data.")
|
oops("Error sending the card raw data.")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Sends an instruction to do nothing, only disconnect
|
-- Sends an instruction to do nothing, only disconnect
|
||||||
local function disconnect()
|
local function disconnect()
|
||||||
local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, arg1 = 0, }
|
local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, arg1 = 0,}
|
||||||
-- We can ignore the response here, no ACK is returned for this command
|
-- We can ignore the response here, no ACK is returned for this command
|
||||||
-- Check /armsrc/iso14443a.c, ReaderIso14443a() for details
|
-- Check /armsrc/iso14443a.c, ReaderIso14443a() for details
|
||||||
return lib14a.sendToDevice(command,true)
|
return lib14a.sendToDevice(command,true)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function writePerso()
|
local function writePerso()
|
||||||
-- Used to write any data, including the keys (Key A and Key B), for all the sectors.
|
-- Used to write any data, including the keys (Key A and Key B), for all the sectors.
|
||||||
-- writePerso() command parameters:
|
-- writePerso() command parameters:
|
||||||
-- 1 byte - 0xA8 - Command Code
|
-- 1 byte - 0xA8 - Command Code
|
||||||
-- 2 bytes - Address of the first block or key to be written to (40 blocks are numbered from 0x0000 to 0x00FF)
|
-- 2 bytes - Address of the first block or key to be written to (40 blocks are numbered from 0x0000 to 0x00FF)
|
||||||
-- X bytes - The data bytes to be written, starting from the first block. Amount of data sent can be from 16 to 240 bytes in 16 byte increments. This allows
|
-- X bytes - The data bytes to be written, starting from the first block. Amount of data sent can be from 16 to 240 bytes in 16 byte increments. This allows
|
||||||
-- up to 15 blocks to be written at once.
|
-- up to 15 blocks to be written at once.
|
||||||
-- response from PICC:
|
-- response from PICC:
|
||||||
-- 0x90 - OK
|
-- 0x90 - OK
|
||||||
-- 0x09 - targeted block is invalid for writes, i.e. block 0, which contains manufacturer data
|
-- 0x09 - targeted block is invalid for writes, i.e. block 0, which contains manufacturer data
|
||||||
-- 0x0B - command invalid
|
-- 0x0B - command invalid
|
||||||
-- 0x0C - unexpected command length
|
-- 0x0C - unexpected command length
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cardsize = 4 --need to set to 4 for 4k or 2 for 2k
|
cardsize = 4 --need to set to 4 for 4k or 2 for 2k
|
||||||
if(cardsize == 4) then
|
if(cardsize == 4) then
|
||||||
numsectors = 39
|
numsectors = 39
|
||||||
elseif(cardsize == 2) then
|
elseif(cardsize == 2) then
|
||||||
numsectors = 31
|
numsectors = 31
|
||||||
else
|
else
|
||||||
oops("Invalid card size")
|
oops("Invalid card size")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Write to the AES sector keys
|
-- Write to the AES sector keys
|
||||||
print("Setting AES Sector keys")
|
print("Setting AES Sector keys")
|
||||||
for i=0,numsectors do --for each sector number
|
for i=0,numsectors do --for each sector number
|
||||||
local keyA_block = "40" .. string.format("%02x", i * 2)
|
local keyA_block = "40" .. string.format("%02x", i * 2)
|
||||||
local keyB_block = "40" .. string.format("%02x", (i * 2) + 1)
|
local keyB_block = "40" .. string.format("%02x", (i * 2) + 1)
|
||||||
--Can also calculate the keys fancily to make them unique, if desired
|
--Can also calculate the keys fancily to make them unique, if desired
|
||||||
keyA = SIXTEEN_BYTES_ZEROS
|
keyA = SIXTEEN_BYTES_ZEROS
|
||||||
keyB = SIXTEEN_BYTES_ZEROS
|
keyB = SIXTEEN_BYTES_ZEROS
|
||||||
writeBlock(keyA_block, keyA)
|
writeBlock(keyA_block, keyA)
|
||||||
writeBlock(keyB_block, keyB)
|
writeBlock(keyB_block, keyB)
|
||||||
end
|
end
|
||||||
print("Finished setting AES Sector keys")
|
print("Finished setting AES Sector keys")
|
||||||
|
|
||||||
print("Setting misc keys which haven't been set yet.")
|
print("Setting misc keys which haven't been set yet.")
|
||||||
--CardMasterKey
|
--CardMasterKey
|
||||||
blocknum = "9000"
|
blocknum = "9000"
|
||||||
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
|
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
|
||||||
--CardConfigurationKey
|
--CardConfigurationKey
|
||||||
blocknum = "9001"
|
blocknum = "9001"
|
||||||
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
|
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
|
||||||
--L3SwitchKey
|
--L3SwitchKey
|
||||||
blocknum = "9003"
|
blocknum = "9003"
|
||||||
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
|
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
|
||||||
--SL1CardAuthKey
|
--SL1CardAuthKey
|
||||||
blocknum = "9004"
|
blocknum = "9004"
|
||||||
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
|
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
|
||||||
--L3SectorSwitchKey
|
--L3SectorSwitchKey
|
||||||
blocknum = "9006"
|
blocknum = "9006"
|
||||||
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
|
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
|
||||||
--L1L3MixSectorSwitchKey
|
--L1L3MixSectorSwitchKey
|
||||||
blocknum = "9007"
|
blocknum = "9007"
|
||||||
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
|
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
|
||||||
--VC Keys
|
--VC Keys
|
||||||
--VCProximityKey
|
--VCProximityKey
|
||||||
blocknum = "A001"
|
blocknum = "A001"
|
||||||
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
|
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
|
||||||
--VCSelectENCKey
|
--VCSelectENCKey
|
||||||
blocknum = "A080"
|
blocknum = "A080"
|
||||||
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
|
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
|
||||||
--VCSelectMACKey
|
--VCSelectMACKey
|
||||||
blocknum = "A081"
|
blocknum = "A081"
|
||||||
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
|
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
|
||||||
--TransactionMACKey1
|
--TransactionMACKey1
|
||||||
blocknum = "C000"
|
blocknum = "C000"
|
||||||
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
|
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
|
||||||
--TransactionMACConfKey1
|
--TransactionMACConfKey1
|
||||||
blocknum = "C001"
|
blocknum = "C001"
|
||||||
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
|
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
|
||||||
print("Finished setting misc keys.")
|
print("Finished setting misc keys.")
|
||||||
|
|
||||||
print("WritePerso finished! Card is ready to move into new security level.")
|
print("WritePerso finished! Card is ready to move into new security level.")
|
||||||
end
|
end
|
||||||
|
|
||||||
local function writeBlock(blocknum, data)
|
local function writeBlock(blocknum, data)
|
||||||
-- Method writes 16 bytes of the string sent (data) to the specified block number
|
-- Method writes 16 bytes of the string sent (data) to the specified block number
|
||||||
-- The block numbers sent to the card need to be in little endian format (i.e. block 0x0001 is sent as 0x1000)
|
-- The block numbers sent to the card need to be in little endian format (i.e. block 0x0001 is sent as 0x1000)
|
||||||
blocknum_little_endian = string.sub(blocknum, 3, 4) .. string.sub(blocknum, 1, 2)
|
blocknum_little_endian = string.sub(blocknum, 3, 4) .. string.sub(blocknum, 1, 2)
|
||||||
commandString = WRITEPERSO .. blocknum_little_endian .. data --Write 16 bytes (32 hex chars).
|
commandString = WRITEPERSO .. blocknum_little_endian .. data --Write 16 bytes (32 hex chars).
|
||||||
response = sendRaw(commandString, true, true) --0x90 is returned upon success
|
response = sendRaw(commandString, true, true) --0x90 is returned upon success
|
||||||
if string.sub(response, 3, 4) ~= "90" then
|
if string.sub(response, 3, 4) ~= "90" then
|
||||||
oops(("error occurred while trying to write to block %s"):format(blocknum))
|
oops(("error occurred while trying to write to block %s"):format(blocknum))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function authenticateAES()
|
local function authenticateAES()
|
||||||
-- Used to try to authenticate with the AES keys we programmed into the card, to ensure the authentication works correctly.
|
-- Used to try to authenticate with the AES keys we programmed into the card, to ensure the authentication works correctly.
|
||||||
commandString = AUTH_FIRST
|
commandString = AUTH_FIRST
|
||||||
commandString = commandString .. ''
|
commandString = commandString .. ''
|
||||||
end
|
end
|
||||||
|
|
||||||
local function getVersion()
|
local function getVersion()
|
||||||
sendRaw(GETVERS_INIT, true, true)
|
sendRaw(GETVERS_INIT, true, true)
|
||||||
sendRaw(GETVERS_CONT, true, true)
|
sendRaw(GETVERS_CONT, true, true)
|
||||||
sendRaw(GETVERS_CONT, true, true)
|
sendRaw(GETVERS_CONT, true, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function commitPerso(SL)
|
local function commitPerso(SL)
|
||||||
--pass SL as "01" to move to SL1 or "03" to move to SL3.
|
--pass SL as "01" to move to SL1 or "03" to move to SL3.
|
||||||
commandString = COMMITPERSO .. SL
|
commandString = COMMITPERSO .. SL
|
||||||
response = sendRaw(commandString, true, true) --0x90 is returned upon success
|
response = sendRaw(commandString, true, true) --0x90 is returned upon success
|
||||||
if string.sub(response, 3, 4) ~= "90" then
|
if string.sub(response, 3, 4) ~= "90" then
|
||||||
oops("error occurred while trying to switch security level")
|
oops("error occurred while trying to switch security level")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function calculateMAC(MAC_input)
|
local function calculateMAC(MAC_input)
|
||||||
-- Pad the input if it is not a multiple of 16 bytes (32 nibbles).
|
-- Pad the input if it is not a multiple of 16 bytes (32 nibbles).
|
||||||
if(string.len(MAC_input) % 32 ~= 0) then
|
if(string.len(MAC_input) % 32 ~= 0) then
|
||||||
MAC_input = MAC_input .. "80"
|
MAC_input = MAC_input .. "80"
|
||||||
end
|
end
|
||||||
while(string.len(MAC_input) % 32 ~= 0) do
|
while(string.len(MAC_input) % 32 ~= 0) do
|
||||||
MAC_input = MAC_input .. "0"
|
MAC_input = MAC_input .. "0"
|
||||||
end
|
end
|
||||||
print("Padded MAC Input = " .. MAC_input .. ", length (bytes) = " .. string.len(MAC_input) / 2)
|
print("Padded MAC Input = " .. MAC_input .. ", length (bytes) = " .. string.len(MAC_input) / 2)
|
||||||
|
|
||||||
--The MAC would actually be calculated here, and the output stored in raw_output
|
--The MAC would actually be calculated here, and the output stored in raw_output
|
||||||
raw_output = "00010203040506070001020304050607" -- Dummy filler for now of 16-byte output. To be filled with actual MAC for testing purposes.
|
raw_output = "00010203040506070001020304050607" -- Dummy filler for now of 16-byte output. To be filled with actual MAC for testing purposes.
|
||||||
|
|
||||||
-- The final 8-byte MAC output is a concatenation of every 2nd byte starting from the second MSB.
|
-- The final 8-byte MAC output is a concatenation of every 2nd byte starting from the second MSB.
|
||||||
final_output = ""
|
final_output = ""
|
||||||
j = 3
|
j = 3
|
||||||
for i = 1,8 do
|
for i = 1,8 do
|
||||||
final_output = final_output .. string.sub(RndR, j, j + 1) .. string.sub(RndC, j, j + 1)
|
final_output = final_output .. string.sub(RndR, j, j + 1) .. string.sub(RndC, j, j + 1)
|
||||||
j = j + 4
|
j = j + 4
|
||||||
end
|
end
|
||||||
return final_output
|
return final_output
|
||||||
end
|
end
|
||||||
|
|
||||||
local function proximityCheck()
|
local function proximityCheck()
|
||||||
--PreparePC--
|
--PreparePC--
|
||||||
commandString = PREPAREPC
|
commandString = PREPAREPC
|
||||||
response = sendRaw(commandString, true, true)
|
response = sendRaw(commandString, true, true)
|
||||||
if not response then return oops("This card is not support the proximity check command.") end
|
if not response then return oops("This card is not support the proximity check command.") end
|
||||||
|
|
||||||
OPT = string.sub(response, 5, 6)
|
OPT = string.sub(response, 5, 6)
|
||||||
if tonumber(OPT) == 1 then
|
if tonumber(OPT) == 1 then
|
||||||
pps_present = true
|
pps_present = true
|
||||||
else
|
else
|
||||||
pps_present = false
|
pps_present = false
|
||||||
end
|
end
|
||||||
pubRespTime = string.sub(response, 7, 10)
|
pubRespTime = string.sub(response, 7, 10)
|
||||||
if(pps_present == true) then
|
if(pps_present == true) then
|
||||||
pps = string.sub(response, 11, 12)
|
pps = string.sub(response, 11, 12)
|
||||||
else
|
else
|
||||||
pps = ''
|
pps = ''
|
||||||
end
|
end
|
||||||
print("OPT = " .. OPT .. " pubRespTime = " .. pubRespTime .. " pps = " .. pps)
|
print("OPT = " .. OPT .. " pubRespTime = " .. pubRespTime .. " pps = " .. pps)
|
||||||
|
|
||||||
--PC--
|
--PC--
|
||||||
RndC = "0001020304050607" --Random Challenge
|
RndC = "0001020304050607" --Random Challenge
|
||||||
num_rounds = 8 --Needs to be 1, 2, 4, or 8
|
num_rounds = 8 --Needs to be 1, 2, 4, or 8
|
||||||
part_len = 8 / num_rounds
|
part_len = 8 / num_rounds
|
||||||
j = 1
|
j = 1
|
||||||
RndR = ""
|
RndR = ""
|
||||||
for i = 1,num_rounds do
|
for i = 1,num_rounds do
|
||||||
pRndC = ""
|
pRndC = ""
|
||||||
for q = 1,(part_len*2) do
|
for q = 1,(part_len*2) do
|
||||||
pRndC = pRndC .. string.sub(RndC,j,j)
|
pRndC = pRndC .. string.sub(RndC,j,j)
|
||||||
j = j + 1
|
j = j + 1
|
||||||
end
|
end
|
||||||
commandString = PROXIMITYCHECK .. "0" .. tostring(part_len) .. pRndC
|
commandString = PROXIMITYCHECK .. "0" .. tostring(part_len) .. pRndC
|
||||||
pRndR = string.sub(sendRaw(commandString, true, true), 3, 3+part_len)
|
pRndR = string.sub(sendRaw(commandString, true, true), 3, 3+part_len)
|
||||||
RndR = RndR .. pRndR
|
RndR = RndR .. pRndR
|
||||||
end
|
end
|
||||||
print("RndC = " .. RndC .. " RndR = " .. RndR)
|
print("RndC = " .. RndC .. " RndR = " .. RndR)
|
||||||
|
|
||||||
--VerifyPC--
|
--VerifyPC--
|
||||||
MAC_input = "FD" .. OPT .. pubRespTime
|
MAC_input = "FD" .. OPT .. pubRespTime
|
||||||
if pps_present then
|
if pps_present then
|
||||||
MAC_input = MAC_input .. pps
|
MAC_input = MAC_input .. pps
|
||||||
end
|
end
|
||||||
rnum_concat = ""
|
rnum_concat = ""
|
||||||
rnum_concat = RndR .. RndC --temporary (only works for when a single random challenge (8 bytes) is sent)
|
rnum_concat = RndR .. RndC --temporary (only works for when a single random challenge (8 bytes) is sent)
|
||||||
-- j = 1
|
-- j = 1
|
||||||
-- for i = 1,8 do
|
-- for i = 1,8 do
|
||||||
-- rnum_concat = rnum_concat .. string.sub(RndR, j, j + 1) .. string.sub(RndC, j, j + 1)
|
-- rnum_concat = rnum_concat .. string.sub(RndR, j, j + 1) .. string.sub(RndC, j, j + 1)
|
||||||
-- j = j + 2
|
-- j = j + 2
|
||||||
-- end
|
-- end
|
||||||
MAC_input = MAC_input .. rnum_concat
|
MAC_input = MAC_input .. rnum_concat
|
||||||
print("Concatenation of random numbers = " .. rnum_concat)
|
print("Concatenation of random numbers = " .. rnum_concat)
|
||||||
print("Final PCD concatenation before input into MAC function = " .. MAC_input)
|
print("Final PCD concatenation before input into MAC function = " .. MAC_input)
|
||||||
MAC_tag = calculateMAC(MAC_input)
|
MAC_tag = calculateMAC(MAC_input)
|
||||||
print("8-byte PCD MAC_tag (placeholder - currently incorrect) = " .. MAC_tag)
|
print("8-byte PCD MAC_tag (placeholder - currently incorrect) = " .. MAC_tag)
|
||||||
commandString = VERIFYPC .. MAC_tag
|
commandString = VERIFYPC .. MAC_tag
|
||||||
response = sendRaw(commandString, true, true)
|
response = sendRaw(commandString, true, true)
|
||||||
print(#response, response)
|
print(#response, response)
|
||||||
if #response < 20 then return oops("Wrong response length (expected 20, got "..#response..") exiting") end
|
if #response < 20 then return oops("Wrong response length (expected 20, got "..#response..") exiting") end
|
||||||
|
|
||||||
PICC_MAC = string.sub(response, 5, 20)
|
PICC_MAC = string.sub(response, 5, 20)
|
||||||
print("8-byte MAC returned by PICC = " .. PICC_MAC)
|
print("8-byte MAC returned by PICC = " .. PICC_MAC)
|
||||||
MAC_input = "90" .. string.sub(MAC_input, 3)
|
MAC_input = "90" .. string.sub(MAC_input, 3)
|
||||||
print("Final PICC concatenation before input into MAC function = " .. MAC_input)
|
print("Final PICC concatenation before input into MAC function = " .. MAC_input)
|
||||||
MAC_tag = calculateMAC(MAC_input)
|
MAC_tag = calculateMAC(MAC_input)
|
||||||
print("8-byte PICC MAC_tag (placeholder - currently incorrect) = " .. MAC_tag)
|
print("8-byte PICC MAC_tag (placeholder - currently incorrect) = " .. MAC_tag)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -303,47 +303,47 @@ end
|
|||||||
-- The main entry point
|
-- The main entry point
|
||||||
function main(args)
|
function main(args)
|
||||||
|
|
||||||
local o, a
|
local o, a
|
||||||
for o, a in getopt.getopt(args, 'h') do -- Populate command line arguments
|
for o, a in getopt.getopt(args, 'h') do -- Populate command line arguments
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Initialize the card using the already-present read14a library
|
-- Initialize the card using the already-present read14a library
|
||||||
-- Perform RATS and PPS (Protocol and Parameter Selection) check to finish the ISO 14443-4 protocol.
|
-- Perform RATS and PPS (Protocol and Parameter Selection) check to finish the ISO 14443-4 protocol.
|
||||||
info,err = lib14a.read(true, false)
|
info,err = lib14a.read(true, false)
|
||||||
if not info then oops(err); disconnect(); return; end
|
if not info then oops(err); disconnect(); return; end
|
||||||
|
|
||||||
--
|
--
|
||||||
response = sendRaw("D01100", true, true)
|
response = sendRaw("D01100", true, true)
|
||||||
if not response then oops("No response from PPS check"); disconnect(); return; end
|
if not response then oops("No response from PPS check"); disconnect(); return; end
|
||||||
|
|
||||||
print("Connected to")
|
print("Connected to")
|
||||||
print(" Type : "..info.name)
|
print(" Type : "..info.name)
|
||||||
print(" UID : "..info.uid)
|
print(" UID : "..info.uid)
|
||||||
|
|
||||||
-- Now, the card is initialized and we can do more interesting things.
|
-- Now, the card is initialized and we can do more interesting things.
|
||||||
|
|
||||||
--writePerso()
|
--writePerso()
|
||||||
--commitPerso("03") --move to SL3
|
--commitPerso("03") --move to SL3
|
||||||
--getVersion()
|
--getVersion()
|
||||||
proximityCheck()
|
proximityCheck()
|
||||||
|
|
||||||
--commandString = VERIFYPC .. "186EFDE8DDC7D30B"
|
--commandString = VERIFYPC .. "186EFDE8DDC7D30B"
|
||||||
-- MAC = f5180d6e 40fdeae8 e9dd6ac7 bcd3350b
|
-- MAC = f5180d6e 40fdeae8 e9dd6ac7 bcd3350b
|
||||||
-- response = sendRaw(commandString, true, true)
|
-- response = sendRaw(commandString, true, true)
|
||||||
|
|
||||||
-- attempt to read VCProximityKey at block A001
|
-- attempt to read VCProximityKey at block A001
|
||||||
-- commandString = READPLAINNOMACUNMACED .. "01A0" .. "01"
|
-- commandString = READPLAINNOMACUNMACED .. "01A0" .. "01"
|
||||||
-- response = sendRaw(commandString, true, true)
|
-- response = sendRaw(commandString, true, true)
|
||||||
|
|
||||||
-- authenticate with CardConfigurationKey
|
-- authenticate with CardConfigurationKey
|
||||||
-- commandString = AUTH_FIRST .. "0190" .. "00"
|
-- commandString = AUTH_FIRST .. "0190" .. "00"
|
||||||
-- response = sendRaw(commandString, true, true)
|
-- response = sendRaw(commandString, true, true)
|
||||||
|
|
||||||
-- Power off the Proxmark
|
-- Power off the Proxmark
|
||||||
sendRaw(POWEROFF, false, false)
|
sendRaw(POWEROFF, false, false)
|
||||||
|
|
||||||
disconnect()
|
disconnect()
|
||||||
end
|
end
|
||||||
|
|
||||||
main(args)
|
main(args)
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ For example: 24 bytes could be 6 blocks of 4 bytes, or vice versa.
|
|||||||
Therefore, the .eml is better to use file when saving dumps.)
|
Therefore, the .eml is better to use file when saving dumps.)
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-d debug logging on
|
-h this help
|
||||||
-h this help
|
-d debug logging on
|
||||||
|
|
||||||
]]
|
]]
|
||||||
local example = "script run xxx"
|
local example = "script run xxx"
|
||||||
@@ -25,116 +25,116 @@ local author = "Martin Holst Swende & Asper"
|
|||||||
---
|
---
|
||||||
-- PrintAndLog
|
-- PrintAndLog
|
||||||
local function prlog(...)
|
local function prlog(...)
|
||||||
-- TODO; replace this with a call to the proper PrintAndLog
|
-- TODO; replace this with a call to the proper PrintAndLog
|
||||||
print(...)
|
print(...)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
prlog("ERROR: ",err)
|
prlog("ERROR: ",err)
|
||||||
return nil,err
|
return nil,err
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Perhaps this will be moved to a separate library at one point
|
-- Perhaps this will be moved to a separate library at one point
|
||||||
local utils = {
|
local utils = {
|
||||||
--- Writes an eml-file.
|
--- Writes an eml-file.
|
||||||
-- @param uid - the uid of the tag. Used in filename
|
-- @param uid - the uid of the tag. Used in filename
|
||||||
-- @param blockData. Assumed to be on the format {'\0\1\2\3,'\b\e\e\f' ...,
|
-- @param blockData. Assumed to be on the format {'\0\1\2\3,'\b\e\e\f' ...,
|
||||||
-- that is, blockData[row] contains a string with the actual data, not ascii hex representation
|
-- that is, blockData[row] contains a string with the actual data, not ascii hex representation
|
||||||
-- return filename if all went well,
|
-- return filename if all went well,
|
||||||
-- @reurn nil, error message if unsuccessfull
|
-- @reurn nil, error message if unsuccessfull
|
||||||
writeDumpFile = function(uid, blockData)
|
writeDumpFile = function(uid, blockData)
|
||||||
local destination = string.format("%s.eml", uid)
|
local destination = string.format("%s.eml", uid)
|
||||||
local file = io.open(destination, "w")
|
local file = io.open(destination, "w")
|
||||||
if file == nil then
|
if file == nil then
|
||||||
return nil, string.format("Could not write to file %s", destination)
|
return nil, string.format("Could not write to file %s", destination)
|
||||||
end
|
end
|
||||||
local rowlen = string.len(blockData[1])
|
local rowlen = string.len(blockData[1])
|
||||||
|
|
||||||
for i,block in ipairs(blockData) do
|
for i,block in ipairs(blockData) do
|
||||||
if rowlen ~= string.len(block) then
|
if rowlen ~= string.len(block) then
|
||||||
prlog(string.format("WARNING: Dumpdata seems corrupted, line %d was not the same length as line 1",i))
|
prlog(string.format("WARNING: Dumpdata seems corrupted, line %d was not the same length as line 1",i))
|
||||||
end
|
end
|
||||||
|
|
||||||
local formatString = string.format("H%d", string.len(block))
|
local formatString = string.format("H%d", string.len(block))
|
||||||
local _,hex = bin.unpack(formatString,block)
|
local _,hex = bin.unpack(formatString,block)
|
||||||
file:write(hex.."\n")
|
file:write(hex.."\n")
|
||||||
end
|
end
|
||||||
file:close()
|
file:close()
|
||||||
return destination
|
return destination
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
prlog(desc)
|
prlog(desc)
|
||||||
prlog("Example usage")
|
prlog("Example usage")
|
||||||
prlog(example)
|
prlog(example)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function debug(...)
|
local function debug(...)
|
||||||
if DEBUG then
|
if DEBUG then
|
||||||
prlog("debug:", ...)
|
prlog("debug:", ...)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- This function is a lua-implementation of
|
--- This function is a lua-implementation of
|
||||||
-- cmdhf14a.c:waitCmd(uint8_t iSelect)
|
-- cmdhf14a.c:waitCmd(uint8_t iSelect)
|
||||||
local function waitCmd(iSelect)
|
local function waitCmd(iSelect)
|
||||||
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,1000)
|
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,1000)
|
||||||
if response then
|
if response then
|
||||||
local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',response)
|
local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',response)
|
||||||
|
|
||||||
local iLen = arg0
|
local iLen = arg0
|
||||||
if iSelect then iLen = arg1 end
|
if iSelect then iLen = arg1 end
|
||||||
debug(("Received %i octets (arg0:%d, arg1:%d)"):format(iLen, arg0, arg1))
|
debug(("Received %i octets (arg0:%d, arg1:%d)"):format(iLen, arg0, arg1))
|
||||||
if iLen == 0 then return nil, "No response from tag" end
|
if iLen == 0 then return nil, "No response from tag" end
|
||||||
local recv = string.sub(response,count, iLen+count-1)
|
local recv = string.sub(response,count, iLen+count-1)
|
||||||
return recv
|
return recv
|
||||||
end
|
end
|
||||||
return nil, "No response from device"
|
return nil, "No response from device"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function show(data)
|
local function show(data)
|
||||||
if DEBUG then
|
if DEBUG then
|
||||||
local formatString = ("H%d"):format(string.len(data))
|
local formatString = ("H%d"):format(string.len(data))
|
||||||
local _,hexdata = bin.unpack(formatString, data)
|
local _,hexdata = bin.unpack(formatString, data)
|
||||||
debug("Hexdata" , hexdata)
|
debug("Hexdata" , hexdata)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
--- Fire up a connection with a tag, return uid
|
--- Fire up a connection with a tag, return uid
|
||||||
-- @return UID if successfull
|
-- @return UID if successfull
|
||||||
-- @return nil, errormessage if unsuccessfull
|
-- @return nil, errormessage if unsuccessfull
|
||||||
|
|
||||||
local function open()
|
local function open()
|
||||||
debug("Opening connection")
|
debug("Opening connection")
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
local x = string.format("hf 14a raw -r -p -s")
|
local x = string.format("hf 14a raw -r -p -s")
|
||||||
debug(x)
|
debug(x)
|
||||||
core.console(x)
|
core.console(x)
|
||||||
debug("done")
|
debug("done")
|
||||||
data, err = waitCmd(true)
|
data, err = waitCmd(true)
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
show(data)
|
show(data)
|
||||||
local formatString = ("H%d"):format(string.len(data))
|
local formatString = ("H%d"):format(string.len(data))
|
||||||
local _,uid = bin.unpack(formatString, data)
|
local _,uid = bin.unpack(formatString, data)
|
||||||
return uid
|
return uid
|
||||||
end
|
end
|
||||||
--- Shut down tag communication
|
--- Shut down tag communication
|
||||||
-- return no return values
|
-- return no return values
|
||||||
local function close()
|
local function close()
|
||||||
debug("Closing connection")
|
debug("Closing connection")
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
local x = string.format("hf 14a raw -r")
|
local x = string.format("hf 14a raw -r")
|
||||||
debug(x)
|
debug(x)
|
||||||
core.console(x)
|
core.console(x)
|
||||||
debug("done")
|
debug("done")
|
||||||
--data, err = waitCmd(true)
|
--data, err = waitCmd(true)
|
||||||
--data, err = waitCmd(false)
|
--data, err = waitCmd(false)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -143,105 +143,105 @@ end
|
|||||||
-- @return {block, block+1, block+2, block+3} if successfull
|
-- @return {block, block+1, block+2, block+3} if successfull
|
||||||
-- @return nil, errormessage if unsuccessfull
|
-- @return nil, errormessage if unsuccessfull
|
||||||
local function getBlock(block)
|
local function getBlock(block)
|
||||||
local data, err
|
local data, err
|
||||||
|
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
local x = string.format("hf 14a raw -r -c -p 30 %02x", block)
|
local x = string.format("hf 14a raw -r -c -p 30 %02x", block)
|
||||||
debug(x)
|
debug(x)
|
||||||
core.console(x)
|
core.console(x)
|
||||||
debug("done")
|
debug("done")
|
||||||
-- By now, there should be an ACK waiting from the device, since
|
-- By now, there should be an ACK waiting from the device, since
|
||||||
-- we used the -r flag (don't read response).
|
-- we used the -r flag (don't read response).
|
||||||
|
|
||||||
data, err = waitCmd(false)
|
data, err = waitCmd(false)
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
show(data)
|
show(data)
|
||||||
|
|
||||||
if string.len(data) < 18 then
|
if string.len(data) < 18 then
|
||||||
return nil, ("Expected at least 18 bytes, got %d - this tag is not NDEF-compliant"):format(string.len(data))
|
return nil, ("Expected at least 18 bytes, got %d - this tag is not NDEF-compliant"):format(string.len(data))
|
||||||
end
|
end
|
||||||
-- Now, parse out the block data
|
-- Now, parse out the block data
|
||||||
-- 0534 00B9 049C AD7F 4A00 0000 E110 1000 2155
|
-- 0534 00B9 049C AD7F 4A00 0000 E110 1000 2155
|
||||||
-- b0b0 b0b0 b1b1 b1b1 b2b2 b2b2 b3b3 b3b3 CRCC
|
-- b0b0 b0b0 b1b1 b1b1 b2b2 b2b2 b3b3 b3b3 CRCC
|
||||||
b0 = string.sub(data,1,4)
|
b0 = string.sub(data,1,4)
|
||||||
b1 = string.sub(data,5,8)
|
b1 = string.sub(data,5,8)
|
||||||
b2 = string.sub(data,9,12)
|
b2 = string.sub(data,9,12)
|
||||||
b3 = string.sub(data,13,16)
|
b3 = string.sub(data,13,16)
|
||||||
return {b0,b1,b2,b3}
|
return {b0,b1,b2,b3}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local function main( args)
|
local function main( args)
|
||||||
debug("script started")
|
debug("script started")
|
||||||
local err, data, data2,k,v,i
|
local err, data, data2,k,v,i
|
||||||
-- Read the parameters
|
-- Read the parameters
|
||||||
for o, a in getopt.getopt(args, 'hd') do
|
for o, a in getopt.getopt(args, 'hd') do
|
||||||
if o == "h" then help() return end
|
if o == "h" then help() return end
|
||||||
if o == "d" then DEBUG = true end
|
if o == "d" then DEBUG = true end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Info contained within the tag (block 0 example)
|
-- Info contained within the tag (block 0 example)
|
||||||
-- 0534 00B9 049C AD7F 4A00 0000 E110 1000 2155
|
-- 0534 00B9 049C AD7F 4A00 0000 E110 1000 2155
|
||||||
-- b0b0 b0b0 b1b1 b1b1 b2b2 b2b2 b3b3 b3b3 CRCC
|
-- b0b0 b0b0 b1b1 b1b1 b2b2 b2b2 b3b3 b3b3 CRCC
|
||||||
-- MM?? ???? ???? ???? ???? ???? NNVV SS?? ----
|
-- MM?? ???? ???? ???? ???? ???? NNVV SS?? ----
|
||||||
-- M = Manufacturer info
|
-- M = Manufacturer info
|
||||||
-- N = NDEF-Structure-Compliant (if value is E1)
|
-- N = NDEF-Structure-Compliant (if value is E1)
|
||||||
-- V = NFC Forum Specification version (if 10 = v1.0)
|
-- V = NFC Forum Specification version (if 10 = v1.0)
|
||||||
|
|
||||||
-- First, 'connect' (fire up the field) and get the uid
|
-- First, 'connect' (fire up the field) and get the uid
|
||||||
local uidHexstr = open()
|
local uidHexstr = open()
|
||||||
|
|
||||||
-- First, get blockt 3 byte 2
|
-- First, get blockt 3 byte 2
|
||||||
local blocks, err = getBlock(0)
|
local blocks, err = getBlock(0)
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
-- Block 3 contains number of blocks
|
-- Block 3 contains number of blocks
|
||||||
local b3chars = {string.byte(blocks[4], 1,4)}
|
local b3chars = {string.byte(blocks[4], 1,4)}
|
||||||
local numBlocks = b3chars[3] * 2 + 6
|
local numBlocks = b3chars[3] * 2 + 6
|
||||||
prlog("Number of blocks:", numBlocks)
|
prlog("Number of blocks:", numBlocks)
|
||||||
|
|
||||||
-- NDEF compliant?
|
-- NDEF compliant?
|
||||||
if b3chars[1] ~= 0xE1 then
|
if b3chars[1] ~= 0xE1 then
|
||||||
return oops("This tag is not NDEF-Compliant")
|
return oops("This tag is not NDEF-Compliant")
|
||||||
end
|
end
|
||||||
|
|
||||||
local ndefVersion = b3chars[2]
|
local ndefVersion = b3chars[2]
|
||||||
|
|
||||||
-- Block 1, byte 1 contains manufacturer info
|
-- Block 1, byte 1 contains manufacturer info
|
||||||
local bl1_b1 = string.byte(blocks[1], 1)
|
local bl1_b1 = string.byte(blocks[1], 1)
|
||||||
local manufacturer = taglib.lookupManufacturer(bl1_b1)
|
local manufacturer = taglib.lookupManufacturer(bl1_b1)
|
||||||
|
|
||||||
-- Reuse existing info
|
-- Reuse existing info
|
||||||
local blockData = {blocks[1],blocks[2],blocks[3],blocks[4]}
|
local blockData = {blocks[1],blocks[2],blocks[3],blocks[4]}
|
||||||
|
|
||||||
|
|
||||||
--[[ Due to the infineon my-d move bug
|
--[[ Due to the infineon my-d move bug
|
||||||
(if I send 30 0F i receive block0f+block00+block01+block02 insted of block0f+block10+block11+block12)
|
(if I send 30 0F i receive block0f+block00+block01+block02 insted of block0f+block10+block11+block12)
|
||||||
the only way to avoid this is to send the read command as many times as block numbers
|
the only way to avoid this is to send the read command as many times as block numbers
|
||||||
removing bytes from 5 to 18 from each answer.
|
removing bytes from 5 to 18 from each answer.
|
||||||
--]]
|
--]]
|
||||||
prlog("Dumping data...please wait")
|
prlog("Dumping data...please wait")
|
||||||
for i=4,numBlocks-1,1 do
|
for i=4,numBlocks-1,1 do
|
||||||
blocks, err = getBlock(i)
|
blocks, err = getBlock(i)
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
table.insert(blockData,blocks[1])
|
table.insert(blockData,blocks[1])
|
||||||
end
|
end
|
||||||
-- Deactivate field
|
-- Deactivate field
|
||||||
close()
|
close()
|
||||||
-- Print results
|
-- Print results
|
||||||
prlog(string.format("Tag manufacturer: %s", manufacturer))
|
prlog(string.format("Tag manufacturer: %s", manufacturer))
|
||||||
prlog(string.format("Tag UID: %s", uidHexstr))
|
prlog(string.format("Tag UID: %s", uidHexstr))
|
||||||
prlog(string.format("Tag NDEF version: 0x%02x", ndefVersion))
|
prlog(string.format("Tag NDEF version: 0x%02x", ndefVersion))
|
||||||
|
|
||||||
for k,v in ipairs(blockData) do
|
for k,v in ipairs(blockData) do
|
||||||
prlog(string.format("Block %02x: %02x %02x %02x %02x",k-1, string.byte(v, 1,4)))
|
prlog(string.format("Block %02x: %02x %02x %02x %02x",k-1, string.byte(v, 1,4)))
|
||||||
end
|
end
|
||||||
local filename, err = utils.writeDumpFile(uidHexstr, blockData)
|
local filename, err = utils.writeDumpFile(uidHexstr, blockData)
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
|
|
||||||
prlog(string.format("Dumped data into %s", filename))
|
prlog(string.format("Dumped data into %s", filename))
|
||||||
|
|
||||||
end
|
end
|
||||||
main(args)
|
main(args)
|
||||||
@@ -16,21 +16,21 @@ example =[[
|
|||||||
-- This will generate GOLD, PLA, TH, EU, 200m, userbased uid.
|
-- This will generate GOLD, PLA, TH, EU, 200m, userbased uid.
|
||||||
script run ntag_3d -u 11223344556677 -c 46 -m 50 -p 5448 -s 4555 -l 200
|
script run ntag_3d -u 11223344556677 -c 46 -m 50 -p 5448 -s 4555 -l 200
|
||||||
|
|
||||||
-- This will generate GOLD, PLA, TH, EU, 200m, userbased uid. and configure a MAGIC NTAG.
|
-- This will generate GOLD, PLA, TH, EU, 200m, userbased uid. and configure a MAGIC NTAG.
|
||||||
script run ntag_3d -u 11223344556677 -c 46 -m 50 -p 5448 -s 4555 -l 200 -1
|
script run ntag_3d -u 11223344556677 -c 46 -m 50 -p 5448 -s 4555 -l 200 -1
|
||||||
]]
|
]]
|
||||||
usage = [[
|
usage = [[
|
||||||
script run calc_ntag_3d -h -t -u <uid> -c <color> -m <material> -p <region> -s <region> -l <length>
|
script run calc_ntag_3d -h -t -u <uid> -c <color> -m <material> -p <region> -s <region> -l <length>
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h : this help
|
-h : this help
|
||||||
-t : selftest
|
-t : selftest
|
||||||
-u <UID> : UID
|
-u <UID> : UID
|
||||||
-c <COLOR> : color of filament
|
-c <COLOR> : color of filament
|
||||||
-m <MATERIAL> : material of filament
|
-m <MATERIAL> : material of filament
|
||||||
-p <REGION> : Manufacturer region
|
-p <REGION> : Manufacturer region
|
||||||
-s <REGION> : Sales region
|
-s <REGION> : Sales region
|
||||||
-l <LENGTH> : Spool length. Use only 100,200,300. 300 has problems on OSX
|
-l <LENGTH> : Spool length. Use only 100,200,300. 300 has problems on OSX
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local DEBUG = true
|
local DEBUG = true
|
||||||
@@ -40,344 +40,344 @@ local band = bit32.band
|
|||||||
local rshift = bit32.rshift
|
local rshift = bit32.rshift
|
||||||
|
|
||||||
local _regions = {
|
local _regions = {
|
||||||
{'4742', 'GB'},
|
{'4742', 'GB'},
|
||||||
{'5457', 'TW'},
|
{'5457', 'TW'},
|
||||||
{'4555', 'EU'},
|
{'4555', 'EU'},
|
||||||
{'5553', 'US'},
|
{'5553', 'US'},
|
||||||
{'454E', 'EN'},
|
{'454E', 'EN'},
|
||||||
{'4A50', 'JP'},
|
{'4A50', 'JP'},
|
||||||
{'434E', 'CN'},
|
{'434E', 'CN'},
|
||||||
{'5448', 'TH'},
|
{'5448', 'TH'},
|
||||||
{'4153', 'AS'},
|
{'4153', 'AS'},
|
||||||
{'5246', 'RF'},
|
{'5246', 'RF'},
|
||||||
{'4746', 'GF'},
|
{'4746', 'GF'},
|
||||||
{'4341', 'CA'},
|
{'4341', 'CA'},
|
||||||
{'504D', 'PM'},
|
{'504D', 'PM'},
|
||||||
{'5044', 'PD'},
|
{'5044', 'PD'},
|
||||||
}
|
}
|
||||||
local _manufacturers = {
|
local _manufacturers = {
|
||||||
{'5457', 'TW'},
|
{'5457', 'TW'},
|
||||||
{'434E', 'CN'},
|
{'434E', 'CN'},
|
||||||
{'5448', 'TH'},
|
{'5448', 'TH'},
|
||||||
}
|
}
|
||||||
local _sales = {
|
local _sales = {
|
||||||
{'4742', 'GB'},
|
{'4742', 'GB'},
|
||||||
{'4555', 'EU'},
|
{'4555', 'EU'},
|
||||||
{'5553', 'US'},
|
{'5553', 'US'},
|
||||||
{'454E', 'EN'},
|
{'454E', 'EN'},
|
||||||
{'504D', 'PM'},
|
{'504D', 'PM'},
|
||||||
}
|
}
|
||||||
local _materials = {
|
local _materials = {
|
||||||
{'20', 'Other material'},
|
{'20', 'Other material'},
|
||||||
{'41', 'ABS'},
|
{'41', 'ABS'},
|
||||||
{'46', 'Flexible TPE Tree'},
|
{'46', 'Flexible TPE Tree'},
|
||||||
{'46', 'TPE'},
|
{'46', 'TPE'},
|
||||||
{'46', 'PVA'},
|
{'46', 'PVA'},
|
||||||
{'47', 'PETG'},
|
{'47', 'PETG'},
|
||||||
{'50', 'PLA'},
|
{'50', 'PLA'},
|
||||||
{'51', 'PLA'},
|
{'51', 'PLA'},
|
||||||
{'54', 'Tough PLA'},
|
{'54', 'Tough PLA'},
|
||||||
{'55', 'UVCR'},
|
{'55', 'UVCR'},
|
||||||
{'56', 'Water Soluble PVA'},
|
{'56', 'Water Soluble PVA'},
|
||||||
}
|
}
|
||||||
local _colors = {
|
local _colors = {
|
||||||
{'30', 'Bronze'},
|
{'30', 'Bronze'},
|
||||||
{'31', 'Silver'},
|
{'31', 'Silver'},
|
||||||
{'32', 'Clear Red'},
|
{'32', 'Clear Red'},
|
||||||
{'33', 'Clear'},
|
{'33', 'Clear'},
|
||||||
{'34', 'Bottle Green'},
|
{'34', 'Bottle Green'},
|
||||||
{'35', 'Neon Magenta'},
|
{'35', 'Neon Magenta'},
|
||||||
{'36', 'SteelBlue'},
|
{'36', 'SteelBlue'},
|
||||||
{'37', 'Sun Orange'},
|
{'37', 'Sun Orange'},
|
||||||
{'38', 'Pearl White'},
|
{'38', 'Pearl White'},
|
||||||
{'39', 'Copper'},
|
{'39', 'Copper'},
|
||||||
{'41', 'Purple'},
|
{'41', 'Purple'},
|
||||||
{'42', 'Blue'},
|
{'42', 'Blue'},
|
||||||
{'43', 'Neon Tangerine'},
|
{'43', 'Neon Tangerine'},
|
||||||
{'44', 'Viridity'},
|
{'44', 'Viridity'},
|
||||||
{'45', 'Olivine'},
|
{'45', 'Olivine'},
|
||||||
{'46', 'Gold'},
|
{'46', 'Gold'},
|
||||||
{'47', 'Green'},
|
{'47', 'Green'},
|
||||||
{'48', 'Neon Green'},
|
{'48', 'Neon Green'},
|
||||||
{'49', 'Snow White'},
|
{'49', 'Snow White'},
|
||||||
{'4A', 'Neon Yellow'},
|
{'4A', 'Neon Yellow'},
|
||||||
{'4B', 'Black'},
|
{'4B', 'Black'},
|
||||||
{'4C', 'Violet'},
|
{'4C', 'Violet'},
|
||||||
{'4D', 'Grape Purple'},
|
{'4D', 'Grape Purple'},
|
||||||
{'4E', 'Purpurine'},
|
{'4E', 'Purpurine'},
|
||||||
{'4F', 'Clear Yellow'},
|
{'4F', 'Clear Yellow'},
|
||||||
{'50', 'Clear Green'},
|
{'50', 'Clear Green'},
|
||||||
{'51', 'Clear Tangerine'},
|
{'51', 'Clear Tangerine'},
|
||||||
{'52', 'Red'},
|
{'52', 'Red'},
|
||||||
{'53', 'Cyber Yellow'},
|
{'53', 'Cyber Yellow'},
|
||||||
{'54', 'Tangerine'},
|
{'54', 'Tangerine'},
|
||||||
{'55', 'Clear Blue'},
|
{'55', 'Clear Blue'},
|
||||||
{'56', 'Clear Purple'},
|
{'56', 'Clear Purple'},
|
||||||
{'57', 'White'},
|
{'57', 'White'},
|
||||||
{'58', 'Clear Magenta'},
|
{'58', 'Clear Magenta'},
|
||||||
{'59', 'Yellow'},
|
{'59', 'Yellow'},
|
||||||
{'5A', 'Nature'},
|
{'5A', 'Nature'},
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
--
|
--
|
||||||
local function find( arr, name )
|
local function find( arr, name )
|
||||||
if not name then return nil end
|
if not name then return nil end
|
||||||
name = name:lower()
|
name = name:lower()
|
||||||
for k, v in pairs(arr) do
|
for k, v in pairs(arr) do
|
||||||
if ( v[2]:lower() == name or v[1]:lower() == name ) then
|
if ( v[2]:lower() == name or v[1]:lower() == name ) then
|
||||||
return v
|
return v
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
--
|
--
|
||||||
local function list( arr, desc )
|
local function list( arr, desc )
|
||||||
print ('Value\t'..desc)
|
print ('Value\t'..desc)
|
||||||
print (string.rep('=', 20))
|
print (string.rep('=', 20))
|
||||||
for k, v in pairs(arr) do
|
for k, v in pairs(arr) do
|
||||||
print(("%s\t%s"):format(v[1],v[2]))
|
print(("%s\t%s"):format(v[1],v[2]))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
local function dbg(args)
|
local function dbg(args)
|
||||||
if not DEBUG then return end
|
if not DEBUG then return end
|
||||||
|
|
||||||
if type(args) == 'table' then
|
if type(args) == 'table' then
|
||||||
local i = 1
|
local i = 1
|
||||||
while result[i] do
|
while result[i] do
|
||||||
dbg(result[i])
|
dbg(result[i])
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print('###', args)
|
print('###', args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print('ERROR: ',err)
|
print('ERROR: ',err)
|
||||||
return nil,err
|
return nil,err
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(copyright)
|
print(copyright)
|
||||||
print(version)
|
print(version)
|
||||||
print(desc)
|
print(desc)
|
||||||
print('Example usage')
|
print('Example usage')
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- Exit message
|
-- Exit message
|
||||||
local function ExitMsg(msg)
|
local function ExitMsg(msg)
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print(msg)
|
print(msg)
|
||||||
print()
|
print()
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
--
|
--
|
||||||
local function write_tag(uid, t)
|
local function write_tag(uid, t)
|
||||||
|
|
||||||
print('Writing to tag')
|
print('Writing to tag')
|
||||||
core.console('hf mf dbg 0')
|
core.console('hf mf dbg 0')
|
||||||
|
|
||||||
local cmd = ''
|
local cmd = ''
|
||||||
local pwd, pack = core.keygen_algo_d(uid)
|
local pwd, pack = core.keygen_algo_d(uid)
|
||||||
|
|
||||||
for i= 8, 23 do
|
for i= 8, 23 do
|
||||||
cmd = ('hf mfu wrbl b %02d d %s k %08X'):format(i, t[i], pwd)
|
cmd = ('hf mfu wrbl b %02d d %s k %08X'):format(i, t[i], pwd)
|
||||||
core.console(cmd)
|
core.console(cmd)
|
||||||
end
|
end
|
||||||
|
|
||||||
--cfg1
|
--cfg1
|
||||||
core.console(('hf mfu wrbl b 42 d %s k %08X'):format(t[42], pwd))
|
core.console(('hf mfu wrbl b 42 d %s k %08X'):format(t[42], pwd))
|
||||||
--cfg0
|
--cfg0
|
||||||
core.console(('hf mfu wrbl b 41 d %s k %08X'):format(t[41], pwd))
|
core.console(('hf mfu wrbl b 41 d %s k %08X'):format(t[41], pwd))
|
||||||
--dynamic
|
--dynamic
|
||||||
core.console(('hf mfu wrbl b 40 d %s k %08X'):format(t[40], pwd))
|
core.console(('hf mfu wrbl b 40 d %s k %08X'):format(t[40], pwd))
|
||||||
|
|
||||||
core.console('hf mf dbg 1')
|
core.console('hf mf dbg 1')
|
||||||
print('Done')
|
print('Done')
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- configures a magic NTAG for NTAG213, with UID and PWD,PACK.
|
-- configures a magic NTAG for NTAG213, with UID and PWD,PACK.
|
||||||
local function configure_magic_ntag(uid)
|
local function configure_magic_ntag(uid)
|
||||||
|
|
||||||
print('Configuring MAGIC NTAG')
|
print('Configuring MAGIC NTAG')
|
||||||
-- Save the global args, those are *our* arguments
|
-- Save the global args, those are *our* arguments
|
||||||
local myargs = args
|
local myargs = args
|
||||||
|
|
||||||
local pwd, pack = core.keygen_algo_d(uid)
|
local pwd, pack = core.keygen_algo_d(uid)
|
||||||
|
|
||||||
-- Set the arguments for mfu_magic script v1.0.8
|
-- Set the arguments for mfu_magic script v1.0.8
|
||||||
-- -t 12 == configure NTAG213F
|
-- -t 12 == configure NTAG213F
|
||||||
-- -u == set UID
|
-- -u == set UID
|
||||||
-- -p == set pwd
|
-- -p == set pwd
|
||||||
-- -a == set pack
|
-- -a == set pack
|
||||||
args =('-t 12 -u %s -p %08X -a %04X'):format(uid, pwd, pack)
|
args =('-t 12 -u %s -p %08X -a %04X'):format(uid, pwd, pack)
|
||||||
require('../scripts/mfu_magic')
|
require('../scripts/mfu_magic')
|
||||||
|
|
||||||
-- Set back args. Not that it's used, just for the karma...
|
-- Set back args. Not that it's used, just for the karma...
|
||||||
args = myargs
|
args = myargs
|
||||||
|
|
||||||
print('Done')
|
print('Done')
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- generates random hex numbers between 31-39
|
-- generates random hex numbers between 31-39
|
||||||
local function random_num_hex(length)
|
local function random_num_hex(length)
|
||||||
local str = ""
|
local str = ""
|
||||||
local i
|
local i
|
||||||
for i = 1, length, 1 do
|
for i = 1, length, 1 do
|
||||||
str = str..math.random(31, 39)
|
str = str..math.random(31, 39)
|
||||||
end
|
end
|
||||||
return str
|
return str
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
--
|
--
|
||||||
local function nwo( val )
|
local function nwo( val )
|
||||||
local b1 = band(val, 0xFF)
|
local b1 = band(val, 0xFF)
|
||||||
local b2 = band( rshift(val, 8), 0xFF)
|
local b2 = band( rshift(val, 8), 0xFF)
|
||||||
local b3 = band( rshift(val, 16), 0xFF)
|
local b3 = band( rshift(val, 16), 0xFF)
|
||||||
local b4 = band( rshift(val, 24), 0xFF)
|
local b4 = band( rshift(val, 24), 0xFF)
|
||||||
return ('%02X%02X%02X%02X'):format(b1, b2, b3, b4)
|
return ('%02X%02X%02X%02X'):format(b1, b2, b3, b4)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- NTAG213 template
|
-- NTAG213 template
|
||||||
local function template_NTAG213(uid, material, color, length, manufacture, sales)
|
local function template_NTAG213(uid, material, color, length, manufacture, sales)
|
||||||
local pwd, pack = core.keygen_algo_d(uid)
|
local pwd, pack = core.keygen_algo_d(uid)
|
||||||
|
|
||||||
local m = tonumber(length, 10) * 1000
|
local m = tonumber(length, 10) * 1000
|
||||||
local m_str = nwo(m)
|
local m_str = nwo(m)
|
||||||
|
|
||||||
local t = {}
|
local t = {}
|
||||||
-- default empty file
|
-- default empty file
|
||||||
for i = 0,42 do
|
for i = 0,42 do
|
||||||
t[i] = '00000000'
|
t[i] = '00000000'
|
||||||
end
|
end
|
||||||
-- t[4] = '0103A00C' --
|
-- t[4] = '0103A00C' --
|
||||||
-- t[5] = '340300FE' --
|
-- t[5] = '340300FE' --
|
||||||
-- 6,7
|
-- 6,7
|
||||||
t[8] = '5A'..material..color..'00' -- 5A, material, color, 00
|
t[8] = '5A'..material..color..'00' -- 5A, material, color, 00
|
||||||
t[9] = '00'..random_num_hex(3) -- 00, three bytes serial number
|
t[9] = '00'..random_num_hex(3) -- 00, three bytes serial number
|
||||||
t[10] = m_str -- total capacity
|
t[10] = m_str -- total capacity
|
||||||
t[11] = m_str -- total capacity
|
t[11] = m_str -- total capacity
|
||||||
t[12] = 'D2002D00' -- fixed
|
t[12] = 'D2002D00' -- fixed
|
||||||
t[13] = manufacture..sales -- regioner,
|
t[13] = manufacture..sales -- regioner,
|
||||||
t[14] = random_num_hex(4) -- serial number
|
t[14] = random_num_hex(4) -- serial number
|
||||||
-- 15,16
|
-- 15,16
|
||||||
t[17] = '34000000' -- fixed
|
t[17] = '34000000' -- fixed
|
||||||
-- 18,19
|
-- 18,19
|
||||||
-- remaining capacity of spool
|
-- remaining capacity of spool
|
||||||
t[20] = m_str
|
t[20] = m_str
|
||||||
t[21] = nwo( bxor( m, 0x54321248))
|
t[21] = nwo( bxor( m, 0x54321248))
|
||||||
t[22] = nwo( bxor( (m - 3876923 ), 0x31275455))
|
t[22] = nwo( bxor( (m - 3876923 ), 0x31275455))
|
||||||
t[23] = nwo( bxor( (m + 6923923 ), 0x76235481))
|
t[23] = nwo( bxor( (m + 6923923 ), 0x76235481))
|
||||||
-- 24-39
|
-- 24-39
|
||||||
t[40] = '000000BD' --dynamic
|
t[40] = '000000BD' --dynamic
|
||||||
t[41] = '07000008' --cfg0
|
t[41] = '07000008' --cfg0
|
||||||
t[42] = '80050000' --cfg1
|
t[42] = '80050000' --cfg1
|
||||||
t[43] = ('%08X'):format(pwd)
|
t[43] = ('%08X'):format(pwd)
|
||||||
t[44] = ('%04X0000'):format(pack)
|
t[44] = ('%04X0000'):format(pack)
|
||||||
return t
|
return t
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- outputs the called arguments
|
-- outputs the called arguments
|
||||||
local function print_conf(uid, material, color, length, producer, sales )
|
local function print_conf(uid, material, color, length, producer, sales )
|
||||||
print('Create tag as following')
|
print('Create tag as following')
|
||||||
print( string.rep('--',16) )
|
print( string.rep('--',16) )
|
||||||
print('UID ', uid)
|
print('UID ', uid)
|
||||||
print('Material ', material[2])
|
print('Material ', material[2])
|
||||||
print('Color ', color[2])
|
print('Color ', color[2])
|
||||||
print('Spool length ', length)
|
print('Spool length ', length)
|
||||||
print('Region')
|
print('Region')
|
||||||
print(' manufacturer', producer[2])
|
print(' manufacturer', producer[2])
|
||||||
print(' sales ', sales[2])
|
print(' sales ', sales[2])
|
||||||
print( string.rep('--',16) )
|
print( string.rep('--',16) )
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- self test
|
-- self test
|
||||||
local function selftest()
|
local function selftest()
|
||||||
list(_regions, 'Regions')
|
list(_regions, 'Regions')
|
||||||
list(_materials, 'Materials')
|
list(_materials, 'Materials')
|
||||||
list(_colors, 'Colors')
|
list(_colors, 'Colors')
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- The main entry point
|
-- The main entry point
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
math.randomseed(os.time());
|
math.randomseed(os.time());
|
||||||
math.random();
|
math.random();
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print()
|
print()
|
||||||
|
|
||||||
local uid = '04C5DF4A6D5180'
|
local uid = '04C5DF4A6D5180'
|
||||||
local useUID = false
|
local useUID = false
|
||||||
local useMAGIC = false
|
local useMAGIC = false
|
||||||
local material, color, length, producer, sales
|
local material, color, length, producer, sales
|
||||||
|
|
||||||
if #args == 0 then return help() end
|
if #args == 0 then return help() end
|
||||||
|
|
||||||
-- Read the parameters
|
-- Read the parameters
|
||||||
for o, a in getopt.getopt(args, 'ht1u:l:m:c:p:s:') do
|
for o, a in getopt.getopt(args, 'ht1u:l:m:c:p:s:') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
if o == "t" then return selftest() end
|
if o == "t" then return selftest() end
|
||||||
if o == "u" then uid = a; useUID = true end
|
if o == "u" then uid = a; useUID = true end
|
||||||
if o == "m" then material = a end
|
if o == "m" then material = a end
|
||||||
if o == "c" then color = a end
|
if o == "c" then color = a end
|
||||||
if o == "l" then length = tonumber(a) end
|
if o == "l" then length = tonumber(a) end
|
||||||
if o == "p" then producer = a end
|
if o == "p" then producer = a end
|
||||||
if o == "s" then sales = a end
|
if o == "s" then sales = a end
|
||||||
if o == "1" then useMAGIC = true end
|
if o == "1" then useMAGIC = true end
|
||||||
end
|
end
|
||||||
|
|
||||||
color = find(_colors, color)
|
color = find(_colors, color)
|
||||||
if not color then list(_colors, 'Colors'); return oops('\n\nNot valid color') end
|
if not color then list(_colors, 'Colors'); return oops('\n\nNot valid color') end
|
||||||
|
|
||||||
material = find(_materials, material)
|
material = find(_materials, material)
|
||||||
if not material then list(_materials, 'Materials'); return oops('\n\nNot valid material') end
|
if not material then list(_materials, 'Materials'); return oops('\n\nNot valid material') end
|
||||||
|
|
||||||
producer = find(_manufacturers, producer)
|
producer = find(_manufacturers, producer)
|
||||||
if not producer then list(_manufacturers, 'Regions Manufacturers'); return oops('\n\nNo valid manufacturer region') end
|
if not producer then list(_manufacturers, 'Regions Manufacturers'); return oops('\n\nNo valid manufacturer region') end
|
||||||
|
|
||||||
sales = find(_sales, sales)
|
sales = find(_sales, sales)
|
||||||
if not sales then list(_sales, 'Regions Sales'); return oops('\n\nNo valid sales region') end
|
if not sales then list(_sales, 'Regions Sales'); return oops('\n\nNo valid sales region') end
|
||||||
|
|
||||||
if length > 300 then
|
if length > 300 then
|
||||||
return oops('\n\nNot valid spool length. Must be lesser than 300')
|
return oops('\n\nNot valid spool length. Must be lesser than 300')
|
||||||
end
|
end
|
||||||
|
|
||||||
if useUID then
|
if useUID then
|
||||||
-- uid string checks
|
-- uid string checks
|
||||||
if uid == nil then return oops('empty uid string') end
|
if uid == nil then return oops('empty uid string') end
|
||||||
if #uid == 0 then return oops('empty uid string') end
|
if #uid == 0 then return oops('empty uid string') end
|
||||||
if #uid ~= 14 then return oops('uid wrong length. Should be 7 hex bytes') end
|
if #uid ~= 14 then return oops('uid wrong length. Should be 7 hex bytes') end
|
||||||
else
|
else
|
||||||
-- GET TAG UID
|
-- GET TAG UID
|
||||||
local tag, err = lib14a.read(false, true)
|
local tag, err = lib14a.read(false, true)
|
||||||
if not tag then return oops(err) end
|
if not tag then return oops(err) end
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
uid = tag.uid
|
uid = tag.uid
|
||||||
end
|
end
|
||||||
|
|
||||||
--print
|
--print
|
||||||
print_conf(uid, material, color, length, producer, sales )
|
print_conf(uid, material, color, length, producer, sales )
|
||||||
|
|
||||||
-- create template
|
-- create template
|
||||||
local t = template_NTAG213(uid, material[1], color[1], length, producer[1], sales[1])
|
local t = template_NTAG213(uid, material[1], color[1], length, producer[1], sales[1])
|
||||||
|
|
||||||
-- using MAGIC NTAG
|
-- using MAGIC NTAG
|
||||||
if useMAGIC then
|
if useMAGIC then
|
||||||
configure_magic_ntag(uid)
|
configure_magic_ntag(uid)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- write template data to tag
|
-- write template data to tag
|
||||||
write_tag(uid, t)
|
write_tag(uid, t)
|
||||||
end
|
end
|
||||||
|
|
||||||
main(args)
|
main(args)
|
||||||
@@ -12,28 +12,28 @@ For more info, check the comments in the code
|
|||||||
|
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
print(desc)
|
print(desc)
|
||||||
print("These parameters were passed")
|
print("These parameters were passed")
|
||||||
--[[
|
--[[
|
||||||
When passing parameters,
|
When passing parameters,
|
||||||
x: means that a value should follow x
|
x: means that a value should follow x
|
||||||
y means that 'y' is a flag, either on or off
|
y means that 'y' is a flag, either on or off
|
||||||
So, the string a:b:def means that we support up to
|
So, the string a:b:def means that we support up to
|
||||||
5 parameters; two with values and three flags. The following
|
5 parameters; two with values and three flags. The following
|
||||||
should be valid:
|
should be valid:
|
||||||
|
|
||||||
script run parameters.lua -a 1 -blala -c -de
|
script run parameters.lua -a 1 -blala -c -de
|
||||||
|
|
||||||
Notice two things:
|
Notice two things:
|
||||||
1. 'blala' works just like 'b lala', both set 'b' to 'lala'
|
1. 'blala' works just like 'b lala', both set 'b' to 'lala'
|
||||||
2. Flags can be put together, '-de' is the same as '-d -e'
|
2. Flags can be put together, '-de' is the same as '-d -e'
|
||||||
3. The format -b=lala is *not* supported
|
3. The format -b=lala is *not* supported
|
||||||
4. The format b lala (without -) is *not* supported
|
4. The format b lala (without -) is *not* supported
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
for o, a in getopt.getopt(args, 'a:b:ced') do
|
for o, a in getopt.getopt(args, 'a:b:ced') do
|
||||||
print(o, a)
|
print(o, a)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,128 +14,128 @@ It was meant to be used as a help tool after using the BogRun standalone mode.
|
|||||||
usage =
|
usage =
|
||||||
[[
|
[[
|
||||||
Usage:
|
Usage:
|
||||||
script run read_pwd_mem -h -o <offset> -l <length> -k <keylength>
|
script run read_pwd_mem -h -o <offset> -l <length> -k <keylength>
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h : this help
|
-h : this help
|
||||||
-o <offset> : memory offset, default is 0
|
-o <offset> : memory offset, default is 0
|
||||||
-l <length> : length in bytes, default is 256
|
-l <length> : length in bytes, default is 256
|
||||||
-k <keylen> : key length in bytes <4|6|8> , default is 4
|
-k <keylen> : key length in bytes <4|6|8> , default is 4
|
||||||
-m : print Mifare dictionary keys
|
-m : print Mifare dictionary keys
|
||||||
-t : print t55xx dictionary passwords
|
-t : print t55xx dictionary passwords
|
||||||
-i : print iClass dictionary keys
|
-i : print iClass dictionary keys
|
||||||
]]
|
]]
|
||||||
example =
|
example =
|
||||||
[[
|
[[
|
||||||
-- This will scan the first 256 bytes of flash memory for stored passwords
|
-- This will scan the first 256 bytes of flash memory for stored passwords
|
||||||
script run read_pwd_mem
|
script run read_pwd_mem
|
||||||
|
|
||||||
-- This will scan 256 bytes of flash memory at offset 64 for stored passwords
|
-- This will scan 256 bytes of flash memory at offset 64 for stored passwords
|
||||||
script run read_pwd_mem -o 64
|
script run read_pwd_mem -o 64
|
||||||
|
|
||||||
-- This will scan 32 bytes of flash memory at offset 64 for stored passwords
|
-- This will scan 32 bytes of flash memory at offset 64 for stored passwords
|
||||||
script run read_pwd_mem -o 64 -l 32
|
script run read_pwd_mem -o 64 -l 32
|
||||||
|
|
||||||
-- This will print found
|
-- This will print found
|
||||||
script run read_pwd_mem -o 241664 -k 6
|
script run read_pwd_mem -o 241664 -k 6
|
||||||
]]
|
]]
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print("ERROR: ", err)
|
print("ERROR: ", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(copyright)
|
print(copyright)
|
||||||
print(version)
|
print(version)
|
||||||
print(desc)
|
print(desc)
|
||||||
print(usage)
|
print(usage)
|
||||||
print('Example usage:')
|
print('Example usage:')
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- The main entry point
|
-- The main entry point
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print()
|
print()
|
||||||
|
|
||||||
local data, err, quadlet
|
local data, err, quadlet
|
||||||
local cnt = 0
|
local cnt = 0
|
||||||
local offset = 0
|
local offset = 0
|
||||||
local length = 256
|
local length = 256
|
||||||
local keylength = 4
|
local keylength = 4
|
||||||
local usedkey = false
|
local usedkey = false
|
||||||
|
|
||||||
for o, a in getopt.getopt(args, 'ho:l:k:mti') do
|
for o, a in getopt.getopt(args, 'ho:l:k:mti') do
|
||||||
|
|
||||||
-- help
|
-- help
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
|
|
||||||
-- offset
|
-- offset
|
||||||
if o == "o" then offset = tonumber(a) end
|
if o == "o" then offset = tonumber(a) end
|
||||||
|
|
||||||
-- num of bytes to read
|
-- num of bytes to read
|
||||||
if o == "l" then length = tonumber(a) end
|
if o == "l" then length = tonumber(a) end
|
||||||
|
|
||||||
-- keylength
|
-- keylength
|
||||||
if o == "k" then keylength = tonumber(a); usedkey = true end
|
if o == "k" then keylength = tonumber(a); usedkey = true end
|
||||||
|
|
||||||
if o == "m" then keylength =6; usedkey = true; offset = 0x3F000-0x4000; end
|
if o == "m" then keylength =6; usedkey = true; offset = 0x3F000-0x4000; end
|
||||||
if o == "t" then keylength =4; usedkey = true; offset = 0x3F000-0x3000; end
|
if o == "t" then keylength =4; usedkey = true; offset = 0x3F000-0x3000; end
|
||||||
if o == "i" then keylength =8; usedkey = true; offset = 0x3F000-0x5000; end
|
if o == "i" then keylength =8; usedkey = true; offset = 0x3F000-0x5000; end
|
||||||
end
|
end
|
||||||
|
|
||||||
if length < 0 or length > 256 then
|
if length < 0 or length > 256 then
|
||||||
return oops('Error: Length is not valid. Must be less than 256')
|
return oops('Error: Length is not valid. Must be less than 256')
|
||||||
end
|
end
|
||||||
|
|
||||||
if (offset < 0) or (offset % 4 ~= 0) then
|
if (offset < 0) or (offset % 4 ~= 0) then
|
||||||
return oops('Error: Offset is not valid. Mod-4 values are only allowed.')
|
return oops('Error: Offset is not valid. Mod-4 values are only allowed.')
|
||||||
end
|
end
|
||||||
|
|
||||||
print('Memory offset', offset)
|
print('Memory offset', offset)
|
||||||
print('Length ', length)
|
print('Length ', length)
|
||||||
print('Key length ', keylength)
|
print('Key length ', keylength)
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
|
|
||||||
if usedkey then length = 4096 end
|
if usedkey then length = 4096 end
|
||||||
|
|
||||||
data, err = core.GetFromFlashMem(offset, length)
|
data, err = core.GetFromFlashMem(offset, length)
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
|
|
||||||
if usedkey then
|
if usedkey then
|
||||||
|
|
||||||
_, keys, s = bin.unpack('SH'..length-2, data)
|
_, keys, s = bin.unpack('SH'..length-2, data)
|
||||||
if keys == 0xFFFF then return "No keys found in section" end
|
if keys == 0xFFFF then return "No keys found in section" end
|
||||||
|
|
||||||
local kl = keylength * 2
|
local kl = keylength * 2
|
||||||
for i = 1, keys do
|
for i = 1, keys do
|
||||||
|
|
||||||
key = string.sub(s, (i - 1) * kl + 1, i * kl )
|
key = string.sub(s, (i - 1) * kl + 1, i * kl )
|
||||||
print(string.format("[%02d] %s",i, key))
|
print(string.format("[%02d] %s",i, key))
|
||||||
end
|
end
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( ('[+] found %d passwords'):format(keys))
|
print( ('[+] found %d passwords'):format(keys))
|
||||||
else
|
else
|
||||||
|
|
||||||
_, s = bin.unpack('H'..length, data)
|
_, s = bin.unpack('H'..length, data)
|
||||||
|
|
||||||
local cnt = 0, i
|
local cnt = 0, i
|
||||||
for i = 1, (length/keylength) do
|
for i = 1, (length/keylength) do
|
||||||
|
|
||||||
key = string.sub(s, (i-1)*8+1, i*8)
|
key = string.sub(s, (i-1)*8+1, i*8)
|
||||||
if key == "FFFFFFFF" then break end
|
if key == "FFFFFFFF" then break end
|
||||||
print(string.format("[%02d] %s",i, key))
|
print(string.format("[%02d] %s",i, key))
|
||||||
cnt = cnt + 1
|
cnt = cnt + 1
|
||||||
end
|
end
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( ('[+] found %d passwords'):format(cnt))
|
print( ('[+] found %d passwords'):format(cnt))
|
||||||
end
|
end
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
end
|
end
|
||||||
|
|
||||||
main(args)
|
main(args)
|
||||||
|
|||||||
@@ -9,95 +9,95 @@ from the dead when it's block 0 has been written with bad values.
|
|||||||
or mifare Ultralight magic card which answers to chinese backdoor commands
|
or mifare Ultralight magic card which answers to chinese backdoor commands
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h this help
|
-h this help
|
||||||
-u remagic a Ultralight tag w 7 bytes UID.
|
-u remagic a Ultralight tag w 7 bytes UID.
|
||||||
]]
|
]]
|
||||||
---
|
---
|
||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
local function dbg(args)
|
local function dbg(args)
|
||||||
if DEBUG then
|
if DEBUG then
|
||||||
print('###', args)
|
print('###', args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print('ERROR: ',err)
|
print('ERROR: ',err)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print('Example usage')
|
print('Example usage')
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function cmdUltralight()
|
local function cmdUltralight()
|
||||||
return {
|
return {
|
||||||
--[[
|
--[[
|
||||||
--]]
|
--]]
|
||||||
[0] = "hf 14a raw -p -a -b 7 40",
|
[0] = "hf 14a raw -p -a -b 7 40",
|
||||||
[1] = "hf 14a raw -p -a 43",
|
[1] = "hf 14a raw -p -a 43",
|
||||||
[2] = "hf 14a raw -c -a A2005380712A",
|
[2] = "hf 14a raw -c -a A2005380712A",
|
||||||
[3] = "hf 14a raw -p -a -b 7 40",
|
[3] = "hf 14a raw -p -a -b 7 40",
|
||||||
[4] = "hf 14a raw -p -a 43",
|
[4] = "hf 14a raw -p -a 43",
|
||||||
[5] = "hf 14a raw -c -a A2010200D980",
|
[5] = "hf 14a raw -c -a A2010200D980",
|
||||||
[6] = "hf 14a raw -p -a -b 7 40",
|
[6] = "hf 14a raw -p -a -b 7 40",
|
||||||
[7] = "hf 14a raw -p -a 43",
|
[7] = "hf 14a raw -p -a 43",
|
||||||
[8] = "hf 14a raw -c -a A2025B480000",
|
[8] = "hf 14a raw -c -a A2025B480000",
|
||||||
[9] = "hf 14a raw -c -a 5000",
|
[9] = "hf 14a raw -c -a 5000",
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
local function cmdClassic()
|
local function cmdClassic()
|
||||||
return {
|
return {
|
||||||
--[[
|
--[[
|
||||||
--]]
|
--]]
|
||||||
[0] = "hf 14a raw -p -a -b 7 40",
|
[0] = "hf 14a raw -p -a -b 7 40",
|
||||||
[1] = "hf 14a raw -p -a 43",
|
[1] = "hf 14a raw -p -a 43",
|
||||||
[2] = "hf 14a raw -c -p -a A000",
|
[2] = "hf 14a raw -c -p -a A000",
|
||||||
[3] = "hf 14a raw -c -p -a 01020304049802000000000000001001",
|
[3] = "hf 14a raw -c -p -a 01020304049802000000000000001001",
|
||||||
[4] = "hf 14a raw -c -a 5000",
|
[4] = "hf 14a raw -c -a 5000",
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
local function cmdRestoreST()
|
local function cmdRestoreST()
|
||||||
local arr = {}
|
local arr = {}
|
||||||
for i = 0, 15 do
|
for i = 0, 15 do
|
||||||
local blk = 3 + (4*i)
|
local blk = 3 + (4*i)
|
||||||
arr[i] = "hf mf csetbl "..blk.." FFFFFFFFFFFFFF078000FFFFFFFFFFFF"
|
arr[i] = "hf mf csetbl "..blk.." FFFFFFFFFFFFFF078000FFFFFFFFFFFF"
|
||||||
end
|
end
|
||||||
return arr
|
return arr
|
||||||
end
|
end
|
||||||
local function sendCmds( cmds )
|
local function sendCmds( cmds )
|
||||||
for i = 0, #cmds do
|
for i = 0, #cmds do
|
||||||
if cmds[i] then
|
if cmds[i] then
|
||||||
print ( cmds[i] )
|
print ( cmds[i] )
|
||||||
core.console( cmds[i] )
|
core.console( cmds[i] )
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- The main entry point
|
-- The main entry point
|
||||||
function main(args)
|
function main(args)
|
||||||
|
|
||||||
local i
|
local i
|
||||||
local cmds = {}
|
local cmds = {}
|
||||||
local isUltralight = false
|
local isUltralight = false
|
||||||
|
|
||||||
-- Read the parameters
|
-- Read the parameters
|
||||||
for o, a in getopt.getopt(args, 'hu') do
|
for o, a in getopt.getopt(args, 'hu') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
if o == "u" then isUltralight = true end
|
if o == "u" then isUltralight = true end
|
||||||
end
|
end
|
||||||
|
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
if isUltralight then
|
if isUltralight then
|
||||||
sendCmds ( cmdUltralight() )
|
sendCmds ( cmdUltralight() )
|
||||||
else
|
else
|
||||||
sendCmds( cmdClassic() )
|
sendCmds( cmdClassic() )
|
||||||
sendCmds( cmdRestoreST() )
|
sendCmds( cmdRestoreST() )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
main(args)
|
main(args)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ local format=string.format
|
|||||||
local floor=math.floor
|
local floor=math.floor
|
||||||
|
|
||||||
example =[[
|
example =[[
|
||||||
1. script run test_t55x7_ask
|
1. script run test_t55x7_ask
|
||||||
]]
|
]]
|
||||||
author = "Iceman"
|
author = "Iceman"
|
||||||
usage = "script run test_t55x7_ask"
|
usage = "script run test_t55x7_ask"
|
||||||
@@ -16,7 +16,7 @@ This script will program a T55x7 TAG with the configuration: block 0x00 data 0x0
|
|||||||
The outlined procedure is as following:
|
The outlined procedure is as following:
|
||||||
|
|
||||||
--ASK
|
--ASK
|
||||||
00 00 80 40
|
00 00 80 40
|
||||||
-- max 2
|
-- max 2
|
||||||
-- manchester
|
-- manchester
|
||||||
-- bit rate
|
-- bit rate
|
||||||
@@ -26,21 +26,21 @@ The outlined procedure is as following:
|
|||||||
"lf t55xx info"
|
"lf t55xx info"
|
||||||
|
|
||||||
Loop:
|
Loop:
|
||||||
change the configuretion block 0 with:
|
change the configuretion block 0 with:
|
||||||
-xx 00 xxxx = RF/8
|
-xx 00 xxxx = RF/8
|
||||||
-xx 04 xxxx = RF/16
|
-xx 04 xxxx = RF/16
|
||||||
-xx 08 xxxx = RF/32
|
-xx 08 xxxx = RF/32
|
||||||
-xx 0C xxxx = RF/40
|
-xx 0C xxxx = RF/40
|
||||||
-xx 10 xxxx = RF/50
|
-xx 10 xxxx = RF/50
|
||||||
-xx 14 xxxx = RF/64
|
-xx 14 xxxx = RF/64
|
||||||
-xx 18 xxxx = RF/100
|
-xx 18 xxxx = RF/100
|
||||||
-xx 1C xxxx = RF/128
|
-xx 1C xxxx = RF/128
|
||||||
|
|
||||||
|
|
||||||
testsuit for the ASK/MANCHESTER demod
|
testsuit for the ASK/MANCHESTER demod
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h : this help
|
-h : this help
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
|
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
|
||||||
@@ -51,90 +51,90 @@ local config1 = '00'
|
|||||||
local config2 = '8040'
|
local config2 = '8040'
|
||||||
|
|
||||||
local procedurecmds = {
|
local procedurecmds = {
|
||||||
[1] = '%s%02X%s',
|
[1] = '%s%02X%s',
|
||||||
[2] = 'lf t55xx detect',
|
[2] = 'lf t55xx detect',
|
||||||
[3] = 'lf t55xx info',
|
[3] = 'lf t55xx info',
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
local function dbg(args)
|
local function dbg(args)
|
||||||
if not DEBUG then
|
if not DEBUG then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if type(args) == "table" then
|
if type(args) == "table" then
|
||||||
local i = 1
|
local i = 1
|
||||||
while args[i] do
|
while args[i] do
|
||||||
dbg(args[i])
|
dbg(args[i])
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print("###", args)
|
print("###", args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- Exit message
|
-- Exit message
|
||||||
local function ExitMsg(msg)
|
local function ExitMsg(msg)
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print(msg)
|
print(msg)
|
||||||
print()
|
print()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function test()
|
local function test()
|
||||||
local y
|
local y
|
||||||
local block = "00"
|
local block = "00"
|
||||||
for y = 0x0, 0x1d, 0x4 do
|
for y = 0x0, 0x1d, 0x4 do
|
||||||
for _ = 1, #procedurecmds do
|
for _ = 1, #procedurecmds do
|
||||||
local pcmd = procedurecmds[_]
|
local pcmd = procedurecmds[_]
|
||||||
|
|
||||||
if #pcmd == 0 then
|
if #pcmd == 0 then
|
||||||
|
|
||||||
elseif _ == 1 then
|
elseif _ == 1 then
|
||||||
|
|
||||||
local config = pcmd:format(config1, y, config2)
|
local config = pcmd:format(config1, y, config2)
|
||||||
dbg(('lf t55xx write b 0 d %s'):format(config))
|
dbg(('lf t55xx write b 0 d %s'):format(config))
|
||||||
config = tonumber(config,16)
|
config = tonumber(config,16)
|
||||||
|
|
||||||
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
|
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
|
||||||
local err = core.SendCommand(writecmd:getBytes())
|
local err = core.SendCommand(writecmd:getBytes())
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
|
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
|
||||||
|
|
||||||
else
|
else
|
||||||
dbg(pcmd)
|
dbg(pcmd)
|
||||||
core.console( pcmd )
|
core.console( pcmd )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
end
|
end
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
end
|
end
|
||||||
|
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
|
|
||||||
-- Arguments for the script
|
-- Arguments for the script
|
||||||
for o, arg in getopt.getopt(args, 'h') do
|
for o, arg in getopt.getopt(args, 'h') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
end
|
end
|
||||||
|
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
test()
|
test()
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
end
|
end
|
||||||
main(args)
|
main(args)
|
||||||
@@ -4,7 +4,7 @@ local bin = require('bin')
|
|||||||
local utils = require('utils')
|
local utils = require('utils')
|
||||||
|
|
||||||
example =[[
|
example =[[
|
||||||
1. script run test_t55x7_bi
|
1. script run test_t55x7_bi
|
||||||
]]
|
]]
|
||||||
author = "Iceman"
|
author = "Iceman"
|
||||||
usage = "script run test_t55x7_bi"
|
usage = "script run test_t55x7_bi"
|
||||||
@@ -20,21 +20,21 @@ The outlined procedure is as following:
|
|||||||
"lf t55xx info"
|
"lf t55xx info"
|
||||||
|
|
||||||
Loop:
|
Loop:
|
||||||
change the configuretion block 0 with:
|
change the configuretion block 0 with:
|
||||||
-xx01xxxx = RF/8
|
-xx01xxxx = RF/8
|
||||||
-xx05xxxx = RF/16
|
-xx05xxxx = RF/16
|
||||||
-xx09xxxx = RF/32
|
-xx09xxxx = RF/32
|
||||||
-xx0Dxxxx = RF/40
|
-xx0Dxxxx = RF/40
|
||||||
-xx11xxxx = RF/50
|
-xx11xxxx = RF/50
|
||||||
-xx15xxxx = RF/64
|
-xx15xxxx = RF/64
|
||||||
-xx19xxxx = RF/100
|
-xx19xxxx = RF/100
|
||||||
-xx1Dxxxx = RF/128
|
-xx1Dxxxx = RF/128
|
||||||
|
|
||||||
|
|
||||||
testsuit for the BIPHASE demod
|
testsuit for the BIPHASE demod
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h : this help
|
-h : this help
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
|
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
|
||||||
@@ -45,90 +45,90 @@ local config1 = '00'
|
|||||||
local config2 = '0040'
|
local config2 = '0040'
|
||||||
|
|
||||||
local procedurecmds = {
|
local procedurecmds = {
|
||||||
[1] = '%s%02X%s',
|
[1] = '%s%02X%s',
|
||||||
[2] = 'lf t55xx detect',
|
[2] = 'lf t55xx detect',
|
||||||
[3] = 'lf t55xx info',
|
[3] = 'lf t55xx info',
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
local function dbg(args)
|
local function dbg(args)
|
||||||
if not DEBUG then
|
if not DEBUG then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if type(args) == "table" then
|
if type(args) == "table" then
|
||||||
local i = 1
|
local i = 1
|
||||||
while args[i] do
|
while args[i] do
|
||||||
dbg(args[i])
|
dbg(args[i])
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print("###", args)
|
print("###", args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- Exit message
|
-- Exit message
|
||||||
local function ExitMsg(msg)
|
local function ExitMsg(msg)
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print(msg)
|
print(msg)
|
||||||
print()
|
print()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function test()
|
local function test()
|
||||||
local y
|
local y
|
||||||
local block = "00"
|
local block = "00"
|
||||||
for y = 1, 0x1D, 4 do
|
for y = 1, 0x1D, 4 do
|
||||||
for _ = 1, #procedurecmds do
|
for _ = 1, #procedurecmds do
|
||||||
local pcmd = procedurecmds[_]
|
local pcmd = procedurecmds[_]
|
||||||
|
|
||||||
if #pcmd == 0 then
|
if #pcmd == 0 then
|
||||||
|
|
||||||
elseif _ == 1 then
|
elseif _ == 1 then
|
||||||
|
|
||||||
local config = pcmd:format(config1, y, config2)
|
local config = pcmd:format(config1, y, config2)
|
||||||
dbg(('lf t55xx write b 0 d %s'):format(config))
|
dbg(('lf t55xx write b 0 d %s'):format(config))
|
||||||
|
|
||||||
config = tonumber(config,16)
|
config = tonumber(config,16)
|
||||||
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
|
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
|
||||||
local err = core.SendCommand(writecmd:getBytes())
|
local err = core.SendCommand(writecmd:getBytes())
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
|
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
|
||||||
else
|
else
|
||||||
dbg(pcmd)
|
dbg(pcmd)
|
||||||
core.console( pcmd )
|
core.console( pcmd )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
end
|
end
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
|
|
||||||
-- Arguments for the script
|
-- Arguments for the script
|
||||||
for o, arg in getopt.getopt(args, 'h') do
|
for o, arg in getopt.getopt(args, 'h') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
end
|
end
|
||||||
|
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
test()
|
test()
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
end
|
end
|
||||||
main(args)
|
main(args)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ local bin = require('bin')
|
|||||||
local utils = require('utils')
|
local utils = require('utils')
|
||||||
|
|
||||||
example =[[
|
example =[[
|
||||||
1. script run test_t55x7_fsk
|
1. script run test_t55x7_fsk
|
||||||
]]
|
]]
|
||||||
author = "Iceman"
|
author = "Iceman"
|
||||||
usage = "script run test_t55x7_fsk"
|
usage = "script run test_t55x7_fsk"
|
||||||
@@ -13,7 +13,7 @@ This script will program a T55x7 TAG with the configuration: block 0x00 data 0x0
|
|||||||
The outlined procedure is as following:
|
The outlined procedure is as following:
|
||||||
|
|
||||||
--ASK
|
--ASK
|
||||||
00 00 80 40
|
00 00 80 40
|
||||||
-- max 2 blocks
|
-- max 2 blocks
|
||||||
-- FSK1
|
-- FSK1
|
||||||
-- bit rate
|
-- bit rate
|
||||||
@@ -23,21 +23,21 @@ The outlined procedure is as following:
|
|||||||
"lf t55xx info"
|
"lf t55xx info"
|
||||||
|
|
||||||
Loop:
|
Loop:
|
||||||
change the configuretion block 0 with:
|
change the configuretion block 0 with:
|
||||||
-xx 00 xxxx = RF/8
|
-xx 00 xxxx = RF/8
|
||||||
-xx 04 xxxx = RF/16
|
-xx 04 xxxx = RF/16
|
||||||
-xx 08 xxxx = RF/32
|
-xx 08 xxxx = RF/32
|
||||||
-xx 0C xxxx = RF/40
|
-xx 0C xxxx = RF/40
|
||||||
-xx 10 xxxx = RF/50
|
-xx 10 xxxx = RF/50
|
||||||
-xx 14 xxxx = RF/64
|
-xx 14 xxxx = RF/64
|
||||||
-xx 18 xxxx = RF/100
|
-xx 18 xxxx = RF/100
|
||||||
-xx 1C xxxx = RF/128
|
-xx 1C xxxx = RF/128
|
||||||
|
|
||||||
|
|
||||||
testsuit for the ASK/MANCHESTER demod
|
testsuit for the ASK/MANCHESTER demod
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h : this help
|
-h : this help
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
|
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
|
||||||
@@ -48,93 +48,93 @@ local config1 = '00'
|
|||||||
local config2 = '040'
|
local config2 = '040'
|
||||||
|
|
||||||
local procedurecmds = {
|
local procedurecmds = {
|
||||||
[1] = '%s%02X%X%s',
|
[1] = '%s%02X%X%s',
|
||||||
[2] = 'lf t55xx detect',
|
[2] = 'lf t55xx detect',
|
||||||
[3] = 'lf t55xx info',
|
[3] = 'lf t55xx info',
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
local function dbg(args)
|
local function dbg(args)
|
||||||
if not DEBUG then
|
if not DEBUG then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if type(args) == "table" then
|
if type(args) == "table" then
|
||||||
local i = 1
|
local i = 1
|
||||||
while args[i] do
|
while args[i] do
|
||||||
dbg(args[i])
|
dbg(args[i])
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print("###", args)
|
print("###", args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- Exit message
|
-- Exit message
|
||||||
local function ExitMsg(msg)
|
local function ExitMsg(msg)
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print(msg)
|
print(msg)
|
||||||
print()
|
print()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function test(modulation)
|
local function test(modulation)
|
||||||
local y
|
local y
|
||||||
local block = "00"
|
local block = "00"
|
||||||
for y = 0x0, 0x1d, 0x4 do
|
for y = 0x0, 0x1d, 0x4 do
|
||||||
for _ = 1, #procedurecmds do
|
for _ = 1, #procedurecmds do
|
||||||
local pcmd = procedurecmds[_]
|
local pcmd = procedurecmds[_]
|
||||||
|
|
||||||
if #pcmd == 0 then
|
if #pcmd == 0 then
|
||||||
|
|
||||||
elseif _ == 1 then
|
elseif _ == 1 then
|
||||||
|
|
||||||
local config = pcmd:format(config1, y, modulation, config2)
|
local config = pcmd:format(config1, y, modulation, config2)
|
||||||
dbg(('lf t55xx write b 0 d %s'):format(config))
|
dbg(('lf t55xx write b 0 d %s'):format(config))
|
||||||
|
|
||||||
config = tonumber(config,16)
|
config = tonumber(config,16)
|
||||||
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
|
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
|
||||||
local err = core.SendCommand(writecmd:getBytes())
|
local err = core.SendCommand(writecmd:getBytes())
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
|
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
|
||||||
|
|
||||||
else
|
else
|
||||||
dbg(pcmd)
|
dbg(pcmd)
|
||||||
core.console( pcmd )
|
core.console( pcmd )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
end
|
end
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
end
|
end
|
||||||
|
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
|
|
||||||
-- Arguments for the script
|
-- Arguments for the script
|
||||||
for o, arg in getopt.getopt(args, 'h') do
|
for o, arg in getopt.getopt(args, 'h') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
end
|
end
|
||||||
|
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
test(4)
|
test(4)
|
||||||
test(5)
|
test(5)
|
||||||
test(6)
|
test(6)
|
||||||
test(7)
|
test(7)
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
end
|
end
|
||||||
main(args)
|
main(args)
|
||||||
@@ -4,8 +4,8 @@ local bin = require('bin')
|
|||||||
local utils = require('utils')
|
local utils = require('utils')
|
||||||
|
|
||||||
example =[[
|
example =[[
|
||||||
1. script run test_t55x7_psk
|
1. script run test_t55x7_psk
|
||||||
2. script run test_t55x7_psk -o
|
2. script run test_t55x7_psk -o
|
||||||
]]
|
]]
|
||||||
author = "Iceman"
|
author = "Iceman"
|
||||||
usage = "script run test_t55x7_psk"
|
usage = "script run test_t55x7_psk"
|
||||||
@@ -18,21 +18,21 @@ The outlined procedure is as following:
|
|||||||
"lf t55xx info"
|
"lf t55xx info"
|
||||||
|
|
||||||
Loop OUTER:
|
Loop OUTER:
|
||||||
change the configuretion block 0 with:
|
change the configuretion block 0 with:
|
||||||
-xxxx8xxx = PSK RF/2 with Manchester modulation
|
-xxxx8xxx = PSK RF/2 with Manchester modulation
|
||||||
-xxxx1xxx = PSK RF/2 with PSK1 modulation (phase change when input changes)
|
-xxxx1xxx = PSK RF/2 with PSK1 modulation (phase change when input changes)
|
||||||
-xxxx2xxx = PSK RF/2 with PSk2 modulation (phase change on bitclk if input high)
|
-xxxx2xxx = PSK RF/2 with PSk2 modulation (phase change on bitclk if input high)
|
||||||
-xxxx3xxx = PSK RF/2 with PSk3 modulation (phase change on rising edge of input)
|
-xxxx3xxx = PSK RF/2 with PSk3 modulation (phase change on rising edge of input)
|
||||||
Loop INNER
|
Loop INNER
|
||||||
for each outer configuration, also do
|
for each outer configuration, also do
|
||||||
XXXXX0XX = PSK RF/2
|
XXXXX0XX = PSK RF/2
|
||||||
XXXXX4XX = PSK RF/4
|
XXXXX4XX = PSK RF/4
|
||||||
XXXXX8XX = PSK RF/8
|
XXXXX8XX = PSK RF/8
|
||||||
|
|
||||||
In all 12 individual test for the PSK demod
|
In all 12 individual test for the PSK demod
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h : this help
|
-h : this help
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
|
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
|
||||||
@@ -40,107 +40,107 @@ local DEBUG = true -- the debug flag
|
|||||||
|
|
||||||
-- --BLOCK 0 = 00 08 80 40 PSK
|
-- --BLOCK 0 = 00 08 80 40 PSK
|
||||||
-- -----------
|
-- -----------
|
||||||
-- 08------- bitrate
|
-- 08------- bitrate
|
||||||
-- 8----- modulation PSK1
|
-- 8----- modulation PSK1
|
||||||
-- 0---- PSK ClockRate
|
-- 0---- PSK ClockRate
|
||||||
-- 40 max 2 blocks
|
-- 40 max 2 blocks
|
||||||
|
|
||||||
local procedurecmds = {
|
local procedurecmds = {
|
||||||
[1] = '00%02X%X%X40',
|
[1] = '00%02X%X%X40',
|
||||||
[2] = 'lf t55xx detect',
|
[2] = 'lf t55xx detect',
|
||||||
[3] = 'lf t55xx info',
|
[3] = 'lf t55xx info',
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
local function dbg(args)
|
local function dbg(args)
|
||||||
if not DEBUG then
|
if not DEBUG then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if type(args) == "table" then
|
if type(args) == "table" then
|
||||||
local i = 1
|
local i = 1
|
||||||
while args[i] do
|
while args[i] do
|
||||||
dbg(args[i])
|
dbg(args[i])
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print("###", args)
|
print("###", args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- Exit message
|
-- Exit message
|
||||||
local function ExitMsg(msg)
|
local function ExitMsg(msg)
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print(msg)
|
print(msg)
|
||||||
print()
|
print()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function test(modulation)
|
local function test(modulation)
|
||||||
local bitrate
|
local bitrate
|
||||||
local clockrate
|
local clockrate
|
||||||
local block = "00"
|
local block = "00"
|
||||||
for bitrate = 0x0, 0x1d, 0x4 do
|
for bitrate = 0x0, 0x1d, 0x4 do
|
||||||
|
|
||||||
for clockrate = 0,8,4 do
|
for clockrate = 0,8,4 do
|
||||||
|
|
||||||
for _ = 1, #procedurecmds do
|
for _ = 1, #procedurecmds do
|
||||||
local cmd = procedurecmds[_]
|
local cmd = procedurecmds[_]
|
||||||
|
|
||||||
if #cmd == 0 then
|
if #cmd == 0 then
|
||||||
|
|
||||||
elseif _ == 1 then
|
elseif _ == 1 then
|
||||||
|
|
||||||
dbg("Writing to T55x7 TAG")
|
dbg("Writing to T55x7 TAG")
|
||||||
|
|
||||||
local config = cmd:format(bitrate, modulation, clockrate)
|
local config = cmd:format(bitrate, modulation, clockrate)
|
||||||
dbg(('lf t55xx write b 0 d %s'):format(config))
|
dbg(('lf t55xx write b 0 d %s'):format(config))
|
||||||
|
|
||||||
config = tonumber(config,16)
|
config = tonumber(config,16)
|
||||||
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
|
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
|
||||||
local err = core.SendCommand(writecmd:getBytes())
|
local err = core.SendCommand(writecmd:getBytes())
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
|
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
|
||||||
else
|
else
|
||||||
dbg(cmd)
|
dbg(cmd)
|
||||||
core.console( cmd )
|
core.console( cmd )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
end
|
end
|
||||||
|
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
|
|
||||||
-- Arguments for the script
|
-- Arguments for the script
|
||||||
for o, arg in getopt.getopt(args, 'h') do
|
for o, arg in getopt.getopt(args, 'h') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
end
|
end
|
||||||
|
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
test(1) -- PSK1
|
test(1) -- PSK1
|
||||||
--test(2) -- PSK2
|
--test(2) -- PSK2
|
||||||
--test(3) -- PSK3
|
--test(3) -- PSK3
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
end
|
end
|
||||||
main(args)
|
main(args)
|
||||||
|
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ local bor = bit32.bor
|
|||||||
local band = bit32.band
|
local band = bit32.band
|
||||||
|
|
||||||
example =[[
|
example =[[
|
||||||
script run tnp3clone
|
script run tnp3clone
|
||||||
script run tnp3clone -h
|
script run tnp3clone -h
|
||||||
script run tnp3clone -l
|
script run tnp3clone -l
|
||||||
script run tnp3clone -t aa00 -s 0030
|
script run tnp3clone -t aa00 -s 0030
|
||||||
|
|
||||||
]]
|
]]
|
||||||
author = "Iceman"
|
author = "Iceman"
|
||||||
@@ -23,152 +23,152 @@ desc =[[
|
|||||||
This script will try making a barebone clone of a tnp3 tag on to a magic generation1 card.
|
This script will try making a barebone clone of a tnp3 tag on to a magic generation1 card.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h : this help
|
-h : this help
|
||||||
-l : list all known toy tokens
|
-l : list all known toy tokens
|
||||||
-t <data> : toytype id, 4hex symbols
|
-t <data> : toytype id, 4hex symbols
|
||||||
-s <data> : subtype id, 4hex symbols
|
-s <data> : subtype id, 4hex symbols
|
||||||
|
|
||||||
For fun, try the following subtype id:
|
For fun, try the following subtype id:
|
||||||
0612 - Lightcore
|
0612 - Lightcore
|
||||||
0118 - Series 1
|
0118 - Series 1
|
||||||
0138 - Series 2
|
0138 - Series 2
|
||||||
0234 - Special
|
0234 - Special
|
||||||
023c - Special
|
023c - Special
|
||||||
0020 - Swapforce
|
0020 - Swapforce
|
||||||
]]
|
]]
|
||||||
|
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
end
|
end
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function waitCmd()
|
local function waitCmd()
|
||||||
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,2000)
|
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,2000)
|
||||||
if response then
|
if response then
|
||||||
local count,cmd,arg0 = bin.unpack('LL',response)
|
local count,cmd,arg0 = bin.unpack('LL',response)
|
||||||
if(arg0==1) then
|
if(arg0==1) then
|
||||||
local count,arg1,arg2,data = bin.unpack('LLH511',response,count)
|
local count,arg1,arg2,data = bin.unpack('LLH511',response,count)
|
||||||
return data:sub(1,32)
|
return data:sub(1,32)
|
||||||
else
|
else
|
||||||
return nil, "Couldn't read block."
|
return nil, "Couldn't read block."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return nil, "No response from device"
|
return nil, "No response from device"
|
||||||
end
|
end
|
||||||
|
|
||||||
local function readblock( blocknum, keyA )
|
local function readblock( blocknum, keyA )
|
||||||
-- Read block N
|
-- Read block N
|
||||||
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blocknum, arg2 = 0, arg3 = 0, data = keyA}
|
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blocknum, arg2 = 0, arg3 = 0, data = keyA}
|
||||||
err = core.SendCommand(cmd:getBytes())
|
err = core.SendCommand(cmd:getBytes())
|
||||||
if err then return nil, err end
|
if err then return nil, err end
|
||||||
local block0, err = waitCmd()
|
local block0, err = waitCmd()
|
||||||
if err then return nil, err end
|
if err then return nil, err end
|
||||||
return block0
|
return block0
|
||||||
end
|
end
|
||||||
|
|
||||||
local function readmagicblock( blocknum )
|
local function readmagicblock( blocknum )
|
||||||
-- Read block N
|
-- Read block N
|
||||||
local CSETBLOCK_SINGLE_OPERATION = 0x1F
|
local CSETBLOCK_SINGLE_OPERATION = 0x1F
|
||||||
cmd = Command:new{cmd = cmds.CMD_MIFARE_CGETBLOCK, arg1 = CSETBLOCK_SINGLE_OPERATION, arg2 = 0, arg3 = blocknum}
|
cmd = Command:new{cmd = cmds.CMD_MIFARE_CGETBLOCK, arg1 = CSETBLOCK_SINGLE_OPERATION, arg2 = 0, arg3 = blocknum}
|
||||||
err = core.SendCommand(cmd:getBytes())
|
err = core.SendCommand(cmd:getBytes())
|
||||||
if err then return nil, err end
|
if err then return nil, err end
|
||||||
local block0, err = waitCmd()
|
local block0, err = waitCmd()
|
||||||
if err then return nil, err end
|
if err then return nil, err end
|
||||||
return block0
|
return block0
|
||||||
end
|
end
|
||||||
|
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
|
|
||||||
local numBlocks = 64
|
local numBlocks = 64
|
||||||
local cset = 'hf mf csetbl '
|
local cset = 'hf mf csetbl '
|
||||||
local csetuid = 'hf mf csetuid '
|
local csetuid = 'hf mf csetuid '
|
||||||
local cget = 'hf mf cgetbl '
|
local cget = 'hf mf cgetbl '
|
||||||
local empty = '00000000000000000000000000000000'
|
local empty = '00000000000000000000000000000000'
|
||||||
local AccAndKeyB = '7F0F0869000000000000'
|
local AccAndKeyB = '7F0F0869000000000000'
|
||||||
local atqa = '0F01'
|
local atqa = '0F01'
|
||||||
local sak = '81'
|
local sak = '81'
|
||||||
-- Defaults to Gusto
|
-- Defaults to Gusto
|
||||||
local toytype = 'C201'
|
local toytype = 'C201'
|
||||||
local subtype = '0030'
|
local subtype = '0030'
|
||||||
local DEBUG = true
|
local DEBUG = true
|
||||||
|
|
||||||
-- Arguments for the script
|
-- Arguments for the script
|
||||||
for o, a in getopt.getopt(args, 'ht:s:l') do
|
for o, a in getopt.getopt(args, 'ht:s:l') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
if o == "t" then toytype = a end
|
if o == "t" then toytype = a end
|
||||||
if o == "s" then subtype = a end
|
if o == "s" then subtype = a end
|
||||||
if o == "l" then return toys.List() end
|
if o == "l" then return toys.List() end
|
||||||
end
|
end
|
||||||
|
|
||||||
if #toytype ~= 4 then return oops('[!] Wrong size - toytype. (4hex symbols)') end
|
if #toytype ~= 4 then return oops('[!] Wrong size - toytype. (4hex symbols)') end
|
||||||
if #subtype ~= 4 then return oops('[!] Wrong size - subtype. (4hex symbols)') end
|
if #subtype ~= 4 then return oops('[!] Wrong size - subtype. (4hex symbols)') end
|
||||||
|
|
||||||
-- look up type, find & validate types
|
-- look up type, find & validate types
|
||||||
local item = toys.Find( toytype, subtype)
|
local item = toys.Find( toytype, subtype)
|
||||||
if item then
|
if item then
|
||||||
print( ('[+] Looking up input: Found %s - %s (%s)'):format(item[6],item[5], item[4]) )
|
print( ('[+] Looking up input: Found %s - %s (%s)'):format(item[6],item[5], item[4]) )
|
||||||
else
|
else
|
||||||
print('[-] Didn\'t find item type. If you are sure about it, post on forum')
|
print('[-] Didn\'t find item type. If you are sure about it, post on forum')
|
||||||
end
|
end
|
||||||
--15,16
|
--15,16
|
||||||
--13-14
|
--13-14
|
||||||
|
|
||||||
-- find tag
|
-- find tag
|
||||||
result, err = lib14a.read(false, true)
|
result, err = lib14a.read(false, true)
|
||||||
if not result then return oops(err) end
|
if not result then return oops(err) end
|
||||||
|
|
||||||
-- load keys
|
-- load keys
|
||||||
local akeys = pre.GetAll(result.uid)
|
local akeys = pre.GetAll(result.uid)
|
||||||
local keyA = akeys:sub(1, 12 )
|
local keyA = akeys:sub(1, 12 )
|
||||||
|
|
||||||
local b0 = readblock(0, keyA)
|
local b0 = readblock(0, keyA)
|
||||||
if not b0 then
|
if not b0 then
|
||||||
print('[-] failed reading block with factorydefault key. Trying chinese magic read.')
|
print('[-] failed reading block with factorydefault key. Trying chinese magic read.')
|
||||||
b0, err = readmagicblock(0)
|
b0, err = readmagicblock(0)
|
||||||
if not b0 then
|
if not b0 then
|
||||||
oops('[!] '..err)
|
oops('[!] '..err)
|
||||||
return oops('[!] failed reading block with chinese magic command. Quitting...')
|
return oops('[!] failed reading block with chinese magic command. Quitting...')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
-- wipe card.
|
-- wipe card.
|
||||||
local cmd = (csetuid..'%s %s %s w'):format(result.uid, atqa, sak)
|
local cmd = (csetuid..'%s %s %s w'):format(result.uid, atqa, sak)
|
||||||
core.console(cmd)
|
core.console(cmd)
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
local b1 = toytype..string.rep('00',10)..subtype
|
local b1 = toytype..string.rep('00',10)..subtype
|
||||||
|
|
||||||
local calc = utils.Crc16(b0..b1)
|
local calc = utils.Crc16(b0..b1)
|
||||||
local calcEndian = bor(rsh(calc,8), lsh(band(calc, 0xff), 8))
|
local calcEndian = bor(rsh(calc,8), lsh(band(calc, 0xff), 8))
|
||||||
|
|
||||||
local cmd = (cset..'1 %s%04x'):format( b1, calcEndian)
|
local cmd = (cset..'1 %s%04x'):format( b1, calcEndian)
|
||||||
core.console(cmd)
|
core.console(cmd)
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
local pos, key
|
local pos, key
|
||||||
for blockNo = 2, numBlocks-1, 1 do
|
for blockNo = 2, numBlocks-1, 1 do
|
||||||
pos = (math.floor( blockNo / 4 ) * 12)+1
|
pos = (math.floor( blockNo / 4 ) * 12)+1
|
||||||
key = akeys:sub(pos, pos + 11 )
|
key = akeys:sub(pos, pos + 11 )
|
||||||
if blockNo%4 == 3 then
|
if blockNo%4 == 3 then
|
||||||
cmd = ('%s %d %s%s'):format(cset,blockNo,key,AccAndKeyB)
|
cmd = ('%s %d %s%s'):format(cset,blockNo,key,AccAndKeyB)
|
||||||
core.console(cmd)
|
core.console(cmd)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
-- Set sector trailer S0, since it has different access rights
|
-- Set sector trailer S0, since it has different access rights
|
||||||
cmd = ('%s 3 %s0f0f0f69000000000000'):format(cset, keyA)
|
cmd = ('%s 3 %s0f0f0f69000000000000'):format(cset, keyA)
|
||||||
core.console(cmd)
|
core.console(cmd)
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
end
|
end
|
||||||
main(args)
|
main(args)
|
||||||
|
|||||||
@@ -8,15 +8,15 @@ local dumplib = require('html_dumplib')
|
|||||||
local toys = require('default_toys')
|
local toys = require('default_toys')
|
||||||
|
|
||||||
example =[[
|
example =[[
|
||||||
script run tnp3dump
|
script run tnp3dump
|
||||||
script run tnp3dump -n
|
script run tnp3dump -n
|
||||||
script run tnp3dump -p
|
script run tnp3dump -p
|
||||||
script run tnp3dump -k aabbccddeeff
|
script run tnp3dump -k aabbccddeeff
|
||||||
script run tnp3dump -k aabbccddeeff -n
|
script run tnp3dump -k aabbccddeeff -n
|
||||||
script run tnp3dump -o myfile
|
script run tnp3dump -o myfile
|
||||||
script run tnp3dump -n -o myfile
|
script run tnp3dump -n -o myfile
|
||||||
script run tnp3dump -p -o myfile
|
script run tnp3dump -p -o myfile
|
||||||
script run tnp3dump -k aabbccddeeff -n -o myfile
|
script run tnp3dump -k aabbccddeeff -n -o myfile
|
||||||
]]
|
]]
|
||||||
author = "Iceman"
|
author = "Iceman"
|
||||||
usage = "script run tnp3dump -k <key> -n -p -o <filename>"
|
usage = "script run tnp3dump -k <key> -n -p -o <filename>"
|
||||||
@@ -24,11 +24,11 @@ desc =[[
|
|||||||
This script will try to dump the contents of a Mifare TNP3xxx card.
|
This script will try to dump the contents of a Mifare TNP3xxx card.
|
||||||
It will need a valid KeyA in order to find the other keys and decode the card.
|
It will need a valid KeyA in order to find the other keys and decode the card.
|
||||||
Arguments:
|
Arguments:
|
||||||
-h : this help
|
-h : this help
|
||||||
-k <key> : Sector 0 Key A.
|
-k <key> : Sector 0 Key A.
|
||||||
-n : Use the nested cmd to find all keys
|
-n : Use the nested cmd to find all keys
|
||||||
-p : Use the precalc to find all keys
|
-p : Use the precalc to find all keys
|
||||||
-o : filename for the saved dumps
|
-o : filename for the saved dumps
|
||||||
]]
|
]]
|
||||||
local RANDOM = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20'
|
local RANDOM = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20'
|
||||||
local TIMEOUT = 2500 -- Shouldn't take longer than 2 seconds
|
local TIMEOUT = 2500 -- Shouldn't take longer than 2 seconds
|
||||||
@@ -38,248 +38,248 @@ local numSectors = 16
|
|||||||
---
|
---
|
||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
function dbg(args)
|
function dbg(args)
|
||||||
if not DEBUG then return end
|
if not DEBUG then return end
|
||||||
|
|
||||||
if type(args) == "table" then
|
if type(args) == "table" then
|
||||||
local i = 1
|
local i = 1
|
||||||
while result[i] do
|
while result[i] do
|
||||||
dbg(result[i])
|
dbg(result[i])
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print("###", args)
|
print("###", args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- 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)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
return nil,err
|
return nil,err
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
function help()
|
function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- Exit message
|
-- Exit message
|
||||||
function ExitMsg(msg)
|
function ExitMsg(msg)
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print(msg)
|
print(msg)
|
||||||
print()
|
print()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function readdumpkeys(infile)
|
local function readdumpkeys(infile)
|
||||||
t = infile:read("*all")
|
t = infile:read("*all")
|
||||||
len = string.len(t)
|
len = string.len(t)
|
||||||
local len,hex = bin.unpack(("H%d"):format(len),t)
|
local len,hex = bin.unpack(("H%d"):format(len),t)
|
||||||
return hex
|
return hex
|
||||||
end
|
end
|
||||||
|
|
||||||
local function waitCmd()
|
local function waitCmd()
|
||||||
local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT)
|
local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT)
|
||||||
if response then
|
if response then
|
||||||
local count, cmd, arg0 = bin.unpack('LL',response)
|
local count, cmd, arg0 = bin.unpack('LL',response)
|
||||||
if(arg0==1) then
|
if(arg0==1) then
|
||||||
local count,arg1,arg2,data = bin.unpack('LLH511',response,count)
|
local count,arg1,arg2,data = bin.unpack('LLH511',response,count)
|
||||||
return data:sub(1,32)
|
return data:sub(1,32)
|
||||||
else
|
else
|
||||||
return nil, "Couldn't read block.. ["..arg0.."]"
|
return nil, "Couldn't read block.. ["..arg0.."]"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return nil, 'No response from device'
|
return nil, 'No response from device'
|
||||||
end
|
end
|
||||||
|
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
|
|
||||||
local keyA
|
local keyA
|
||||||
local cmd
|
local cmd
|
||||||
local err
|
local err
|
||||||
local useNested = false
|
local useNested = false
|
||||||
local usePreCalc = false
|
local usePreCalc = false
|
||||||
local cmdReadBlockString = 'hf mf rdbl %d A %s'
|
local cmdReadBlockString = 'hf mf rdbl %d A %s'
|
||||||
local input = "dumpkeys.bin"
|
local input = "dumpkeys.bin"
|
||||||
local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S");
|
local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S");
|
||||||
|
|
||||||
-- Arguments for the script
|
-- Arguments for the script
|
||||||
for o, a in getopt.getopt(args, 'hk:npo:') do
|
for o, a in getopt.getopt(args, 'hk:npo:') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
if o == "k" then keyA = a end
|
if o == "k" then keyA = a end
|
||||||
if o == "n" then useNested = true end
|
if o == "n" then useNested = true end
|
||||||
if o == "p" then usePreCalc = true end
|
if o == "p" then usePreCalc = true end
|
||||||
if o == "o" then outputTemplate = a end
|
if o == "o" then outputTemplate = a end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- validate input args.
|
-- validate input args.
|
||||||
keyA = keyA or '4b0b20107ccb'
|
keyA = keyA or '4b0b20107ccb'
|
||||||
if #(keyA) ~= 12 then
|
if #(keyA) ~= 12 then
|
||||||
return oops( string.format('Wrong length of write key (was %d) expected 12', #keyA))
|
return oops( string.format('Wrong length of write key (was %d) expected 12', #keyA))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Turn off Debug
|
-- Turn off Debug
|
||||||
local cmdSetDbgOff = "hf mf dbg 0"
|
local cmdSetDbgOff = "hf mf dbg 0"
|
||||||
core.console( cmdSetDbgOff)
|
core.console( cmdSetDbgOff)
|
||||||
|
|
||||||
result, err = lib14a.read(false, true)
|
result, err = lib14a.read(false, true)
|
||||||
if not result then
|
if not result then
|
||||||
return oops(err)
|
return oops(err)
|
||||||
end
|
end
|
||||||
|
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
-- Show tag info
|
-- Show tag info
|
||||||
print((' Found tag %s'):format(result.name))
|
print((' Found tag %s'):format(result.name))
|
||||||
|
|
||||||
dbg(('Using keyA : %s'):format(keyA))
|
dbg(('Using keyA : %s'):format(keyA))
|
||||||
|
|
||||||
--Trying to find the other keys
|
--Trying to find the other keys
|
||||||
if useNested then
|
if useNested then
|
||||||
core.console( ('hf mf nested 1 0 A %s d'):format(keyA) )
|
core.console( ('hf mf nested 1 0 A %s d'):format(keyA) )
|
||||||
end
|
end
|
||||||
|
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
local akeys = ''
|
local akeys = ''
|
||||||
if usePreCalc then
|
if usePreCalc then
|
||||||
local pre = require('precalc')
|
local pre = require('precalc')
|
||||||
akeys = pre.GetAll(result.uid)
|
akeys = pre.GetAll(result.uid)
|
||||||
dbg(akeys)
|
dbg(akeys)
|
||||||
else
|
else
|
||||||
print('Loading dumpkeys.bin')
|
print('Loading dumpkeys.bin')
|
||||||
local hex, err = utils.ReadDumpFile(input)
|
local hex, err = utils.ReadDumpFile(input)
|
||||||
if not hex then
|
if not hex then
|
||||||
return oops(err)
|
return oops(err)
|
||||||
end
|
end
|
||||||
akeys = hex:sub(0,12*16)
|
akeys = hex:sub(0,12*16)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Read block 0
|
-- Read block 0
|
||||||
dbg('Reading block 0')
|
dbg('Reading block 0')
|
||||||
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 0, arg2 = 0, arg3 = 0, data = keyA}
|
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 0, arg2 = 0, arg3 = 0, data = keyA}
|
||||||
err = core.SendCommand(cmd:getBytes())
|
err = core.SendCommand(cmd:getBytes())
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
local block0, err = waitCmd()
|
local block0, err = waitCmd()
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
|
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
-- Read block 1
|
-- Read block 1
|
||||||
dbg('Reading block 1')
|
dbg('Reading block 1')
|
||||||
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 1, arg2 = 0, arg3 = 0, data = keyA}
|
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 1, arg2 = 0, arg3 = 0, data = keyA}
|
||||||
err = core.SendCommand(cmd:getBytes())
|
err = core.SendCommand(cmd:getBytes())
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
local block1, err = waitCmd()
|
local block1, err = waitCmd()
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
|
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
local tmpHash = block0..block1..'%02x'..RANDOM
|
local tmpHash = block0..block1..'%02x'..RANDOM
|
||||||
|
|
||||||
local key
|
local key
|
||||||
local pos = 0
|
local pos = 0
|
||||||
local blockNo
|
local blockNo
|
||||||
local blocks = {}
|
local blocks = {}
|
||||||
|
|
||||||
-- main loop
|
-- main loop
|
||||||
io.write('Reading blocks > ')
|
io.write('Reading blocks > ')
|
||||||
for blockNo = 0, numBlocks-1, 1 do
|
for blockNo = 0, numBlocks-1, 1 do
|
||||||
|
|
||||||
io.flush()
|
io.flush()
|
||||||
|
|
||||||
if core.ukbhit() then
|
if core.ukbhit() then
|
||||||
print("aborted by user")
|
print("aborted by user")
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
pos = (math.floor( blockNo / 4 ) * 12)+1
|
pos = (math.floor( blockNo / 4 ) * 12)+1
|
||||||
key = akeys:sub(pos, pos + 11 )
|
key = akeys:sub(pos, pos + 11 )
|
||||||
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blockNo ,arg2 = 0,arg3 = 0, data = key}
|
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blockNo ,arg2 = 0,arg3 = 0, data = key}
|
||||||
local err = core.SendCommand(cmd:getBytes())
|
local err = core.SendCommand(cmd:getBytes())
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
local blockdata, err = waitCmd()
|
local blockdata, err = waitCmd()
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
|
|
||||||
|
|
||||||
if blockNo%4 ~= 3 then
|
if blockNo%4 ~= 3 then
|
||||||
|
|
||||||
if blockNo < 8 then
|
if blockNo < 8 then
|
||||||
-- Block 0-7 not encrypted
|
-- Block 0-7 not encrypted
|
||||||
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata)
|
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata)
|
||||||
else
|
else
|
||||||
-- blocks with zero not encrypted.
|
-- blocks with zero not encrypted.
|
||||||
if string.find(blockdata, '^0+$') then
|
if string.find(blockdata, '^0+$') then
|
||||||
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata)
|
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata)
|
||||||
else
|
else
|
||||||
local baseStr = utils.ConvertHexToAscii(tmpHash:format(blockNo))
|
local baseStr = utils.ConvertHexToAscii(tmpHash:format(blockNo))
|
||||||
local key = md5.sumhexa(baseStr)
|
local key = md5.sumhexa(baseStr)
|
||||||
local aestest = core.aes128_decrypt(key, blockdata)
|
local aestest = core.aes128_decrypt(key, blockdata)
|
||||||
local hex = utils.ConvertAsciiToHex(aestest)
|
local hex = utils.ConvertAsciiToHex(aestest)
|
||||||
|
|
||||||
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,hex)
|
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,hex)
|
||||||
io.write(blockNo..',')
|
io.write(blockNo..',')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
-- Sectorblocks, not encrypted
|
-- Sectorblocks, not encrypted
|
||||||
blocks[blockNo+1] = ('%02d :: %s%s'):format(blockNo,key,blockdata:sub(13,32))
|
blocks[blockNo+1] = ('%02d :: %s%s'):format(blockNo,key,blockdata:sub(13,32))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
io.write('\n')
|
io.write('\n')
|
||||||
|
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
-- Print results
|
-- Print results
|
||||||
local bindata = {}
|
local bindata = {}
|
||||||
local emldata = ''
|
local emldata = ''
|
||||||
|
|
||||||
for _,s in pairs(blocks) do
|
for _,s in pairs(blocks) do
|
||||||
local slice = s:sub(8,#s)
|
local slice = s:sub(8,#s)
|
||||||
local str = utils.ConvertHexToAscii(slice)
|
local str = utils.ConvertHexToAscii(slice)
|
||||||
emldata = emldata..slice..'\n'
|
emldata = emldata..slice..'\n'
|
||||||
for c in (str):gmatch('.') do
|
for c in (str):gmatch('.') do
|
||||||
bindata[#bindata+1] = c
|
bindata[#bindata+1] = c
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
|
|
||||||
local uid = block0:sub(1,8)
|
local uid = block0:sub(1,8)
|
||||||
local toytype = block1:sub(1,4)
|
local toytype = block1:sub(1,4)
|
||||||
local cardidLsw = block1:sub(9,16)
|
local cardidLsw = block1:sub(9,16)
|
||||||
local cardidMsw = block1:sub(16,24)
|
local cardidMsw = block1:sub(16,24)
|
||||||
local cardid = block1:sub(9,24)
|
local cardid = block1:sub(9,24)
|
||||||
local subtype = block1:sub(25,28)
|
local subtype = block1:sub(25,28)
|
||||||
|
|
||||||
-- Write dump to files
|
-- Write dump to files
|
||||||
if not DEBUG then
|
if not DEBUG then
|
||||||
local foo = dumplib.SaveAsBinary(bindata, outputTemplate..'-'..uid..'.bin')
|
local foo = dumplib.SaveAsBinary(bindata, outputTemplate..'-'..uid..'.bin')
|
||||||
print(("Wrote a BIN dump to: %s"):format(foo))
|
print(("Wrote a BIN dump to: %s"):format(foo))
|
||||||
local bar = dumplib.SaveAsText(emldata, outputTemplate..'-'..uid..'.eml')
|
local bar = dumplib.SaveAsText(emldata, outputTemplate..'-'..uid..'.eml')
|
||||||
print(("Wrote a EML dump to: %s"):format(bar))
|
print(("Wrote a EML dump to: %s"):format(bar))
|
||||||
end
|
end
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
-- Show info
|
-- Show info
|
||||||
|
|
||||||
local item = toys.Find(toytype, subtype)
|
local item = toys.Find(toytype, subtype)
|
||||||
if item then
|
if item then
|
||||||
print((' ITEM TYPE : %s - %s (%s)'):format(item[6],item[5], item[4]) )
|
print((' ITEM TYPE : %s - %s (%s)'):format(item[6],item[5], item[4]) )
|
||||||
else
|
else
|
||||||
print((' ITEM TYPE : 0x%s 0x%s'):format(toytype, subtype))
|
print((' ITEM TYPE : 0x%s 0x%s'):format(toytype, subtype))
|
||||||
end
|
end
|
||||||
|
|
||||||
print( (' UID : 0x%s'):format(uid) )
|
print( (' UID : 0x%s'):format(uid) )
|
||||||
print( (' CARDID : 0x%s'):format(cardid ) )
|
print( (' CARDID : 0x%s'):format(cardid ) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
|
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
end
|
end
|
||||||
main(args)
|
main(args)
|
||||||
@@ -8,9 +8,9 @@ local toys = require('default_toys')
|
|||||||
local pre = require('precalc')
|
local pre = require('precalc')
|
||||||
|
|
||||||
example =[[
|
example =[[
|
||||||
1. script run tnp3sim
|
1. script run tnp3sim
|
||||||
2. script run tnp3sim -m
|
2. script run tnp3sim -m
|
||||||
3. script run tnp3sim -m -i myfile
|
3. script run tnp3sim -m -i myfile
|
||||||
]]
|
]]
|
||||||
author = "Iceman"
|
author = "Iceman"
|
||||||
usage = "script run tnp3sim -h -m -i <filename>"
|
usage = "script run tnp3sim -h -m -i <filename>"
|
||||||
@@ -21,11 +21,11 @@ For an experimental mode, it tries to manipulate some data.
|
|||||||
At last it sends all data to the PM3 device memory where it can be used in the command "hf mf sim"
|
At last it sends all data to the PM3 device memory where it can be used in the command "hf mf sim"
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h : this help
|
-h : this help
|
||||||
-m : Maxed out items (experimental)
|
-m : Maxed out items (experimental)
|
||||||
-i : filename for the datadump to read (bin)
|
-i : filename for the datadump to read (bin)
|
||||||
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
|
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
|
||||||
local DEBUG = true -- the debug flag
|
local DEBUG = true -- the debug flag
|
||||||
@@ -43,236 +43,236 @@ local format = string.format
|
|||||||
---
|
---
|
||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
function dbg(args)
|
function dbg(args)
|
||||||
if not DEBUG then return end
|
if not DEBUG then return end
|
||||||
|
|
||||||
if type(args) == "table" then
|
if type(args) == "table" then
|
||||||
local i = 1
|
local i = 1
|
||||||
while result[i] do
|
while result[i] do
|
||||||
dbg(result[i])
|
dbg(result[i])
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print("###", args)
|
print("###", args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- 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)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
return nil,err
|
return nil,err
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
function help()
|
function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- Exit message
|
-- Exit message
|
||||||
function ExitMsg(msg)
|
function ExitMsg(msg)
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print(msg)
|
print(msg)
|
||||||
print()
|
print()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function writedumpfile(infile)
|
local function writedumpfile(infile)
|
||||||
t = infile:read("*all")
|
t = infile:read("*all")
|
||||||
len = string.len(t)
|
len = string.len(t)
|
||||||
local len,hex = bin.unpack(("H%d"):format(len),t)
|
local len,hex = bin.unpack(("H%d"):format(len),t)
|
||||||
return hex
|
return hex
|
||||||
end
|
end
|
||||||
-- blocks with data
|
-- blocks with data
|
||||||
-- there are two dataareas, in block 8 or block 36, ( 1==8 ,
|
-- there are two dataareas, in block 8 or block 36, ( 1==8 ,
|
||||||
-- checksum type = 0, 1, 2, 3
|
-- checksum type = 0, 1, 2, 3
|
||||||
local function GetCheckSum(blocks, dataarea, chksumtype)
|
local function GetCheckSum(blocks, dataarea, chksumtype)
|
||||||
|
|
||||||
local crc
|
local crc
|
||||||
local area = 36
|
local area = 36
|
||||||
if dataarea == 1 then
|
if dataarea == 1 then
|
||||||
area = 8
|
area = 8
|
||||||
end
|
end
|
||||||
|
|
||||||
if chksumtype == 0 then
|
if chksumtype == 0 then
|
||||||
crc = blocks[1]:sub(29,32)
|
crc = blocks[1]:sub(29,32)
|
||||||
elseif chksumtype == 1 then
|
elseif chksumtype == 1 then
|
||||||
crc = blocks[area]:sub(29,32)
|
crc = blocks[area]:sub(29,32)
|
||||||
elseif chksumtype == 2 then
|
elseif chksumtype == 2 then
|
||||||
crc = blocks[area]:sub(25,28)
|
crc = blocks[area]:sub(25,28)
|
||||||
elseif chksumtype == 3 then
|
elseif chksumtype == 3 then
|
||||||
crc = blocks[area]:sub(21,24)
|
crc = blocks[area]:sub(21,24)
|
||||||
end
|
end
|
||||||
return utils.SwapEndianness(crc,16)
|
return utils.SwapEndianness(crc,16)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function SetAllCheckSum(blocks)
|
local function SetAllCheckSum(blocks)
|
||||||
print('Updating all checksums')
|
print('Updating all checksums')
|
||||||
SetCheckSum(blocks, 3)
|
SetCheckSum(blocks, 3)
|
||||||
SetCheckSum(blocks, 2)
|
SetCheckSum(blocks, 2)
|
||||||
SetCheckSum(blocks, 1)
|
SetCheckSum(blocks, 1)
|
||||||
SetCheckSum(blocks, 0)
|
SetCheckSum(blocks, 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function SetCheckSum(blocks, chksumtype)
|
local function SetCheckSum(blocks, chksumtype)
|
||||||
|
|
||||||
if blocks == nil then return nil, 'Argument \"blocks\" nil' end
|
if blocks == nil then return nil, 'Argument \"blocks\" nil' end
|
||||||
local newcrc
|
local newcrc
|
||||||
local area1 = 8
|
local area1 = 8
|
||||||
local area2 = 36
|
local area2 = 36
|
||||||
|
|
||||||
if chksumtype == 0 then
|
if chksumtype == 0 then
|
||||||
newcrc = ('%04X'):format(CalcCheckSum(blocks,1,0))
|
newcrc = ('%04X'):format(CalcCheckSum(blocks,1,0))
|
||||||
blocks[1] = blocks[1]:sub(1,28)..newcrc:sub(3,4)..newcrc:sub(1,2)
|
blocks[1] = blocks[1]:sub(1,28)..newcrc:sub(3,4)..newcrc:sub(1,2)
|
||||||
elseif chksumtype == 1 then
|
elseif chksumtype == 1 then
|
||||||
newcrc = ('%04X'):format(CalcCheckSum(blocks,1,1))
|
newcrc = ('%04X'):format(CalcCheckSum(blocks,1,1))
|
||||||
blocks[area1] = blocks[area1]:sub(1,28)..newcrc:sub(3,4)..newcrc:sub(1,2)
|
blocks[area1] = blocks[area1]:sub(1,28)..newcrc:sub(3,4)..newcrc:sub(1,2)
|
||||||
newcrc = ('%04X'):format(CalcCheckSum(blocks,2,1))
|
newcrc = ('%04X'):format(CalcCheckSum(blocks,2,1))
|
||||||
blocks[area2] = blocks[area2]:sub(1,28)..newcrc:sub(3,4)..newcrc:sub(1,2)
|
blocks[area2] = blocks[area2]:sub(1,28)..newcrc:sub(3,4)..newcrc:sub(1,2)
|
||||||
elseif chksumtype == 2 then
|
elseif chksumtype == 2 then
|
||||||
newcrc = ('%04X'):format(CalcCheckSum(blocks,1,2))
|
newcrc = ('%04X'):format(CalcCheckSum(blocks,1,2))
|
||||||
blocks[area1] = blocks[area1]:sub(1,24)..newcrc:sub(3,4)..newcrc:sub(1,2)..blocks[area1]:sub(29,32)
|
blocks[area1] = blocks[area1]:sub(1,24)..newcrc:sub(3,4)..newcrc:sub(1,2)..blocks[area1]:sub(29,32)
|
||||||
newcrc = ('%04X'):format(CalcCheckSum(blocks,2,2))
|
newcrc = ('%04X'):format(CalcCheckSum(blocks,2,2))
|
||||||
blocks[area2] = blocks[area2]:sub(1,24)..newcrc:sub(3,4)..newcrc:sub(1,2)..blocks[area2]:sub(29,32)
|
blocks[area2] = blocks[area2]:sub(1,24)..newcrc:sub(3,4)..newcrc:sub(1,2)..blocks[area2]:sub(29,32)
|
||||||
elseif chksumtype == 3 then
|
elseif chksumtype == 3 then
|
||||||
newcrc = ('%04X'):format(CalcCheckSum(blocks,1,3))
|
newcrc = ('%04X'):format(CalcCheckSum(blocks,1,3))
|
||||||
blocks[area1] = blocks[area1]:sub(1,20)..newcrc:sub(3,4)..newcrc:sub(1,2)..blocks[area1]:sub(25,32)
|
blocks[area1] = blocks[area1]:sub(1,20)..newcrc:sub(3,4)..newcrc:sub(1,2)..blocks[area1]:sub(25,32)
|
||||||
newcrc = ('%04X'):format(CalcCheckSum(blocks,2,3))
|
newcrc = ('%04X'):format(CalcCheckSum(blocks,2,3))
|
||||||
blocks[area2] = blocks[area2]:sub(1,20)..newcrc:sub(3,4)..newcrc:sub(1,2)..blocks[area2]:sub(25,32)
|
blocks[area2] = blocks[area2]:sub(1,20)..newcrc:sub(3,4)..newcrc:sub(1,2)..blocks[area2]:sub(25,32)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function CalcCheckSum(blocks, dataarea, chksumtype)
|
function CalcCheckSum(blocks, dataarea, chksumtype)
|
||||||
local area = 36
|
local area = 36
|
||||||
if dataarea == 1 then
|
if dataarea == 1 then
|
||||||
area = 8
|
area = 8
|
||||||
end
|
end
|
||||||
|
|
||||||
if chksumtype == 0 then
|
if chksumtype == 0 then
|
||||||
data = blocks[0]..blocks[1]:sub(1,28)
|
data = blocks[0]..blocks[1]:sub(1,28)
|
||||||
elseif chksumtype == 1 then
|
elseif chksumtype == 1 then
|
||||||
data = blocks[area]:sub(1,28)..'0500'
|
data = blocks[area]:sub(1,28)..'0500'
|
||||||
elseif chksumtype == 2 then
|
elseif chksumtype == 2 then
|
||||||
data = blocks[area+1]..blocks[area+2]..blocks[area+4]
|
data = blocks[area+1]..blocks[area+2]..blocks[area+4]
|
||||||
elseif chksumtype == 3 then
|
elseif chksumtype == 3 then
|
||||||
data = blocks[area+5]..blocks[area+6]..blocks[area+8]..string.rep('00',0xe0)
|
data = blocks[area+5]..blocks[area+6]..blocks[area+8]..string.rep('00',0xe0)
|
||||||
end
|
end
|
||||||
return utils.Crc16(data)
|
return utils.Crc16(data)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function ValidateCheckSums(blocks)
|
local function ValidateCheckSums(blocks)
|
||||||
print(' Validating checksums')
|
print(' Validating checksums')
|
||||||
|
|
||||||
local isOk, crc, calc
|
local isOk, crc, calc
|
||||||
-- Checksum Type 0
|
-- Checksum Type 0
|
||||||
crc = GetCheckSum(blocks,1,0)
|
crc = GetCheckSum(blocks,1,0)
|
||||||
calc = CalcCheckSum(blocks, 1, 0)
|
calc = CalcCheckSum(blocks, 1, 0)
|
||||||
if crc == calc then isOk='Ok' else isOk = 'Error' end
|
if crc == calc then isOk='Ok' else isOk = 'Error' end
|
||||||
io.write( ('TYPE 0 : %04x = %04x -- %s\n'):format(crc,calc,isOk))
|
io.write( ('TYPE 0 : %04x = %04x -- %s\n'):format(crc,calc,isOk))
|
||||||
|
|
||||||
-- Checksum Type 1 (DATAAREAHEADER 1)
|
-- Checksum Type 1 (DATAAREAHEADER 1)
|
||||||
crc = GetCheckSum(blocks,1,1)
|
crc = GetCheckSum(blocks,1,1)
|
||||||
calc = CalcCheckSum(blocks,1,1)
|
calc = CalcCheckSum(blocks,1,1)
|
||||||
if crc == calc then isOk='Ok' else isOk = 'Error' end
|
if crc == calc then isOk='Ok' else isOk = 'Error' end
|
||||||
io.write( ('TYPE 1 area 1: %04x = %04x -- %s\n'):format(crc,calc,isOk))
|
io.write( ('TYPE 1 area 1: %04x = %04x -- %s\n'):format(crc,calc,isOk))
|
||||||
|
|
||||||
-- Checksum Type 1 (DATAAREAHEADER 2)
|
-- Checksum Type 1 (DATAAREAHEADER 2)
|
||||||
crc = GetCheckSum(blocks,2,1)
|
crc = GetCheckSum(blocks,2,1)
|
||||||
calc = CalcCheckSum(blocks,2,1)
|
calc = CalcCheckSum(blocks,2,1)
|
||||||
if crc == calc then isOk='Ok' else isOk = 'Error' end
|
if crc == calc then isOk='Ok' else isOk = 'Error' end
|
||||||
io.write( ('TYPE 1 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk))
|
io.write( ('TYPE 1 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk))
|
||||||
|
|
||||||
-- Checksum Type 2 (DATAAREA 1)
|
-- Checksum Type 2 (DATAAREA 1)
|
||||||
crc = GetCheckSum(blocks,1,2)
|
crc = GetCheckSum(blocks,1,2)
|
||||||
calc = CalcCheckSum(blocks,1,2)
|
calc = CalcCheckSum(blocks,1,2)
|
||||||
if crc == calc then isOk='Ok' else isOk = 'Error' end
|
if crc == calc then isOk='Ok' else isOk = 'Error' end
|
||||||
io.write( ('TYPE 2 area 1: %04x = %04x -- %s\n'):format(crc,calc,isOk))
|
io.write( ('TYPE 2 area 1: %04x = %04x -- %s\n'):format(crc,calc,isOk))
|
||||||
|
|
||||||
-- Checksum Type 2 (DATAAREA 2)
|
-- Checksum Type 2 (DATAAREA 2)
|
||||||
crc = GetCheckSum(blocks,2,2)
|
crc = GetCheckSum(blocks,2,2)
|
||||||
calc = CalcCheckSum(blocks,2,2)
|
calc = CalcCheckSum(blocks,2,2)
|
||||||
if crc == calc then isOk='Ok' else isOk = 'Error' end
|
if crc == calc then isOk='Ok' else isOk = 'Error' end
|
||||||
io.write( ('TYPE 2 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk))
|
io.write( ('TYPE 2 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk))
|
||||||
|
|
||||||
-- Checksum Type 3 (DATAAREA 1)
|
-- Checksum Type 3 (DATAAREA 1)
|
||||||
crc = GetCheckSum(blocks,1,3)
|
crc = GetCheckSum(blocks,1,3)
|
||||||
calc = CalcCheckSum(blocks,1,3)
|
calc = CalcCheckSum(blocks,1,3)
|
||||||
if crc == calc then isOk='Ok' else isOk = 'Error' end
|
if crc == calc then isOk='Ok' else isOk = 'Error' end
|
||||||
io.write( ('TYPE 3 area 1: %04x = %04x -- %s\n'):format(crc,calc,isOk))
|
io.write( ('TYPE 3 area 1: %04x = %04x -- %s\n'):format(crc,calc,isOk))
|
||||||
|
|
||||||
-- Checksum Type 3 (DATAAREA 2)
|
-- Checksum Type 3 (DATAAREA 2)
|
||||||
crc = GetCheckSum(blocks,2,3)
|
crc = GetCheckSum(blocks,2,3)
|
||||||
calc = CalcCheckSum(blocks,2,3)
|
calc = CalcCheckSum(blocks,2,3)
|
||||||
if crc == calc then isOk='Ok' else isOk = 'Error' end
|
if crc == calc then isOk='Ok' else isOk = 'Error' end
|
||||||
io.write( ('TYPE 3 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk))
|
io.write( ('TYPE 3 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk))
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function AddKey(keys, blockNo, data)
|
local function AddKey(keys, blockNo, data)
|
||||||
local pos = (math.floor( blockNo / 4 ) * 12)+1
|
local pos = (math.floor( blockNo / 4 ) * 12)+1
|
||||||
local key = keys:sub(pos, pos + 11 )
|
local key = keys:sub(pos, pos + 11 )
|
||||||
return key..data:sub(13)
|
return key..data:sub(13)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function LoadEmulator(uid, blocks)
|
local function LoadEmulator(uid, blocks)
|
||||||
print('Sending dumpdata to emulator memory')
|
print('Sending dumpdata to emulator memory')
|
||||||
local keys = pre.GetAll(uid)
|
local keys = pre.GetAll(uid)
|
||||||
local cmd, blockdata
|
local cmd, blockdata
|
||||||
for _,b in pairs(blocks) do
|
for _,b in pairs(blocks) do
|
||||||
|
|
||||||
blockdata = b
|
blockdata = b
|
||||||
|
|
||||||
if _%4 ~= 3 then
|
if _%4 ~= 3 then
|
||||||
if (_ >= 8 and _<=21) or (_ >= 36 and _<=49) then
|
if (_ >= 8 and _<=21) or (_ >= 36 and _<=49) then
|
||||||
local base = ('%s%s%02x%s'):format(blocks[0], blocks[1], _ , RANDOM)
|
local base = ('%s%s%02x%s'):format(blocks[0], blocks[1], _ , RANDOM)
|
||||||
local baseStr = utils.ConvertHexToAscii(base)
|
local baseStr = utils.ConvertHexToAscii(base)
|
||||||
local key = md5.sumhexa(baseStr)
|
local key = md5.sumhexa(baseStr)
|
||||||
local enc = core.aes128_encrypt(key, blockdata)
|
local enc = core.aes128_encrypt(key, blockdata)
|
||||||
blockdata = utils.ConvertAsciiToHex(enc)
|
blockdata = utils.ConvertAsciiToHex(enc)
|
||||||
io.write( _..',')
|
io.write( _..',')
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
-- add keys if not existing..
|
-- add keys if not existing..
|
||||||
if ( blockdata:sub(1,12) == '000000000000' ) then
|
if ( blockdata:sub(1,12) == '000000000000' ) then
|
||||||
blockdata = AddKey(keys, _, blockdata)
|
blockdata = AddKey(keys, _, blockdata)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
cmd = Command:new{cmd = cmds.CMD_MIFARE_EML_MEMSET, arg1 = _ ,arg2 = 1,arg3 = 16, data = blockdata}
|
cmd = Command:new{cmd = cmds.CMD_MIFARE_EML_MEMSET, arg1 = _ ,arg2 = 1,arg3 = 16, data = blockdata}
|
||||||
local err = core.SendCommand(cmd:getBytes())
|
local err = core.SendCommand(cmd:getBytes())
|
||||||
if err then return err end
|
if err then return err end
|
||||||
end
|
end
|
||||||
io.write('\n')
|
io.write('\n')
|
||||||
end
|
end
|
||||||
|
|
||||||
local function Num2Card(m, l)
|
local function Num2Card(m, l)
|
||||||
|
|
||||||
local k = {
|
local k = {
|
||||||
0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,0x42, 0x43, 0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B,
|
0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,0x42, 0x43, 0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B,
|
||||||
0x4C, 0x4D, 0x4E, 0x50, 0x51, 0x52, 0x53, 0x54,0x56, 0x57, 0x58, 0x59, 0x5A, 0x00
|
0x4C, 0x4D, 0x4E, 0x50, 0x51, 0x52, 0x53, 0x54,0x56, 0x57, 0x58, 0x59, 0x5A, 0x00
|
||||||
}
|
}
|
||||||
local msw = tonumber(utils.SwapEndiannessStr(m,32),16)
|
local msw = tonumber(utils.SwapEndiannessStr(m,32),16)
|
||||||
local lsw = tonumber(utils.SwapEndiannessStr(l,32),16)
|
local lsw = tonumber(utils.SwapEndiannessStr(l,32),16)
|
||||||
|
|
||||||
if msw > 0x17ea1 then
|
if msw > 0x17ea1 then
|
||||||
return "too big"
|
return "too big"
|
||||||
end
|
end
|
||||||
|
|
||||||
if msw == 0x17ea1 and lsw > 0x8931fee8 then
|
if msw == 0x17ea1 and lsw > 0x8931fee8 then
|
||||||
return "out of range"
|
return "out of range"
|
||||||
end
|
end
|
||||||
|
|
||||||
local s = ""
|
local s = ""
|
||||||
local index
|
local index
|
||||||
for i = 1,10 do
|
for i = 1,10 do
|
||||||
index, msw, lsw = DivideByK( msw, lsw)
|
index, msw, lsw = DivideByK( msw, lsw)
|
||||||
if ( index <= 1 ) then
|
if ( index <= 1 ) then
|
||||||
s = char(k[index]) .. s
|
s = char(k[index]) .. s
|
||||||
else
|
else
|
||||||
s = char(k[index-1]) .. s
|
s = char(k[index-1]) .. s
|
||||||
end
|
end
|
||||||
print (index-1, msw, lsw)
|
print (index-1, msw, lsw)
|
||||||
end
|
end
|
||||||
return s
|
return s
|
||||||
end
|
end
|
||||||
--33LRT-LM9Q9
|
--33LRT-LM9Q9
|
||||||
@@ -289,37 +289,37 @@ end
|
|||||||
|
|
||||||
function DivideByK(msw, lsw)
|
function DivideByK(msw, lsw)
|
||||||
|
|
||||||
local lowLSW
|
local lowLSW
|
||||||
local highLSW
|
local highLSW
|
||||||
local remainder = 0
|
local remainder = 0
|
||||||
local RADIX = 29
|
local RADIX = 29
|
||||||
|
|
||||||
--local num = 0 | band( rshift(msw,16), 0xffff)
|
--local num = 0 | band( rshift(msw,16), 0xffff)
|
||||||
local num = band( rshift(msw, 16), 0xffff)
|
local num = band( rshift(msw, 16), 0xffff)
|
||||||
|
|
||||||
--highLSW = 0 | lshift( (num / RADIX) , 16)
|
--highLSW = 0 | lshift( (num / RADIX) , 16)
|
||||||
highLSW = lshift( (num / RADIX) , 16)
|
highLSW = lshift( (num / RADIX) , 16)
|
||||||
remainder = num % RADIX
|
remainder = num % RADIX
|
||||||
|
|
||||||
num = bor( lshift(remainder,16), band(msw, 0xffff))
|
num = bor( lshift(remainder,16), band(msw, 0xffff))
|
||||||
|
|
||||||
--highLSW |= num / RADIX
|
--highLSW |= num / RADIX
|
||||||
highLSW = highLSW or (num / RADIX)
|
highLSW = highLSW or (num / RADIX)
|
||||||
remainder = num % RADIX
|
remainder = num % RADIX
|
||||||
|
|
||||||
num = bor( lshift(remainder,16), ( band(rshift(lsw,16), 0xffff)))
|
num = bor( lshift(remainder,16), ( band(rshift(lsw,16), 0xffff)))
|
||||||
|
|
||||||
--lowLSW = 0 | (num / RADIX) << 16
|
--lowLSW = 0 | (num / RADIX) << 16
|
||||||
lowLSW = 0 or (lshift( (num / RADIX), 16))
|
lowLSW = 0 or (lshift( (num / RADIX), 16))
|
||||||
remainder = num % RADIX
|
remainder = num % RADIX
|
||||||
|
|
||||||
num = bor( lshift(remainder,16) , band(lsw, 0xffff) )
|
num = bor( lshift(remainder,16) , band(lsw, 0xffff) )
|
||||||
|
|
||||||
lowLSW = bor(lowLSW, (num / RADIX))
|
lowLSW = bor(lowLSW, (num / RADIX))
|
||||||
remainder = num % RADIX
|
remainder = num % RADIX
|
||||||
return remainder, highLSW, lowLSW
|
return remainder, highLSW, lowLSW
|
||||||
|
|
||||||
-- uint num = 0 | (msw >> 16) & 0xffff;
|
-- uint num = 0 | (msw >> 16) & 0xffff;
|
||||||
|
|
||||||
-- highLSW = 0 | (num / RADIX) << 16;
|
-- highLSW = 0 | (num / RADIX) << 16;
|
||||||
-- remainder = num % RADIX;
|
-- remainder = num % RADIX;
|
||||||
@@ -343,147 +343,147 @@ end
|
|||||||
|
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
|
|
||||||
local result, err, hex
|
local result, err, hex
|
||||||
local maxed = false
|
local maxed = false
|
||||||
local inputTemplate = "dumpdata.bin"
|
local inputTemplate = "dumpdata.bin"
|
||||||
local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M");
|
local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M");
|
||||||
|
|
||||||
-- Arguments for the script
|
-- Arguments for the script
|
||||||
for o, a in getopt.getopt(args, 'hmi:o:') do
|
for o, a in getopt.getopt(args, 'hmi:o:') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
if o == "m" then maxed = true end
|
if o == "m" then maxed = true end
|
||||||
if o == "o" then outputTemplate = a end
|
if o == "o" then outputTemplate = a end
|
||||||
if o == "i" then inputTemplate = a end
|
if o == "i" then inputTemplate = a end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Turn off Debug
|
-- Turn off Debug
|
||||||
local cmdSetDbgOff = "hf mf dbg 0"
|
local cmdSetDbgOff = "hf mf dbg 0"
|
||||||
core.console( cmdSetDbgOff)
|
core.console( cmdSetDbgOff)
|
||||||
|
|
||||||
-- Load dump.bin file
|
-- Load dump.bin file
|
||||||
print( (' Load data from %s'):format(inputTemplate))
|
print( (' Load data from %s'):format(inputTemplate))
|
||||||
hex, err = utils.ReadDumpFile(inputTemplate)
|
hex, err = utils.ReadDumpFile(inputTemplate)
|
||||||
if not hex then return oops(err) end
|
if not hex then return oops(err) end
|
||||||
|
|
||||||
local blocks = {}
|
local blocks = {}
|
||||||
local blockindex = 0
|
local blockindex = 0
|
||||||
for i = 1, #hex, 32 do
|
for i = 1, #hex, 32 do
|
||||||
blocks[blockindex] = hex:sub(i,i+31)
|
blocks[blockindex] = hex:sub(i,i+31)
|
||||||
blockindex = blockindex + 1
|
blockindex = blockindex + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
if DEBUG then ValidateCheckSums(blocks) end
|
if DEBUG then ValidateCheckSums(blocks) end
|
||||||
|
|
||||||
--
|
--
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print(' Gathering info')
|
print(' Gathering info')
|
||||||
local uid = blocks[0]:sub(1,8)
|
local uid = blocks[0]:sub(1,8)
|
||||||
local toytype = blocks[1]:sub(1,4)
|
local toytype = blocks[1]:sub(1,4)
|
||||||
local cardidLsw = blocks[1]:sub(9,16)
|
local cardidLsw = blocks[1]:sub(9,16)
|
||||||
local cardidMsw = blocks[1]:sub(17,24)
|
local cardidMsw = blocks[1]:sub(17,24)
|
||||||
local subtype = blocks[1]:sub(25,28)
|
local subtype = blocks[1]:sub(25,28)
|
||||||
|
|
||||||
-- Show info
|
-- Show info
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
|
|
||||||
local item = toys.Find( toytype, subtype)
|
local item = toys.Find( toytype, subtype)
|
||||||
if item then
|
if item then
|
||||||
local itemStr = ('%s - %s (%s)'):format(item[6],item[5], item[4])
|
local itemStr = ('%s - %s (%s)'):format(item[6],item[5], item[4])
|
||||||
print(' ITEM TYPE : '..itemStr )
|
print(' ITEM TYPE : '..itemStr )
|
||||||
else
|
else
|
||||||
print( (' ITEM TYPE : 0x%s 0x%s'):format(toytype, subtype) )
|
print( (' ITEM TYPE : 0x%s 0x%s'):format(toytype, subtype) )
|
||||||
end
|
end
|
||||||
|
|
||||||
print( (' UID : 0x%s'):format(uid) )
|
print( (' UID : 0x%s'):format(uid) )
|
||||||
print( (' CARDID : 0x%s %s [%s]'):format(
|
print( (' CARDID : 0x%s %s [%s]'):format(
|
||||||
cardidMsw,cardidLsw,
|
cardidMsw,cardidLsw,
|
||||||
--Num2Card(cardidMsw, cardidLsw))
|
--Num2Card(cardidMsw, cardidLsw))
|
||||||
'')
|
'')
|
||||||
)
|
)
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
|
|
||||||
|
|
||||||
-- Experience should be:
|
-- Experience should be:
|
||||||
local experience = blocks[8]:sub(1,6)
|
local experience = blocks[8]:sub(1,6)
|
||||||
print(('Experience : %d'):format(utils.SwapEndianness(experience,16)))
|
print(('Experience : %d'):format(utils.SwapEndianness(experience,16)))
|
||||||
|
|
||||||
local money = blocks[8]:sub(7,10)
|
local money = blocks[8]:sub(7,10)
|
||||||
print(('Money : %d'):format(utils.SwapEndianness(money,16)))
|
print(('Money : %d'):format(utils.SwapEndianness(money,16)))
|
||||||
|
|
||||||
--
|
--
|
||||||
|
|
||||||
-- Sequence number
|
-- Sequence number
|
||||||
local seqnum = blocks[8]:sub(18,19)
|
local seqnum = blocks[8]:sub(18,19)
|
||||||
print(('Sequence number : %d'):format( tonumber(seqnum,16)))
|
print(('Sequence number : %d'):format( tonumber(seqnum,16)))
|
||||||
|
|
||||||
local fairy = blocks[9]:sub(1,8)
|
local fairy = blocks[9]:sub(1,8)
|
||||||
--FD0F = Left, FF0F = Right
|
--FD0F = Left, FF0F = Right
|
||||||
local path = 'not choosen'
|
local path = 'not choosen'
|
||||||
if fairy:sub(2,2) == 'D' then
|
if fairy:sub(2,2) == 'D' then
|
||||||
path = 'Left'
|
path = 'Left'
|
||||||
elseif fairy:sub(2,2) == 'F' then
|
elseif fairy:sub(2,2) == 'F' then
|
||||||
path = 'Right'
|
path = 'Right'
|
||||||
end
|
end
|
||||||
print(('Fairy : %d [Path: %s] '):format(utils.SwapEndianness(fairy,24),path))
|
print(('Fairy : %d [Path: %s] '):format(utils.SwapEndianness(fairy,24),path))
|
||||||
|
|
||||||
local hat = blocks[9]:sub(8,11)
|
local hat = blocks[9]:sub(8,11)
|
||||||
print(('Hat : %d'):format(utils.SwapEndianness(hat,16)))
|
print(('Hat : %d'):format(utils.SwapEndianness(hat,16)))
|
||||||
|
|
||||||
local level = blocks[13]:sub(27,28)
|
local level = blocks[13]:sub(27,28)
|
||||||
print(('LEVEL : %d'):format( tonumber(level,16)))
|
print(('LEVEL : %d'):format( tonumber(level,16)))
|
||||||
|
|
||||||
--local health = blocks[]:sub();
|
--local health = blocks[]:sub();
|
||||||
--print(('Health : %d'):format( tonumber(health,16))
|
--print(('Health : %d'):format( tonumber(health,16))
|
||||||
|
|
||||||
--0x0D 0x29 0x0A 0x02 16-bit hero points value. Maximum 100.
|
--0x0D 0x29 0x0A 0x02 16-bit hero points value. Maximum 100.
|
||||||
local heropoints = blocks[13]:sub(20,23)
|
local heropoints = blocks[13]:sub(20,23)
|
||||||
print(('Hero points : %d'):format(utils.SwapEndianness(heropoints,16)))
|
print(('Hero points : %d'):format(utils.SwapEndianness(heropoints,16)))
|
||||||
|
|
||||||
--0x10 0x2C 0x0C 0x04 32 bit flag value indicating heroic challenges completed.
|
--0x10 0x2C 0x0C 0x04 32 bit flag value indicating heroic challenges completed.
|
||||||
local challenges = blocks[16]:sub(25,32)
|
local challenges = blocks[16]:sub(25,32)
|
||||||
print(('Finished hero challenges : %d'):format(utils.SwapEndianness(challenges,32)))
|
print(('Finished hero challenges : %d'):format(utils.SwapEndianness(challenges,32)))
|
||||||
|
|
||||||
-- Character Name
|
-- Character Name
|
||||||
local name1 = blocks[10]:sub(1,32)
|
local name1 = blocks[10]:sub(1,32)
|
||||||
local name2 = blocks[12]:sub(1,32)
|
local name2 = blocks[12]:sub(1,32)
|
||||||
print('Custom name : '..utils.ConvertHexToAscii(name1..name2))
|
print('Custom name : '..utils.ConvertHexToAscii(name1..name2))
|
||||||
|
|
||||||
if maxed then
|
if maxed then
|
||||||
print('Lets try to max out some values')
|
print('Lets try to max out some values')
|
||||||
-- max out money, experience
|
-- max out money, experience
|
||||||
--print (blocks[8])
|
--print (blocks[8])
|
||||||
blocks[8] = 'FFFFFF'..'FFFF'..blocks[8]:sub(11,32)
|
blocks[8] = 'FFFFFF'..'FFFF'..blocks[8]:sub(11,32)
|
||||||
blocks[36] = 'FFFFFF'..'FFFF'..blocks[36]:sub(11,32)
|
blocks[36] = 'FFFFFF'..'FFFF'..blocks[36]:sub(11,32)
|
||||||
--print (blocks[8])
|
--print (blocks[8])
|
||||||
|
|
||||||
-- max out hero challenges
|
-- max out hero challenges
|
||||||
--print (blocks[16])
|
--print (blocks[16])
|
||||||
blocks[16] = blocks[16]:sub(1,24)..'FFFFFFFF'
|
blocks[16] = blocks[16]:sub(1,24)..'FFFFFFFF'
|
||||||
blocks[44] = blocks[44]:sub(1,24)..'FFFFFFFF'
|
blocks[44] = blocks[44]:sub(1,24)..'FFFFFFFF'
|
||||||
--print (blocks[16])
|
--print (blocks[16])
|
||||||
|
|
||||||
-- max out heropoints
|
-- max out heropoints
|
||||||
--print (blocks[13])
|
--print (blocks[13])
|
||||||
blocks[13] = blocks[13]:sub(1,19)..'0064'..blocks[13]:sub(24,32)
|
blocks[13] = blocks[13]:sub(1,19)..'0064'..blocks[13]:sub(24,32)
|
||||||
blocks[41] = blocks[41]:sub(1,19)..'0064'..blocks[41]:sub(24,32)
|
blocks[41] = blocks[41]:sub(1,19)..'0064'..blocks[41]:sub(24,32)
|
||||||
--print (blocks[13])
|
--print (blocks[13])
|
||||||
|
|
||||||
-- Update Checksums
|
-- Update Checksums
|
||||||
SetAllCheckSum(blocks)
|
SetAllCheckSum(blocks)
|
||||||
|
|
||||||
-- Validate Checksums
|
-- Validate Checksums
|
||||||
ValidateCheckSums(blocks)
|
ValidateCheckSums(blocks)
|
||||||
end
|
end
|
||||||
|
|
||||||
--Load dumpdata to emulator memory
|
--Load dumpdata to emulator memory
|
||||||
if DEBUG then
|
if DEBUG then
|
||||||
err = LoadEmulator(uid, blocks)
|
err = LoadEmulator(uid, blocks)
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
print('The simulation is now prepared.\n --> run \"hf mf sim u '..uid..'\" <--')
|
print('The simulation is now prepared.\n --> run \"hf mf sim u '..uid..'\" <--')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
main(args)
|
main(args)
|
||||||
@@ -5,7 +5,7 @@ local utils = require('utils')
|
|||||||
local dumplib = require('html_dumplib')
|
local dumplib = require('html_dumplib')
|
||||||
|
|
||||||
example =[[
|
example =[[
|
||||||
1. script run tracetest
|
1. script run tracetest
|
||||||
]]
|
]]
|
||||||
author = "Iceman"
|
author = "Iceman"
|
||||||
usage = "script run tracetest"
|
usage = "script run tracetest"
|
||||||
@@ -19,7 +19,7 @@ The following tracefiles will be loaded:
|
|||||||
m*.pm3
|
m*.pm3
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h : this help
|
-h : this help
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
|
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
|
||||||
@@ -27,100 +27,100 @@ local DEBUG = true -- the debug flag
|
|||||||
---
|
---
|
||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
function dbg(args)
|
function dbg(args)
|
||||||
if not DEBUG then
|
if not DEBUG then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if type(args) == "table" then
|
if type(args) == "table" then
|
||||||
local i = 1
|
local i = 1
|
||||||
while result[i] do
|
while result[i] do
|
||||||
dbg(result[i])
|
dbg(result[i])
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print("###", args)
|
print("###", args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- 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)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
function help()
|
function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- Exit message
|
-- Exit message
|
||||||
function ExitMsg(msg)
|
function ExitMsg(msg)
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print(msg)
|
print(msg)
|
||||||
print()
|
print()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function main(args)
|
local function main(args)
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
|
|
||||||
local cmdDataLoad = 'data load %s';
|
local cmdDataLoad = 'data load %s';
|
||||||
local tracesEM = "find '../traces/' -iname 'em*.pm3' -type f"
|
local tracesEM = "find '../traces/' -iname 'em*.pm3' -type f"
|
||||||
local tracesMOD = "find '../traces/' -iname 'm*.pm3' -type f"
|
local tracesMOD = "find '../traces/' -iname 'm*.pm3' -type f"
|
||||||
|
|
||||||
local write2File = false
|
local write2File = false
|
||||||
local outputTemplate = os.date("testtest_%Y-%m-%d_%H%M%S")
|
local outputTemplate = os.date("testtest_%Y-%m-%d_%H%M%S")
|
||||||
|
|
||||||
-- Arguments for the script
|
-- Arguments for the script
|
||||||
for o, arg in getopt.getopt(args, 'h') do
|
for o, arg in getopt.getopt(args, 'h') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
end
|
end
|
||||||
|
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
local files = {}
|
local files = {}
|
||||||
|
|
||||||
-- Find a set of traces staring with EM
|
-- Find a set of traces staring with EM
|
||||||
local p = assert( io.popen(tracesEM))
|
local p = assert( io.popen(tracesEM))
|
||||||
for file in p:lines() do
|
for file in p:lines() do
|
||||||
table.insert(files, file)
|
table.insert(files, file)
|
||||||
end
|
end
|
||||||
p.close();
|
p.close();
|
||||||
|
|
||||||
-- Find a set of traces staring with MOD
|
-- Find a set of traces staring with MOD
|
||||||
p = assert( io.popen(tracesMOD) )
|
p = assert( io.popen(tracesMOD) )
|
||||||
for file in p:lines() do
|
for file in p:lines() do
|
||||||
table.insert(files, file)
|
table.insert(files, file)
|
||||||
end
|
end
|
||||||
p.close();
|
p.close();
|
||||||
|
|
||||||
local cmdLFSEARCH = "lf search 1 u"
|
local cmdLFSEARCH = "lf search 1 u"
|
||||||
|
|
||||||
-- main loop
|
-- main loop
|
||||||
io.write('Starting to test traces > ')
|
io.write('Starting to test traces > ')
|
||||||
for _,file in pairs(files) do
|
for _,file in pairs(files) do
|
||||||
|
|
||||||
local x = "data load "..file
|
local x = "data load "..file
|
||||||
dbg(x)
|
dbg(x)
|
||||||
core.console(x)
|
core.console(x)
|
||||||
|
|
||||||
dbg(cmdLFSEARCH)
|
dbg(cmdLFSEARCH)
|
||||||
core.console(cmdLFSEARCH)
|
core.console(cmdLFSEARCH)
|
||||||
|
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
if core.ukbhit() then
|
if core.ukbhit() then
|
||||||
print("aborted by user")
|
print("aborted by user")
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
io.write('\n')
|
io.write('\n')
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
|
|
||||||
end
|
end
|
||||||
main(args)
|
main(args)
|
||||||
@@ -3,8 +3,8 @@ local getopt = require('getopt')
|
|||||||
local lib14a = require('read14a')
|
local lib14a = require('read14a')
|
||||||
local utils = require('utils')
|
local utils = require('utils')
|
||||||
example = [[
|
example = [[
|
||||||
script run ufodump
|
script run ufodump
|
||||||
script run ufodump -b 10
|
script run ufodump -b 10
|
||||||
]]
|
]]
|
||||||
author = "Iceman"
|
author = "Iceman"
|
||||||
desc =
|
desc =
|
||||||
@@ -25,41 +25,41 @@ local DEBUG = false -- the debug flag
|
|||||||
---
|
---
|
||||||
-- A debug printout-function
|
-- A debug printout-function
|
||||||
local function dbg(args)
|
local function dbg(args)
|
||||||
if DEBUG then
|
if DEBUG then
|
||||||
print("###", args)
|
print("###", args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- writes data to ascii textfile.
|
-- writes data to ascii textfile.
|
||||||
function writeDumpFile(uid, blockData)
|
function writeDumpFile(uid, blockData)
|
||||||
local destination = string.format("%s.eml", uid)
|
local destination = string.format("%s.eml", uid)
|
||||||
local file = io.open(destination, "w")
|
local file = io.open(destination, "w")
|
||||||
if file == nil then
|
if file == nil then
|
||||||
return nil, string.format("Could not write to file %s", destination)
|
return nil, string.format("Could not write to file %s", destination)
|
||||||
end
|
end
|
||||||
local rowlen = string.len(blockData[1])
|
local rowlen = string.len(blockData[1])
|
||||||
|
|
||||||
for i,block in ipairs(blockData) do
|
for i,block in ipairs(blockData) do
|
||||||
if rowlen ~= string.len(block) then
|
if rowlen ~= string.len(block) then
|
||||||
print(string.format("WARNING: Dumpdata seems corrupted, line %d was not the same length as line 1",i))
|
print(string.format("WARNING: Dumpdata seems corrupted, line %d was not the same length as line 1",i))
|
||||||
end
|
end
|
||||||
file:write(block.."\n")
|
file:write(block.."\n")
|
||||||
end
|
end
|
||||||
file:close()
|
file:close()
|
||||||
return destination
|
return destination
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
--- Picks out and displays the data read from a tag
|
--- Picks out and displays the data read from a tag
|
||||||
@@ -70,107 +70,107 @@ end
|
|||||||
-- @blockno just to print which block the data belong to
|
-- @blockno just to print which block the data belong to
|
||||||
-- @param usbpacket the data received from the device
|
-- @param usbpacket the data received from the device
|
||||||
function showdata(blockno, data)
|
function showdata(blockno, data)
|
||||||
local xorkey = '55AA55AA55AA55AA6262'
|
local xorkey = '55AA55AA55AA55AA6262'
|
||||||
local s = data.." | "
|
local s = data.." | "
|
||||||
local dex = ''
|
local dex = ''
|
||||||
local rs
|
local rs
|
||||||
for i = 1, 20-4, 4 do
|
for i = 1, 20-4, 4 do
|
||||||
local item = string.sub(data, i, i+3)
|
local item = string.sub(data, i, i+3)
|
||||||
local xor = string.sub(xorkey, i, i+3)
|
local xor = string.sub(xorkey, i, i+3)
|
||||||
|
|
||||||
if blockno > 2 then
|
if blockno > 2 then
|
||||||
rs = bit32.bxor(tonumber(item,16) , tonumber(xor,16))
|
rs = bit32.bxor(tonumber(item,16) , tonumber(xor,16))
|
||||||
else
|
else
|
||||||
rs = tonumber(item, 16)
|
rs = tonumber(item, 16)
|
||||||
end
|
end
|
||||||
dex = (dex..'%04X'):format(rs)
|
dex = (dex..'%04X'):format(rs)
|
||||||
end
|
end
|
||||||
s = s..dex.." | "
|
s = s..dex.." | "
|
||||||
print( (" %02d | %s"):format(blockno,s))
|
print( (" %02d | %s"):format(blockno,s))
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- Send a "raw" iso14443a package, ie "hf 14a raw" command
|
-- Send a "raw" iso14443a package, ie "hf 14a raw" command
|
||||||
function sendRaw(rawdata, options)
|
function sendRaw(rawdata, options)
|
||||||
--print(">> ", rawdata)
|
--print(">> ", rawdata)
|
||||||
local flags = lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT + lib14a.ISO14A_COMMAND.ISO14A_RAW + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC + lib14a.ISO14A_COMMAND.ISO14A_NO_RATS
|
local flags = lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT + lib14a.ISO14A_COMMAND.ISO14A_RAW + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC + lib14a.ISO14A_COMMAND.ISO14A_NO_RATS
|
||||||
local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a,
|
local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a,
|
||||||
arg1 = flags, -- Send raw
|
arg1 = flags, -- Send raw
|
||||||
-- arg2 contains the length, which is half the length
|
-- arg2 contains the length, which is half the length
|
||||||
-- of the ASCII-string rawdata
|
-- of the ASCII-string rawdata
|
||||||
arg2 = string.len(rawdata)/2,
|
arg2 = string.len(rawdata)/2,
|
||||||
data = rawdata}
|
data = rawdata}
|
||||||
return lib14a.sendToDevice(command, options.ignore_response)
|
return lib14a.sendToDevice(command, options.ignore_response)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- Sends an instruction to do nothing, only disconnect
|
-- Sends an instruction to do nothing, only disconnect
|
||||||
function disconnect()
|
function disconnect()
|
||||||
local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, arg1 = 0, }
|
local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, arg1 = 0,}
|
||||||
-- We can ignore the response here, no ACK is returned for this command
|
-- We can ignore the response here, no ACK is returned for this command
|
||||||
-- Check /armsrc/iso14443a.c, ReaderIso14443a() for details
|
-- Check /armsrc/iso14443a.c, ReaderIso14443a() for details
|
||||||
return lib14a.sendToDevice(command, true)
|
return lib14a.sendToDevice(command, true)
|
||||||
--core.console("hf 14a raw -r")
|
--core.console("hf 14a raw -r")
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- The main entry point
|
-- The main entry point
|
||||||
function main(args)
|
function main(args)
|
||||||
|
|
||||||
local ignore_response = false
|
local ignore_response = false
|
||||||
local endblock = 20
|
local endblock = 20
|
||||||
|
|
||||||
-- Read the parameters
|
-- Read the parameters
|
||||||
for o, a in getopt.getopt(args, 'hb:') do
|
for o, a in getopt.getopt(args, 'hb:') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
if o == "b" then endblock = a end
|
if o == "b" then endblock = a end
|
||||||
end
|
end
|
||||||
endblock = endblock or 20
|
endblock = endblock or 20
|
||||||
|
|
||||||
-- First of all, connect
|
-- First of all, connect
|
||||||
info, err = lib14a.read(true, true)
|
info, err = lib14a.read(true, true)
|
||||||
if err then disconnect() return oops(err) end
|
if err then disconnect() return oops(err) end
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
local blockData = {}
|
local blockData = {}
|
||||||
|
|
||||||
-- Show tag info
|
-- Show tag info
|
||||||
print(("\nFound Card UID [%s]\n"):format(info.uid))
|
print(("\nFound Card UID [%s]\n"):format(info.uid))
|
||||||
|
|
||||||
print("blk | data | xored")
|
print("blk | data | xored")
|
||||||
print("----+------------------+-------------------")
|
print("----+------------------+-------------------")
|
||||||
for block = 00, endblock do
|
for block = 00, endblock do
|
||||||
local cmd = string.format("10%02x00", block)
|
local cmd = string.format("10%02x00", block)
|
||||||
res, err = sendRaw(cmd , {ignore_response = ignore_response})
|
res, err = sendRaw(cmd , {ignore_response = ignore_response})
|
||||||
if err then disconnect() return oops(err) end
|
if err then disconnect() return oops(err) end
|
||||||
|
|
||||||
local cmd_response = Command.parse(res)
|
local cmd_response = Command.parse(res)
|
||||||
local len = tonumber(cmd_response.arg1) * 2
|
local len = tonumber(cmd_response.arg1) * 2
|
||||||
local data = string.sub(tostring(cmd_response.data), 0, len-4)
|
local data = string.sub(tostring(cmd_response.data), 0, len-4)
|
||||||
|
|
||||||
showdata(block, data)
|
showdata(block, data)
|
||||||
table.insert(blockData, data)
|
table.insert(blockData, data)
|
||||||
end
|
end
|
||||||
print("----+------------------+-------------------")
|
print("----+------------------+-------------------")
|
||||||
disconnect()
|
disconnect()
|
||||||
|
|
||||||
local filename, err = writeDumpFile(info.uid, blockData)
|
local filename, err = writeDumpFile(info.uid, blockData)
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
|
|
||||||
print(string.format("\nDumped data into %s", filename))
|
print(string.format("\nDumped data into %s", filename))
|
||||||
end
|
end
|
||||||
|
|
||||||
-------------------------
|
-------------------------
|
||||||
-- Testing
|
-- Testing
|
||||||
-------------------------
|
-------------------------
|
||||||
function selftest()
|
function selftest()
|
||||||
DEBUG = true
|
DEBUG = true
|
||||||
dbg("Performing test")
|
dbg("Performing test")
|
||||||
main()
|
main()
|
||||||
dbg("Tests done")
|
dbg("Tests done")
|
||||||
end
|
end
|
||||||
-- Flip the switch here to perform a sanity check.
|
-- Flip the switch here to perform a sanity check.
|
||||||
-- It read a nonce in two different ways, as specified in the usage-section
|
-- It read a nonce in two different ways, as specified in the usage-section
|
||||||
if "--test"==args then
|
if "--test"==args then
|
||||||
selftest()
|
selftest()
|
||||||
else
|
else
|
||||||
-- Call the main
|
-- Call the main
|
||||||
main(args)
|
main(args)
|
||||||
end
|
end
|
||||||
@@ -10,19 +10,19 @@ This script tries to set UID on a mifare Ultralight magic card which either
|
|||||||
- brickable magic tag (must write in one session)
|
- brickable magic tag (must write in one session)
|
||||||
]]
|
]]
|
||||||
example = [[
|
example = [[
|
||||||
-- backdoor magic tag
|
-- backdoor magic tag
|
||||||
script run ul_uid -u 11223344556677
|
script run ul_uid -u 11223344556677
|
||||||
|
|
||||||
-- brickable magic tag
|
-- brickable magic tag
|
||||||
script run ul_uid -b -u 11223344556677
|
script run ul_uid -b -u 11223344556677
|
||||||
]]
|
]]
|
||||||
usage = [[
|
usage = [[
|
||||||
script run ul_uid -h -b -u <uid>
|
script run ul_uid -h -b -u <uid>
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h : this help
|
-h : this help
|
||||||
-u <UID> : UID (14 hexsymbols)
|
-u <UID> : UID (14 hexsymbols)
|
||||||
-b : write to brickable magic tag
|
-b : write to brickable magic tag
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local DEBUG = true
|
local DEBUG = true
|
||||||
@@ -32,113 +32,113 @@ local bxor = bit32.bxor
|
|||||||
local function dbg(args)
|
local function dbg(args)
|
||||||
if not DEBUG then return end
|
if not DEBUG then return end
|
||||||
if type(args) == "table" then
|
if type(args) == "table" then
|
||||||
local i = 1
|
local i = 1
|
||||||
while args[i] do
|
while args[i] do
|
||||||
dbg(args[i])
|
dbg(args[i])
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print("###", args)
|
print("###", args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
return nil, err
|
return nil, err
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
local function help()
|
local function help()
|
||||||
print(copyright)
|
print(copyright)
|
||||||
print(author)
|
print(author)
|
||||||
print(version)
|
print(version)
|
||||||
print(desc)
|
print(desc)
|
||||||
print('Example usage')
|
print('Example usage')
|
||||||
print(example)
|
print(example)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
--- Set UID on magic command enabled
|
--- Set UID on magic command enabled
|
||||||
function magicUID(b0, b1, b2)
|
function magicUID(b0, b1, b2)
|
||||||
|
|
||||||
print('Using backdoor Magic tag function')
|
print('Using backdoor Magic tag function')
|
||||||
|
|
||||||
-- write block 0
|
-- write block 0
|
||||||
core.console("hf 14a raw -p -a -b 7 40")
|
core.console("hf 14a raw -p -a -b 7 40")
|
||||||
core.console("hf 14a raw -p -a 43")
|
core.console("hf 14a raw -p -a 43")
|
||||||
core.console("hf 14a raw -c -a A200"..b0)
|
core.console("hf 14a raw -c -a A200"..b0)
|
||||||
|
|
||||||
-- write block 1
|
-- write block 1
|
||||||
core.console("hf 14a raw -p -a -b 7 40")
|
core.console("hf 14a raw -p -a -b 7 40")
|
||||||
core.console("hf 14a raw -p -a 43")
|
core.console("hf 14a raw -p -a 43")
|
||||||
core.console("hf 14a raw -c -a A201"..b1)
|
core.console("hf 14a raw -c -a A201"..b1)
|
||||||
|
|
||||||
-- write block 2
|
-- write block 2
|
||||||
core.console("hf 14a raw -p -a -b 7 40")
|
core.console("hf 14a raw -p -a -b 7 40")
|
||||||
core.console("hf 14a raw -p -a 43")
|
core.console("hf 14a raw -p -a 43")
|
||||||
core.console("hf 14a raw -c -a A202"..b2)
|
core.console("hf 14a raw -c -a A202"..b2)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
--- Set UID on magic but brickable
|
--- Set UID on magic but brickable
|
||||||
function brickableUID(b0, b1, b2)
|
function brickableUID(b0, b1, b2)
|
||||||
|
|
||||||
print('Using BRICKABLE Magic tag function')
|
print('Using BRICKABLE Magic tag function')
|
||||||
|
|
||||||
core.console("hf 14a raw -p -s -3")
|
core.console("hf 14a raw -p -s -3")
|
||||||
|
|
||||||
-- write block 0
|
-- write block 0
|
||||||
core.console("hf 14a raw -p -c A200"..b0)
|
core.console("hf 14a raw -p -c A200"..b0)
|
||||||
|
|
||||||
-- write block 1
|
-- write block 1
|
||||||
core.console("hf 14a raw -p -c A201"..b1)
|
core.console("hf 14a raw -p -c A201"..b1)
|
||||||
|
|
||||||
-- write block 2
|
-- write block 2
|
||||||
core.console("hf 14a raw -p -c A202"..b2)
|
core.console("hf 14a raw -p -c A202"..b2)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- The main entry point
|
-- The main entry point
|
||||||
function main(args)
|
function main(args)
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print()
|
print()
|
||||||
|
|
||||||
local uid = '04112233445566'
|
local uid = '04112233445566'
|
||||||
local tagtype = 1
|
local tagtype = 1
|
||||||
|
|
||||||
-- Read the parameters
|
-- Read the parameters
|
||||||
for o, a in getopt.getopt(args, 'hu:b') do
|
for o, a in getopt.getopt(args, 'hu:b') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
if o == "u" then uid = a end
|
if o == "u" then uid = a end
|
||||||
if o == "b" then tagtype = 2 end
|
if o == "b" then tagtype = 2 end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- uid string checks
|
-- uid string checks
|
||||||
if uid == nil then return oops('empty uid string') end
|
if uid == nil then return oops('empty uid string') end
|
||||||
if #uid == 0 then return oops('empty uid string') end
|
if #uid == 0 then return oops('empty uid string') end
|
||||||
if #uid ~= 14 then return oops('uid wrong length. Should be 7 hex bytes') end
|
if #uid ~= 14 then return oops('uid wrong length. Should be 7 hex bytes') end
|
||||||
|
|
||||||
local uidbytes = utils.ConvertHexToBytes(uid)
|
local uidbytes = utils.ConvertHexToBytes(uid)
|
||||||
|
|
||||||
local bcc1 = bxor(0x88, uidbytes[1], uidbytes[2], uidbytes[3])
|
local bcc1 = bxor(0x88, uidbytes[1], uidbytes[2], uidbytes[3])
|
||||||
local bcc2 = bxor(uidbytes[4], uidbytes[5], uidbytes[6], uidbytes[7])
|
local bcc2 = bxor(uidbytes[4], uidbytes[5], uidbytes[6], uidbytes[7])
|
||||||
|
|
||||||
local block0 = string.format('%02X%02X%02X%02X', uidbytes[1], uidbytes[2], uidbytes[3], bcc1)
|
local block0 = string.format('%02X%02X%02X%02X', uidbytes[1], uidbytes[2], uidbytes[3], bcc1)
|
||||||
local block1 = string.format('%02X%02X%02X%02X', uidbytes[4], uidbytes[5], uidbytes[6], uidbytes[7])
|
local block1 = string.format('%02X%02X%02X%02X', uidbytes[4], uidbytes[5], uidbytes[6], uidbytes[7])
|
||||||
local block2 = string.format('%02X%02X%02X%02X', bcc2, 0x48, 0x00, 0x00)
|
local block2 = string.format('%02X%02X%02X%02X', bcc2, 0x48, 0x00, 0x00)
|
||||||
|
|
||||||
print('new UID | '..uid)
|
print('new UID | '..uid)
|
||||||
|
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
if tagtype == 2 then
|
if tagtype == 2 then
|
||||||
brickableUID(block0, block1, block2)
|
brickableUID(block0, block1, block2)
|
||||||
else
|
else
|
||||||
magicUID(block0, block1, block2)
|
magicUID(block0, block1, block2)
|
||||||
end
|
end
|
||||||
|
|
||||||
--halt
|
--halt
|
||||||
core.console("hf 14a raw -c -a 5000")
|
core.console("hf 14a raw -c -a 5000")
|
||||||
end
|
end
|
||||||
|
|
||||||
main(args)
|
main(args)
|
||||||
|
|||||||
Reference in New Issue
Block a user