1 local getopt = require('getopt')
2 local reader = require('read14a')
3 local cmds = require('commands')
5 example = "script run mifare_autopwn"
6 author = "Martin Holst Swende"
11 This is a script which automates cracking and dumping mifare classic cards. It sets itself into
12 'listening'-mode, after which it cracks and dumps any mifare classic card that you
19 Output files from this operation:
20 <uid>.eml - emulator file
21 <uid>.html - html file containing card data
22 dumpkeys.bin - keys are dumped here. OBS! This file is volatile, as other commands overwrite it sometimes.
23 dumpdata.bin - card data in binary form. OBS! This file is volatile, as other commands (hf mf dump) overwrite it.
27 -------------------------------
29 -------------------------------
32 -- A debug printout-function
39 -- This is only meant to be used when errors occur
49 print("Example usage")
54 -- Waits for a mifare card to be placed within the vicinity of the reader.
55 -- @return if successfull: an table containing card info
56 -- @return if unsuccessfull : nil, error
57 function wait_for_mifare()
58 while not core.ukbhit() do
59 res, err = reader.read14443a(false, true)
60 if res then return res end
61 -- err means that there was no response from card
63 return nil, "Aborted by user"
66 function nested(key,sak)
68 if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k
70 elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k
72 elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k
74 elseif 0x10 == sak then-- "NXP MIFARE Plus 2k"
76 elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K"
79 print("I don't know how many sectors there are on this type of card, defaulting to 16")
81 local cmd = string.format("hf mf nested %d 0 A %s d",typ,key)
86 core.console("hf mf dump")
87 -- Save the global args, those are *our* arguments
89 -- Set the arguments for htmldump script
90 args =("-o %s.html"):format(uid)
92 require('../scripts/htmldump')
96 require('../scripts/dumptoemul')
97 -- Set back args. Not that it's used, just for the karma...
102 -- The main entry point
106 local verbose, exit,res,uid,err,_,sak
109 -- Read the parameters
110 for o, a in getopt.getopt(args, 'hd') do
111 if o == "h" then help() return end
112 if o == "d" then DEBUG = true end
116 res, err = wait_for_mifare()
117 if err then return oops(err) end
121 if not seen_uids[uid] then
124 print("Card found, commencing crack", uid)
127 err, res = core.mfDarkside()
128 if err == -1 then return oops("Button pressed. Aborted.")
129 elseif err == -2 then return oops("Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests).")
130 elseif err == -3 then return oops("Card is not vulnerable to Darkside attack (its random number generator is not predictable).")
131 elseif err == -4 then return oops([[
132 Card is not vulnerable to Darkside attack (its random number generator seems to be based on the wellknown
133 generating polynomial with 16 effective bits only, but shows unexpected behaviour.]])
134 elseif err == -5 then return oops("Aborted via keyboard.")
136 -- The key is actually 8 bytes, so a
137 -- 6-byte key is sent as 00XXXXXX
138 -- This means we unpack it as first
139 -- two bytes, then six bytes actual key data
140 -- We can discard first and second return values
141 _,_,key = bin.unpack("H2H6",res)