lua: fix mix of spaces & tabs

This commit is contained in:
Philippe Teuwen 2019-03-09 10:34:43 +01:00
commit 05ff45e550
41 changed files with 5185 additions and 5185 deletions

View file

@ -6,22 +6,22 @@ example = "script run 14araw -x 6000F57b"
author = "Martin Holst Swende"
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:
-o do not connect - use this only if you previously used -p to stay connected
-r do not read response
-c calculate and append CRC
-p stay connected - dont inactivate the field
-x <payload> Data to send (NO SPACES!)
-d Debug flag
-t Topaz mode
-3 ISO14443-4 (use RATS)
-o do not connect - use this only if you previously used -p to stay connected
-r do not read response
-c calculate and append CRC
-p stay connected - dont inactivate the field
-x <payload> Data to send (NO SPACES!)
-d Debug flag
-t Topaz mode
-3 ISO14443-4 (use RATS)
Examples :
Examples :
# 1. Connect and don't disconnect
script run 14araw -p
script run 14araw -p
# 2. Send mf auth, read response (nonce)
script run 14araw -o -x 6000F57b -p
# 3. disconnect
@ -33,11 +33,11 @@ script run 14araw -x 6000F57b
--[[
This script communicates with
/armsrc/iso14443a.c, specifically ReaderIso14443a() at around line 1779 and onwards.
This script communicates with
/armsrc/iso14443a.c, specifically ReaderIso14443a() at around line 1779 and onwards.
Check there for details about data format and how commands are interpreted on the
device-side.
Check there for details about data format and how commands are interpreted on the
device-side.
]]
-- Some globals
@ -45,143 +45,143 @@ local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
local DEBUG = false -- the debug flag
-------------------------------
-- Some utilities
-- Some utilities
-------------------------------
---
---
-- A debug printout-function
local function dbg(args)
if DEBUG then
print("###", args)
end
end
---
if DEBUG then
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
local function oops(err)
print("ERROR: ",err)
print("ERROR: ",err)
end
---
---
-- Usage help
local function help()
print(desc)
print("Example usage")
print(example)
print(desc)
print("Example usage")
print(example)
end
---
---
-- The main entry point
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 append_crc = false
local stayconnected = false
local payload = nil
local doconnect = true
local topaz_mode = false
local no_rats = false
-- Read the parameters
for o, a in getopt.getopt(args, 'orcpx:dt3') do
if o == "o" then doconnect = false end
if o == "r" then ignore_response = true end
if o == "c" then append_crc = true end
if o == "p" then stayconnected = true end
if o == "x" then payload = a end
if o == "d" then DEBUG = true end
if o == "t" then topaz_mode = true end
if o == "3" then no_rats = true end
end
local ignore_response = false
local append_crc = false
local stayconnected = false
local payload = nil
local doconnect = true
local topaz_mode = false
local no_rats = false
-- First of all, connect
if doconnect then
dbg("doconnect")
-- We reuse the connect functionality from a
-- common library
info, err = lib14a.read(true, no_rats)
-- Read the parameters
for o, a in getopt.getopt(args, 'orcpx:dt3') do
if o == "o" then doconnect = false end
if o == "r" then ignore_response = true end
if o == "c" then append_crc = true end
if o == "p" then stayconnected = true end
if o == "x" then payload = a end
if o == "d" then DEBUG = true end
if o == "t" then topaz_mode = true end
if o == "3" then no_rats = true end
end
if err then return oops(err) end
print(("Connected to card, uid = %s"):format(info.uid))
end
-- First of all, connect
if doconnect then
dbg("doconnect")
-- We reuse the connect functionality from a
-- common library
info, err = lib14a.read(true, no_rats)
-- The actual raw payload, if any
if payload then
res,err = sendRaw(payload,{ignore_response = ignore_response, topaz_mode = topaz_mode, append_crc = append_crc})
if err then return oops(err) end
if not ignoreresponse then
-- Display the returned data
showdata(res)
end
end
-- And, perhaps disconnect?
if not stayconnected then
disconnect()
end
if err then return oops(err) end
print(("Connected to card, uid = %s"):format(info.uid))
end
-- The actual raw payload, if any
if payload then
res,err = sendRaw(payload,{ignore_response = ignore_response, topaz_mode = topaz_mode, append_crc = append_crc})
if err then return oops(err) end
if not ignoreresponse then
-- Display the returned data
showdata(res)
end
end
-- And, perhaps disconnect?
if not stayconnected then
disconnect()
end
end
--- Picks out and displays the data read from a tag
-- Specifically, takes a usb packet, converts to a Command
-- (as in commands.lua), takes the data-array and
-- (as in commands.lua), takes the data-array and
-- reads the number of bytes specified in arg1 (arg0 in c-struct)
-- and displays the data
-- @param usbpacket the data received from the device
function showdata(usbpacket)
local cmd_response = Command.parse(usbpacket)
local len = tonumber(cmd_response.arg1) *2
--print("data length:",len)
local data = string.sub(tostring(cmd_response.data), 0, len);
print("<< ",data)
--print("----------------")
local cmd_response = Command.parse(usbpacket)
local len = tonumber(cmd_response.arg1) *2
--print("data length:",len)
local data = string.sub(tostring(cmd_response.data), 0, len);
print("<< ",data)
--print("----------------")
end
function sendRaw(rawdata, options)
print(">> ", rawdata)
local flags = lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT + lib14a.ISO14A_COMMAND.ISO14A_RAW
print(">> ", rawdata)
if options.topaz_mode then
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_TOPAZMODE
end
if options.append_crc then
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC
end
local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a,
arg1 = flags, -- Send raw
-- arg2 contains the length, which is half the length
-- of the ASCII-string rawdata
arg2 = string.len(rawdata)/2,
data = rawdata}
return lib14a.sendToDevice(command, options.ignore_response)
local flags = lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT + lib14a.ISO14A_COMMAND.ISO14A_RAW
if options.topaz_mode then
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_TOPAZMODE
end
if options.append_crc then
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC
end
local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a,
arg1 = flags, -- Send raw
-- arg2 contains the length, which is half the length
-- of the ASCII-string rawdata
arg2 = string.len(rawdata)/2,
data = rawdata}
return lib14a.sendToDevice(command, options.ignore_response)
end
-- Sends an instruction to do nothing, only disconnect
function disconnect()
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
-- Check /armsrc/iso14443a.c, ReaderIso14443a() for details
return lib14a.sendToDevice(command,true)
end
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
-- Check /armsrc/iso14443a.c, ReaderIso14443a() for details
return lib14a.sendToDevice(command,true)
end
-------------------------
-- Testing
-- Testing
-------------------------
function selftest()
DEBUG = true
dbg("Performing test")
main()
main("-p")
main(" -o -x 6000F57b -p")
main("-o")
main("-x 6000F57b")
dbg("Tests done")
DEBUG = true
dbg("Performing test")
main()
main("-p")
main(" -o -x 6000F57b -p")
main("-o")
main("-x 6000F57b")
dbg("Tests done")
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
if "--test"==args then
selftest()
else
-- Call the main
main(args)
if "--test"==args then
selftest()
else
-- Call the main
main(args)
end

View file

