1 local bin
= require('bin')
2 local getopt
= require('getopt')
3 local lib14a
= require('read14a')
4 local utils
= require('utils')
5 local ansicolors
= require('ansicolors')
11 This script calculates mifare keys based on uid diversification for mizip.
15 -- if called without, it reads tag uid
16 script run hf_mf_uidkeycalc-mizip
19 script run hf_mf_uidkeycalc-mizip -u 11223344
22 script run hf_mf_uidkeycalc-mizip -h -u <uid>
29 local bxor
= bit32
.bxor
31 --[[ sector key A/B, 6byte xor
33 {1, '09125a2589e5', 'F12C8453D821'},
34 {2, 'AB75C937922F', '73E799FE3241'},
35 {3, 'E27241AF2C09', 'AA4D137656AE'},
36 {4, '317AB72F4490', 'B01327272DFD'},
39 -- A debug printout-function
40 local function dbg(args
)
41 if not DEBUG
then return end
42 if type(args
) == 'table' then
53 -- This is only meant to be used when errors occur
54 local function oops(err
)
56 core
.clearCommandBuffer()
66 print(ansicolors
.cyan
..'Usage'..ansicolors
.reset
)
68 print(ansicolors
.cyan
..'Arguments'..ansicolors
.reset
)
70 print(ansicolors
.cyan
..'Example usage'..ansicolors
.reset
)
75 local function exitMsg(msg
)
76 print( string.rep('--',20) )
77 print( string.rep('--',20) )
82 -- dumps all keys to file
83 local function dumptofile(uid
, keys
)
84 dbg('dumping keys to file')
86 if utils
.confirm('Do you wish to save the keys to dumpfile?') then
87 local filename
= ('hf-mf-%s-key.bin'):format(uid
);
88 local destination
= utils
.input('Select a filename to store to', filename
)
89 local file
= io
.open(destination
, 'wb')
91 print('Could not write to file ', destination
)
95 -- Mifare Mini has 5 sectors,
99 for sector
= 0, #keys
do
100 local keyA
, keyB
= table.unpack(keys
[sector
])
101 key_a
= key_a
.. bin
.pack('H', keyA
);
102 key_b
= key_b
.. bin
.pack('H', keyB
);
110 -- key bytes to string
111 local function keyStr(p1
, p2
, p3
, p4
, p5
, p6
)
112 return string.format('%02X%02X%02X%02X%02X%02X',p1
, p2
, p3
, p4
, p5
, p6
)
116 local function calckey(uid
, xorkey
, keytype
)
117 local p1
,p2
,p3
,p4
,p5
,p6
119 if keytype
== 'A' then
120 p1
= bxor( uid
[1], xorkey
[1])
121 p2
= bxor( uid
[2], xorkey
[2])
122 p3
= bxor( uid
[3], xorkey
[3])
123 p4
= bxor( uid
[4], xorkey
[4])
124 p5
= bxor( uid
[1], xorkey
[5])
125 p6
= bxor( uid
[2], xorkey
[6])
127 p1
= bxor( uid
[3], xorkey
[1])
128 p2
= bxor( uid
[4], xorkey
[2])
129 p3
= bxor( uid
[1], xorkey
[3])
130 p4
= bxor( uid
[2], xorkey
[4])
131 p5
= bxor( uid
[3], xorkey
[5])
132 p6
= bxor( uid
[4], xorkey
[6])
134 return keyStr(p1
,p2
,p3
,p4
,p5
,p6
)
138 local function printKeys(keys
)
139 print('|---|----------------|---|----------------|---|')
140 print('|sec|key A |res|key B |res|')
141 print('|---|----------------|---|----------------|---|')
142 for sector
= 0, #keys
do
143 local keyA
, keyB
= table.unpack(keys
[sector
])
144 print(('|%03d| %s | %s | %s | %s |'):format(sector
, keyA
, 1, keyB
, 1))
146 print('|---|----------------|---|----------------|---|')
149 -- create a full set of keys
150 local function createKeys(uid
)
151 local uidbytes
= utils
.ConvertHexToBytes(uid
)
154 k
[0] = { keyStr(0xA0,0xA1,0xA2,0xA3,0xA4,0xA5), keyStr(0xB4,0xC1,0x32,0x43,0x9e,0xef) }
156 for _
, v
in pairs(_xortable
) do
157 local keyA
= calckey(uidbytes
, utils
.ConvertHexToBytes(v
[2]), 'A')
158 local keyB
= calckey(uidbytes
, utils
.ConvertHexToBytes(v
[3]), 'B')
159 k
[v
[1]]
= { keyA
, keyB
}
165 local function main(args
)
167 print( string.rep('==', 30) )
170 local uid
= '11223344'
173 -- Arguments for the script
174 for o
, a
in getopt
.getopt(args
, 'hu:') do
175 if o
== 'h' then return help() end
176 if o
== 'u' then uid
= a
; useUID
= true end
181 if uid
== nil then return oops('empty uid string') end
182 if #uid
== 0 then return oops('empty uid string') end
183 if #uid
~= 8 then return oops('uid wrong length. Should be 4 hex bytes') end
186 local tag, err
= lib14a
.read(false, true)
187 if not tag then return oops(err
) end
188 core
.clearCommandBuffer()
191 if 0x09 ~= tag.sak
then
192 if 0x4400 ~= tag.atqa
then
193 return oops(('[!] found tag %s :: looking for Mifare Mini 0.3k'):format(tag.name
))
201 local keys
, err
= createKeys( uid
)
203 dumptofile( uid
, keys
)