text
[RRG-proxmark3.git] / client / luascripts / hf_mf_autopwn.lua
blob08e8b218c2c1132e2cd3e3f06efe21f28cc2dc28
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 ~= 0 then return oops('Darkside attack failed.') end
190 -- The key is actually 8 bytes, so a
191 -- 6-byte key is sent as 00XXXXXX
192 -- This means we unpack it as first
193 -- two bytes, then six bytes actual key data
194 -- We can discard first and second return values
195 _,_,key = bin.unpack('H2H6',res)
196 print('Found valid key: '..key);
198 -- Use nested attack
199 nested(key, sak)
200 -- Dump info
201 dump_tag(uid, sak)
203 if #key == 12 then _exit = true end
204 else
205 print('Card found, darkside attack useless PRNG hardend on UID', uid)
207 print_message = true
212 -- Call the main
213 main(args)