@ -1,87 +1,87 @@
--[[
script to create a clone-dump with new crc
script to create a clone-dump with new crc
Author: mosci
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
2. write to outfile
3. set byte 0x05 to newcrc
4. until byte 0x21 plain like in inputfile
5. from 0x22..end xored with newcrc
6. calculate new crc on each segment (needs to know the new MCD & MSN0..2)
simplest usage:
read a valid legic tag with 'hf legic reader'
save the dump with 'hf legic save orig.hex'
1. read tag-dump, xor byte 22..end with byte 0x05 of the inputfile
2. write to outfile
3. set byte 0x05 to newcrc
4. until byte 0x21 plain like in inputfile
5. from 0x22..end xored with newcrc
6. calculate new crc on each segment (needs to know the new MCD & MSN0..2)
simplest usage:
read a valid legic tag with 'hf legic reader'
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'
you will see some output like:
read 1024 bytes from legic_dumps/j_0000.hex
place your empty tag onto the PM3 to read and display the MCD & MSN0..2
the values will be shown below
confirm whnen ready [y/n] ?y
#db# setting up legic card
#db# MIM 256 card found, reading card ...
#db# Card read, use 'hf legic decode' or
#db# 'data hexsamples 8' to view results
0b ad c0 de <- !! here you'll see the MCD & MSN of your empty tag, which has to be typed in manually as seen below !!
type in MCD as 2-digit value - e.g.: 00 (default: 79 )
> 0b
type in MSN0 as 2-digit value - e.g.: 01 (default: 28 )
> ad
type in MSN1 as 2-digit value - e.g.: 02 (default: d1 )
> c0
type in MSN2 as 2-digit value - e.g.: 03 (default: 43 )
> de
MCD: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
enter number of bytes to write? (default: 86 )
loaded 1024 samples
#db# setting up legic card
#db# MIM 256 card found, writing 0x00 - 0x01 ...
#db# write successful
...
#db# setting up legic card
#db# MIM 256 card found, writing 0x56 - 0x01 ...
#db# write successful
proxmark3>
the default value (number of bytes to write) is calculated over all valid segments and should be ok - just hit enter, wait until write has finished
and your clone should be ready (except there has to be a additional KGH-CRC to be calculated - which credentials are unknown until yet)
the '-w' switch will only work with my fork - it needs the binary legic_crc8 which is not part of the proxmark3-master-branch
also the ability to write DCF is not possible with the proxmark3-master-branch
but creating dumpfile-clone files will be possible (without valid segment-crc - this has to done manually with)
read 1024 bytes from legic_dumps/j_0000.hex
(example) Legic-Prime Layout with 'Kaba Group Header'
+----+----+----+----+----+----+----+----+
0x00|MCD |MSN0|MSN1|MSN2|MCC | 60 | ea | 9f |
+----+----+----+----+----+----+----+----+
0x08| ff | 00 | 00 | 00 | 11 |Bck0|Bck1|Bck2|
+----+----+----+----+----+----+----+----+
0x10|Bck3|Bck4|Bck5|BCC | 00 | 00 |Seg0|Seg1|
+----+----+----+----+----+----+----+----+
0x18|Seg2|Seg3|SegC|Stp0|Stp1|Stp2|Stp3|UID0|
+----+----+----+----+----+----+----+----+
0x20|UID1|UID2|kghC|
+----+----+----+
MCD= ManufacturerID (1 Byte)
MSN0..2= ManufactureSerialNumber (3 Byte)
MCC= CRC (1 Byte) calculated over MCD,MSN0..2
DCF= DecrementalField (2 Byte) 'credential' (enduser-Tag) seems to have always DCF-low=0x60 DCF-high=0xea
Bck0..5= Backup (6 Byte) Bck0 'dirty-flag', Bck1..5 SegmentHeader-Backup
BCC= BackupCRC (1 Byte) CRC calculated over Bck1..5
Seg0..3= SegmentHeader (on MIM 4 Byte )
SegC= SegmentCRC (1 Byte) calculated over MCD,MSN0..2,Seg0..3
Stp0..n= Stamp0... (variable length) length = Segment-Len - UserData - 1
UID0..n= UserDater (variable length - with KGH hex 0x00-0x63 / dec 0-99) length = Segment-Len - WRP - WRC - 1
kghC= KabaGroupHeader (1 Byte + addr 0x0c must be 0x11)
as seen on 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)
place your empty tag onto the PM3 to read and display the MCD & MSN0..2
the values will be shown below
confirm whnen ready [y/n] ?y
#db# setting up legic card
#db# MIM 256 card found, reading card ...
#db# Card read, use 'hf legic decode' or
#db# 'data hexsamples 8' to view results
0b ad c0 de <- !! here you'll see the MCD & MSN of your empty tag, which has to be typed in manually as seen below !!
type in MCD as 2-digit value - e.g.: 00 (default: 79 )
> 0b
type in MSN0 as 2-digit value - e.g.: 01 (default: 28 )
> ad
type in MSN1 as 2-digit value - e.g.: 02 (default: d1 )
> c0
type in MSN2 as 2-digit value - e.g.: 03 (default: 43 )
> de
MCD: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
enter number of bytes to write? (default: 86 )
loaded 1024 samples
#db# setting up legic card
#db# MIM 256 card found, writing 0x00 - 0x01 ...
#db# write successful
...
#db# setting up legic card
#db# MIM 256 card found, writing 0x56 - 0x01 ...
#db# write successful
proxmark3>
the default value (number of bytes to write) is calculated over all valid segments and should be ok - just hit enter, wait until write has finished
and your clone should be ready (except there has to be a additional KGH-CRC to be calculated - which credentials are unknown until yet)
the '-w' switch will only work with my fork - it needs the binary legic_crc8 which is not part of the proxmark3-master-branch
also the ability to write DCF is not possible with the proxmark3-master-branch
but creating dumpfile-clone files will be possible (without valid segment-crc - this has to done manually with)
(example) Legic-Prime Layout with 'Kaba Group Header'
+----+----+----+----+----+----+----+----+
0x00|MCD |MSN0|MSN1|MSN2|MCC | 60 | ea | 9f |
+----+----+----+----+----+----+----+----+
0x08| ff | 00 | 00 | 00 | 11 |Bck0|Bck1|Bck2|
+----+----+----+----+----+----+----+----+
0x10|Bck3|Bck4|Bck5|BCC | 00 | 00 |Seg0|Seg1|
+----+----+----+----+----+----+----+----+
0x18|Seg2|Seg3|SegC|Stp0|Stp1|Stp2|Stp3|UID0|
+----+----+----+----+----+----+----+----+
0x20|UID1|UID2|kghC|
+----+----+----+
MCD= ManufacturerID (1 Byte)
MSN0..2= ManufactureSerialNumber (3 Byte)
MCC= CRC (1 Byte) calculated over MCD,MSN0..2
DCF= DecrementalField (2 Byte) 'credential' (enduser-Tag) seems to have always DCF-low=0x60 DCF-high=0xea
Bck0..5= Backup (6 Byte) Bck0 'dirty-flag', Bck1..5 SegmentHeader-Backup
BCC= BackupCRC (1 Byte) CRC calculated over Bck1..5
Seg0..3= SegmentHeader (on MIM 4 Byte )
SegC= SegmentCRC (1 Byte) calculated over MCD,MSN0..2,Seg0..3
Stp0..n= Stamp0... (variable length) length = Segment-Len - UserData - 1
UID0..n= UserDater (variable length - with KGH hex 0x00-0x63 / dec 0-99) length = Segment-Len - WRP - WRC - 1
kghC= KabaGroupHeader (1 Byte + addr 0x0c must be 0x11)
as seen on this example: addr 0x05..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"
@ -89,24 +89,24 @@ author = "Mosci"
desc =
[[
This is a script which create a clone-dump of a dump from a Legic Prime Tag (MIM256 or MIM1024)
(created with 'hf legic save my_dump.hex')
(created with 'hf legic save my_dump.hex')
requiered arguments:
-i <input file> (file to read data from)
optional arguments :
-h - Help text
-o <output file> - requieres option -c to be given
-c <new-tag crc> - requieres option -o to be given
-d - Display content of found Segments
-s - Display summary at the end
-w - write directly to Tag - a file myLegicClone.hex wille be generated also
e.g.:
hint: using the CRC '00' will result in a plain dump ( -c 00 )
-i <input file> (file to read data from)
Examples :
script run legic_clone -i my_dump.hex -o my_clone.hex -c f8
script run legic_clone -i my_dump.hex -d -s
optional arguments :
-h - Help text
-o <output file> - requieres option -c to be given
-c <new-tag crc> - requieres option -o to be given
-d - Display content of found Segments
-s - Display summary at the end
-w - write directly to Tag - a file myLegicClone.hex wille be generated also
e.g.:
hint: using the CRC '00' will result in a plain dump ( -c 00 )
Examples :
script run legic_clone -i my_dump.hex -o my_clone.hex -c f8
script run legic_clone -i my_dump.hex -d -s
]]
local utils = require('utils')
@ -114,33 +114,33 @@ local getopt = require('getopt')
local bxor = bit32.bxor
-- we need always 2 digits
function prepend_zero(s)
if (string.len(s)==1) then return "0" .. s
else
if (string.len(s)==0) then return "00"
else return s
end
end
function prepend_zero(s)
if (string.len(s)==1) then return "0" .. s
else
if (string.len(s)==0) then return "00"
else return s
end
end
end
---
---
-- This is only meant to be used when errors occur
function oops(err)
print("ERROR: ",err)
return nil, err
print("ERROR: ",err)
return nil, err
end
---
---
-- Usage help
function help()
print(desc)
print("Example usage")
print(example)
print(desc)
print("Example usage")
print(example)
end
-- Check availability of file
function file_check(file_name)
local file_found=io.open(file_name, "r")
local file_found=io.open(file_name, "r")
if file_found==nil then
file_found=false
else
@ -152,113 +152,113 @@ end
--- xor-wrapper
-- xor all from addr 0x22 (start counting from 1 => 23)
function xorme(hex, xor, index)
if ( index >= 23 ) then
return ('%02x'):format(bxor( tonumber(hex,16) , tonumber(xor,16) ))
else
return hex
end
if ( index >= 23 ) then
return ('%02x'):format(bxor( tonumber(hex,16) , tonumber(xor,16) ))
else
return hex
end
end
-- read input-file into array
function getInputBytes(infile)
local line
local bytes = {}
local line
local bytes = {}
local fhi,err = io.open(infile)
if err then print("OOps ... faild to read from file ".. infile); return false; end
local fhi,err = io.open(infile)
if err then print("OOps ... faild to read from file ".. infile); return false; end
while true do
line = fhi:read()
if line == nil then break end
while true do
line = fhi:read()
if line == nil then break end
for byte in line:gmatch("%w+") do
table.insert(bytes, byte)
end
end
fhi:close()
for byte in line:gmatch("%w+") do
table.insert(bytes, byte)
end
end
print("\nread ".. #bytes .." bytes from ".. infile)
return bytes
fhi:close()
print("\nread ".. #bytes .." bytes from ".. infile)
return bytes
end
-- write to file
function writeOutputBytes(bytes, outfile)
local line
local bcnt=0
local fho,err = io.open(outfile,"w")
if err then print("OOps ... faild to open output-file ".. outfile); return false; end
local line
local bcnt=0
local fho,err = io.open(outfile,"w")
if err then print("OOps ... faild to open output-file ".. outfile); return false; end
for i = 1, #bytes do
if (bcnt == 0) then
line=bytes[i]
elseif (bcnt <= 7) then
line=line.." "..bytes[i]
end
if (bcnt == 7) then
-- write line to new file
fho:write(line.."\n")
-- reset counter & line
bcnt=-1
line=""
end
bcnt=bcnt+1
end
fho:close()
print("\nwrote ".. #bytes .." bytes to " .. outfile)
return true
for i = 1, #bytes do
if (bcnt == 0) then
line=bytes[i]
elseif (bcnt <= 7) then
line=line.." "..bytes[i]
end
if (bcnt == 7) then
-- write line to new file
fho:write(line.."\n")
-- reset counter & line
bcnt=-1
line=""
end
bcnt=bcnt+1
end
fho:close()
print("\nwrote ".. #bytes .." bytes to " .. outfile)
return true
end
-- xore certain bytes
function xorBytes(inBytes, crc)
local bytes = {}
for index = 1, #inBytes do
bytes[index] = xorme(inBytes[index], crc, index)
end
if (#inBytes == #bytes) then
-- replace crc
bytes[5] = string.sub(crc,-2)
return bytes
else
print("error: byte-count missmatch")
return false
end
local bytes = {}
for index = 1, #inBytes do
bytes[index] = xorme(inBytes[index], crc, index)
end
if (#inBytes == #bytes) then
-- replace crc
bytes[5] = string.sub(crc,-2)
return bytes
else
print("error: byte-count missmatch")
return false
end
end
-- get raw segment-data
function getSegmentData(bytes, start, index)
local raw, len, valid, last, wrp, wrc, rd, crc
local segment = {}
segment[0] = bytes[start].." "..bytes[start+1].." "..bytes[start+2].." "..bytes[start+3]
-- flag = high nibble of byte 1
segment[1] = string.sub(bytes[start+1],0,1)
local raw, len, valid, last, wrp, wrc, rd, crc
local segment = {}
segment[0] = bytes[start].." "..bytes[start+1].." "..bytes[start+2].." "..bytes[start+3]
-- flag = high nibble of byte 1
segment[1] = string.sub(bytes[start+1],0,1)
-- valid = bit 6 of byte 1
segment[2] = tonumber(bit32.extract("0x"..bytes[start+1],6,1),16)
-- valid = bit 6 of byte 1
segment[2] = tonumber(bit32.extract("0x"..bytes[start+1],6,1),16)
-- last = bit 7 of byte 1
segment[3] = tonumber(bit32.extract("0x"..bytes[start+1],7,1),16)
-- last = bit 7 of byte 1
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)
-- wrp (write proteted) = byte 2
segment[5] = tonumber(bytes[start+2])
-- wrc (write control) - bit 4-6 of byte 3
segment[6] = tonumber(bit32.extract("0x"..bytes[start+3],4,3),16)
-- wrp (write proteted) = byte 2
segment[5] = tonumber(bytes[start+2])
-- rd (read disabled) - bit 7 of byte 3
segment[7] = tonumber(bit32.extract("0x"..bytes[start+3],7,1),16)
-- wrc (write control) - bit 4-6 of byte 3
segment[6] = tonumber(bit32.extract("0x"..bytes[start+3],4,3),16)
-- crc byte 4
segment[8] = bytes[start+4]
-- rd (read disabled) - bit 7 of byte 3
segment[7] = tonumber(bit32.extract("0x"..bytes[start+3],7,1),16)
-- segment index
segment[9] = index
-- crc byte 4
segment[8] = bytes[start+4]
-- # crc-byte
segment[10] = start+4
-- segment index
segment[9] = index
-- # crc-byte
segment[10] = start+4
return segment
end
@ -276,7 +276,7 @@ function CheckKgh(bytes, segStart, segEnd)
local WRP = bytes[(segStart+2)]
local WRC = ("%02x"):format(tonumber(bit32.extract("0x"..bytes[segStart+3],4,3),16))
local RD = ("%02x"):format(tonumber(bit32.extract("0x"..bytes[segStart+3],7,1),16))
local XX = "00"
local XX = "00"
cmd = bytes[1]..bytes[2]..bytes[3]..bytes[4]..WRP..WRC..RD..XX
for i=(segStart+5), (segStart+5+dataLen-2) do
cmd = cmd..bytes[i]
@ -294,247 +294,247 @@ end
-- get only the addresses of segemnt-crc's and the length of bytes
function getSegmentCrcBytes(bytes)
local start=23
local index=0
local crcbytes = {}
repeat
seg = getSegmentData(bytes,start,index)
crcbytes[index]= seg[10]
start = start + seg[4]
index = index + 1
until (seg[3] == 1 or tonumber(seg[9]) == 126 )
crcbytes[index] = start
return crcbytes
local start=23
local index=0
local crcbytes = {}
repeat
seg = getSegmentData(bytes,start,index)
crcbytes[index]= seg[10]
start = start + seg[4]
index = index + 1
until (seg[3] == 1 or tonumber(seg[9]) == 126 )
crcbytes[index] = start
return crcbytes
end
-- print segment-data (hf legic decode like)
function displaySegments(bytes)
--display segment header(s)
start=23
index="00"
--repeat until last-flag ist set to 1 or segment-index has reached 126
repeat
wrc=""
wrp=""
pld=""
Seg = getSegmentData(bytes,start,index)
KGH = CheckKgh(bytes,start,(start+tonumber(Seg[4],10)))
printSegment(Seg)
--display segment header(s)
start=23
index="00"
-- wrc
if(Seg[6]>0) then
print("WRC protected area:")
-- length of wrc = wrc
for i=1, Seg[6] do
-- starts at (segment-start + segment-header + segment-crc)-1
wrc = wrc..bytes[(start+4+1+i)-1].." "
end
print(wrc)
elseif(Seg[5]>0) then
print("Remaining write protected area:")
-- length of wrp = (wrp-wrc)
for i=1, (Seg[5]-Seg[6]) do
-- starts at (segment-start + segment-header + segment-crc + wrc)-1
wrp = wrp..bytes[(start+4+1+Seg[6]+i)-1].." "
end
print(wrp)
end
-- payload
print("Remaining segment payload:")
--length of payload = segment-len - segment-header - segment-crc - wrp -wrc
for i=1, (Seg[4]-4-1-Seg[5]-Seg[6]) do
-- starts at (segment-start + segment-header + segment-crc + segment-wrp + segemnt-wrc)-1
pld = pld..bytes[(start+4+1+Seg[5]+Seg[6]+i)-1].." "
end
print(pld)
--repeat until last-flag ist set to 1 or segment-index has reached 126
repeat
wrc=""
wrp=""
pld=""
Seg = getSegmentData(bytes,start,index)
KGH = CheckKgh(bytes,start,(start+tonumber(Seg[4],10)))
printSegment(Seg)
-- wrc
if(Seg[6]>0) then
print("WRC protected area:")
-- length of wrc = wrc
for i=1, Seg[6] do
-- starts at (segment-start + segment-header + segment-crc)-1
wrc = wrc..bytes[(start+4+1+i)-1].." "
end
print(wrc)
elseif(Seg[5]>0) then
print("Remaining write protected area:")
-- length of wrp = (wrp-wrc)
for i=1, (Seg[5]-Seg[6]) do
-- starts at (segment-start + segment-header + segment-crc + wrc)-1
wrp = wrp..bytes[(start+4+1+Seg[6]+i)-1].." "
end
print(wrp)
end
-- payload
print("Remaining segment payload:")
--length of payload = segment-len - segment-header - segment-crc - wrp -wrc
for i=1, (Seg[4]-4-1-Seg[5]-Seg[6]) do
-- starts at (segment-start + segment-header + segment-crc + segment-wrp + segemnt-wrc)-1
pld = pld..bytes[(start+4+1+Seg[5]+Seg[6]+i)-1].." "
end
print(pld)
if (KGH) then print("'Kaba Group Header' detected"); end
start = start+Seg[4]
index = prepend_zero(tonumber(Seg[9])+1)
until (Seg[3] == 1 or tonumber(Seg[9]) == 126 )
start = start+Seg[4]
index = prepend_zero(tonumber(Seg[9])+1)
until (Seg[3] == 1 or tonumber(Seg[9]) == 126 )
end
-- print Segment values
function printSegment(SegmentData)
res = "\nSegment "..SegmentData[9]..": "
res = res.. "raw header="..SegmentData[0]..", "
res = res.. "flag="..SegmentData[1].." (valid="..SegmentData[2].." last="..SegmentData[3].."), "
res = res.. "len="..("%04d"):format(SegmentData[4])..", "
res = res.. "WRP="..prepend_zero(SegmentData[5])..", "
res = res.. "WRC="..prepend_zero(SegmentData[6])..", "
res = res.. "RD="..SegmentData[7]..", "
res = res.. "crc="..SegmentData[8]
print(res)
res = "\nSegment "..SegmentData[9]..": "
res = res.. "raw header="..SegmentData[0]..", "
res = res.. "flag="..SegmentData[1].." (valid="..SegmentData[2].." last="..SegmentData[3].."), "
res = res.. "len="..("%04d"):format(SegmentData[4])..", "
res = res.. "WRP="..prepend_zero(SegmentData[5])..", "
res = res.. "WRC="..prepend_zero(SegmentData[6])..", "
res = res.. "RD="..SegmentData[7]..", "
res = res.. "crc="..SegmentData[8]
print(res)
end
-- write clone-data to tag
function writeToTag(plainBytes)
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
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
return
end
-- gather MCD & MSN from new Tag - this must be enterd manually
cmd = 'hf legic read 0x00 0x04'
core.console(cmd)
print("\nthese are the MCD MSN0 MSN1 MSN2 from the Tag that has being read:")
cmd = 'data hexsamples 4'
core.console(cmd)
-- gather MCD & MSN from new Tag - this must be enterd manually
cmd = 'hf legic read 0x00 0x04'
core.console(cmd)
print("\nthese are the MCD MSN0 MSN1 MSN2 from the Tag that has being read:")
cmd = 'data hexsamples 4'
core.console(cmd)
print("^^ use this values as input for the following answers (one 2-digit-value per question/answer):")
-- enter MCD & MSN (in hex)
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])
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])
-- enter MCD & MSN (in hex)
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])
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])
-- calculate crc8 over MCD & MSN
cmd = MCD..MSN0..MSN1..MSN2
MCC = ("%02x"):format(utils.Crc8Legic(cmd))
print("MCD:"..MCD..", MSN:"..MSN0.." "..MSN1.." "..MSN2..", MCC:"..MCC)
-- calculate crc8 over MCD & MSN
cmd = MCD..MSN0..MSN1..MSN2
MCC = ("%02x"):format(utils.Crc8Legic(cmd))
print("MCD:"..MCD..", MSN:"..MSN0.." "..MSN1.." "..MSN2..", MCC:"..MCC)
-- calculate new Segment-CRC for each valid segment
SegCrcs = getSegmentCrcBytes(plainBytes)
for i=0, (#SegCrcs-1) do
-- calculate new Segment-CRC for each valid segment
SegCrcs = getSegmentCrcBytes(plainBytes)
for i=0, (#SegCrcs-1) do
-- SegCrcs[i]-4 = address of first byte of segmentHeader (low byte segment-length)
segLen=tonumber(("%1x"):format(tonumber(bit32.extract("0x"..plainBytes[(SegCrcs[i]-3)],0,3),16))..("%02x"):format(tonumber(plainBytes[SegCrcs[i]-4],16)),16)
segStart=(SegCrcs[i]-4)
segEnd=(SegCrcs[i]-4+segLen)
KGH=CheckKgh(plainBytes,segStart,segEnd)
if (KGH) then
if (KGH) then
print("'Kaba Group Header' detected - re-calculate...")
end
cmd = MCD..MSN0..MSN1..MSN2..plainBytes[SegCrcs[i]-4]..plainBytes[SegCrcs[i]-3]..plainBytes[SegCrcs[i]-2]..plainBytes[SegCrcs[i]-1]
plainBytes[SegCrcs[i]] = ("%02x"):format(utils.Crc8Legic(cmd))
end
cmd = MCD..MSN0..MSN1..MSN2..plainBytes[SegCrcs[i]-4]..plainBytes[SegCrcs[i]-3]..plainBytes[SegCrcs[i]-2]..plainBytes[SegCrcs[i]-1]
plainBytes[SegCrcs[i]] = ("%02x"):format(utils.Crc8Legic(cmd))
end
-- apply MCD & MSN to plain data
plainBytes[1] = MCD
plainBytes[2] = MSN0
plainBytes[3] = MSN1
plainBytes[4] = MSN2
plainBytes[5] = MCC
-- prepare plainBytes for writing (xor plain data with new MCC)
bytes = xorBytes(plainBytes, MCC)
-- write data to file
if (writeOutputBytes(bytes, "myLegicClone.hex")) then
WriteBytes = utils.input("enter number of bytes to write?", SegCrcs[#SegCrcs])
-- apply MCD & MSN to plain data
plainBytes[1] = MCD
plainBytes[2] = MSN0
plainBytes[3] = MSN1
plainBytes[4] = MSN2
plainBytes[5] = MCC
-- load file into pm3-buffer
cmd = 'hf legic load myLegicClone.hex'
core.console(cmd)
-- write pm3-buffer to Tag
for i=0, WriteBytes do
if ( i<5 or i>6) then
cmd = ('hf legic write 0x%02x 0x01'):format(i)
core.console(cmd)
elseif (i == 6) then
-- write DCF in reverse order (requires 'mosci-patch')
cmd = 'hf legic write 0x05 0x02'
core.console(cmd)
else
print("skipping byte 0x05 - will be written next step")
end
utils.Sleep(0.2)
end
end
-- prepare plainBytes for writing (xor plain data with new MCC)
bytes = xorBytes(plainBytes, MCC)
-- write data to file
if (writeOutputBytes(bytes, "myLegicClone.hex")) then
WriteBytes = utils.input("enter number of bytes to write?", SegCrcs[#SegCrcs])
-- load file into pm3-buffer
cmd = 'hf legic load myLegicClone.hex'
core.console(cmd)
-- write pm3-buffer to Tag
for i=0, WriteBytes do
if ( i<5 or i>6) then
cmd = ('hf legic write 0x%02x 0x01'):format(i)
core.console(cmd)
elseif (i == 6) then
-- write DCF in reverse order (requires 'mosci-patch')
cmd = 'hf legic write 0x05 0x02'
core.console(cmd)
else
print("skipping byte 0x05 - will be written next step")
end
utils.Sleep(0.2)
end
end
end
-- main function
function main(args)
-- some variables
local i=0
local oldcrc, newcrc, infile, outfile
local bytes = {}
local segments = {}
-- parse arguments for the script
for o, a in getopt.getopt(args, 'hwsdc:i:o:') do
-- output file
if o == "o" then
outfile = a
ofs = true
if (file_check(a)) then
local answer = utils.confirm("\nthe output-file "..a.." alredy exists!\nthis will delete the previous content!\ncontinue?")
if (answer==false) then return oops("quiting") end
end
end
-- input file
if o == "i" then
infile = a
if (file_check(infile)==false) then
return oops("input file: "..infile.." not found")
else
bytes = getInputBytes(infile)
oldcrc = bytes[5]
ifs = true
if (bytes == false) then return oops('couldnt get input bytes') end
end
i = i+1
end
-- new crc
if o == "c" then
newcrc = a
ncs = true
end
-- display segments switch
if o == "d" then ds = true; end
-- display summary switch
if o == "s" then ss = true; end
-- write to tag switch
if o == "w" then ws = true; end
-- help
if o == "h" then return help() end
end
if (not ifs) then return oops("option -i <input file> is required but missing") end
-- bytes to plain
bytes = xorBytes(bytes, oldcrc)
-- show segments (works only on plain bytes)
if (ds) then
print("+------------------------------------------- Segments -------------------------------------------+")
displaySegments(bytes);
end
-- some variables
local i=0
local oldcrc, newcrc, infile, outfile
local bytes = {}
local segments = {}
if (ofs and ncs) then
-- xor bytes with new crc
newBytes = xorBytes(bytes, newcrc)
-- write output
if (writeOutputBytes(newBytes, outfile)) then
-- show summary if requested
if (ss) then
-- information
res = "\n+-------------------------------------------- Summary -------------------------------------------+"
res = res .."\ncreated clone_dump from\n\t"..infile.." crc: "..oldcrc.."\ndump_file:"
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 .."\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 .."\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 .."\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
print(res)
end
end
else
if (ss) then
-- show why the output-file was not written
print("\nnew file not written - some arguments are missing ..")
print("output file: ".. (ofs and outfile or "not given"))
print("new crc: ".. (ncs and newcrc or "not given"))
end
end
-- write to tag
if (ws and #bytes == 1024) then
writeToTag(bytes)
end
-- parse arguments for the script
for o, a in getopt.getopt(args, 'hwsdc:i:o:') do
-- output file
if o == "o" then
outfile = a
ofs = true
if (file_check(a)) then
local answer = utils.confirm("\nthe output-file "..a.." alredy exists!\nthis will delete the previous content!\ncontinue?")
if (answer==false) then return oops("quiting") end
end
end
-- input file
if o == "i" then
infile = a
if (file_check(infile)==false) then
return oops("input file: "..infile.." not found")
else
bytes = getInputBytes(infile)
oldcrc = bytes[5]
ifs = true
if (bytes == false) then return oops('couldnt get input bytes') end
end
i = i+1
end
-- new crc
if o == "c" then
newcrc = a
ncs = true
end
-- display segments switch
if o == "d" then ds = true; end
-- display summary switch
if o == "s" then ss = true; end
-- write to tag switch
if o == "w" then ws = true; end
-- help
if o == "h" then return help() end
end
if (not ifs) then return oops("option -i <input file> is required but missing") end
-- bytes to plain
bytes = xorBytes(bytes, oldcrc)
-- show segments (works only on plain bytes)
if (ds) then
print("+------------------------------------------- Segments -------------------------------------------+")
displaySegments(bytes);
end
if (ofs and ncs) then
-- xor bytes with new crc
newBytes = xorBytes(bytes, newcrc)
-- write output
if (writeOutputBytes(newBytes, outfile)) then
-- show summary if requested
if (ss) then
-- information
res = "\n+-------------------------------------------- Summary -------------------------------------------+"
res = res .."\ncreated clone_dump from\n\t"..infile.." crc: "..oldcrc.."\ndump_file:"
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 .."\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 .."\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 .."\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
print(res)
end
end
else
if (ss) then
-- show why the output-file was not written
print("\nnew file not written - some arguments are missing ..")
print("output file: ".. (ofs and outfile or "not given"))
print("new crc: ".. (ncs and newcrc or "not given"))
end
end
-- write to tag
if (ws and #bytes == 1024) then
writeToTag(bytes)
end
end
-- call main with arguments

View file

@ -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 _, err = reader.sendToDevice(simCmd)
if err then
print('Failed to start simulator', err)
return
print('Failed to start simulator', err)
return
else
print('Starting simulator')
print('Starting simulator')
end
end

View file

@ -21,7 +21,7 @@ desc = [[
This script uses the proxmark3 implementations of simulation to bruteforce given ranges of id.
It uses both LF and HF simulations.
-- Author note
-- I wrote this as i was doing a PACS audit. This is far from complete, but is easily expandable.
-- The idea was based on proxbrute, but i needed more options, and support for different readers.
@ -38,8 +38,8 @@ usage = [[
script run brutesim -r rfid_tag -f facility_code -b base_card_number -c count -t timeout -d direction
Arguments:
-h this help
-r *see below RFID Tag: the RFID tag to emulate
-h this help
-r *see below RFID Tag: the RFID tag to emulate
pyramid
awid
fdx
@ -50,251 +50,251 @@ Arguments:
14a
hid
-f 0-999 facility code (dfx: country id, 14a: type)
-b 0-65535 base card number to start from
-c 1-65536 number of cards to try
-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
-f 0-999 facility code (dfx: country id, 14a: type)
-b 0-65535 base card number to start from
-c 1-65536 number of cards to try
-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
]]
local DEBUG = true
local bor = bit32.bor
local bxor = bit32.bxor
local bor = bit32.bor
local bxor = bit32.bxor
local lshift = bit32.lshift
---
---
-- A debug printout-function
local function dbg(args)
if type(args) == "table" then
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print("###", args)
end
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print("###", args)
end
end
---
---
-- This is only meant to be used when errors occur
local function oops(err)
print("ERROR: ",err)
return nil,err
print("ERROR: ",err)
return nil,err
end
---
---
-- Usage help
local function help()
print(copyright)
print(author)
print(version)
print(desc)
print("Example usage")
print(example)
print(copyright)
print(author)
print(version)
print(desc)
print("Example usage")
print(example)
end
--
-- Exit message
function exitMsg(msg)
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
end
--
-- Check if a string is empty
local function isempty(s)
return s == nil or s == ''
return s == nil or s == ''
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)
bits = bits or math.max(1, select(2, math.frexp(num)))
local t = {}
for b = bits, 1, -1 do
t[b] = math.fmod(num, 2)
num = math.floor((num - t[b]) / 2)
end
return table.concat(t)
bits = bits or math.max(1, select(2, math.frexp(num)))
local t = {}
for b = bits, 1, -1 do
t[b] = math.fmod(num, 2)
num = math.floor((num - t[b]) / 2)
end
return table.concat(t)
end
--
-- check for parity in bit-string.
-- check for parity in bit-string.
local function evenparity(s)
local _, count = string.gsub(s, "1", "")
local p = count % 2
if (p == 0) then
return false
end
return true
local _, count = string.gsub(s, "1", "")
local p = count % 2
if (p == 0) then
return false
end
return true
end
--
-- calcs hex for HID
-- calcs hex for HID
local function cardHex(i, f)
fac = lshift(f, 16)
id = bor(i, fac)
stream = toBits(id, 26)
high = evenparity(string.sub(stream, 0, 12)) and 1 or 0
low = not evenparity(string.sub(stream, 13)) and 1 or 0
bits = bor(lshift(id, 1), low)
bits = bor(bits, lshift(high, 25))
preamble = bor(0, lshift(1, 5))
bits = bor(bits, lshift(1, 26))
return ("%04x%08x"):format(preamble, bits)
fac = lshift(f, 16)
id = bor(i, fac)
stream = toBits(id, 26)
high = evenparity(string.sub(stream, 0, 12)) and 1 or 0
low = not evenparity(string.sub(stream, 13)) and 1 or 0
bits = bor(lshift(id, 1), low)
bits = bor(bits, lshift(high, 25))
preamble = bor(0, lshift(1, 5))
bits = bor(bits, lshift(1, 26))
return ("%04x%08x"):format(preamble, bits)
end
--
--
local function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
print()
if #args == 0 then return help() end
print( string.rep('--',20) )
print( string.rep('--',20) )
print()
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 == 'f' then facility = a end
if o == 'b' then baseid = a end
if o == 'c' then count = a end
if o == 't' then timeout = a end
if o == 'd' then direction = a end
if o == 'h' then return print(usage) end
end
if #args == 0 then return help() end
-- Check to see if -r argument was passed
if isempty(rfidtag) then
print("You must supply the flag -r (rfid tag)")
print(usage)
return
end
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 == 'f' then facility = a end
if o == 'b' then baseid = a end
if o == 'c' then count = a end
if o == 't' then timeout = a end
if o == 'd' then direction = a end
if o == 'h' then return print(usage) end
end
-- Check what RFID Tag we are using
if rfidtag == 'pyramid' then
consolecommand = 'lf pyramid sim' -- set the console command
rfidtagname = 'Farpointe/Pyramid' -- set the display name
facilityrequired = 1 -- set if FC is required
elseif rfidtag == 'awid' then
consolecommand = 'lf awid sim'
rfidtagname = 'AWID'
facilityrequired = 1
elseif rfidtag == 'fdx' then -- I'm not sure why you would need to bruteforce this ¯\_(ツ)_/¯
consolecommand = 'lf fdx sim'
rfidtagname = 'FDX-B'
facilityrequired = 1
elseif rfidtag == 'jablotron' then
consolecommand = 'lf jablotron sim'
rfidtagname = 'Jablotron'
facilityrequired = 0
elseif rfidtag == 'noralsy' then
consolecommand = 'lf noralsy sim'
rfidtagname = 'Noralsy'
facilityrequired = 0
elseif rfidtag == 'presco' then
consolecommand = 'lf presco sim d'
rfidtagname = 'Presco'
facilityrequired = 0
elseif rfidtag == 'visa2000' then
consolecommand = 'lf visa2000 sim'
rfidtagname = 'Visa2000'
facilityrequired = 0
elseif rfidtag == '14a' then
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
elseif facility == "2" then rfidtagname = 'MIFARE Ultralight'
elseif facility == "3" then rfidtagname = 'MIFARE Desfire'
elseif facility == "4" then rfidtagname = 'ISO/IEC 14443-4'
elseif facility == "5" then rfidtagname = 'MIFARE Tnp3xxx'
else
print("Invalid 14a type (-f) supplied. Must be 1-5")
print(usage)
return
end
facilityrequired = 0 -- Disable the FC required check, as we used it for type instead of FC
elseif rfidtag == 'hid' then
consolecommand = 'lf hid sim'
rfidtagname = 'HID'
facilityrequired = 1
else -- Display error and exit out if bad RFID tag was supplied
print("Invalid rfid tag (-r) supplied")
print(usage)
return
end
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(usage)
return
end
-- Check to see if -r argument was passed
if isempty(rfidtag) then
print("You must supply the flag -r (rfid tag)")
print(usage)
return
end
if isempty(count) then -- Display error and exit out of no count is set
print("You must supply the flag -c (count)")
print(usage)
return
end
if facilityrequired == 1 then -- If FC is required
facilitymessage = " - Facility Code: " -- Add FC to status message
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")
facility = 0
end
else -- If FC is not required
facility = "" -- Clear FC
facilitymessage = "" -- Remove FC from status message
end
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")
timeout = 0
end
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")
direction = 'down'
end
if tonumber(count) < 1 then
print("Count -c must be set to 1 or higher")
return
else
count = count -1 -- Make our count accurate by removing 1, because math
end
if direction == 'down' then -- If counting down, set up our for loop to count down
endid = baseid - count
fordirection = -1
elseif direction == 'up' then -- If counting up, set our for loop to count up
endid = baseid + count
fordirection = 1
else -- If invalid direction was set, show warning and set up our for loop to count down
print("Invalid direction (-d) supplied, using down")
endid = baseid - count
fordirection = -1
end
-- Check what RFID Tag we are using
if rfidtag == 'pyramid' then
consolecommand = 'lf pyramid sim' -- set the console command
rfidtagname = 'Farpointe/Pyramid' -- set the display name
facilityrequired = 1 -- set if FC is required
elseif rfidtag == 'awid' then
consolecommand = 'lf awid sim'
rfidtagname = 'AWID'
facilityrequired = 1
elseif rfidtag == 'fdx' then -- I'm not sure why you would need to bruteforce this ¯\_(ツ)_/¯
consolecommand = 'lf fdx sim'
rfidtagname = 'FDX-B'
facilityrequired = 1
elseif rfidtag == 'jablotron' then
consolecommand = 'lf jablotron sim'
rfidtagname = 'Jablotron'
facilityrequired = 0
elseif rfidtag == 'noralsy' then
consolecommand = 'lf noralsy sim'
rfidtagname = 'Noralsy'
facilityrequired = 0
elseif rfidtag == 'presco' then
consolecommand = 'lf presco sim d'
rfidtagname = 'Presco'
facilityrequired = 0
elseif rfidtag == 'visa2000' then
consolecommand = 'lf visa2000 sim'
rfidtagname = 'Visa2000'
facilityrequired = 0
elseif rfidtag == '14a' then
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
elseif facility == "2" then rfidtagname = 'MIFARE Ultralight'
elseif facility == "3" then rfidtagname = 'MIFARE Desfire'
elseif facility == "4" then rfidtagname = 'ISO/IEC 14443-4'
elseif facility == "5" then rfidtagname = 'MIFARE Tnp3xxx'
else
print("Invalid 14a type (-f) supplied. Must be 1-5")
print(usage)
return
end
facilityrequired = 0 -- Disable the FC required check, as we used it for type instead of FC
elseif rfidtag == 'hid' then
consolecommand = 'lf hid sim'
rfidtagname = 'HID'
facilityrequired = 1
else -- Display error and exit out if bad RFID tag was supplied
print("Invalid rfid tag (-r) supplied")
print(usage)
return
end
-- display status message
print("")
print("BruteForcing "..rfidtagname..""..facilitymessage..""..facility.." - CardNumber Start: "..baseid.." - CardNumber End: "..endid.." - TimeOut: "..timeout)
print("")
-- loop through for each count (-c)
for cardnum = baseid, endid, fordirection do
-- 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
-- send command to proxmark
core.console(consolecommand..' '..facility..' '..cardnum)
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(usage)
return
end
if timeout == 'pause' then
print("Press enter to continue ...")
io.read()
else
os.execute("sleep "..timeout.."")
end
end
-- ping the proxmark to stop emulation and see if its still responding
core.console('hw ping')
if isempty(count) then -- Display error and exit out of no count is set
print("You must supply the flag -c (count)")
print(usage)
return
end
if facilityrequired == 1 then -- If FC is required
facilitymessage = " - Facility Code: " -- Add FC to status message
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")
facility = 0
end
else -- If FC is not required
facility = "" -- Clear FC
facilitymessage = "" -- Remove FC from status message
end
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")
timeout = 0
end
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")
direction = 'down'
end
if tonumber(count) < 1 then
print("Count -c must be set to 1 or higher")
return
else
count = count -1 -- Make our count accurate by removing 1, because math
end
if direction == 'down' then -- If counting down, set up our for loop to count down
endid = baseid - count
fordirection = -1
elseif direction == 'up' then -- If counting up, set our for loop to count up
endid = baseid + count
fordirection = 1
else -- If invalid direction was set, show warning and set up our for loop to count down
print("Invalid direction (-d) supplied, using down")
endid = baseid - count
fordirection = -1
end
-- display status message
print("")
print("BruteForcing "..rfidtagname..""..facilitymessage..""..facility.." - CardNumber Start: "..baseid.." - CardNumber End: "..endid.." - TimeOut: "..timeout)
print("")
-- loop through for each count (-c)
for cardnum = baseid, endid, fordirection do
-- 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
-- send command to proxmark
core.console(consolecommand..' '..facility..' '..cardnum)
if timeout == 'pause' then
print("Press enter to continue ...")
io.read()
else
os.execute("sleep "..timeout.."")
end
end
-- ping the proxmark to stop emulation and see if its still responding
core.console('hw ping')
end
main(args)

View file

@ -7,170 +7,170 @@ copyright = ''
author = "Iceman"
version = 'v1.0.0'
desc = [[
This script calculates mifare keys based on uid diversification for DI.
This script calculates mifare keys based on uid diversification for DI.
Algo not found by me.
]]
example = [[
-- if called without, it reads tag uid
script run calc_di
--
script run calc_di -u 11223344556677
-- if called without, it reads tag uid
script run calc_di
--
script run calc_di -u 11223344556677
]]
usage = [[
script run calc_di -h -u <uid>
Arguments:
-h : this help
-u <UID> : UID
-h : this help
-u <UID> : UID
]]
local DEBUG = true
local BAR = '286329204469736E65792032303133'
local MIS = '0A14FD0507FF4BCD026BA83F0A3B89A9'
local bxor = bit32.bxor
---
---
-- A debug printout-function
local function dbg(args)
if not DEBUG then return end
if type(args) == "table" then
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print("###", args)
end
end
---
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
local function oops(err)
print("ERROR: ",err)
return nil,err
print("ERROR: ",err)
return nil,err
end
---
---
-- Usage help
local function help()
print(copyright)
print(author)
print(version)
print(desc)
print('Example usage')
print(example)
print(copyright)
print(author)
print(version)
print(desc)
print('Example usage')
print(example)
end
---
-- Exit message
local function exitMsg(msg)
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
end
---
-- dumps all keys to file
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
local destination = utils.input('Select a filename to store to', 'dumpkeys.bin')
local file = io.open(destination, 'wb')
if file == nil then
print('Could not write to file ', destination)
return
end
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 file = io.open(destination, 'wb')
if file == nil then
print('Could not write to file ', destination)
return
end
-- Mifare Mini has 5 sectors,
local key_a = ''
local key_b = ''
for sector = 0, #keys do
local keyA, keyB = unpack(keys[sector])
key_a = key_a .. bin.pack('H', keyA);
key_b = key_b .. bin.pack('H', keyB);
end
file:write(key_a)
file:write(key_b)
file:close()
end
-- Mifare Mini has 5 sectors,
local key_a = ''
local key_b = ''
for sector = 0, #keys do
local keyA, keyB = unpack(keys[sector])
key_a = key_a .. bin.pack('H', keyA);
key_b = key_b .. bin.pack('H', keyB);
end
file:write(key_a)
file:write(key_b)
file:close()
end
end
---
-- create key
local function keygen(uid)
local data = MIS..uid..BAR
local hash = utils.ConvertAsciiToBytes(utils.Sha1Hex(data))
return string.format("%02X%02X%02X%02X%02X%02X",
hash[3+1],
hash[2+1],
hash[1+1],
hash[0+1],
hash[7+1],
hash[6+1]
)
local data = MIS..uid..BAR
local hash = utils.ConvertAsciiToBytes(utils.Sha1Hex(data))
return string.format("%02X%02X%02X%02X%02X%02X",
hash[3+1],
hash[2+1],
hash[1+1],
hash[0+1],
hash[7+1],
hash[6+1]
)
end
---
-- print keys
local function printKeys(keys)
print('|---|----------------|---|----------------|---|')
print('|sec|key A |res|key B |res|')
print('|---|----------------|---|----------------|---|')
for sector = 0, #keys do
local keyA, keyB = unpack(keys[sector])
print(('|%03d| %s | %s | %s | %s |'):format(sector, keyA, 1, keyB, 1))
end
print('|---|----------------|---|----------------|---|')
print('|---|----------------|---|----------------|---|')
print('|sec|key A |res|key B |res|')
print('|---|----------------|---|----------------|---|')
for sector = 0, #keys do
local keyA, keyB = unpack(keys[sector])
print(('|%03d| %s | %s | %s | %s |'):format(sector, keyA, 1, keyB, 1))
end
print('|---|----------------|---|----------------|---|')
end
---
-- createfull set of keys
local function createKeys(uid)
local key = keygen(uid)
local k = {}
for i = 0,4 do
k[i] = { key, key }
end
return k
local key = keygen(uid)
local k = {}
for i = 0,4 do
k[i] = { key, key }
end
return k
end
---
-- main
local function main(args)
print( string.rep('==', 30) )
print()
local uid
local useUID = false
-- Arguments for the script
for o, a in getopt.getopt(args, 'hu:') do
if o == "h" then return help() end
if o == "u" then uid = a; useUID = true end
end
print( string.rep('==', 30) )
print()
if useUID then
-- uid string checks if supplied
if uid == nil 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
else
-- GET TAG UID
local tag, err = lib14a.read(false, true)
if not tag then return oops(err) end
core.clearCommandBuffer()
local uid
local useUID = false
-- simple tag check
if 0x09 ~= tag.sak then
if 0x4400 ~= tag.atqa then
return oops(('[fail] found tag %s :: looking for Mifare Mini 0.3k'):format(tag.name))
end
end
uid = tag.uid
end
print('|UID|', uid)
local keys, err = createKeys( uid )
printKeys( keys )
dumptofile( keys )
-- Arguments for the script
for o, a in getopt.getopt(args, 'hu:') do
if o == "h" then return help() end
if o == "u" then uid = a; useUID = true end
end
if useUID then
-- uid string checks if supplied
if uid == nil 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
else
-- GET TAG UID
local tag, err = lib14a.read(false, true)
if not tag then return oops(err) end
core.clearCommandBuffer()
-- simple tag check
if 0x09 ~= tag.sak then
if 0x4400 ~= tag.atqa then
return oops(('[fail] found tag %s :: looking for Mifare Mini 0.3k'):format(tag.name))
end
end
uid = tag.uid
end
print('|UID|', uid)
local keys, err = createKeys( uid )
printKeys( keys )
dumptofile( keys )
end
main(args)

View file

@ -12,167 +12,167 @@ Algo not found by me.
]]
example =[[
-- if called without, it reads tag uid
script run calc_ev1_it
--
script run calc_ev1_it -u 11223344556677
script run calc_ev1_it
--
script run calc_ev1_it -u 11223344556677
]]
usage = [[
script run calc_ev1_it -h -u <uid> "
Arguments:
-h : this help
-u <UID> : UID
-h : this help
-u <UID> : UID
]]
local DEBUG = true
local bxor = bit32.bxor
---
---
-- A debug printout-function
local function dbg(args)
if not DEBUG then return end
if not DEBUG then return end
if type(args) == "table" then
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print("###", args)
end
end
---
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
local function oops(err)
print("ERROR: ",err)
return nil,err
print("ERROR: ",err)
return nil,err
end
---
---
-- Usage help
local function help()
print(copyright)
print(author)
print(version)
print(desc)
print("Example usage")
print(example)
print(copyright)
print(author)
print(version)
print(desc)
print("Example usage")
print(example)
end
--
-- Exit message
function exitMsg(msg)
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
end
local _xortable = {
--[[ position, 4byte xor
--]]
{"00","4f2711c1"},
{"01","07D7BB83"},
{"02","9636EF07"},
{"03","B5F4460E"},
{"04","F271141C"},
{"05","7D7BB038"},
{"06","636EF871"},
{"07","5F4468E3"},
{"08","271149C7"},
{"09","D7BB0B8F"},
{"0A","36EF8F1E"},
{"0B","F446863D"},
{"0C","7114947A"},
{"0D","7BB0B0F5"},
{"0E","6EF8F9EB"},
{"0F","44686BD7"},
{"10","11494fAF"},
{"11","BB0B075F"},
{"12","EF8F96BE"},
{"13","4686B57C"},
{"14","1494F2F9"},
{"15","B0B07DF3"},
{"16","F8F963E6"},
{"17","686B5FCC"},
{"18","494F2799"},
{"19","0B07D733"},
{"1A","8F963667"},
{"1B","86B5F4CE"},
{"1C","94F2719C"},
{"1D","B07D7B38"},
{"1E","F9636E70"},
{"1F","6B5F44E0"},
{"00","4f2711c1"},
{"01","07D7BB83"},
{"02","9636EF07"},
{"03","B5F4460E"},
{"04","F271141C"},
{"05","7D7BB038"},
{"06","636EF871"},
{"07","5F4468E3"},
{"08","271149C7"},
{"09","D7BB0B8F"},
{"0A","36EF8F1E"},
{"0B","F446863D"},
{"0C","7114947A"},
{"0D","7BB0B0F5"},
{"0E","6EF8F9EB"},
{"0F","44686BD7"},
{"10","11494fAF"},
{"11","BB0B075F"},
{"12","EF8F96BE"},
{"13","4686B57C"},
{"14","1494F2F9"},
{"15","B0B07DF3"},
{"16","F8F963E6"},
{"17","686B5FCC"},
{"18","494F2799"},
{"19","0B07D733"},
{"1A","8F963667"},
{"1B","86B5F4CE"},
{"1C","94F2719C"},
{"1D","B07D7B38"},
{"1E","F9636E70"},
{"1F","6B5F44E0"},
}
local function findEntryByUid( uid )
-- xor UID4,UID5,UID6,UID7
-- mod 0x20 (dec 32)
local pos = (bxor(uid[4], uid[5], uid[6], uid[7])) % 32
-- xor UID4,UID5,UID6,UID7
-- mod 0x20 (dec 32)
local pos = (bxor(uid[4], uid[5], uid[6], uid[7])) % 32
-- convert to hexstring
pos = string.format('%02X', pos)
-- convert to hexstring
pos = string.format('%02X', pos)
for k, v in pairs(_xortable) do
if ( v[1] == pos ) then
return utils.ConvertHexToBytes(v[2])
end
end
return nil
if ( v[1] == pos ) then
return utils.ConvertHexToBytes(v[2])
end
end
return nil
end
---
-- create pwd
local function pwdgen(uid)
-- PWD CALC
-- PWD0 = T0 xor B xor C xor D
-- PWD1 = T1 xor A xor C xor E
-- PWD2 = T2 xor A xor B xor F
-- PWD3 = T3 xor G
local uidbytes = utils.ConvertHexToBytes(uid)
-- PWD CALC
-- PWD0 = T0 xor B xor C xor D
-- PWD1 = T1 xor A xor C xor E
-- PWD2 = T2 xor A xor B xor F
-- PWD3 = T3 xor G
local uidbytes = utils.ConvertHexToBytes(uid)
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 pwd1 = bxor( entry[2], uidbytes[1], uidbytes[3], uidbytes[5])
local pwd2 = bxor( entry[3], uidbytes[1], uidbytes[2], uidbytes[6])
local pwd3 = bxor( entry[4], uidbytes[7])
return string.format('%02X%02X%02X%02X', pwd0, pwd1, pwd2, pwd3)
local pwd1 = bxor( entry[2], uidbytes[1], uidbytes[3], uidbytes[5])
local pwd2 = bxor( entry[3], uidbytes[1], uidbytes[2], uidbytes[6])
local pwd3 = bxor( entry[4], uidbytes[7])
return string.format('%02X%02X%02X%02X', pwd0, pwd1, pwd2, pwd3)
end
--
-- main
local function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
print()
local uid = '04111211121110'
local useUID = false
-- Arguments for the script
for o, a in getopt.getopt(args, 'hu:') do
if o == "h" then return help() end
if o == "u" then uid = a; useUID = true end
end
print( string.rep('--',20) )
print( string.rep('--',20) )
print()
if useUID then
-- uid string checks
if uid == nil 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
else
-- GET TAG UID
local tag, err = lib14a.read(false, true)
if not tag then return oops(err) end
core.clearCommandBuffer()
uid = tag.uid
end
print('UID | '..uid)
local pwd, err = pwdgen(uid)
if not pwd then return ooops(err) end
print(string.format('PWD | %s', pwd))
local uid = '04111211121110'
local useUID = false
-- Arguments for the script
for o, a in getopt.getopt(args, 'hu:') do
if o == "h" then return help() end
if o == "u" then uid = a; useUID = true end
end
if useUID then
-- uid string checks
if uid == nil 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
else
-- GET TAG UID
local tag, err = lib14a.read(false, true)
if not tag then return oops(err) end
core.clearCommandBuffer()
uid = tag.uid
end
print('UID | '..uid)
local pwd, err = pwdgen(uid)
if not pwd then return ooops(err) end
print(string.format('PWD | %s', pwd))
end
main(args)

View file

@ -6,192 +6,192 @@ local utils = require('utils')
author = 'Iceman'
version = 'v1.0.0'
desc = [[
This script calculates mifare keys based on uid diversification for mizip.
This script calculates mifare keys based on uid diversification for mizip.
Algo not found by me.
]]
example = [[
-- if called without, it reads tag uid
script run calc_mizip
--
script run calc_mizip -u 11223344
-- if called without, it reads tag uid
script run calc_mizip
--
script run calc_mizip -u 11223344
]]
usage = [[
script run calc_mizip -h -u <uid>
Arguments:
-h : this help
-u <UID> : UID
-h : this help
-u <UID> : UID
]]
local DEBUG = true
local bxor = bit32.bxor
local _xortable = {
--[[ sector key A/B, 6byte xor
--]]
{1, "09125a2589e5", "F12C8453D821"},
{2, "AB75C937922F", "73E799FE3241"},
{3, "E27241AF2C09", "AA4D137656AE"},
{4, "317AB72F4490", "B01327272DFD"},
{1, "09125a2589e5", "F12C8453D821"},
{2, "AB75C937922F", "73E799FE3241"},
{3, "E27241AF2C09", "AA4D137656AE"},
{4, "317AB72F4490", "B01327272DFD"},
}
---
---
-- A debug printout-function
local function dbg(args)
if not DEBUG then return end
if type(args) == "table" then
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print("###", args)
end
end
---
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
local function oops(err)
print("ERROR: ",err)
return nil,err
print("ERROR: ",err)
return nil,err
end
---
---
-- Usage help
local function help()
print(copyright)
print(author)
print(version)
print(desc)
print("Example usage")
print(example)
print(copyright)
print(author)
print(version)
print(desc)
print("Example usage")
print(example)
end
--
-- Exit message
local function exitMsg(msg)
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
end
--
-- dumps all keys to file
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
local destination = utils.input('Select a filename to store to', 'dumpkeys.bin')
local file = io.open(destination, 'wb')
if file == nil then
print('Could not write to file ', destination)
return
end
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 file = io.open(destination, 'wb')
if file == nil then
print('Could not write to file ', destination)
return
end
-- Mifare Mini has 5 sectors,
local key_a = ''
local key_b = ''
for sector = 0, #keys do
local keyA, keyB = unpack(keys[sector])
key_a = key_a .. bin.pack('H', keyA);
key_b = key_b .. bin.pack('H', keyB);
end
file:write(key_a)
file:write(key_b)
file:close()
end
-- Mifare Mini has 5 sectors,
local key_a = ''
local key_b = ''
for sector = 0, #keys do
local keyA, keyB = unpack(keys[sector])
key_a = key_a .. bin.pack('H', keyA);
key_b = key_b .. bin.pack('H', keyB);
end
file:write(key_a)
file:write(key_b)
file:close()
end
end
---
-- key bytes to string
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
---
-- create key
local function calckey(uid, xorkey, keytype)
local p1,p2,p3,p4,p5,p6
if keytype == 'A' then
p1 = bxor( uid[1], xorkey[1])
p2 = bxor( uid[2], xorkey[2])
p3 = bxor( uid[3], xorkey[3])
p4 = bxor( uid[4], xorkey[4])
p5 = bxor( uid[1], xorkey[5])
p6 = bxor( uid[2], xorkey[6])
else
p1 = bxor( uid[3], xorkey[1])
p2 = bxor( uid[4], xorkey[2])
p3 = bxor( uid[1], xorkey[3])
p4 = bxor( uid[2], xorkey[4])
p5 = bxor( uid[3], xorkey[5])
p6 = bxor( uid[4], xorkey[6])
end
return keyStr(p1,p2,p3,p4,p5,p6)
end
local p1,p2,p3,p4,p5,p6
if keytype == 'A' then
p1 = bxor( uid[1], xorkey[1])
p2 = bxor( uid[2], xorkey[2])
p3 = bxor( uid[3], xorkey[3])
p4 = bxor( uid[4], xorkey[4])
p5 = bxor( uid[1], xorkey[5])
p6 = bxor( uid[2], xorkey[6])
else
p1 = bxor( uid[3], xorkey[1])
p2 = bxor( uid[4], xorkey[2])
p3 = bxor( uid[1], xorkey[3])
p4 = bxor( uid[2], xorkey[4])
p5 = bxor( uid[3], xorkey[5])
p6 = bxor( uid[4], xorkey[6])
end
return keyStr(p1,p2,p3,p4,p5,p6)
end
---
-- print keys
local function printKeys(keys)
print('|---|----------------|---|----------------|---|')
print('|sec|key A |res|key B |res|')
print('|---|----------------|---|----------------|---|')
for sector = 0, #keys do
local keyA, keyB = unpack(keys[sector])
print(('|%03d| %s | %s | %s | %s |'):format(sector, keyA, 1, keyB, 1))
end
print('|---|----------------|---|----------------|---|')
print('|---|----------------|---|----------------|---|')
print('|sec|key A |res|key B |res|')
print('|---|----------------|---|----------------|---|')
for sector = 0, #keys do
local keyA, keyB = unpack(keys[sector])
print(('|%03d| %s | %s | %s | %s |'):format(sector, keyA, 1, keyB, 1))
end
print('|---|----------------|---|----------------|---|')
end
---
-- create a full set of keys
local function createKeys(uid)
local uidbytes = utils.ConvertHexToBytes(uid)
local k = {}
k[0] = { keyStr(0xA0,0xA1,0xA2,0xA3,0xA4,0xA5), keyStr(0xB4,0xC1,0x32,0x43,0x9e,0xef) }
local uidbytes = utils.ConvertHexToBytes(uid)
local k = {}
k[0] = { keyStr(0xA0,0xA1,0xA2,0xA3,0xA4,0xA5), keyStr(0xB4,0xC1,0x32,0x43,0x9e,0xef) }
for _, v in pairs(_xortable) do
local keyA = calckey(uidbytes, utils.ConvertHexToBytes(v[2]), 'A')
local keyB = calckey(uidbytes, utils.ConvertHexToBytes(v[3]), 'B')
k[v[1]] = { keyA, keyB }
end
return k
local keyA = calckey(uidbytes, utils.ConvertHexToBytes(v[2]), 'A')
local keyB = calckey(uidbytes, utils.ConvertHexToBytes(v[3]), 'B')
k[v[1]] = { keyA, keyB }
end
return k
end
---
-- main
local function main(args)
print( string.rep('==', 30) )
print()
local uid = '11223344'
local useUID = false
-- Arguments for the script
for o, a in getopt.getopt(args, 'hu:') do
if o == "h" then return help() end
if o == "u" then uid = a ; useUID = true end
end
print( string.rep('==', 30) )
print()
if useUID then
-- uid string checks
if uid == nil 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
else
-- GET TAG UID
local tag, err = lib14a.read(false, true)
if not tag then return oops(err) end
core.clearCommandBuffer()
local uid = '11223344'
local useUID = false
-- simple tag check
if 0x09 ~= tag.sak then
if 0x4400 ~= tag.atqa then
return oops(('[fail] found tag %s :: looking for Mifare Mini 0.3k'):format(tag.name))
end
end
uid = tag.uid
end
print('|UID|', uid)
local keys, err = createKeys( uid )
printKeys( keys )
dumptofile( keys )
-- Arguments for the script
for o, a in getopt.getopt(args, 'hu:') do
if o == "h" then return help() end
if o == "u" then uid = a ; useUID = true end
end
if useUID then
-- uid string checks
if uid == nil 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
else
-- GET TAG UID
local tag, err = lib14a.read(false, true)
if not tag then return oops(err) end
core.clearCommandBuffer()
-- simple tag check
if 0x09 ~= tag.sak then
if 0x4400 ~= tag.atqa then
return oops(('[fail] found tag %s :: looking for Mifare Mini 0.3k'):format(tag.name))
end
end
uid = tag.uid
end
print('|UID|', uid)
local keys, err = createKeys( uid )
printKeys( keys )
dumptofile( keys )
end
main(args)

View file

@ -11,15 +11,15 @@ desc =
This is a script to communicate with a CALYSPO / 14443b tag using the '14b raw' commands
Arguments:
-b 123
Examples :
script run f -b 11223344
script run f
-b 123
Examples :
script run f -b 11223344
script run f
Examples :
Examples :
# 1. Connect and don't disconnect
script run f
script run f
# 2. Send mf auth, read response
script run f
# 3. disconnect
@ -28,56 +28,56 @@ script run f
]]
--[[
This script communicates with /armsrc/iso14443b.c,
Check there for details about data format and how commands are interpreted on the
device-side.
This script communicates with /armsrc/iso14443b.c,
Check there for details about data format and how commands are interpreted on the
device-side.
]]
---
--
local function calypso_switch_on_field()
local flags = lib14b.ISO14B_COMMAND.ISO14B_CONNECT
local c = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND, arg1 = flags}
return lib14b.sendToDevice(c, true)
local flags = lib14b.ISO14B_COMMAND.ISO14B_CONNECT
local c = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND, arg1 = flags}
return lib14b.sendToDevice(c, true)
end
---
-- Disconnect (poweroff) the antenna forcing a disconnect of a 14b tag.
local function calypso_switch_off_field()
local flags = lib14b.ISO14B_COMMAND.ISO14B_DISCONNECT
local c = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND, arg1 = flags}
return lib14b.sendToDevice(c, true)
local flags = lib14b.ISO14B_COMMAND.ISO14B_DISCONNECT
local c = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND, arg1 = flags}
return lib14b.sendToDevice(c, true)
end
local function calypso_parse(result)
local r = Command.parse(result)
local len = r.arg2 * 2
r.data = string.sub(r.data, 0, len);
print('GOT:', r.data)
if r.arg1 == 0 then
return r, nil
end
return nil,nil
local r = Command.parse(result)
local len = r.arg2 * 2
r.data = string.sub(r.data, 0, len);
print('GOT:', r.data)
if r.arg1 == 0 then
return r, nil
end
return nil,nil
end
---
---
-- A debug printout-function
local function dbg(args)
if DEBUG then
print("###", args)
end
end
---
if DEBUG then
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
local function oops(err)
print("ERROR: ", err)
calypso_switch_off_field()
return nil, err
print("ERROR: ", err)
calypso_switch_off_field()
return nil, err
end
---
---
-- Usage help
local function help()
print(desc)
print("Example usage")
print(example)
print(desc)
print("Example usage")
print(example)
end
--
-- helper function, give current count of items in lua-table.
@ -87,7 +87,7 @@ local function tablelen(T)
return count
end
---
-- helper function, gives a sorted table from table t,
-- helper function, gives a sorted table from table t,
-- order can be a seperate sorting-order function.
local function spairs(t, order)
-- collect the keys
@ -95,7 +95,7 @@ local function spairs(t, order)
for k in pairs(t) do keys[#keys+1] = k end
-- if order function given, sort by it by passing the table and keys a, b,
-- otherwise just sort the keys
-- otherwise just sort the keys
if order then
table.sort(keys, function(a,b) return order(t, a, b) end)
else
@ -112,54 +112,54 @@ local function spairs(t, order)
end
end
---
-- Sends a usbpackage , "hf 14b raw"
-- Sends a usbpackage , "hf 14b raw"
-- 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 command, flags, result, err
flags = lib14b.ISO14B_COMMAND.ISO14B_RAW +
lib14b.ISO14B_COMMAND.ISO14B_APPEND_CRC
local command, flags, result, err
flags = lib14b.ISO14B_COMMAND.ISO14B_RAW +
lib14b.ISO14B_COMMAND.ISO14B_APPEND_CRC
data = data or "00"
data = data or "00"
command = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND,
arg1 = flags,
arg2 = #data/2, -- LEN of data, half the length of the ASCII-string hex string
arg3 = 0,
data = data} -- data bytes (commands etc)
result, err = lib14b.sendToDevice(command, false)
if ignoreresponse then return response, err end
if result then
local r = calypso_parse(result)
return r, nil
end
return respone, err
command = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND,
arg1 = flags,
arg2 = #data/2, -- LEN of data, half the length of the ASCII-string hex string
arg3 = 0,
data = data} -- data bytes (commands etc)
result, err = lib14b.sendToDevice(command, false)
if ignoreresponse then return response, err end
if result then
local r = calypso_parse(result)
return r, nil
end
return respone, err
end
---
-- calypso_card_num : Reads card number from ATR and
-- writes it in the tree in decimal format.
local function calypso_card_num(card)
if not card then return end
local card_num = tonumber( card.uid:sub(1,8),16 )
print('Card UID', card.uid)
print('Card Number', card_num)
if not card then return end
local card_num = tonumber( card.uid:sub(1,8),16 )
print('Card UID', card.uid)
print('Card Number', card_num)
end
---
-- analyse CALYPSO apdu status bytes.
local function calypso_apdu_status(apdu)
-- last two is CRC
-- next two is APDU status bytes.
local status = false
local mess = 'FAIL'
local sw = apdu:sub( #apdu-7, #apdu-4)
desc, err = iso7816.tostring(sw)
print ('SW', sw, desc, err )
-- last two is CRC
-- next two is APDU status bytes.
local status = false
local mess = 'FAIL'
local sw = apdu:sub( #apdu-7, #apdu-4)
desc, err = iso7816.tostring(sw)
print ('SW', sw, desc, err )
status = ( sw == '9000' )
return status
status = ( sw == '9000' )
return status
end
local _calypso_cmds = {
@ -167,16 +167,16 @@ local _calypso_cmds = {
-- Break down of command bytes:
-- A4 = select
-- Master File 3F00
-- 0x3F = master file
-- 0x3F = master file
-- 0x00 = master file id, is constant to 0x00.
-- DF Dedicated File 38nn
-- can be seen as directories
-- 0x38
-- 0x38
-- 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
-- EF2 Key file
-- Grey Lock file
@ -184,93 +184,93 @@ local _calypso_cmds = {
-- Electronic Purse file
-- Electronic Transaction log file
--["01.Select ICC file"] = '0294 a4 00 0002 3f00',
["01.Select ICC file"] = '0294 a4 080004 3f00 0002',
["02.ICC"] = '0394 b2 01 041d',
["03.Select EnvHol file"] = '0294 a4 080004 2000 2001',
["04.EnvHol1"] = '0394 b2 01 041d',
["05.Select EvLog file"] = '0294 a4 080004 2000 2010',
["06.EvLog1"] = '0394 b2 01 041d',
["07.EvLog2"] = '0294 b2 02 041d',
["08.EvLog3"] = '0394 b2 03 041d',
["09.Select ConList file"] ='0294 a4 080004 2000 2050',
["10.ConList"] = '0394 b2 01 041d',
["11.Select Contra file"] = '0294 a4 080004 2000 2020',
["12.Contra1"] = '0394 b2 01 041d',
["13.Contra2"] = '0294 b2 02 041d',
["14.Contra3"] = '0394 b2 03 041d',
["15.Contra4"] = '0294 b2 04 041d',
["16.Select Counter file"]= '0394 a4 080004 2000 2069',
["17.Counter"] = '0294 b2 01 041d',
["18.Select SpecEv file"]= '0394 a4 080004 2000 2040',
["19.SpecEv1"] = '0294 b2 01 041d',
--["01.Select ICC file"] = '0294 a4 00 0002 3f00',
["01.Select ICC file"] = '0294 a4 080004 3f00 0002',
["02.ICC"] = '0394 b2 01 041d',
["03.Select EnvHol file"] = '0294 a4 080004 2000 2001',
["04.EnvHol1"] = '0394 b2 01 041d',
["05.Select EvLog file"] = '0294 a4 080004 2000 2010',
["06.EvLog1"] = '0394 b2 01 041d',
["07.EvLog2"] = '0294 b2 02 041d',
["08.EvLog3"] = '0394 b2 03 041d',
["09.Select ConList file"]= '0294 a4 080004 2000 2050',
["10.ConList"] = '0394 b2 01 041d',
["11.Select Contra file"] = '0294 a4 080004 2000 2020',
["12.Contra1"] = '0394 b2 01 041d',
["13.Contra2"] = '0294 b2 02 041d',
["14.Contra3"] = '0394 b2 03 041d',
["15.Contra4"] = '0294 b2 04 041d',
["16.Select Counter file"]= '0394 a4 080004 2000 2069',
["17.Counter"] = '0294 b2 01 041d',
["18.Select SpecEv file"] = '0394 a4 080004 2000 2040',
["19.SpecEv1"] = '0294 b2 01 041d',
}
---
---
-- The main entry point
function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
print()
local data, apdu, flags, uid, cid, result, err, card
-- Read the parameters
for o, a in getopt.getopt(args, 'h') do
if o == "h" then return help() end
end
calypso_switch_on_field()
-- Select 14b tag.
card, err = lib14b.waitFor14443b()
if not card then return oops(err) end
calypso_card_num(card)
cid = card.cid
print( string.rep('--',20) )
print( string.rep('--',20) )
print()
--[[
NAME VALUE APDU_POS
PCB 0x0A 0
CID 0x00 1
CLA 0x94 2
SELECT FILE 0xA4 3
READ FILE 0xB2 3
P1 4
P2 5
LEN_
0 1 2 3 4 5 6 7
apdu = '02 94 a4 08 00 04 3f 00 00 02' --select ICC file
DF_NAME = "1TIC.ICA"
--]]
--for i = 1,10 do
--result, err = calypso_send_cmd_raw('0294a40800043f000002',false) --select ICC file
for i, apdu in spairs(_calypso_cmds) do
print('>>', i )
apdu = apdu:gsub("%s+","")
result, err = calypso_send_cmd_raw(apdu , false)
if result then
calypso_apdu_status(result.data)
print('<<', result.data )
else
print('<< no answer')
end
end
calypso_switch_off_field()
local data, apdu, flags, uid, cid, result, err, card
-- Read the parameters
for o, a in getopt.getopt(args, 'h') do
if o == "h" then return help() end
end
calypso_switch_on_field()
-- Select 14b tag.
card, err = lib14b.waitFor14443b()
if not card then return oops(err) end
calypso_card_num(card)
cid = card.cid
--[[
NAME VALUE APDU_POS
PCB 0x0A 0
CID 0x00 1
CLA 0x94 2
SELECT FILE 0xA4 3
READ FILE 0xB2 3
P1 4
P2 5
LEN_
0 1 2 3 4 5 6 7
apdu = '02 94 a4 08 00 04 3f 00 00 02' --select ICC file
DF_NAME = "1TIC.ICA"
--]]
--for i = 1,10 do
--result, err = calypso_send_cmd_raw('0294a40800043f000002',false) --select ICC file
for i, apdu in spairs(_calypso_cmds) do
print('>>', i )
apdu = apdu:gsub("%s+","")
result, err = calypso_send_cmd_raw(apdu , false)
if result then
calypso_apdu_status(result.data)
print('<<', result.data )
else
print('<< no answer')
end
end
calypso_switch_off_field()
end
---
-- a simple selftest function, tries to convert
-- a simple selftest function, tries to convert
function selftest()
DEBUG = true
dbg("Performing test")
dbg("Tests done")
DEBUG = true
dbg("Performing test")
dbg("Tests done")
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
if "--test"==args then
selftest()
else
-- Call the main
main(args)
if "--test"==args then
selftest()
else
-- Call the main
main(args)
end

View file

@ -1,12 +1,12 @@
print("This is how a cmd-line interface could be implemented\nPrint 'exit' to exit.\n")
local answer
repeat
io.write("$>")
io.flush()
answer=io.read()
if answer ~= 'exit' then
local func = assert(loadstring("return " .. answer))
io.write("\n"..tostring(func() or "").."\n");
end--]]
until answer=="exit"
io.write("$>")
io.flush()
answer=io.read()
if answer ~= 'exit' then
local func = assert(loadstring("return " .. answer))
io.write("\n"..tostring(func() or "").."\n");
end--]]
until answer=="exit"
print("Bye\n");

