2 -- hf_mf_sim_hid.lua - A tool to clone a large number of tags at once.
3 -- Adapted from lf_hid_bulkclone.lua
5 local getopt
= require('getopt')
6 local ansicolors
= require('ansicolors')
9 author
= "Michael Micsen"
12 Perform simulation of Mifare credentials with HID encoding
13 This script only supports: H10301
17 script run hf_mf_sim_hid.lua -f 1 -c 10000
20 script run hf_mf_sim_hid.lua -f <dec> -c <dec>
28 --local bxor = bit32.bxor
30 local lshift
= bit32
.lshift
32 -- A debug printout-function
33 local function dbg(args
)
34 if not DEBUG
then return end
35 if type(args
) == 'table' then
46 -- This is only meant to be used when errors occur
47 local function oops(err
)
49 core
.clearCommandBuffer()
59 print(ansicolors
.cyan
..'Usage'..ansicolors
.reset
)
61 print(ansicolors
.cyan
..'Arguments'..ansicolors
.reset
)
63 print(ansicolors
.cyan
..'Example usage'..ansicolors
.reset
)
68 local function exitMsg(msg
)
69 print( string.rep('--',20) )
70 print( string.rep('--',20) )
74 --[[Implement a function to simply visualize the bitstream in a text format
75 --This is especially helpful for troubleshooting bitwise math issues]]--
76 local function toBits(num
,bits
)
77 -- returns a table of bits, most significant first.
78 bits
= bits
or math
.max(1, select(2, math
.frexp(num
)))
79 local t
= {} -- will contain the bits
80 for b
= bits
, 1, -1 do
81 t
[b
] = math
.fmod(num
, 2)
82 num
= math
.floor((num
- t
[b
]) / 2)
84 return table.concat(t
)
88 Likely, I'm an idiot, but I couldn't find any parity functions in Lua
89 This can also be done with a combination of bitwise operations (in fact,
90 is the canonically "correct" way to do it, but my brain doesn't just
91 default to this and so counting some ones is good enough for me
93 local function evenparity(s
)
94 local _
, count
= string.gsub(s
, '1', '')
103 local function isempty(s
)
104 return s
== nil or s
== ''
108 The Proxmark3 "clone" functions expect the data to be in hex format so
109 take the card id number and facility ID as arguments and construct the
110 hex. This should be easy enough to extend to non 26bit formats
112 local function cardHex(i
, f
)
116 stream
= toBits(id
, 24)
118 --As the function defaults to even parity and returns a boolean,
119 --perform a 'not' function to get odd parity
120 high
= evenparity(string.sub(stream
,1,12)) and 1 or 0
121 low
= not evenparity(string.sub(stream
,13)) and 1 or 0
122 bits
= bor( lshift(id
, 1), low
)
123 bits
= bor( bits
, lshift(high
, 25))
126 sentinel
= lshift(1, 26)
127 bits
= bor(bits
, sentinel
)
129 return ('%08x'):format(bits
)
133 local function main(args
)
135 print( string.rep('--',20) )
136 print( string.rep('--',20) )
139 if #args
== 0 then return help() end
141 --I really wish a better getopt function would be brought in supporting
142 --long arguments, but it seems this library was chosen for BSD style
144 for o
, a
in getopt
.getopt(args
, 'f:c:h') do
145 if o
== 'h' then return help() end
148 print('Defaulting to facility code 0')
155 if isempty(a
) then return oops('You must supply a card number') end
160 --Due to my earlier complaints about how this specific getopt library
161 --works, specifying ':' does not enforce supplying a value, thus we
162 --need to do these checks all over again.
163 if isempty(cardnum
) then return oops('You must supply a card number') end
165 --If the facility ID is non specified, ensure we code it as zero
166 if isempty(facility
) then
167 print('Defaulting to facility code 0')
171 -- Write the MAD to read for a Mifare HID credential
172 core
.console('hf mf esetblk --blk 1 -d 1B014D48000000000000000000000000')
173 core
.console('hf mf esetblk --blk 3 -d A0A1A2A3A4A5787788C189ECA97F8C2A')
174 --Write the sector trailer for the credential sector
175 core
.console('hf mf esetblk --blk 7 -d 484944204953787788AA204752454154')
176 local cardh
= cardHex(cardnum
, facility
)
178 print('Facility Code... ' .. facility
)
179 print('Card number..... ' .. cardnum
)
180 print('Hex............. ' .. cardh
)
183 core
.console( ('hf mf esetblk --blk 5 -d 020000000000000000000000%s'):format(cardh
) )
184 core
.console('hf mf sim --1k -i')