CHG: 'script run didump' - got some remake. unfinished.

CHG: some default keys
This commit is contained in:
iceman1001 2017-07-04 20:23:47 +02:00
parent 3ca3d401c0
commit a211877853
6 changed files with 347 additions and 75 deletions

View file

@ -565,16 +565,12 @@ static command_t CommandTable[] =
}; };
int CmdHFTopaz(const char *Cmd) { int CmdHFTopaz(const char *Cmd) {
// flush
clearCommandBuffer(); clearCommandBuffer();
// parse
CmdsParse(CommandTable, Cmd); CmdsParse(CommandTable, Cmd);
return 0; return 0;
} }
static int CmdHelp(const char *Cmd) static int CmdHelp(const char *Cmd) {
{
CmdsHelp(CommandTable); CmdsHelp(CommandTable);
return 0; return 0;
} }

View file

@ -4,6 +4,7 @@ ffffffffffff,//Defaultkey(firstkeyusedbyprogramifnouserdefinedkey)
000000000000,//Blankkey 000000000000,//Blankkey
a0a1a2a3a4a5,//NFCForumMADkey a0a1a2a3a4a5,//NFCForumMADkey
b0b1b2b3b4b5, b0b1b2b3b4b5,
c0c1c2c3c4c5,
aabbccddeeff, aabbccddeeff,
4d3a99c351dd, 4d3a99c351dd,
1a982c7e459a, 1a982c7e459a,
@ -351,3 +352,103 @@ a6cac2886412,
aa0720018738, aa0720018738,
e64a986a5d94, e64a986a5d94,
bf1f4424af76, bf1f4424af76,
#
# Intratone Cogelec
# Data from http://bouzdeck.com/rfid/32-cloning-a-mifare-classic-1k-tag.html
484558414354,
a22ae129c013,
49fae4e3849f,
38fcf33072e0,
8ad5517b4b18,
509359f131b1,
6c78928e1317,
aa0720018738,
a6cac2886412,
62d0c424ed8e,
e64a986a5d94,
8fa1d601d0a2,
89347350bd36,
66d2b7dc39ef,
6bc1e1ae547d,
22729a9bd40f,
#
# Data from https://dfir.lu/blog/cloning-a-mifare-classic-1k-tag.html
925b158f796f,
fad63ecb5891,
bba840ba1c57,
cc6b3b3cd263,
6245e47352e6,
6c78928e1317,
8ed41e8b8056,
2dd39a54e1f3,
6d4c5b3658d2,
1877ed29435a,
52264716efde,
961c0db4a7ed,
703140fd6d86,
157c9a513fa5,
e2a5dc8e066f,
#
# Data from a oyster card
374bf468607f,
bfc8e353af63,
15cafd6159f6,
62efd80ab715,
987a7f7f1a35,
c4104fa3c526,
4c961f23e6be,
67546972bc69,
f4cd5d4c13ff,
94414c1a07dc,
16551d52fd20,
9cb290282f7d,
77a84170b574,
ed646c83a4f3,
e703589db50b,
513c85d06cde,
95093f0b2e22,
543b01b27a95,
c6d375b99972,
ee4cc572b40e,
5106ca7e4a69,
c96bd1ce607f,
167a1be102e0,
a8d0d850a606,
a2abb693ce34,
7b296c40c486,
91f93a5564c9,
e10623e7a016,
b725f9cbf183,
#
# Data from FDi tag
8829da9daf76,
#
# Data from GitHub issue
0A7932DC7E65,
11428B5BCE06,
11428B5BCE07,
11428B5BCE08,
11428B5BCE09,
11428B5BCE0A,
11428B5BCE0F,
18971D893494,
25D60050BF6E,
3FA7217EC575,
44F0B5FBE344,
7B296F353C6B,
8553263F4FF0,
8E5D33A6ED51,
9F42971E8322,
C620318EF179,
D4FE03CE5B06,
D4FE03CE5B07,
D4FE03CE5B08,
D4FE03CE5B09,
D4FE03CE5B0A,
D4FE03CE5B0F,
E241E8AFCBAF,
#
# Data from forum post
123F8888F322,
050908080008,