View file

@ -1,4 +1,4 @@
---
---
-- requirements
local cmds = require('commands')
local getopt = require('getopt')
@ -8,9 +8,9 @@ local json = require('dkjson')
local toys = require('default_toys_di')
example =[[
script run didump
script run didump -t
script run didump -r
script run didump
script run didump -t
script run didump -r
]]
author = "Iceman"
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.
The dump is decrypted. If a raw dump is wanted, use the -r parameter
Arguments:
-h : this help
-r : raw
-t : selftest
-h : this help
-r : raw
-t : selftest
]]
local band=bit32.band
@ -40,50 +40,50 @@ local numBlocks = 20
local numSectors = 5
local CHECKSUM_OFFSET = 12; -- +1???
---
---
-- A debug printout-function
local function dbg(args)
if not DEBUG then return end
if type(args) == "table" then
local i = 1
while args[i] do
print("###", args[i])
i = i+1
end
else
print("###", args)
end
end
---
if type(args) == "table" then
local i = 1
while args[i] do
print("###", args[i])
i = i+1
end
else
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
local function oops(err)
print("ERROR: ",err)
core.clearCommandBuffer()
return false
print("ERROR: ",err)
core.clearCommandBuffer()
return false
end
---
---
-- Usage help
local function help()
print(desc)
print("Example usage")
print(example)
print(desc)
print("Example usage")
print(example)
end
---
--
local function print_info(tagdata)
--got table with data.
local h = tagdata[2]:sub(1,8)
local t = tostring( tonumber( h, 16 ) )
local item = toys.Find(t)
print( ("Modelid : %s , %s, v.%s.0"):format(t, item[3], item[2]))
--got table with data.
local h = tagdata[2]:sub(1,8)
local t = tostring( tonumber( h, 16 ) )
local item = toys.Find(t)
print( ("Modelid : %s , %s, v.%s.0"):format(t, item[3], item[2]))
end
---
-- Get checksum,
-- called: data is string (32 hex digits)
-- returns: number
local function getChecksum(data)
local chksum = data:sub(25,32)
return tonumber(chksum,16)
local chksum = data:sub(25,32)
return tonumber(chksum,16)
end
---
-- calculate checksum
@ -91,8 +91,8 @@ end
-- returns: number
local function calculateChecksum(data)
-- Generate table
local _tbl = {}
-- Generate table
local _tbl = {}
_tbl[0] = { 0x0 }
_tbl[1] = { 0x77073096 }
_tbl[2] = { 0xEE0E612C }
@ -351,248 +351,248 @@ _tbl[254] = { 0x5A05DF1B }
_tbl[255] = { 0x2D02EF8D }
-- Calculate it
local ret = 0
for i,item in pairs(data) do
local tmp = band(ret, 0xFF)
local index = band( bxor(tmp, item), 0xFF)
ret = bxor(rsh(ret,8), _tbl[index][1])
end
return ret
-- Calculate it
local ret = 0
for i,item in pairs(data) do
local tmp = band(ret, 0xFF)
local index = band( bxor(tmp, item), 0xFF)
ret = bxor(rsh(ret,8), _tbl[index][1])
end
return ret
end
---
-- update checksum
-- called: data is string, ( >= 24 hex digits )
-- returns: string, (data concat new checksum)
local function updateChecksum(data)
local part = data:sub(1,24)
local chksum = calculateChecksum( utils.ConvertHexToBytes(part))
return string.format("%s%X", part, chksum)
local part = data:sub(1,24)
local chksum = calculateChecksum( utils.ConvertHexToBytes(part))
return string.format("%s%X", part, chksum)
end
---
-- receives the answer from deviceside, used with a readblock command
local function waitCmd()
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
if response then
local count,cmd,arg0 = bin.unpack('LL',response)
if(arg0==1) then
local count,arg1,arg2,data = bin.unpack('LLH511',response,count)
return data:sub(1,32)
else
return nil, "Couldn't read block.."
end
end
return nil, "No response from device"
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
if response then
local count,cmd,arg0 = bin.unpack('LL',response)
if(arg0==1) then
local count,arg1,arg2,data = bin.unpack('LLH511',response,count)
return data:sub(1,32)
else
return nil, "Couldn't read block.."
end
end
return nil, "No response from device"
end
local function keygen(uid)
local data = MIS..uid..BAR
local hash = utils.ConvertAsciiToBytes(utils.Sha1Hex(data))
return string.format("%02X%02X%02X%02X%02X%02X",
hash[3+1],
hash[2+1],
hash[1+1],
hash[0+1],
hash[7+1],
hash[6+1]
)
local data = MIS..uid..BAR
local hash = utils.ConvertAsciiToBytes(utils.Sha1Hex(data))
return string.format("%02X%02X%02X%02X%02X%02X",
hash[3+1],
hash[2+1],
hash[1+1],
hash[0+1],
hash[7+1],
hash[6+1]
)
end
--- encode 'table' into a json formatted string
--
--
local function convert_to_json( obj )
if type(obj) == "table" then
return json.encode (obj, { indent = true })
end
return oops('[fail] input object must be a lua-TABLE')
if type(obj) == "table" then
return json.encode (obj, { indent = true })
end
return oops('[fail] input object must be a lua-TABLE')
end
--
-- Save
-- Save
local function save_json(filename, data)
jsondata = convert_to_json(data)
filename = filename or 'dumpdata.json'
local f = io.open(filename, "w")
if not f then return oops(string.format("Could not write to file %s", tostring(filename))) end
f:write(jsondata)
io.close(f)
return filename
jsondata = convert_to_json(data)
filename = filename or 'dumpdata.json'
local f = io.open(filename, "w")
if not f then return oops(string.format("Could not write to file %s", tostring(filename))) end
f:write(jsondata)
io.close(f)
return filename
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)
local function load_json(filename)
filename = filename or 'dumpdata.json'
local f = io.open(filename, "rb")
if not f then return oops(string.format("Could not read file %s", tostring(filename))) end
-- Read file
local t = f:read("*all")
io.close(f)
filename = filename or 'dumpdata.json'
local f = io.open(filename, "rb")
if not f then return oops(string.format("Could not read file %s", tostring(filename))) end
local obj, pos, err = json.decode(t, 1, nil)
if err then return oops(string.format("importing json file failed. %s", err)) end
-- Read file
local t = f:read("*all")
io.close(f)
dbg(string.format('loaded file %s', input))
return obj
local obj, pos, err = json.decode(t, 1, nil)
if err then return oops(string.format("importing json file failed. %s", err)) end
-- local len, hex = bin.unpack( ("H%d"):format(#t), t)
dbg(string.format('loaded file %s', input))
return obj
-- local len, hex = bin.unpack( ("H%d"):format(#t), t)
end
---
-- Generate encryption key
local function create_key(uid)
local key = ''
local sha = utils.Sha1Hex( FOO..BAR..uid )
sha = utils.ConvertBytesToHex( utils.ConvertAsciiToBytes(sha:sub(1,16)) )
key = utils.SwapEndiannessStr( sha:sub(1,8) , 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(25,32), 32 )
return key
local key = ''
local sha = utils.Sha1Hex( FOO..BAR..uid )
sha = utils.ConvertBytesToHex( utils.ConvertAsciiToBytes(sha:sub(1,16)) )
key = utils.SwapEndiannessStr( sha:sub(1,8) , 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(25,32), 32 )
return key
end
--- reads all blocks from tag
--
local function readtag(mfkey, aeskey )
local tagdata = {}
for blockNo = 0, numBlocks-1 do
if core.ukbhit() then
print("[fail] aborted by user")
return nil
end
local tagdata = {}
-- read block from tag.
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blockNo ,arg2 = 0,arg3 = 0, data = mfkey}
local err = core.SendCommand(cmd:getBytes())
if err then return oops(err) end
local blockdata, err = waitCmd()
if err then return oops(err) end
for blockNo = 0, numBlocks-1 do
-- rules:
-- the following blocks is NOT encrypted
-- block 0 (manufacturing) and 18
-- block with all zeros
-- sector trailor
if blockNo == 0 or blockNo == 18 then
elseif blockNo%4 ~= 3 then
if not string.find(blockdata, '^0+$') then
if aeskey then
local decrypted, err = core.aes128_decrypt_ecb(aeskey, blockdata)
if err then dbg(err) end
blockdata = utils.ConvertAsciiToHex(decrypted)
end
end
else
-- Sectorblocks, not encrypted, but we add our known key to it since it is normally zeros.
blockdata = mfkey..blockdata:sub(13,20)..mfkey
--dbg(blockdata:sub(13,20))
end
table.insert(tagdata, blockdata)
end
return tagdata
if core.ukbhit() then
print("[fail] aborted by user")
return nil
end
-- read block from tag.
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blockNo ,arg2 = 0,arg3 = 0, data = mfkey}
local err = core.SendCommand(cmd:getBytes())
if err then return oops(err) end
local blockdata, err = waitCmd()
if err then return oops(err) end
-- rules:
-- the following blocks is NOT encrypted
-- block 0 (manufacturing) and 18
-- block with all zeros
-- sector trailor
if blockNo == 0 or blockNo == 18 then
elseif blockNo%4 ~= 3 then
if not string.find(blockdata, '^0+$') then
if aeskey then
local decrypted, err = core.aes128_decrypt_ecb(aeskey, blockdata)
if err then dbg(err) end
blockdata = utils.ConvertAsciiToHex(decrypted)
end
end
else
-- Sectorblocks, not encrypted, but we add our known key to it since it is normally zeros.
blockdata = mfkey..blockdata:sub(13,20)..mfkey
--dbg(blockdata:sub(13,20))
end
table.insert(tagdata, blockdata)
end
return tagdata
end
---
-- simple selftest of functionality
local function selftest()
local testdata = '000F42430D0A14000001D11F'..'5D738517'
local chksum = getChecksum(testdata)
local calc = calculateChecksum( utils.ConvertHexToBytes(testdata:sub(1,24)))
print ( testdata:sub(1,24) )
print ( ('%x - %x'):format(chksum, calc))
local isValid = false
local validStr = "FAIL"
if calc == chksum then
isValid = true
validStr = "OK"
end
local newtestdata = updateChecksum(testdata)
local revalidated = "FAIL"
if newtestdata == testdata then
revalidated = "OK"
end
print ('TESTDATA :: '..testdata)
print ('DATA :: '..testdata:sub(1,24))
print (('VALID CHKSUM :: %s'):format(validStr ))
print (('UPDATE CHKSUM :: %s'):format(revalidated))
local testkey = keygen('0456263a873a80')
print ('TEST KEY :: '..testkey)
print ('VALID KEY :: 29564af75805')
local testdata = '000F42430D0A14000001D11F'..'5D738517'
local chksum = getChecksum(testdata)
local calc = calculateChecksum( utils.ConvertHexToBytes(testdata:sub(1,24)))
print ( testdata:sub(1,24) )
print ( ('%x - %x'):format(chksum, calc))
local isValid = false
local validStr = "FAIL"
if calc == chksum then
isValid = true
validStr = "OK"
end
local newtestdata = updateChecksum(testdata)
local revalidated = "FAIL"
if newtestdata == testdata then
revalidated = "OK"
end
print ('TESTDATA :: '..testdata)
print ('DATA :: '..testdata:sub(1,24))
print (('VALID CHKSUM :: %s'):format(validStr ))
print (('UPDATE CHKSUM :: %s'):format(revalidated))
local testkey = keygen('0456263a873a80')
print ('TEST KEY :: '..testkey)
print ('VALID KEY :: 29564af75805')
end
local function setdevicedebug( status )
local c = 'hf mf dbg '
if status then
c = c..'1'
else
c = c..'0'
end
core.console(c)
local c = 'hf mf dbg '
if status then
c = c..'1'
else
c = c..'0'
end
core.console(c)
end
---
---
-- The main entry point
-- -d decrypt
-- -e encrypt
-- -v validate
function main(args)
local cmd, tag, err, blockNo, mfkey
local shall_validate = false
local shall_dec = false
local shall_enc = false
local blocks = {}
local aeskey = ''
local input = ''
-- Read the parameters
for o, a in getopt.getopt(args, 'htdevi:') do
if o == "h" then help() return end
if o == "t" then return selftest() end
if o == "d" then shall_dec = true end
if o == "e" then shall_enc = true end
if o == "v" then shall_validate = true end
if o == "i" then input = load_json(a) end
end
local cmd, tag, err, blockNo, mfkey
local shall_validate = false
local shall_dec = false
local shall_enc = false
local blocks = {}
local aeskey = ''
local input = ''
-- Turn off Debug
setdevicedebug(false)
-- Read the parameters
for o, a in getopt.getopt(args, 'htdevi:') do
if o == "h" then help() return end
if o == "t" then return selftest() end
if o == "d" then shall_dec = true end
if o == "e" then shall_enc = true end
if o == "v" then shall_validate = true end
if o == "i" then input = load_json(a) end
end
-- GET TAG UID
tag, err = lib14a.read(false, true)
if not tag then return oops(err) end
core.clearCommandBuffer()
-- simple tag check
if 0x09 ~= tag.sak then
if 0x4400 ~= tag.atqa then
return oops(('[fail] found tag %s :: looking for Mifare Mini 0.3k'):format(tag.name))
end
end
dbg ('[ok] found '..tag.name)
-- tag key
mfkey = keygen(tag.uid)
dbg('[ok] using mf keyA : '.. mfkey)
-- AES key
aeskey = create_key(tag.uid)
dbg('[ok] using AES key : '.. aeskey)
-- Turn off Debug
setdevicedebug(false)
-- read tag data, complete, enc/dec
tagdata = readtag(mfkey, aeskey)
dbg('[ok] read card data')
-- GET TAG UID
tag, err = lib14a.read(false, true)
if not tag then return oops(err) end
core.clearCommandBuffer()
-- show information?
print_info(tagdata)
-- simple tag check
if 0x09 ~= tag.sak then
if 0x4400 ~= tag.atqa then
return oops(('[fail] found tag %s :: looking for Mifare Mini 0.3k'):format(tag.name))
end
end
dbg ('[ok] found '..tag.name)
-- save
res = save_json(nil, tagdata)
if not res then return oops('[fail] saving json file') end
dbg('[ok] read card data')
-- tag key
mfkey = keygen(tag.uid)
dbg('[ok] using mf keyA : '.. mfkey)
-- AES key
aeskey = create_key(tag.uid)
dbg('[ok] using AES key : '.. aeskey)
-- read tag data, complete, enc/dec
tagdata = readtag(mfkey, aeskey)
dbg('[ok] read card data')
-- show information?
print_info(tagdata)
-- save
res = save_json(nil, tagdata)
if not res then return oops('[fail] saving json file') end
dbg('[ok] read card data')
end
main(args)

View file

@ -13,120 +13,120 @@ This script takes a dumpfile from 'hf mfu dump' and converts it to a format that
by the emulator
Arguments:
-h This help
-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.
-h This help
-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.
]]
local DEBUG = false
---
---
-- A debug printout-function
local function dbg(args)
if not DEBUG then return end
if type(args) == 'table' then
local i = 1
while result[i] do
dbg(result[i])
i = i+1
end
else
print('###', args)
end
end
---
if not DEBUG then return end
if type(args) == 'table' then
local i = 1
while result[i] do
dbg(result[i])
i = i+1
end
else
print('###', args)
end
end
---
-- This is only meant to be used when errors occur
local function oops(err)
print('ERROR: ',err)
return nil,err
print('ERROR: ',err)
return nil,err
end
---
---
-- Usage help
function help()
print(desc)
print(author)
print("Example usage")
print(example)
print(desc)
print(author)
print("Example usage")
print(example)
end
local function convert_to_ascii(hexdata)
if string.len(hexdata) % 8 ~= 0 then
return oops(("Bad data, length should be a multiple of 8 (was %d)"):format(string.len(hexdata)))
end
if string.len(hexdata) % 8 ~= 0 then
return oops(("Bad data, length should be a multiple of 8 (was %d)"):format(string.len(hexdata)))
end
local js,i = "[";
for i = 1, string.len(hexdata),8 do
js = js .."'" ..string.sub(hexdata,i,i+7).."',\n"
end
js = js .. "]"
return js
local js,i = "[";
for i = 1, string.len(hexdata),8 do
js = js .."'" ..string.sub(hexdata,i,i+7).."',\n"
end
js = js .. "]"
return js
end
local function readdump(infile)
t = infile:read("*all")
len = string.len(t)
local len,hex = bin.unpack(("H%d"):format(len),t)
return hex
t = infile:read("*all")
len = string.len(t)
local len,hex = bin.unpack(("H%d"):format(len),t)
return hex
end
local function convert_to_emulform(hexdata)
if string.len(hexdata) % 8 ~= 0 then
return oops(("Bad data, length should be a multiple of 8 (was %d)"):format(string.len(hexdata)))
end
local ascii,i = "";
for i = 1, string.len(hexdata), 8 do
ascii = ascii..string.sub(hexdata, i, i+7).."\n"
end
return string.sub(ascii, 1, -2)
if string.len(hexdata) % 8 ~= 0 then
return oops(("Bad data, length should be a multiple of 8 (was %d)"):format(string.len(hexdata)))
end
local ascii,i = "";
for i = 1, string.len(hexdata), 8 do
ascii = ascii..string.sub(hexdata, i, i+7).."\n"
end
return string.sub(ascii, 1, -2)
end
local function main(args)
local input = "dumpdata.bin"
local output
local input = "dumpdata.bin"
local output
for o, a in getopt.getopt(args, 'i:o:h') do
if o == "h" then return help() end
if o == "i" then input = a end
if o == "o" then output = a end
end
-- Validate the parameters
local infile = io.open(input, "rb")
if infile == nil then
return oops("Could not read file ", input)
end
local dumpdata = readdump(infile)
-- The hex-data is now in ascii-format,
for o, a in getopt.getopt(args, 'i:o:h') do
if o == "h" then return help() end
if o == "i" then input = a end
if o == "o" then output = a end
end
-- Validate the parameters
-- But first, check the uid
-- lua uses start index and endindex, not count.
-- UID is 3three skip bcc0 then 4bytes.
-- 1 lua is one-index.
-- 1 + 96 (48*2) new dump format has version/signature/counter data here
-- 97,98,99,100,101,102 UID first three bytes
-- 103,104 bcc0
-- 105--- UID last four bytes
local uid = string.sub(dumpdata, 97, 97+5)..string.sub(dumpdata, 97+8, 97+8+7)
output = output or (uid .. ".eml")
local infile = io.open(input, "rb")
if infile == nil then
return oops("Could not read file ", input)
end
local dumpdata = readdump(infile)
-- The hex-data is now in ascii-format,
-- Format some linebreaks
dumpdata = convert_to_emulform(dumpdata)
-- But first, check the uid
-- lua uses start index and endindex, not count.
-- UID is 3three skip bcc0 then 4bytes.
-- 1 lua is one-index.
-- 1 + 96 (48*2) new dump format has version/signature/counter data here
-- 97,98,99,100,101,102 UID first three bytes
-- 103,104 bcc0
-- 105--- UID last four bytes
local uid = string.sub(dumpdata, 97, 97+5)..string.sub(dumpdata, 97+8, 97+8+7)
output = output or (uid .. ".eml")
local outfile = io.open(output, "w")
if outfile == nil then
return oops("Could not write to file ", output)
end
outfile:write(dumpdata:lower())
io.close(outfile)
print(("Wrote an emulator-dump to the file %s"):format(output))
-- Format some linebreaks
dumpdata = convert_to_emulform(dumpdata)
local outfile = io.open(output, "w")
if outfile == nil then
return oops("Could not write to file ", output)
end
outfile:write(dumpdata:lower())
io.close(outfile)
print(("Wrote an emulator-dump to the file %s"):format(output))
end
--[[
In the future, we may implement so that scripts are invoked directly
In the future, we may implement so that scripts are invoked directly
into a 'main' function, instead of being executed blindly. For future
compatibility, I have done so, but I invoke my main from here.
compatibility, I have done so, but I invoke my main from here.
--]]
main(args)

View file

@ -11,117 +11,117 @@ This script takes a dumpfile from 'hf mf dump' and converts it to a format that
by the emulator
Arguments:
-h This help
-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.
-h This help
-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.
]]
local DEBUG = false
-------------------------------
-- Some utilities
-- Some utilities
-------------------------------
---
---
-- A debug printout-function
local function dbg(args)
if not DEBUG then return end
if type(args) == 'table' then
local i = 1
while result[i] do
dbg(result[i])
i = i+1
end
else
print('###', args)
end
end
---
if not DEBUG then return end
if type(args) == 'table' then
local i = 1
while result[i] do
dbg(result[i])
i = i+1
end
else
print('###', args)
end
end
---
-- This is only meant to be used when errors occur
local function oops(err)
print('ERROR: ',err)
return nil,err
print('ERROR: ',err)
return nil,err
end
---
---
-- Usage help
function help()
print(desc)
print(author)
print("Example usage")
print(example)
print(desc)
print(author)
print("Example usage")
print(example)
end
local function convert_to_ascii(hexdata)
if string.len(hexdata) % 32 ~= 0 then
return oops(("Bad data, length should be a multiple of 32 (was %d)"):format(string.len(hexdata)))
end
if string.len(hexdata) % 32 ~= 0 then
return oops(("Bad data, length should be a multiple of 32 (was %d)"):format(string.len(hexdata)))
end
local js,i = "[";
for i = 1, string.len(hexdata),32 do
js = js .."'" ..string.sub(hexdata,i,i+31).."',\n"
end
js = js .. "]"
return js
local js,i = "[";
for i = 1, string.len(hexdata),32 do
js = js .."'" ..string.sub(hexdata,i,i+31).."',\n"
end
js = js .. "]"
return js
end
local function readdump(infile)
t = infile:read("*all")
len = string.len(t)
local len,hex = bin.unpack(("H%d"):format(len),t)
return hex
t = infile:read("*all")
len = string.len(t)
local len,hex = bin.unpack(("H%d"):format(len),t)
return hex
end
local function convert_to_emulform(hexdata)
if string.len(hexdata) % 32 ~= 0 then
return oops(("Bad data, length should be a multiple of 32 (was %d)"):format(string.len(hexdata)))
end
local ascii,i = "";
for i = 1, string.len(hexdata),32 do
ascii = ascii..string.sub(hexdata,i,i+31).."\n"
end
return string.sub(ascii, 1, -2)
if string.len(hexdata) % 32 ~= 0 then
return oops(("Bad data, length should be a multiple of 32 (was %d)"):format(string.len(hexdata)))
end
local ascii,i = "";
for i = 1, string.len(hexdata),32 do
ascii = ascii..string.sub(hexdata,i,i+31).."\n"
end
return string.sub(ascii, 1, -2)
end
local function main(args)
local input = "dumpdata.bin"
local output
local input = "dumpdata.bin"
local output
for o, a in getopt.getopt(args, 'i:o:h') do
if o == "h" then return help() end
if o == "i" then input = a end
if o == "o" then output = a end
end
-- Validate the parameters
local infile = io.open(input, "rb")
if infile == nil then
return oops("Could not read file ", input)
end
local dumpdata = readdump(infile)
-- The hex-data is now in ascii-format,
for o, a in getopt.getopt(args, 'i:o:h') do
if o == "h" then return help() end
if o == "i" then input = a end
if o == "o" then output = a end
end
-- Validate the parameters
-- But first, check the uid
local uid = string.sub(dumpdata,1,8)
output = output or (uid .. ".eml")
local infile = io.open(input, "rb")
if infile == nil then
return oops("Could not read file ", input)
end
local dumpdata = readdump(infile)
-- The hex-data is now in ascii-format,
-- Format some linebreaks
dumpdata = convert_to_emulform(dumpdata)
-- But first, check the uid
local uid = string.sub(dumpdata,1,8)
output = output or (uid .. ".eml")
local outfile = io.open(output, "w")
if outfile == nil then
return oops("Could not write to file ", output)
end
outfile:write(dumpdata:lower())
io.close(outfile)
print(("Wrote an emulator-dump to the file %s"):format(output))
-- Format some linebreaks
dumpdata = convert_to_emulform(dumpdata)
local outfile = io.open(output, "w")
if outfile == nil then
return oops("Could not write to file ", output)
end
outfile:write(dumpdata:lower())
io.close(outfile)
print(("Wrote an emulator-dump to the file %s"):format(output))
end
--[[
In the future, we may implement so that scripts are invoked directly
In the future, we may implement so that scripts are invoked directly
into a 'main' function, instead of being executed blindly. For future
compatibility, I have done so, but I invoke my main from here.
compatibility, I have done so, but I invoke my main from here.
--]]
main(args)

View file

@ -5,73 +5,73 @@ example = "script calculates many different checksums (CRC) over the provided he
author = "Iceman"
desc =
[[
This script calculates many checksums (CRC) over the provided hex input.
This script calculates many checksums (CRC) over the provided hex input.
Arguments:
-b data in hex
-w bitwidth of the CRC family of algorithm. <optional> defaults to all known CRC presets.
Examples :
script run e -b 010203040506070809
script run e -b 010203040506070809 -w 16
-b data in hex
-w bitwidth of the CRC family of algorithm. <optional> defaults to all known CRC presets.
Examples :
script run e -b 010203040506070809
script run e -b 010203040506070809 -w 16
]]
---
---
-- A debug printout-function
function dbg(args)
if DEBUG then
print("###", args)
end
end
---
if DEBUG then
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
function oops(err)
print("[!] ERROR: ",err)
return nil,err
print("[!] ERROR: ",err)
return nil,err
end
---
---
-- Usage help
function help()
print(desc)
print("Example usage")
print(example)
print(desc)
print("Example usage")
print(example)
end
---
---
-- The main entry point
function main(args)
local data
local width = 0
local data
local width = 0
-- Read the parameters
for o, a in getopt.getopt(args, 'hb:w:') do
if o == "h" then return help() end
if o == "b" then data = a end
if o == "w" then width = a end
end
-- Read the parameters
for o, a in getopt.getopt(args, 'hb:w:') do
if o == "h" then return help() end
if o == "b" then data = a end
if o == "w" then width = a end
end
data = data or '01020304'
width = width or 0
print( string.rep('-',60) )
print('Bit width of CRC | '..width)
print('Bytes | '..data)
print('')
print( ('%-20s| %-16s| %s'):format('Model','CRC', 'CRC reverse','bigEnd', 'bigEnd','little','little'))
print( string.rep('-',60) )
local lists, err = core.reveng_models(width)
if lists == nil then return oops(err) end
for _,i in pairs(lists) do
if string.len(i) > 1 then
local a1 = core.reveng_runmodel(i, data, false, '0')
local a2 = core.reveng_runmodel(i, data, true, '0')
local a3 = 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 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() ) )
end
end
data = data or '01020304'
width = width or 0
print( string.rep('-',60) )
print('Bit width of CRC | '..width)
print('Bytes | '..data)
print('')
print( ('%-20s| %-16s| %s'):format('Model','CRC', 'CRC reverse','bigEnd', 'bigEnd','little','little'))
print( string.rep('-',60) )
local lists, err = core.reveng_models(width)
if lists == nil then return oops(err) end
for _,i in pairs(lists) do
if string.len(i) > 1 then
local a1 = core.reveng_runmodel(i, data, false, '0')
local a2 = core.reveng_runmodel(i, data, true, '0')
local a3 = 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 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() ) )
end
end
end
main(args)

View file

@ -1,60 +1,60 @@
local getopt = require('getopt')
local bin = require('bin')
local dumplib = require('html_dumplib')
example =[[
1. script run emul2dump
2. script run emul2dump -i myfile.eml
3. script run emul2dump -i myfile.eml -o myfile.bin
]]
author = "Iceman"
usage = "script run emul2dump [-i <file>] [-o <file>]"
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"
Arguments:
-h This help
-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.
]]
---
-- This is only meant to be used when errors occur
function oops(err)
print("ERROR: ",err)
end
---
-- Usage help
function help()
print(desc)
print("Example usage")
print(example)
end
--
-- Exit message
function ExitMsg(msg)
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
end
local function main(args)
local input = "dumpdata.eml"
local output = os.date("%Y-%m-%d_%H%M%S.bin");
-- Arguments for the script
for o, a in getopt.getopt(args, 'hi:o:') do
if o == "h" then return help() end
if o == "i" then input = a end
if o == "o" then output = a end
end
local filename, err = dumplib.convert_eml_to_bin(input,output)
if err then return oops(err) end
ExitMsg(("Wrote a BIN dump to the file %s"):format(filename))
end
local getopt = require('getopt')
local bin = require('bin')
local dumplib = require('html_dumplib')
example =[[
1. script run emul2dump
2. script run emul2dump -i myfile.eml
3. script run emul2dump -i myfile.eml -o myfile.bin
]]
author = "Iceman"
usage = "script run emul2dump [-i <file>] [-o <file>]"
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"
Arguments:
-h This help
-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.
]]
---
-- This is only meant to be used when errors occur
function oops(err)
print("ERROR: ",err)
end
---
-- Usage help
function help()
print(desc)
print("Example usage")
print(example)
end
--
-- Exit message
function ExitMsg(msg)
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
end
local function main(args)
local input = "dumpdata.eml"
local output = os.date("%Y-%m-%d_%H%M%S.bin");
-- Arguments for the script
for o, a in getopt.getopt(args, 'hi:o:') do
if o == "h" then return help() end
if o == "i" then input = a end
if o == "o" then output = a end
end
local filename, err = dumplib.convert_eml_to_bin(input,output)
if err then return oops(err) end
ExitMsg(("Wrote a BIN dump to the file %s"):format(filename))
end
main(args)

View file

@ -8,60 +8,60 @@ example = "script run emul2html -o dumpdata.eml "
author = "Martin Holst Swende"
usage = "script run htmldump [-i <file>] [-o <file>]"
desc =[[
This script takes a dumpfile on EML (ASCII) format and produces a html based dump, which is a
bit more easily analyzed.
This script takes a dumpfile on EML (ASCII) format and produces a html based dump, which is a
bit more easily analyzed.
Arguments:
-h This help
-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.
-h This help
-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.
]]
-------------------------------
-- Some utilities
-- Some utilities
-------------------------------
---
---
-- A debug printout-function
function dbg(args)
if DEBUG then
print("###", args)
end
end
---
if DEBUG then
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
function oops(err)
print("ERROR: ",err)
print("ERROR: ",err)
end
---
---
-- Usage help
function help()
print(desc)
print("Example usage")
print(example)
print(desc)
print("Example usage")
print(example)
end
local function main(args)
local input = "dumpdata.eml"
local output = os.date("%Y-%m-%d_%H%M%S.html");
for o, a in getopt.getopt(args, 'i:o:h') do
if o == "h" then return help() end
if o == "i" then input = a end
if o == "o" then output = a end
end
local filename, err = dumplib.convert_eml_to_html(input,output)
if err then return oops(err) end
local input = "dumpdata.eml"
local output = os.date("%Y-%m-%d_%H%M%S.html");
for o, a in getopt.getopt(args, 'i:o:h') do
if o == "h" then return help() end
if o == "i" then input = a end
if o == "o" then output = a end
end
local filename, err = dumplib.convert_eml_to_html(input,output)
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
--[[
In the future, we may implement so that scripts are invoked directly
In the future, we may implement so that scripts are invoked directly
into a 'main' function, instead of being executed blindly. For future
compatibility, I have done so, but I invoke my main from here.
compatibility, I have done so, but I invoke my main from here.
--]]
main(args)

