mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-01-01 05:07:03 +08:00
CHG: 'script run didump' - got some remake. unfinished.
CHG: some default keys
This commit is contained in:
parent
3ca3d401c0
commit
a211877853
6 changed files with 347 additions and 75 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
|
@ -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;
|
||||||
|
|
|
@ -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",
|
||||||
}
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue