Merge branch 'master' of github.com:RfidResearchGroup/proxmark3

This commit is contained in:
iceman1001 2020-09-05 07:41:19 +02:00
commit 4a254a13ce
5 changed files with 597 additions and 3 deletions

View file

@ -38,6 +38,9 @@ define KNOWN_STANDALONE_DEFINITIONS
| HF_14ASNIFF | 14a sniff to flashmem | | HF_14ASNIFF | 14a sniff to flashmem |
| (RDV4 only) | | | (RDV4 only) | |
+----------------------------------------------------------+ +----------------------------------------------------------+
| HF_AVEFUL | Mifare ultralight read/simulation |
| | - Ave Ozkal |
+----------------------------------------------------------+
| HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth | | HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth |
| (RDV4 only) | storing in flashmem - Bogito | | (RDV4 only) | storing in flashmem - Bogito |
+----------------------------------------------------------+ +----------------------------------------------------------+
@ -62,7 +65,7 @@ define KNOWN_STANDALONE_DEFINITIONS
endef endef
STANDALONE_MODES := LF_SKELETON LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RWC LF_HIDBRUTE LF_ICEHID LF_PROXBRUTE LF_SAMYRUN STANDALONE_MODES := LF_SKELETON LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RWC LF_HIDBRUTE LF_ICEHID LF_PROXBRUTE LF_SAMYRUN
STANDALONE_MODES += HF_14ASNIFF HF_BOG HF_COLIN HF_ICECLASS HF_LEGIC HF_MATTYRUN HF_MSDSAL HF_YOUNG STANDALONE_MODES += HF_14ASNIFF HF_AVEFUL HF_BOG HF_COLIN HF_ICECLASS HF_LEGIC HF_MATTYRUN HF_MSDSAL HF_YOUNG
STANDALONE_MODES_REQ_SMARTCARD := STANDALONE_MODES_REQ_SMARTCARD :=
STANDALONE_MODES_REQ_FLASH := LF_ICEHID HF_14ASNIFF HF_BOG HF_COLIN HF_ICECLASS STANDALONE_MODES_REQ_FLASH := LF_ICEHID HF_14ASNIFF HF_BOG HF_COLIN HF_ICECLASS
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),) ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),)

View file

@ -37,6 +37,10 @@ endif
ifneq (,$(findstring WITH_STANDALONE_HF_14ASNIFF,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_HF_14ASNIFF,$(APP_CFLAGS)))
SRC_STANDALONE = hf_14asniff.c SRC_STANDALONE = hf_14asniff.c
endif endif
# WITH_STANDALONE_HF_AVEFUL
ifneq (,$(findstring WITH_STANDALONE_HF_AVEFUL,$(APP_CFLAGS)))
SRC_STANDALONE = hf_aveful.c
endif
# WITH_STANDALONE_LF_ICEHID # WITH_STANDALONE_LF_ICEHID
ifneq (,$(findstring WITH_STANDALONE_LF_ICEHID,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_LF_ICEHID,$(APP_CFLAGS)))
SRC_STANDALONE = lf_icehid.c SRC_STANDALONE = lf_icehid.c

View file