View file

@ -1,216 +1,216 @@
local cmds = require('commands')
local getopt = require('getopt')
local bin = require('bin')
local lib14a = require('read14a')
local utils = require('utils')
example = [[
-- generate commands
1. script run formatMifare
-- generate command, replacing key with new key.
2. script run formatMifare -k aabbccddeeff -n 112233445566 -a FF0780
-- generate commands and excute them against card.
3. script run formatMifare -x
]]
copyright = ''
version = ''
author = 'Iceman'
usage = [[
script run formatMifare -k <key> -n <key> -a <access> -x
]]
desc = [[
This script will generate 'hf mf wrbl' commands for each block to format a Mifare card.
Alla datablocks gets 0x00
As default the script sets the keys A/B to 0xFFFFFFFFFFFF
and the access bytes will become 0x78,0x77,0x88
The GDB will become 0x00
The script will skip the manufactoring block 0.
Arguments:
-h - this help
-k <key> - the current six byte key with write access
-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
-x - execute the commands aswell.
]]
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
local DEBUG = true -- the debug flag
local CmdString = 'hf mf wrbl %d B %s %s'
local numBlocks = 64
local numSectors = 16
---
-- A debug printout-function
function dbg(args)
if not DEBUG then
return
end
if type(args) == "table" then
local i = 1
while result[i] do
dbg(result[i])
i = i+1
end
else
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
function oops(err)
print("ERROR: ",err)
end
---
-- Usage help
function help()
print(copyright)
print(author)
print(version)
print(desc)
print("Example usage")
print(example)
end
--
-- Exit message
function ExitMsg(msg)
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
end
--
-- Read information from a card
function GetCardInfo()
result, err = lib14a.read(false, true)
if not result then
print(err)
return
end
print(("Found: %s"):format(result.name))
core.clearCommandBuffer()
if 0x18 == result.sak then -- NXP MIFARE Classic 4k | Plus 4k
-- 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.
numSectors = 40
elseif 0x08 == result.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k
-- 1K offers 1024 bytes of data storage, split into 16 sector
numSectors = 16
elseif 0x09 == result.sak then -- NXP MIFARE Mini 0.3k
-- MIFARE Classic mini offers 320 bytes split into five sectors.
numSectors = 5
elseif 0x10 == result.sak then -- NXP MIFARE Plus 2k
numSectors = 32
elseif 0x01 == result.sak then -- NXP MIFARE TNP3xxx 1K
numSectors = 16
else
print("I don't know how many sectors there are on this type of card, defaulting to 16")
end
--[[
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
8 sectors consist of 16 data blocks.
--]]
-- Defaults to 16 * 4 = 64 - 1 = 63
numBlocks = numSectors * 4 - 1
if numSectors > 32 then
numBlocks = 32*4+ (numSectors-32)*16 -1
end
end
local function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
print()
local OldKey, NewKey, Accessbytes
local x = false
-- Arguments for the script
for o, a in getopt.getopt(args, 'hk:n:a:x') do
if o == "h" then return help() end
if o == "k" then OldKey = a end
if o == "n" then NewKey = a end
if o == "a" then Accessbytes = a end
if o == "x" then x = true end
end
-- validate input args.
OldKey = OldKey or 'FFFFFFFFFFFF'
if #(OldKey) ~= 12 then
return oops( string.format('Wrong length of write key (was %d) expected 12', #OldKey))
end
NewKey = NewKey or 'FFFFFFFFFFFF'
if #(NewKey) ~= 12 then
return oops( string.format('Wrong length of new key (was %d) expected 12', #NewKey))
end
--Accessbytes = Accessbytes or '787788'
Accessbytes = Accessbytes or 'FF0780'
if #(Accessbytes) ~= 6 then
return oops( string.format('Wrong length of accessbytes (was %d) expected 12', #Accessbytes))
end
GetCardInfo()
-- Show info
print( string.format('Estimating number of blocks: %d', numBlocks))
print( string.format('Old key: %s', OldKey))
print( string.format('New key: %s', NewKey))
print( string.format('New Access: %s', Accessbytes))
print( string.rep('--',20) )
-- Set new block data
local EMPTY_BL = string.rep('00',16)
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 emptyblock: %s',EMPTY_BL))
dbg('')
if x then
print('[Warning] you have used the EXECUTE parameter, which means this will run these commands against card.')
end
-- Ask
local dialogResult = utils.confirm("Do you want to erase this card")
if dialogResult == false then
return ExitMsg('Quiting it is then. Your wish is my command...')
end
print( string.rep('--',20) )
-- main loop
for block=0,numBlocks,1 do
local reminder = (block+1) % 4
local cmd
if reminder == 0 then
cmd = CmdString:format(block, OldKey , EMPTY_SECTORTRAIL)
else
cmd = CmdString:format(block, OldKey , EMPTY_BL)
end
if block ~= 0 then
print(cmd)
if x then core.console(cmd) end
end
if core.ukbhit() then
print("aborted by user")
break
end
end
end
local cmds = require('commands')
local getopt = require('getopt')
local bin = require('bin')
local lib14a = require('read14a')
local utils = require('utils')
example = [[
-- generate commands
1. script run formatMifare
-- generate command, replacing key with new key.
2. script run formatMifare -k aabbccddeeff -n 112233445566 -a FF0780
-- generate commands and excute them against card.
3. script run formatMifare -x
]]
copyright = ''
version = ''
author = 'Iceman'
usage = [[
script run formatMifare -k <key> -n <key> -a <access> -x
]]
desc = [[
This script will generate 'hf mf wrbl' commands for each block to format a Mifare card.
Alla datablocks gets 0x00
As default the script sets the keys A/B to 0xFFFFFFFFFFFF
and the access bytes will become 0x78,0x77,0x88
The GDB will become 0x00
The script will skip the manufactoring block 0.
Arguments:
-h - this help
-k <key> - the current six byte key with write access
-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
-x - execute the commands aswell.
]]
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
local DEBUG = true -- the debug flag
local CmdString = 'hf mf wrbl %d B %s %s'
local numBlocks = 64
local numSectors = 16
---
-- A debug printout-function
function dbg(args)
if not DEBUG then
return
end
if type(args) == "table" then
local i = 1
while result[i] do
dbg(result[i])
i = i+1
end
else
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
function oops(err)
print("ERROR: ",err)
end
---
-- Usage help
function help()
print(copyright)
print(author)
print(version)
print(desc)
print("Example usage")
print(example)
end
--
-- Exit message
function ExitMsg(msg)
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
end
--
-- Read information from a card
function GetCardInfo()
result, err = lib14a.read(false, true)
if not result then
print(err)
return
end
print(("Found: %s"):format(result.name))
core.clearCommandBuffer()
if 0x18 == result.sak then -- NXP MIFARE Classic 4k | Plus 4k
-- 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.
numSectors = 40
elseif 0x08 == result.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k
-- 1K offers 1024 bytes of data storage, split into 16 sector
numSectors = 16
elseif 0x09 == result.sak then -- NXP MIFARE Mini 0.3k
-- MIFARE Classic mini offers 320 bytes split into five sectors.
numSectors = 5
elseif 0x10 == result.sak then -- NXP MIFARE Plus 2k
numSectors = 32
elseif 0x01 == result.sak then -- NXP MIFARE TNP3xxx 1K
numSectors = 16
else
print("I don't know how many sectors there are on this type of card, defaulting to 16")
end
--[[
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
8 sectors consist of 16 data blocks.
--]]
-- Defaults to 16 * 4 = 64 - 1 = 63
numBlocks = numSectors * 4 - 1
if numSectors > 32 then
numBlocks = 32*4+ (numSectors-32)*16 -1
end
end
local function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
print()
local OldKey, NewKey, Accessbytes
local x = false
-- Arguments for the script
for o, a in getopt.getopt(args, 'hk:n:a:x') do
if o == "h" then return help() end
if o == "k" then OldKey = a end
if o == "n" then NewKey = a end
if o == "a" then Accessbytes = a end
if o == "x" then x = true end
end
-- validate input args.
OldKey = OldKey or 'FFFFFFFFFFFF'
if #(OldKey) ~= 12 then
return oops( string.format('Wrong length of write key (was %d) expected 12', #OldKey))
end
NewKey = NewKey or 'FFFFFFFFFFFF'
if #(NewKey) ~= 12 then
return oops( string.format('Wrong length of new key (was %d) expected 12', #NewKey))
end
--Accessbytes = Accessbytes or '787788'
Accessbytes = Accessbytes or 'FF0780'
if #(Accessbytes) ~= 6 then
return oops( string.format('Wrong length of accessbytes (was %d) expected 12', #Accessbytes))
end
GetCardInfo()
-- Show info
print( string.format('Estimating number of blocks: %d', numBlocks))
print( string.format('Old key: %s', OldKey))
print( string.format('New key: %s', NewKey))
print( string.format('New Access: %s', Accessbytes))
print( string.rep('--',20) )
-- Set new block data
local EMPTY_BL = string.rep('00',16)
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 emptyblock: %s',EMPTY_BL))
dbg('')
if x then
print('[Warning] you have used the EXECUTE parameter, which means this will run these commands against card.')
end
-- Ask
local dialogResult = utils.confirm("Do you want to erase this card")
if dialogResult == false then
return ExitMsg('Quiting it is then. Your wish is my command...')
end
print( string.rep('--',20) )
-- main loop
for block=0,numBlocks,1 do
local reminder = (block+1) % 4
local cmd
if reminder == 0 then
cmd = CmdString:format(block, OldKey , EMPTY_SECTORTRAIL)
else
cmd = CmdString:format(block, OldKey , EMPTY_BL)
end
if block ~= 0 then
print(cmd)
if x then core.console(cmd) end
end
if core.ukbhit() then
print("aborted by user")
break
end
end
end
main(args)

View file

@ -1,18 +1,18 @@
local reader = require('hf_reader')
local function main(args)
print("WORK IN PROGRESS - not expected to be functional yet")
info, err = reader.waitForTag()
print("WORK IN PROGRESS - not expected to be functional yet")
info, err = reader.waitForTag()
if err then
print(err)
return
end
local k,v
print("Tag info")
for k,v in pairs(info) do
print(string.format(" %s : %s", tostring(k), tostring(v)))
end
return
if err then
print(err)
return
end
local k,v
print("Tag info")
for k,v in pairs(info) do
print(string.format(" %s : %s", tostring(k), tostring(v)))
end
return
end
main(args)

View file

@ -8,58 +8,58 @@ example = "script run htmldump -o mifarecard_foo.html"
author = "Martin Holst Swende"
usage = "script run htmldump [-i <file>] [-o <file>]"
desc =[[
This script takes a dumpfile and produces a html based dump, which is a
bit more easily analyzed.
This script takes a dumpfile and produces a html based dump, which is a
bit more easily analyzed.
Arguments:
-h This help
-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.
-h This help
-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.
]]
-------------------------------
-- Some utilities
-- Some utilities
-------------------------------
---
---
-- A debug printout-function
function dbg(args)
if DEBUG then
print("###", args)
end
end
---
if DEBUG then
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
function oops(err)
print("ERROR: ",err)
print("ERROR: ",err)
end
---
---
-- Usage help
function help()
print(desc)
print("Example usage")
print(example)
print(desc)
print("Example usage")
print(example)
end
local function main(args)
local input = "dumpdata.bin"
local output = os.date("%Y-%m-%d_%H%M%S.html");
for o, a in getopt.getopt(args, 'i:o:h') do
if o == "h" then return help() end
if o == "i" then input = a end
if o == "o" then output = a end
end
local filename, err = dumplib.convert_bin_to_html(input,output,16)
if err then return oops(err) end
local input = "dumpdata.bin"
local output = os.date("%Y-%m-%d_%H%M%S.html");
for o, a in getopt.getopt(args, 'i:o:h') do
if o == "h" then return help() end
if o == "i" then input = a end
if o == "o" then output = a end
end
local filename, err = dumplib.convert_bin_to_html(input,output,16)
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
--[[
In the future, we may implement so that scripts are invoked directly
In the future, we may implement so that scripts are invoked directly
into a 'main' function, instead of being executed blindly. For future
compatibility, I have done so, but I invoke my main from here.
compatibility, I have done so, but I invoke my main from here.
--]]
main(args)

View file

@ -7,112 +7,112 @@ copyright = 'Copyright (c) 2018 IceSQL AB. All rights reserved.'
author = 'Christian Herrmann'
version = 'v1.0.4'
desc = [[
This script tries to set UID on a IS15693 SLIX magic card
This script tries to set UID on a IS15693 SLIX magic card
Remember the UID ->MUST<- start with 0xE0
]]
example = [[
-- ISO15693 slix magic tag
-- ISO15693 slix magic tag
script run iso15_magic -u E004013344556677
script run iso15_magic -u E004013344556677 -a
script run iso15_magic -u E004013344556677
script run iso15_magic -u E004013344556677 -a
]]
usage = [[
script run iso15_magic -h -u <uid>
Arguments:
-h : this help
-u <UID> : UID (16 hexsymbols)
-a : use offical pm3 repo ISO15 commands instead of iceman fork.
-h : this help
-u <UID> : UID (16 hexsymbols)
-a : use offical pm3 repo ISO15 commands instead of iceman fork.
]]
local DEBUG = true
---
---
-- A debug printout-function
local function dbg(args)
if not DEBUG then return end
if type(args) == "table" then
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print("###", args)
end
end
---
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
local function oops(err)
print("ERROR: ",err)
return nil, err
print("ERROR: ",err)
return nil, err
end
---
---
-- Usage help
local function help()
print(copyright)
print(author)
print(version)
print(desc)
print('Example usage')
print(example)
print(copyright)
print(author)
print(version)
print(desc)
print('Example usage')
print(example)
end
--
--- Set UID on magic command enabled on a ICEMAN based REPO
local function magicUID_iceman(b0, b1)
print('Using backdoor Magic tag function')
core.console("hf 15 raw -2 -c 02213E00000000")
core.console("hf 15 raw -2 -c 02213F69960000")
core.console("hf 15 raw -2 -c 022138"..b1)
core.console("hf 15 raw -2 -c 022139"..b0)
print('Using backdoor Magic tag function')
core.console("hf 15 raw -2 -c 02213E00000000")
core.console("hf 15 raw -2 -c 02213F69960000")
core.console("hf 15 raw -2 -c 022138"..b1)
core.console("hf 15 raw -2 -c 022139"..b0)
end
--
--- Set UID on magic command enabled, OFFICAL REPO
local function magicUID_offical(b0, b1)
print('Using backdoor Magic tag function OFFICAL REPO')
core.console("hf 15 cmd raw -c 02213E00000000")
core.console("hf 15 cmd raw -c 02213F69960000")
core.console("hf 15 cmd raw -c 022138"..b1)
core.console("hf 15 cmd raw -c 022139"..b0)
print('Using backdoor Magic tag function OFFICAL REPO')
core.console("hf 15 cmd raw -c 02213E00000000")
core.console("hf 15 cmd raw -c 02213F69960000")
core.console("hf 15 cmd raw -c 022138"..b1)
core.console("hf 15 cmd raw -c 022139"..b0)
end
---
---
-- The main entry point
function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
print()
print( string.rep('--',20) )
print( string.rep('--',20) )
print()
local uid = 'E004013344556677'
local use_iceman = true
-- Read the parameters
for o, a in getopt.getopt(args, 'hu:a') do
if o == "h" then return help() end
if o == "u" then uid = a end
if o == "a" then use_iceman = false end
end
-- uid string checks
if uid == nil 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
local uid = 'E004013344556677'
local use_iceman = true
local bytes = utils.ConvertHexToBytes(uid)
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])
print('new UID | '..uid)
core.clearCommandBuffer()
if use_iceman then
magicUID_iceman(block0, block1)
else
magicUID_offical(block0, block1)
end
-- Read the parameters
for o, a in getopt.getopt(args, 'hu:a') do
if o == "h" then return help() end
if o == "u" then uid = a end
if o == "a" then use_iceman = false end
end
-- uid string checks
if uid == nil 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
local bytes = utils.ConvertHexToBytes(uid)
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])
print('new UID | '..uid)
core.clearCommandBuffer()
if use_iceman then
magicUID_iceman(block0, block1)
else
magicUID_offical(block0, block1)
end
end
main(args)

File diff suppressed because it is too large Load diff

View file

@ -4,51 +4,51 @@ author = "Mosci"
desc =
[[
This is a script which writes value 0x01 to bytes from position 0x07 until 0xFF on a Legic Prime Tag (MIM256 or MIM1024)
(created with 'hf legic save my_dump.hex')
optional arguments :
-h - Help text
(created with 'hf legic save my_dump.hex')
Examples :
script run legic_buffer2card
optional arguments :
-h - Help text
Examples :
script run legic_buffer2card
]]
local utils = require('utils')
local getopt = require('getopt')
---
---
-- This is only meant to be used when errors occur
function oops(err)
print("ERROR: ",err)
return nil, err
print("ERROR: ",err)
return nil, err
end
---
---
-- Usage help
function help()
print(desc)
print("Example usage")
print(example)
print(desc)
print("Example usage")
print(example)
end
--
-- simple loop-write from 0x07 to 0xff
function main()
-- parse arguments for the script
for o, a in getopt.getopt(args, 'h') do
if o == "h" then return help() end
end
-- parse arguments for the script
for o, a in getopt.getopt(args, 'h') do
if o == "h" then return help() end
end
local cmd = ''
local i
for i = 7, 255 do
cmd = ('hf legic write 0x%02x 0x01'):format(i)
print(cmd)
core.clearCommandBuffer()
core.console(cmd)
-- got a 'cmd-buffer overflow' on my mac - so just wait a little
-- works without that pause on my linux-box
utils.Sleep(0.1)
end
local cmd = ''
local i
for i = 7, 255 do
cmd = ('hf legic write 0x%02x 0x01'):format(i)
print(cmd)
core.clearCommandBuffer()
core.console(cmd)
-- got a 'cmd-buffer overflow' on my mac - so just wait a little
-- works without that pause on my linux-box
utils.Sleep(0.1)
end
end
main()

View file

@ -12,59 +12,59 @@ Perform bulk enrollment of 26 bit H10301 style RFID Tags
For more info, check the comments in the code
]]
example = [[
--
script run lf_bulk.lua -f 1 -b 1000 -c 10
--
script run lf_bulk.lua -f 1 -b 1000 -c 10
]]
usage = [[
script run lf_bulk.lua -f facility -b base_id_num -c count
Arguments:
-h : this help
-f : facility id
-b : starting card id
-c : count, number of cards to make
-h : this help
-f : facility id
-b : starting card id
-c : count, number of cards to make
]]
local DEBUG = true
--local bxor = bit32.bxor
local bor = bit32.bor
local lshift = bit32.lshift
---
---
-- A debug printout-function
local function dbg(args)
if not DEBUG then return end
if type(args) == "table" then
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print("###", args)
end
end
---
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
local function oops(err)
print("ERROR: ",err)
return nil,err
print("ERROR: ",err)
return nil,err
end
---
---
-- Usage help
local function help()
print(copyright)
print(author)
print(version)
print(desc)
print('Example usage')
print(example)
print(copyright)
print(author)
print(version)
print(desc)
print('Example usage')
print(example)
end
---
-- Exit message
local function exitMsg(msg)
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
end
--[[Implement a function to simply visualize the bitstream in a text format
--This is especially helpful for troubleshooting bitwise math issues]]--
@ -81,22 +81,22 @@ end
--[[
Likely, I'm an idiot, but I couldn't find any parity functions in Lua
This can also be done with a combination of bitwise operations (in fact,
This can also be done with a combination of bitwise operations (in fact,
is the canonically "correct" way to do it, but my brain doesn't just
default to this and so counting some ones is good enough for me
]]--
local function evenparity(s)
local _, count = string.gsub(s, "1", "")
local p = count % 2
if (p == 0) then
return false
else
return true
end
local _, count = string.gsub(s, "1", "")
local p = count % 2
if (p == 0) then
return false
else
return true
end
end
local function isempty(s)
return s == nil or s == ''
return s == nil or s == ''
end
--[[
@ -105,89 +105,89 @@ end
hex. This should be easy enough to extend to non 26bit formats
]]--
local function cardHex(i, f)
fac = lshift(f, 16)
id = bor(i, fac)
stream = toBits(id, 24)
fac = lshift(f, 16)
id = bor(i, fac)
stream = toBits(id, 24)
--As the function defaults to even parity and returns a boolean,
--perform a 'not' function to get odd parity
high = evenparity(string.sub(stream,1,12)) and 1 or 0
low = not evenparity(string.sub(stream,13)) and 1 or 0
bits = bor( lshift(id, 1), low)
bits = bor( bits, lshift(high, 25))
--As the function defaults to even parity and returns a boolean,
--perform a 'not' function to get odd parity
high = evenparity(string.sub(stream,1,12)) and 1 or 0
low = not evenparity(string.sub(stream,13)) and 1 or 0
bits = bor( lshift(id, 1), low)
bits = bor( bits, lshift(high, 25))
--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
--to create a higher order and lower order component which we will
--then assemble in the return. The math above defines the proper
--encoding as per HID/Weigand/etc. These bit flips are due to the
--format length check on bit 38 (cmdlfhid.c:64) and
--bit 31 (cmdlfhid.c:66).
preamble = bor(0, lshift(1, 5))
bits = bor(bits, lshift(1, 26))
--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
--to create a higher order and lower order component which we will
--then assemble in the return. The math above defines the proper
--encoding as per HID/Weigand/etc. These bit flips are due to the
--format length check on bit 38 (cmdlfhid.c:64) and
--bit 31 (cmdlfhid.c:66).
preamble = bor(0, lshift(1, 5))
bits = bor(bits, lshift(1, 26))
return ("%04x%08x"):format(preamble, bits)
return ("%04x%08x"):format(preamble, bits)
end
---
-- main
local function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
print()
if #args == 0 then return help() end
--I really wish a better getopt function would be brought in supporting
--long arguments, but it seems this library was chosen for BSD style
--compatibility
for o, a in getopt.getopt(args, 'f:b:c:h') do
if o == 'h' then return help() end
if o == 'f' then
if isempty(a) then
print("You did not supply a facility code, using 0")
facility = 0
else
facility = a
end
end
if o == 'b' then
if isempty(a) then return oops("You must supply the flag -b (base id)") end
baseid = a
end
if o == 'c' then
if isempty(a) then return oops("You must supply the flag -c (count)") end
count = a
end
end
print( string.rep('--',20) )
print( string.rep('--',20) )
print()
--Due to my earlier complaints about how this specific getopt library
--works, specifying ":" does not enforce supplying a value, thus we
--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(count) then return oops("You must supply the flag -c (count)") end
if #args == 0 then return help() end
--If the facility ID is non specified, ensure we code it as zero
if isempty(facility) then
print("Using 0 for the facility code as -f was not supplied")
facility = 0
end
--I really wish a better getopt function would be brought in supporting
--long arguments, but it seems this library was chosen for BSD style
--compatibility
for o, a in getopt.getopt(args, 'f:b:c:h') do
if o == 'h' then return help() end
if o == 'f' then
if isempty(a) then
print("You did not supply a facility code, using 0")
facility = 0
else
facility = a
end
end
if o == 'b' then
if isempty(a) then return oops("You must supply the flag -b (base id)") end
baseid = a
end
if o == 'c' then
if isempty(a) then return oops("You must supply the flag -c (count)") end
count = a
end
end
--The next baseid + count function presents a logic/UX conflict
--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
--other values encode the expected amount.
if tonumber(count) > 0 then count = count - 1 end
--Due to my earlier complaints about how this specific getopt library
--works, specifying ":" does not enforce supplying a value, thus we
--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(count) then return oops("You must supply the flag -c (count)") end
endid = baseid + count
--If the facility ID is non specified, ensure we code it as zero
if isempty(facility) then
print("Using 0 for the facility code as -f was not supplied")
facility = 0
end
for cardnum = baseid, endid do
local card = cardHex(cardnum, facility)
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.
io.read()
core.console( ('lf hid clone %s'):format(card) )
end
--The next baseid + count function presents a logic/UX conflict
--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
--other values encode the expected amount.
if tonumber(count) > 0 then count = count - 1 end
endid = baseid + count
for cardnum = baseid, endid do
local card = cardHex(cardnum, facility)
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.
io.read()
core.console( ('lf hid clone %s'):format(card) )
end
end
main(args)

View file

@ -1,12 +1,12 @@
--[[
This is an example of Lua-scripting within proxmark3. This is a lua-side
implementation of hf mf chk
This is an example of Lua-scripting within proxmark3. This is a lua-side
implementation of hf mf chk
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
the license.
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
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
local cmds = require('commands')
@ -19,7 +19,7 @@ local getopt = require('getopt')
local utils = require('utils')
example =[[
script run mfkeys
script run mfkeys
]]
author = "Holiman"
usage = "script run mfkeys"
@ -29,247 +29,247 @@ If you want to add more, just put them inside /lualibs/mf_default_keys.lua\n"):f
[[
Arguments:
-h : this help
-p : print keys
-h : this help
-p : print keys
]]
local TIMEOUT = 10000 -- 10 seconds
---
---
-- This is only meant to be used when errors occur
local function oops(err)
print('ERROR: ',err)
return nil,err
print('ERROR: ',err)
return nil,err
end
---
---
-- Usage help
local function help()
print(desc)
print("Example usage")
print(example)
print(desc)
print("Example usage")
print(example)
end
--
-- waits for answer from pm3 device
local function checkCommand(command)
core.clearCommandBuffer()
local usb = command:getBytes()
core.SendCommand(usb)
local result = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT)
if result then
local count, cmd, arg0 = bin.unpack('LL',result)
if(arg0==1) then
local count, arg1, arg2, data = bin.unpack('LLH511',result,count)
key = data:sub(1,12)
return key
else
return nil
end
else
print("Timeout while waiting for response. Increase TIMEOUT in mfkeys.lua to wait longer")
return nil, "Timeout while waiting for device to respond"
end
core.clearCommandBuffer()
local usb = command:getBytes()
core.SendCommand(usb)
local result = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT)
if result then
local count, cmd, arg0 = bin.unpack('LL',result)
if(arg0==1) then
local count, arg1, arg2, data = bin.unpack('LLH511',result,count)
key = data:sub(1,12)
return key
else
return nil
end
else
print("Timeout while waiting for response. Increase TIMEOUT in mfkeys.lua to wait longer")
return nil, "Timeout while waiting for device to respond"
end
end
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.
-- If there's more, we need to split it up
local arg1 = bit32.bor(bit32.lshift(keytype, 8), blockno)
-- 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
local arg1 = bit32.bor(bit32.lshift(keytype, 8), blockno)
local start, remaining = 1, #testkeys
local chunksize = remaining
if remaining > 85 then chunksize = 85 end
local n = chunksize
while remaining > 0 do
--print('start', start, 'chunksize', chunksize, 'testkeys kvar', remaining, 'N-index=', n)
local start, remaining = 1, #testkeys
local chunksize = remaining
if remaining > 85 then chunksize = 85 end
local n = chunksize
local d1 = table.concat(testkeys, "", start, n)
print(("Testing block %d, keytype %d, with %d keys"):format(blockno, keytype, chunksize))
local command = Command:new{cmd = cmds.CMD_MIFARE_CHKKEYS,
arg1 = arg1,
arg2 = 0,
arg3 = chunksize,
data = d1}
local status = checkCommand(command)
if status then return status, blockno end
start = start + chunksize
remaining = remaining - chunksize
if remaining < 85 then chunksize = remaining end
n = n + chunksize
end
return nil
while remaining > 0 do
--print('start', start, 'chunksize', chunksize, 'testkeys kvar', remaining, 'N-index=', n)
local d1 = table.concat(testkeys, "", start, n)
print(("Testing block %d, keytype %d, with %d keys"):format(blockno, keytype, chunksize))
local command = Command:new{cmd = cmds.CMD_MIFARE_CHKKEYS,
arg1 = arg1,
arg2 = 0,
arg3 = chunksize,
data = d1}
local status = checkCommand(command)
if status then return status, blockno end
start = start + chunksize
remaining = remaining - chunksize
if remaining < 85 then chunksize = remaining end
n = n + chunksize
end
return nil
end
-- A function to display the results
local function display_results(keys)
local sector, keyA, keyB, succA, succB
print('')
print('|---|----------------|---|----------------|---|')
print('|sec|key A |res|key B |res|')
print('|---|----------------|---|----------------|---|')
local sector, keyA, keyB, succA, succB
print('')
print('|---|----------------|---|----------------|---|')
print('|sec|key A |res|key B |res|')
print('|---|----------------|---|----------------|---|')
for sector = 0, #keys do
succA, succB, keyA, keyB = unpack(keys[sector])
print(('|%03d| %s | %s | %s | %s |'):format(sector, keyA, succA, keyB, succB))
end
print('|---|----------------|---|----------------|---|')
for sector = 0, #keys do
succA, succB, keyA, keyB = unpack(keys[sector])
print(('|%03d| %s | %s | %s | %s |'):format(sector, keyA, succA, keyB, succB))
end
print('|---|----------------|---|----------------|---|')
end
-- A little helper to place an item first in the list
local function placeFirst(akey, list)
akey = akey:lower()
if list[1] == akey then
-- Already at pole position
return list
end
local result = {akey}
--print(("Putting '%s' first"):format(akey))
for i,v in ipairs(list) do
if v ~= akey then
result[#result+1] = v
end
end
return result
akey = akey:lower()
if list[1] == akey then
-- Already at pole position
return list
end
local result = {akey}
--print(("Putting '%s' first"):format(akey))
for i,v in ipairs(list) do
if v ~= akey then
result[#result+1] = v
end
end
return result
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
8 sectors consist of 16 data blocks.
8 sectors consist of 16 data blocks.
--]]
local function get_blockno(s)
local b, sector
local b, sector
if type(s) == 'string' then
sector = tonumber(s)
else
sector = s
end
if type(s) == 'string' then
sector = tonumber(s)
else
sector = s
end
if sector < 32 then
b = sector * 4
else
b = 32 * 4 + (sector - 32) * 16
if sector < 32 then
b = sector * 4
else
b = 32 * 4 + (sector - 32) * 16
end
return ('%02x'):format(b)
return ('%02x'):format(b)
end
--
-- dumps all keys to file
local function dumptofile(keys)
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 file = io.open(destination, 'wb')
if file == nil then
print('Could not write to file ', destination)
return
end
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 file = io.open(destination, 'wb')
if file == nil then
print('Could not write to file ', destination)
return
end
local key_a = ''
local key_b = ''
local key_a = ''
local key_b = ''
--for sector,_ in pairs(keys) do
for sector = 0, #keys do
local succA, succB, keyA, keyB = unpack(keys[sector])
key_a = key_a .. bin.pack('H', keyA);
key_b = key_b .. bin.pack('H', keyB);
end
file:write(key_a)
file:write(key_b)
file:close()
end
--for sector,_ in pairs(keys) do
for sector = 0, #keys do
local succA, succB, keyA, keyB = unpack(keys[sector])
key_a = key_a .. bin.pack('H', keyA);
key_b = key_b .. bin.pack('H', keyB);
end
file:write(key_a)
file:write(key_b)
file:close()
end
end
local function printkeys()
for i=1, #keylist do
print(i, keylist[i])
end
print ('Number of keys: '..#keylist)
local function printkeys()
for i=1, #keylist do
print(i, keylist[i])
end
print ('Number of keys: '..#keylist)
end
local function perform_check(numsectors)
local keyType = 0 -- A=0, B=1
local keyType = 0 -- A=0, B=1
-- empty list of found keys
local keys = {}
for i = 0, numsectors-1 do
keys[i] = {0,0,'',''}
end
-- empty list of found keys
local keys = {}
for i = 0, numsectors-1 do
keys[i] = {0,0,'',''}
end
for sector = 0, #keys do
-- Check if user aborted
if core.ukbhit() then
print('Aborted by user')
break
end
for sector = 0, #keys do
-- Check if user aborted
if core.ukbhit() then
print('Aborted by user')
break
end
local targetblock = tonumber(get_blockno(sector), 16)
local succA, succB, keyA, keyB = unpack(keys[sector])
local keyA = checkBlock(targetblock, keylist, 0)
if keyA then succA = 1; keylist = placeFirst(keyA, keylist) end
keyA = keyA or '------------'
local targetblock = tonumber(get_blockno(sector), 16)
local keyB = checkBlock(targetblock, keylist, 1)
if keyB then succB = 1; keylist = placeFirst(keyB, keylist) end
keyB = keyB or '------------'
local succA, succB, keyA, keyB = unpack(keys[sector])
keys[sector] = {succA, succB, keyA, keyB}
end
display_results(keys)
local keyA = checkBlock(targetblock, keylist, 0)
if keyA then succA = 1; keylist = placeFirst(keyA, keylist) end
keyA = keyA or '------------'
-- save to dumpkeys.bin
dumptofile(keys)
local keyB = checkBlock(targetblock, keylist, 1)
if keyB then succB = 1; keylist = placeFirst(keyB, keylist) end
keyB = keyB or '------------'
keys[sector] = {succA, succB, keyA, keyB}
end
display_results(keys)
-- save to dumpkeys.bin
dumptofile(keys)
end
--
-- shows tag information
local function taginfo(tag)
local sectors = 16
-- Show tag info
print((' Found tag %s'):format(tag.name))
local sectors = 16
-- Show tag info
print((' Found tag %s'):format(tag.name))
if 0x18 == tag.sak then --NXP MIFARE Classic 4k | Plus 4k
-- 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.
sectors = 40
elseif 0x08 == tag.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k
-- 1K offers 1024 bytes of data storage, split into 16 sector
sectors = 16
elseif 0x09 == tag.sak then -- NXP MIFARE Mini 0.3k
-- MIFARE Classic mini offers 320 bytes split into five sectors.
sectors = 5
elseif 0x10 == tag.sak then-- "NXP MIFARE Plus 2k"
sectors = 32
else
print("I don't know how many sectors there are on this type of card, defaulting to 16")
end
return sectors
if 0x18 == tag.sak then --NXP MIFARE Classic 4k | Plus 4k
-- 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.
sectors = 40
elseif 0x08 == tag.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k
-- 1K offers 1024 bytes of data storage, split into 16 sector
sectors = 16
elseif 0x09 == tag.sak then -- NXP MIFARE Mini 0.3k
-- MIFARE Classic mini offers 320 bytes split into five sectors.
sectors = 5
elseif 0x10 == tag.sak then-- "NXP MIFARE Plus 2k"
sectors = 32
else
print("I don't know how many sectors there are on this type of card, defaulting to 16")
end
return sectors
end
---
-- The main entry point
local function main(args)
local start_time = os.time()
local numSectors = 16
local start_time = os.time()
local numSectors = 16
-- Arguments for the script
for o, a in getopt.getopt(args, 'hp') do
if o == "h" then return help() end
if o == "p" then return printkeys() end
end
-- identify tag
tag, err = lib14a.read(false, true)
if not tag then return oops(err) end
-- Arguments for the script
for o, a in getopt.getopt(args, 'hp') do
if o == "h" then return help() end
if o == "p" then return printkeys() end
end
-- identify tag
tag, err = lib14a.read(false, true)
if not tag then return oops(err) end
-- detect sectors and print taginfo
numsectors = taginfo(tag)
-- detect sectors and print taginfo
numsectors = taginfo(tag)
perform_check(numsectors)
perform_check(numsectors)
local end_time = os.time()
print('mfkeys - Total execution time: '..os.difftime(end_time, start_time)..' sec')
local end_time = os.time()
print('mfkeys - Total execution time: '..os.difftime(end_time, start_time)..' sec')
end
main( args)

View file

@ -11,8 +11,8 @@ usage = [[
script run mifare_access -h -a <access bytes>
Arguments:
-h : this help
-a <access bytes> : 4 bytes ACCESS CONDITIONS
-h : this help
-a <access bytes> : 4 bytes ACCESS CONDITIONS
]]
local DEBUG = true
@ -20,35 +20,35 @@ local bxor = bit32.bxor
local band = bit32.band
local rshift = bit32.rshift
---
---
-- A debug printout-function
local function dbg(args)
if not DEBUG then return end
if type(args) == "table" then
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print("###", args)
end
end
---
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
local function oops(err)
print("ERROR: ",err)
return nil, err
print("ERROR: ",err)
return nil, err
end
---
---
-- Usage help
local function help()
print(copyright)
print(author)
print(version)
print(desc)
print('Example usage')
print(example)
print(copyright)
print(author)
print(version)
print(desc)
print('Example usage')
print(example)
end
local access_condition_sector_trailer = {}
@ -73,58 +73,58 @@ access_condition_data_block[0x7] = {'never','never','never','never'}
local function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
print()
print( string.rep('--',20) )
print( string.rep('--',20) )
print()
local access = ''
-- Read the parameters
for o, a in getopt.getopt(args, 'ha:') do
if o == "h" then return help() end
if o == "a" then access = a end
end
if access == nil 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
local c2_b = tonumber(string.sub(access, 1, 1), 16)
local c1_b = tonumber(string.sub(access, 2, 2), 16)
local c1 = tonumber(string.sub(access, 3, 3), 16)
local c3_b = tonumber(string.sub(access, 4, 4), 16)
local c3 = tonumber(string.sub(access, 5, 5), 16)
local c2 = tonumber(string.sub(access, 6, 6), 16)
local gpb = string.sub(access, 7, 8)
local access = ''
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(c3, c3_b) ~= 0xF then print("!!! bitflip in c3") end
-- Read the parameters
for o, a in getopt.getopt(args, 'ha:') do
if o == "h" then return help() end
if o == "a" then access = a end
end
local ab = c1 * 256 + c2 * 16 + c3
if access == nil 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
for block = 0,3 do
print("--> block "..block)
-- mask bits for block
local abi = band(rshift(ab, block), 0x111)
-- compress bits
abi = band(abi + rshift(abi, 3) + rshift(abi, 6),7)
-- print(abi)
if block == 3 then
print(" KEYSECXA read: "..access_condition_sector_trailer[abi][1])
print(" KEYSECXA write: "..access_condition_sector_trailer[abi][2])
print(" ACCESS COND. read: "..access_condition_sector_trailer[abi][3])
print("ACCESS COND. write: "..access_condition_sector_trailer[abi][4])
print(" KEYSECXB read: "..access_condition_sector_trailer[abi][5])
print(" KEYSECXB write: "..access_condition_sector_trailer[abi][6])
else
print(" read: "..access_condition_data_block[abi][1])
print(" write: "..access_condition_data_block[abi][2])
print(" inc: "..access_condition_data_block[abi][3])
print("decr, transfer, restore: "..access_condition_data_block[abi][4])
end
end
local c2_b = tonumber(string.sub(access, 1, 1), 16)
local c1_b = tonumber(string.sub(access, 2, 2), 16)
local c1 = tonumber(string.sub(access, 3, 3), 16)
local c3_b = tonumber(string.sub(access, 4, 4), 16)
local c3 = tonumber(string.sub(access, 5, 5), 16)
local c2 = tonumber(string.sub(access, 6, 6), 16)
local gpb = string.sub(access, 7, 8)
print("GPB: "..gpb)
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(c3, c3_b) ~= 0xF then print("!!! bitflip in c3") end
local ab = c1 * 256 + c2 * 16 + c3
for block = 0,3 do
print("--> block "..block)
-- mask bits for block
local abi = band(rshift(ab, block), 0x111)
-- compress bits
abi = band(abi + rshift(abi, 3) + rshift(abi, 6),7)
-- print(abi)
if block == 3 then
print(" KEYSECXA read: "..access_condition_sector_trailer[abi][1])
print(" KEYSECXA write: "..access_condition_sector_trailer[abi][2])
print(" ACCESS COND. read: "..access_condition_sector_trailer[abi][3])
print("ACCESS COND. write: "..access_condition_sector_trailer[abi][4])
print(" KEYSECXB read: "..access_condition_sector_trailer[abi][5])
print(" KEYSECXB write: "..access_condition_sector_trailer[abi][6])
else
print(" read: "..access_condition_data_block[abi][1])
print(" write: "..access_condition_data_block[abi][2])
print(" inc: "..access_condition_data_block[abi][3])
print("decr, transfer, restore: "..access_condition_data_block[abi][4])
end
end
print("GPB: "..gpb)
end
main(args)

View file

@ -7,208 +7,208 @@ example = "script run mifare_autopwn"
author = "Martin Holst Swende"
desc =
[[
This is a script which automates cracking and dumping mifare classic cards. It sets itself into
'listening'-mode, after which it cracks and dumps any mifare classic card that you
place by the device.
This is a script which automates cracking and dumping mifare classic cards. It sets itself into
'listening'-mode, after which it cracks and dumps any mifare classic card that you
place by the device.
Arguments:
-h this help
-d debug logging on
-k known key for Sector 0 , keytype A
-h this help
-d debug logging on
-k known key for Sector 0 , keytype A
Output files from this operation:
<uid>.eml - emulator file
<uid>.html - html file containing card data
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.
<uid>.eml - emulator file
<uid>.html - html file containing card data
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.
]]
-------------------------------
-- Some utilities
-- Some utilities
-------------------------------
local DEBUG = false
---
---
-- A debug printout-function
local function dbg(args)
if not DEBUG then return end
if type(args) == 'table' then
local i = 1
while result[i] do
dbg(result[i])
i = i+1
end
else
print('###', args)
end
end
---
-- This is only meant to be used when errors occur
local function oops(err)
print("ERROR: ",err)
return nil,err
end
---
-- Usage help
local function help()
print(desc)
print("Example usage")
print(example)
if not DEBUG then return end
if type(args) == 'table' then
local i = 1
while result[i] do
dbg(result[i])
i = i+1
end
else
print('###', args)
end
end
---
-- Waits for a mifare card to be placed within the vicinity of the reader.
-- This is only meant to be used when errors occur
local function oops(err)
print("ERROR: ",err)
return nil,err
end
---
-- Usage help
local function help()
print(desc)
print("Example usage")
print(example)
end
---
-- Waits for a mifare card to be placed within the vicinity of the reader.
-- @return if successfull: an table containing card info
-- @return if unsuccessfull : nil, error
local function wait_for_mifare()
while not core.ukbhit() do
res, err = lib14a.read()
if res then return res end
-- err means that there was no response from card
end
return nil, "Aborted by user"
while not core.ukbhit() do
res, err = lib14a.read()
if res then return res end
-- err means that there was no response from card
end
return nil, "Aborted by user"
end
local function nested(key,sak)
local typ = 1
if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k | Ev1 4k
typ = 4
elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k | Ev1 1K
typ = 1
elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k
typ = 0
elseif 0x10 == sak then-- "NXP MIFARE Plus 2k"
typ = 2
elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K"
typ = 1
else
print("I don't know how many sectors there are on this type of card, defaulting to 16")
end
local cmd = string.format("hf mf nested %d 0 A %s d", typ, key)
core.console(cmd)
local typ = 1
if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k | Ev1 4k
typ = 4
elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k | Ev1 1K
typ = 1
elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k
typ = 0
elseif 0x10 == sak then-- "NXP MIFARE Plus 2k"
typ = 2
elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K"
typ = 1
else
print("I don't know how many sectors there are on this type of card, defaulting to 16")
end
local cmd = string.format("hf mf nested %d 0 A %s d", typ, key)
core.console(cmd)
end
local function dump(uid, numsectors)
dbg('dumping tag memory')
dbg('dumping tag memory')
local typ = 1
if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k | Ev1 4k
typ = 4
elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k | Ev1 1K
typ = 1
elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k
typ = 0
elseif 0x10 == sak then-- "NXP MIFARE Plus 2k"
typ = 2
elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K"
typ = 1
end
local typ = 1
if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k | Ev1 4k
typ = 4
elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k | Ev1 1K
typ = 1
elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k
typ = 0
elseif 0x10 == sak then-- "NXP MIFARE Plus 2k"
typ = 2
elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K"
typ = 1
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)
core.console(dmp)
local dmp = ('hf mf dump %s f %s'):format(typ, dumpfile)
core.console(dmp)
-- Save the global args, those are *our* arguments
local myargs = args
-- Set the arguments for htmldump script
args =('-i %s -o %s.html'):format(dumpfile, uid)
-- call it
require('htmldump')
-- Save the global args, those are *our* arguments
local myargs = args
-- Set the arguments for htmldump script
args =('-i %s -o %s.html'):format(dumpfile, uid)
-- call it
require('htmldump')
-- dump to emulator
args =('-i %s -o %s.eml'):format(dumpfile, uid)
require('dumptoemul')
-- dump to emulator
args =('-i %s -o %s.eml'):format(dumpfile, uid)
require('dumptoemul')
-- Set back args. Not that it's used, just for the karma...
args = myargs
end
-- Set back args. Not that it's used, just for the karma...
args = myargs
end
end
--
-- performs a test if tag nonce uses weak or hardend prng
local function perform_prng_test()
local isweak = core.detect_prng()
if isweak == 1 then
dbg('PRNG detection : WEAK nonce detected')
elseif isweak == 0 then
dbg('PRNG detection : HARDEND nonce detected')
else
dbg('PRNG detection : failed')
end
return isweak
local isweak = core.detect_prng()
if isweak == 1 then
dbg('PRNG detection : WEAK nonce detected')
elseif isweak == 0 then
dbg('PRNG detection : HARDEND nonce detected')
else
dbg('PRNG detection : failed')
end
return isweak
end
---
---
-- The main entry point
local function main(args)
local verbose, exit, res, uid, err, _, sak
local seen_uids = {}
local key = ''
local print_message = true
-- Read the parameters
for o, a in getopt.getopt(args, 'hdk:') do
if o == "h" then help() return end
if o == "d" then DEBUG = true end
if o == 'k' then key = a end
end
local verbose, exit, res, uid, err, _, sak
local seen_uids = {}
local key = ''
local print_message = true
-- Read the parameters
for o, a in getopt.getopt(args, 'hdk:') do
if o == "h" then help() return end
if o == "d" then DEBUG = true end
if o == 'k' then key = a end
end
while not exit do
if print_message then
print("Waiting for card or press any key to stop")
print_message = false
end
res, err = wait_for_mifare()
if err then return oops(err) end
-- Seen already?
uid = res.uid
sak = res.sak
if not seen_uids[uid] then
-- Store it
seen_uids[uid] = uid
-- check if PRNG is WEAK
if perform_prng_test() == 1 then
print("Card found, commencing crack on UID", uid)
while not exit do
if print_message then
print("Waiting for card or press any key to stop")
print_message = false
end
res, err = wait_for_mifare()
if err then return oops(err) end
-- Seen already?
uid = res.uid
sak = res.sak
if #key == 12 then
print("Using key: "..key);
else
-- Crack it
local cnt
err, res = core.mfDarkside()
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 == -3 then return oops("Card is not vulnerable to Darkside attack (its random number generator is not predictable).")
elseif err == -4 then return oops([[
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.]])
elseif err == -5 then return oops("Aborted via keyboard.")
end
-- The key is actually 8 bytes, so a
-- 6-byte key is sent as 00XXXXXX
-- This means we unpack it as first
-- two bytes, then six bytes actual key data
-- We can discard first and second return values
_,_,key = bin.unpack("H2H6",res)
print("Found valid key: "..key);
end
-- Use nested attack
nested(key, sak)
-- Dump info
dump(uid, sak)
if not seen_uids[uid] then
-- Store it
seen_uids[uid] = uid
if #key == 12 then exit = true end
else
print("Card found, darkside attack useless PRNG hardend on UID", uid)
end
print_message = true
end
end
-- check if PRNG is WEAK
if perform_prng_test() == 1 then
print("Card found, commencing crack on UID", uid)
if #key == 12 then
print("Using key: "..key);
else
-- Crack it
local cnt
err, res = core.mfDarkside()
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 == -3 then return oops("Card is not vulnerable to Darkside attack (its random number generator is not predictable).")
elseif err == -4 then return oops([[
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.]])
elseif err == -5 then return oops("Aborted via keyboard.")
end
-- The key is actually 8 bytes, so a
-- 6-byte key is sent as 00XXXXXX
-- This means we unpack it as first
-- two bytes, then six bytes actual key data
-- We can discard first and second return values
_,_,key = bin.unpack("H2H6",res)
print("Found valid key: "..key);
end
-- Use nested attack
nested(key, sak)
-- Dump info
dump(uid, sak)
if #key == 12 then exit = true end
else
print("Card found, darkside attack useless PRNG hardend on UID", uid)
end
print_message = true
end
end
end
-- Call the main
-- Call the main
main(args)

View file

@ -9,19 +9,19 @@ 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.
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 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).
- 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.
- 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.
]]
usage = [[
script run mifareplus -h
Arguments:
-h : this help
-h : this help
]]
-- Default
-- Default
SIXTEEN_BYTES_ZEROS = '00000000000000000000000000000000'
-- ISO7816 commands used
@ -38,264 +38,264 @@ PROXIMITYCHECK = '03F2'
VERIFYPC = '03FD'
READPLAINNOMACUNMACED = '0336'
---
---
-- This is only meant to be used when errors occur
local function oops(err)
print('ERROR: ',err)
return nil, err
print('ERROR: ',err)
return nil, err
end
---
-- Usage help
local function help()
print(copyright)
print(author)
print(version)
print(desc)
print('Example usage')
print(example)
print(copyright)
print(author)
print(version)
print(desc)
print('Example usage')
print(example)
end
---
-- Used to send raw data to the firmware to subsequently forward the data to the card.
local function sendRaw(rawdata, crc, power)
print(("<sent>: %s"):format(rawdata))
print(("<sent>: %s"):format(rawdata))
local flags = lib14a.ISO14A_COMMAND.ISO14A_RAW
if crc then
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC
end
if power then
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT
end
local flags = lib14a.ISO14A_COMMAND.ISO14A_RAW
if crc then
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC
end
if power then
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT
end
local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a,
arg1 = flags, -- Send raw
arg2 = string.len(rawdata) / 2, -- arg2 contains the length, which is half the length of the ASCII-string rawdata
data = rawdata}
local ignore_response = false
local result, err = lib14a.sendToDevice(command, ignore_response)
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
local count,cmd,arg1,arg2,arg3,data = bin.unpack('LLLLH512',result)
local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a,
arg1 = flags, -- Send raw
arg2 = string.len(rawdata) / 2, -- arg2 contains the length, which is half the length of the ASCII-string rawdata
data = rawdata}
local ignore_response = false
local result, err = lib14a.sendToDevice(command, ignore_response)
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
local count,cmd,arg1,arg2,arg3,data = bin.unpack('LLLLH512',result)
returned_bytes = string.sub(data, 1, arg1 * 2)
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
return returned_bytes
else
return nil
end
else
oops("Error sending the card raw data.")
return nil
end
returned_bytes = string.sub(data, 1, arg1 * 2)
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
return returned_bytes
else
return nil
end
else
oops("Error sending the card raw data.")
return nil
end
end
-- Sends an instruction to do nothing, only disconnect
local function disconnect()
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
-- Check /armsrc/iso14443a.c, ReaderIso14443a() for details
return lib14a.sendToDevice(command,true)
end
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
-- Check /armsrc/iso14443a.c, ReaderIso14443a() for details
return lib14a.sendToDevice(command,true)
end
local function writePerso()
-- Used to write any data, including the keys (Key A and Key B), for all the sectors.
-- writePerso() command parameters:
-- 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)
-- 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.
-- response from PICC:
-- 0x90 - OK
-- 0x09 - targeted block is invalid for writes, i.e. block 0, which contains manufacturer data
-- 0x0B - command invalid
-- 0x0C - unexpected command length
-- Used to write any data, including the keys (Key A and Key B), for all the sectors.
-- writePerso() command parameters:
-- 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)
-- 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.
-- response from PICC:
-- 0x90 - OK
-- 0x09 - targeted block is invalid for writes, i.e. block 0, which contains manufacturer data
-- 0x0B - command invalid
-- 0x0C - unexpected command length
cardsize = 4 --need to set to 4 for 4k or 2 for 2k
if(cardsize == 4) then
numsectors = 39
elseif(cardsize == 2) then
numsectors = 31
else
oops("Invalid card size")
end
-- Write to the AES sector keys
print("Setting AES Sector keys")
for i=0,numsectors do --for each sector number
local keyA_block = "40" .. string.format("%02x", i * 2)
local keyB_block = "40" .. string.format("%02x", (i * 2) + 1)
--Can also calculate the keys fancily to make them unique, if desired
keyA = SIXTEEN_BYTES_ZEROS
keyB = SIXTEEN_BYTES_ZEROS
writeBlock(keyA_block, keyA)
writeBlock(keyB_block, keyB)
end
print("Finished setting AES Sector keys")
cardsize = 4 --need to set to 4 for 4k or 2 for 2k
if(cardsize == 4) then
numsectors = 39
elseif(cardsize == 2) then
numsectors = 31
else
oops("Invalid card size")
end
print("Setting misc keys which haven't been set yet.")
--CardMasterKey
blocknum = "9000"
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
--CardConfigurationKey
blocknum = "9001"
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
--L3SwitchKey
blocknum = "9003"
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
--SL1CardAuthKey
blocknum = "9004"
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
--L3SectorSwitchKey
blocknum = "9006"
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
--L1L3MixSectorSwitchKey
blocknum = "9007"
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
--VC Keys
--VCProximityKey
blocknum = "A001"
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
--VCSelectENCKey
blocknum = "A080"
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
--VCSelectMACKey
blocknum = "A081"
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
--TransactionMACKey1
blocknum = "C000"
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
--TransactionMACConfKey1
blocknum = "C001"
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
print("Finished setting misc keys.")
-- Write to the AES sector keys
print("Setting AES Sector keys")
for i=0,numsectors do --for each sector number
local keyA_block = "40" .. string.format("%02x", i * 2)
local keyB_block = "40" .. string.format("%02x", (i * 2) + 1)
--Can also calculate the keys fancily to make them unique, if desired
keyA = SIXTEEN_BYTES_ZEROS
keyB = SIXTEEN_BYTES_ZEROS
writeBlock(keyA_block, keyA)
writeBlock(keyB_block, keyB)
end
print("Finished setting AES Sector keys")
print("WritePerso finished! Card is ready to move into new security level.")
print("Setting misc keys which haven't been set yet.")
--CardMasterKey
blocknum = "9000"
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
--CardConfigurationKey
blocknum = "9001"
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
--L3SwitchKey
blocknum = "9003"
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
--SL1CardAuthKey
blocknum = "9004"
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
--L3SectorSwitchKey
blocknum = "9006"
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
--L1L3MixSectorSwitchKey
blocknum = "9007"
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
--VC Keys
--VCProximityKey
blocknum = "A001"
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
--VCSelectENCKey
blocknum = "A080"
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
--VCSelectMACKey
blocknum = "A081"
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
--TransactionMACKey1
blocknum = "C000"
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
--TransactionMACConfKey1
blocknum = "C001"
writeBlock(blocknum, SIXTEEN_BYTES_ZEROS)
print("Finished setting misc keys.")
print("WritePerso finished! Card is ready to move into new security level.")
end
local function writeBlock(blocknum, data)
-- 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)
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).
response = sendRaw(commandString, true, true) --0x90 is returned upon success
if string.sub(response, 3, 4) ~= "90" then
oops(("error occurred while trying to write to block %s"):format(blocknum))
end
-- 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)
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).
response = sendRaw(commandString, true, true) --0x90 is returned upon success
if string.sub(response, 3, 4) ~= "90" then
oops(("error occurred while trying to write to block %s"):format(blocknum))
end
end
local function authenticateAES()
-- Used to try to authenticate with the AES keys we programmed into the card, to ensure the authentication works correctly.
commandString = AUTH_FIRST
commandString = commandString .. ''
-- Used to try to authenticate with the AES keys we programmed into the card, to ensure the authentication works correctly.
commandString = AUTH_FIRST
commandString = commandString .. ''
end
local function getVersion()
sendRaw(GETVERS_INIT, true, true)
sendRaw(GETVERS_CONT, true, true)
sendRaw(GETVERS_CONT, true, true)
sendRaw(GETVERS_INIT, true, true)
sendRaw(GETVERS_CONT, true, true)
sendRaw(GETVERS_CONT, true, true)
end
local function commitPerso(SL)
--pass SL as "01" to move to SL1 or "03" to move to SL3.
commandString = COMMITPERSO .. SL
response = sendRaw(commandString, true, true) --0x90 is returned upon success
if string.sub(response, 3, 4) ~= "90" then
oops("error occurred while trying to switch security level")
end
--pass SL as "01" to move to SL1 or "03" to move to SL3.
commandString = COMMITPERSO .. SL
response = sendRaw(commandString, true, true) --0x90 is returned upon success
if string.sub(response, 3, 4) ~= "90" then
oops("error occurred while trying to switch security level")
end
end
local function calculateMAC(MAC_input)
-- Pad the input if it is not a multiple of 16 bytes (32 nibbles).
if(string.len(MAC_input) % 32 ~= 0) then
MAC_input = MAC_input .. "80"
end
while(string.len(MAC_input) % 32 ~= 0) do
MAC_input = MAC_input .. "0"
end
print("Padded MAC Input = " .. MAC_input .. ", length (bytes) = " .. string.len(MAC_input) / 2)
-- Pad the input if it is not a multiple of 16 bytes (32 nibbles).
if(string.len(MAC_input) % 32 ~= 0) then
MAC_input = MAC_input .. "80"
end
while(string.len(MAC_input) % 32 ~= 0) do
MAC_input = MAC_input .. "0"
end
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
raw_output = "00010203040506070001020304050607" -- Dummy filler for now of 16-byte output. To be filled with actual MAC for testing purposes.
--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.
-- The final 8-byte MAC output is a concatenation of every 2nd byte starting from the second MSB.
final_output = ""
j = 3
for i = 1,8 do
final_output = final_output .. string.sub(RndR, j, j + 1) .. string.sub(RndC, j, j + 1)
j = j + 4
end
return final_output
-- The final 8-byte MAC output is a concatenation of every 2nd byte starting from the second MSB.
final_output = ""
j = 3
for i = 1,8 do
final_output = final_output .. string.sub(RndR, j, j + 1) .. string.sub(RndC, j, j + 1)
j = j + 4
end
return final_output
end
local function proximityCheck()
--PreparePC--
commandString = PREPAREPC
response = sendRaw(commandString, true, true)
if not response then return oops("This card is not support the proximity check command.") end
OPT = string.sub(response, 5, 6)
if tonumber(OPT) == 1 then
pps_present = true
else
pps_present = false
end
pubRespTime = string.sub(response, 7, 10)
if(pps_present == true) then
pps = string.sub(response, 11, 12)
else
pps = ''
end
print("OPT = " .. OPT .. " pubRespTime = " .. pubRespTime .. " pps = " .. pps)
--PreparePC--
commandString = PREPAREPC
response = sendRaw(commandString, true, true)
if not response then return oops("This card is not support the proximity check command.") end
--PC--
RndC = "0001020304050607" --Random Challenge
num_rounds = 8 --Needs to be 1, 2, 4, or 8
part_len = 8 / num_rounds
j = 1
RndR = ""
for i = 1,num_rounds do
pRndC = ""
for q = 1,(part_len*2) do
pRndC = pRndC .. string.sub(RndC,j,j)
j = j + 1
end
commandString = PROXIMITYCHECK .. "0" .. tostring(part_len) .. pRndC
pRndR = string.sub(sendRaw(commandString, true, true), 3, 3+part_len)
RndR = RndR .. pRndR
end
print("RndC = " .. RndC .. " RndR = " .. RndR)
OPT = string.sub(response, 5, 6)
if tonumber(OPT) == 1 then
pps_present = true
else
pps_present = false
end
pubRespTime = string.sub(response, 7, 10)
if(pps_present == true) then
pps = string.sub(response, 11, 12)
else
pps = ''
end
print("OPT = " .. OPT .. " pubRespTime = " .. pubRespTime .. " pps = " .. pps)
--VerifyPC--
MAC_input = "FD" .. OPT .. pubRespTime
if pps_present then
MAC_input = MAC_input .. pps
end
rnum_concat = ""
rnum_concat = RndR .. RndC --temporary (only works for when a single random challenge (8 bytes) is sent)
-- j = 1
-- for i = 1,8 do
-- rnum_concat = rnum_concat .. string.sub(RndR, j, j + 1) .. string.sub(RndC, j, j + 1)
-- j = j + 2
-- end
MAC_input = MAC_input .. rnum_concat
print("Concatenation of random numbers = " .. rnum_concat)
print("Final PCD concatenation before input into MAC function = " .. MAC_input)
MAC_tag = calculateMAC(MAC_input)
print("8-byte PCD MAC_tag (placeholder - currently incorrect) = " .. MAC_tag)
commandString = VERIFYPC .. MAC_tag
response = sendRaw(commandString, true, true)
print(#response, response)
if #response < 20 then return oops("Wrong response length (expected 20, got "..#response..") exiting") end
PICC_MAC = string.sub(response, 5, 20)
print("8-byte MAC returned by PICC = " .. PICC_MAC)
MAC_input = "90" .. string.sub(MAC_input, 3)
print("Final PICC concatenation before input into MAC function = " .. MAC_input)
MAC_tag = calculateMAC(MAC_input)
print("8-byte PICC MAC_tag (placeholder - currently incorrect) = " .. MAC_tag)
--PC--
RndC = "0001020304050607" --Random Challenge
num_rounds = 8 --Needs to be 1, 2, 4, or 8
part_len = 8 / num_rounds
j = 1
RndR = ""
for i = 1,num_rounds do
pRndC = ""
for q = 1,(part_len*2) do
pRndC = pRndC .. string.sub(RndC,j,j)
j = j + 1
end
commandString = PROXIMITYCHECK .. "0" .. tostring(part_len) .. pRndC
pRndR = string.sub(sendRaw(commandString, true, true), 3, 3+part_len)
RndR = RndR .. pRndR
end
print("RndC = " .. RndC .. " RndR = " .. RndR)
--VerifyPC--
MAC_input = "FD" .. OPT .. pubRespTime
if pps_present then
MAC_input = MAC_input .. pps
end
rnum_concat = ""
rnum_concat = RndR .. RndC --temporary (only works for when a single random challenge (8 bytes) is sent)
-- j = 1
-- for i = 1,8 do
-- rnum_concat = rnum_concat .. string.sub(RndR, j, j + 1) .. string.sub(RndC, j, j + 1)
-- j = j + 2
-- end
MAC_input = MAC_input .. rnum_concat
print("Concatenation of random numbers = " .. rnum_concat)
print("Final PCD concatenation before input into MAC function = " .. MAC_input)
MAC_tag = calculateMAC(MAC_input)
print("8-byte PCD MAC_tag (placeholder - currently incorrect) = " .. MAC_tag)
commandString = VERIFYPC .. MAC_tag
response = sendRaw(commandString, true, true)
print(#response, response)
if #response < 20 then return oops("Wrong response length (expected 20, got "..#response..") exiting") end
PICC_MAC = string.sub(response, 5, 20)
print("8-byte MAC returned by PICC = " .. PICC_MAC)
MAC_input = "90" .. string.sub(MAC_input, 3)
print("Final PICC concatenation before input into MAC function = " .. MAC_input)
MAC_tag = calculateMAC(MAC_input)
print("8-byte PICC MAC_tag (placeholder - currently incorrect) = " .. MAC_tag)
end
@ -303,47 +303,47 @@ end
-- The main entry point
function main(args)
local o, a
for o, a in getopt.getopt(args, 'h') do -- Populate command line arguments
if o == "h" then return help() end
end
local o, a
for o, a in getopt.getopt(args, 'h') do -- Populate command line arguments
if o == "h" then return help() end
end
-- 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.
info,err = lib14a.read(true, false)
if not info then oops(err); disconnect(); return; end
--
response = sendRaw("D01100", true, true)
if not response then oops("No response from PPS check"); disconnect(); return; end
-- 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.
info,err = lib14a.read(true, false)
if not info then oops(err); disconnect(); return; end
print("Connected to")
print(" Type : "..info.name)
print(" UID : "..info.uid)
-- Now, the card is initialized and we can do more interesting things.
--
response = sendRaw("D01100", true, true)
if not response then oops("No response from PPS check"); disconnect(); return; end
--writePerso()
--commitPerso("03") --move to SL3
--getVersion()
proximityCheck()
print("Connected to")
print(" Type : "..info.name)
print(" UID : "..info.uid)
--commandString = VERIFYPC .. "186EFDE8DDC7D30B"
-- MAC = f5180d6e 40fdeae8 e9dd6ac7 bcd3350b
-- response = sendRaw(commandString, true, true)
-- Now, the card is initialized and we can do more interesting things.
-- attempt to read VCProximityKey at block A001
-- commandString = READPLAINNOMACUNMACED .. "01A0" .. "01"
-- response = sendRaw(commandString, true, true)
--writePerso()
--commitPerso("03") --move to SL3
--getVersion()
proximityCheck()
-- authenticate with CardConfigurationKey
-- commandString = AUTH_FIRST .. "0190" .. "00"
-- response = sendRaw(commandString, true, true)
--commandString = VERIFYPC .. "186EFDE8DDC7D30B"
-- MAC = f5180d6e 40fdeae8 e9dd6ac7 bcd3350b
-- response = sendRaw(commandString, true, true)
-- Power off the Proxmark
sendRaw(POWEROFF, false, false)
disconnect()
-- attempt to read VCProximityKey at block A001
-- commandString = READPLAINNOMACUNMACED .. "01A0" .. "01"
-- response = sendRaw(commandString, true, true)
-- authenticate with CardConfigurationKey
-- commandString = AUTH_FIRST .. "0190" .. "00"
-- response = sendRaw(commandString, true, true)
-- Power off the Proxmark
sendRaw(POWEROFF, false, false)
disconnect()
end
main(args)

View file

@ -4,20 +4,20 @@ local getopt = require('getopt')
local cmds = require('commands')
local taglib = require('taglib')
local desc =
local desc =
[[This script will automatically recognize and dump full content of a NFC NDEF Initialized tag; non-initialized tags will be ignored.
It also write the dump to an eml-file <uid>.eml.
(The difference between an .eml-file and a .bin-file is that the eml file contains
ASCII representation of the hex-data, with linebreaks between 'rows'. A .bin-file contains the
raw data, but when saving into that for, we lose the infromation about how the memory is structured.
For example: 24 bytes could be 6 blocks of 4 bytes, or vice versa.
ASCII representation of the hex-data, with linebreaks between 'rows'. A .bin-file contains the
raw data, but when saving into that for, we lose the infromation about how the memory is structured.
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.)
Arguments:
-d debug logging on
-h this help
-h this help
-d debug logging on
]]
local example = "script run xxx"
@ -25,116 +25,116 @@ local author = "Martin Holst Swende & Asper"
---
-- PrintAndLog
local function prlog(...)
-- TODO; replace this with a call to the proper PrintAndLog
print(...)
-- TODO; replace this with a call to the proper PrintAndLog
print(...)
end
---
---
-- This is only meant to be used when errors occur
local function oops(err)
prlog("ERROR: ",err)
return nil,err
prlog("ERROR: ",err)
return nil,err
end
-- Perhaps this will be moved to a separate library at one point
local utils = {
--- Writes an eml-file.
-- @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' ...,
-- that is, blockData[row] contains a string with the actual data, not ascii hex representation
-- return filename if all went well,
-- @reurn nil, error message if unsuccessfull
writeDumpFile = function(uid, blockData)
local destination = string.format("%s.eml", uid)
local file = io.open(destination, "w")
if file == nil then
return nil, string.format("Could not write to file %s", destination)
end
local rowlen = string.len(blockData[1])
--- Writes an eml-file.
-- @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' ...,
-- that is, blockData[row] contains a string with the actual data, not ascii hex representation
-- return filename if all went well,
-- @reurn nil, error message if unsuccessfull
writeDumpFile = function(uid, blockData)
local destination = string.format("%s.eml", uid)
local file = io.open(destination, "w")
if file == nil then
return nil, string.format("Could not write to file %s", destination)
end
local rowlen = string.len(blockData[1])
for i,block in ipairs(blockData) do
if rowlen ~= string.len(block) then
prlog(string.format("WARNING: Dumpdata seems corrupted, line %d was not the same length as line 1",i))
end
for i,block in ipairs(blockData) do
if rowlen ~= string.len(block) then
prlog(string.format("WARNING: Dumpdata seems corrupted, line %d was not the same length as line 1",i))
end
local formatString = string.format("H%d", string.len(block))
local _,hex = bin.unpack(formatString,block)
file:write(hex.."\n")
end
file:close()
return destination
end,
local formatString = string.format("H%d", string.len(block))
local _,hex = bin.unpack(formatString,block)
file:write(hex.."\n")
end
file:close()
return destination
end,
}
---
---
-- Usage help
local function help()
prlog(desc)
prlog("Example usage")
prlog(example)
prlog(desc)
prlog("Example usage")
prlog(example)
end
local function debug(...)
if DEBUG then
prlog("debug:", ...)
end
if DEBUG then
prlog("debug:", ...)
end
end
--- This function is a lua-implementation of
-- cmdhf14a.c:waitCmd(uint8_t iSelect)
local function waitCmd(iSelect)
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,1000)
if response then
local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',response)
local iLen = arg0
if iSelect then iLen = arg1 end
debug(("Received %i octets (arg0:%d, arg1:%d)"):format(iLen, arg0, arg1))
if iLen == 0 then return nil, "No response from tag" end
local recv = string.sub(response,count, iLen+count-1)
return recv
end
return nil, "No response from device"
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,1000)
if response then
local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',response)
local iLen = arg0
if iSelect then iLen = arg1 end
debug(("Received %i octets (arg0:%d, arg1:%d)"):format(iLen, arg0, arg1))
if iLen == 0 then return nil, "No response from tag" end
local recv = string.sub(response,count, iLen+count-1)
return recv
end
return nil, "No response from device"
end
local function show(data)
if DEBUG then
local formatString = ("H%d"):format(string.len(data))
local _,hexdata = bin.unpack(formatString, data)
debug("Hexdata" , hexdata)
end
if DEBUG then
local formatString = ("H%d"):format(string.len(data))
local _,hexdata = bin.unpack(formatString, data)
debug("Hexdata" , hexdata)
end
end
--- Fire up a connection with a tag, return uid
-- @return UID if successfull
-- @return nil, errormessage if unsuccessfull
local function open()
debug("Opening connection")
core.clearCommandBuffer()
local x = string.format("hf 14a raw -r -p -s")
debug(x)
core.console(x)
debug("done")
data, err = waitCmd(true)
if err then return oops(err) end
show(data)
local formatString = ("H%d"):format(string.len(data))
local _,uid = bin.unpack(formatString, data)
return uid
debug("Opening connection")
core.clearCommandBuffer()
local x = string.format("hf 14a raw -r -p -s")
debug(x)
core.console(x)
debug("done")
data, err = waitCmd(true)
if err then return oops(err) end
show(data)
local formatString = ("H%d"):format(string.len(data))
local _,uid = bin.unpack(formatString, data)
return uid
end
--- Shut down tag communication
-- return no return values
local function close()
debug("Closing connection")
core.clearCommandBuffer()
local x = string.format("hf 14a raw -r")
debug(x)
core.console(x)
debug("done")
--data, err = waitCmd(true)
--data, err = waitCmd(false)
debug("Closing connection")
core.clearCommandBuffer()
local x = string.format("hf 14a raw -r")
debug(x)
core.console(x)
debug("done")
--data, err = waitCmd(true)
--data, err = waitCmd(false)
end
@ -143,105 +143,105 @@ end
-- @return {block, block+1, block+2, block+3} if successfull
-- @return nil, errormessage if unsuccessfull
local function getBlock(block)
local data, err
local data, err
core.clearCommandBuffer()
local x = string.format("hf 14a raw -r -c -p 30 %02x", block)
debug(x)
core.console(x)
debug("done")
-- By now, there should be an ACK waiting from the device, since
-- we used the -r flag (don't read response).
core.clearCommandBuffer()
data, err = waitCmd(false)
if err then return oops(err) end
show(data)
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))
end
-- Now, parse out the block data
-- 0534 00B9 049C AD7F 4A00 0000 E110 1000 2155
-- b0b0 b0b0 b1b1 b1b1 b2b2 b2b2 b3b3 b3b3 CRCC
b0 = string.sub(data,1,4)
b1 = string.sub(data,5,8)
b2 = string.sub(data,9,12)
b3 = string.sub(data,13,16)
return {b0,b1,b2,b3}
local x = string.format("hf 14a raw -r -c -p 30 %02x", block)
debug(x)
core.console(x)
debug("done")
-- By now, there should be an ACK waiting from the device, since
-- we used the -r flag (don't read response).
data, err = waitCmd(false)
if err then return oops(err) end
show(data)
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))
end
-- Now, parse out the block data
-- 0534 00B9 049C AD7F 4A00 0000 E110 1000 2155
-- b0b0 b0b0 b1b1 b1b1 b2b2 b2b2 b3b3 b3b3 CRCC
b0 = string.sub(data,1,4)
b1 = string.sub(data,5,8)
b2 = string.sub(data,9,12)
b3 = string.sub(data,13,16)
return {b0,b1,b2,b3}
end
local function main( args)
debug("script started")
local err, data, data2,k,v,i
-- Read the parameters
for o, a in getopt.getopt(args, 'hd') do
if o == "h" then help() return end
if o == "d" then DEBUG = true end
end
debug("script started")
local err, data, data2,k,v,i
-- Read the parameters
for o, a in getopt.getopt(args, 'hd') do
if o == "h" then help() return end
if o == "d" then DEBUG = true end
end
-- Info contained within the tag (block 0 example)
-- 0534 00B9 049C AD7F 4A00 0000 E110 1000 2155
-- b0b0 b0b0 b1b1 b1b1 b2b2 b2b2 b3b3 b3b3 CRCC
-- MM?? ???? ???? ???? ???? ???? NNVV SS?? ----
-- M = Manufacturer info
-- N = NDEF-Structure-Compliant (if value is E1)
-- V = NFC Forum Specification version (if 10 = v1.0)
-- Info contained within the tag (block 0 example)
-- 0534 00B9 049C AD7F 4A00 0000 E110 1000 2155
-- b0b0 b0b0 b1b1 b1b1 b2b2 b2b2 b3b3 b3b3 CRCC
-- MM?? ???? ???? ???? ???? ???? NNVV SS?? ----
-- M = Manufacturer info
-- N = NDEF-Structure-Compliant (if value is E1)
-- V = NFC Forum Specification version (if 10 = v1.0)
-- First, 'connect' (fire up the field) and get the uid
local uidHexstr = open()
-- First, 'connect' (fire up the field) and get the uid
local uidHexstr = open()
-- First, get blockt 3 byte 2
local blocks, err = getBlock(0)
if err then return oops(err) end
-- Block 3 contains number of blocks
local b3chars = {string.byte(blocks[4], 1,4)}
local numBlocks = b3chars[3] * 2 + 6
prlog("Number of blocks:", numBlocks)
-- First, get blockt 3 byte 2
local blocks, err = getBlock(0)
if err then return oops(err) end
-- Block 3 contains number of blocks
local b3chars = {string.byte(blocks[4], 1,4)}
local numBlocks = b3chars[3] * 2 + 6
prlog("Number of blocks:", numBlocks)
-- NDEF compliant?
if b3chars[1] ~= 0xE1 then
return oops("This tag is not NDEF-Compliant")
end
-- NDEF compliant?
if b3chars[1] ~= 0xE1 then
return oops("This tag is not NDEF-Compliant")
end
local ndefVersion = b3chars[2]
local ndefVersion = b3chars[2]
-- Block 1, byte 1 contains manufacturer info
local bl1_b1 = string.byte(blocks[1], 1)
local manufacturer = taglib.lookupManufacturer(bl1_b1)
-- Block 1, byte 1 contains manufacturer info
local bl1_b1 = string.byte(blocks[1], 1)
local manufacturer = taglib.lookupManufacturer(bl1_b1)
-- Reuse existing info
local blockData = {blocks[1],blocks[2],blocks[3],blocks[4]}
-- Reuse existing info
local blockData = {blocks[1],blocks[2],blocks[3],blocks[4]}
--[[ 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)
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.
--]]
prlog("Dumping data...please wait")
for i=4,numBlocks-1,1 do
blocks, err = getBlock(i)
if err then return oops(err) end
table.insert(blockData,blocks[1])
end
-- Deactivate field
close()
-- Print results
prlog(string.format("Tag manufacturer: %s", manufacturer))
prlog(string.format("Tag UID: %s", uidHexstr))
prlog(string.format("Tag NDEF version: 0x%02x", ndefVersion))
for k,v in ipairs(blockData) do
prlog(string.format("Block %02x: %02x %02x %02x %02x",k-1, string.byte(v, 1,4)))
end
local filename, err = utils.writeDumpFile(uidHexstr, blockData)
if err then return oops(err) end
--[[ 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)
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.
--]]
prlog("Dumping data...please wait")
for i=4,numBlocks-1,1 do
blocks, err = getBlock(i)
if err then return oops(err) end
table.insert(blockData,blocks[1])
end
-- Deactivate field
close()
-- Print results
prlog(string.format("Tag manufacturer: %s", manufacturer))
prlog(string.format("Tag UID: %s", uidHexstr))
prlog(string.format("Tag NDEF version: 0x%02x", ndefVersion))
prlog(string.format("Dumped data into %s", filename))
for k,v in ipairs(blockData) do
prlog(string.format("Block %02x: %02x %02x %02x %02x",k-1, string.byte(v, 1,4)))
end
local filename, err = utils.writeDumpFile(uidHexstr, blockData)
if err then return oops(err) end
prlog(string.format("Dumped data into %s", filename))
end
main(args)

