1 local cmds
= require('commands')
2 local getopt
= require('getopt')
3 local utils
= require('utils')
4 local lib14a
= require('read14a')
8 script run didump -k aabbccddeeff
11 usage
= "script run didump -k <key> "
13 This is a script to dump and decrypt the data of a specific type of Mifare Mini token.
17 -k <key> : Mifare Key A.
24 local lshift
=bit32
.lshift
25 local rshift
=bit32
.rshift
27 local FOO
= 'AF62D2EC0491968CC52A1A7165F865FE'
28 local BAR
= '286329204469736E65792032303133'
29 local RANDOM
= FOO
..BAR
30 local outputTemplate
= os
.date("toydump_%Y-%m-%d_%H%M%S");
35 local CHECKSUM_OFFSET
= 12; -- +1???
37 -- A debug printout-function
44 -- This is only meant to be used when errors occur
47 core
.clearCommandBuffer()
53 print("Example usage")
58 -- called: data is string (32 hex digits)
60 local function getChecksum(data
)
61 local chksum
= data
:sub(25,32)
62 return tonumber(chksum
,16)
66 -- called: data is bytes (24 hex digits)
68 local function calculateChecksum(data
)
73 _tbl
[1] = { 0x77073096 }
74 _tbl
[2] = { 0xEE0E612C }
75 _tbl
[3] = { 0x990951BA }
76 _tbl
[4] = { 0x76DC419 }
77 _tbl
[5] = { 0x706AF48F }
78 _tbl
[6] = { 0xE963A535 }
79 _tbl
[7] = { 0x9E6495A3 }
80 _tbl
[8] = { 0xEDB8832 }
81 _tbl
[9] = { 0x79DCB8A4 }
82 _tbl
[10] = { 0xE0D5E91E }
83 _tbl
[11] = { 0x97D2D988 }
84 _tbl
[12] = { 0x9B64C2B }
85 _tbl
[13] = { 0x7EB17CBD }
86 _tbl
[14] = { 0xE7B82D07 }
87 _tbl
[15] = { 0x90BF1D91 }
88 _tbl
[16] = { 0x1DB71064 }
89 _tbl
[17] = { 0x6AB020F2 }
90 _tbl
[18] = { 0xF3B97148 }
91 _tbl
[19] = { 0x84BE41DE }
92 _tbl
[20] = { 0x1ADAD47D }
93 _tbl
[21] = { 0x6DDDE4EB }
94 _tbl
[22] = { 0xF4D4B551 }
95 _tbl
[23] = { 0x83D385C7 }
96 _tbl
[24] = { 0x136C9856 }
97 _tbl
[25] = { 0x646BA8C0 }
98 _tbl
[26] = { 0xFD62F97A }
99 _tbl
[27] = { 0x8A65C9EC }
100 _tbl
[28] = { 0x14015C4F }
101 _tbl
[29] = { 0x63066CD9 }
102 _tbl
[30] = { 0xFA0F3D63 }
103 _tbl
[31] = { 0x8D080DF5 }
104 _tbl
[32] = { 0x3B6E20C8 }
105 _tbl
[33] = { 0x4C69105E }
106 _tbl
[34] = { 0xD56041E4 }
107 _tbl
[35] = { 0xA2677172 }
108 _tbl
[36] = { 0x3C03E4D1 }
109 _tbl
[37] = { 0x4B04D447 }
110 _tbl
[38] = { 0xD20D85FD }
111 _tbl
[39] = { 0xA50AB56B }
112 _tbl
[40] = { 0x35B5A8FA }
113 _tbl
[41] = { 0x42B2986C }
114 _tbl
[42] = { 0xDBBBC9D6 }
115 _tbl
[43] = { 0xACBCF940 }
116 _tbl
[44] = { 0x32D86CE3 }
117 _tbl
[45] = { 0x45DF5C75 }
118 _tbl
[46] = { 0xDCD60DCF }
119 _tbl
[47] = { 0xABD13D59 }
120 _tbl
[48] = { 0x26D930AC }
121 _tbl
[49] = { 0x51DE003A }
122 _tbl
[50] = { 0xC8D75180 }
123 _tbl
[51] = { 0xBFD06116 }
124 _tbl
[52] = { 0x21B4F4B5 }
125 _tbl
[53] = { 0x56B3C423 }
126 _tbl
[54] = { 0xCFBA9599 }
127 _tbl
[55] = { 0xB8BDA50F }
128 _tbl
[56] = { 0x2802B89E }
129 _tbl
[57] = { 0x5F058808 }
130 _tbl
[58] = { 0xC60CD9B2 }
131 _tbl
[59] = { 0xB10BE924 }
132 _tbl
[60] = { 0x2F6F7C87 }
133 _tbl
[61] = { 0x58684C11 }
134 _tbl
[62] = { 0xC1611DAB }
135 _tbl
[63] = { 0xB6662D3D }
136 _tbl
[64] = { 0x76DC4190 }
137 _tbl
[65] = { 0x1DB7106 }
138 _tbl
[66] = { 0x98D220BC }
139 _tbl
[67] = { 0xEFD5102A }
140 _tbl
[68] = { 0x71B18589 }
141 _tbl
[69] = { 0x6B6B51F }
142 _tbl
[70] = { 0x9FBFE4A5 }
143 _tbl
[71] = { 0xE8B8D433 }
144 _tbl
[72] = { 0x7807C9A2 }
145 _tbl
[73] = { 0xF00F934 }
146 _tbl
[74] = { 0x9609A88E }
147 _tbl
[75] = { 0xE10E9818 }
148 _tbl
[76] = { 0x7F6A0DBB }
149 _tbl
[77] = { 0x86D3D2D }
150 _tbl
[78] = { 0x91646C97 }
151 _tbl
[79] = { 0xE6635C01 }
152 _tbl
[80] = { 0x6B6B51F4 }
153 _tbl
[81] = { 0x1C6C6162 }
154 _tbl
[82] = { 0x856530D8 }
155 _tbl
[83] = { 0xF262004E }
156 _tbl
[84] = { 0x6C0695ED }
157 _tbl
[85] = { 0x1B01A57B }
158 _tbl
[86] = { 0x8208F4C1 }
159 _tbl
[87] = { 0xF50FC457 }
160 _tbl
[88] = { 0x65B0D9C6 }
161 _tbl
[89] = { 0x12B7E950 }
162 _tbl
[90] = { 0x8BBEB8EA }
163 _tbl
[91] = { 0xFCB9887C }
164 _tbl
[92] = { 0x62DD1DDF }
165 _tbl
[93] = { 0x15DA2D49 }
166 _tbl
[94] = { 0x8CD37CF3 }
167 _tbl
[95] = { 0xFBD44C65 }
168 _tbl
[96] = { 0x4DB26158 }
169 _tbl
[97] = { 0x3AB551CE }
170 _tbl
[98] = { 0xA3BC0074 }
171 _tbl
[99] = { 0xD4BB30E2 }
172 _tbl
[100] = { 0x4ADFA541 }
173 _tbl
[101] = { 0x3DD895D7 }
174 _tbl
[102] = { 0xA4D1C46D }
175 _tbl
[103] = { 0xD3D6F4FB }
176 _tbl
[104] = { 0x4369E96A }
177 _tbl
[105] = { 0x346ED9FC }
178 _tbl
[106] = { 0xAD678846 }
179 _tbl
[107] = { 0xDA60B8D0 }
180 _tbl
[108] = { 0x44042D73 }
181 _tbl
[109] = { 0x33031DE5 }
182 _tbl
[110] = { 0xAA0A4C5F }
183 _tbl
[111] = { 0xDD0D7CC9 }
184 _tbl
[112] = { 0x5005713C }
185 _tbl
[113] = { 0x270241AA }
186 _tbl
[114] = { 0xBE0B1010 }
187 _tbl
[115] = { 0xC90C2086 }
188 _tbl
[116] = { 0x5768B525 }
189 _tbl
[117] = { 0x206F85B3 }
190 _tbl
[118] = { 0xB966D409 }
191 _tbl
[119] = { 0xCE61E49F }
192 _tbl
[120] = { 0x5EDEF90E }
193 _tbl
[121] = { 0x29D9C998 }
194 _tbl
[122] = { 0xB0D09822 }
195 _tbl
[123] = { 0xC7D7A8B4 }
196 _tbl
[124] = { 0x59B33D17 }
197 _tbl
[125] = { 0x2EB40D81 }
198 _tbl
[126] = { 0xB7BD5C3B }
199 _tbl
[127] = { 0xC0BA6CAD }
200 _tbl
[128] = { 0xEDB88320 }
201 _tbl
[129] = { 0x9ABFB3B6 }
202 _tbl
[130] = { 0x3B6E20C }
203 _tbl
[131] = { 0x74B1D29A }
204 _tbl
[132] = { 0xEAD54739 }
205 _tbl
[133] = { 0x9DD277AF }
206 _tbl
[134] = { 0x4DB2615 }
207 _tbl
[135] = { 0x73DC1683 }
208 _tbl
[136] = { 0xE3630B12 }
209 _tbl
[137] = { 0x94643B84 }
210 _tbl
[138] = { 0xD6D6A3E }
211 _tbl
[139] = { 0x7A6A5AA8 }
212 _tbl
[140] = { 0xE40ECF0B }
213 _tbl
[141] = { 0x9309FF9D }
214 _tbl
[142] = { 0xA00AE27 }
215 _tbl
[143] = { 0x7D079EB1 }
216 _tbl
[144] = { 0xF00F9344 }
217 _tbl
[145] = { 0x8708A3D2 }
218 _tbl
[146] = { 0x1E01F268 }
219 _tbl
[147] = { 0x6906C2FE }
220 _tbl
[148] = { 0xF762575D }
221 _tbl
[149] = { 0x806567CB }
222 _tbl
[150] = { 0x196C3671 }
223 _tbl
[151] = { 0x6E6B06E7 }
224 _tbl
[152] = { 0xFED41B76 }
225 _tbl
[153] = { 0x89D32BE0 }
226 _tbl
[154] = { 0x10DA7A5A }
227 _tbl
[155] = { 0x67DD4ACC }
228 _tbl
[156] = { 0xF9B9DF6F }
229 _tbl
[157] = { 0x8EBEEFF9 }
230 _tbl
[158] = { 0x17B7BE43 }
231 _tbl
[159] = { 0x60B08ED5 }
232 _tbl
[160] = { 0xD6D6A3E8 }
233 _tbl
[161] = { 0xA1D1937E }
234 _tbl
[162] = { 0x38D8C2C4 }
235 _tbl
[163] = { 0x4FDFF252 }
236 _tbl
[164] = { 0xD1BB67F1 }
237 _tbl
[165] = { 0xA6BC5767 }
238 _tbl
[166] = { 0x3FB506DD }
239 _tbl
[167] = { 0x48B2364B }
240 _tbl
[168] = { 0xD80D2BDA }
241 _tbl
[169] = { 0xAF0A1B4C }
242 _tbl
[170] = { 0x36034AF6 }
243 _tbl
[171] = { 0x41047A60 }
244 _tbl
[172] = { 0xDF60EFC3 }
245 _tbl
[173] = { 0xA867DF55 }
246 _tbl
[174] = { 0x316E8EEF }
247 _tbl
[175] = { 0x4669BE79 }
248 _tbl
[176] = { 0xCB61B38C }
249 _tbl
[177] = { 0xBC66831A }
250 _tbl
[178] = { 0x256FD2A0 }
251 _tbl
[179] = { 0x5268E236 }
252 _tbl
[180] = { 0xCC0C7795 }
253 _tbl
[181] = { 0xBB0B4703 }
254 _tbl
[182] = { 0x220216B9 }
255 _tbl
[183] = { 0x5505262F }
256 _tbl
[184] = { 0xC5BA3BBE }
257 _tbl
[185] = { 0xB2BD0B28 }
258 _tbl
[186] = { 0x2BB45A92 }
259 _tbl
[187] = { 0x5CB36A04 }
260 _tbl
[188] = { 0xC2D7FFA7 }
261 _tbl
[189] = { 0xB5D0CF31 }
262 _tbl
[190] = { 0x2CD99E8B }
263 _tbl
[191] = { 0x5BDEAE1D }
264 _tbl
[192] = { 0x9B64C2B0 }
265 _tbl
[193] = { 0xEC63F226 }
266 _tbl
[194] = { 0x756AA39C }
267 _tbl
[195] = { 0x26D930A }
268 _tbl
[196] = { 0x9C0906A9 }
269 _tbl
[197] = { 0xEB0E363F }
270 _tbl
[198] = { 0x72076785 }
271 _tbl
[199] = { 0x5005713 }
272 _tbl
[200] = { 0x95BF4A82 }
273 _tbl
[201] = { 0xE2B87A14 }
274 _tbl
[202] = { 0x7BB12BAE }
275 _tbl
[203] = { 0xCB61B38 }
276 _tbl
[204] = { 0x92D28E9B }
277 _tbl
[205] = { 0xE5D5BE0D }
278 _tbl
[206] = { 0x7CDCEFB7 }
279 _tbl
[207] = { 0xBDBDF21 }
280 _tbl
[208] = { 0x86D3D2D4 }
281 _tbl
[209] = { 0xF1D4E242 }
282 _tbl
[210] = { 0x68DDB3F8 }
283 _tbl
[211] = { 0x1FDA836E }
284 _tbl
[212] = { 0x81BE16CD }
285 _tbl
[213] = { 0xF6B9265B }
286 _tbl
[214] = { 0x6FB077E1 }
287 _tbl
[215] = { 0x18B74777 }
288 _tbl
[216] = { 0x88085AE6 }
289 _tbl
[217] = { 0xFF0F6A70 }
290 _tbl
[218] = { 0x66063BCA }
291 _tbl
[219] = { 0x11010B5C }
292 _tbl
[220] = { 0x8F659EFF }
293 _tbl
[221] = { 0xF862AE69 }
294 _tbl
[222] = { 0x616BFFD3 }
295 _tbl
[223] = { 0x166CCF45 }
296 _tbl
[224] = { 0xA00AE278 }
297 _tbl
[225] = { 0xD70DD2EE }
298 _tbl
[226] = { 0x4E048354 }
299 _tbl
[227] = { 0x3903B3C2 }
300 _tbl
[228] = { 0xA7672661 }
301 _tbl
[229] = { 0xD06016F7 }
302 _tbl
[230] = { 0x4969474D }
303 _tbl
[231] = { 0x3E6E77DB }
304 _tbl
[232] = { 0xAED16A4A }
305 _tbl
[233] = { 0xD9D65ADC }
306 _tbl
[234] = { 0x40DF0B66 }
307 _tbl
[235] = { 0x37D83BF0 }
308 _tbl
[236] = { 0xA9BCAE53 }
309 _tbl
[237] = { 0xDEBB9EC5 }
310 _tbl
[238] = { 0x47B2CF7F }
311 _tbl
[239] = { 0x30B5FFE9 }
312 _tbl
[240] = { 0xBDBDF21C }
313 _tbl
[241] = { 0xCABAC28A }
314 _tbl
[242] = { 0x53B39330 }
315 _tbl
[243] = { 0x24B4A3A6 }
316 _tbl
[244] = { 0xBAD03605 }
317 _tbl
[245] = { 0xCDD70693 }
318 _tbl
[246] = { 0x54DE5729 }
319 _tbl
[247] = { 0x23D967BF }
320 _tbl
[248] = { 0xB3667A2E }
321 _tbl
[249] = { 0xC4614AB8 }
322 _tbl
[250] = { 0x5D681B02 }
323 _tbl
[251] = { 0x2A6F2B94 }
324 _tbl
[252] = { 0xB40BBE37 }
325 _tbl
[253] = { 0xC30C8EA1 }
326 _tbl
[254] = { 0x5A05DF1B }
327 _tbl
[255] = { 0x2D02EF8D }
332 for i
,item
in pairs(data
) do
333 local tmp
= band(ret
, 0xFF)
334 local index
= band( bxor(tmp
, item
), 0xFF)
335 ret
= bxor(rshift(ret
,8), _tbl
[index
][1])
341 -- called: data is string, ( >= 24 hex digits )
342 -- returns: string, (data concat new checksum)
343 local function updateChecksum(data
)
344 local part
= data
:sub(1,24)
345 local chksum
= calculateChecksum( utils
.ConvertHexToBytes(part
))
346 return string.format("%s%X", part
, chksum
)
349 -- receives the answer from deviceside, used with a readblock command
350 local function waitCmd()
351 local response
= core
.WaitForResponseTimeout(cmds
.CMD_ACK
,TIMEOUT
)
353 local count
,cmd
,arg0
= bin
.unpack('LL',response
)
355 local count
,arg1
,arg2
,data
= bin
.unpack('LLH511',response
,count
)
356 return data
:sub(1,32)
358 return nil, "Couldn't read block.."
361 return nil, "No response from device"
364 local function selftest()
365 local testdata
= '000F42430D0A14000001D11F'..'5D738517'
366 local chksum
= getChecksum(testdata
)
367 local calc
= calculateChecksum( utils
.ConvertHexToBytes(testdata
:sub(1,24)))
368 print ('TESTDATA :: '..testdata
)
369 print ('DATA :: '..testdata
:sub(1,24))
370 print (('CHKSUM :: %X'):format(chksum
))
371 print (('CHKSUM CALC :: %X'):format(calc
))
372 print ('UPDATE CHKSUM :: '..updateChecksum(testdata
))
377 -- The main entry point
383 local cmd
, result
, err
, blockNo
, keyA
385 local decryptkey
= ''
387 -- Read the parameters
388 for o
, a
in getopt
.getopt(args
, 'hk:') do
389 if o
== "h" then help() return end
390 if o
== "k" then keyA
= a
end
395 local tst2
= '00100100030209094312356432324E34B79A349B'
397 -- validate input args.
398 keyA
= keyA
or '6dd747e86975'
399 if #(keyA
) ~= 12 then
400 return oops( string.format('Wrong length of write key (was %d) expected 12', #keyA
))
404 local cmdSetDbgOff
= "hf mf dbg 0"
405 core
.console( cmdSetDbgOff
)
409 result
, err
= lib14a
.read1443a(false)
414 core
.clearCommandBuffer()
416 print(result
.uid
, keyA
)
418 local my
= result
.uid
424 print((' Found tag %s'):format(result
.name
))
426 local longrandom
= RANDOM
..result
.uid
427 local res
= utils
.Sha1Hex(longrandom
)
428 res
= utils
.ConvertBytesToHex(utils
.ConvertAsciiToBytes(res
:sub(1,16)))
429 decryptkey
= utils
.SwapEndiannessStr(res
:sub(1,8) , 32)
430 decryptkey
= decryptkey
..utils
.SwapEndiannessStr( res
:sub(9,16),32)
431 decryptkey
= decryptkey
..utils
.SwapEndiannessStr( res
:sub(17,24),32)
432 decryptkey
= decryptkey
..utils
.SwapEndiannessStr( res
:sub(25,32),32)
433 print('Decrypt key::',decryptkey
)
434 print('Reading card data')
435 print('Raw','Decrypted')
436 for blockNo
= 0, numBlocks
-1, 1 do
438 if core
.ukbhit() then
439 print("aborted by user")
443 cmd
= Command
:new
{cmd
= cmds
.CMD_MIFARE_READBL
, arg1
= blockNo
,arg2
= 0,arg3
= 0, data
= keyA
}
444 local err
= core
.SendCommand(cmd
:getBytes())
445 if err
then return oops(err
) end
446 local blockdata
, err
= waitCmd()
447 if err
then return oops(err
) end
449 if blockNo
%4 ~= 3 then
451 -- blocks with zero not encrypted.
452 if string.find(blockdata
, '^0+$') then
453 print(blockdata
, blockdata
)
455 local aes
= core
.aes128_decrypt_ecb(decryptkey
, blockdata
)
456 local bytes
= utils
.ConvertAsciiToBytes(aes
)
457 local hex
= utils
.ConvertBytesToHex(bytes
)
458 print(blockdata
, hex
)
460 elseif blockNo
== 0 then
461 print(blockdata
,blockdata
)
463 -- Sectorblocks, not encrypted
464 local sectortrailer
= keyA
..blockdata
:sub(13,20)..keyA
465 print(sectortrailer
, sectortrailer
, blockdata
:sub(13,20))
468 -- checksum fyra sista bytes i varje rad. (kanske inte för s0)
469 -- s0b1,s1b0,s2b0,s3b0