View file

@ -84,10 +84,8 @@ int saveFile(const char *preferredName, const char *suffix, const void* data, si
return 1; return 1;
} }
fwrite(data, 1, datalen, f); fwrite(data, 1, datalen, f);
if (f) { if (f)
fclose(f); fclose(f);
f = NULL;
}
prnlog("Saved data to '%s'", fileName); prnlog("Saved data to '%s'", fileName);
free(fileName); free(fileName);
return 0; return 0;

View file

@ -7,6 +7,7 @@ local _keys = {
'000000000000', -- Blank key '000000000000', -- Blank key
'a0a1a2a3a4a5', -- NFCForum MAD key 'a0a1a2a3a4a5', -- NFCForum MAD key
'b0b1b2b3b4b5', 'b0b1b2b3b4b5',
'c0c1c2c3c4c5',
'aabbccddeeff', 'aabbccddeeff',
'4d3a99c351dd', '4d3a99c351dd',
'1a982c7e459a', '1a982c7e459a',
@ -454,6 +455,63 @@ local _keys = {
--[[ --[[
--]] --]]
'a56c2df9a26d', 'a56c2df9a26d',
--[[
Intratone Cogelec
Data from http://bouzdeck.com/rfid/32-cloning-a-mifare-classic-1k-tag.html
--]]
'484558414354',
'a22ae129c013',
'49fae4e3849f',
'38fcf33072e0',
'8ad5517b4b18',
'509359f131b1',
'6c78928e1317',
'aa0720018738',
'a6cac2886412',
'62d0c424ed8e',
'e64a986a5d94',
'8fa1d601d0a2',
'89347350bd36',
'66d2b7dc39ef',
'6bc1e1ae547d',
'22729a9bd40f',
--[[
Data from a oyster card
--]]
'374bf468607f',
'bfc8e353af63',
'15cafd6159f6',
'62efd80ab715',
'987a7f7f1a35',
'c4104fa3c526',
'4c961f23e6be',
'67546972bc69',
'f4cd5d4c13ff',
'94414c1a07dc',
'16551d52fd20',
'9cb290282f7d',
'77a84170b574',
'ed646c83a4f3',
'e703589db50b',
'513c85d06cde',
'95093f0b2e22',
'543b01b27a95',
'c6d375b99972',
'ee4cc572b40e',
'5106ca7e4a69',
'c96bd1ce607f',
'167a1be102e0',
'a8d0d850a606',
'a2abb693ce34',
'7b296c40c486',
'91f93a5564c9',
'e10623e7a016',
'b725f9cbf183',
--[[
Data from forum post
--]]
"123F8888F322",
"050908080008",
} }
--- ---

View file