View file

@ -12,25 +12,25 @@ Thanks to @jack for his invaluable input on some of the configuration.
example =[[
-- This will generate GOLD, PLA, TH, EU, 200m, tagbased uid.
script run ntag_3d -c 46 -m 50 -p 5448 -s 4555 -l 200
-- 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
-- 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
-- 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
]]
usage = [[
script run calc_ntag_3d -h -t -u <uid> -c <color> -m <material> -p <region> -s <region> -l <length>
Arguments:
-h : this help
-t : selftest
-u <UID> : UID
-c <COLOR> : color of filament
-m <MATERIAL> : material of filament
-p <REGION> : Manufacturer region
-s <REGION> : Sales region
-l <LENGTH> : Spool length. Use only 100,200,300. 300 has problems on OSX
-h : this help
-t : selftest
-u <UID> : UID
-c <COLOR> : color of filament
-m <MATERIAL> : material of filament
-p <REGION> : Manufacturer region
-s <REGION> : Sales region
-l <LENGTH> : Spool length. Use only 100,200,300. 300 has problems on OSX
]]
local DEBUG = true
@ -40,344 +40,344 @@ local band = bit32.band
local rshift = bit32.rshift
local _regions = {
{'4742', 'GB'},
{'5457', 'TW'},
{'4555', 'EU'},
{'5553', 'US'},
{'454E', 'EN'},
{'4A50', 'JP'},
{'434E', 'CN'},
{'5448', 'TH'},
{'4153', 'AS'},
{'5246', 'RF'},
{'4746', 'GF'},
{'4341', 'CA'},
{'504D', 'PM'},
{'5044', 'PD'},
{'4742', 'GB'},
{'5457', 'TW'},
{'4555', 'EU'},
{'5553', 'US'},
{'454E', 'EN'},
{'4A50', 'JP'},
{'434E', 'CN'},
{'5448', 'TH'},
{'4153', 'AS'},
{'5246', 'RF'},
{'4746', 'GF'},
{'4341', 'CA'},
{'504D', 'PM'},
{'5044', 'PD'},
}
local _manufacturers = {
{'5457', 'TW'},
{'434E', 'CN'},
{'5448', 'TH'},
{'5457', 'TW'},
{'434E', 'CN'},
{'5448', 'TH'},
}
local _sales = {
{'4742', 'GB'},
{'4555', 'EU'},
{'5553', 'US'},
{'454E', 'EN'},
{'504D', 'PM'},
{'4742', 'GB'},
{'4555', 'EU'},
{'5553', 'US'},
{'454E', 'EN'},
{'504D', 'PM'},
}
local _materials = {
{'20', 'Other material'},
{'41', 'ABS'},
{'46', 'Flexible TPE Tree'},
{'46', 'TPE'},
{'46', 'PVA'},
{'47', 'PETG'},
{'50', 'PLA'},
{'51', 'PLA'},
{'54', 'Tough PLA'},
{'55', 'UVCR'},
{'56', 'Water Soluble PVA'},
{'20', 'Other material'},
{'41', 'ABS'},
{'46', 'Flexible TPE Tree'},
{'46', 'TPE'},
{'46', 'PVA'},
{'47', 'PETG'},
{'50', 'PLA'},
{'51', 'PLA'},
{'54', 'Tough PLA'},
{'55', 'UVCR'},
{'56', 'Water Soluble PVA'},
}
local _colors = {
{'30', 'Bronze'},
{'31', 'Silver'},
{'32', 'Clear Red'},
{'33', 'Clear'},
{'34', 'Bottle Green'},
{'35', 'Neon Magenta'},
{'36', 'SteelBlue'},
{'37', 'Sun Orange'},
{'38', 'Pearl White'},
{'39', 'Copper'},
{'41', 'Purple'},
{'42', 'Blue'},
{'43', 'Neon Tangerine'},
{'44', 'Viridity'},
{'45', 'Olivine'},
{'46', 'Gold'},
{'47', 'Green'},
{'48', 'Neon Green'},
{'49', 'Snow White'},
{'4A', 'Neon Yellow'},
{'4B', 'Black'},
{'4C', 'Violet'},
{'4D', 'Grape Purple'},
{'4E', 'Purpurine'},
{'4F', 'Clear Yellow'},
{'50', 'Clear Green'},
{'51', 'Clear Tangerine'},
{'52', 'Red'},
{'53', 'Cyber Yellow'},
{'54', 'Tangerine'},
{'55', 'Clear Blue'},
{'56', 'Clear Purple'},
{'57', 'White'},
{'58', 'Clear Magenta'},
{'59', 'Yellow'},
{'5A', 'Nature'},
{'30', 'Bronze'},
{'31', 'Silver'},
{'32', 'Clear Red'},
{'33', 'Clear'},
{'34', 'Bottle Green'},
{'35', 'Neon Magenta'},
{'36', 'SteelBlue'},
{'37', 'Sun Orange'},
{'38', 'Pearl White'},
{'39', 'Copper'},
{'41', 'Purple'},
{'42', 'Blue'},
{'43', 'Neon Tangerine'},
{'44', 'Viridity'},
{'45', 'Olivine'},
{'46', 'Gold'},
{'47', 'Green'},
{'48', 'Neon Green'},
{'49', 'Snow White'},
{'4A', 'Neon Yellow'},
{'4B', 'Black'},
{'4C', 'Violet'},
{'4D', 'Grape Purple'},
{'4E', 'Purpurine'},
{'4F', 'Clear Yellow'},
{'50', 'Clear Green'},
{'51', 'Clear Tangerine'},
{'52', 'Red'},
{'53', 'Cyber Yellow'},
{'54', 'Tangerine'},
{'55', 'Clear Blue'},
{'56', 'Clear Purple'},
{'57', 'White'},
{'58', 'Clear Magenta'},
{'59', 'Yellow'},
{'5A', 'Nature'},
}
---
--
local function find( arr, name )
if not name then return nil end
if not name then return nil end
name = name:lower()
for k, v in pairs(arr) do
if ( v[2]:lower() == name or v[1]:lower() == name ) then
return v
end
end
return nil
if ( v[2]:lower() == name or v[1]:lower() == name ) then
return v
end
end
return nil
end
---
--
local function list( arr, desc )
print ('Value\t'..desc)
print (string.rep('=', 20))
print ('Value\t'..desc)
print (string.rep('=', 20))
for k, v in pairs(arr) do
print(("%s\t%s"):format(v[1],v[2]))
end
print(("%s\t%s"):format(v[1],v[2]))
end
end
---
---
-- A debug printout-function
local function dbg(args)
if not DEBUG then return end
if type(args) == 'table' then
local i = 1
while result[i] do
dbg(result[i])
i = i+1
end
else
print('###', args)
end
end
---
if not DEBUG then return end
if type(args) == 'table' then
local i = 1
while result[i] do
dbg(result[i])
i = i+1
end
else
print('###', args)
end
end
---
-- This is only meant to be used when errors occur
local function oops(err)
print('ERROR: ',err)
return nil,err
print('ERROR: ',err)
return nil,err
end
---
---
-- Usage help
local function help()
print(copyright)
print(version)
print(desc)
print('Example usage')
print(example)
print(copyright)
print(version)
print(desc)
print('Example usage')
print(example)
end
--
-- Exit message
local function ExitMsg(msg)
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
end
---
--
local function write_tag(uid, t)
print('Writing to tag')
core.console('hf mf dbg 0')
local cmd = ''
local pwd, pack = core.keygen_algo_d(uid)
for i= 8, 23 do
cmd = ('hf mfu wrbl b %02d d %s k %08X'):format(i, t[i], pwd)
core.console(cmd)
end
--cfg1
core.console(('hf mfu wrbl b 42 d %s k %08X'):format(t[42], pwd))
--cfg0
core.console(('hf mfu wrbl b 41 d %s k %08X'):format(t[41], pwd))
--dynamic
core.console(('hf mfu wrbl b 40 d %s k %08X'):format(t[40], pwd))
core.console('hf mf dbg 1')
print('Done')
print('Writing to tag')
core.console('hf mf dbg 0')
local cmd = ''
local pwd, pack = core.keygen_algo_d(uid)
for i= 8, 23 do
cmd = ('hf mfu wrbl b %02d d %s k %08X'):format(i, t[i], pwd)
core.console(cmd)
end
--cfg1
core.console(('hf mfu wrbl b 42 d %s k %08X'):format(t[42], pwd))
--cfg0
core.console(('hf mfu wrbl b 41 d %s k %08X'):format(t[41], pwd))
--dynamic
core.console(('hf mfu wrbl b 40 d %s k %08X'):format(t[40], pwd))
core.console('hf mf dbg 1')
print('Done')
end
---
-- configures a magic NTAG for NTAG213, with UID and PWD,PACK.
local function configure_magic_ntag(uid)
print('Configuring MAGIC NTAG')
-- Save the global args, those are *our* arguments
local myargs = args
local pwd, pack = core.keygen_algo_d(uid)
-- Set the arguments for mfu_magic script v1.0.8
-- -t 12 == configure NTAG213F
-- -u == set UID
-- -p == set pwd
-- -a == set pack
args =('-t 12 -u %s -p %08X -a %04X'):format(uid, pwd, pack)
require('../scripts/mfu_magic')
-- Set back args. Not that it's used, just for the karma...
args = myargs
print('Done')
print('Configuring MAGIC NTAG')
-- Save the global args, those are *our* arguments
local myargs = args
local pwd, pack = core.keygen_algo_d(uid)
-- Set the arguments for mfu_magic script v1.0.8
-- -t 12 == configure NTAG213F
-- -u == set UID
-- -p == set pwd
-- -a == set pack
args =('-t 12 -u %s -p %08X -a %04X'):format(uid, pwd, pack)
require('../scripts/mfu_magic')
-- Set back args. Not that it's used, just for the karma...
args = myargs
print('Done')
end
---
-- generates random hex numbers between 31-39
local function random_num_hex(length)
local str = ""
local i
for i = 1, length, 1 do
str = str..math.random(31, 39)
end
return str
local str = ""
local i
for i = 1, length, 1 do
str = str..math.random(31, 39)
end
return str
end
---
--
local function nwo( val )
local b1 = band(val, 0xFF)
local b2 = band( rshift(val, 8), 0xFF)
local b3 = band( rshift(val, 16), 0xFF)
local b4 = band( rshift(val, 24), 0xFF)
return ('%02X%02X%02X%02X'):format(b1, b2, b3, b4)
local b1 = band(val, 0xFF)
local b2 = band( rshift(val, 8), 0xFF)
local b3 = band( rshift(val, 16), 0xFF)
local b4 = band( rshift(val, 24), 0xFF)
return ('%02X%02X%02X%02X'):format(b1, b2, b3, b4)
end
---
-- NTAG213 template
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_str = nwo(m)
local t = {}
-- default empty file
for i = 0,42 do
t[i] = '00000000'
end
-- t[4] = '0103A00C' --
-- t[5] = '340300FE' --
local m = tonumber(length, 10) * 1000
local m_str = nwo(m)
local t = {}
-- default empty file
for i = 0,42 do
t[i] = '00000000'
end
-- t[4] = '0103A00C' --
-- t[5] = '340300FE' --
-- 6,7
t[8] = '5A'..material..color..'00' -- 5A, material, color, 00
t[9] = '00'..random_num_hex(3) -- 00, three bytes serial number
t[10] = m_str -- total capacity
t[11] = m_str -- total capacity
t[12] = 'D2002D00' -- fixed
t[13] = manufacture..sales -- regioner,
t[14] = random_num_hex(4) -- serial number
t[8] = '5A'..material..color..'00' -- 5A, material, color, 00
t[9] = '00'..random_num_hex(3) -- 00, three bytes serial number
t[10] = m_str -- total capacity
t[11] = m_str -- total capacity
t[12] = 'D2002D00' -- fixed
t[13] = manufacture..sales -- regioner,
t[14] = random_num_hex(4) -- serial number
-- 15,16
t[17] = '34000000' -- fixed
t[17] = '34000000' -- fixed
-- 18,19
-- remaining capacity of spool
t[20] = m_str
t[21] = nwo( bxor( m, 0x54321248))
t[22] = nwo( bxor( (m - 3876923 ), 0x31275455))
t[23] = nwo( bxor( (m + 6923923 ), 0x76235481))
-- 24-39
t[40] = '000000BD' --dynamic
t[41] = '07000008' --cfg0
t[42] = '80050000' --cfg1
t[43] = ('%08X'):format(pwd)
t[44] = ('%04X0000'):format(pack)
return t
-- remaining capacity of spool
t[20] = m_str
t[21] = nwo( bxor( m, 0x54321248))
t[22] = nwo( bxor( (m - 3876923 ), 0x31275455))
t[23] = nwo( bxor( (m + 6923923 ), 0x76235481))
-- 24-39
t[40] = '000000BD' --dynamic
t[41] = '07000008' --cfg0
t[42] = '80050000' --cfg1
t[43] = ('%08X'):format(pwd)
t[44] = ('%04X0000'):format(pack)
return t
end
---
-- outputs the called arguments
local function print_conf(uid, material, color, length, producer, sales )
print('Create tag as following')
print( string.rep('--',16) )
print('UID ', uid)
print('Material ', material[2])
print('Color ', color[2])
print('Spool length ', length)
print('Region')
print(' manufacturer', producer[2])
print(' sales ', sales[2])
print( string.rep('--',16) )
print('Create tag as following')
print( string.rep('--',16) )
print('UID ', uid)
print('Material ', material[2])
print('Color ', color[2])
print('Spool length ', length)
print('Region')
print(' manufacturer', producer[2])
print(' sales ', sales[2])
print( string.rep('--',16) )
end
---
-- self test
local function selftest()
list(_regions, 'Regions')
list(_materials, 'Materials')
list(_colors, 'Colors')
return nil
local function selftest()
list(_regions, 'Regions')
list(_materials, 'Materials')
list(_colors, 'Colors')
return nil
end
---
---
-- The main entry point
local function main(args)
math.randomseed(os.time());
math.random();
math.randomseed(os.time());
math.random();
print( string.rep('--',20) )
print( string.rep('--',20) )
print()
local uid = '04C5DF4A6D5180'
local useUID = false
local useMAGIC = false
local material, color, length, producer, sales
if #args == 0 then return help() end
print( string.rep('--',20) )
print( string.rep('--',20) )
print()
-- Read the parameters
for o, a in getopt.getopt(args, 'ht1u:l:m:c:p:s:') do
if o == "h" then return help() end
if o == "t" then return selftest() end
if o == "u" then uid = a; useUID = true end
if o == "m" then material = a end
if o == "c" then color = a end
if o == "l" then length = tonumber(a) end
if o == "p" then producer = a end
if o == "s" then sales = a end
if o == "1" then useMAGIC = true end
end
local uid = '04C5DF4A6D5180'
local useUID = false
local useMAGIC = false
local material, color, length, producer, sales
color = find(_colors, color)
if not color then list(_colors, 'Colors'); return oops('\n\nNot valid color') end
material = find(_materials, material)
if not material then list(_materials, 'Materials'); return oops('\n\nNot valid material') end
producer = find(_manufacturers, producer)
if not producer then list(_manufacturers, 'Regions Manufacturers'); return oops('\n\nNo valid manufacturer region') end
if #args == 0 then return help() end
sales = find(_sales, sales)
if not sales then list(_sales, 'Regions Sales'); return oops('\n\nNo valid sales region') end
if length > 300 then
return oops('\n\nNot valid spool length. Must be lesser than 300')
end
if useUID then
-- uid string checks
if uid == nil 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
else
-- GET TAG UID
local tag, err = lib14a.read(false, true)
if not tag then return oops(err) end
core.clearCommandBuffer()
uid = tag.uid
end
-- Read the parameters
for o, a in getopt.getopt(args, 'ht1u:l:m:c:p:s:') do
if o == "h" then return help() end
if o == "t" then return selftest() end
if o == "u" then uid = a; useUID = true end
if o == "m" then material = a end
if o == "c" then color = a end
if o == "l" then length = tonumber(a) end
if o == "p" then producer = a end
if o == "s" then sales = a end
if o == "1" then useMAGIC = true end
end
--print
print_conf(uid, material, color, length, producer, sales )
-- create template
local t = template_NTAG213(uid, material[1], color[1], length, producer[1], sales[1])
color = find(_colors, color)
if not color then list(_colors, 'Colors'); return oops('\n\nNot valid color') end
-- using MAGIC NTAG
if useMAGIC then
configure_magic_ntag(uid)
end
-- write template data to tag
write_tag(uid, t)
material = find(_materials, material)
if not material then list(_materials, 'Materials'); return oops('\n\nNot valid material') end
producer = find(_manufacturers, producer)
if not producer then list(_manufacturers, 'Regions Manufacturers'); return oops('\n\nNo valid manufacturer region') end
sales = find(_sales, sales)
if not sales then list(_sales, 'Regions Sales'); return oops('\n\nNo valid sales region') end
if length > 300 then
return oops('\n\nNot valid spool length. Must be lesser than 300')
end
if useUID then
-- uid string checks
if uid == nil 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
else
-- GET TAG UID
local tag, err = lib14a.read(false, true)
if not tag then return oops(err) end
core.clearCommandBuffer()
uid = tag.uid
end
--print
print_conf(uid, material, color, length, producer, sales )
-- create template
local t = template_NTAG213(uid, material[1], color[1], length, producer[1], sales[1])
-- using MAGIC NTAG
if useMAGIC then
configure_magic_ntag(uid)
end
-- write template data to tag
write_tag(uid, t)
end
main(args)

