2020-03-17 18:37:38 +08:00
local utils = require ( ' utils ' )
2020-03-19 17:29:39 +08:00
local getopt = require ( ' getopt ' )
2020-04-21 01:29:32 +08:00
local cmds = require ( ' commands ' )
2020-03-17 18:37:38 +08:00
local read14a = require ( ' read14a ' )
2020-04-21 01:29:32 +08:00
--
---
-------------------------------
-- Notes
-------------------------------
---
--
2020-03-21 19:34:58 +08:00
--[[
2020-03-21 17:04:03 +08:00
---Suggestions of improvement:
--- Add support another types of dumps: BIN, JSON
--- Maybe it will be not only as `mfc_gen3_writer`, like a universal dump manager.
--- Add undependence from the operation system. At the moment code not working in Linux.
--- Add more chinesse backdoors RAW commands for UID changing (find RAW for the 4 byte familiar chinese card, from native it soft: http://bit.ly/39VIDsU)
--- Hide system messages when you writing a dumps, replace it to some of like [#####----------] 40%
-- iceman notes:
-- doesn't take consideration filepaths for dump files.
-- doesn't allow A keys for authenticating when writing
-- doesn't verify that card is magic gen3.
2020-03-21 19:34:58 +08:00
-- doesn't take several versions of same dump ( -1, -2, -3 ) styles.
2020-03-21 17:04:03 +08:00
--]]
2020-04-21 01:29:32 +08:00
--
---
-------------------------------
-- Script hat
-------------------------------
---
--
2020-03-18 18:39:10 +08:00
copyright = ' '
author = ' Winds '
version = ' v1.0.0 '
desc = [ [
2020-03-21 17:04:03 +08:00
The script gives you a easy way to write your * . eml dumps onto normal MFC and magic Gen3 cards .
Works with both 4 and 7 bytes NXP MIFARE Classic 1 K cards .
The script also has the possibility to change UID and permanent lock uid on magic Gen3 cards .
2020-04-22 05:24:01 +08:00
2020-03-21 17:04:03 +08:00
It supports the following functionality .
2020-03-18 18:39:10 +08:00
2020-03-21 17:04:03 +08:00
1. Write it to the same of current card UID .
2. Write it to magic Gen3 card .
3. Change uid to match dump on magic Gen3 card .
4. Permanent lock UID on magic Gen3 card .
5. Erase all data at the card and set the FF FF FF FF FF FF keys , and Access Conditions to 78778800.
2020-04-22 05:24:01 +08:00
2020-03-21 17:04:03 +08:00
Script works in a wizard styled way .
2020-03-18 18:39:10 +08:00
] ]
example = [ [
2020-03-21 17:04:03 +08:00
1. script run mfc_gen3_writer
2020-03-18 18:39:10 +08:00
] ]
usage = [ [
2020-03-21 17:04:03 +08:00
Select your * . eml dump from list to write to the card .
2020-03-18 18:39:10 +08:00
] ]
2020-04-21 01:29:32 +08:00
--
---
2020-03-21 19:34:58 +08:00
-------------------------------
2020-04-21 01:29:32 +08:00
-- Global variables
2020-03-21 19:34:58 +08:00
-------------------------------
---
2020-04-21 01:29:32 +08:00
--
local DEBUG = false -- the debug flag
local files = { } -- Array for eml files
local b_keys = { } -- Array for B keys
local eml = { } -- Array for data in block 32
local num_dumps = 0 -- num of found eml dump files
local tab = string.rep ( ' - ' , 64 )
local empty = string.rep ( ' 0 ' , 32 ) -- Writing blocks
local default_key = ' FFFFFFFFFFFF ' -- Writing blocks
local default_key_type = ' 01 ' --KeyA: 00, KeyB: 01
local default_key_blk = ' FFFFFFFFFFFF78778800FFFFFFFFFFFF ' -- Writing blocks
local piswords_uid_lock = ' hf 14a raw -s -c -t 2000 90fd111100 '
local piswords_uid_change = ' hf 14a raw -s -c -t 2000 90f0cccc10 '
local cmd_wrbl = ' hf mf wrbl %d B %s %s ' -- Writing blocks
--
---
-------------------------------
2020-03-21 19:34:58 +08:00
-- A debug printout-function
2020-04-21 01:29:32 +08:00
-------------------------------
---
--
2020-03-21 19:34:58 +08:00
local function dbg ( args )
if not DEBUG then return end
if type ( args ) == ' table ' then
local i = 1
while args [ i ] do
dbg ( args [ i ] )
i = i + 1
end
else
print ( ' ### ' , args )
end
end
2020-04-21 01:29:32 +08:00
--
2020-03-21 19:34:58 +08:00
---
2020-04-21 01:29:32 +08:00
-------------------------------
2020-03-21 19:34:58 +08:00
-- This is only meant to be used when errors occur
2020-04-21 01:29:32 +08:00
-------------------------------
---
--
2020-03-21 19:34:58 +08:00
local function oops ( err )
print ( ' ERROR: ' , err )
core.clearCommandBuffer ( )
return nil , err
end
2020-04-21 01:29:32 +08:00
--
2020-03-19 17:29:39 +08:00
---
2020-04-21 01:29:32 +08:00
-------------------------------
2020-03-19 17:29:39 +08:00
-- Usage help
2020-04-21 01:29:32 +08:00
-------------------------------
---
--
2020-03-19 17:29:39 +08:00
local function help ( )
print ( copyright )
print ( author )
print ( version )
print ( desc )
2020-03-21 19:34:58 +08:00
print ( ' Example usage ' )
2020-03-19 17:29:39 +08:00
print ( example )
print ( usage )
end
2020-04-21 01:29:32 +08:00
--
2020-03-21 17:04:03 +08:00
---
2020-04-21 01:29:32 +08:00
-------------------------------
2020-03-21 17:04:03 +08:00
-- GetUID
2020-04-21 01:29:32 +08:00
-------------------------------
---
--
2020-03-21 17:04:03 +08:00
local function GetUID ( )
return read14a.read ( true , true ) . uid
2020-03-17 18:37:38 +08:00
end
2020-04-16 15:01:14 +08:00
--
2020-03-21 17:04:03 +08:00
local function dropfield ( )
2020-03-17 18:37:38 +08:00
read14a.disconnect ( )
core.clearCommandBuffer ( )
end
2020-04-21 01:29:32 +08:00
--
2020-03-21 17:04:03 +08:00
---
2020-04-21 01:29:32 +08:00
-------------------------------
2020-03-21 17:04:03 +08:00
-- Wait for tag (MFC)
2020-04-21 01:29:32 +08:00
-------------------------------
---
--
2020-03-18 18:39:10 +08:00
local function wait ( )
read14a.waitFor14443a ( )
2020-03-17 18:37:38 +08:00
end
2020-04-21 01:29:32 +08:00
--
---
-------------------------------
2020-04-22 23:59:02 +08:00
-- Return key code 00/01 to string
-------------------------------
---
--
local function KeyAB ( )
if default_key_type == ' 00 ' then
return ' KeyA '
else
return ' KeyB '
end
end
--
---
-------------------------------
-- Check response from Proxmark
2020-04-21 01:29:32 +08:00
-------------------------------
---
--
local function getblockdata ( response )
if response.Status == 0 then
return true
else
return false
end
end
--
2020-04-22 23:59:02 +08:00
---
-------------------------------
-- Check 0xFFFFFFFFFFFF key for tag (MFC)
-------------------------------
---
--
2020-04-21 01:29:32 +08:00
local function checkkey ( )
local status = 0
for i = 1 , # eml do
2020-04-22 23:59:02 +08:00
cmd = Command : newNG { cmd = cmds.CMD_HF_MIFARE_READBL , data = ( ' %02x%02x%s ' ) : format ( ( i - 1 ) , default_key_type , default_key ) }
2020-04-21 01:29:32 +08:00
if ( getblockdata ( cmd : sendNG ( false ) ) == true ) then
status = status + 1
2020-04-22 23:59:02 +08:00
print ( ( ' %s %02s %s %s %s ' ) : format ( ' ' , ( i - 1 ) , KeyAB ( ) , default_key , ' OK ' ) )
2020-04-21 01:29:32 +08:00
else
break
end
end
if status == # eml then
return true
end
end
--
---
-------------------------------
-- Check Pissword backdor
-------------------------------
---
--
local function checkmagic ( )
--Have no RAW ISO14443A command in appmain.c
cmd = Command : newNG { cmd = cmds.CMD_HF_ISO14443A_READER , data = piswords_uid_change .. GetUID ( ) } -- sample check to pull the same UID to card and check response
if ( getblockdata ( cmd : sendNG ( false ) ) == true ) then
print ( ' Magic ' )
else
print ( ' Not magic ' )
end
end
--
---
-------------------------------
-- Main function
-------------------------------
2020-03-21 17:04:03 +08:00
---
--
2020-03-18 18:39:10 +08:00
local function main ( args )
2020-04-21 01:29:32 +08:00
--
---
-------------------------------
-- Arguments for script
-------------------------------
---
--
2020-03-21 19:37:40 +08:00
for o , a in getopt.getopt ( args , ' hd ' ) do
2020-03-19 17:29:39 +08:00
if o == ' h ' then return help ( ) end
2020-03-21 19:37:40 +08:00
if o == ' d ' then DEBUG = true end
2020-03-19 17:29:39 +08:00
end
2020-03-21 17:04:03 +08:00
--
2020-03-18 18:39:10 +08:00
wait ( )
print ( tab )
2020-04-21 01:29:32 +08:00
--
---
-------------------------------
-- Detect 7/4 byte card
-------------------------------
---
--
2020-04-16 15:01:14 +08:00
if string.len ( GetUID ( ) ) == 14 then
2020-04-21 01:29:32 +08:00
eml_file_uid_start = 18 -- For windows with '---------- ' prefix
eml_file_uid_end = 31
eml_file_lengt = 40
else
eml_file_uid_start = 18 -- For windows with '---------- ' prefix
eml_file_uid_end = 25
eml_file_lengt = 34
2020-04-16 15:01:14 +08:00
end
2020-03-21 19:34:58 +08:00
dropfield ( )
2020-04-21 01:29:32 +08:00
--
---
-------------------------------
-- List all EML files in /client
-------------------------------
---
--
local dumpEML = ' find "." "*dump.eml" ' -- Fixed for windows
2020-04-16 15:01:14 +08:00
local p = assert ( io.popen ( dumpEML ) )
2020-03-21 19:34:58 +08:00
for _ in p : lines ( ) do
-- The length of eml file
2020-04-21 01:29:32 +08:00
if string.len ( _ ) == eml_file_lengt then
2020-03-21 19:34:58 +08:00
num_dumps = num_dumps + 1
2020-04-21 01:29:32 +08:00
-- cut UID from eml file
files [ num_dumps ] = string.sub ( _ , eml_file_uid_start , eml_file_uid_end ) -- cut numeretic UID
2020-03-21 19:34:58 +08:00
print ( ' ' .. num_dumps .. ' | ' .. files [ num_dumps ] )
2020-03-17 18:37:38 +08:00
end
2020-04-16 15:01:14 +08:00
end
2020-04-21 01:29:32 +08:00
--
2020-03-21 19:40:16 +08:00
p.close ( )
2020-04-21 01:29:32 +08:00
--
2020-03-21 19:34:58 +08:00
if num_dumps == 0 then return oops ( " Didn't find any dump files " ) end
2020-04-21 01:29:32 +08:00
--
2020-03-17 18:37:38 +08:00
print ( tab )
2020-03-21 17:04:03 +08:00
print ( ' Your card has UID ' .. GetUID ( ) )
print ( ' ' )
print ( ' Select which dump to write (1 until ' .. num_dumps .. ' ) ' )
2020-03-18 18:39:10 +08:00
print ( tab )
2020-03-21 17:04:03 +08:00
io.write ( ' --> ' )
2020-04-21 01:29:32 +08:00
--
local uid_no = tonumber ( io.read ( ) )
2020-03-18 18:39:10 +08:00
print ( tab )
2020-04-21 01:29:32 +08:00
print ( ' You have been selected card dump No ' .. uid_no .. ' , with UID: ' .. files [ uid_no ] .. ' . Your card UID: ' .. GetUID ( ) )
--
--
---
-------------------------------
-- Load eml file
-------------------------------
---
--
local dumpfile = assert ( io.open ( ' ./hf-mf- ' .. files [ uid_no ] .. ' -dump.eml ' , ' r ' ) )
2020-03-21 19:40:16 +08:00
for _ in dumpfile : lines ( ) do table.insert ( eml , _ ) ; end
dumpfile.close ( )
2020-04-21 01:29:32 +08:00
--
---
-------------------------------
2020-04-22 05:24:01 +08:00
-- Extract B key from EML file
2020-04-21 01:29:32 +08:00
-------------------------------
---
2020-04-22 05:24:01 +08:00
--
2020-03-21 17:04:03 +08:00
local b = 0
2020-03-18 18:39:10 +08:00
for i = 1 , # eml do
if ( i % 4 == 0 ) then
repeat
b = b + 1
2020-03-21 17:04:03 +08:00
-- Cut key from block
2020-04-16 15:01:14 +08:00
b_keys [ b ] = string.sub ( eml [ i ] , ( # eml [ i ] - 11 ) , # eml [ i ] )
2020-03-18 18:39:10 +08:00
until b % 4 == 0
end
2020-04-16 15:01:14 +08:00
end
2020-03-21 17:04:03 +08:00
print ( tab )
2020-03-21 19:34:58 +08:00
dbg ( b_keys )
dbg ( eml )
2020-04-21 01:29:32 +08:00
--
---
-------------------------------
-- Change UID on certain version of magic Gen3 card.
-------------------------------
---
--
2020-03-21 17:04:03 +08:00
if ( utils.confirm ( ' Change UID ? ' ) == true ) then
2020-03-18 18:39:10 +08:00
wait ( )
2020-04-21 01:29:32 +08:00
core.console ( piswords_uid_change .. tostring ( eml [ 1 ] ) )
2020-03-18 18:39:10 +08:00
print ( tab )
2020-03-21 17:04:03 +08:00
print ( ' The new card UID : ' .. GetUID ( ) )
2020-04-22 05:24:01 +08:00
end
2020-04-16 15:01:14 +08:00
print ( tab )
2020-04-21 01:29:32 +08:00
--checkmagic()
--
---
-------------------------------
-- Lock UID
-------------------------------
---
--
2020-03-21 17:04:03 +08:00
if ( utils.confirm ( ' Permanent lock UID ? (card can never change uid again) ' ) == true ) then
2020-03-18 18:39:10 +08:00
wait ( )
2020-04-21 01:29:32 +08:00
core.console ( piswords_uid_lock )
2020-04-16 15:01:14 +08:00
end
2020-04-21 01:29:32 +08:00
--
2020-03-21 17:04:03 +08:00
print ( tab )
2020-04-22 23:59:02 +08:00
print ( ' Going to check the all ' .. KeyAB ( ) .. ' by ' .. default_key )
print ( tab )
2020-04-21 01:29:32 +08:00
--
if checkkey ( ) == true then
2020-04-22 23:59:02 +08:00
print ( tab )
2020-04-21 01:29:32 +08:00
if ( utils.confirm ( ' Card is Empty. Write selected dump to card ? ' ) == true ) then
for i = 1 , # eml do
core.console ( string.format ( cmd_wrbl , ( i - 1 ) , default_key , eml [ i ] ) )
end
2020-03-17 18:37:38 +08:00
end
else
2020-03-18 18:39:10 +08:00
print ( tab )
2020-04-21 01:29:32 +08:00
if ( utils.confirm ( ' Delete ALL data and write all keys to 0x ' .. default_key .. ' ? ' ) == true ) then
2020-03-18 18:39:10 +08:00
wait ( )
for i = 1 , # eml do
if ( i % 4 == 0 ) then
2020-03-21 19:37:40 +08:00
core.console ( string.format ( cmd_wrbl , ( i - 1 ) , b_keys [ i ] , default_key_blk ) )
2020-03-18 18:39:10 +08:00
else
2020-03-21 19:37:40 +08:00
core.console ( string.format ( cmd_wrbl , ( i - 1 ) , b_keys [ i ] , empty ) )
2020-03-18 18:39:10 +08:00
end
end
else
2020-03-21 17:04:03 +08:00
print ( tab )
2020-04-21 01:29:32 +08:00
if ( utils.confirm ( ' Write selected dump to card ? ' ) == true ) then
print ( tab )
wait ( )
for i = 1 , # eml do
core.console ( string.format ( cmd_wrbl , ( i - 1 ) , b_keys [ i ] , eml [ i ] ) )
end
2020-03-18 18:39:10 +08:00
end
2020-03-17 18:37:38 +08:00
end
end
2020-03-21 17:04:03 +08:00
dropfield ( )
print ( tab )
2020-04-21 01:29:32 +08:00
print ( ' You are welcome ' )
2020-03-17 18:37:38 +08:00
end
2020-04-21 01:29:32 +08:00
--
---
-------------------------------
-- Start Main function
-------------------------------
---
--
2020-03-21 17:04:03 +08:00
main ( args )