@ -685,11 +685,11 @@ bool detect_classic_prng(){
uint8_t cmd[] = {MIFARE_AUTH_KEYA, 0x00}; uint8_t cmd[] = {MIFARE_AUTH_KEYA, 0x00};
uint32_t flags = ISO14A_CONNECT | ISO14A_RAW | ISO14A_APPEND_CRC; uint32_t flags = ISO14A_CONNECT | ISO14A_RAW | ISO14A_APPEND_CRC;
UsbCommand cAuth = {CMD_READER_ISO_14443a, {flags, sizeof(cmd), 0}}; UsbCommand c = {CMD_READER_ISO_14443a, {flags, sizeof(cmd), 0}};
memcpy(cAuth.d.asBytes, cmd, sizeof(cmd)); memcpy(c.d.asBytes, cmd, sizeof(cmd));
clearCommandBuffer(); clearCommandBuffer();
SendCommand(&cAuth); SendCommand(&c);
WaitForResponse(CMD_ACK, &resp); WaitForResponse(CMD_ACK, &resp);
WaitForResponse(CMD_ACK, &respA); WaitForResponse(CMD_ACK, &respA);

View file

@ -1,19 +1,25 @@
---
-- requirements
local cmds = require('commands') local cmds = require('commands')
local getopt = require('getopt') local getopt = require('getopt')
local utils = require('utils') local utils = require('utils')
local lib14a = require('read14a') local lib14a = require('read14a')
local json = require('dkjson')
local toys = require('default_toys_di')
example =[[ example =[[
script run didump script run didump
script run didump -t script run didump -t
script run didump -r
]] ]]
author = "Iceman" author = "Iceman"
usage = "script run didump -h -t" usage = "script run didump -h -t"
desc = [[ desc = [[
This is a script to dump and decrypt the data of a specific type of Mifare Mini token. This is a script to dump and decrypt the data of a specific type of Mifare Mini token.
The dump is decrypted. If a raw dump is wanted, use the -r parameter
Arguments: Arguments:
-h : this help -h : this help
-r : raw
-t : selftest -t : selftest
]] ]]
@ -21,40 +27,57 @@ local band=bit32.band
local bor=bit32.bor local bor=bit32.bor
local bnot=bit32.bnot local bnot=bit32.bnot
local bxor=bit32.bxor local bxor=bit32.bxor
local lshift=bit32.lshift local lsh=bit32.lshift
local rshift=bit32.rshift local rsh=bit32.rshift
local FOO = 'AF62D2EC0491968CC52A1A7165F865FE' local FOO = 'AF62D2EC0491968CC52A1A7165F865FE'
local BAR = '286329204469736E65792032303133' local BAR = '286329204469736E65792032303133'
local MIS = '0A14FD0507FF4BCD026BA83F0A3B89A9' local MIS = '0A14FD0507FF4BCD026BA83F0A3B89A9'
local RANDOM = FOO..BAR
local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S"); local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S");
local TIMEOUT = 2000 local TIMEOUT = 2000
local DEBUG = false local DEBUG = true
local numBlocks = 20 local numBlocks = 20
local numSectors = 5 local numSectors = 5
local CHECKSUM_OFFSET = 12; -- +1??? local CHECKSUM_OFFSET = 12; -- +1???
--- ---
-- A debug printout-function -- A debug printout-function
function dbg(args) local function dbg(args)
if DEBUG then if not DEBUG then return end
if type(args) == "table" then
local i = 1
while args[i] do
print("###", args[i])
i = i+1
end
else
print("###", args) print("###", args)
end end
end end
--- ---
-- This is only meant to be used when errors occur -- This is only meant to be used when errors occur
function oops(err) local function oops(err)
print("ERROR: ",err) print("ERROR: ",err)
core.clearCommandBuffer() core.clearCommandBuffer()
return false
end end
--- ---
-- Usage help -- Usage help
function help() local function help()
print(desc) print(desc)
print("Example usage") print("Example usage")
print(example) print(example)
end end
--- ---
--
local function print_info(tagdata)
--got table with data.
local h = tagdata[2]:sub(1,8)
local t = tostring( tonumber( h, 16 ) )
local item = toys.Find(t)
print( ("Modelid : %s , %s, v.%s.0"):format(t, item[3], item[2]))
end
---
-- Get checksum, -- Get checksum,
-- called: data is string (32 hex digits) -- called: data is string (32 hex digits)
-- returns: number -- returns: number
@ -333,7 +356,7 @@ _tbl[255] = { 0x2D02EF8D }
for i,item in pairs(data) do for i,item in pairs(data) do
local tmp = band(ret, 0xFF) local tmp = band(ret, 0xFF)
local index = band( bxor(tmp, item), 0xFF) local index = band( bxor(tmp, item), 0xFF)
ret = bxor(rshift(ret,8), _tbl[index][1]) ret = bxor(rsh(ret,8), _tbl[index][1])
end end
return ret return ret
end end
@ -375,10 +398,111 @@ local function keygen(uid)
) )
end end
--- encode 'table' into a json formatted string
--
local function convert_to_json( obj )
if type(obj) == "table" then
return json.encode (obj, { indent = true })
end
return oops('[fail] input object must be a lua-TABLE')
end
--
-- Save
local function save_json(filename, data)
jsondata = convert_to_json(data)
filename = filename or 'dumpdata.json'
local f = io.open(filename, "w")
if not f then return oops(string.format("Could not write to file %s", tostring(filename))) end
f:write(jsondata)
io.close(f)
return filename
end
--- loads a json formatted text file with
--
-- @param filename the file containing the json-dump (defaults to dumpdata.json)
local function load_json(filename)
filename = filename or 'dumpdata.json'
local f = io.open(filename, "rb")
if not f then return oops(string.format("Could not read file %s", tostring(filename))) end
-- Read file
local t = f:read("*all")
io.close(f)
local obj, pos, err = json.decode(t, 1, nil)
if err then return oops(string.format("importing json file failed. %s", err)) end
dbg(string.format('loaded file %s', input))
return obj
-- local len, hex = bin.unpack( ("H%d"):format(#t), t)
end
---
-- Generate encryption key
local function create_key(uid)
local key = ''
local sha = utils.Sha1Hex( FOO..BAR..uid )
sha = utils.ConvertBytesToHex( utils.ConvertAsciiToBytes(sha:sub(1,16)) )
key = utils.SwapEndiannessStr( sha:sub(1,8) , 32 )
key = key..utils.SwapEndiannessStr( sha:sub(9,16), 32 )
key = key..utils.SwapEndiannessStr( sha:sub(17,24), 32 )
key = key..utils.SwapEndiannessStr( sha:sub(25,32), 32 )
return key
end
--- reads all blocks from tag
--
local function readtag(mfkey, aeskey )
local tagdata = {}
for blockNo = 0, numBlocks-1 do
if core.ukbhit() then
print("[fail] aborted by user")
return nil
end
-- read block from tag.
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blockNo ,arg2 = 0,arg3 = 0, data = mfkey}
local err = core.SendCommand(cmd:getBytes())
if err then return oops(err) end
local blockdata, err = waitCmd()
if err then return oops(err) end
-- rules:
-- the following blocks is NOT encrypted
-- block 0 (manufacturing) and 18
-- block with all zeros
-- sector trailor
if blockNo == 0 or blockNo == 18 then
elseif blockNo%4 ~= 3 then
if not string.find(blockdata, '^0+$') then
if aeskey then
local decrypted, err = core.aes128_decrypt_ecb(aeskey, blockdata)
if err then dbg(err) end
blockdata = utils.ConvertAsciiToHex(decrypted)
end
end
else
-- Sectorblocks, not encrypted, but we add our known key to it since it is normally zeros.
blockdata = mfkey..blockdata:sub(13,20)..mfkey
--dbg(blockdata:sub(13,20))
end
table.insert(tagdata, blockdata)
end
return tagdata
end
---
-- simple selftest of functionality
local function selftest() local function selftest()
local testdata = '000F42430D0A14000001D11F'..'5D738517' local testdata = '000F42430D0A14000001D11F'..'5D738517'
local chksum = getChecksum(testdata) local chksum = getChecksum(testdata)
local calc = calculateChecksum( utils.ConvertHexToBytes(testdata:sub(1,24))) local calc = calculateChecksum( utils.ConvertHexToBytes(testdata:sub(1,24)))
print ( testdata:sub(1,24) )
print ( ('%x - %x'):format(chksum, calc))
local isValid = false local isValid = false
local validStr = "FAIL" local validStr = "FAIL"
if calc == chksum then if calc == chksum then
@ -399,6 +523,15 @@ local function selftest()
print ('TEST KEY :: '..testkey) print ('TEST KEY :: '..testkey)
print ('VALID KEY :: 29564af75805') print ('VALID KEY :: 29564af75805')
end end
local function setdevicedebug( status )
local c = 'hf mf dbg '
if status then
c = c..'1'
else
c = c..'0'
end
core.console(c)
end
--- ---
-- The main entry point -- The main entry point
-- -d decrypt -- -d decrypt
@ -406,74 +539,60 @@ end
-- -v validate -- -v validate
function main(args) function main(args)
local cmd, result, err, blockNo, keyA local cmd, tag, err, blockNo, mfkey
local shall_validate = false
local shall_dec = false
local shall_enc = false
local blocks = {} local blocks = {}
local magic = '' local aeskey = ''
local input = ''
-- Read the parameters -- Read the parameters
for o, a in getopt.getopt(args, 'ht') do for o, a in getopt.getopt(args, 'htdevi:') do
if o == "h" then help() return end if o == "h" then help() return end
if o == "t" then return selftest() end if o == "t" then return selftest() end
if o == "d" then shall_dec = true end
if o == "e" then shall_enc = true end
if o == "v" then shall_validate = true end
if o == "i" then input = load_json(a) end
end end
-- Turn off Debug -- Turn off Debug
local cmdSetDbgOff = "hf mf dbg 0" setdevicedebug(false)
core.console( cmdSetDbgOff)
-- GET TAG UID -- GET TAG UID
tag, err = lib14a.read1443a(false)
result, err = lib14a.read1443a(false) if not tag then return oops(err) end
if not result then
return oops(err)
end
core.clearCommandBuffer() core.clearCommandBuffer()
local keyA = keygen(result.uid) -- simple tag check
if 0x09 ~= tag.sak then
-- Show tag info if 0x4400 ~= tag.atqa then
print((' Found tag %s'):format(result.name)) return oops(('[fail] found tag %s :: looking for Mifare Mini 0.3k'):format(tag.name))
local longrandom = RANDOM..result.uid
local res = utils.Sha1Hex(longrandom)
res = utils.ConvertBytesToHex(utils.ConvertAsciiToBytes(res:sub(1,16)))
magic = utils.SwapEndiannessStr(res:sub(1,8) , 32)
magic = magic..utils.SwapEndiannessStr( res:sub(9,16),32)
magic = magic..utils.SwapEndiannessStr( res:sub(17,24),32)
magic = magic..utils.SwapEndiannessStr( res:sub(25,32),32)
print('Reading card data')
print('Raw','Decrypted')
for blockNo = 0, numBlocks-1, 1 do
if core.ukbhit() then
print("aborted by user")
break
end end
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blockNo ,arg2 = 0,arg3 = 0, data = keyA}
local err = core.SendCommand(cmd:getBytes())
if err then return oops(err) end
local blockdata, err = waitCmd()
if err then return oops(err) end
if blockNo%4 ~= 3 then
-- blocks with zero not encrypted.
if string.find(blockdata, '^0+$') then
print(blockdata, blockdata)
else
local aes = core.aes128_decrypt_ecb(magic, blockdata)
local bytes = utils.ConvertAsciiToBytes(aes)
local hex = utils.ConvertBytesToHex(bytes)
print(blockdata , hex)
end end
elseif blockNo == 0 then dbg ('[ok] found '..tag.name)
print(blockdata,blockdata)
else -- tag key
-- Sectorblocks, not encrypted mfkey = keygen(tag.uid)
local sectortrailer = keyA..blockdata:sub(13,20)..keyA dbg('[ok] using mf keyA : '.. mfkey)
print(sectortrailer, sectortrailer, blockdata:sub(13,20))
end -- AES key
end aeskey = create_key(tag.uid)
dbg('[ok] using AES key : '.. aeskey)
-- read tag data, complete, enc/dec
tagdata = readtag(mfkey, aeskey)
dbg('[ok] read card data')
-- show information?
print_info(tagdata)
-- save
res = save_json(nil, tagdata)
if not res then return oops('[fail] saving json file') end
dbg('[ok] read card data')
end end
main(args) main(args)