View file

@ -6,40 +6,40 @@ getopt = require('getopt')
usage = "script run parameters.lua -a 1 -blala -c -de"
author = "Martin Holst Swende"
desc =[[
This is an example script to demonstrate handle parameters in scripts.
This is an example script to demonstrate handle parameters in scripts.
For more info, check the comments in the code
]]
local function main(args)
print(desc)
print("These parameters were passed")
--[[
When passing parameters,
x: means that a value should follow x
y means that 'y' is a flag, either on or off
So, the string a:b:def means that we support up to
5 parameters; two with values and three flags. The following
should be valid:
print(desc)
print("These parameters were passed")
--[[
When passing parameters,
x: means that a value should follow x
y means that 'y' is a flag, either on or off
So, the string a:b:def means that we support up to
5 parameters; two with values and three flags. The following
should be valid:
script run parameters.lua -a 1 -blala -c -de
script run parameters.lua -a 1 -blala -c -de
Notice two things:
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'
3. The format -b=lala is *not* supported
4. The format b lala (without -) is *not* supported
--]]
Notice two things:
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'
3. The format -b=lala is *not* supported
4. The format b lala (without -) is *not* supported
--]]
for o, a in getopt.getopt(args, 'a:b:ced') do
print(o, a)
end
for o, a in getopt.getopt(args, 'a:b:ced') do
print(o, a)
end
end
--[[
In the future, we may implement so that scripts are invoked directly
In the future, we may implement so that scripts are invoked directly
into a 'main' function, instead of being executed blindly. For future
compatibility, I have done so, but I invoke my main from here.
compatibility, I have done so, but I invoke my main from here.
--]]
main(args)

View file

@ -1,141 +1,141 @@
local getopt = require('getopt')
local bin = require('bin')
copyright = 'Copyright (c) 2018 Bogito. All rights reserved.'
author = "Bogito"
version = 'v1.0.1'
desc =
[[
This script will read the flash memory of RDV4 and print the stored passwords.
It was meant to be used as a help tool after using the BogRun standalone mode.
(Iceman) script adapted to read and print keys in the default dictionary flashmemory sections.
]]
usage =
[[
Usage:
script run read_pwd_mem -h -o <offset> -l <length> -k <keylength>
Arguments:
-h : this help
-o <offset> : memory offset, default is 0
-l <length> : length in bytes, default is 256
-k <keylen> : key length in bytes <4|6|8> , default is 4
-m : print Mifare dictionary keys
-t : print t55xx dictionary passwords
-i : print iClass dictionary keys
]]
example =
[[
-- This will scan the first 256 bytes of flash memory for stored passwords
script run read_pwd_mem
-- This will scan 256 bytes of flash memory at offset 64 for stored passwords
script run read_pwd_mem -o 64
-- This will scan 32 bytes of flash memory at offset 64 for stored passwords
script run read_pwd_mem -o 64 -l 32
-- This will print found
script run read_pwd_mem -o 241664 -k 6
]]
---
-- This is only meant to be used when errors occur
local function oops(err)
print("ERROR: ", err)
return nil, err
end
---
-- Usage help
local function help()
print(copyright)
print(version)
print(desc)
print(usage)
print('Example usage:')
print(example)
end
---
-- The main entry point
local function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
print()
local data, err, quadlet
local cnt = 0
local offset = 0
local length = 256
local keylength = 4
local usedkey = false
for o, a in getopt.getopt(args, 'ho:l:k:mti') do
-- help
if o == "h" then return help() end
-- offset
if o == "o" then offset = tonumber(a) end
-- num of bytes to read
if o == "l" then length = tonumber(a) end
-- keylength
if o == "k" then keylength = tonumber(a); usedkey = true 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 == "i" then keylength =8; usedkey = true; offset = 0x3F000-0x5000; end
end
if length < 0 or length > 256 then
return oops('Error: Length is not valid. Must be less than 256')
end
if (offset < 0) or (offset % 4 ~= 0) then
return oops('Error: Offset is not valid. Mod-4 values are only allowed.')
end
print('Memory offset', offset)
print('Length ', length)
print('Key length ', keylength)
print( string.rep('--',20) )
if usedkey then length = 4096 end
data, err = core.GetFromFlashMem(offset, length)
if err then return oops(err) end
if usedkey then
_, keys, s = bin.unpack('SH'..length-2, data)
if keys == 0xFFFF then return "No keys found in section" end
local kl = keylength * 2
for i = 1, keys do
key = string.sub(s, (i - 1) * kl + 1, i * kl )
print(string.format("[%02d] %s",i, key))
end
print( string.rep('--',20) )
print( ('[+] found %d passwords'):format(keys))
else
_, s = bin.unpack('H'..length, data)
local cnt = 0, i
for i = 1, (length/keylength) do
key = string.sub(s, (i-1)*8+1, i*8)
if key == "FFFFFFFF" then break end
print(string.format("[%02d] %s",i, key))
cnt = cnt + 1
end
print( string.rep('--',20) )
print( ('[+] found %d passwords'):format(cnt))
end
print( string.rep('--',20) )
end
main(args)
local getopt = require('getopt')
local bin = require('bin')
copyright = 'Copyright (c) 2018 Bogito. All rights reserved.'
author = "Bogito"
version = 'v1.0.1'
desc =
[[
This script will read the flash memory of RDV4 and print the stored passwords.
It was meant to be used as a help tool after using the BogRun standalone mode.
(Iceman) script adapted to read and print keys in the default dictionary flashmemory sections.
]]
usage =
[[
Usage:
script run read_pwd_mem -h -o <offset> -l <length> -k <keylength>
Arguments:
-h : this help
-o <offset> : memory offset, default is 0
-l <length> : length in bytes, default is 256
-k <keylen> : key length in bytes <4|6|8> , default is 4
-m : print Mifare dictionary keys
-t : print t55xx dictionary passwords
-i : print iClass dictionary keys
]]
example =
[[
-- This will scan the first 256 bytes of flash memory for stored passwords
script run read_pwd_mem
-- This will scan 256 bytes of flash memory at offset 64 for stored passwords
script run read_pwd_mem -o 64
-- This will scan 32 bytes of flash memory at offset 64 for stored passwords
script run read_pwd_mem -o 64 -l 32
-- This will print found
script run read_pwd_mem -o 241664 -k 6
]]
---
-- This is only meant to be used when errors occur
local function oops(err)
print("ERROR: ", err)
return nil, err
end
---
-- Usage help
local function help()
print(copyright)
print(version)
print(desc)
print(usage)
print('Example usage:')
print(example)
end
---
-- The main entry point
local function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
print()
local data, err, quadlet
local cnt = 0
local offset = 0
local length = 256
local keylength = 4
local usedkey = false
for o, a in getopt.getopt(args, 'ho:l:k:mti') do
-- help
if o == "h" then return help() end
-- offset
if o == "o" then offset = tonumber(a) end
-- num of bytes to read
if o == "l" then length = tonumber(a) end
-- keylength
if o == "k" then keylength = tonumber(a); usedkey = true 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 == "i" then keylength =8; usedkey = true; offset = 0x3F000-0x5000; end
end
if length < 0 or length > 256 then
return oops('Error: Length is not valid. Must be less than 256')
end
if (offset < 0) or (offset % 4 ~= 0) then
return oops('Error: Offset is not valid. Mod-4 values are only allowed.')
end
print('Memory offset', offset)
print('Length ', length)
print('Key length ', keylength)
print( string.rep('--',20) )
if usedkey then length = 4096 end
data, err = core.GetFromFlashMem(offset, length)
if err then return oops(err) end
if usedkey then
_, keys, s = bin.unpack('SH'..length-2, data)
if keys == 0xFFFF then return "No keys found in section" end
local kl = keylength * 2
for i = 1, keys do
key = string.sub(s, (i - 1) * kl + 1, i * kl )
print(string.format("[%02d] %s",i, key))
end
print( string.rep('--',20) )
print( ('[+] found %d passwords'):format(keys))
else
_, s = bin.unpack('H'..length, data)
local cnt = 0, i
for i = 1, (length/keylength) do
key = string.sub(s, (i-1)*8+1, i*8)
if key == "FFFFFFFF" then break end
print(string.format("[%02d] %s",i, key))
cnt = cnt + 1
end
print( string.rep('--',20) )
print( ('[+] found %d passwords'):format(cnt))
end
print( string.rep('--',20) )
end
main(args)

View file

@ -4,100 +4,100 @@ example = "script run remagic"
author = "Iceman"
desc =
[[
This is a script that tries to bring back a chinese magic card (1k generation1)
This is a script that tries to bring back a chinese magic card (1k generation1)
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
Arguments:
-h this help
-u remagic a Ultralight tag w 7 bytes UID.
-h this help
-u remagic a Ultralight tag w 7 bytes UID.
]]
---
---
-- A debug printout-function
local function dbg(args)
if DEBUG then
print('###', args)
end
end
---
if DEBUG then
print('###', args)
end
end
---
-- This is only meant to be used when errors occur
local function oops(err)
print('ERROR: ',err)
print('ERROR: ',err)
end
---
---
-- Usage help
local function help()
print(desc)
print('Example usage')
print(example)
print(desc)
print('Example usage')
print(example)
end
local function cmdUltralight()
return {
return {
--[[
--]]
[0] = "hf 14a raw -p -a -b 7 40",
[1] = "hf 14a raw -p -a 43",
[2] = "hf 14a raw -c -a A2005380712A",
[3] = "hf 14a raw -p -a -b 7 40",
[4] = "hf 14a raw -p -a 43",
[5] = "hf 14a raw -c -a A2010200D980",
[6] = "hf 14a raw -p -a -b 7 40",
[7] = "hf 14a raw -p -a 43",
[8] = "hf 14a raw -c -a A2025B480000",
[9] = "hf 14a raw -c -a 5000",
}
[0] = "hf 14a raw -p -a -b 7 40",
[1] = "hf 14a raw -p -a 43",
[2] = "hf 14a raw -c -a A2005380712A",
[3] = "hf 14a raw -p -a -b 7 40",
[4] = "hf 14a raw -p -a 43",
[5] = "hf 14a raw -c -a A2010200D980",
[6] = "hf 14a raw -p -a -b 7 40",
[7] = "hf 14a raw -p -a 43",
[8] = "hf 14a raw -c -a A2025B480000",
[9] = "hf 14a raw -c -a 5000",
}
end
local function cmdClassic()
return {
return {
--[[
--]]
[0] = "hf 14a raw -p -a -b 7 40",
[1] = "hf 14a raw -p -a 43",
[2] = "hf 14a raw -c -p -a A000",
[3] = "hf 14a raw -c -p -a 01020304049802000000000000001001",
[4] = "hf 14a raw -c -a 5000",
}
[0] = "hf 14a raw -p -a -b 7 40",
[1] = "hf 14a raw -p -a 43",
[2] = "hf 14a raw -c -p -a A000",
[3] = "hf 14a raw -c -p -a 01020304049802000000000000001001",
[4] = "hf 14a raw -c -a 5000",
}
end
local function cmdRestoreST()
local arr = {}
for i = 0, 15 do
local blk = 3 + (4*i)
arr[i] = "hf mf csetbl "..blk.." FFFFFFFFFFFFFF078000FFFFFFFFFFFF"
end
return arr
end
local function sendCmds( cmds )
for i = 0, #cmds do
if cmds[i] then
print ( cmds[i] )
core.console( cmds[i] )
core.clearCommandBuffer()
end
end
local arr = {}
for i = 0, 15 do
local blk = 3 + (4*i)
arr[i] = "hf mf csetbl "..blk.." FFFFFFFFFFFFFF078000FFFFFFFFFFFF"
end
return arr
end
---
local function sendCmds( cmds )
for i = 0, #cmds do
if cmds[i] then
print ( cmds[i] )
core.console( cmds[i] )
core.clearCommandBuffer()
end
end
end
---
-- The main entry point
function main(args)
local i
local cmds = {}
local isUltralight = false
-- Read the parameters
for o, a in getopt.getopt(args, 'hu') do
if o == "h" then return help() end
if o == "u" then isUltralight = true end
end
local i
local cmds = {}
local isUltralight = false
core.clearCommandBuffer()
if isUltralight then
sendCmds ( cmdUltralight() )
else
sendCmds( cmdClassic() )
sendCmds( cmdRestoreST() )
end
-- Read the parameters
for o, a in getopt.getopt(args, 'hu') do
if o == "h" then return help() end
if o == "u" then isUltralight = true end
end
core.clearCommandBuffer()
if isUltralight then
sendCmds ( cmdUltralight() )
else
sendCmds( cmdClassic() )
sendCmds( cmdRestoreST() )
end
end
main(args)

View file

@ -7,7 +7,7 @@ local format=string.format
local floor=math.floor
example =[[
1. script run test_t55x7_ask
1. script run test_t55x7_ask
]]
author = "Iceman"
usage = "script run test_t55x7_ask"
@ -15,32 +15,32 @@ desc =[[
This script will program a T55x7 TAG with the configuration: block 0x00 data 0x000100
The outlined procedure is as following:
--ASK
00 00 80 40
--ASK
00 00 80 40
-- max 2
-- manchester
-- bit rate
"lf t55xx write b 0 d 00008040"
"lf t55xx detect"
"lf t55xx info"
Loop:
change the configuretion block 0 with:
-xx 00 xxxx = RF/8
-xx 04 xxxx = RF/16
-xx 08 xxxx = RF/32
-xx 0C xxxx = RF/40
-xx 10 xxxx = RF/50
-xx 14 xxxx = RF/64
-xx 18 xxxx = RF/100
-xx 1C xxxx = RF/128
change the configuretion block 0 with:
-xx 00 xxxx = RF/8
-xx 04 xxxx = RF/16
-xx 08 xxxx = RF/32
-xx 0C xxxx = RF/40
-xx 10 xxxx = RF/50
-xx 14 xxxx = RF/64
-xx 18 xxxx = RF/100
-xx 1C xxxx = RF/128
testsuit for the ASK/MANCHESTER demod
Arguments:
-h : this help
-h : this help
]]
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
@ -51,90 +51,90 @@ local config1 = '00'
local config2 = '8040'
local procedurecmds = {
[1] = '%s%02X%s',
[2] = 'lf t55xx detect',
[3] = 'lf t55xx info',
[1] = '%s%02X%s',
[2] = 'lf t55xx detect',
[3] = 'lf t55xx info',
}
---
---
-- A debug printout-function
local function dbg(args)
if not DEBUG then
return
end
if not DEBUG then
return
end
if type(args) == "table" then
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print("###", args)
end
end
---
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
local function oops(err)
print("ERROR: ",err)
print("ERROR: ",err)
end
---
---
-- Usage help
local function help()
print(desc)
print("Example usage")
print(example)
print(desc)
print("Example usage")
print(example)
end
--
-- Exit message
local function ExitMsg(msg)
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
end
local function test()
local y
local block = "00"
for y = 0x0, 0x1d, 0x4 do
for _ = 1, #procedurecmds do
local pcmd = procedurecmds[_]
if #pcmd == 0 then
elseif _ == 1 then
local y
local block = "00"
for y = 0x0, 0x1d, 0x4 do
for _ = 1, #procedurecmds do
local pcmd = procedurecmds[_]
local config = pcmd:format(config1, y, config2)
dbg(('lf t55xx write b 0 d %s'):format(config))
config = tonumber(config,16)
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
local err = core.SendCommand(writecmd:getBytes())
if err then return oops(err) end
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
if #pcmd == 0 then
else
dbg(pcmd)
core.console( pcmd )
end
end
core.clearCommandBuffer()
end
print( string.rep('--',20) )
elseif _ == 1 then
local config = pcmd:format(config1, y, config2)
dbg(('lf t55xx write b 0 d %s'):format(config))
config = tonumber(config,16)
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
local err = core.SendCommand(writecmd:getBytes())
if err then return oops(err) end
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
else
dbg(pcmd)
core.console( pcmd )
end
end
core.clearCommandBuffer()
end
print( string.rep('--',20) )
end
local function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
print( string.rep('--',20) )
print( string.rep('--',20) )
-- Arguments for the script
for o, arg in getopt.getopt(args, 'h') do
if o == "h" then return help() end
end
-- Arguments for the script
for o, arg in getopt.getopt(args, 'h') do
if o == "h" then return help() end
end
core.clearCommandBuffer()
test()
print( string.rep('--',20) )
core.clearCommandBuffer()
test()
print( string.rep('--',20) )
end
main(args)

