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
= 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
118 if keytype
== 'A' then
119 p1
= bxor( uid
[1], xorkey
[1])
120 p2
= bxor( uid
[2], xorkey
[2])
121 p3
= bxor( uid
[3], xorkey
[3])
122 p4
= bxor( uid
[4], xorkey
[4])
123 p5
= bxor( uid
[1], xorkey
[5])
124 p6
= bxor( uid
[2], xorkey
[6])
126 p1
= bxor( uid
[3], xorkey
[1])
127 p2
= bxor( uid
[4], xorkey
[2])
128 p3
= bxor( uid
[1], xorkey
[3])
129 p4
= bxor( uid
[2], xorkey
[4])
130 p5
= bxor( uid
[3], xorkey
[5])
131 p6
= bxor( uid
[4], xorkey
[6])
133 return keyStr(p1
,p2
,p3
,p4
,p5
,p6
)
137 local function printKeys(keys
)
138 print('|---|----------------|---|----------------|---|')
139 print('|sec|key A |res|key B |res|')
140 print('|---|----------------|---|----------------|---|')
141 for sector
= 0, #keys
do
142 local keyA
, keyB
= unpack(keys
[sector
])
143 print(('|%03d| %s | %s | %s | %s |'):format(sector
, keyA
, 1, keyB
, 1))
145 print('|---|----------------|---|----------------|---|')
148 -- create a full set of keys
149 local function createKeys(uid
)
150 local uidbytes
= utils
.ConvertHexToBytes(uid
)
153 k
[0] = { keyStr(0xA0,0xA1,0xA2,0xA3,0xA4,0xA5), keyStr(0xB4,0xC1,0x32,0x43,0x9e,0xef) }
155 for _
, v
in pairs(_xortable
) do
156 local keyA
= calckey(uidbytes
, utils
.ConvertHexToBytes(v
[2]), 'A')
157 local keyB
= calckey(uidbytes
, utils
.ConvertHexToBytes(v
[3]), 'B')
158 k
[v
[1]]
= { keyA
, keyB
}
164 local function main(args
)
166 print( string.rep('==', 30) )
169 local uid
= '11223344'
172 -- Arguments for the script
173 for o
, a
in getopt
.getopt(args
, 'hu:') do
174 if o
== 'h' then return help() end
175 if o
== 'u' then uid
= a
; useUID
= true end
180 if uid
== nil then return oops('empty uid string') end
181 if #uid
== 0 then return oops('empty uid string') end
182 if #uid
~= 8 then return oops('uid wrong length. Should be 4 hex bytes') end
185 local tag, err
= lib14a
.read(false, true)
186 if not tag then return oops(err
) end
187 core
.clearCommandBuffer()
190 if 0x09 ~= tag.sak
then
191 if 0x4400 ~= tag.atqa
then
192 return oops(('[!] found tag %s :: looking for Mifare Mini 0.3k'):format(tag.name
))
200 local keys
, err
= createKeys( uid
)
202 dumptofile( uid
, keys
)