@ -0,0 +1,127 @@
//-----------------------------------------------------------------------------
// A. Ozkal, 2020
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// main code for HF Mifare Ultralight read/simulation by Ave Ozkal
//-----------------------------------------------------------------------------
// Several parts of this code is based on code by Craig Young from HF_YOUNG
// This code does not:
// - Account for cards with authentication (MFU EV1 etc)
// - Determine if cards have block count that's not the same as the BLOCKS def
#include "standalone.h" // standalone definitions
#include "proxmark3_arm.h"
#include "appmain.h"
#include "fpgaloader.h"
#include "util.h"
#include "dbprint.h"
#include "ticks.h" // SpinDelay
#include "mifareutil.h"
#include "iso14443a.h"
#define BLOCKS 16
#define SAK 0x00
#define ATQA0 0x44
#define ATQA1 0x00
#define STATE_SEARCH 0
#define STATE_READ 1
#define STATE_EMUL 2
typedef struct {
uint8_t uid[10];
uint8_t uidlen;
uint8_t atqa[2];
uint8_t sak;
} PACKED card_clone_t;
void ModInfo(void) {
DbpString(" HF Mifare Ultralight read/simulation by Ave Ozkal");
}
void RunMod(void) {
StandAloneMode();
Dbprintf("AveFUL (MF Ultralight read/emul) started");
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
// the main loop for your standalone mode
for (;;) {
WDT_HIT();
// exit from RunMod, send a usbcommand.
if (data_available()) break;
iso14a_card_select_t card;
SpinDelay(500);
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
// 0 = search, 1 = read, 2 = emul
int state = STATE_SEARCH;
DbpString("Scanning...");
for (;;) {
// Was our button held down or pressed?
int button_pressed = BUTTON_HELD(1000);
if (button_pressed != BUTTON_NO_CLICK || data_available())
break;
else if (state == STATE_SEARCH) {
if (!iso14443a_select_card(NULL, &card, NULL, true, 0, true)) {
continue;
} else {
if (card.sak == SAK && card.atqa[0] == ATQA0 && card.atqa[1] == ATQA1 && card.uidlen == 7) {
DbpString("Found ultralight with UID: ");
Dbhexdump(card.uidlen, card.uid, 0);
state = STATE_READ;
} else {
DbpString("Found non-ultralight card, ignoring.");
}
}
} else if (state == STATE_READ) {
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
iso14443a_select_card(NULL, NULL, NULL, true, 0, true);
bool read_successful = true;
Dbprintf("Contents:");
for (int i = 0; i < BLOCKS; i++) {
uint8_t dataout[4] = {0x00};
if (mifare_ultra_readblock(i, dataout)) {
// If there's an error reading, go back to search state
read_successful = false;
break;
}
// We're skipping 14 blocks (56 bytes) here, as that "[...] has version/signature/counter data here" according to comments on dumptoemul-mfu
// When converting a bin, it's almost all 0 other than one 0x0F byte, and functionality seems to be unaffected if that byte is set to 0x00.
emlSetMem_xt(dataout, 14 + i, 1, 4);
Dbhexdump(4, dataout, 0);
}
if (read_successful) {
Dbprintf("Successfully loaded into emulator memory...");
state = STATE_EMUL;
} else {
Dbprintf("Read failure, going back to search state.");
state = STATE_SEARCH;
}
} else if (state == 2) {
uint8_t flags = FLAG_7B_UID_IN_DATA;
Dbprintf("Starting simulation, press pm3-button to stop and go back to search state.");
SimulateIso14443aTag(2, flags, card.uid);
// Go back to search state if user presses pm3-button
state = STATE_SEARCH;
}
}
}
DbpString("exiting");
LEDsoff();
}

View file

