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) {
// flush
clearCommandBuffer();
// parse
CmdsParse(CommandTable, Cmd);
return 0;
}
static int CmdHelp(const char *Cmd)
{
static int CmdHelp(const char *Cmd) {
CmdsHelp(CommandTable);
return 0;
}

View file

@ -4,6 +4,7 @@ ffffffffffff,//Defaultkey(firstkeyusedbyprogramifnouserdefinedkey)
000000000000,//Blankkey
a0a1a2a3a4a5,//NFCForumMADkey
b0b1b2b3b4b5,
c0c1c2c3c4c5,
aabbccddeeff,
4d3a99c351dd,
1a982c7e459a,
@ -351,3 +352,103 @@ a6cac2886412,
aa0720018738,
e64a986a5d94,
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;
}
fwrite(data, 1, datalen, f);
if (f) {
if (f)
fclose(f);
f = NULL;
}
prnlog("Saved data to '%s'", fileName);
free(fileName);
return 0;

View file

@ -7,6 +7,7 @@ local _keys = {
'000000000000', -- Blank key
'a0a1a2a3a4a5', -- NFCForum MAD key
'b0b1b2b3b4b5',
'c0c1c2c3c4c5',
'aabbccddeeff',
'4d3a99c351dd',
'1a982c7e459a',
@ -454,6 +455,63 @@ local _keys = {
--[[
--]]
'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};
uint32_t flags = ISO14A_CONNECT | ISO14A_RAW | ISO14A_APPEND_CRC;
UsbCommand cAuth = {CMD_READER_ISO_14443a, {flags, sizeof(cmd), 0}};
memcpy(cAuth.d.asBytes, cmd, sizeof(cmd));
UsbCommand c = {CMD_READER_ISO_14443a, {flags, sizeof(cmd), 0}};
memcpy(c.d.asBytes, cmd, sizeof(cmd));
clearCommandBuffer();
SendCommand(&cAuth);
SendCommand(&c);
WaitForResponse(CMD_ACK, &resp);
WaitForResponse(CMD_ACK, &respA);

View file

@ -1,19 +1,25 @@
---
-- requirements
local cmds = require('commands')
local getopt = require('getopt')
local utils = require('utils')
local lib14a = require('read14a')
local json = require('dkjson')
local toys = require('default_toys_di')
example =[[
script run didump
script run didump -t
script run didump -r
]]
author = "Iceman"
usage = "script run didump -h -t"
desc = [[
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:
-h : this help
-r : raw
-t : selftest
]]
@ -21,40 +27,57 @@ local band=bit32.band
local bor=bit32.bor
local bnot=bit32.bnot
local bxor=bit32.bxor
local lshift=bit32.lshift
local rshift=bit32.rshift
local lsh=bit32.lshift
local rsh=bit32.rshift
local FOO = 'AF62D2EC0491968CC52A1A7165F865FE'
local BAR = '286329204469736E65792032303133'
local MIS = '0A14FD0507FF4BCD026BA83F0A3B89A9'
local RANDOM = FOO..BAR
local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S");
local TIMEOUT = 2000
local DEBUG = false
local DEBUG = true
local numBlocks = 20
local numSectors = 5
local CHECKSUM_OFFSET = 12; -- +1???
---
-- A debug printout-function
function dbg(args)
if DEBUG then
local function dbg(args)
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)
end
end
---
-- This is only meant to be used when errors occur
function oops(err)
local function oops(err)
print("ERROR: ",err)
core.clearCommandBuffer()
return false
end
---
-- Usage help
function help()
local function help()
print(desc)
print("Example usage")
print(example)
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,
-- called: data is string (32 hex digits)
-- returns: number
@ -333,7 +356,7 @@ _tbl[255] = { 0x2D02EF8D }
for i,item in pairs(data) do
local tmp = band(ret, 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
return ret
end
@ -375,10 +398,111 @@ local function keygen(uid)
)
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 testdata = '000F42430D0A14000001D11F'..'5D738517'
local chksum = getChecksum(testdata)
local calc = calculateChecksum( utils.ConvertHexToBytes(testdata:sub(1,24)))
print ( testdata:sub(1,24) )
print ( ('%x - %x'):format(chksum, calc))
local isValid = false
local validStr = "FAIL"
if calc == chksum then
@ -399,6 +523,15 @@ local function selftest()
print ('TEST KEY :: '..testkey)
print ('VALID KEY :: 29564af75805')
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
-- -d decrypt
@ -406,74 +539,60 @@ end
-- -v validate
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 magic = ''
local aeskey = ''
local input = ''
-- 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 == "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
-- Turn off Debug
local cmdSetDbgOff = "hf mf dbg 0"
core.console( cmdSetDbgOff)
setdevicedebug(false)
-- GET TAG UID
result, err = lib14a.read1443a(false)
if not result then
return oops(err)
end
tag, err = lib14a.read1443a(false)
if not tag then return oops(err) end
core.clearCommandBuffer()
local keyA = keygen(result.uid)
-- Show tag info
print((' Found tag %s'):format(result.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
-- simple tag check
if 0x09 ~= tag.sak then
if 0x4400 ~= tag.atqa then
return oops(('[fail] found tag %s :: looking for Mifare Mini 0.3k'):format(tag.name))
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
elseif blockNo == 0 then
print(blockdata,blockdata)
else
-- Sectorblocks, not encrypted
local sectortrailer = keyA..blockdata:sub(13,20)..keyA
print(sectortrailer, sectortrailer, blockdata:sub(13,20))
end
end
dbg ('[ok] found '..tag.name)
-- tag key
mfkey = keygen(tag.uid)
dbg('[ok] using mf keyA : '.. mfkey)
-- AES key
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
main(args)