View file

@ -4,7 +4,7 @@ local bin = require('bin')
local utils = require('utils')
example =[[
1. script run test_t55x7_bi
1. script run test_t55x7_bi
]]
author = "Iceman"
usage = "script run test_t55x7_bi"
@ -20,21 +20,21 @@ The outlined procedure is as following:
"lf t55xx info"
Loop:
change the configuretion block 0 with:
-xx01xxxx = RF/8
change the configuretion block 0 with:
-xx01xxxx = RF/8
-xx05xxxx = RF/16
-xx09xxxx = RF/32
-xx0Dxxxx = RF/40
-xx11xxxx = RF/50
-xx15xxxx = RF/64
-xx19xxxx = RF/100
-xx1Dxxxx = RF/128
-xx09xxxx = RF/32
-xx0Dxxxx = RF/40
-xx11xxxx = RF/50
-xx15xxxx = RF/64
-xx19xxxx = RF/100
-xx1Dxxxx = RF/128
testsuit for the BIPHASE demod
Arguments:
-h : this help
-h : this help
]]
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
@ -45,90 +45,90 @@ local config1 = '00'
local config2 = '0040'
local procedurecmds = {
[1] = '%s%02X%s',
[2] = 'lf t55xx detect',
[3] = 'lf t55xx info',
[1] = '%s%02X%s',
[2] = 'lf t55xx detect',
[3] = 'lf t55xx info',
}
---
---
-- A debug printout-function
local function dbg(args)
if not DEBUG then
return
end
if not DEBUG then
return
end
if type(args) == "table" then
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print("###", args)
end
end
---
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
local function oops(err)
print("ERROR: ",err)
print("ERROR: ",err)
end
---
---
-- Usage help
local function help()
print(desc)
print("Example usage")
print(example)
print(desc)
print("Example usage")
print(example)
end
--
-- Exit message
local function ExitMsg(msg)
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
end
local function test()
local y
local block = "00"
for y = 1, 0x1D, 4 do
for _ = 1, #procedurecmds do
local pcmd = procedurecmds[_]
if #pcmd == 0 then
elseif _ == 1 then
local y
local block = "00"
for y = 1, 0x1D, 4 do
for _ = 1, #procedurecmds do
local pcmd = procedurecmds[_]
local config = pcmd:format(config1, y, config2)
dbg(('lf t55xx write b 0 d %s'):format(config))
config = tonumber(config,16)
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
local err = core.SendCommand(writecmd:getBytes())
if err then return oops(err) end
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
else
dbg(pcmd)
core.console( pcmd )
end
end
core.clearCommandBuffer()
end
print( string.rep('--',20) )
if #pcmd == 0 then
elseif _ == 1 then
local config = pcmd:format(config1, y, config2)
dbg(('lf t55xx write b 0 d %s'):format(config))
config = tonumber(config,16)
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
local err = core.SendCommand(writecmd:getBytes())
if err then return oops(err) end
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
else
dbg(pcmd)
core.console( pcmd )
end
end
core.clearCommandBuffer()
end
print( string.rep('--',20) )
end
local function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
print( string.rep('--',20) )
print( string.rep('--',20) )
-- Arguments for the script
for o, arg in getopt.getopt(args, 'h') do
if o == "h" then return help() end
end
-- Arguments for the script
for o, arg in getopt.getopt(args, 'h') do
if o == "h" then return help() end
end
core.clearCommandBuffer()
test()
print( string.rep('--',20) )
core.clearCommandBuffer()
test()
print( string.rep('--',20) )
end
main(args)

View file

@ -4,7 +4,7 @@ local bin = require('bin')
local utils = require('utils')
example =[[
1. script run test_t55x7_fsk
1. script run test_t55x7_fsk
]]
author = "Iceman"
usage = "script run test_t55x7_fsk"
@ -12,32 +12,32 @@ desc =[[
This script will program a T55x7 TAG with the configuration: block 0x00 data 0x000100
The outlined procedure is as following:
--ASK
00 00 80 40
--ASK
00 00 80 40
-- max 2 blocks
-- FSK1
-- bit rate
"lf t55xx write b 0 d 00007040"
"lf t55xx detect"
"lf t55xx info"
Loop:
change the configuretion block 0 with:
-xx 00 xxxx = RF/8
change the configuretion block 0 with:
-xx 00 xxxx = RF/8
-xx 04 xxxx = RF/16
-xx 08 xxxx = RF/32
-xx 0C xxxx = RF/40
-xx 10 xxxx = RF/50
-xx 14 xxxx = RF/64
-xx 18 xxxx = RF/100
-xx 1C xxxx = RF/128
-xx 08 xxxx = RF/32
-xx 0C xxxx = RF/40
-xx 10 xxxx = RF/50
-xx 14 xxxx = RF/64
-xx 18 xxxx = RF/100
-xx 1C xxxx = RF/128
testsuit for the ASK/MANCHESTER demod
Arguments:
-h : this help
-h : this help
]]
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
@ -48,93 +48,93 @@ local config1 = '00'
local config2 = '040'
local procedurecmds = {
[1] = '%s%02X%X%s',
[2] = 'lf t55xx detect',
[3] = 'lf t55xx info',
[1] = '%s%02X%X%s',
[2] = 'lf t55xx detect',
[3] = 'lf t55xx info',
}
---
---
-- A debug printout-function
local function dbg(args)
if not DEBUG then
return
end
if not DEBUG then
return
end
if type(args) == "table" then
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print("###", args)
end
end
---
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
local function oops(err)
print("ERROR: ",err)
print("ERROR: ",err)
end
---
---
-- Usage help
local function help()
print(desc)
print("Example usage")
print(example)
print(desc)
print("Example usage")
print(example)
end
--
-- Exit message
local function ExitMsg(msg)
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
end
local function test(modulation)
local y
local block = "00"
for y = 0x0, 0x1d, 0x4 do
for _ = 1, #procedurecmds do
local pcmd = procedurecmds[_]
if #pcmd == 0 then
elseif _ == 1 then
local y
local block = "00"
for y = 0x0, 0x1d, 0x4 do
for _ = 1, #procedurecmds do
local pcmd = procedurecmds[_]
local config = pcmd:format(config1, y, modulation, config2)
dbg(('lf t55xx write b 0 d %s'):format(config))
config = tonumber(config,16)
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
local err = core.SendCommand(writecmd:getBytes())
if err then return oops(err) end
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
if #pcmd == 0 then
else
dbg(pcmd)
core.console( pcmd )
end
end
core.clearCommandBuffer()
end
print( string.rep('--',20) )
elseif _ == 1 then
local config = pcmd:format(config1, y, modulation, config2)
dbg(('lf t55xx write b 0 d %s'):format(config))
config = tonumber(config,16)
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
local err = core.SendCommand(writecmd:getBytes())
if err then return oops(err) end
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
else
dbg(pcmd)
core.console( pcmd )
end
end
core.clearCommandBuffer()
end
print( string.rep('--',20) )
end
local function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
print( string.rep('--',20) )
print( string.rep('--',20) )
-- Arguments for the script
for o, arg in getopt.getopt(args, 'h') do
if o == "h" then return help() end
end
-- Arguments for the script
for o, arg in getopt.getopt(args, 'h') do
if o == "h" then return help() end
end
core.clearCommandBuffer()
test(4)
test(5)
test(6)
test(7)
print( string.rep('--',20) )
core.clearCommandBuffer()
test(4)
test(5)
test(6)
test(7)
print( string.rep('--',20) )
end
main(args)

View file

@ -4,8 +4,8 @@ local bin = require('bin')
local utils = require('utils')
example =[[
1. script run test_t55x7_psk
2. script run test_t55x7_psk -o
1. script run test_t55x7_psk
2. script run test_t55x7_psk -o
]]
author = "Iceman"
usage = "script run test_t55x7_psk"
@ -18,21 +18,21 @@ The outlined procedure is as following:
"lf t55xx info"
Loop OUTER:
change the configuretion block 0 with:
change the configuretion block 0 with:
-xxxx8xxx = PSK RF/2 with Manchester modulation
-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)
-xxxx3xxx = PSK RF/2 with PSk3 modulation (phase change on rising edge of input)
Loop INNER
for each outer configuration, also do
XXXXX0XX = PSK RF/2
XXXXX4XX = PSK RF/4
XXXXX8XX = PSK RF/8
Loop INNER
for each outer configuration, also do
XXXXX0XX = PSK RF/2
XXXXX4XX = PSK RF/4
XXXXX8XX = PSK RF/8
In all 12 individual test for the PSK demod
Arguments:
-h : this help
-h : this help
]]
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
@ -40,111 +40,111 @@ local DEBUG = true -- the debug flag
-- --BLOCK 0 = 00 08 80 40 PSK
-- -----------
-- 08------- bitrate
-- 8----- modulation PSK1
-- 0---- PSK ClockRate
-- 40 max 2 blocks
-- 08------- bitrate
-- 8----- modulation PSK1
-- 0---- PSK ClockRate
-- 40 max 2 blocks
local procedurecmds = {
[1] = '00%02X%X%X40',
[2] = 'lf t55xx detect',
[3] = 'lf t55xx info',
[1] = '00%02X%X%X40',
[2] = 'lf t55xx detect',
[3] = 'lf t55xx info',
}
---
---
-- A debug printout-function
local function dbg(args)
if not DEBUG then
return
end
if not DEBUG then
return
end
if type(args) == "table" then
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print("###", args)
end
end
---
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
local function oops(err)
print("ERROR: ",err)
print("ERROR: ",err)
end
---
---
-- Usage help
local function help()
print(desc)
print("Example usage")
print(example)
print(desc)
print("Example usage")
print(example)
end
--
-- Exit message
local function ExitMsg(msg)
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
end
local function test(modulation)
local bitrate
local clockrate
local block = "00"
for bitrate = 0x0, 0x1d, 0x4 do
for clockrate = 0,8,4 do
local bitrate
local clockrate
local block = "00"
for bitrate = 0x0, 0x1d, 0x4 do
for _ = 1, #procedurecmds do
local cmd = procedurecmds[_]
if #cmd == 0 then
elseif _ == 1 then
for clockrate = 0,8,4 do
dbg("Writing to T55x7 TAG")
for _ = 1, #procedurecmds do
local cmd = procedurecmds[_]
local config = cmd:format(bitrate, modulation, clockrate)
dbg(('lf t55xx write b 0 d %s'):format(config))
config = tonumber(config,16)
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
local err = core.SendCommand(writecmd:getBytes())
if err then return oops(err) end
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
else
dbg(cmd)
core.console( cmd )
end
end
core.clearCommandBuffer()
end
end
print( string.rep('--',20) )
if #cmd == 0 then
elseif _ == 1 then
dbg("Writing to T55x7 TAG")
local config = cmd:format(bitrate, modulation, clockrate)
dbg(('lf t55xx write b 0 d %s'):format(config))
config = tonumber(config,16)
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
local err = core.SendCommand(writecmd:getBytes())
if err then return oops(err) end
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
else
dbg(cmd)
core.console( cmd )
end
end
core.clearCommandBuffer()
end
end
print( string.rep('--',20) )
end
local function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
print( string.rep('--',20) )
print( string.rep('--',20) )
-- Arguments for the script
for o, arg in getopt.getopt(args, 'h') do
if o == "h" then return help() end
end
-- Arguments for the script
for o, arg in getopt.getopt(args, 'h') do
if o == "h" then return help() end
end
core.clearCommandBuffer()
core.clearCommandBuffer()
test(1) -- PSK1
--test(2) -- PSK2
--test(3) -- PSK3
print( string.rep('--',20) )
test(1) -- PSK1
--test(2) -- PSK2
--test(3) -- PSK3
print( string.rep('--',20) )
end
main(args)
-- Where it iterates over
-- Where it iterates over
-- xxxx8xxx = PSK RF/2 with Manchester modulation
-- 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)

View file

@ -11,10 +11,10 @@ local bor = bit32.bor
local band = bit32.band
example =[[
script run tnp3clone
script run tnp3clone -h
script run tnp3clone -l
script run tnp3clone -t aa00 -s 0030
script run tnp3clone
script run tnp3clone -h
script run tnp3clone -l
script run tnp3clone -t aa00 -s 0030
]]
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.
Arguments:
-h : this help
-l : list all known toy tokens
-t <data> : toytype id, 4hex symbols
-s <data> : subtype id, 4hex symbols
For fun, try the following subtype id:
0612 - Lightcore
0118 - Series 1
0138 - Series 2
0234 - Special
023c - Special
0020 - Swapforce
-h : this help
-l : list all known toy tokens
-t <data> : toytype id, 4hex symbols
-s <data> : subtype id, 4hex symbols
For fun, try the following subtype id:
0612 - Lightcore
0118 - Series 1
0138 - Series 2
0234 - Special
023c - Special
0020 - Swapforce
]]
-- This is only meant to be used when errors occur
local function oops(err)
print("ERROR: ",err)
print("ERROR: ",err)
end
-- Usage help
local function help()
print(desc)
print("Example usage")
print(example)
print(desc)
print("Example usage")
print(example)
end
local function waitCmd()
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,2000)
if response then
local count,cmd,arg0 = bin.unpack('LL',response)
if(arg0==1) then
local count,arg1,arg2,data = bin.unpack('LLH511',response,count)
return data:sub(1,32)
else
return nil, "Couldn't read block."
end
end
return nil, "No response from device"
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,2000)
if response then
local count,cmd,arg0 = bin.unpack('LL',response)
if(arg0==1) then
local count,arg1,arg2,data = bin.unpack('LLH511',response,count)
return data:sub(1,32)
else
return nil, "Couldn't read block."
end
end
return nil, "No response from device"
end
local function readblock( blocknum, keyA )
-- Read block N
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blocknum, arg2 = 0, arg3 = 0, data = keyA}
err = core.SendCommand(cmd:getBytes())
if err then return nil, err end
local block0, err = waitCmd()
if err then return nil, err end
return block0
-- Read block N
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blocknum, arg2 = 0, arg3 = 0, data = keyA}
err = core.SendCommand(cmd:getBytes())
if err then return nil, err end
local block0, err = waitCmd()
if err then return nil, err end
return block0
end
local function readmagicblock( blocknum )
-- Read block N
local CSETBLOCK_SINGLE_OPERATION = 0x1F
cmd = Command:new{cmd = cmds.CMD_MIFARE_CGETBLOCK, arg1 = CSETBLOCK_SINGLE_OPERATION, arg2 = 0, arg3 = blocknum}
err = core.SendCommand(cmd:getBytes())
if err then return nil, err end
local block0, err = waitCmd()
if err then return nil, err end
return block0
-- Read block N
local CSETBLOCK_SINGLE_OPERATION = 0x1F
cmd = Command:new{cmd = cmds.CMD_MIFARE_CGETBLOCK, arg1 = CSETBLOCK_SINGLE_OPERATION, arg2 = 0, arg3 = blocknum}
err = core.SendCommand(cmd:getBytes())
if err then return nil, err end
local block0, err = waitCmd()
if err then return nil, err end
return block0
end
local function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
local numBlocks = 64
local cset = 'hf mf csetbl '
local csetuid = 'hf mf csetuid '
local cget = 'hf mf cgetbl '
local empty = '00000000000000000000000000000000'
local AccAndKeyB = '7F0F0869000000000000'
local atqa = '0F01'
local sak = '81'
-- Defaults to Gusto
local toytype = 'C201'
local subtype = '0030'
local DEBUG = true
-- Arguments for the script
for o, a in getopt.getopt(args, 'ht:s:l') do
if o == "h" then return help() end
if o == "t" then toytype = a end
if o == "s" then subtype = a end
if o == "l" then return toys.List() end
end
print( string.rep('--',20) )
print( string.rep('--',20) )
if #toytype ~= 4 then return oops('[!] Wrong size - toytype. (4hex symbols)') end
if #subtype ~= 4 then return oops('[!] Wrong size - subtype. (4hex symbols)') end
local numBlocks = 64
local cset = 'hf mf csetbl '
local csetuid = 'hf mf csetuid '
local cget = 'hf mf cgetbl '
local empty = '00000000000000000000000000000000'
local AccAndKeyB = '7F0F0869000000000000'
local atqa = '0F01'
local sak = '81'
-- Defaults to Gusto
local toytype = 'C201'
local subtype = '0030'
local DEBUG = true
-- look up type, find & validate types
local item = toys.Find( toytype, subtype)
if item then
print( ('[+] Looking up input: Found %s - %s (%s)'):format(item[6],item[5], item[4]) )
else
print('[-] Didn\'t find item type. If you are sure about it, post on forum')
end
--15,16
--13-14
-- find tag
result, err = lib14a.read(false, true)
if not result then return oops(err) end
-- Arguments for the script
for o, a in getopt.getopt(args, 'ht:s:l') do
if o == "h" then return help() end
if o == "t" then toytype = a end
if o == "s" then subtype = a end
if o == "l" then return toys.List() end
end
-- load keys
local akeys = pre.GetAll(result.uid)
local keyA = akeys:sub(1, 12 )
if #toytype ~= 4 then return oops('[!] Wrong size - toytype. (4hex symbols)') end
if #subtype ~= 4 then return oops('[!] Wrong size - subtype. (4hex symbols)') end
local b0 = readblock(0, keyA)
if not b0 then
print('[-] failed reading block with factorydefault key. Trying chinese magic read.')
b0, err = readmagicblock(0)
if not b0 then
oops('[!] '..err)
return oops('[!] failed reading block with chinese magic command. Quitting...')
end
end
core.clearCommandBuffer()
-- look up type, find & validate types
local item = toys.Find( toytype, subtype)
if item then
print( ('[+] Looking up input: Found %s - %s (%s)'):format(item[6],item[5], item[4]) )
else
print('[-] Didn\'t find item type. If you are sure about it, post on forum')
end
--15,16
--13-14
-- wipe card.
local cmd = (csetuid..'%s %s %s w'):format(result.uid, atqa, sak)
core.console(cmd)
core.clearCommandBuffer()
local b1 = toytype..string.rep('00',10)..subtype
local calc = utils.Crc16(b0..b1)
local calcEndian = bor(rsh(calc,8), lsh(band(calc, 0xff), 8))
local cmd = (cset..'1 %s%04x'):format( b1, calcEndian)
core.console(cmd)
core.clearCommandBuffer()
local pos, key
for blockNo = 2, numBlocks-1, 1 do
pos = (math.floor( blockNo / 4 ) * 12)+1
key = akeys:sub(pos, pos + 11 )
if blockNo%4 == 3 then
cmd = ('%s %d %s%s'):format(cset,blockNo,key,AccAndKeyB)
core.console(cmd)
end
end
core.clearCommandBuffer()
-- Set sector trailer S0, since it has different access rights
cmd = ('%s 3 %s0f0f0f69000000000000'):format(cset, keyA)
core.console(cmd)
core.clearCommandBuffer()
-- find tag
result, err = lib14a.read(false, true)
if not result then return oops(err) end
-- load keys
local akeys = pre.GetAll(result.uid)
local keyA = akeys:sub(1, 12 )
local b0 = readblock(0, keyA)
if not b0 then
print('[-] failed reading block with factorydefault key. Trying chinese magic read.')
b0, err = readmagicblock(0)
if not b0 then
oops('[!] '..err)
return oops('[!] failed reading block with chinese magic command. Quitting...')
end
end
core.clearCommandBuffer()
-- wipe card.
local cmd = (csetuid..'%s %s %s w'):format(result.uid, atqa, sak)
core.console(cmd)
core.clearCommandBuffer()
local b1 = toytype..string.rep('00',10)..subtype
local calc = utils.Crc16(b0..b1)
local calcEndian = bor(rsh(calc,8), lsh(band(calc, 0xff), 8))
local cmd = (cset..'1 %s%04x'):format( b1, calcEndian)
core.console(cmd)
core.clearCommandBuffer()
local pos, key
for blockNo = 2, numBlocks-1, 1 do
pos = (math.floor( blockNo / 4 ) * 12)+1
key = akeys:sub(pos, pos + 11 )
if blockNo%4 == 3 then
cmd = ('%s %d %s%s'):format(cset,blockNo,key,AccAndKeyB)
core.console(cmd)
end
end
core.clearCommandBuffer()
-- Set sector trailer S0, since it has different access rights
cmd = ('%s 3 %s0f0f0f69000000000000'):format(cset, keyA)
core.console(cmd)
core.clearCommandBuffer()
end
main(args)

View file