@ -0,0 +1,431 @@
local utils = require('utils')
local getopt = require('getopt')
local cmds = require('commands')
local read14a = require('read14a')
--
---
-------------------------------
-- Notes
-------------------------------
---
--
--[[
---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.
--- 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.
-- doesn't take several versions of same dump ( -1, -2, -3 ) styles.
--]]
--
---
-------------------------------
-- Script hat
-------------------------------
---
--
copyright = 'RRG Team'
author = 'Winds'
version = 'v1.0.0'
desc = [[
This script gives you an easy way to write your *.eml dumps into normal MIFARE Classic and Magic Gen3 cards.
Works with both 4 and 7 bytes NXP MIFARE Classic 1K cards.
The script also has the possibility to change UID and permanent lock uid on magic Gen3 cards.
It supports the following functionality.
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.
Script works in a wizard styled way.
Author Youtube channel: https://yev.ooo/
Many Thanks,
Best Regards
]]
example = [[
1. script run mfc_gen3_writer
]]
usage = [[
Give script to know if you uses an Windows OS
Select your *.eml dump from list to write to the card.
Follow the wizard.
]]
--
---
-------------------------------
-- Global variables
-------------------------------
---
--
local DEBUG = false -- the debug flag
local dumpEML -- Find all *.EML files
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 = 'FFFFFFFFFFFF7C378800FFFFFFFFFFFF' -- 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_a = 'hf mf wrbl %d A %s %s' -- Writing blocks by A key
local cmd_wrbl_b = 'hf mf wrbl %d B %s %s' -- Writing blocks by B key
--
---
-------------------------------
-- A debug printout-function
-------------------------------
---
--
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
--
---
-------------------------------
-- This is only meant to be used when errors occur
-------------------------------
---
--
local function oops(err)
print('ERROR:', err)
core.clearCommandBuffer()
return nil, err
end
--
---
-------------------------------
-- Usage help
-------------------------------
---
--
local function help()
print(copyright)
print(author)
print(version)
print(desc)
print('Example usage')
print(example)
print(usage)
end
--
---
-------------------------------
-- GetUID
-------------------------------
---
--
local function GetUID()
return read14a.read(true, true).uid
end
--
local function dropfield()
read14a.disconnect()
core.clearCommandBuffer()
end
--
---
-------------------------------
-- Wait for tag (MFC)
-------------------------------
---
--
local function wait()
read14a.waitFor14443a()
end
--
---
-------------------------------
-- 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
-------------------------------
---
--
local function getblockdata(response)
if response.Status == 0 then
return true
else
return false
end
end
--
---
-------------------------------
-- Check 0xFFFFFFFFFFFF key for tag (MFC)
-------------------------------
---
--
local function checkkey()
local status = 0
for i = 1, #eml do
cmd = Command:newNG{cmd = cmds.CMD_HF_MIFARE_READBL, data = ('%02x%02x%s'):format((i-1), default_key_type, default_key)}
if (getblockdata(cmd:sendNG(false)) == true) then
status = status + 1
print(('%s %02s %s %s %s'):format(' ', (i-1), KeyAB(), default_key, 'OK'))
else
break
end
end
if status == #eml then
return true
end
end
--
---
-------------------------------
-- Check user input A or B for blank tag (MFC)
-------------------------------
---
--
local function check_user_key(user_key_type)
if user_key_type == 'A' then
return cmd_wrbl_a
elseif user_key_type == 'B' then
return cmd_wrbl_b
end
end
--
---
-------------------------------
-- Main function
-------------------------------
---
--
local function main(args)
--
---
-------------------------------
-- Arguments for script
-------------------------------
---
--
for o, a in getopt.getopt(args, 'hd') do
if o == 'h' then return help() end
if o == 'd' then DEBUG = true end
end
--
wait()
print(tab)
--
---
-------------------------------
-- Detect 7/4 byte card
-------------------------------
---
--
if (utils.confirm(' Are you use a Windwos OS ?') == true) then
dumpEML = 'find "." "*dump.eml"'
if string.len(GetUID()) == 14 then
eml_file_uid_start = 18
eml_file_uid_end = 31
eml_file_lengt = 40
else
eml_file_uid_start = 18
eml_file_uid_end = 25
eml_file_lengt = 34
end
else
dumpEML = "find '.' -iname '*dump.eml' -type f"
if string.len(GetUID()) == 14 then
eml_file_uid_start = 9
eml_file_uid_end = 22
eml_file_lengt = 31
else
eml_file_uid_start = 9
eml_file_uid_end = 16
eml_file_lengt = 25
end
end
print(tab)
dropfield()
--
---
-------------------------------
-- List all EML files in /client
-------------------------------
---
--
local p = assert(io.popen(dumpEML))
for _ in p:lines() do
-- The length of eml file
if string.len(_) == eml_file_lengt then
num_dumps = num_dumps + 1
-- cut UID from eml file
files[num_dumps] = string.sub(_, eml_file_uid_start, eml_file_uid_end) -- cut numeretic UID
print(' '..num_dumps..' | '..files[num_dumps])
end
end
--
p.close()
--
if num_dumps == 0 then return oops("Didn't find any dump files") end
--
print(tab)
print(' Your card has UID '..GetUID())
print('')
print(' Select which dump to write (1 until '..num_dumps..')')
print(tab)
io.write(' --> ')
--
local uid_no = tonumber(io.read())
print(tab)
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'))
for _ in dumpfile:lines() do table.insert(eml, _); end
dumpfile.close()
--
---
-------------------------------
-- Extract B key from EML file
-------------------------------
---
--
local b = 0
for i = 1, #eml do
if (i % 4 == 0) then
repeat
b = b + 1
-- Cut key from block
b_keys[b] = string.sub(eml[i], (#eml[i] - 11), #eml[i])
until b % 4 == 0
end
end
print(tab)
dbg(b_keys)
dbg(eml)
--
---
-------------------------------
-- Change UID on certain version of magic Gen3 card.
-------------------------------
---
--
if (utils.confirm(' Change UID ?') == true) then
wait()
core.console(piswords_uid_change .. tostring(eml[1]))
print(tab)
print(' The new card UID : ' .. GetUID())
end
print(tab)
--
---
-------------------------------
-- Lock UID
-------------------------------
---
--
if (utils.confirm(' Permanent lock UID ? (card can never change uid again) ') == true) then
wait()
core.console(piswords_uid_lock)
end
--
print(tab)
print(' Going to check the all ' .. KeyAB() .. ' by ' .. default_key)
print(tab)
--
if checkkey() == true then
print(tab)
if (utils.confirm(' Card is Empty. Write selected dump to card ?') == true) then
for i = 1, #eml do
core.console(string.format(cmd_wrbl_b, (i-1), default_key, eml[i]))
end
end
else
print(tab)
if (utils.confirm(' It this is a new blank card ? Do you wishing to change Access Conditions to using B key ' .. default_key .. ' as main ?') == true) then
print(tab)
print(' With one key type we will use, A or B ?')
print(tab)
io.write(' --> ')
local user_key_type = tostring(io.read())
print(tab)
print(' Enter 12 HEX chars of the key for access to card. By default ' .. default_key .. '.')
print(tab)
io.write(' --> ')
local user_key_input = tostring(io.read())
wait()
for i = 1, #eml do
if (i % 4 == 0) then
core.console(string.format(check_user_key(user_key_type), (i-1), user_key_input, default_key_blk))
else
core.console(string.format(check_user_key(user_key_type), (i-1), user_key_input, empty))
end
end
else
print(tab)
if (utils.confirm(' Write selected dump to card ?') == true) then
print(tab)
wait()
for i = 1, #eml do
core.console(string.format(cmd_wrbl_b, (i-1), b_keys[i], eml[i]))
end
else
print(tab)
if (utils.confirm(' Delete ALL data and write all keys to 0x' .. default_key .. ' ?') == true) then
wait()
for i = 1, #eml do
if (i % 4 == 0) then
core.console(string.format(cmd_wrbl_b, (i-1), b_keys[i], default_key_blk))
else
core.console(string.format(cmd_wrbl_b, (i-1), b_keys[i], empty))
end
end
end
end
end
end
dropfield()
print(tab)
print('You are welcome')
end
--
---
-------------------------------
-- Start Main function
-------------------------------
---
--
main(args)

View file

@ -292,7 +292,36 @@ static int CmdFdxDemod(const char *Cmd) {
} }
static int CmdFdxRead(const char *Cmd) { static int CmdFdxRead(const char *Cmd) {
lf_read(false, 10000); sample_config config;
memset(&config, 0, sizeof(sample_config));
int retval = lf_getconfig(&config);
if (retval != PM3_SUCCESS) {
PrintAndLogEx(ERR, "failed to get current device LF config");
return retval;
}
int16_t tmp_div = config.divisor;
if (tmp_div != LF_DIVISOR_134) {
config.divisor = LF_DIVISOR_134;
config.verbose = false;
retval = lf_config(&config);
if (retval != PM3_SUCCESS) {
PrintAndLogEx(ERR, "failed to change LF configuration");
return retval;
}
}
retval = lf_read(false, 10000);
if (retval != PM3_SUCCESS) {
PrintAndLogEx(ERR, "failed to get LF read from device");
return retval;
}
if (tmp_div != LF_DIVISOR_134) {
config.divisor = tmp_div;
retval = lf_config(&config);
if (retval != PM3_SUCCESS) {
PrintAndLogEx(ERR, "failed to restore LF configuration");
return retval;
}
}
return CmdFdxDemod(Cmd); return CmdFdxDemod(Cmd);
} }
@ -393,7 +422,7 @@ static int CmdFdxSim(const char *Cmd) {
static command_t CommandTable[] = { static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "this help"}, {"help", CmdHelp, AlwaysAvailable, "this help"},
{"demod", CmdFdxDemod, AlwaysAvailable, "demodulate a FDX-B ISO11784/85 tag from the GraphBuffer"}, {"demod", CmdFdxDemod, AlwaysAvailable, "demodulate a FDX-B ISO11784/85 tag from the GraphBuffer"},
{"read", CmdFdxRead, IfPm3Lf, "attempt to read and extract tag data"}, {"read", CmdFdxRead, IfPm3Lf, "attempt to read at 134kHz and extract tag data"},
{"clone", CmdFdxClone, IfPm3Lf, "clone animal ID tag to T55x7 or Q5/T5555"}, {"clone", CmdFdxClone, IfPm3Lf, "clone animal ID tag to T55x7 or Q5/T5555"},
{"sim", CmdFdxSim, IfPm3Lf, "simulate Animal ID tag"}, {"sim", CmdFdxSim, IfPm3Lf, "simulate Animal ID tag"},
{NULL, NULL, NULL, NULL} {NULL, NULL, NULL, NULL}