2 -- hf_mf_uid_downgrade.lua - Downgrading to UID-based Mifare Classic
3 -- Adapted from hf_mf_sim_hid.lua
6 local getopt
= require('getopt')
7 local ansicolors
= require('ansicolors')
10 author
= "Adam Foster (evildaemond)"
13 Convert a facility code and card number to a Mifare Classic UID, which can be used as part of a downgrade attack.
14 This abuses the fact that some controllers interpret the UID for Mifare Classic cards as a CN and FN, it requires the controller to interpret the wiegand payload in this way.
16 The example of FC 146 CN 5 would be read by the reader and send as a payload like 0920005, where 9200 is dec 146 and 05 is interpreted as 5
18 Working on HID Readers with any of the following enabled
20 - Mifare Classic SIO + CSN
24 -- Downgrade a card with the facility code of 146 and card number of 5
25 script run hf_mf_uid_downgrade.lua -f 146 -c 5
28 script run hf_mf_uid_downgrade.lua -f <dec> -c <dec>
32 -f <dec> : facility code
33 -c <dec> : card number
36 --local bxor = bit32.bxor
38 local lshift
= bit32
.lshift
47 print(ansicolors
.cyan
..'Usage'..ansicolors
.reset
)
49 print(ansicolors
.cyan
..'Arguments'..ansicolors
.reset
)
51 print(ansicolors
.cyan
..'Example usage'..ansicolors
.reset
)
56 local function exitMsg(msg
)
57 print( string.rep('--',20) )
58 print( string.rep('--',20) )
63 local function oops(err
)
65 core
.clearCommandBuffer()
70 local function isempty(s
)
71 return s
== nil or s
== ''
74 -- Function to combine two hexadecimal strings
75 local function convertToUID(hex_str1
, hex_str2
)
76 local hex1
= string.format('%04x', hex_str1
)
77 local hex2
= string.format('%04x', hex_str2
)
79 local combined_hex
= hex1
.. hex2
80 local reversed_hex
= ''
81 for i
= #combined_hex
, 1, -2 do
82 reversed_hex
= reversed_hex
.. string.sub(combined_hex
, i
- 1, i
)
89 local function main(args
)
91 print( string.rep('--',20) )
92 print( string.rep('--',20) )
95 if #args
== 0 then return help() end
97 --I really wish a better getopt function would be brought in supporting
98 --long arguments, but it seems this library was chosen for BSD style
100 for o
, a
in getopt
.getopt(args
, 'f:c:h') do
101 if o
== 'h' then return help() end
103 if isempty(a
) then return oops('You must supply a facility code') end
107 if isempty(a
) then return oops('You must supply a card number') end
112 --Due to my earlier complaints about how this specific getopt library
113 --works, specifying ':' does not enforce supplying a value, thus we
114 --need to do these checks all over again.
115 if isempty(facility
) then return oops('You must supply a facility code') end
116 if isempty(cardnum
) then return oops('You must supply a card number') end
118 local cardh
= convertToUID(facility
, cardnum
)
120 print('Facility Code... ' .. facility
)
121 print('Card number..... ' .. cardnum
)
122 print('UID............. ' .. cardh
)
125 -- Print emulation or writing string based on flags
126 print('Emulate via PM3:')
127 print('hf mf sim --1k -u', cardh
, '\n')
129 print('Write to Mifare Classic Card (Gen1a or Above):')
130 print('hf mf csetuid -u', cardh
)