X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/0dae56d81ed737be4f2fa010326cbf41ea0af228..4cdd63b245e34b42df42b384009838020d8fad02:/client/scripts/mifare_autopwn.lua?ds=inline diff --git a/client/scripts/mifare_autopwn.lua b/client/scripts/mifare_autopwn.lua index ccb46c53..d743f21e 100644 --- a/client/scripts/mifare_autopwn.lua +++ b/client/scripts/mifare_autopwn.lua @@ -8,7 +8,7 @@ author = "Martin Holst Swende" desc = [[ -This is a which automates cracking and dumping mifare classic cards. It sets itself into +This is a script which automates cracking and dumping mifare classic cards. It sets itself into 'listening'-mode, after which it cracks and dumps any mifare classic card that you place by the device. @@ -56,75 +56,29 @@ end -- @return if unsuccessfull : nil, error function wait_for_mifare() while not core.ukbhit() do - res, err = reader.read1443a() + res, err = reader.read14443a(false, true) if res then return res end -- err means that there was no response from card end return nil, "Aborted by user" end -function mfcrack() - core.clearCommandBuffer() - -- Build the mifare-command - local cmd = Command:new{cmd = cmds.CMD_READER_MIFARE, arg1 = 1} - - local retry = true - while retry do - core.SendCommand(cmd:getBytes()) - local key, errormessage = mfcrack_inner() - -- Success? - if key then return key end - -- Failure? - if errormessage then return nil, errormessage end - -- Try again..set arg1 to 0 this time. - - cmd = Command:new{cmd = cmds.CMD_READER_MIFARE, arg1 = 0} - end - return nil, "Aborted by user" -end - - -function mfcrack_inner() - while not core.ukbhit() do - local result = core.WaitForResponseTimeout(cmds.CMD_ACK,1000) - if result then - -- Unpacking the three arg-parameters - local count,cmd,isOK = bin.unpack('LL',result) - - if isOK ~= 1 then return nil, "Error occurred" end - - - -- The data-part is left - -- Starts 32 bytes in, at byte 33 - local data = result:sub(33) - - -- A little helper - local get = function(num) - local x = data:sub(1,num) - data = data:sub(num+1) - return x - end - - local uid,nt,pl = get(4),get(4),get(8) - local ks,nr = get(8),get(4) - - local status, key = core.nonce2key(uid,nt, nr, pl,ks) - if not status then return status,key end - - if status > 0 then - print("Key not found (lfsr_common_prefix problem)") - -- try again - return nil,nil - else - return key - end - end +function nested(key,sak) + local typ = 1 + if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k + typ = 4 + elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k + typ= 1 + elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k + typ = 0 + elseif 0x10 == sak then-- "NXP MIFARE Plus 2k" + typ = 2 + elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K" + typ = 1 + else + print("I don't know how many sectors there are on this type of card, defaulting to 16") end - return nil, "Aborted by user" -end - -function nested(key) - local cmd = string.format("hf mf nested 1 0 A %s d",key) + local cmd = string.format("hf mf nested %d 0 A %s d",typ,key) core.console(cmd) end @@ -149,7 +103,7 @@ end function main(args) - local verbose, exit,res,uid,err,_ + local verbose, exit,res,uid,err,_,sak local seen_uids = {} -- Read the parameters @@ -163,19 +117,32 @@ function main(args) if err then return oops(err) end -- Seen already? uid = res.uid + sak = res.sak if not seen_uids[uid] then -- Store it seen_uids[uid] = uid print("Card found, commencing crack", uid) -- Crack it local key, cnt - res,err = mfcrack() - if not res then return oops(err) end - _,key = bin.unpack("H6",res) + err, res = core.mfDarkside() + if err == -1 then return oops("Button pressed. Aborted.") + elseif err == -2 then return oops("Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests).") + elseif err == -3 then return oops("Card is not vulnerable to Darkside attack (its random number generator is not predictable).") + elseif err == -4 then return oops([[ +Card is not vulnerable to Darkside attack (its random number generator seems to be based on the wellknown +generating polynomial with 16 effective bits only, but shows unexpected behaviour.]]) + elseif err == -5 then return oops("Aborted via keyboard.") + end + -- The key is actually 8 bytes, so a + -- 6-byte key is sent as 00XXXXXX + -- This means we unpack it as first + -- two bytes, then six bytes actual key data + -- We can discard first and second return values + _,_,key = bin.unpack("H2H6",res) print("Key ", key) -- Use nested attack - nested(key) + nested(key,sak) -- Dump info dump(uid) end