@ -8,15 +8,15 @@ local dumplib = require('html_dumplib')
local toys = require('default_toys')
example =[[
script run tnp3dump
script run tnp3dump -n
script run tnp3dump -p
script run tnp3dump -k aabbccddeeff
script run tnp3dump -k aabbccddeeff -n
script run tnp3dump -o myfile
script run tnp3dump -n -o myfile
script run tnp3dump -p -o myfile
script run tnp3dump -k aabbccddeeff -n -o myfile
script run tnp3dump
script run tnp3dump -n
script run tnp3dump -p
script run tnp3dump -k aabbccddeeff
script run tnp3dump -k aabbccddeeff -n
script run tnp3dump -o myfile
script run tnp3dump -n -o myfile
script run tnp3dump -p -o myfile
script run tnp3dump -k aabbccddeeff -n -o myfile
]]
author = "Iceman"
usage = "script run tnp3dump -k <key> -n -p -o <filename>"
@ -24,262 +24,262 @@ desc =[[
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.
Arguments:
-h : this help
-k <key> : Sector 0 Key A.
-n : Use the nested cmd to find all keys
-p : Use the precalc to find all keys
-o : filename for the saved dumps
-h : this help
-k <key> : Sector 0 Key A.
-n : Use the nested cmd to find all keys
-p : Use the precalc to find all keys
-o : filename for the saved dumps
]]
local RANDOM = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20'
local TIMEOUT = 2500 -- Shouldn't take longer than 2 seconds
local DEBUG = false -- the debug flag
local numBlocks = 64
local numSectors = 16
---
---
-- A debug printout-function
function dbg(args)
if not DEBUG then return end
if not DEBUG then return end
if type(args) == "table" then
local i = 1
while result[i] do
dbg(result[i])
i = i+1
end
else
print("###", args)
end
end
---
local i = 1
while result[i] do
dbg(result[i])
i = i+1
end
else
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
function oops(err)
print("ERROR: ",err)
return nil,err
print("ERROR: ",err)
return nil,err
end
---
---
-- Usage help
function help()
print(desc)
print("Example usage")
print(example)
print(desc)
print("Example usage")
print(example)
end
--
-- Exit message
function ExitMsg(msg)
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
end
local function readdumpkeys(infile)
t = infile:read("*all")
len = string.len(t)
local len,hex = bin.unpack(("H%d"):format(len),t)
return hex
t = infile:read("*all")
len = string.len(t)
local len,hex = bin.unpack(("H%d"):format(len),t)
return hex
end
local function waitCmd()
local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT)
if response then
local count, cmd, arg0 = bin.unpack('LL',response)
if(arg0==1) then
local count,arg1,arg2,data = bin.unpack('LLH511',response,count)
return data:sub(1,32)
else
return nil, "Couldn't read block.. ["..arg0.."]"
end
end
return nil, 'No response from device'
local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT)
if response then
local count, cmd, arg0 = bin.unpack('LL',response)
if(arg0==1) then
local count,arg1,arg2,data = bin.unpack('LLH511',response,count)
return data:sub(1,32)
else
return nil, "Couldn't read block.. ["..arg0.."]"
end
end
return nil, 'No response from device'
end
local function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
local keyA
local cmd
local err
local useNested = false
local usePreCalc = false
local cmdReadBlockString = 'hf mf rdbl %d A %s'
local input = "dumpkeys.bin"
local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S");
print( string.rep('--',20) )
print( string.rep('--',20) )
-- Arguments for the script
for o, a in getopt.getopt(args, 'hk:npo:') do
if o == "h" then return help() end
if o == "k" then keyA = a end
if o == "n" then useNested = true end
if o == "p" then usePreCalc = true end
if o == "o" then outputTemplate = a end
end
-- validate input args.
keyA = keyA or '4b0b20107ccb'
if #(keyA) ~= 12 then
return oops( string.format('Wrong length of write key (was %d) expected 12', #keyA))
end
local keyA
local cmd
local err
local useNested = false
local usePreCalc = false
local cmdReadBlockString = 'hf mf rdbl %d A %s'
local input = "dumpkeys.bin"
local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S");
-- Turn off Debug
local cmdSetDbgOff = "hf mf dbg 0"
core.console( cmdSetDbgOff)
result, err = lib14a.read(false, true)
if not result then
return oops(err)
end
-- Arguments for the script
for o, a in getopt.getopt(args, 'hk:npo:') do
if o == "h" then return help() end
if o == "k" then keyA = a end
if o == "n" then useNested = true end
if o == "p" then usePreCalc = true end
if o == "o" then outputTemplate = a end
end
core.clearCommandBuffer()
-- Show tag info
print((' Found tag %s'):format(result.name))
-- validate input args.
keyA = keyA or '4b0b20107ccb'
if #(keyA) ~= 12 then
return oops( string.format('Wrong length of write key (was %d) expected 12', #keyA))
end
dbg(('Using keyA : %s'):format(keyA))
-- Turn off Debug
local cmdSetDbgOff = "hf mf dbg 0"
core.console( cmdSetDbgOff)
--Trying to find the other keys
if useNested then
core.console( ('hf mf nested 1 0 A %s d'):format(keyA) )
end
result, err = lib14a.read(false, true)
if not result then
return oops(err)
end
core.clearCommandBuffer()
local akeys = ''
if usePreCalc then
local pre = require('precalc')
akeys = pre.GetAll(result.uid)
dbg(akeys)
else
print('Loading dumpkeys.bin')
local hex, err = utils.ReadDumpFile(input)
if not hex then
return oops(err)
end
akeys = hex:sub(0,12*16)
end
-- Read block 0
dbg('Reading block 0')
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 0, arg2 = 0, arg3 = 0, data = keyA}
err = core.SendCommand(cmd:getBytes())
if err then return oops(err) end
local block0, err = waitCmd()
if err then return oops(err) end
core.clearCommandBuffer()
-- Read block 1
dbg('Reading block 1')
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 1, arg2 = 0, arg3 = 0, data = keyA}
err = core.SendCommand(cmd:getBytes())
if err then return oops(err) end
local block1, err = waitCmd()
if err then return oops(err) end
core.clearCommandBuffer()
core.clearCommandBuffer()
local tmpHash = block0..block1..'%02x'..RANDOM
-- Show tag info
print((' Found tag %s'):format(result.name))
local key
local pos = 0
local blockNo
local blocks = {}
-- main loop
io.write('Reading blocks > ')
for blockNo = 0, numBlocks-1, 1 do
dbg(('Using keyA : %s'):format(keyA))
io.flush()
if core.ukbhit() then
print("aborted by user")
break
end
core.clearCommandBuffer()
pos = (math.floor( blockNo / 4 ) * 12)+1
key = akeys:sub(pos, pos + 11 )
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blockNo ,arg2 = 0,arg3 = 0, data = key}
local err = core.SendCommand(cmd:getBytes())
if err then return oops(err) end
local blockdata, err = waitCmd()
if err then return oops(err) end
--Trying to find the other keys
if useNested then
core.console( ('hf mf nested 1 0 A %s d'):format(keyA) )
end
core.clearCommandBuffer()
local akeys = ''
if usePreCalc then
local pre = require('precalc')
akeys = pre.GetAll(result.uid)
dbg(akeys)
else
print('Loading dumpkeys.bin')
local hex, err = utils.ReadDumpFile(input)
if not hex then
return oops(err)
end
akeys = hex:sub(0,12*16)
end
-- Read block 0
dbg('Reading block 0')
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 0, arg2 = 0, arg3 = 0, data = keyA}
err = core.SendCommand(cmd:getBytes())
if err then return oops(err) end
local block0, err = waitCmd()
if err then return oops(err) end
core.clearCommandBuffer()
-- Read block 1
dbg('Reading block 1')
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 1, arg2 = 0, arg3 = 0, data = keyA}
err = core.SendCommand(cmd:getBytes())
if err then return oops(err) end
local block1, err = waitCmd()
if err then return oops(err) end
core.clearCommandBuffer()
local tmpHash = block0..block1..'%02x'..RANDOM
local key
local pos = 0
local blockNo
local blocks = {}
-- main loop
io.write('Reading blocks > ')
for blockNo = 0, numBlocks-1, 1 do
io.flush()
if core.ukbhit() then
print("aborted by user")
break
end
core.clearCommandBuffer()
pos = (math.floor( blockNo / 4 ) * 12)+1
key = akeys:sub(pos, pos + 11 )
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blockNo ,arg2 = 0,arg3 = 0, data = key}
local err = core.SendCommand(cmd:getBytes())
if err then return oops(err) end
local blockdata, err = waitCmd()
if err then return oops(err) end
if blockNo%4 ~= 3 then
if blockNo < 8 then
-- Block 0-7 not encrypted
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata)
else
-- blocks with zero not encrypted.
if string.find(blockdata, '^0+$') then
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata)
else
local baseStr = utils.ConvertHexToAscii(tmpHash:format(blockNo))
local key = md5.sumhexa(baseStr)
local aestest = core.aes128_decrypt(key, blockdata)
local hex = utils.ConvertAsciiToHex(aestest)
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,hex)
io.write(blockNo..',')
end
end
else
-- Sectorblocks, not encrypted
blocks[blockNo+1] = ('%02d :: %s%s'):format(blockNo,key,blockdata:sub(13,32))
end
end
io.write('\n')
core.clearCommandBuffer()
-- Print results
local bindata = {}
local emldata = ''
if blockNo%4 ~= 3 then
for _,s in pairs(blocks) do
local slice = s:sub(8,#s)
local str = utils.ConvertHexToAscii(slice)
emldata = emldata..slice..'\n'
for c in (str):gmatch('.') do
bindata[#bindata+1] = c
end
end
if blockNo < 8 then
-- Block 0-7 not encrypted
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata)
else
-- blocks with zero not encrypted.
if string.find(blockdata, '^0+$') then
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata)
else
local baseStr = utils.ConvertHexToAscii(tmpHash:format(blockNo))
local key = md5.sumhexa(baseStr)
local aestest = core.aes128_decrypt(key, blockdata)
local hex = utils.ConvertAsciiToHex(aestest)
print( string.rep('--',20) )
local uid = block0:sub(1,8)
local toytype = block1:sub(1,4)
local cardidLsw = block1:sub(9,16)
local cardidMsw = block1:sub(16,24)
local cardid = block1:sub(9,24)
local subtype = block1:sub(25,28)
-- Write dump to files
if not DEBUG then
local foo = dumplib.SaveAsBinary(bindata, outputTemplate..'-'..uid..'.bin')
print(("Wrote a BIN dump to: %s"):format(foo))
local bar = dumplib.SaveAsText(emldata, outputTemplate..'-'..uid..'.eml')
print(("Wrote a EML dump to: %s"):format(bar))
end
print( string.rep('--',20) )
-- Show info
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,hex)
io.write(blockNo..',')
end
end
else
-- Sectorblocks, not encrypted
blocks[blockNo+1] = ('%02d :: %s%s'):format(blockNo,key,blockdata:sub(13,32))
end
end
io.write('\n')
local item = toys.Find(toytype, subtype)
if item then
print((' ITEM TYPE : %s - %s (%s)'):format(item[6],item[5], item[4]) )
else
print((' ITEM TYPE : 0x%s 0x%s'):format(toytype, subtype))
end
core.clearCommandBuffer()
print( (' UID : 0x%s'):format(uid) )
print( (' CARDID : 0x%s'):format(cardid ) )
print( string.rep('--',20) )
core.clearCommandBuffer()
-- Print results
local bindata = {}
local emldata = ''
for _,s in pairs(blocks) do
local slice = s:sub(8,#s)
local str = utils.ConvertHexToAscii(slice)
emldata = emldata..slice..'\n'
for c in (str):gmatch('.') do
bindata[#bindata+1] = c
end
end
print( string.rep('--',20) )
local uid = block0:sub(1,8)
local toytype = block1:sub(1,4)
local cardidLsw = block1:sub(9,16)
local cardidMsw = block1:sub(16,24)
local cardid = block1:sub(9,24)
local subtype = block1:sub(25,28)
-- Write dump to files
if not DEBUG then
local foo = dumplib.SaveAsBinary(bindata, outputTemplate..'-'..uid..'.bin')
print(("Wrote a BIN dump to: %s"):format(foo))
local bar = dumplib.SaveAsText(emldata, outputTemplate..'-'..uid..'.eml')
print(("Wrote a EML dump to: %s"):format(bar))
end
print( string.rep('--',20) )
-- Show info
local item = toys.Find(toytype, subtype)
if item then
print((' ITEM TYPE : %s - %s (%s)'):format(item[6],item[5], item[4]) )
else
print((' ITEM TYPE : 0x%s 0x%s'):format(toytype, subtype))
end
print( (' UID : 0x%s'):format(uid) )
print( (' CARDID : 0x%s'):format(cardid ) )
print( string.rep('--',20) )
core.clearCommandBuffer()
end
main(args)

View file

@ -6,11 +6,11 @@ local utils = require('utils')
local md5 = require('md5')
local toys = require('default_toys')
local pre = require('precalc')
example =[[
1. script run tnp3sim
2. script run tnp3sim -m
3. script run tnp3sim -m -i myfile
1. script run tnp3sim
2. script run tnp3sim -m
3. script run tnp3sim -m -i myfile
]]
author = "Iceman"
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"
Arguments:
-h : this help
-m : Maxed out items (experimental)
-i : filename for the datadump to read (bin)
-h : this help
-m : Maxed out items (experimental)
-i : filename for the datadump to read (bin)
]]
]]
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
local DEBUG = true -- the debug flag
@ -40,239 +40,239 @@ local char = string.char
local sub = string.sub
local format = string.format
---
---
-- A debug printout-function
function dbg(args)
if not DEBUG then return end
if not DEBUG then return end
if type(args) == "table" then
local i = 1
while result[i] do
dbg(result[i])
i = i+1
end
else
print("###", args)
end
end
---
local i = 1
while result[i] do
dbg(result[i])
i = i+1
end
else
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
function oops(err)
print("ERROR: ",err)
return nil,err
print("ERROR: ",err)
return nil,err
end
---
---
-- Usage help
function help()
print(desc)
print("Example usage")
print(example)
print(desc)
print("Example usage")
print(example)
end
--
-- Exit message
function ExitMsg(msg)
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
end
local function writedumpfile(infile)
t = infile:read("*all")
len = string.len(t)
local len,hex = bin.unpack(("H%d"):format(len),t)
return hex
t = infile:read("*all")
len = string.len(t)
local len,hex = bin.unpack(("H%d"):format(len),t)
return hex
end
-- blocks with data
-- there are two dataareas, in block 8 or block 36, ( 1==8 ,
-- checksum type = 0, 1, 2, 3
local function GetCheckSum(blocks, dataarea, chksumtype)
local crc
local area = 36
if dataarea == 1 then
area = 8
end
if chksumtype == 0 then
crc = blocks[1]:sub(29,32)
elseif chksumtype == 1 then
crc = blocks[area]:sub(29,32)
elseif chksumtype == 2 then
crc = blocks[area]:sub(25,28)
elseif chksumtype == 3 then
crc = blocks[area]:sub(21,24)
end
return utils.SwapEndianness(crc,16)
local crc
local area = 36
if dataarea == 1 then
area = 8
end
if chksumtype == 0 then
crc = blocks[1]:sub(29,32)
elseif chksumtype == 1 then
crc = blocks[area]:sub(29,32)
elseif chksumtype == 2 then
crc = blocks[area]:sub(25,28)
elseif chksumtype == 3 then
crc = blocks[area]:sub(21,24)
end
return utils.SwapEndianness(crc,16)
end
local function SetAllCheckSum(blocks)
print('Updating all checksums')
SetCheckSum(blocks, 3)
SetCheckSum(blocks, 2)
SetCheckSum(blocks, 1)
SetCheckSum(blocks, 0)
print('Updating all checksums')
SetCheckSum(blocks, 3)
SetCheckSum(blocks, 2)
SetCheckSum(blocks, 1)
SetCheckSum(blocks, 0)
end
local function SetCheckSum(blocks, chksumtype)
if blocks == nil then return nil, 'Argument \"blocks\" nil' end
local newcrc
local area1 = 8
local area2 = 36
if chksumtype == 0 then
newcrc = ('%04X'):format(CalcCheckSum(blocks,1,0))
blocks[1] = blocks[1]:sub(1,28)..newcrc:sub(3,4)..newcrc:sub(1,2)
elseif chksumtype == 1 then
newcrc = ('%04X'):format(CalcCheckSum(blocks,1,1))
blocks[area1] = blocks[area1]:sub(1,28)..newcrc:sub(3,4)..newcrc:sub(1,2)
newcrc = ('%04X'):format(CalcCheckSum(blocks,2,1))
blocks[area2] = blocks[area2]:sub(1,28)..newcrc:sub(3,4)..newcrc:sub(1,2)
elseif chksumtype == 2 then
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)
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)
elseif chksumtype == 3 then
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)
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)
end
if blocks == nil then return nil, 'Argument \"blocks\" nil' end
local newcrc
local area1 = 8
local area2 = 36
if chksumtype == 0 then
newcrc = ('%04X'):format(CalcCheckSum(blocks,1,0))
blocks[1] = blocks[1]:sub(1,28)..newcrc:sub(3,4)..newcrc:sub(1,2)
elseif chksumtype == 1 then
newcrc = ('%04X'):format(CalcCheckSum(blocks,1,1))
blocks[area1] = blocks[area1]:sub(1,28)..newcrc:sub(3,4)..newcrc:sub(1,2)
newcrc = ('%04X'):format(CalcCheckSum(blocks,2,1))
blocks[area2] = blocks[area2]:sub(1,28)..newcrc:sub(3,4)..newcrc:sub(1,2)
elseif chksumtype == 2 then
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)
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)
elseif chksumtype == 3 then
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)
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)
end
end
function CalcCheckSum(blocks, dataarea, chksumtype)
local area = 36
if dataarea == 1 then
area = 8
end
if chksumtype == 0 then
data = blocks[0]..blocks[1]:sub(1,28)
elseif chksumtype == 1 then
data = blocks[area]:sub(1,28)..'0500'
elseif chksumtype == 2 then
data = blocks[area+1]..blocks[area+2]..blocks[area+4]
elseif chksumtype == 3 then
data = blocks[area+5]..blocks[area+6]..blocks[area+8]..string.rep('00',0xe0)
end
return utils.Crc16(data)
local area = 36
if dataarea == 1 then
area = 8
end
if chksumtype == 0 then
data = blocks[0]..blocks[1]:sub(1,28)
elseif chksumtype == 1 then
data = blocks[area]:sub(1,28)..'0500'
elseif chksumtype == 2 then
data = blocks[area+1]..blocks[area+2]..blocks[area+4]
elseif chksumtype == 3 then
data = blocks[area+5]..blocks[area+6]..blocks[area+8]..string.rep('00',0xe0)
end
return utils.Crc16(data)
end
local function ValidateCheckSums(blocks)
print(' Validating checksums')
local isOk, crc, calc
-- Checksum Type 0
crc = GetCheckSum(blocks,1,0)
calc = CalcCheckSum(blocks, 1, 0)
if crc == calc then isOk='Ok' else isOk = 'Error' end
io.write( ('TYPE 0 : %04x = %04x -- %s\n'):format(crc,calc,isOk))
print(' Validating checksums')
-- Checksum Type 1 (DATAAREAHEADER 1)
crc = GetCheckSum(blocks,1,1)
calc = CalcCheckSum(blocks,1,1)
if crc == calc then isOk='Ok' else isOk = 'Error' end
io.write( ('TYPE 1 area 1: %04x = %04x -- %s\n'):format(crc,calc,isOk))
-- Checksum Type 1 (DATAAREAHEADER 2)
crc = GetCheckSum(blocks,2,1)
calc = CalcCheckSum(blocks,2,1)
if crc == calc then isOk='Ok' else isOk = 'Error' end
io.write( ('TYPE 1 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk))
-- Checksum Type 2 (DATAAREA 1)
crc = GetCheckSum(blocks,1,2)
calc = CalcCheckSum(blocks,1,2)
if crc == calc then isOk='Ok' else isOk = 'Error' end
io.write( ('TYPE 2 area 1: %04x = %04x -- %s\n'):format(crc,calc,isOk))
local isOk, crc, calc
-- Checksum Type 0
crc = GetCheckSum(blocks,1,0)
calc = CalcCheckSum(blocks, 1, 0)
if crc == calc then isOk='Ok' else isOk = 'Error' end
io.write( ('TYPE 0 : %04x = %04x -- %s\n'):format(crc,calc,isOk))
-- Checksum Type 2 (DATAAREA 2)
crc = GetCheckSum(blocks,2,2)
calc = CalcCheckSum(blocks,2,2)
if crc == calc then isOk='Ok' else isOk = 'Error' end
io.write( ('TYPE 2 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk))
-- Checksum Type 1 (DATAAREAHEADER 1)
crc = GetCheckSum(blocks,1,1)
calc = CalcCheckSum(blocks,1,1)
if crc == calc then isOk='Ok' else isOk = 'Error' end
io.write( ('TYPE 1 area 1: %04x = %04x -- %s\n'):format(crc,calc,isOk))
-- Checksum Type 3 (DATAAREA 1)
crc = GetCheckSum(blocks,1,3)
calc = CalcCheckSum(blocks,1,3)
if crc == calc then isOk='Ok' else isOk = 'Error' end
io.write( ('TYPE 3 area 1: %04x = %04x -- %s\n'):format(crc,calc,isOk))
-- Checksum Type 1 (DATAAREAHEADER 2)
crc = GetCheckSum(blocks,2,1)
calc = CalcCheckSum(blocks,2,1)
if crc == calc then isOk='Ok' else isOk = 'Error' end
io.write( ('TYPE 1 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk))
-- Checksum Type 3 (DATAAREA 2)
crc = GetCheckSum(blocks,2,3)
calc = CalcCheckSum(blocks,2,3)
if crc == calc then isOk='Ok' else isOk = 'Error' end
io.write( ('TYPE 3 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk))
-- Checksum Type 2 (DATAAREA 1)
crc = GetCheckSum(blocks,1,2)
calc = CalcCheckSum(blocks,1,2)
if crc == calc then isOk='Ok' else isOk = 'Error' end
io.write( ('TYPE 2 area 1: %04x = %04x -- %s\n'):format(crc,calc,isOk))
-- Checksum Type 2 (DATAAREA 2)
crc = GetCheckSum(blocks,2,2)
calc = CalcCheckSum(blocks,2,2)
if crc == calc then isOk='Ok' else isOk = 'Error' end
io.write( ('TYPE 2 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk))
-- Checksum Type 3 (DATAAREA 1)
crc = GetCheckSum(blocks,1,3)
calc = CalcCheckSum(blocks,1,3)
if crc == calc then isOk='Ok' else isOk = 'Error' end
io.write( ('TYPE 3 area 1: %04x = %04x -- %s\n'):format(crc,calc,isOk))
-- Checksum Type 3 (DATAAREA 2)
crc = GetCheckSum(blocks,2,3)
calc = CalcCheckSum(blocks,2,3)
if crc == calc then isOk='Ok' else isOk = 'Error' end
io.write( ('TYPE 3 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk))
end
local function AddKey(keys, blockNo, data)
local pos = (math.floor( blockNo / 4 ) * 12)+1
local key = keys:sub(pos, pos + 11 )
return key..data:sub(13)
local pos = (math.floor( blockNo / 4 ) * 12)+1
local key = keys:sub(pos, pos + 11 )
return key..data:sub(13)
end
local function LoadEmulator(uid, blocks)
print('Sending dumpdata to emulator memory')
local keys = pre.GetAll(uid)
local cmd, blockdata
for _,b in pairs(blocks) do
blockdata = b
if _%4 ~= 3 then
if (_ >= 8 and _<=21) or (_ >= 36 and _<=49) then
local base = ('%s%s%02x%s'):format(blocks[0], blocks[1], _ , RANDOM)
local baseStr = utils.ConvertHexToAscii(base)
local key = md5.sumhexa(baseStr)
local enc = core.aes128_encrypt(key, blockdata)
blockdata = utils.ConvertAsciiToHex(enc)
io.write( _..',')
end
else
-- add keys if not existing..
if ( blockdata:sub(1,12) == '000000000000' ) then
blockdata = AddKey(keys, _, blockdata)
end
end
core.clearCommandBuffer()
cmd = Command:new{cmd = cmds.CMD_MIFARE_EML_MEMSET, arg1 = _ ,arg2 = 1,arg3 = 16, data = blockdata}
local err = core.SendCommand(cmd:getBytes())
if err then return err end
end
io.write('\n')
print('Sending dumpdata to emulator memory')
local keys = pre.GetAll(uid)
local cmd, blockdata
for _,b in pairs(blocks) do
blockdata = b
if _%4 ~= 3 then
if (_ >= 8 and _<=21) or (_ >= 36 and _<=49) then
local base = ('%s%s%02x%s'):format(blocks[0], blocks[1], _ , RANDOM)
local baseStr = utils.ConvertHexToAscii(base)
local key = md5.sumhexa(baseStr)
local enc = core.aes128_encrypt(key, blockdata)
blockdata = utils.ConvertAsciiToHex(enc)
io.write( _..',')
end
else
-- add keys if not existing..
if ( blockdata:sub(1,12) == '000000000000' ) then
blockdata = AddKey(keys, _, blockdata)
end
end
core.clearCommandBuffer()
cmd = Command:new{cmd = cmds.CMD_MIFARE_EML_MEMSET, arg1 = _ ,arg2 = 1,arg3 = 16, data = blockdata}
local err = core.SendCommand(cmd:getBytes())
if err then return err end
end
io.write('\n')
end
local function Num2Card(m, l)
local k = {
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
}
local msw = tonumber(utils.SwapEndiannessStr(m,32),16)
local lsw = tonumber(utils.SwapEndiannessStr(l,32),16)
local k = {
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
}
local msw = tonumber(utils.SwapEndiannessStr(m,32),16)
local lsw = tonumber(utils.SwapEndiannessStr(l,32),16)
if msw > 0x17ea1 then
return "too big"
end
if msw > 0x17ea1 then
return "too big"
end
if msw == 0x17ea1 and lsw > 0x8931fee8 then
return "out of range"
end
if msw == 0x17ea1 and lsw > 0x8931fee8 then
return "out of range"
end
local s = ""
local index
for i = 1,10 do
index, msw, lsw = DivideByK( msw, lsw)
if ( index <= 1 ) then
s = char(k[index]) .. s
else
s = char(k[index-1]) .. s
end
print (index-1, msw, lsw)
end
local s = ""
local index
for i = 1,10 do
index, msw, lsw = DivideByK( msw, lsw)
if ( index <= 1 ) then
s = char(k[index]) .. s
else
s = char(k[index-1]) .. s
end
print (index-1, msw, lsw)
end
return s
end
--33LRT-LM9Q9
@ -289,43 +289,43 @@ end
function DivideByK(msw, lsw)
local lowLSW
local highLSW
local remainder = 0
local RADIX = 29
local lowLSW
local highLSW
local remainder = 0
local RADIX = 29
--local num = 0 | band( rshift(msw,16), 0xffff)
local num = band( rshift(msw, 16), 0xffff)
--highLSW = 0 | lshift( (num / RADIX) , 16)
highLSW = lshift( (num / RADIX) , 16)
remainder = num % RADIX
--local num = 0 | band( rshift(msw,16), 0xffff)
local num = band( rshift(msw, 16), 0xffff)
num = bor( lshift(remainder,16), band(msw, 0xffff))
--highLSW = 0 | lshift( (num / RADIX) , 16)
highLSW = lshift( (num / RADIX) , 16)
remainder = num % RADIX
--highLSW |= num / RADIX
highLSW = highLSW or (num / RADIX)
remainder = num % RADIX
num = bor( lshift(remainder,16), band(msw, 0xffff))
num = bor( lshift(remainder,16), ( band(rshift(lsw,16), 0xffff)))
--highLSW |= num / RADIX
highLSW = highLSW or (num / RADIX)
remainder = num % RADIX
--lowLSW = 0 | (num / RADIX) << 16
lowLSW = 0 or (lshift( (num / RADIX), 16))
remainder = num % RADIX
num = bor( lshift(remainder,16), ( band(rshift(lsw,16), 0xffff)))
num = bor( lshift(remainder,16) , band(lsw, 0xffff) )
--lowLSW = 0 | (num / RADIX) << 16
lowLSW = 0 or (lshift( (num / RADIX), 16))
remainder = num % RADIX
num = bor( lshift(remainder,16) , band(lsw, 0xffff) )
lowLSW = bor(lowLSW, (num / RADIX))
remainder = num % RADIX
return remainder, highLSW, lowLSW
-- uint num = 0 | (msw >> 16) & 0xffff;
lowLSW = bor(lowLSW, (num / RADIX))
remainder = num % RADIX
return remainder, highLSW, lowLSW
-- uint num = 0 | (msw >> 16) & 0xffff;
-- highLSW = 0 | (num / RADIX) << 16;
-- remainder = num % RADIX;
-- num = (remainder << 16) | (msw & 0xffff);
-- highLSW |= num / RADIX;
-- remainder = num % RADIX;
@ -343,147 +343,147 @@ end
local function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
local result, err, hex
local maxed = false
local inputTemplate = "dumpdata.bin"
local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M");
-- Arguments for the script
for o, a in getopt.getopt(args, 'hmi:o:') do
if o == "h" then return help() end
if o == "m" then maxed = true end
if o == "o" then outputTemplate = a end
if o == "i" then inputTemplate = a end
end
-- Turn off Debug
local cmdSetDbgOff = "hf mf dbg 0"
core.console( cmdSetDbgOff)
-- Load dump.bin file
print( (' Load data from %s'):format(inputTemplate))
hex, err = utils.ReadDumpFile(inputTemplate)
if not hex then return oops(err) end
local blocks = {}
local blockindex = 0
for i = 1, #hex, 32 do
blocks[blockindex] = hex:sub(i,i+31)
blockindex = blockindex + 1
end
print( string.rep('--',20) )
print( string.rep('--',20) )
if DEBUG then ValidateCheckSums(blocks) end
--
print( string.rep('--',20) )
print(' Gathering info')
local uid = blocks[0]:sub(1,8)
local toytype = blocks[1]:sub(1,4)
local cardidLsw = blocks[1]:sub(9,16)
local cardidMsw = blocks[1]:sub(17,24)
local subtype = blocks[1]:sub(25,28)
local result, err, hex
local maxed = false
local inputTemplate = "dumpdata.bin"
local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M");
-- Show info
print( string.rep('--',20) )
local item = toys.Find( toytype, subtype)
if item then
local itemStr = ('%s - %s (%s)'):format(item[6],item[5], item[4])
print(' ITEM TYPE : '..itemStr )
else
print( (' ITEM TYPE : 0x%s 0x%s'):format(toytype, subtype) )
end
print( (' UID : 0x%s'):format(uid) )
print( (' CARDID : 0x%s %s [%s]'):format(
cardidMsw,cardidLsw,
--Num2Card(cardidMsw, cardidLsw))
'')
)
print( string.rep('--',20) )
-- Arguments for the script
for o, a in getopt.getopt(args, 'hmi:o:') do
if o == "h" then return help() end
if o == "m" then maxed = true end
if o == "o" then outputTemplate = a end
if o == "i" then inputTemplate = a end
end
-- Turn off Debug
local cmdSetDbgOff = "hf mf dbg 0"
core.console( cmdSetDbgOff)
-- Load dump.bin file
print( (' Load data from %s'):format(inputTemplate))
hex, err = utils.ReadDumpFile(inputTemplate)
if not hex then return oops(err) end
local blocks = {}
local blockindex = 0
for i = 1, #hex, 32 do
blocks[blockindex] = hex:sub(i,i+31)
blockindex = blockindex + 1
end
if DEBUG then ValidateCheckSums(blocks) end
--
print( string.rep('--',20) )
print(' Gathering info')
local uid = blocks[0]:sub(1,8)
local toytype = blocks[1]:sub(1,4)
local cardidLsw = blocks[1]:sub(9,16)
local cardidMsw = blocks[1]:sub(17,24)
local subtype = blocks[1]:sub(25,28)
-- Show info
print( string.rep('--',20) )
local item = toys.Find( toytype, subtype)
if item then
local itemStr = ('%s - %s (%s)'):format(item[6],item[5], item[4])
print(' ITEM TYPE : '..itemStr )
else
print( (' ITEM TYPE : 0x%s 0x%s'):format(toytype, subtype) )
end
print( (' UID : 0x%s'):format(uid) )
print( (' CARDID : 0x%s %s [%s]'):format(
cardidMsw,cardidLsw,
--Num2Card(cardidMsw, cardidLsw))
'')
)
print( string.rep('--',20) )
-- Experience should be:
local experience = blocks[8]:sub(1,6)
print(('Experience : %d'):format(utils.SwapEndianness(experience,16)))
local money = blocks[8]:sub(7,10)
print(('Money : %d'):format(utils.SwapEndianness(money,16)))
-- Experience should be:
local experience = blocks[8]:sub(1,6)
print(('Experience : %d'):format(utils.SwapEndianness(experience,16)))
--
-- Sequence number
local seqnum = blocks[8]:sub(18,19)
print(('Sequence number : %d'):format( tonumber(seqnum,16)))
local fairy = blocks[9]:sub(1,8)
--FD0F = Left, FF0F = Right
local path = 'not choosen'
if fairy:sub(2,2) == 'D' then
path = 'Left'
elseif fairy:sub(2,2) == 'F' then
path = 'Right'
end
print(('Fairy : %d [Path: %s] '):format(utils.SwapEndianness(fairy,24),path))
local hat = blocks[9]:sub(8,11)
print(('Hat : %d'):format(utils.SwapEndianness(hat,16)))
local money = blocks[8]:sub(7,10)
print(('Money : %d'):format(utils.SwapEndianness(money,16)))
local level = blocks[13]:sub(27,28)
print(('LEVEL : %d'):format( tonumber(level,16)))
--
--local health = blocks[]:sub();
--print(('Health : %d'):format( tonumber(health,16))
--0x0D 0x29 0x0A 0x02 16-bit hero points value. Maximum 100.
local heropoints = blocks[13]:sub(20,23)
print(('Hero points : %d'):format(utils.SwapEndianness(heropoints,16)))
-- Sequence number
local seqnum = blocks[8]:sub(18,19)
print(('Sequence number : %d'):format( tonumber(seqnum,16)))
--0x10 0x2C 0x0C 0x04 32 bit flag value indicating heroic challenges completed.
local challenges = blocks[16]:sub(25,32)
print(('Finished hero challenges : %d'):format(utils.SwapEndianness(challenges,32)))
-- Character Name
local name1 = blocks[10]:sub(1,32)
local name2 = blocks[12]:sub(1,32)
print('Custom name : '..utils.ConvertHexToAscii(name1..name2))
if maxed then
print('Lets try to max out some values')
-- max out money, experience
--print (blocks[8])
blocks[8] = 'FFFFFF'..'FFFF'..blocks[8]:sub(11,32)
blocks[36] = 'FFFFFF'..'FFFF'..blocks[36]:sub(11,32)
--print (blocks[8])
-- max out hero challenges
--print (blocks[16])
blocks[16] = blocks[16]:sub(1,24)..'FFFFFFFF'
blocks[44] = blocks[44]:sub(1,24)..'FFFFFFFF'
--print (blocks[16])
-- max out heropoints
--print (blocks[13])
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)
--print (blocks[13])
-- Update Checksums
SetAllCheckSum(blocks)
local fairy = blocks[9]:sub(1,8)
--FD0F = Left, FF0F = Right
local path = 'not choosen'
if fairy:sub(2,2) == 'D' then
path = 'Left'
elseif fairy:sub(2,2) == 'F' then
path = 'Right'
end
print(('Fairy : %d [Path: %s] '):format(utils.SwapEndianness(fairy,24),path))
-- Validate Checksums
ValidateCheckSums(blocks)
end
local hat = blocks[9]:sub(8,11)
print(('Hat : %d'):format(utils.SwapEndianness(hat,16)))
--Load dumpdata to emulator memory
if DEBUG then
err = LoadEmulator(uid, blocks)
if err then return oops(err) end
core.clearCommandBuffer()
print('The simulation is now prepared.\n --> run \"hf mf sim u '..uid..'\" <--')
end
local level = blocks[13]:sub(27,28)
print(('LEVEL : %d'):format( tonumber(level,16)))
--local health = blocks[]:sub();
--print(('Health : %d'):format( tonumber(health,16))
--0x0D 0x29 0x0A 0x02 16-bit hero points value. Maximum 100.
local heropoints = blocks[13]:sub(20,23)
print(('Hero points : %d'):format(utils.SwapEndianness(heropoints,16)))
--0x10 0x2C 0x0C 0x04 32 bit flag value indicating heroic challenges completed.
local challenges = blocks[16]:sub(25,32)
print(('Finished hero challenges : %d'):format(utils.SwapEndianness(challenges,32)))
-- Character Name
local name1 = blocks[10]:sub(1,32)
local name2 = blocks[12]:sub(1,32)
print('Custom name : '..utils.ConvertHexToAscii(name1..name2))
if maxed then
print('Lets try to max out some values')
-- max out money, experience
--print (blocks[8])
blocks[8] = 'FFFFFF'..'FFFF'..blocks[8]:sub(11,32)
blocks[36] = 'FFFFFF'..'FFFF'..blocks[36]:sub(11,32)
--print (blocks[8])
-- max out hero challenges
--print (blocks[16])
blocks[16] = blocks[16]:sub(1,24)..'FFFFFFFF'
blocks[44] = blocks[44]:sub(1,24)..'FFFFFFFF'
--print (blocks[16])
-- max out heropoints
--print (blocks[13])
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)
--print (blocks[13])
-- Update Checksums
SetAllCheckSum(blocks)
-- Validate Checksums
ValidateCheckSums(blocks)
end
--Load dumpdata to emulator memory
if DEBUG then
err = LoadEmulator(uid, blocks)
if err then return oops(err) end
core.clearCommandBuffer()
print('The simulation is now prepared.\n --> run \"hf mf sim u '..uid..'\" <--')
end
end
main(args)

View file

@ -5,122 +5,122 @@ local utils = require('utils')
local dumplib = require('html_dumplib')
example =[[
1. script run tracetest
1. script run tracetest
]]
author = "Iceman"
usage = "script run tracetest"
desc =[[
This script will load several traces files in ../traces/ folder and do
This script will load several traces files in ../traces/ folder and do
"data load"
"lf search 1 u"
"lf search 1 u"
The following tracefiles will be loaded:
The following tracefiles will be loaded:
em*.pm3
m*.pm3
Arguments:
-h : this help
-h : this help
]]
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
local DEBUG = true -- the debug flag
---
---
-- A debug printout-function
function dbg(args)
if not DEBUG then
return
end
if not DEBUG then
return
end
if type(args) == "table" then
local i = 1
while result[i] do
dbg(result[i])
i = i+1
end
else
print("###", args)
end
end
---
local i = 1
while result[i] do
dbg(result[i])
i = i+1
end
else
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
function oops(err)
print("ERROR: ",err)
print("ERROR: ",err)
end
---
---
-- Usage help
function help()
print(desc)
print("Example usage")
print(example)
print(desc)
print("Example usage")
print(example)
end
--
-- Exit message
function ExitMsg(msg)
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
end
local function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
local cmdDataLoad = 'data load %s';
local tracesEM = "find '../traces/' -iname 'em*.pm3' -type f"
local tracesMOD = "find '../traces/' -iname 'm*.pm3' -type f"
print( string.rep('--',20) )
print( string.rep('--',20) )
local write2File = false
local outputTemplate = os.date("testtest_%Y-%m-%d_%H%M%S")
local cmdDataLoad = 'data load %s';
local tracesEM = "find '../traces/' -iname 'em*.pm3' -type f"
local tracesMOD = "find '../traces/' -iname 'm*.pm3' -type f"
-- Arguments for the script
for o, arg in getopt.getopt(args, 'h') do
if o == "h" then return help() end
end
core.clearCommandBuffer()
local files = {}
-- Find a set of traces staring with EM
local p = assert( io.popen(tracesEM))
for file in p:lines() do
table.insert(files, file)
end
p.close();
-- Find a set of traces staring with MOD
p = assert( io.popen(tracesMOD) )
for file in p:lines() do
table.insert(files, file)
end
p.close();
local cmdLFSEARCH = "lf search 1 u"
-- main loop
io.write('Starting to test traces > ')
for _,file in pairs(files) do
local write2File = false
local outputTemplate = os.date("testtest_%Y-%m-%d_%H%M%S")
local x = "data load "..file
dbg(x)
core.console(x)
dbg(cmdLFSEARCH)
core.console(cmdLFSEARCH)
core.clearCommandBuffer()
if core.ukbhit() then
print("aborted by user")
break
end
end
io.write('\n')
-- Arguments for the script
for o, arg in getopt.getopt(args, 'h') do
if o == "h" then return help() end
end
print( string.rep('--',20) )
core.clearCommandBuffer()
local files = {}
-- Find a set of traces staring with EM
local p = assert( io.popen(tracesEM))
for file in p:lines() do
table.insert(files, file)
end
p.close();
-- Find a set of traces staring with MOD
p = assert( io.popen(tracesMOD) )
for file in p:lines() do
table.insert(files, file)
end
p.close();
local cmdLFSEARCH = "lf search 1 u"
-- main loop
io.write('Starting to test traces > ')
for _,file in pairs(files) do
local x = "data load "..file
dbg(x)
core.console(x)
dbg(cmdLFSEARCH)
core.console(cmdLFSEARCH)
core.clearCommandBuffer()
if core.ukbhit() then
print("aborted by user")
break
end
end
io.write('\n')
print( string.rep('--',20) )
end
main(args)

View file

@ -3,8 +3,8 @@ local getopt = require('getopt')
local lib14a = require('read14a')
local utils = require('utils')
example = [[
script run ufodump
script run ufodump -b 10
script run ufodump
script run ufodump -b 10
]]
author = "Iceman"
desc =
@ -22,155 +22,155 @@ Arguments:
-- Some globals
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
local DEBUG = false -- the debug flag
---
---
-- A debug printout-function
local function dbg(args)
if DEBUG then
print("###", args)
end
end
---
if DEBUG then
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
local function oops(err)
print("ERROR: ",err)
core.clearCommandBuffer()
print("ERROR: ",err)
core.clearCommandBuffer()
end
---
---
-- Usage help
local function help()
print(desc)
print("Example usage")
print(example)
print(desc)
print("Example usage")
print(example)
end
--
-- writes data to ascii textfile.
function writeDumpFile(uid, blockData)
local destination = string.format("%s.eml", uid)
local file = io.open(destination, "w")
if file == nil then
return nil, string.format("Could not write to file %s", destination)
end
local rowlen = string.len(blockData[1])
local destination = string.format("%s.eml", uid)
local file = io.open(destination, "w")
if file == nil then
return nil, string.format("Could not write to file %s", destination)
end
local rowlen = string.len(blockData[1])
for i,block in ipairs(blockData) do
if rowlen ~= string.len(block) then
print(string.format("WARNING: Dumpdata seems corrupted, line %d was not the same length as line 1",i))
end
file:write(block.."\n")
end
file:close()
return destination
for i,block in ipairs(blockData) do
if rowlen ~= string.len(block) then
print(string.format("WARNING: Dumpdata seems corrupted, line %d was not the same length as line 1",i))
end
file:write(block.."\n")
end
file:close()
return destination
end
--
--- Picks out and displays the data read from a tag
-- Specifically, takes a usb packet, converts to a Command
-- (as in commands.lua), takes the data-array and
-- (as in commands.lua), takes the data-array and
-- reads the number of bytes specified in arg1 (arg0 in c-struct)
-- and displays the data
-- @blockno just to print which block the data belong to
-- @param usbpacket the data received from the device
function showdata(blockno, data)
local xorkey = '55AA55AA55AA55AA6262'
local s = data.." | "
local dex = ''
local rs
for i = 1, 20-4, 4 do
local item = string.sub(data, i, i+3)
local xor = string.sub(xorkey, i, i+3)
local xorkey = '55AA55AA55AA55AA6262'
local s = data.." | "
local dex = ''
local rs
for i = 1, 20-4, 4 do
local item = string.sub(data, i, i+3)
local xor = string.sub(xorkey, i, i+3)
if blockno > 2 then
rs = bit32.bxor(tonumber(item,16) , tonumber(xor,16))
else
rs = tonumber(item, 16)
end
dex = (dex..'%04X'):format(rs)
end
s = s..dex.." | "
print( (" %02d | %s"):format(blockno,s))
if blockno > 2 then
rs = bit32.bxor(tonumber(item,16) , tonumber(xor,16))
else
rs = tonumber(item, 16)
end
dex = (dex..'%04X'):format(rs)
end
s = s..dex.." | "
print( (" %02d | %s"):format(blockno,s))
end
--
-- Send a "raw" iso14443a package, ie "hf 14a raw" command
function sendRaw(rawdata, options)
--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 command = Command:new{cmd = cmds.CMD_READER_ISO_14443a,
arg1 = flags, -- Send raw
-- arg2 contains the length, which is half the length
-- of the ASCII-string rawdata
arg2 = string.len(rawdata)/2,
data = rawdata}
return lib14a.sendToDevice(command, options.ignore_response)
--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 command = Command:new{cmd = cmds.CMD_READER_ISO_14443a,
arg1 = flags, -- Send raw
-- arg2 contains the length, which is half the length
-- of the ASCII-string rawdata
arg2 = string.len(rawdata)/2,
data = rawdata}
return lib14a.sendToDevice(command, options.ignore_response)
end
--
-- Sends an instruction to do nothing, only disconnect
function disconnect()
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
-- Check /armsrc/iso14443a.c, ReaderIso14443a() for details
return lib14a.sendToDevice(command, true)
--core.console("hf 14a raw -r")
end
---
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
-- Check /armsrc/iso14443a.c, ReaderIso14443a() for details
return lib14a.sendToDevice(command, true)
--core.console("hf 14a raw -r")
end
---
-- The main entry point
function main(args)
local ignore_response = false
local endblock = 20
-- Read the parameters
for o, a in getopt.getopt(args, 'hb:') do
if o == "h" then return help() end
if o == "b" then endblock = a end
end
endblock = endblock or 20
-- First of all, connect
info, err = lib14a.read(true, true)
if err then disconnect() return oops(err) end
core.clearCommandBuffer()
local blockData = {}
-- Show tag info
print(("\nFound Card UID [%s]\n"):format(info.uid))
local ignore_response = false
local endblock = 20
print("blk | data | xored")
print("----+------------------+-------------------")
for block = 00, endblock do
local cmd = string.format("10%02x00", block)
res, err = sendRaw(cmd , {ignore_response = ignore_response})
if err then disconnect() return oops(err) end
local cmd_response = Command.parse(res)
local len = tonumber(cmd_response.arg1) * 2
local data = string.sub(tostring(cmd_response.data), 0, len-4)
-- Read the parameters
for o, a in getopt.getopt(args, 'hb:') do
if o == "h" then return help() end
if o == "b" then endblock = a end
end
endblock = endblock or 20
showdata(block, data)
table.insert(blockData, data)
end
print("----+------------------+-------------------")
disconnect()
local filename, err = writeDumpFile(info.uid, blockData)
if err then return oops(err) end
-- First of all, connect
info, err = lib14a.read(true, true)
if err then disconnect() return oops(err) end
core.clearCommandBuffer()
print(string.format("\nDumped data into %s", filename))
local blockData = {}
-- Show tag info
print(("\nFound Card UID [%s]\n"):format(info.uid))
print("blk | data | xored")
print("----+------------------+-------------------")
for block = 00, endblock do
local cmd = string.format("10%02x00", block)
res, err = sendRaw(cmd , {ignore_response = ignore_response})
if err then disconnect() return oops(err) end
local cmd_response = Command.parse(res)
local len = tonumber(cmd_response.arg1) * 2
local data = string.sub(tostring(cmd_response.data), 0, len-4)
showdata(block, data)
table.insert(blockData, data)
end
print("----+------------------+-------------------")
disconnect()
local filename, err = writeDumpFile(info.uid, blockData)
if err then return oops(err) end
print(string.format("\nDumped data into %s", filename))
end
-------------------------
-- Testing
-- Testing
-------------------------
function selftest()
DEBUG = true
dbg("Performing test")
main()
dbg("Tests done")
DEBUG = true
dbg("Performing test")
main()
dbg("Tests done")
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
if "--test"==args then
selftest()
else
-- Call the main
main(args)
if "--test"==args then
selftest()
else
-- Call the main
main(args)
end

View file

@ -6,139 +6,139 @@ author = "Iceman"
version = 'v1.0.0'
desc = [[
This script tries to set UID on a mifare Ultralight magic card which either
- answers to chinese backdoor commands
- answers to chinese backdoor commands
- brickable magic tag (must write in one session)
]]
example = [[
-- backdoor magic tag
script run ul_uid -u 11223344556677
-- brickable magic tag
script run ul_uid -b -u 11223344556677
-- backdoor magic tag
script run ul_uid -u 11223344556677
-- brickable magic tag
script run ul_uid -b -u 11223344556677
]]
usage = [[
script run ul_uid -h -b -u <uid>
Arguments:
-h : this help
-u <UID> : UID (14 hexsymbols)
-b : write to brickable magic tag
-h : this help
-u <UID> : UID (14 hexsymbols)
-b : write to brickable magic tag
]]
local DEBUG = true
local bxor = bit32.bxor
---
---
-- A debug printout-function
local function dbg(args)
if not DEBUG then return end
if type(args) == "table" then
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print("###", args)
end
end
---
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
local function oops(err)
print("ERROR: ",err)
return nil, err
print("ERROR: ",err)
return nil, err
end
---
---
-- Usage help
local function help()
print(copyright)
print(author)
print(version)
print(desc)
print('Example usage')
print(example)
print(copyright)
print(author)
print(version)
print(desc)
print('Example usage')
print(example)
end
--
--- Set UID on magic command enabled
function magicUID(b0, b1, b2)
print('Using backdoor Magic tag function')
print('Using backdoor Magic tag function')
-- write block 0
core.console("hf 14a raw -p -a -b 7 40")
core.console("hf 14a raw -p -a 43")
core.console("hf 14a raw -c -a A200"..b0)
-- write block 0
core.console("hf 14a raw -p -a -b 7 40")
core.console("hf 14a raw -p -a 43")
core.console("hf 14a raw -c -a A200"..b0)
-- write block 1
core.console("hf 14a raw -p -a -b 7 40")
core.console("hf 14a raw -p -a 43")
core.console("hf 14a raw -c -a A201"..b1)
-- write block 1
core.console("hf 14a raw -p -a -b 7 40")
core.console("hf 14a raw -p -a 43")
core.console("hf 14a raw -c -a A201"..b1)
-- write block 2
core.console("hf 14a raw -p -a -b 7 40")
core.console("hf 14a raw -p -a 43")
core.console("hf 14a raw -c -a A202"..b2)
-- write block 2
core.console("hf 14a raw -p -a -b 7 40")
core.console("hf 14a raw -p -a 43")
core.console("hf 14a raw -c -a A202"..b2)
end
--
--- Set UID on magic but brickable
--- Set UID on magic but brickable
function brickableUID(b0, b1, b2)
print('Using BRICKABLE Magic tag function')
core.console("hf 14a raw -p -s -3")
-- write block 0
core.console("hf 14a raw -p -c A200"..b0)
-- write block 1
core.console("hf 14a raw -p -c A201"..b1)
print('Using BRICKABLE Magic tag function')
-- write block 2
core.console("hf 14a raw -p -c A202"..b2)
core.console("hf 14a raw -p -s -3")
-- write block 0
core.console("hf 14a raw -p -c A200"..b0)
-- write block 1
core.console("hf 14a raw -p -c A201"..b1)
-- write block 2
core.console("hf 14a raw -p -c A202"..b2)
end
---
---
-- The main entry point
function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
print()
print( string.rep('--',20) )
print( string.rep('--',20) )
print()
local uid = '04112233445566'
local tagtype = 1
-- Read the parameters
for o, a in getopt.getopt(args, 'hu:b') do
if o == "h" then return help() end
if o == "u" then uid = a end
if o == "b" then tagtype = 2 end
end
-- uid string checks
if uid == nil 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
local uid = '04112233445566'
local tagtype = 1
local uidbytes = utils.ConvertHexToBytes(uid)
local bcc1 = bxor(0x88, uidbytes[1], uidbytes[2], uidbytes[3])
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 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)
print('new UID | '..uid)
core.clearCommandBuffer()
if tagtype == 2 then
brickableUID(block0, block1, block2)
else
magicUID(block0, block1, block2)
end
--halt
core.console("hf 14a raw -c -a 5000")
-- Read the parameters
for o, a in getopt.getopt(args, 'hu:b') do
if o == "h" then return help() end
if o == "u" then uid = a end
if o == "b" then tagtype = 2 end
end
-- uid string checks
if uid == nil 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
local uidbytes = utils.ConvertHexToBytes(uid)
local bcc1 = bxor(0x88, uidbytes[1], uidbytes[2], uidbytes[3])
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 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)
print('new UID | '..uid)
core.clearCommandBuffer()
if tagtype == 2 then
brickableUID(block0, block1, block2)
else
magicUID(block0, block1, block2)
end
--halt
core.console("hf 14a raw -c -a 5000")
end
main(args)