added more keys (@equipter)
[RRG-proxmark3.git] / client / luascripts / hf_mf_uidkeycalc-mizip.lua
blob902aeeda82279b0b5795874708fd4cdec414ee46
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')
7 copyright = ''
8 author = 'Iceman'
9 version = 'v1.0.2'
10 desc = [[
11 This script calculates mifare keys based on uid diversification for mizip.
12 Algo not found by me.
14 example = [[
15 -- if called without, it reads tag uid
16 script run hf_mf_uidkeycalc-mizip
19 script run hf_mf_uidkeycalc-mizip -u 11223344
21 usage = [[
22 script run hf_mf_uidkeycalc-mizip -h -u <uid>
24 arguments = [[
25 -h : this help
26 -u <UID> : UID
28 local DEBUG = true
29 local bxor = bit32.bxor
30 local _xortable = {
31 --[[ sector key A/B, 6byte xor
32 --]]
33 {1, '09125a2589e5', 'F12C8453D821'},
34 {2, 'AB75C937922F', '73E799FE3241'},
35 {3, 'E27241AF2C09', 'AA4D137656AE'},
36 {4, '317AB72F4490', 'B01327272DFD'},
38 ---
39 -- A debug printout-function
40 local function dbg(args)
41 if not DEBUG then return end
42 if type(args) == 'table' then
43 local i = 1
44 while args[i] do
45 dbg(args[i])
46 i = i+1
47 end
48 else
49 print('###', args)
50 end
51 end
52 ---
53 -- This is only meant to be used when errors occur
54 local function oops(err)
55 print('ERROR: ', err)
56 core.clearCommandBuffer()
57 return nil, err
58 end
59 ---
60 -- Usage help
61 local function help()
62 print(copyright)
63 print(author)
64 print(version)
65 print(desc)
66 print(ansicolors.cyan..'Usage'..ansicolors.reset)
67 print(usage)
68 print(ansicolors.cyan..'Arguments'..ansicolors.reset)
69 print(arguments)
70 print(ansicolors.cyan..'Example usage'..ansicolors.reset)
71 print(example)
72 end
74 -- Exit message
75 local function exitMsg(msg)
76 print( string.rep('--',20) )
77 print( string.rep('--',20) )
78 print(msg)
79 print()
80 end
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')
90 if file == nil then
91 print('Could not write to file ', destination)
92 return
93 end
95 -- Mifare Mini has 5 sectors,
96 local key_a = ''
97 local key_b = ''
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);
104 file:write(key_a)
105 file:write(key_b)
106 file:close()
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)
115 -- create key
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])
125 else
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)
136 -- print keys
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)
152 local k = {}
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 }
160 return k
163 -- main
164 local function main(args)
166 print( string.rep('==', 30) )
167 print()
169 local uid = '11223344'
170 local useUID = false
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
178 if useUID then
179 -- uid string checks
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
183 else
184 -- GET TAG UID
185 local tag, err = lib14a.read(false, true)
186 if not tag then return oops(err) end
187 core.clearCommandBuffer()
189 -- simple tag check
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))
195 uid = tag.uid
198 print('|UID|', uid)
200 local keys, err = createKeys( uid )
201 printKeys( keys )
202 dumptofile( uid, keys )
205 main(args)