From 2010f8db038f5841abce8265d246dd0151127869 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 5 Apr 2020 12:28:49 +0200 Subject: [PATCH 01/31] colors --- client/luascripts/Legic_clone.lua | 24 +++++----- client/luascripts/formatMifare.lua | 14 +++--- client/luascripts/hf_bruteforce.lua | 51 +++++++++++---------- client/luascripts/hf_read.lua | 60 +++++++++++++++++++++++++ client/luascripts/htmldump.lua | 14 +++--- client/luascripts/init_rdv4.lua | 15 ++++--- client/luascripts/iso15_magic.lua | 14 +++--- client/luascripts/legic_buffer2card.lua | 14 +++--- client/luascripts/lf_bulk.lua | 14 +++--- client/luascripts/lto_dump.lua | 14 +++--- 10 files changed, 164 insertions(+), 70 deletions(-) diff --git a/client/luascripts/Legic_clone.lua b/client/luascripts/Legic_clone.lua index 982b17aec..191f9f9e0 100644 --- a/client/luascripts/Legic_clone.lua +++ b/client/luascripts/Legic_clone.lua @@ -1,3 +1,6 @@ +local utils = require('utils') +local getopt = require('getopt') +local ansicolors = require('ansicolors') --[[ script to create a clone-dump with new crc Author: mosci @@ -86,7 +89,7 @@ copyright = '' author = 'Mosci' -version = 'v1.0.1' +version = 'v1.0.2' desc = [[ This is a script which creates a clone-dump of a dump from a Legic Prime Tag (MIM256 or MIM1024) (created with 'hf legic save my_dump.hex') @@ -97,11 +100,12 @@ example = [[ ]] usage = [[ script run legic_clone -h -i -o -c -d -s -w - -required arguments: +]] +arguments = [[ +required : -i (file to read data from) -optional arguments : +optional : -h - Help text -o - requires option -c to be given -c - requires option -o to be given @@ -112,8 +116,7 @@ optional arguments : e.g.: hint: using the CRC '00' will result in a plain dump ( -c 00 ) ]] -local utils = require('utils') -local getopt = require('getopt') + local bxor = bit32.bxor -- we need always 2 digits @@ -128,7 +131,6 @@ local function prepend_zero(s) end end end - --- -- This is only meant to be used when errors occur local function oops(err) @@ -136,7 +138,6 @@ local function oops(err) core.clearCommandBuffer() return nil, err end - --- -- Usage help local function help() @@ -144,9 +145,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end -- Check availability of file diff --git a/client/luascripts/formatMifare.lua b/client/luascripts/formatMifare.lua index 7c6fd92c0..30ab20535 100644 --- a/client/luascripts/formatMifare.lua +++ b/client/luascripts/formatMifare.lua @@ -3,10 +3,11 @@ local getopt = require('getopt') local bin = require('bin') local lib14a = require('read14a') local utils = require('utils') +local ansicolors = require('ansicolors') copyright = '' author = 'Iceman' -version = 'v1.0.1' +version = 'v1.0.2' desc = [[ This script will generate 'hf mf wrbl' commands for each block to format a Mifare card. @@ -29,8 +30,8 @@ example = [[ ]] usage = [[ script run formatMifare -k -n -a -x - -Arguments: +]] +arguments = [[ -h - this help -k - the current six byte key with write access -n - the new key that will be written to the card @@ -71,9 +72,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end -- -- Exit message diff --git a/client/luascripts/hf_bruteforce.lua b/client/luascripts/hf_bruteforce.lua index 485d72809..a1ba34fad 100644 --- a/client/luascripts/hf_bruteforce.lua +++ b/client/luascripts/hf_bruteforce.lua @@ -2,38 +2,38 @@ -- Run me like this (connected via Blueshark addon): ./client/proxmark3 /dev/rfcomm0 -l ./hf_bruteforce.lua local getopt = require('getopt') +local ansicolors = require('ansicolors') copyright = '' author = 'Daniel Underhay (updated), Keld Norman(original)' -version = 'v2.0.0' -usage = [[ - -pm3 --> script run hf_bruteforce -s start_id -e end_id -t timeout -x mifare_card_type - -Arguments: - -h this help - -s 0-0xFFFFFFFF start id - -e 0-0xFFFFFFFF end id - -t 0-99999, pause timeout (ms) between cards (use the word 'pause' to wait for user input) - -x mfc, mfu mifare type: mfc for Mifare Classic (default) or mfu for Mifare Ultralight EV1 - - -Example: - -pm3 --> script run hf_bruteforce -s 0x11223344 -e 0x11223346 -t 1000 -x mfc - +version = 'v2.0.1' +desc =[[ +This script bruteforces 4 or 7 byte UID Mifare classic card numbers. +]] +example =[[ Bruteforce a 4 byte UID Mifare classic card number, starting at 11223344, ending at 11223346. - - -pm3 --> script run hf_bruteforce -s 0x11223344556677 -e 0x11223344556679 -t 1000 -x mfu + + script run hf_bruteforce -s 0x11223344 -e 0x11223346 -t 1000 -x mfc Bruteforce a 7 byte UID Mifare Ultralight card number, starting at 11223344556677, ending at 11223344556679. + script run hf_bruteforce -s 0x11223344556677 -e 0x11223344556679 -t 1000 -x mfu +]] +usage = [[ +script run hf_bruteforce [-s ] [-e ] [-t ] [-x ] +]] +arguments = [[ + -h this help + -s 0-0xFFFFFFFF start id + -e 0-0xFFFFFFFF end id + -t 0-99999, pause timeout (ms) between cards + (use the word 'pause' to wait for user input) + -x mfc, mfu mifare type: + mfc for Mifare Classic (default) + mfu for Mifare Ultralight EV1 ]] - local DEBUG = true - --- -- Debug print function local function dbg(args) @@ -62,9 +62,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end --- --- Print user message diff --git a/client/luascripts/hf_read.lua b/client/luascripts/hf_read.lua index 00238a67c..e416cdd2e 100644 --- a/client/luascripts/hf_read.lua +++ b/client/luascripts/hf_read.lua @@ -1,6 +1,65 @@ local reader = require('hf_reader') +local getopt = require('getopt') +local ansicolors = require('ansicolors') +copyright = '' +author = '' +version = 'v1.0.1' +desc = [[ +This script tries to detect a HF card. Just like 'hf search' does but this is experimental +]] +example = [[ + 1. script run hf_read +]] +usage = [[ +script run hf_read +]] +arguments = [[ + -h - this help +]] +--- +-- This is only meant to be used when errors occur +local function dbg(err) + 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(ansicolors.cyan..'Usage'..ansicolors.reset) + print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) +end +--- +-- local function main(args) + -- Arguments for the script + for o, a in getopt.getopt(args, 'h') do + if o == 'h' then return help() end + end + print("WORK IN PROGRESS - not expected to be functional yet") info, err = reader.waitForTag() @@ -15,4 +74,5 @@ local function main(args) end return end + main(args) diff --git a/client/luascripts/htmldump.lua b/client/luascripts/htmldump.lua index 0101c14a8..2853d343b 100644 --- a/client/luascripts/htmldump.lua +++ b/client/luascripts/htmldump.lua @@ -3,10 +3,11 @@ getopt = require('getopt') bin = require('bin') dumplib = require('html_dumplib') +local ansicolors = require('ansicolors') copyright = '' author = 'Martin Holst Swende' -version = 'v1.0.1' +version = 'v1.0.2' desc =[[ This script takes a dumpfile and produces a html based dump, which is a bit more easily analyzed. @@ -16,8 +17,8 @@ example = [[ ]] usage = [[ script run htmldump [-i ] [-o ] - -Arguments: +]] +arguments = [[ -h This help -i Specifies the dump-file (input). If omitted, 'dumpdata.bin' is used -o Speciies the output file. If omitted, .html is used. @@ -55,9 +56,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end local function main(args) diff --git a/client/luascripts/init_rdv4.lua b/client/luascripts/init_rdv4.lua index d2dd03e24..bc18dc0a9 100644 --- a/client/luascripts/init_rdv4.lua +++ b/client/luascripts/init_rdv4.lua @@ -1,21 +1,21 @@ local getopt = require('getopt') +local ansicolors = require('ansicolors') copyright = 'Copyright (c) 2019 IceSQL AB. All rights reserved.' author = 'Christian Herrmann' -version = 'v1.0.0' +version = 'v1.0.1' desc = [[ This script initialize a Proxmark3 RDV4.0 with - uploading dictionary files to flashmem - configuring the LF T55X7 device settings ]] example = [[ - script run init_rdv4 ]] usage = [[ script run init_rdv4 -h - -Arguments: +]] +arguments = [[ -h : this help ]] @@ -48,9 +48,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end --- -- The main entry point diff --git a/client/luascripts/iso15_magic.lua b/client/luascripts/iso15_magic.lua index ba94465e4..94f1d8f97 100644 --- a/client/luascripts/iso15_magic.lua +++ b/client/luascripts/iso15_magic.lua @@ -2,10 +2,11 @@ local cmds = require('commands') local lib15 = require('read15') local getopt = require('getopt') local utils = require('utils') +local ansicolors = require('ansicolors') copyright = 'Copyright (c) 2018 IceSQL AB. All rights reserved.' author = 'Christian Herrmann' -version = 'v1.0.5' +version = 'v1.0.6' desc = [[ This script tries to set UID on a IS15693 SLIX magic card Remember the UID ->MUST<- start with 0xE0 @@ -20,8 +21,8 @@ example = [[ ]] usage = [[ script run iso15_magic -h -u - -Arguments: +]] +arguments = [[ -h : this help -u : UID (16 hexsymbols) -a : use offical pm3 repo ISO15 commands instead of iceman fork. @@ -56,9 +57,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end -- --- Set UID on magic command enabled on a ICEMAN based REPO diff --git a/client/luascripts/legic_buffer2card.lua b/client/luascripts/legic_buffer2card.lua index 462880ce5..d0a018d83 100644 --- a/client/luascripts/legic_buffer2card.lua +++ b/client/luascripts/legic_buffer2card.lua @@ -1,10 +1,11 @@ local utils = require('utils') local getopt = require('getopt') +local ansicolors = require('ansicolors') -- this script writes bytes 8 to 256 on the Legic MIM256 copyright = '' author = 'Mosci' -version = 'v1.0.1' +version = 'v1.0.2' desc = [[ This is a script which writes value 0x01 to bytes from position 0x07 until 0xFF on a Legic Prime Tag (MIM256 or MIM1024) -- (created with 'hf legic save my_dump.hex') -- @@ -14,8 +15,8 @@ example = [[ ]] usage = [[ script run legic_buffer2card -h - -Arguments +]] +arguments = [[ -h - Help text ]] @@ -33,9 +34,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end -- -- simple loop-write from 0x07 to 0xff diff --git a/client/luascripts/lf_bulk.lua b/client/luascripts/lf_bulk.lua index 54c60fb89..709c992a4 100644 --- a/client/luascripts/lf_bulk.lua +++ b/client/luascripts/lf_bulk.lua @@ -3,10 +3,11 @@ -- Updated 2017-04-18 -- Updated 2018-02-20 iceman local getopt = require('getopt') +local ansicolors = require('ansicolors') copyright = '' author = "Brian Redbeard" -version = 'v1.0.1' +version = 'v1.0.2' desc = [[ Perform bulk enrollment of 26 bit H10301 style RFID Tags For more info, check the comments in the code @@ -17,8 +18,8 @@ example = [[ ]] usage = [[ script run lf_bulk.lua -f facility -b base_id_num -c count - -Arguments: +]] +arguments = [[ -h : this help -f : facility id -b : starting card id @@ -56,9 +57,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end --- -- Exit message diff --git a/client/luascripts/lto_dump.lua b/client/luascripts/lto_dump.lua index a384a4f9b..d2dd87762 100644 --- a/client/luascripts/lto_dump.lua +++ b/client/luascripts/lto_dump.lua @@ -2,10 +2,11 @@ local cmds = require('commands') local getopt = require('getopt') local lib14a = require('read14a') local utils = require('utils') +local ansicolors = require('ansicolors') copyright = '' author = 'Kevin' -version = 'v1.0.1' +version = 'v1.0.2' desc = [[ This is a script that reads LTO-CM ISO14443a tags. It starts from block 0 and ends at default block 254. @@ -19,8 +20,8 @@ example = [[ ]] usage = [[ script run lto_dump -h -s -e - -Arguments: +]] +arguments = [[ h this helptext s start block in decimal e end block in decimal @@ -58,9 +59,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end local function sendRaw(rawdata, options) From 8fea6cddf722a43701b64a48d5c161c9e13b3af0 Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Sun, 5 Apr 2020 20:36:39 +1000 Subject: [PATCH 02/31] Concept --- client/Makefile | 3 +- client/emv/emvjson.c | 3 + client/emv/emvjson.h | 1 + client/fileutils.c | 10 ++- client/fileutils.h | 1 + client/proxmark3.c | 8 ++ client/settings.c | 186 +++++++++++++++++++++++++++++++++++++++++++ client/settings.h | 32 ++++++++ 8 files changed, 242 insertions(+), 2 deletions(-) create mode 100644 client/settings.c create mode 100644 client/settings.h diff --git a/client/Makefile b/client/Makefile index a09a033d9..2c5a663c4 100644 --- a/client/Makefile +++ b/client/Makefile @@ -251,7 +251,8 @@ CMDSRCS = crapto1/crapto1.c \ flash.c \ wiegand_formats.c \ wiegand_formatutils.c \ - cardhelper.c + cardhelper.c \ + settings.c cpu_arch = $(shell uname -m) ifneq ($(findstring 86, $(cpu_arch)), ) diff --git a/client/emv/emvjson.c b/client/emv/emvjson.c index 75b2e87bf..9b86b38ca 100644 --- a/client/emv/emvjson.c +++ b/client/emv/emvjson.c @@ -94,6 +94,9 @@ int JsonSaveStr(json_t *root, const char *path, const char *value) { return JsonSaveJsonObject(root, path, json_string(value)); }; +int JsonSaveBoolean(json_t *root, const char *path, bool value) { + return JsonSaveJsonObject(root, path, json_boolean(value)); +} int JsonSaveBufAsHexCompact(json_t *elm, const char *path, uint8_t *data, size_t datalen) { char *msg = sprint_hex_inrow(data, datalen); if (msg && strlen(msg) && msg[strlen(msg) - 1] == ' ') diff --git a/client/emv/emvjson.h b/client/emv/emvjson.h index 54d97ada8..9b1efb034 100644 --- a/client/emv/emvjson.h +++ b/client/emv/emvjson.h @@ -24,6 +24,7 @@ const char *GetApplicationDataName(tlv_tag_t tag); int JsonSaveJsonObject(json_t *root, const char *path, json_t *value); int JsonSaveStr(json_t *root, const char *path, const char *value); +int JsonSaveBoolean(json_t *root, const char *path, bool value); int JsonSaveInt(json_t *root, const char *path, int value); int JsonSaveBufAsHexCompact(json_t *elm, const char *path, uint8_t *data, size_t datalen); int JsonSaveBufAsHex(json_t *elm, const char *path, uint8_t *data, size_t datalen); diff --git a/client/fileutils.c b/client/fileutils.c index ecf47383f..5ce1f3a6a 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -52,6 +52,9 @@ #define PATH_MAX_LENGTH 200 +extern void JsonLoadSettingsCallback (json_t *root); +extern void JsonSaveSettingsCallback (json_t *root); + struct wave_info_t { char signature[4]; uint32_t filesize; @@ -425,6 +428,9 @@ int saveFileJSON(const char *preferredName, JSONFileType ftype, uint8_t *data, s } } break; + case jsfSettings: + JsonSaveSettingsCallback (root); + break; default: break; } @@ -863,7 +869,9 @@ int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_ } *datalen = sptr; } - + if (!strcmp(ctype,"settings")) { + JsonLoadSettingsCallback (root); + } PrintAndLogEx(SUCCESS, "loaded from JSON file " _YELLOW_("%s"), fileName); out: json_decref(root); diff --git a/client/fileutils.h b/client/fileutils.h index 3747e0850..06d3ff20a 100644 --- a/client/fileutils.h +++ b/client/fileutils.h @@ -62,6 +62,7 @@ typedef enum { jsfT55x7, jsfT5555, jsfMfPlusKeys, + jsfSettings, } JSONFileType; typedef enum { diff --git a/client/proxmark3.c b/client/proxmark3.c index 5a6ae23a9..504ae93e5 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -27,6 +27,7 @@ #include "comms.h" #include "fileutils.h" #include "flash.h" +#include "settings.h" static void showBanner(void) { g_printAndLog = PRINTANDLOG_PRINT; @@ -557,6 +558,7 @@ int main(int argc, char *argv[]) { /* initialize history */ using_history(); + #ifdef RL_STATE_READCMD rl_extend_line_buffer(1024); @@ -581,6 +583,12 @@ int main(int argc, char *argv[]) { set_my_executable_path(); set_my_user_directory(); + // Settings + settingsLoad (); + settingsSave (); + printf ("Ver : %s\n",mySettings.version); + // End Settings + for (int i = 1; i < argc; i++) { if (argv[i][0] != '-') { diff --git a/client/settings.c b/client/settings.c new file mode 100644 index 000000000..a3571c566 --- /dev/null +++ b/client/settings.c @@ -0,0 +1,186 @@ +/***************************************************************************** + * WARNING + * + * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. + * + * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL + * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, + * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. + * + * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. + * + ***************************************************************************** + * + * This file is part of loclass. It is a reconstructon of the cipher engine + * used in iClass, and RFID techology. + * + * The implementation is based on the work performed by + * Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and + * Milosch Meriac in the paper "Dismantling IClass". + * + * Copyright (C) 2014 Martin Holst Swende + * + * This is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation, or, at your option, any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with loclass. If not, see . + * + * + ****************************************************************************/ + +//----------------------------------------------------------------------------- +// Settings Functions +//----------------------------------------------------------------------------- + +#include "settings.h" +#include "comms.h" +#include "emv/emvjson.h" + +// settings_t mySettings; + +// Load all settings into memory (struct) +void settingsLoad (void) +{ + // loadFileJson wants these, so pass in place holder values, though not used + // in settings load; + uint8_t dummyData = 0x00; + size_t dummyDL = 0x00; + + // clear all settings + memset (&mySettings,0x00,sizeof(mySettings)); + + if (loadFileJSON(settingsFilename, &dummyData, sizeof(dummyData), &dummyDL) == PM3_SUCCESS) { + printf ("==> Settings Loaded\n"); + mySettings.loaded = true; + } + + + // Test results + /* + bool os_windows_usecolor; + bool os_windows_useansicolor; + int window_xpos; + int window_ypos; + int window_hsize; + int window_wsize; + */ + printf (" Settings Version : [%s]\n",mySettings.version); + printf (" os_windows_usecolor (bool) : [%d]\n",mySettings.os_windows_usecolor); + printf (" os_windows_useAnsicolor (bool) : [%d]\n",mySettings.os_windows_useansicolor); + printf (" window_xpos (int) : [%d]\n",mySettings.window_xpos); + printf (" window_ypos (int) : [%d]\n",mySettings.window_ypos); + printf (" window_hsize (int) : [%d]\n",mySettings.window_hsize); + printf (" window_wsize (int) : [%d]\n",mySettings.window_wsize); + +} + +// Save all settings from memory (struct) to file +int settingsSave (void) +{ + // Note sure if backup has value ? + char backupFilename[500]; + // if (mySettings.loaded) + + snprintf (backupFilename,sizeof(backupFilename),"%s.bak",settingsFilename); + + if (fileExists (backupFilename)) { + if (remove (backupFilename) != 0) { + PrintAndLogEx (FAILED, "Error - could not delete old settings backup file \"%s\"",backupFilename); + return PM3_ESOFT; + } + } + + if (fileExists (settingsFilename)) { + if (rename (settingsFilename,backupFilename) != 0) { + PrintAndLogEx (FAILED, "Error - could not backup settings file \"%s\" to \"%s\"",settingsFilename,backupFilename); + return PM3_ESOFT; + } + } + + uint8_t dummyData = 0x00; + size_t dummyDL = 0x00; + + // int saveFileJSON(const char *preferredName, JSONFileType ftype, uint8_t *data, size_t datalen); + + if (saveFileJSON(settingsFilename, jsfSettings, &dummyData, dummyDL) == PM3_SUCCESS) + PrintAndLogEx (NORMAL, "settings have been saved to \"%s\"",settingsFilename); + + return PM3_SUCCESS; +} + +void JsonSaveSettingsCallback (json_t *root) +{ + // extern settings_t mySettings; + + printf ("==> Save Settings\n"); + //JsonSaveStr(root, "FileType", "settings"); + //JsonSaveStr (root,"Test1.Test2","test settings"); + /* + "version": "1.0 Nov 2019", + "os.windows.usecolor": true, + "os.windows.useAnsiColor": true, + "window.xpos": 10, + "window.ypos": 10, + "window.hsize": 300, + "window.wsize": 600 + */ + JsonSaveStr (root,"FileType","settings"); + JsonSaveStr (root,"version","1.0 Nov 2019");//mySettings.version); + JsonSaveBoolean (root,"os.windows.useColor",mySettings.os_windows_usecolor); + JsonSaveBoolean (root,"os.windows.useAnsiColor",mySettings.os_windows_useansicolor); + JsonSaveInt (root,"window.xpos",mySettings.window_xpos); + JsonSaveInt (root,"window.ypos",mySettings.window_ypos); + JsonSaveInt (root,"window.hsize",mySettings.window_hsize); + JsonSaveInt (root,"window.wsize",mySettings.window_wsize); +} + +void JsonLoadSettingsCallback (json_t *root) +{ +// extern settings_t mySettings; + json_error_t up_error = {0}; + int b1; + int i1; + const char *s1; + + if (json_unpack_ex(root, &up_error , 0, "{s:s}","version",&s1) == 0) + strncpy (mySettings.version,s1,sizeof (mySettings.version) - 1); + else + strncpy (mySettings.version,"unknown",sizeof (mySettings.version) - 1); + + // os.windows... + if (json_unpack_ex(root,&up_error, 0, "{s:b}","os.windows.useColor",&b1) == 0) + mySettings.os_windows_usecolor = b1; + else // default + mySettings.os_windows_useansicolor = false; + + if (json_unpack_ex(root,&up_error, 0, "{s:b}","os.windows.useAnsiColor",&b1) == 0) + mySettings.os_windows_useansicolor = b1; + else // default + mySettings.os_windows_useansicolor = false; + + // window... + if (json_unpack_ex(root,&up_error, 0, "{s:i}","window.xpos",&i1) == 0) + mySettings.window_xpos = i1; + else // default + mySettings.window_xpos = 0; + if (json_unpack_ex(root,&up_error, 0, "{s:i}","window.ypos",&i1) == 0) + mySettings.window_ypos = i1; + else // default + mySettings.window_ypos = 0; + if (json_unpack_ex(root,&up_error, 0, "{s:i}","window.hsize",&i1) == 0) + mySettings.window_hsize = i1; + else // default + mySettings.window_hsize = 0; + if (json_unpack_ex(root,&up_error, 0, "{s:i}","window.wsize",&i1) == 0) + mySettings.window_wsize = i1; + else // default + mySettings.window_wsize = 0; + +} diff --git a/client/settings.h b/client/settings.h new file mode 100644 index 000000000..f0093c207 --- /dev/null +++ b/client/settings.h @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2009 Michael Gernoth +// Copyright (C) 2010 iZsh +// +// 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. +//----------------------------------------------------------------------------- +// Settings Functions +//----------------------------------------------------------------------------- + +#include "fileutils.h" + +#define settingsFilename "settings.json" +typedef struct { + bool loaded; + char version[20]; + bool os_windows_usecolor; + bool os_windows_useansicolor; + int window_xpos; + int window_ypos; + int window_hsize; + int window_wsize; +} settings_t; + +settings_t mySettings; + +void settingsLoad (void); +int settingsSave (void); + +void JsonSaveCallback ( json_t *root); +void JsonLoadCallback ( json_t *root); From 95bc1230d7516abbfbc1f964fb63760963885f69 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 5 Apr 2020 12:41:38 +0200 Subject: [PATCH 03/31] colors --- client/luascripts/emul2dump.lua | 2 +- client/luascripts/luxeodump.lua | 59 +++++++++++++++++++--------- client/luascripts/mfckeys.lua | 18 ++++++--- client/luascripts/mfu_magic.lua | 21 +++++----- client/luascripts/mifare_access.lua | 16 +++++--- client/luascripts/mifare_autopwn.lua | 16 +++++--- client/luascripts/mifareplus.lua | 22 ++++++----- client/luascripts/ndef_dump.lua | 16 +++++--- client/luascripts/ntag_3d.lua | 16 +++++--- 9 files changed, 118 insertions(+), 68 deletions(-) diff --git a/client/luascripts/emul2dump.lua b/client/luascripts/emul2dump.lua index 9249dd5c0..cf6900bff 100644 --- a/client/luascripts/emul2dump.lua +++ b/client/luascripts/emul2dump.lua @@ -1,7 +1,7 @@ local getopt = require('getopt') local bin = require('bin') local dumplib = require('html_dumplib') -local ansicolors = require('ansicolors') +local ansicolors = require('ansicolors') copyright = '' author = 'Iceman' diff --git a/client/luascripts/luxeodump.lua b/client/luascripts/luxeodump.lua index 6b7254801..3efc8e7c0 100644 --- a/client/luascripts/luxeodump.lua +++ b/client/luascripts/luxeodump.lua @@ -12,9 +12,9 @@ local ansicolors = require('ansicolors') copyright = '' author = '0xdrrb' -version = 'v0.1.0' +version = 'v0.1.1' desc = [[ -This is a script to dump and decrypt the data of a specific type of Mifare laundromat token. +This is a script that tries to dump and decrypt the data of a specific type of Mifare laundromat token. OBS! Tag must be on the antenna. ]] example = [[ script run luxeodump @@ -22,7 +22,9 @@ example = [[ usage = [[ script run luxeodump ]] - +arguments = [[ + -h This help +]] local PM3_SUCCESS = 0 -- Some shortcuts @@ -48,7 +50,22 @@ local function oops(err) core.clearCommandBuffer() return nil, err end - +--- +-- Usage help +local function help() + print(copyright) + print(author) + print(version) + print(desc) + print(ansicolors.cyan..'Usage'..ansicolors.reset) + print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) +end +--- +-- local function setdevicedebug( status ) local c = 'hw dbg ' if status then @@ -72,8 +89,8 @@ local function xteaCrypt(num_rounds, v, key) -- v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]); v1 = band(bxor(bxor(lsh(v0,4), rsh(v0,5)) + v0, sum + key[band(rsh(sum,11),3)]) + v1, 0xFFFFFFFF) end - v[0]=v0 - v[1]=v1 + v[0] = v0 + v[1] = v1 end local function xteaDecrypt(num_rounds, v, key) @@ -89,8 +106,8 @@ local function xteaDecrypt(num_rounds, v, key) -- v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]); v0 = band(v0 - bxor(bxor(lsh(v1,4), rsh(v1,5)) + v1, sum + key[band(sum,3)]), 0xFFFFFFFF) end - v[0]=v0 - v[1]=v1 + v[0] = v0 + v[1] = v1 end local function createxteakey(mfuid) @@ -150,7 +167,7 @@ local function readtag(mfkey,xteakey) -- Read 4 sectors and build table for sect = 8, 11 do - for blockn = sect*4, (sect*4)+2 do + for blockn = sect * 4, (sect * 4) + 2 do local blockdata = readblock(blockn, mfkey) if not blockdata then return oops('[!] failed reading block') end table.insert(tagdata, blockdata) @@ -160,17 +177,17 @@ local function readtag(mfkey,xteakey) -- Decrypt data and build clear table for key,value in ipairs(tagdata) do local clearblockdata - v[0]=utils.SwapEndianness(value:sub(1,8),32) - v[1]=utils.SwapEndianness(value:sub(9,16),32) + v[0] = utils.SwapEndianness(value:sub(1, 8), 32) + v[1] = utils.SwapEndianness(value:sub(9, 16), 32) xteaDecrypt(16, v, xteakey) - vv[0]=utils.SwapEndianness(value:sub(17,24),32) - vv[1]=utils.SwapEndianness(value:sub(25,32),32) + vv[0] = utils.SwapEndianness(value:sub(17, 24), 32) + vv[1] = utils.SwapEndianness(value:sub(25, 32), 32) xteaDecrypt(16, vv, xteakey) clearblockdata=string.format("%08X%08X%08X%08X", - utils.SwapEndianness(string.format("%08X", v[0]),32), - utils.SwapEndianness(string.format("%08X", v[1]),32), - utils.SwapEndianness(string.format("%08X", vv[0]),32), - utils.SwapEndianness(string.format("%08X", vv[1]),32)) + utils.SwapEndianness(string.format("%08X", v[0]), 32), + utils.SwapEndianness(string.format("%08X", v[1]), 32), + utils.SwapEndianness(string.format("%08X", vv[0]), 32), + utils.SwapEndianness(string.format("%08X", vv[1]), 32)) table.insert(cleardata, clearblockdata) end @@ -180,6 +197,12 @@ end local function main(args) + + -- Arguments for the script + for o, a in getopt.getopt(args, 'h') do + if o == 'h' then return help() end + end + local xteakey = {} -- local v = {} local edata = {} @@ -207,7 +230,7 @@ local function main(args) print(acblue.."UID: "..tag.uid..acoff) print(acblue..string.format("XTEA key: %08X %08X %08X %08X", xteakey[0], xteakey[1], xteakey[2], xteakey[3])..acoff) - edata, cdata = readtag("415A54454B4D",xteakey) + edata, cdata = readtag("415A54454B4D", xteakey) if edata == nil or cdata == nil then print("ERROR Reading tag!") diff --git a/client/luascripts/mfckeys.lua b/client/luascripts/mfckeys.lua index 32808b62d..bf0cccb45 100644 --- a/client/luascripts/mfckeys.lua +++ b/client/luascripts/mfckeys.lua @@ -13,10 +13,11 @@ local keylist = require('mfc_default_keys') local lib14a = require('read14a') local getopt = require('getopt') local utils = require('utils') +local ansicolors = require('ansicolors') copyright = '' author = "Holiman" -version = 'v1.0.1' +version = 'v1.0.2' desc = ("This script implements Mifare check keys.\ It utilises a large list of default keys (currently %d keys).\ If you want to add more, just put them inside /lualibs/mfc_default_keys.lua\n"):format(#keylist) @@ -24,7 +25,9 @@ example = [[ 1. script run mfckeys ]] usage = [[ -Arguments: +script run mfckeys [-p] +]] +arguments = [[ -h : this help -p : print keys ]] @@ -46,9 +49,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end -- -- waits for answer from pm3 device @@ -269,8 +275,6 @@ end -- The main entry point local function main(args) - local numSectors = 16 - -- Arguments for the script for o, a in getopt.getopt(args, 'hp') do if o == 'h' then return help() end @@ -280,6 +284,8 @@ local function main(args) tag, err = lib14a.read(false, true) if not tag then return oops(err) end + local numSectors = 16 + -- detect sectors and print taginfo numsectors = taginfo(tag) diff --git a/client/luascripts/mfu_magic.lua b/client/luascripts/mfu_magic.lua index badc691c5..d921a9fb2 100644 --- a/client/luascripts/mfu_magic.lua +++ b/client/luascripts/mfu_magic.lua @@ -2,6 +2,7 @@ local cmds = require('commands') local getopt = require('getopt') local lib14a = require('read14a') local utils = require('utils') +local ansicolors = require('ansicolors') -- global local DEBUG = false -- the debug flag @@ -11,10 +12,9 @@ local err_lock = 'use -k or change cfg0 block' copyright = 'Copyright (c) 2017 IceSQL AB. All rights reserved.' author = 'Christian Herrmann' -version = 'v1.1.2' +version = 'v1.1.3' desc = 'This script enables easy programming of a MAGIC NTAG 21* card' -example = -[[ +example = [[ -- wipe tag script run mfu_magic -w @@ -36,12 +36,10 @@ example = -- set signature script run mfu_magic -s 1122334455667788990011223344556677889900112233445566778899001122 ]] -usage = -[[ -Usage: +usage = [[ script run mfu_magic -h -k -c -w -u -t -p -a -s -o -v - -Arguments: +]] +arguments = [[ -h this help -c read magic configuration -u UID (14 hexsymbols), set UID on tag @@ -94,9 +92,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end --- -- set the global password variable diff --git a/client/luascripts/mifare_access.lua b/client/luascripts/mifare_access.lua index 1c38576e7..4c416e8d6 100644 --- a/client/luascripts/mifare_access.lua +++ b/client/luascripts/mifare_access.lua @@ -1,8 +1,9 @@ local getopt = require('getopt') +local ansicolors = require('ansicolors') copyright = '' author = "Neuromancer" -version = 'v1.0.1' +version = 'v1.0.2' desc = [[ This script tries to decode Mifare Classic Access bytes ]] @@ -10,9 +11,9 @@ example = [[ 1. script run mifare_access -a 7F0F0869 ]] usage = [[ -script run mifare_access -h -a - -Arguments: +script run mifare_access [-h] [-a ] +]] +arguments = [[ -h : this help -a : 4 bytes ACCESS CONDITIONS ]] @@ -50,9 +51,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end local access_condition_sector_trailer = {} diff --git a/client/luascripts/mifare_autopwn.lua b/client/luascripts/mifare_autopwn.lua index bc7582760..6ff40a70d 100644 --- a/client/luascripts/mifare_autopwn.lua +++ b/client/luascripts/mifare_autopwn.lua @@ -2,20 +2,23 @@ local getopt = require('getopt') local lib14a = require('read14a') local cmds = require('commands') local utils = require('utils') +local ansicolors = require('ansicolors') copyright = '' author = "Martin Holst Swende" -version = 'v1.0.2' +version = 'v1.0.3' desc = [[ This is a script which automates cracking and dumping mifare classic cards. It sets itself into 'listening'-mode, after which it cracks and dumps any mifare classic card that you place by the device. ]] example = [[ -script run mifare_autopwn + 1. script run mifare_autopwn ]] usage = [[ -Arguments: +script run mifare_autopwn [-h] [-d] [-k ] +]] +arguments = [[ -h this help -d debug logging on -k known key for Sector 0 , keytype A @@ -61,9 +64,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end --- -- Waits for a mifare card to be placed within the vicinity of the reader. diff --git a/client/luascripts/mifareplus.lua b/client/luascripts/mifareplus.lua index f49ad95e5..a30f24f8b 100644 --- a/client/luascripts/mifareplus.lua +++ b/client/luascripts/mifareplus.lua @@ -1,12 +1,12 @@ local cmds = require('commands') local lib14a = require('read14a') local getopt = require('getopt') +local ansicolors = require('ansicolors') copyright = '' author = 'Dominic Celiano' -version = 'v1.0.1' -desc = -[[ +version = 'v1.0.2' +desc = [[ Purpose: Lua script to communicate with the Mifare Plus EV1, including personalization (setting the keys) and proximity check. Manually edit the file to add to the commands you can send the card. Please read the NXP manual before running this script to prevent making irreversible changes. Also note: - The Mifare Plus must start in SL0 for personalization. Card can then be moved to SL1 or SL3. @@ -15,13 +15,12 @@ Please read the NXP manual before running this script to prevent making irrevers Small changes can be to made this script to communicate with the Mifare Plus S, X, or SE. ]] example = [[ - -- default - script run mifareplus + 1. script run mifareplus ]] usage = [[ -script run mifareplus -h - -Arguments: +script run mifareplus [-h] +]] +arguments = [[ -h : this help ]] @@ -57,9 +56,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end --- -- Used to send raw data to the firmware to subsequently forward the data to the card. diff --git a/client/luascripts/ndef_dump.lua b/client/luascripts/ndef_dump.lua index a4cbdf655..672beda1c 100644 --- a/client/luascripts/ndef_dump.lua +++ b/client/luascripts/ndef_dump.lua @@ -2,11 +2,12 @@ local getopt = require('getopt') local cmds = require('commands') local lib14a = require('read14a') local utils = require('utils') +local ansicolors = require('ansicolors') -- -- Refactored iceman, 2019 copyright = '' author = 'Martin Holst Swende & Asper' -version = 'v1.0.1' +version = 'v1.0.2' desc = [[ This script will automatically recognize and dump full content of a NFC NDEF Initialized tag; non-initialized tags will be ignored. @@ -23,9 +24,9 @@ example = [[ 1. script run ndef_dump ]] usage = [[ -script run ndef_dump - -Arguments: +script run ndef_dump [-h] [-d] [-v] +]] +arguments = [[ -h this help -d debug logging on -v verbose output (from ndef parsing) @@ -63,9 +64,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end -- -- Sends an instruction to do nothing, only disconnect diff --git a/client/luascripts/ntag_3d.lua b/client/luascripts/ntag_3d.lua index 869590cf2..d986923ba 100644 --- a/client/luascripts/ntag_3d.lua +++ b/client/luascripts/ntag_3d.lua @@ -1,10 +1,11 @@ local getopt = require('getopt') local lib14a = require('read14a') local utils = require('utils') +local ansicolors = require('ansicolors') copyright = 'Copyright (c) 2017 IceSQL AB. All rights reserved.' author = "Christian Herrmann" -version = 'v1.0.4' +version = 'v1.0.5' desc = [[ This script writes a empty template for 3D printing system onto a empty NTAG213 or MAGIC NTAG21* @@ -21,9 +22,9 @@ example =[[ script run ntag_3d -u 11223344556677 -c 46 -m 50 -p 5448 -s 4555 -l 200 -1 ]] usage = [[ -script run ntag_3d -h -t -u -c -m -p -s -l - -Arguments: +script run ntag_3d [-h] [-t] [-u ] [-c ] [-m ] [-p ] [-s ] [-l ] +]] +arguments = [[ -h : this help -t : selftest -u : UID @@ -168,9 +169,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end -- -- Exit message From 2474385ab09a246898cecf44673d6aa3e3fd64b3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 5 Apr 2020 12:49:25 +0200 Subject: [PATCH 04/31] colors --- client/luascripts/parameters.lua | 23 ++++++++++++++++---- client/luascripts/read_pwd_mem.lua | 26 +++++++++++------------ client/luascripts/read_pwd_mem_spiffs.lua | 26 +++++++++++------------ client/luascripts/remagic.lua | 19 ++++++++++------- client/luascripts/test_t55x7.lua | 17 +++++++++------ 5 files changed, 66 insertions(+), 45 deletions(-) diff --git a/client/luascripts/parameters.lua b/client/luascripts/parameters.lua index d68b7b06a..dce215eb7 100644 --- a/client/luascripts/parameters.lua +++ b/client/luascripts/parameters.lua @@ -1,19 +1,31 @@ -- The getopt-functionality is loaded from pm3/getopt.lua -- Have a look there for further details -getopt = require('getopt') +local getopt = require('getopt') +local ansicolors = require('ansicolors') copyright = '' usage = 'script run parameters.lua -a 1 -blala -c -de' author = 'Martin Holst Swende' -version = 'v1.0.1' +version = 'v1.0.2' desc = [[ This is an example script to demonstrate handle parameters in scripts. For more info, check the comments in the code ]] example = [[ + 1. script run parameters -a mytestparam_input -c ]] usage = [[ +script run parameters [-h] [-a ] [-b ] [-c] [-d] [-e] ]] +arguments = [[ + -h This help + -a text + -b text + -c test param w/o input + -d test param w/o input + -e test param w/o input +]] + --- -- Usage help local function help() @@ -21,9 +33,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end local function main(args) diff --git a/client/luascripts/read_pwd_mem.lua b/client/luascripts/read_pwd_mem.lua index ffc00a998..0c786f6f9 100644 --- a/client/luascripts/read_pwd_mem.lua +++ b/client/luascripts/read_pwd_mem.lua @@ -1,11 +1,11 @@ local getopt = require('getopt') local bin = require('bin') +local ansicolors = require('ansicolors') copyright = 'Copyright (c) 2018 Bogito. All rights reserved.' author = 'Bogito' -version = 'v1.0.3' -desc = -[[ +version = 'v1.0.4' +desc = [[ This script will read the flash memory of RDV4 and print the stored passwords/keys. It was meant to be used as a help tool after using the BogRun standalone mode before SPIFFS. @@ -13,8 +13,7 @@ You should now use read_pwd_mem_spiffs instead after the updated BogRun standalo (Iceman) script adapted to read and print keys in the default dictionary flashmemory sections. ]] -example = -[[ +example = [[ -- This will scan the first 256 bytes of flash memory for stored passwords script run read_pwd_mem @@ -33,12 +32,10 @@ example = -- This will print the stored iClass dictionary keys script run read_pwd_mem -i ]] -usage = -[[ -Usage: - script run read_pwd_mem -h -o -l -k - -Arguments: +usage = [[ + script run read_pwd_mem [-h] [-o ] [-l ] [-k ] [-m] [-t] [-i] +]] +arguments = [[ -h : this help -o : memory offset, default is 0 -l : length in bytes, default is 256 @@ -61,9 +58,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end --- -- The main entry point diff --git a/client/luascripts/read_pwd_mem_spiffs.lua b/client/luascripts/read_pwd_mem_spiffs.lua index 89ef64e6d..ae2f0ba99 100644 --- a/client/luascripts/read_pwd_mem_spiffs.lua +++ b/client/luascripts/read_pwd_mem_spiffs.lua @@ -1,16 +1,15 @@ local getopt = require('getopt') local bin = require('bin') +local ansicolors = require('ansicolors') copyright = 'Copyright (c) 2019 Bogito. All rights reserved.' author = 'Bogito' -version = 'v1.1.1' -desc = -[[ +version = 'v1.1.2' +desc = [[ This script will read the flash memory of RDV4 using SPIFFS and print the stored passwords. It was meant to be used as a help tool after using the BogRun standalone mode. ]] -example = -[[ +example = [[ -- This will read the hf_bog.log file in SPIFFS and print the stored passwords script run read_pwd_mem_spiffs @@ -20,12 +19,10 @@ example = -- This will delete the hf_bog.log file from SPIFFS script run read_pwd_mem_spiffs -r ]] -usage = -[[ -Usage: - script run read_pwd_mem_spiffs -h -f -r - -Arguments: +usage = [[ + script run read_pwd_mem_spiffs [-h] [-f ] [-r] +]] +arguments = [[ -h : this help -f : filename in SPIFFS -r : delete filename from SPIFFS @@ -44,9 +41,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end --- -- The main entry point diff --git a/client/luascripts/remagic.lua b/client/luascripts/remagic.lua index 096fcfa27..51aa0be40 100644 --- a/client/luascripts/remagic.lua +++ b/client/luascripts/remagic.lua @@ -1,10 +1,10 @@ local getopt = require('getopt') +local ansicolors = require('ansicolors') copyright = '' author = 'Iceman' -version = 'v1.0.1' -desc = -[[ +version = 'v1.0.2' +desc = [[ This is a script that tries to bring back a chinese magic card (1k generation1) from the dead when it's block 0 has been written with bad values. or mifare Ultralight magic card which answers to chinese backdoor commands @@ -15,9 +15,9 @@ example = [[ ]] usage = [[ -script run remagic - -Arguments: +script run remagic [-h] [-u] +]] +arguments = [[ -h this help -u remagic a Ultralight tag w 7 bytes UID. ]] @@ -49,9 +49,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end local function cmdUltralight() diff --git a/client/luascripts/test_t55x7.lua b/client/luascripts/test_t55x7.lua index 0fc112ea7..b92375520 100644 --- a/client/luascripts/test_t55x7.lua +++ b/client/luascripts/test_t55x7.lua @@ -2,13 +2,14 @@ local cmds = require('commands') local getopt = require('getopt') local bin = require('bin') local utils = require('utils') +local ansicolors = require('ansicolors') local format = string.format local floor = math.floor copyright = '' author = "Iceman" -version = 'v1.0.1' +version = 'v1.0.2' desc =[[ This script will program a T55x7 TAG with a configuration and four blocks of data. It will then try to detect and read back those block data and compare if read data matches the expected data. @@ -32,10 +33,9 @@ example = [[ 1. script run test_t55x7 ]] usage = [[ - -script run test_t55x7 - -Arguments: +script run test_t55x7 [-h] +]] +arguments = [[ -h this help ]] @@ -79,9 +79,12 @@ local function help() print(author) print(version) print(desc) - print("Example usage") - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end --- -- Exit message From 175a5718b03e01a0a1e1adacb168da69c6f29642 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 5 Apr 2020 12:56:35 +0200 Subject: [PATCH 05/31] colors --- client/luascripts/test_t55x7_ask.lua | 18 +++++++++++------- client/luascripts/test_t55x7_bi.lua | 16 ++++++++++------ client/luascripts/test_t55x7_fsk.lua | 16 ++++++++++------ client/luascripts/test_t55x7_psk.lua | 16 ++++++++++------ client/luascripts/tnp3clone.lua | 20 ++++++++++++-------- client/luascripts/tnp3dump.lua | 18 +++++++++++------- client/luascripts/tnp3sim.lua | 20 ++++++++++++-------- client/luascripts/tracetest.lua | 22 +++++++++++++--------- client/luascripts/ufodump.lua | 20 ++++++++++++-------- client/luascripts/ul_uid.lua | 16 ++++++++++------ 10 files changed, 111 insertions(+), 71 deletions(-) diff --git a/client/luascripts/test_t55x7_ask.lua b/client/luascripts/test_t55x7_ask.lua index bb232a6fd..adfaf1eeb 100644 --- a/client/luascripts/test_t55x7_ask.lua +++ b/client/luascripts/test_t55x7_ask.lua @@ -2,14 +2,15 @@ local cmds = require('commands') local getopt = require('getopt') local bin = require('bin') local utils = require('utils') +local ansicolors = require('ansicolors') local format=string.format local floor=math.floor copyright = '' author = 'Iceman' -version = 'v1.0.1' -desc =[[ +version = 'v1.0.2' +desc = [[ This script will program a T55x7 TAG with the configuration: block 0x00 data 0x000100 The outlined procedure is as following: @@ -41,9 +42,9 @@ example =[[ 1. script run test_t55x7_ask ]] usage = [[ -script run test_t55x7_ask - -Arguments: +script run test_t55x7_ask [-h] +]] +arguments = [[ -h : this help ]] @@ -87,9 +88,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end -- -- Exit message diff --git a/client/luascripts/test_t55x7_bi.lua b/client/luascripts/test_t55x7_bi.lua index 49ee4882a..4b897b367 100644 --- a/client/luascripts/test_t55x7_bi.lua +++ b/client/luascripts/test_t55x7_bi.lua @@ -2,10 +2,11 @@ local cmds = require('commands') local getopt = require('getopt') local bin = require('bin') local utils = require('utils') +local ansicolors = require('ansicolors') copyright = '' author = 'Iceman' -version = 'v1.0.1' +version = 'v1.0.2' desc = [[ This script will program a T55x7 TAG with the configuration: block 0x00 data 0x00010040 The outlined procedure is as following: @@ -35,9 +36,9 @@ example = [[ 1. script run test_t55x7_bi ]] usage = [[ -script run test_t55x7_bi - -Arguments: +script run test_t55x7_bi [-h] +]] +arguments = [[ -h : this help ]] @@ -81,9 +82,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end -- -- Exit message diff --git a/client/luascripts/test_t55x7_fsk.lua b/client/luascripts/test_t55x7_fsk.lua index c755042b1..7a8d724a0 100644 --- a/client/luascripts/test_t55x7_fsk.lua +++ b/client/luascripts/test_t55x7_fsk.lua @@ -2,10 +2,11 @@ local cmds = require('commands') local getopt = require('getopt') local bin = require('bin') local utils = require('utils') +local ansicolors = require('ansicolors') copyright = '' author = 'Iceman' -version = 'v1.0.1' +version = 'v1.0.2' desc = [[ This script will program a T55x7 TAG with the configuration: block 0x00 data 0x000100 The outlined procedure is as following: @@ -37,9 +38,9 @@ example = [[ 1. script run test_t55x7_fsk ]] usage = [[ -script run test_t55x7_fsk - -Arguments: +script run test_t55x7_fsk [-h] +]] +arguments = [[ -h : this help ]] @@ -83,9 +84,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end -- -- Exit message diff --git a/client/luascripts/test_t55x7_psk.lua b/client/luascripts/test_t55x7_psk.lua index 10fecd549..0c991dcb0 100644 --- a/client/luascripts/test_t55x7_psk.lua +++ b/client/luascripts/test_t55x7_psk.lua @@ -2,10 +2,11 @@ local cmds = require('commands') local getopt = require('getopt') local bin = require('bin') local utils = require('utils') +local ansicolors = require('ansicolors') copyright = '' author = 'Iceman' -version = 'v1.0.1' +version = 'v1.0.2' desc = [[ This script will program a T55x7 TAG with the configuration: block 0x00 data 0x00088040 The outlined procedure is as following: @@ -33,9 +34,9 @@ example = [[ 2. script run test_t55x7_psk -o ]] usage = [[ -script run test_t55x7_psk - -Arguments: +script run test_t55x7_psk [-h] +]] +arguments = [[ -h : this help ]] @@ -82,9 +83,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end -- -- Exit message diff --git a/client/luascripts/tnp3clone.lua b/client/luascripts/tnp3clone.lua index 58bb5d338..056e7021b 100644 --- a/client/luascripts/tnp3clone.lua +++ b/client/luascripts/tnp3clone.lua @@ -4,6 +4,7 @@ local lib14a = require('read14a') local utils = require('utils') local pre = require('precalc') local toys = require('default_toys') +local ansicolors = require('ansicolors') local lsh = bit32.lshift local rsh = bit32.rshift @@ -12,11 +13,11 @@ local band = bit32.band copyright = '' author = "Iceman" -version = 'v1.0.1' -desc =[[ +version = 'v1.0.2' +desc = [[ This script will try making a barebone clone of a tnp3 tag on to a magic generation1 card. ]] -example =[[ +example = [[ script run tnp3clone script run tnp3clone -h script run tnp3clone -l @@ -24,9 +25,9 @@ example =[[ ]] usage = [[ -script run tnp3clone -t -s - -Arguments: +script run tnp3clone [-h] [-t ] [-s ] +]] +arguments = [[ -h : this help -l : list all known toy tokens -t : toytype id, 4hex symbols @@ -56,9 +57,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end --- -- decode response and get the blockdata from a normal mifare read command diff --git a/client/luascripts/tnp3dump.lua b/client/luascripts/tnp3dump.lua index 9a7a9bc8f..0dea0a01a 100644 --- a/client/luascripts/tnp3dump.lua +++ b/client/luascripts/tnp3dump.lua @@ -6,11 +6,12 @@ local utils = require('utils') local md5 = require('md5') local dumplib = require('html_dumplib') local toys = require('default_toys') +local ansicolors = require('ansicolors') copyright = '' author = 'Iceman' -version = 'v1.0.1' -desc =[[ +version = 'v1.0.2' +desc = [[ This script will try to dump the contents of a Mifare TNP3xxx card. It will need a valid KeyA in order to find the other keys and decode the card. ]] @@ -26,9 +27,9 @@ example = [[ script run tnp3dump -k aabbccddeeff -n -o myfile ]] usage = [[ -script run tnp3dump -k -n -p -o - -Arguments: +script run tnp3dump [-h] [-k ] [-n] [-p] [-o ] +]] +arguments = [[ -h : this help -k : Sector 0 Key A. -n : Use the nested cmd to find all keys @@ -69,9 +70,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end -- -- Exit message diff --git a/client/luascripts/tnp3sim.lua b/client/luascripts/tnp3sim.lua index 014474416..069bbfe08 100644 --- a/client/luascripts/tnp3sim.lua +++ b/client/luascripts/tnp3sim.lua @@ -6,25 +6,26 @@ local utils = require('utils') local md5 = require('md5') local toys = require('default_toys') local pre = require('precalc') +local ansicolors = require('ansicolors') copyright = '' author = 'Iceman' -version = 'v1.0.1' -desc =[[ +version = 'v1.0.2' +desc = [[ This script will try to load a binary datadump of a Mifare TNP3xxx card. It vill try to validate all checksums and view some information stored in the dump For an experimental mode, it tries to manipulate some data. At last it sends all data to the PM3 device memory where it can be used in the command "hf mf sim" ]] -example =[[ +example = [[ 1. script run tnp3sim 2. script run tnp3sim -m 3. script run tnp3sim -m -i myfile ]] usage = [[ -script run tnp3sim -h -m -i - -Arguments: +script run tnp3sim [-h] [-m] [-i ] +]] +arguments = [[ -h : this help -m : Maxed out items (experimental) -i : filename for the datadump to read (bin) @@ -70,9 +71,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end -- -- Exit message diff --git a/client/luascripts/tracetest.lua b/client/luascripts/tracetest.lua index 44cd66b58..c1917b401 100644 --- a/client/luascripts/tracetest.lua +++ b/client/luascripts/tracetest.lua @@ -3,11 +3,12 @@ local getopt = require('getopt') local bin = require('bin') local utils = require('utils') local dumplib = require('html_dumplib') +local ansicolors = require('ansicolors') copyright = '' author = 'Iceman' -version = 'v1.0.1' -desc =[[ +version = 'v1.0.2' +desc = [[ This script will load several traces files in ../traces/ folder and do "data load" "lf search 1 u" @@ -16,13 +17,13 @@ The following tracefiles will be loaded: em*.pm3 m*.pm3 ]] -example =[[ - script run tracetest +example = [[ + 1. script run tracetest ]] usage = [[ -script run tracetest -h - -Arguments: +script run tracetest [-h] +]] +arguments = [[ -h : this help ]] local DEBUG = true -- the debug flag @@ -54,9 +55,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end -- -- Exit message diff --git a/client/luascripts/ufodump.lua b/client/luascripts/ufodump.lua index ccf20f6b4..d9a8faa68 100644 --- a/client/luascripts/ufodump.lua +++ b/client/luascripts/ufodump.lua @@ -2,10 +2,11 @@ local cmds = require('commands') local getopt = require('getopt') local lib14a = require('read14a') local utils = require('utils') +local ansicolors = require('ansicolors') copyright = '' author = 'Iceman' -version = 'v1.0.1' +version = 'v1.0.2' desc = [[ This is a script that reads AZTEK ISO14443a tags. It starts from block 0 and ends at default block 20. Use 'b' to say different endblock. @@ -19,11 +20,11 @@ example = [[ script run ufodump -b 10 ]] usage = [[ -script run ufudump -h -b - -Arguments: - h this helptext - b endblock in decimal (1-255, default 20) +script run ufudump [-h] [-b] +]] +arguments = [[ + -h This help + -b endblock in decimal (1-255, default 20) ]] -- Some globals @@ -56,9 +57,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end -- --- Picks out and displays the data read from a tag diff --git a/client/luascripts/ul_uid.lua b/client/luascripts/ul_uid.lua index 9ac89c211..ece368ce5 100644 --- a/client/luascripts/ul_uid.lua +++ b/client/luascripts/ul_uid.lua @@ -1,9 +1,10 @@ local getopt = require('getopt') local utils = require('utils') +local ansicolors = require('ansicolors') copyright = '' author = "Iceman" -version = 'v1.0.1' +version = 'v1.0.2' desc = [[ This script tries to set UID on a mifare Ultralight magic card which either - answers to chinese backdoor commands @@ -17,9 +18,9 @@ example = [[ script run ul_uid -b -u 11223344556677 ]] usage = [[ -script run ul_uid -h -b -u - -Arguments: +script run ul_uid [-h] [-b] [-u ] +]] +arguments = [[ -h : this help -u : UID (14 hexsymbols) -b : write to brickable magic tag @@ -55,9 +56,12 @@ local function help() print(author) print(version) print(desc) - print('Example usage') - print(example) + print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) end -- --- Set UID on magic command enabled From 06afb795a0c78d213fb69af4cb899e9a4cf2849c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 5 Apr 2020 13:02:50 +0200 Subject: [PATCH 06/31] text --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 95d7ce2e6..946b7c541 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Updated helptext layout in all luascripts (@iceman1001) + - Change `hf mfdes info` - output and logging (@brkeler) + - Updated texts in legic commands (@ikarus23) + - Fix timing bug inside 40x5 (@mwalker33) + - Refactored all Hitag2 attacks (@doegox) + - Added two new Hitag2 attacks (@doegox) - Change `hf search` - now continue to search in case of dual tech cards (@iceman1001) Thanks to @ikarus23 for the suggestion! - Added `hf topas info` - old reader command, now also prints NDEF (@iceman1001) - Change `hf topaz reader` - now only prints lighter info, like UID. (@iceman1001) From 16b14aa0e670b488906f8bf43ed2d123b8056090 Mon Sep 17 00:00:00 2001 From: Uli Heilmeier Date: Sun, 5 Apr 2020 12:56:00 +0200 Subject: [PATCH 07/31] Legic_clone.lua: Refactor to work with current command set Refactored to work with current command set and MIM256 and MIM1024 tags --- client/luascripts/Legic_clone.lua | 119 +++++++++++++----------------- 1 file changed, 52 insertions(+), 67 deletions(-) diff --git a/client/luascripts/Legic_clone.lua b/client/luascripts/Legic_clone.lua index 191f9f9e0..a0a8e590d 100644 --- a/client/luascripts/Legic_clone.lua +++ b/client/luascripts/Legic_clone.lua @@ -1,4 +1,5 @@ local utils = require('utils') +local cmds = require('commands') local getopt = require('getopt') local ansicolors = require('ansicolors') --[[ @@ -16,10 +17,10 @@ local ansicolors = require('ansicolors') simplest usage: read a valid legic tag with 'hf legic reader' - save the dump with 'hf legic save orig.hex' - place your 'empty' tag on the reader and run 'script run Legic_clone -i orig.hex -w' + save the dump with 'hf legic dump o orig' + place your 'empty' tag on the reader and run 'script run Legic_clone -i orig.bin -w' you will see some output like: - read 1024 bytes from legic_dumps/j_0000.hex + read 1024 bytes from orig.bin place your empty tag onto the PM3 to read and display the MCD & MSN0..2 the values will be shown below @@ -92,18 +93,18 @@ author = 'Mosci' version = 'v1.0.2' desc = [[ This is a script which creates a clone-dump of a dump from a Legic Prime Tag (MIM256 or MIM1024) -(created with 'hf legic save my_dump.hex') +(created with 'hf legic dump o my_dump') ]] example = [[ - script run legic_clone -i my_dump.hex -o my_clone.hex -c f8 - script run legic_clone -i my_dump.hex -d -s + script run legic_clone -i my_dump.bin -o my_clone.bin -c f8 + script run legic_clone -i my_dump.bin -d -s ]] usage = [[ script run legic_clone -h -i -o -c -d -s -w ]] arguments = [[ required : - -i (file to read data from) + -i (file to read data from, must be in binary format (*.bin)) optional : -h - Help text @@ -111,7 +112,7 @@ optional : -c - requires option -o to be given -d - Display content of found Segments -s - Display summary at the end - -w - write directly to Tag - a file myLegicClone.hex wille be generated also + -w - write directly to Tag - a file myLegicClone.bin will be generated also e.g.: hint: using the CRC '00' will result in a plain dump ( -c 00 ) @@ -138,6 +139,23 @@ local function oops(err) core.clearCommandBuffer() return nil, err end + +-- read LEGIC data +local function readlegicdata( offset, length, iv ) + -- Read data + local command = Command:newMIX{ + cmd = cmds.CMD_HF_LEGIC_READER + , arg1 = offset + , arg2 = length + , arg3 = iv + , data = nil + } + local result, err = command:sendMIX() + if not result then return oops(err) end + -- result is a packed data structure, data starts at offset 33 + return result +end + --- -- Usage help local function help() @@ -179,16 +197,12 @@ local function getInputBytes(infile) local line local bytes = {} - local fhi,err = io.open(infile) + local fhi,err = io.open(infile,"rb") if err then print("OOps ... faild to read from file ".. infile); return false; end - while true do - line = fhi:read() - if line == nil then break end - - for byte in line:gmatch("%w+") do - table.insert(bytes, byte) - end + str = fhi:read("*all") + for c in (str or ''):gmatch'.' do + bytes[#bytes+1] = ('%02x'):format(c:byte()) end fhi:close() @@ -199,25 +213,11 @@ end -- write to file local function writeOutputBytes(bytes, outfile) - local line - local bcnt = 0 - local fho,err = io.open(outfile,"w") + local fho,err = io.open(outfile,"wb") if err then print("OOps ... faild to open output-file ".. outfile); return false; end for i = 1, #bytes do - if (bcnt == 0) then - line = bytes[i] - elseif (bcnt <= 7) then - line = line.." "..bytes[i] - end - if (bcnt == 7) then - -- write line to new file - fho:write(line.."\n") - -- reset counter & line - bcnt = -1 - line = "" - end - bcnt = bcnt + 1 + fho:write(string.char(tonumber(bytes[i],16))) end fho:close() print("\nwrote ".. #bytes .." bytes to " .. outfile) @@ -322,7 +322,7 @@ function getSegmentCrcBytes(bytes) return crcbytes end --- print segment-data (hf legic decode like) +-- print segment-data (hf legic info like) function displaySegments(bytes) --display segment header(s) start = 23 @@ -389,23 +389,25 @@ end -- write clone-data to tag function writeToTag(plainBytes) local SegCrcs = {} - if(utils.confirm("\nplace your empty tag onto the PM3 to read and display the MCD & MSN0..2\nthe values will be shown below\n confirm when ready") == false) then + local output + local readbytes + if(utils.confirm("\nplace your empty tag onto the PM3 to restore the data of the input file\nthe CRCs will be calculated as needed\n confirm when ready") == false) then return end + readbytes = readlegicdata(0, 4, 0x55) -- gather MCD & MSN from new Tag - this must be enterd manually - cmd = 'hf legic read 0x00 0x04' - core.console(cmd) print("\nthese are the MCD MSN0 MSN1 MSN2 from the Tag that has being read:") - cmd = 'data hexsamples 4' - core.console(cmd) - print("^^ use this values as input for the following answers (one 2-digit-value per question/answer):") - -- enter MCD & MSN (in hex) - MCD = utils.input("type in MCD as 2-digit value - e.g.: 00", plainBytes[1]) - MSN0 = utils.input("type in MSN0 as 2-digit value - e.g.: 01", plainBytes[2]) - MSN1 = utils.input("type in MSN1 as 2-digit value - e.g.: 02", plainBytes[3]) - MSN2 = utils.input("type in MSN2 as 2-digit value - e.g.: 03", plainBytes[4]) + plainBytes[1] = ('%02x'):format(readbytes:byte(33)) + plainBytes[2] = ('%02x'):format(readbytes:byte(34)) + plainBytes[3] = ('%02x'):format(readbytes:byte(35)) + plainBytes[4] = ('%02x'):format(readbytes:byte(36)) + + MCD = plainBytes[1] + MSN0 = plainBytes[2] + MSN1 = plainBytes[3] + MSN2 = plainBytes[4] -- calculate crc8 over MCD & MSN cmd = MCD..MSN0..MSN1..MSN2 MCC = ("%02x"):format(utils.Crc8Legic(cmd)) @@ -437,27 +439,10 @@ function writeToTag(plainBytes) bytes = xorBytes(plainBytes, MCC) -- write data to file - if (writeOutputBytes(bytes, "myLegicClone.hex")) then - WriteBytes = utils.input("enter number of bytes to write?", SegCrcs[#SegCrcs]) - - -- load file into pm3-buffer - cmd = 'hf legic eload myLegicClone.hex' - core.console(cmd) - + if (writeOutputBytes(bytes, "myLegicClone.bin")) then -- write pm3-buffer to Tag - for i=0, WriteBytes do - if ( i<5 or i>6) then - cmd = ('hf legic write o %02x d 01'):format(i) - core.console(cmd) - elseif (i == 6) then - -- write DCF in reverse order (requires 'mosci-patch') - cmd = 'hf legic write o 05 d 02' - core.console(cmd) - else - print("skipping byte 0x05 - will be written next step") - end - utils.Sleep(0.2) - end + cmd = ('hf legic restore i myLegicClone') + core.console(cmd) end end @@ -495,7 +480,7 @@ function main(args) end -- new crc if o == 'c' then - newcrc = a + newcrc = a:lower() ncs = true end -- display segments switch @@ -535,7 +520,7 @@ function main(args) res = res .."\nafter writing this dump to a tag!" res = res .."\n\na segmentCRC gets calculated over MCD,MSN0..3,Segment-Header0..3" res = res .."\ne.g. (based on Segment00 of the data from "..infile.."):" - res = res .."\nhf legic crc8 "..bytes[1]..bytes[2]..bytes[3]..bytes[4]..bytes[23]..bytes[24]..bytes[25]..bytes[26] + res = res .."\nhf legic crc d "..bytes[1]..bytes[2]..bytes[3]..bytes[4]..bytes[23]..bytes[24]..bytes[25]..bytes[26].." u "..newcrc.." c 8" -- this can not be calculated without knowing the new MCD, MSN0..2 print(res) end @@ -549,7 +534,7 @@ function main(args) end end -- write to tag - if (ws and #bytes == 1024) then + if (ws and ( #bytes == 1024 or #bytes == 256)) then writeToTag(bytes) end end From eac19be4142010d537588e89220f3da5958de705 Mon Sep 17 00:00:00 2001 From: Uli Heilmeier Date: Sun, 5 Apr 2020 13:16:14 +0200 Subject: [PATCH 08/31] Legic_clone.lua: Adopt last command changes --- client/luascripts/Legic_clone.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/luascripts/Legic_clone.lua b/client/luascripts/Legic_clone.lua index a0a8e590d..00834c98b 100644 --- a/client/luascripts/Legic_clone.lua +++ b/client/luascripts/Legic_clone.lua @@ -93,7 +93,7 @@ author = 'Mosci' version = 'v1.0.2' desc = [[ This is a script which creates a clone-dump of a dump from a Legic Prime Tag (MIM256 or MIM1024) -(created with 'hf legic dump o my_dump') +(created with 'hf legic dump f my_dump') ]] example = [[ script run legic_clone -i my_dump.bin -o my_clone.bin -c f8 @@ -441,7 +441,7 @@ function writeToTag(plainBytes) -- write data to file if (writeOutputBytes(bytes, "myLegicClone.bin")) then -- write pm3-buffer to Tag - cmd = ('hf legic restore i myLegicClone') + cmd = ('hf legic restore f myLegicClone') core.console(cmd) end end @@ -515,7 +515,7 @@ function main(args) res = "\n+-------------------------------------------- Summary -------------------------------------------+" res = res .."\ncreated clone_dump from\n\t"..infile.." crc: "..oldcrc.."\ndump_file:" res = res .."\n\t"..outfile.." crc: "..string.sub(newcrc,-2) - res = res .."\nyou may load the new file with: hf legic load "..outfile + res = res .."\nyou may load the new file with: hf legic eload "..outfile res = res .."\n\nif you don't write to tag immediately ('-w' switch) you will need to recalculate each segmentCRC" res = res .."\nafter writing this dump to a tag!" res = res .."\n\na segmentCRC gets calculated over MCD,MSN0..3,Segment-Header0..3" From acfe18e7e97218cc8c47bef31023f851e8fd297c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 5 Apr 2020 14:18:07 +0200 Subject: [PATCH 09/31] rename to lower --- client/luascripts/legic_clone.lua | 543 ++++++++++++++++++++++++++++++ 1 file changed, 543 insertions(+) create mode 100644 client/luascripts/legic_clone.lua diff --git a/client/luascripts/legic_clone.lua b/client/luascripts/legic_clone.lua new file mode 100644 index 000000000..00834c98b --- /dev/null +++ b/client/luascripts/legic_clone.lua @@ -0,0 +1,543 @@ +local utils = require('utils') +local cmds = require('commands') +local getopt = require('getopt') +local ansicolors = require('ansicolors') +--[[ + script to create a clone-dump with new crc + Author: mosci + my Fork: https://github.com/icsom/proxmark3.git + Upstream: https://github.com/Proxmark/proxmark3.git + + 1. read tag-dump, xor byte 22..end with byte 0x05 of the inputfile + 2. write to outfile + 3. set byte 0x05 to newcrc + 4. until byte 0x21 plain like in inputfile + 5. from 0x22..end xored with newcrc + 6. calculate new crc on each segment (needs to know the new MCD & MSN0..2) + + simplest usage: + read a valid legic tag with 'hf legic reader' + save the dump with 'hf legic dump o orig' + place your 'empty' tag on the reader and run 'script run Legic_clone -i orig.bin -w' + you will see some output like: + read 1024 bytes from orig.bin + + place your empty tag onto the PM3 to read and display the MCD & MSN0..2 + the values will be shown below + confirm when ready [y/n] ?y + #db# setting up legic card + #db# MIM 256 card found, reading card ... + #db# Card read, use 'hf legic decode' or + #db# 'data hexsamples 8' to view results + 0b ad c0 de <- !! here you'll see the MCD & MSN of your empty tag, which has to be typed in manually as seen below !! + type in MCD as 2-digit value - e.g.: 00 (default: 79 ) + > 0b + type in MSN0 as 2-digit value - e.g.: 01 (default: 28 ) + > ad + type in MSN1 as 2-digit value - e.g.: 02 (default: d1 ) + > c0 + type in MSN2 as 2-digit value - e.g.: 03 (default: 43 ) + > de + MCD:0b, MSN:ad c0 de, MCC:79 <- this crc is calculated from the MCD & MSN and must match the one on yout empty tag + + wrote 1024 bytes to myLegicClone.hex + enter number of bytes to write? (default: 86 ) + + loaded 1024 samples + #db# setting up legic card + #db# MIM 256 card found, writing 0x00 - 0x01 ... + #db# write successful + ... + #db# setting up legic card + #db# MIM 256 card found, writing 0x56 - 0x01 ... + #db# write successful + proxmark3> + + the default value (number of bytes to write) is calculated over all valid segments and should be ok - just hit enter, wait until write has finished + and your clone should be ready (except there has to be a additional KGH-CRC to be calculated - which credentials are unknown until yet) + + the '-w' switch will only work with my fork - it needs the binary legic_crc8 which is not part of the proxmark3-master-branch + also the ability to write DCF is not possible with the proxmark3-master-branch + but creating dumpfile-clone files will be possible (without valid segment-crc - this has to done manually with) + + + (example) Legic-Prime Layout with 'Kaba Group Header' + +----+----+----+----+----+----+----+----+ + 0x00|MCD |MSN0|MSN1|MSN2|MCC | 60 | ea | 9f | + +----+----+----+----+----+----+----+----+ + 0x08| ff | 00 | 00 | 00 | 11 |Bck0|Bck1|Bck2| + +----+----+----+----+----+----+----+----+ + 0x10|Bck3|Bck4|Bck5|BCC | 00 | 00 |Seg0|Seg1| + +----+----+----+----+----+----+----+----+ + 0x18|Seg2|Seg3|SegC|Stp0|Stp1|Stp2|Stp3|UID0| + +----+----+----+----+----+----+----+----+ + 0x20|UID1|UID2|kghC| + +----+----+----+ + + MCD= ManufacturerID (1 Byte) + MSN0..2= ManufactureSerialNumber (3 Byte) + MCC= CRC (1 Byte) calculated over MCD,MSN0..2 + DCF= DecrementalField (2 Byte) 'credential' (enduser-Tag) seems to have always DCF-low=0x60 DCF-high=0xea + Bck0..5= Backup (6 Byte) Bck0 'dirty-flag', Bck1..5 SegmentHeader-Backup + BCC= BackupCRC (1 Byte) CRC calculated over Bck1..5 + Seg0..3= SegmentHeader (on MIM 4 Byte ) + SegC= SegmentCRC (1 Byte) calculated over MCD,MSN0..2,Seg0..3 + Stp0..n= Stamp0... (variable length) length = Segment-Len - UserData - 1 + UID0..n= UserDater (variable length - with KGH hex 0x00-0x63 / dec 0-99) length = Segment-Len - WRP - WRC - 1 + kghC= KabaGroupHeader (1 Byte + addr 0x0c must be 0x11) + as seen on this example: addr 0x05..0x08 & 0x0c must have been set to this values - otherwise kghCRC will not be created by a official reader (not accepted) +--]] + +copyright = '' +author = 'Mosci' +version = 'v1.0.2' +desc = [[ +This is a script which creates a clone-dump of a dump from a Legic Prime Tag (MIM256 or MIM1024) +(created with 'hf legic dump f my_dump') +]] +example = [[ + script run legic_clone -i my_dump.bin -o my_clone.bin -c f8 + script run legic_clone -i my_dump.bin -d -s +]] +usage = [[ +script run legic_clone -h -i -o -c -d -s -w +]] +arguments = [[ +required : + -i (file to read data from, must be in binary format (*.bin)) + +optional : + -h - Help text + -o - requires option -c to be given + -c - requires option -o to be given + -d - Display content of found Segments + -s - Display summary at the end + -w - write directly to Tag - a file myLegicClone.bin will be generated also + + e.g.: + hint: using the CRC '00' will result in a plain dump ( -c 00 ) +]] + +local bxor = bit32.bxor + +-- we need always 2 digits +local function prepend_zero(s) + if (string.len(s) == 1) then + return '0' .. s + else + if (string.len(s) == 0) then + return '00' + else + return s + end + 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 + +-- read LEGIC data +local function readlegicdata( offset, length, iv ) + -- Read data + local command = Command:newMIX{ + cmd = cmds.CMD_HF_LEGIC_READER + , arg1 = offset + , arg2 = length + , arg3 = iv + , data = nil + } + local result, err = command:sendMIX() + if not result then return oops(err) end + -- result is a packed data structure, data starts at offset 33 + return result +end + +--- +-- Usage help +local function help() + print(copyright) + print(author) + print(version) + print(desc) + print(ansicolors.cyan..'Usage'..ansicolors.reset) + print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) +end + +-- Check availability of file +local function file_check(file_name) + local file_found = io.open(file_name, "r") + if not file_found then + file_found = false + else + file_found = true + end + return file_found +end + +--- xor-wrapper +-- xor all from addr 0x22 (start counting from 1 => 23) +local function xorme(hex, xor, index) + if ( index >= 23 ) then + return ('%02x'):format(bxor( tonumber(hex,16) , tonumber(xor,16) )) + else + return hex + end +end + +-- read input-file into array +local function getInputBytes(infile) + local line + local bytes = {} + + local fhi,err = io.open(infile,"rb") + if err then print("OOps ... faild to read from file ".. infile); return false; end + + str = fhi:read("*all") + for c in (str or ''):gmatch'.' do + bytes[#bytes+1] = ('%02x'):format(c:byte()) + end + + fhi:close() + + print("\nread ".. #bytes .." bytes from ".. infile) + return bytes +end + +-- write to file +local function writeOutputBytes(bytes, outfile) + local fho,err = io.open(outfile,"wb") + if err then print("OOps ... faild to open output-file ".. outfile); return false; end + + for i = 1, #bytes do + fho:write(string.char(tonumber(bytes[i],16))) + end + fho:close() + print("\nwrote ".. #bytes .." bytes to " .. outfile) + return true +end + +-- xore certain bytes +local function xorBytes(inBytes, crc) + local bytes = {} + for index = 1, #inBytes do + bytes[index] = xorme(inBytes[index], crc, index) + end + if (#inBytes == #bytes) then + -- replace crc + bytes[5] = string.sub(crc,-2) + return bytes + else + print("error: byte-count missmatch") + return false + end +end + +-- get raw segment-data +function getSegmentData(bytes, start, index) + local raw, len, valid, last, wrp, wrc, rd, crc + local segment = {} + segment[0] = bytes[start]..' '..bytes[start+1]..' '..bytes[start+2]..' '..bytes[start+3] + -- flag = high nibble of byte 1 + segment[1] = string.sub(bytes[start+1],0,1) + + -- valid = bit 6 of byte 1 + segment[2] = tonumber(bit32.extract('0x'..bytes[start+1],6,1),16) + + -- last = bit 7 of byte 1 + segment[3] = tonumber(bit32.extract('0x'..bytes[start+1],7,1),16) + + -- len = (byte 0)+(bit0-3 of byte 1) + segment[4] = tonumber(('%03x'):format(tonumber(bit32.extract('0x'..bytes[start+1],0,3),16)..tonumber(bytes[start],16)),16) + + -- wrp (write proteted) = byte 2 + segment[5] = tonumber(bytes[start+2]) + + -- wrc (write control) - bit 4-6 of byte 3 + segment[6] = tonumber(bit32.extract('0x'..bytes[start+3],4,3),16) + + -- rd (read disabled) - bit 7 of byte 3 + segment[7] = tonumber(bit32.extract('0x'..bytes[start+3],7,1),16) + + -- crc byte 4 + segment[8] = bytes[start+4] + + -- segment index + segment[9] = index + + -- # crc-byte + segment[10] = start+4 + return segment +end + +--- Kaba Group Header +-- checks if a segment does have a kghCRC +-- returns boolean false if no kgh has being detected or the kghCRC if a kgh was detected +function CheckKgh(bytes, segStart, segEnd) + if (bytes[8]=='9f' and bytes[9]=='ff' and bytes[13]=='11') then + local i + local data = {} + segStart = tonumber(segStart, 10) + segEnd = tonumber(segEnd, 10) + local dataLen = segEnd-segStart-5 + --- gather creadentials for verify + local WRP = bytes[(segStart+2)] + local WRC = ("%02x"):format(tonumber(bit32.extract("0x"..bytes[segStart+3],4,3),16)) + local RD = ("%02x"):format(tonumber(bit32.extract("0x"..bytes[segStart+3],7,1),16)) + local XX = "00" + cmd = bytes[1]..bytes[2]..bytes[3]..bytes[4]..WRP..WRC..RD..XX + for i = (segStart+5), (segStart+5+dataLen-2) do + cmd = cmd..bytes[i] + end + local KGH = ("%02x"):format(utils.Crc8Legic(cmd)) + if (KGH == bytes[segEnd-1]) then + return KGH + else + return false + end + else + return false + end +end + +-- get only the addresses of segemnt-crc's and the length of bytes +function getSegmentCrcBytes(bytes) + local start = 23 + local index = 0 + local crcbytes = {} + repeat + seg = getSegmentData(bytes,start,index) + crcbytes[index] = seg[10] + start = start + seg[4] + index = index + 1 + until (seg[3] == 1 or tonumber(seg[9]) == 126 ) + crcbytes[index] = start + return crcbytes +end + +-- print segment-data (hf legic info like) +function displaySegments(bytes) + --display segment header(s) + start = 23 + index = '00' + + --repeat until last-flag ist set to 1 or segment-index has reached 126 + repeat + wrc = '' + wrp = '' + pld = '' + Seg = getSegmentData(bytes, start, index) + KGH = CheckKgh(bytes, start, (start+tonumber(Seg[4],10))) + printSegment(Seg) + + -- wrc + if (Seg[6] > 0) then + print("WRC protected area:") + -- length of wrc = wrc + for i=1, Seg[6] do + -- starts at (segment-start + segment-header + segment-crc)-1 + wrc = wrc..bytes[(start+4+1+i)-1]..' ' + end + print(wrc) + elseif (Seg[5] > 0) then + print("Remaining write protected area:") + -- length of wrp = (wrp-wrc) + for i=1, (Seg[5]-Seg[6]) do + -- starts at (segment-start + segment-header + segment-crc + wrc)-1 + wrp = wrp..bytes[(start+4+1+Seg[6]+i)-1]..' ' + end + print(wrp) + end + + -- payload + print("Remaining segment payload:") + --length of payload = segment-len - segment-header - segment-crc - wrp -wrc + for i=1, (Seg[4]-4-1-Seg[5]-Seg[6]) do + -- starts at (segment-start + segment-header + segment-crc + segment-wrp + segemnt-wrc)-1 + pld = pld..bytes[(start+4+1+Seg[5]+Seg[6]+i)-1]..' ' + end + print(pld) + if (KGH) then + print("'Kaba Group Header' detected") + end + start = start+Seg[4] + index = prepend_zero(tonumber(Seg[9])+1) + + until (Seg[3] == 1 or tonumber(Seg[9]) == 126 ) +end + +-- print Segment values +function printSegment(SegmentData) + res = "\nSegment "..SegmentData[9]..": " + res = res.. "raw header="..SegmentData[0]..", " + res = res.. "flag="..SegmentData[1].." (valid="..SegmentData[2].." last="..SegmentData[3].."), " + res = res.. "len="..("%04d"):format(SegmentData[4])..", " + res = res.. "WRP="..prepend_zero(SegmentData[5])..", " + res = res.. "WRC="..prepend_zero(SegmentData[6])..", " + res = res.. "RD="..SegmentData[7]..", " + res = res.. "crc="..SegmentData[8] + print(res) +end + +-- write clone-data to tag +function writeToTag(plainBytes) + local SegCrcs = {} + local output + local readbytes + if(utils.confirm("\nplace your empty tag onto the PM3 to restore the data of the input file\nthe CRCs will be calculated as needed\n confirm when ready") == false) then + return + end + + readbytes = readlegicdata(0, 4, 0x55) + -- gather MCD & MSN from new Tag - this must be enterd manually + print("\nthese are the MCD MSN0 MSN1 MSN2 from the Tag that has being read:") + + plainBytes[1] = ('%02x'):format(readbytes:byte(33)) + plainBytes[2] = ('%02x'):format(readbytes:byte(34)) + plainBytes[3] = ('%02x'):format(readbytes:byte(35)) + plainBytes[4] = ('%02x'):format(readbytes:byte(36)) + + MCD = plainBytes[1] + MSN0 = plainBytes[2] + MSN1 = plainBytes[3] + MSN2 = plainBytes[4] + -- calculate crc8 over MCD & MSN + cmd = MCD..MSN0..MSN1..MSN2 + MCC = ("%02x"):format(utils.Crc8Legic(cmd)) + print("MCD:"..MCD..", MSN:"..MSN0.." "..MSN1.." "..MSN2..", MCC:"..MCC) + + -- calculate new Segment-CRC for each valid segment + SegCrcs = getSegmentCrcBytes(plainBytes) + for i=0, (#SegCrcs-1) do + -- SegCrcs[i]-4 = address of first byte of segmentHeader (low byte segment-length) + segLen = tonumber(("%1x"):format(tonumber(bit32.extract("0x"..plainBytes[(SegCrcs[i]-3)],0,3),16))..("%02x"):format(tonumber(plainBytes[SegCrcs[i]-4],16)),16) + segStart = (SegCrcs[i]-4) + segEnd = (SegCrcs[i]-4+segLen) + KGH = CheckKgh(plainBytes,segStart,segEnd) + if (KGH) then + print("'Kaba Group Header' detected - re-calculate...") + end + cmd = MCD..MSN0..MSN1..MSN2..plainBytes[SegCrcs[i]-4]..plainBytes[SegCrcs[i]-3]..plainBytes[SegCrcs[i]-2]..plainBytes[SegCrcs[i]-1] + plainBytes[SegCrcs[i]] = ("%02x"):format(utils.Crc8Legic(cmd)) + end + + -- apply MCD & MSN to plain data + plainBytes[1] = MCD + plainBytes[2] = MSN0 + plainBytes[3] = MSN1 + plainBytes[4] = MSN2 + plainBytes[5] = MCC + + -- prepare plainBytes for writing (xor plain data with new MCC) + bytes = xorBytes(plainBytes, MCC) + + -- write data to file + if (writeOutputBytes(bytes, "myLegicClone.bin")) then + -- write pm3-buffer to Tag + cmd = ('hf legic restore f myLegicClone') + core.console(cmd) + end +end + +-- main function +function main(args) + -- some variables + local i = 0 + local oldcrc, newcrc, infile, outfile + local bytes = {} + local segments = {} + + -- parse arguments for the script + for o, a in getopt.getopt(args, 'hwsdc:i:o:') do + -- output file + if o == 'o' then + outfile = a + ofs = true + if (file_check(a)) then + local answer = utils.confirm('\nthe output-file '..a..' already exists!\nthis will delete the previous content!\ncontinue?') + if (answer==false) then return oops('quiting') end + end + end + -- input file + if o == 'i' then + infile = a + if (file_check(infile)==false) then + return oops('input file: '..infile..' not found') + else + bytes = getInputBytes(infile) + oldcrc = bytes[5] + ifs = true + if (bytes == false) then return oops('couldnt get input bytes') end + end + i = i+1 + end + -- new crc + if o == 'c' then + newcrc = a:lower() + ncs = true + end + -- display segments switch + if o == 'd' then ds = true; end + -- display summary switch + if o == 's' then ss = true; end + -- write to tag switch + if o == 'w' then ws = true; end + -- help + if o == 'h' then return help() end + end + + if (not ifs) then return oops('option -i is required but missing') end + + -- bytes to plain + bytes = xorBytes(bytes, oldcrc) + + -- show segments (works only on plain bytes) + if (ds) then + print("+------------------------------------------- Segments -------------------------------------------+") + displaySegments(bytes); + end + + if (ofs and ncs) then + -- xor bytes with new crc + newBytes = xorBytes(bytes, newcrc) + -- write output + if (writeOutputBytes(newBytes, outfile)) then + -- show summary if requested + if (ss) then + -- information + res = "\n+-------------------------------------------- Summary -------------------------------------------+" + res = res .."\ncreated clone_dump from\n\t"..infile.." crc: "..oldcrc.."\ndump_file:" + res = res .."\n\t"..outfile.." crc: "..string.sub(newcrc,-2) + res = res .."\nyou may load the new file with: hf legic eload "..outfile + res = res .."\n\nif you don't write to tag immediately ('-w' switch) you will need to recalculate each segmentCRC" + res = res .."\nafter writing this dump to a tag!" + res = res .."\n\na segmentCRC gets calculated over MCD,MSN0..3,Segment-Header0..3" + res = res .."\ne.g. (based on Segment00 of the data from "..infile.."):" + res = res .."\nhf legic crc d "..bytes[1]..bytes[2]..bytes[3]..bytes[4]..bytes[23]..bytes[24]..bytes[25]..bytes[26].." u "..newcrc.." c 8" + -- this can not be calculated without knowing the new MCD, MSN0..2 + print(res) + end + end + else + if (ss) then + -- show why the output-file was not written + print("\nnew file not written - some arguments are missing ..") + print("output file: ".. (ofs and outfile or "not given")) + print("new crc: ".. (ncs and newcrc or "not given")) + end + end + -- write to tag + if (ws and ( #bytes == 1024 or #bytes == 256)) then + writeToTag(bytes) + end +end + +-- call main with arguments +main(args) From 3a2723ac63f9eed70c08fb1daefabaa7a54f604f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 5 Apr 2020 14:53:32 +0200 Subject: [PATCH 10/31] style --- client/luascripts/legic_clone.lua | 204 +++++++++++++++--------------- 1 file changed, 101 insertions(+), 103 deletions(-) diff --git a/client/luascripts/legic_clone.lua b/client/luascripts/legic_clone.lua index 00834c98b..29a43a184 100644 --- a/client/luascripts/legic_clone.lua +++ b/client/luascripts/legic_clone.lua @@ -2,6 +2,7 @@ local utils = require('utils') local cmds = require('commands') local getopt = require('getopt') local ansicolors = require('ansicolors') + --[[ script to create a clone-dump with new crc Author: mosci @@ -17,18 +18,15 @@ local ansicolors = require('ansicolors') simplest usage: read a valid legic tag with 'hf legic reader' - save the dump with 'hf legic dump o orig' - place your 'empty' tag on the reader and run 'script run Legic_clone -i orig.bin -w' + save the dump with 'hf legic dump f orig' + place your 'empty' tag on the reader and run 'script run legic_clone -i orig.bin -w' you will see some output like: read 1024 bytes from orig.bin place your empty tag onto the PM3 to read and display the MCD & MSN0..2 the values will be shown below confirm when ready [y/n] ?y - #db# setting up legic card - #db# MIM 256 card found, reading card ... - #db# Card read, use 'hf legic decode' or - #db# 'data hexsamples 8' to view results + 0b ad c0 de <- !! here you'll see the MCD & MSN of your empty tag, which has to be typed in manually as seen below !! type in MCD as 2-digit value - e.g.: 00 (default: 79 ) > 0b @@ -93,18 +91,18 @@ author = 'Mosci' version = 'v1.0.2' desc = [[ This is a script which creates a clone-dump of a dump from a Legic Prime Tag (MIM256 or MIM1024) -(created with 'hf legic dump f my_dump') +Create a dump by running 'hf legic dump'. ]] example = [[ script run legic_clone -i my_dump.bin -o my_clone.bin -c f8 script run legic_clone -i my_dump.bin -d -s ]] usage = [[ -script run legic_clone -h -i -o -c -d -s -w +script run legic_clone [-h] [-i ] [-o ] [-c ] [-d] [-s] [-w] ]] arguments = [[ required : - -i (file to read data from, must be in binary format (*.bin)) + -i - file to read data from, must be in binary format (*.bin) optional : -h - Help text @@ -112,7 +110,7 @@ optional : -c - requires option -o to be given -d - Display content of found Segments -s - Display summary at the end - -w - write directly to Tag - a file myLegicClone.bin will be generated also + -w - write directly to tag - a file hf-legic-UID-dump.bin will also be generated e.g.: hint: using the CRC '00' will result in a plain dump ( -c 00 ) @@ -139,23 +137,6 @@ local function oops(err) core.clearCommandBuffer() return nil, err end - --- read LEGIC data -local function readlegicdata( offset, length, iv ) - -- Read data - local command = Command:newMIX{ - cmd = cmds.CMD_HF_LEGIC_READER - , arg1 = offset - , arg2 = length - , arg3 = iv - , data = nil - } - local result, err = command:sendMIX() - if not result then return oops(err) end - -- result is a packed data structure, data starts at offset 33 - return result -end - --- -- Usage help local function help() @@ -170,23 +151,38 @@ local function help() print(ansicolors.cyan..'Example usage'..ansicolors.reset) print(example) end +-- read LEGIC data +local function readlegicdata(offset, length, iv) + -- Read data + local command = Command:newMIX{ + cmd = cmds.CMD_HF_LEGIC_READER + , arg1 = offset + , arg2 = length + , arg3 = iv + , data = nil + } + local result, err = command:sendMIX() + if not result then return oops(err) end + -- result is a packed data structure, data starts at offset 33 + return result +end -- Check availability of file local function file_check(file_name) - local file_found = io.open(file_name, "r") - if not file_found then - file_found = false + local exists = io.open(file_name, "r") + if not exists then + exists = false else - file_found = true + exists = true end - return file_found + return exists end --- xor-wrapper -- xor all from addr 0x22 (start counting from 1 => 23) local function xorme(hex, xor, index) if ( index >= 23 ) then - return ('%02x'):format(bxor( tonumber(hex,16) , tonumber(xor,16) )) + return ('%02x'):format(bxor( tonumber(hex, 16) , tonumber(xor, 16) )) else return hex end @@ -197,12 +193,12 @@ local function getInputBytes(infile) local line local bytes = {} - local fhi,err = io.open(infile,"rb") + local fhi,err = io.open(infile, "rb") if err then print("OOps ... faild to read from file ".. infile); return false; end str = fhi:read("*all") for c in (str or ''):gmatch'.' do - bytes[#bytes+1] = ('%02x'):format(c:byte()) + bytes[#bytes + 1] = ('%02x'):format(c:byte()) end fhi:close() @@ -213,11 +209,11 @@ end -- write to file local function writeOutputBytes(bytes, outfile) - local fho,err = io.open(outfile,"wb") + local fho,err = io.open(outfile, "wb") if err then print("OOps ... faild to open output-file ".. outfile); return false; end for i = 1, #bytes do - fho:write(string.char(tonumber(bytes[i],16))) + fho:write(string.char(tonumber(bytes[i], 16))) end fho:close() print("\nwrote ".. #bytes .." bytes to " .. outfile) @@ -232,7 +228,7 @@ local function xorBytes(inBytes, crc) end if (#inBytes == #bytes) then -- replace crc - bytes[5] = string.sub(crc,-2) + bytes[5] = string.sub(crc, -2) return bytes else print("error: byte-count missmatch") @@ -241,63 +237,63 @@ local function xorBytes(inBytes, crc) end -- get raw segment-data -function getSegmentData(bytes, start, index) +local function getSegmentData(bytes, start, index) local raw, len, valid, last, wrp, wrc, rd, crc local segment = {} - segment[0] = bytes[start]..' '..bytes[start+1]..' '..bytes[start+2]..' '..bytes[start+3] + segment[0] = bytes[start]..' '..bytes[start + 1]..' '..bytes[start + 2]..' '..bytes[start + 3] -- flag = high nibble of byte 1 - segment[1] = string.sub(bytes[start+1],0,1) + segment[1] = string.sub(bytes[start + 1], 0, 1) -- valid = bit 6 of byte 1 - segment[2] = tonumber(bit32.extract('0x'..bytes[start+1],6,1),16) + segment[2] = tonumber(bit32.extract('0x'..bytes[start + 1], 6, 1), 16) -- last = bit 7 of byte 1 - segment[3] = tonumber(bit32.extract('0x'..bytes[start+1],7,1),16) + segment[3] = tonumber(bit32.extract('0x'..bytes[start + 1], 7, 1), 16) -- len = (byte 0)+(bit0-3 of byte 1) - segment[4] = tonumber(('%03x'):format(tonumber(bit32.extract('0x'..bytes[start+1],0,3),16)..tonumber(bytes[start],16)),16) + segment[4] = tonumber(('%03x'):format(tonumber(bit32.extract('0x'..bytes[start + 1], 0, 3), 16)..tonumber(bytes[start], 16)), 16) -- wrp (write proteted) = byte 2 - segment[5] = tonumber(bytes[start+2]) + segment[5] = tonumber(bytes[start + 2]) -- wrc (write control) - bit 4-6 of byte 3 - segment[6] = tonumber(bit32.extract('0x'..bytes[start+3],4,3),16) + segment[6] = tonumber(bit32.extract('0x'..bytes[start + 3], 4, 3), 16) -- rd (read disabled) - bit 7 of byte 3 - segment[7] = tonumber(bit32.extract('0x'..bytes[start+3],7,1),16) + segment[7] = tonumber(bit32.extract('0x'..bytes[start + 3], 7, 1), 16) -- crc byte 4 - segment[8] = bytes[start+4] + segment[8] = bytes[start + 4] -- segment index segment[9] = index -- # crc-byte - segment[10] = start+4 + segment[10] = start + 4 return segment end --- Kaba Group Header -- checks if a segment does have a kghCRC -- returns boolean false if no kgh has being detected or the kghCRC if a kgh was detected -function CheckKgh(bytes, segStart, segEnd) - if (bytes[8]=='9f' and bytes[9]=='ff' and bytes[13]=='11') then +local function CheckKgh(bytes, segStart, segEnd) + if (bytes[8] == '9f' and bytes[9] == 'ff' and bytes[13] == '11') then local i local data = {} segStart = tonumber(segStart, 10) segEnd = tonumber(segEnd, 10) - local dataLen = segEnd-segStart-5 + local dataLen = segEnd - segStart - 5 --- gather creadentials for verify - local WRP = bytes[(segStart+2)] - local WRC = ("%02x"):format(tonumber(bit32.extract("0x"..bytes[segStart+3],4,3),16)) - local RD = ("%02x"):format(tonumber(bit32.extract("0x"..bytes[segStart+3],7,1),16)) + local WRP = bytes[(segStart + 2)] + local WRC = ("%02x"):format(tonumber(bit32.extract("0x"..bytes[segStart+3], 4, 3), 16)) + local RD = ("%02x"):format(tonumber(bit32.extract("0x"..bytes[segStart+3], 7, 1), 16)) local XX = "00" cmd = bytes[1]..bytes[2]..bytes[3]..bytes[4]..WRP..WRC..RD..XX - for i = (segStart+5), (segStart+5+dataLen-2) do + for i = (segStart + 5), (segStart + 5 + dataLen - 2) do cmd = cmd..bytes[i] end local KGH = ("%02x"):format(utils.Crc8Legic(cmd)) - if (KGH == bytes[segEnd-1]) then + if (KGH == bytes[segEnd - 1]) then return KGH else return false @@ -308,12 +304,12 @@ function CheckKgh(bytes, segStart, segEnd) end -- get only the addresses of segemnt-crc's and the length of bytes -function getSegmentCrcBytes(bytes) +local function getSegmentCrcBytes(bytes) local start = 23 local index = 0 local crcbytes = {} repeat - seg = getSegmentData(bytes,start,index) + seg = getSegmentData(bytes, start, index) crcbytes[index] = seg[10] start = start + seg[4] index = index + 1 @@ -323,7 +319,7 @@ function getSegmentCrcBytes(bytes) end -- print segment-data (hf legic info like) -function displaySegments(bytes) +local function displaySegments(bytes) --display segment header(s) start = 23 index = '00' @@ -334,24 +330,24 @@ function displaySegments(bytes) wrp = '' pld = '' Seg = getSegmentData(bytes, start, index) - KGH = CheckKgh(bytes, start, (start+tonumber(Seg[4],10))) + KGH = CheckKgh(bytes, start, (start + tonumber(Seg[4], 10))) printSegment(Seg) -- wrc if (Seg[6] > 0) then print("WRC protected area:") -- length of wrc = wrc - for i=1, Seg[6] do + for i = 1, Seg[6] do -- starts at (segment-start + segment-header + segment-crc)-1 - wrc = wrc..bytes[(start+4+1+i)-1]..' ' + wrc = wrc..bytes[(start + 4 + 1 + i) - 1]..' ' end print(wrc) elseif (Seg[5] > 0) then print("Remaining write protected area:") -- length of wrp = (wrp-wrc) - for i=1, (Seg[5]-Seg[6]) do + for i = 1, (Seg[5] - Seg[6]) do -- starts at (segment-start + segment-header + segment-crc + wrc)-1 - wrp = wrp..bytes[(start+4+1+Seg[6]+i)-1]..' ' + wrp = wrp..bytes[(start + 4 + 1 + Seg[6] + i) - 1]..' ' end print(wrp) end @@ -359,22 +355,22 @@ function displaySegments(bytes) -- payload print("Remaining segment payload:") --length of payload = segment-len - segment-header - segment-crc - wrp -wrc - for i=1, (Seg[4]-4-1-Seg[5]-Seg[6]) do + for i = 1, (Seg[4] - 4 - 1 - Seg[5] - Seg[6]) do -- starts at (segment-start + segment-header + segment-crc + segment-wrp + segemnt-wrc)-1 - pld = pld..bytes[(start+4+1+Seg[5]+Seg[6]+i)-1]..' ' + pld = pld..bytes[(start + 4 + 1 + Seg[5] + Seg[6] + i) - 1]..' ' end print(pld) if (KGH) then - print("'Kaba Group Header' detected") + print(ansicolors.yellow.."'Kaba Group Header' detected"..ansicolors.reset) end - start = start+Seg[4] - index = prepend_zero(tonumber(Seg[9])+1) + start = start + Seg[4] + index = prepend_zero(tonumber(Seg[9]) + 1) until (Seg[3] == 1 or tonumber(Seg[9]) == 126 ) end -- print Segment values -function printSegment(SegmentData) +local function printSegment(SegmentData) res = "\nSegment "..SegmentData[9]..": " res = res.. "raw header="..SegmentData[0]..", " res = res.. "flag="..SegmentData[1].." (valid="..SegmentData[2].." last="..SegmentData[3].."), " @@ -387,18 +383,19 @@ function printSegment(SegmentData) end -- write clone-data to tag -function writeToTag(plainBytes) +local function writeToTag(plainBytes) local SegCrcs = {} local output local readbytes - if(utils.confirm("\nplace your empty tag onto the PM3 to restore the data of the input file\nthe CRCs will be calculated as needed\n confirm when ready") == false) then - return - end + if (utils.confirm("\nplace your empty tag onto the PM3 to restore the data of the input file\nthe CRCs will be calculated as needed\n confirm when ready") == false) then + return + end readbytes = readlegicdata(0, 4, 0x55) -- gather MCD & MSN from new Tag - this must be enterd manually print("\nthese are the MCD MSN0 MSN1 MSN2 from the Tag that has being read:") + -- readbytes is a usbcommandOLD package, hence 32 bytes offset until data. plainBytes[1] = ('%02x'):format(readbytes:byte(33)) plainBytes[2] = ('%02x'):format(readbytes:byte(34)) plainBytes[3] = ('%02x'):format(readbytes:byte(35)) @@ -411,19 +408,19 @@ function writeToTag(plainBytes) -- calculate crc8 over MCD & MSN cmd = MCD..MSN0..MSN1..MSN2 MCC = ("%02x"):format(utils.Crc8Legic(cmd)) - print("MCD:"..MCD..", MSN:"..MSN0.." "..MSN1.." "..MSN2..", MCC:"..MCC) + print("MCD:"..ansicolors.green..MCD..ansicolors.reset..", MSN:"..ansicolors.green..MSN0.." "..MSN1.." "..MSN2..ansicolors.reset..", MCC:"..MCC) -- calculate new Segment-CRC for each valid segment SegCrcs = getSegmentCrcBytes(plainBytes) - for i=0, (#SegCrcs-1) do - -- SegCrcs[i]-4 = address of first byte of segmentHeader (low byte segment-length) - segLen = tonumber(("%1x"):format(tonumber(bit32.extract("0x"..plainBytes[(SegCrcs[i]-3)],0,3),16))..("%02x"):format(tonumber(plainBytes[SegCrcs[i]-4],16)),16) - segStart = (SegCrcs[i]-4) - segEnd = (SegCrcs[i]-4+segLen) - KGH = CheckKgh(plainBytes,segStart,segEnd) - if (KGH) then - print("'Kaba Group Header' detected - re-calculate...") - end + for i = 0, (#SegCrcs - 1) do + -- SegCrcs[i]-4 = address of first byte of segmentHeader (low byte segment-length) + segLen = tonumber(("%1x"):format(tonumber(bit32.extract("0x"..plainBytes[(SegCrcs[i] - 3)], 0, 3), 16))..("%02x"):format(tonumber(plainBytes[SegCrcs[i] - 4], 16)), 16) + segStart = (SegCrcs[i] - 4) + segEnd = (SegCrcs[i] - 4 + segLen) + KGH = CheckKgh(plainBytes, segStart, segEnd) + if (KGH) then + print("'Kaba Group Header' detected - re-calculate...") + end cmd = MCD..MSN0..MSN1..MSN2..plainBytes[SegCrcs[i]-4]..plainBytes[SegCrcs[i]-3]..plainBytes[SegCrcs[i]-2]..plainBytes[SegCrcs[i]-1] plainBytes[SegCrcs[i]] = ("%02x"):format(utils.Crc8Legic(cmd)) end @@ -439,15 +436,15 @@ function writeToTag(plainBytes) bytes = xorBytes(plainBytes, MCC) -- write data to file - if (writeOutputBytes(bytes, "myLegicClone.bin")) then + if (writeOutputBytes(bytes, "hf-legic-UID-dump.bin")) then -- write pm3-buffer to Tag - cmd = ('hf legic restore f myLegicClone') + cmd = ('hf legic restore f hf-legic-UID-dump') core.console(cmd) end end -- main function -function main(args) +local function main(args) -- some variables local i = 0 local oldcrc, newcrc, infile, outfile @@ -462,21 +459,20 @@ function main(args) ofs = true if (file_check(a)) then local answer = utils.confirm('\nthe output-file '..a..' already exists!\nthis will delete the previous content!\ncontinue?') - if (answer==false) then return oops('quiting') end + if (answer == false) then return oops('quiting') end end end -- input file if o == 'i' then infile = a - if (file_check(infile)==false) then - return oops('input file: '..infile..' not found') - else - bytes = getInputBytes(infile) - oldcrc = bytes[5] - ifs = true - if (bytes == false) then return oops('couldnt get input bytes') end - end - i = i+1 + if (file_check(infile) == false) then return oops('input file: '..infile..' not found') end + + bytes = getInputBytes(infile) + oldcrc = bytes[5] + ifs = true + if (bytes == false) then return oops('couldnt get input bytes') end + + i = i + 1 end -- new crc if o == 'c' then @@ -514,13 +510,15 @@ function main(args) -- information res = "\n+-------------------------------------------- Summary -------------------------------------------+" res = res .."\ncreated clone_dump from\n\t"..infile.." crc: "..oldcrc.."\ndump_file:" - res = res .."\n\t"..outfile.." crc: "..string.sub(newcrc,-2) - res = res .."\nyou may load the new file with: hf legic eload "..outfile + res = res .."\n\t"..outfile.." crc: "..string.sub(newcrc, -2) + res = res .."\nyou may load the new file with:" + res = res ..ansicolors.yellow.."hf legic eload f "..outfile..ansicolors.reset res = res .."\n\nif you don't write to tag immediately ('-w' switch) you will need to recalculate each segmentCRC" res = res .."\nafter writing this dump to a tag!" - res = res .."\n\na segmentCRC gets calculated over MCD,MSN0..3,Segment-Header0..3" + res = res .."\n\na segmentCRC gets calculated over MCD,MSN0..3, Segment-Header0..3" res = res .."\ne.g. (based on Segment00 of the data from "..infile.."):" - res = res .."\nhf legic crc d "..bytes[1]..bytes[2]..bytes[3]..bytes[4]..bytes[23]..bytes[24]..bytes[25]..bytes[26].." u "..newcrc.." c 8" + res = res .."\n" + res = res ..ansicolors.yellow.."hf legic crc d "..bytes[1]..bytes[2]..bytes[3]..bytes[4]..bytes[23]..bytes[24]..bytes[25]..bytes[26].." u "..newcrc.." c 8"..ansicolors.reset -- this can not be calculated without knowing the new MCD, MSN0..2 print(res) end @@ -535,7 +533,7 @@ function main(args) end -- write to tag if (ws and ( #bytes == 1024 or #bytes == 256)) then - writeToTag(bytes) + writeToTag(bytes) end end From 214bb46e9c073c7e7479c34372c516fca121d58a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 5 Apr 2020 16:59:14 +0200 Subject: [PATCH 11/31] fix: hf mfu ndef - ul ev1 48 bytes with a NDEF otp. e1101200, max size mismatch. Now it will select smallest --- client/cmdhfmfu.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 1f97c6b36..7c204f861 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -2781,7 +2781,20 @@ static int CmdHF14MfuNDEF(const char *Cmd) { // max datasize; maxsize = ndef_get_maxsize(data + 12); } - + + // iceman: maybe always take MIN of tag identified size vs NDEF reported size? + // fix: UL_EV1 48bytes != NDEF reported size + for (uint8_t i = 0; i < ARRAYLEN(UL_TYPES_ARRAY); i++) { + if (tagtype & UL_TYPES_ARRAY[i]) { + + if (maxsize != (UL_MEMORY_ARRAY[i] * 4) ) { + PrintAndLogEx(INFO, "Tag reported size vs NDEF reported size mismatch. Using smallest value"); + } + maxsize = MIN(maxsize, (UL_MEMORY_ARRAY[i] * 4)); + break; + } + } + // allocate mem uint8_t *records = calloc(maxsize, sizeof(uint8_t)); if (records == NULL) { From 0263273ec3788beeaa818640b9f2b8b613b4ef73 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 5 Apr 2020 17:00:16 +0200 Subject: [PATCH 12/31] fix: wrong paramname --- client/luascripts/emul2dump.lua | 4 ++-- client/luascripts/hf_read.lua | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/luascripts/emul2dump.lua b/client/luascripts/emul2dump.lua index cf6900bff..e0286e625 100644 --- a/client/luascripts/emul2dump.lua +++ b/client/luascripts/emul2dump.lua @@ -7,7 +7,7 @@ copyright = '' author = 'Iceman' version = 'v1.0.2' desc =[[ -This script takes an dumpfile on EML (ASCII) format and converts it to the PM3 dumpbin file to be used with `hf mf restore` +This script takes an dumpfile in EML (ASCII) format and converts it to the PM3 dumpbin file to be used with `hf mf restore` ]] example =[[ 1. script run emul2dump @@ -25,7 +25,7 @@ arguments = [[ ]] --- -- This is only meant to be used when errors occur -local function dbg(err) +local function dbg(args) if not DEBUG then return end if type(args) == 'table' then local i = 1 diff --git a/client/luascripts/hf_read.lua b/client/luascripts/hf_read.lua index e416cdd2e..22234e116 100644 --- a/client/luascripts/hf_read.lua +++ b/client/luascripts/hf_read.lua @@ -19,7 +19,7 @@ arguments = [[ ]] --- -- This is only meant to be used when errors occur -local function dbg(err) +local function dbg(args) if not DEBUG then return end if type(args) == 'table' then local i = 1 From 0029f6fceb22fdae2ee10115a359affed34b1196 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 5 Apr 2020 17:02:41 +0200 Subject: [PATCH 13/31] minor fixes. wrong params, helptext --- client/luascripts/legic_clone.lua | 90 ++++++++++++++++++------------- 1 file changed, 54 insertions(+), 36 deletions(-) diff --git a/client/luascripts/legic_clone.lua b/client/luascripts/legic_clone.lua index 29a43a184..c27da3c08 100644 --- a/client/luascripts/legic_clone.lua +++ b/client/luascripts/legic_clone.lua @@ -4,10 +4,9 @@ local getopt = require('getopt') local ansicolors = require('ansicolors') --[[ - script to create a clone-dump with new crc + script to create a clone-dump with new crc Author: mosci - my Fork: https://github.com/icsom/proxmark3.git - Upstream: https://github.com/Proxmark/proxmark3.git + my Fork: https://github.com/icsom/proxmark3.git 1. read tag-dump, xor byte 22..end with byte 0x05 of the inputfile 2. write to outfile @@ -16,11 +15,13 @@ local ansicolors = require('ansicolors') 5. from 0x22..end xored with newcrc 6. calculate new crc on each segment (needs to know the new MCD & MSN0..2) - simplest usage: - read a valid legic tag with 'hf legic reader' - save the dump with 'hf legic dump f orig' - place your 'empty' tag on the reader and run 'script run legic_clone -i orig.bin -w' - you will see some output like: + simplest usage: + Dump a legic tag with 'hf legic dump' + place your 'empty' tag on the reader and run + 'script run legic_clone -i orig.bin -w' + + you will see some output like: + read 1024 bytes from orig.bin place your empty tag onto the PM3 to read and display the MCD & MSN0..2 @@ -90,8 +91,8 @@ copyright = '' author = 'Mosci' version = 'v1.0.2' desc = [[ -This is a script which creates a clone-dump of a dump from a Legic Prime Tag (MIM256 or MIM1024) -Create a dump by running 'hf legic dump'. +This is a script which creates a clone-dump of a dump from a LEGIC Prime Tag (MIM256 or MIM1024) +Create a dump by running `hf legic dump`. ]] example = [[ script run legic_clone -i my_dump.bin -o my_clone.bin -c f8 @@ -115,15 +116,30 @@ optional : e.g.: hint: using the CRC '00' will result in a plain dump ( -c 00 ) ]] - +local DEBUG = true local bxor = bit32.bxor - +--- +-- This is only meant to be used when errors occur +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 -- we need always 2 digits local function prepend_zero(s) - if (string.len(s) == 1) then + if s == nil then return '..' end + + if (#s == 1) then return '0' .. s else - if (string.len(s) == 0) then + if (#s == 0) then return '00' else return s @@ -190,20 +206,18 @@ end -- read input-file into array local function getInputBytes(infile) - local line local bytes = {} + local f = io.open(infile, "rb") + if f == nil then print("OOps ... failed to read from file ".. infile); return false; end - local fhi,err = io.open(infile, "rb") - if err then print("OOps ... faild to read from file ".. infile); return false; end + local str = f:read("*all") + f:close() - str = fhi:read("*all") for c in (str or ''):gmatch'.' do bytes[#bytes + 1] = ('%02x'):format(c:byte()) end - fhi:close() - - print("\nread ".. #bytes .." bytes from ".. infile) + print("\nread ".. #bytes .." bytes from "..ansicolors.yellow..infile..ansicolors.reset) return bytes end @@ -318,8 +332,22 @@ local function getSegmentCrcBytes(bytes) return crcbytes end +-- print Segment values +local function printSegment(SegmentData) + res = "\nSegment "..SegmentData[9]..": " + res = res.. "raw header="..SegmentData[0]..", " + res = res.. "flag="..SegmentData[1].." (valid="..SegmentData[2].." last="..SegmentData[3].."), " + res = res.. "len="..("%04d"):format(SegmentData[4])..", " + res = res.. "WRP="..prepend_zero(SegmentData[5])..", " + res = res.. "WRC="..prepend_zero(SegmentData[6])..", " + res = res.. "RD="..SegmentData[7]..", " + res = res.. "crc="..SegmentData[8] + print(res) +end + -- print segment-data (hf legic info like) local function displaySegments(bytes) + --display segment header(s) start = 23 index = '00' @@ -330,7 +358,10 @@ local function displaySegments(bytes) wrp = '' pld = '' Seg = getSegmentData(bytes, start, index) + if Seg == nil then return OOps("segment is nil") end + KGH = CheckKgh(bytes, start, (start + tonumber(Seg[4], 10))) + printSegment(Seg) -- wrc @@ -369,19 +400,6 @@ local function displaySegments(bytes) until (Seg[3] == 1 or tonumber(Seg[9]) == 126 ) end --- print Segment values -local function printSegment(SegmentData) - res = "\nSegment "..SegmentData[9]..": " - res = res.. "raw header="..SegmentData[0]..", " - res = res.. "flag="..SegmentData[1].." (valid="..SegmentData[2].." last="..SegmentData[3].."), " - res = res.. "len="..("%04d"):format(SegmentData[4])..", " - res = res.. "WRP="..prepend_zero(SegmentData[5])..", " - res = res.. "WRC="..prepend_zero(SegmentData[6])..", " - res = res.. "RD="..SegmentData[7]..", " - res = res.. "crc="..SegmentData[8] - print(res) -end - -- write clone-data to tag local function writeToTag(plainBytes) local SegCrcs = {} @@ -470,7 +488,7 @@ local function main(args) bytes = getInputBytes(infile) oldcrc = bytes[5] ifs = true - if (bytes == false) then return oops('couldnt get input bytes') end + if (bytes == false) then return oops('couldnt read file') end i = i + 1 end @@ -489,7 +507,7 @@ local function main(args) if o == 'h' then return help() end end - if (not ifs) then return oops('option -i is required but missing') end + if (not ifs) then return oops('option -i is required') end -- bytes to plain bytes = xorBytes(bytes, oldcrc) From aa642d5d1e803b4d4ff7519aa71036d05b692bc8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 5 Apr 2020 18:27:54 +0200 Subject: [PATCH 14/31] ax --- client/luascripts/Legic_clone.lua | 543 ------------------------------ 1 file changed, 543 deletions(-) delete mode 100644 client/luascripts/Legic_clone.lua diff --git a/client/luascripts/Legic_clone.lua b/client/luascripts/Legic_clone.lua deleted file mode 100644 index 00834c98b..000000000 --- a/client/luascripts/Legic_clone.lua +++ /dev/null @@ -1,543 +0,0 @@ -local utils = require('utils') -local cmds = require('commands') -local getopt = require('getopt') -local ansicolors = require('ansicolors') ---[[ - script to create a clone-dump with new crc - Author: mosci - my Fork: https://github.com/icsom/proxmark3.git - Upstream: https://github.com/Proxmark/proxmark3.git - - 1. read tag-dump, xor byte 22..end with byte 0x05 of the inputfile - 2. write to outfile - 3. set byte 0x05 to newcrc - 4. until byte 0x21 plain like in inputfile - 5. from 0x22..end xored with newcrc - 6. calculate new crc on each segment (needs to know the new MCD & MSN0..2) - - simplest usage: - read a valid legic tag with 'hf legic reader' - save the dump with 'hf legic dump o orig' - place your 'empty' tag on the reader and run 'script run Legic_clone -i orig.bin -w' - you will see some output like: - read 1024 bytes from orig.bin - - place your empty tag onto the PM3 to read and display the MCD & MSN0..2 - the values will be shown below - confirm when ready [y/n] ?y - #db# setting up legic card - #db# MIM 256 card found, reading card ... - #db# Card read, use 'hf legic decode' or - #db# 'data hexsamples 8' to view results - 0b ad c0 de <- !! here you'll see the MCD & MSN of your empty tag, which has to be typed in manually as seen below !! - type in MCD as 2-digit value - e.g.: 00 (default: 79 ) - > 0b - type in MSN0 as 2-digit value - e.g.: 01 (default: 28 ) - > ad - type in MSN1 as 2-digit value - e.g.: 02 (default: d1 ) - > c0 - type in MSN2 as 2-digit value - e.g.: 03 (default: 43 ) - > de - MCD:0b, MSN:ad c0 de, MCC:79 <- this crc is calculated from the MCD & MSN and must match the one on yout empty tag - - wrote 1024 bytes to myLegicClone.hex - enter number of bytes to write? (default: 86 ) - - loaded 1024 samples - #db# setting up legic card - #db# MIM 256 card found, writing 0x00 - 0x01 ... - #db# write successful - ... - #db# setting up legic card - #db# MIM 256 card found, writing 0x56 - 0x01 ... - #db# write successful - proxmark3> - - the default value (number of bytes to write) is calculated over all valid segments and should be ok - just hit enter, wait until write has finished - and your clone should be ready (except there has to be a additional KGH-CRC to be calculated - which credentials are unknown until yet) - - the '-w' switch will only work with my fork - it needs the binary legic_crc8 which is not part of the proxmark3-master-branch - also the ability to write DCF is not possible with the proxmark3-master-branch - but creating dumpfile-clone files will be possible (without valid segment-crc - this has to done manually with) - - - (example) Legic-Prime Layout with 'Kaba Group Header' - +----+----+----+----+----+----+----+----+ - 0x00|MCD |MSN0|MSN1|MSN2|MCC | 60 | ea | 9f | - +----+----+----+----+----+----+----+----+ - 0x08| ff | 00 | 00 | 00 | 11 |Bck0|Bck1|Bck2| - +----+----+----+----+----+----+----+----+ - 0x10|Bck3|Bck4|Bck5|BCC | 00 | 00 |Seg0|Seg1| - +----+----+----+----+----+----+----+----+ - 0x18|Seg2|Seg3|SegC|Stp0|Stp1|Stp2|Stp3|UID0| - +----+----+----+----+----+----+----+----+ - 0x20|UID1|UID2|kghC| - +----+----+----+ - - MCD= ManufacturerID (1 Byte) - MSN0..2= ManufactureSerialNumber (3 Byte) - MCC= CRC (1 Byte) calculated over MCD,MSN0..2 - DCF= DecrementalField (2 Byte) 'credential' (enduser-Tag) seems to have always DCF-low=0x60 DCF-high=0xea - Bck0..5= Backup (6 Byte) Bck0 'dirty-flag', Bck1..5 SegmentHeader-Backup - BCC= BackupCRC (1 Byte) CRC calculated over Bck1..5 - Seg0..3= SegmentHeader (on MIM 4 Byte ) - SegC= SegmentCRC (1 Byte) calculated over MCD,MSN0..2,Seg0..3 - Stp0..n= Stamp0... (variable length) length = Segment-Len - UserData - 1 - UID0..n= UserDater (variable length - with KGH hex 0x00-0x63 / dec 0-99) length = Segment-Len - WRP - WRC - 1 - kghC= KabaGroupHeader (1 Byte + addr 0x0c must be 0x11) - as seen on this example: addr 0x05..0x08 & 0x0c must have been set to this values - otherwise kghCRC will not be created by a official reader (not accepted) ---]] - -copyright = '' -author = 'Mosci' -version = 'v1.0.2' -desc = [[ -This is a script which creates a clone-dump of a dump from a Legic Prime Tag (MIM256 or MIM1024) -(created with 'hf legic dump f my_dump') -]] -example = [[ - script run legic_clone -i my_dump.bin -o my_clone.bin -c f8 - script run legic_clone -i my_dump.bin -d -s -]] -usage = [[ -script run legic_clone -h -i -o -c -d -s -w -]] -arguments = [[ -required : - -i (file to read data from, must be in binary format (*.bin)) - -optional : - -h - Help text - -o - requires option -c to be given - -c - requires option -o to be given - -d - Display content of found Segments - -s - Display summary at the end - -w - write directly to Tag - a file myLegicClone.bin will be generated also - - e.g.: - hint: using the CRC '00' will result in a plain dump ( -c 00 ) -]] - -local bxor = bit32.bxor - --- we need always 2 digits -local function prepend_zero(s) - if (string.len(s) == 1) then - return '0' .. s - else - if (string.len(s) == 0) then - return '00' - else - return s - end - 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 - --- read LEGIC data -local function readlegicdata( offset, length, iv ) - -- Read data - local command = Command:newMIX{ - cmd = cmds.CMD_HF_LEGIC_READER - , arg1 = offset - , arg2 = length - , arg3 = iv - , data = nil - } - local result, err = command:sendMIX() - if not result then return oops(err) end - -- result is a packed data structure, data starts at offset 33 - return result -end - ---- --- Usage help -local function help() - print(copyright) - print(author) - print(version) - print(desc) - print(ansicolors.cyan..'Usage'..ansicolors.reset) - print(usage) - print(ansicolors.cyan..'Arguments'..ansicolors.reset) - print(arguments) - print(ansicolors.cyan..'Example usage'..ansicolors.reset) - print(example) -end - --- Check availability of file -local function file_check(file_name) - local file_found = io.open(file_name, "r") - if not file_found then - file_found = false - else - file_found = true - end - return file_found -end - ---- xor-wrapper --- xor all from addr 0x22 (start counting from 1 => 23) -local function xorme(hex, xor, index) - if ( index >= 23 ) then - return ('%02x'):format(bxor( tonumber(hex,16) , tonumber(xor,16) )) - else - return hex - end -end - --- read input-file into array -local function getInputBytes(infile) - local line - local bytes = {} - - local fhi,err = io.open(infile,"rb") - if err then print("OOps ... faild to read from file ".. infile); return false; end - - str = fhi:read("*all") - for c in (str or ''):gmatch'.' do - bytes[#bytes+1] = ('%02x'):format(c:byte()) - end - - fhi:close() - - print("\nread ".. #bytes .." bytes from ".. infile) - return bytes -end - --- write to file -local function writeOutputBytes(bytes, outfile) - local fho,err = io.open(outfile,"wb") - if err then print("OOps ... faild to open output-file ".. outfile); return false; end - - for i = 1, #bytes do - fho:write(string.char(tonumber(bytes[i],16))) - end - fho:close() - print("\nwrote ".. #bytes .." bytes to " .. outfile) - return true -end - --- xore certain bytes -local function xorBytes(inBytes, crc) - local bytes = {} - for index = 1, #inBytes do - bytes[index] = xorme(inBytes[index], crc, index) - end - if (#inBytes == #bytes) then - -- replace crc - bytes[5] = string.sub(crc,-2) - return bytes - else - print("error: byte-count missmatch") - return false - end -end - --- get raw segment-data -function getSegmentData(bytes, start, index) - local raw, len, valid, last, wrp, wrc, rd, crc - local segment = {} - segment[0] = bytes[start]..' '..bytes[start+1]..' '..bytes[start+2]..' '..bytes[start+3] - -- flag = high nibble of byte 1 - segment[1] = string.sub(bytes[start+1],0,1) - - -- valid = bit 6 of byte 1 - segment[2] = tonumber(bit32.extract('0x'..bytes[start+1],6,1),16) - - -- last = bit 7 of byte 1 - segment[3] = tonumber(bit32.extract('0x'..bytes[start+1],7,1),16) - - -- len = (byte 0)+(bit0-3 of byte 1) - segment[4] = tonumber(('%03x'):format(tonumber(bit32.extract('0x'..bytes[start+1],0,3),16)..tonumber(bytes[start],16)),16) - - -- wrp (write proteted) = byte 2 - segment[5] = tonumber(bytes[start+2]) - - -- wrc (write control) - bit 4-6 of byte 3 - segment[6] = tonumber(bit32.extract('0x'..bytes[start+3],4,3),16) - - -- rd (read disabled) - bit 7 of byte 3 - segment[7] = tonumber(bit32.extract('0x'..bytes[start+3],7,1),16) - - -- crc byte 4 - segment[8] = bytes[start+4] - - -- segment index - segment[9] = index - - -- # crc-byte - segment[10] = start+4 - return segment -end - ---- Kaba Group Header --- checks if a segment does have a kghCRC --- returns boolean false if no kgh has being detected or the kghCRC if a kgh was detected -function CheckKgh(bytes, segStart, segEnd) - if (bytes[8]=='9f' and bytes[9]=='ff' and bytes[13]=='11') then - local i - local data = {} - segStart = tonumber(segStart, 10) - segEnd = tonumber(segEnd, 10) - local dataLen = segEnd-segStart-5 - --- gather creadentials for verify - local WRP = bytes[(segStart+2)] - local WRC = ("%02x"):format(tonumber(bit32.extract("0x"..bytes[segStart+3],4,3),16)) - local RD = ("%02x"):format(tonumber(bit32.extract("0x"..bytes[segStart+3],7,1),16)) - local XX = "00" - cmd = bytes[1]..bytes[2]..bytes[3]..bytes[4]..WRP..WRC..RD..XX - for i = (segStart+5), (segStart+5+dataLen-2) do - cmd = cmd..bytes[i] - end - local KGH = ("%02x"):format(utils.Crc8Legic(cmd)) - if (KGH == bytes[segEnd-1]) then - return KGH - else - return false - end - else - return false - end -end - --- get only the addresses of segemnt-crc's and the length of bytes -function getSegmentCrcBytes(bytes) - local start = 23 - local index = 0 - local crcbytes = {} - repeat - seg = getSegmentData(bytes,start,index) - crcbytes[index] = seg[10] - start = start + seg[4] - index = index + 1 - until (seg[3] == 1 or tonumber(seg[9]) == 126 ) - crcbytes[index] = start - return crcbytes -end - --- print segment-data (hf legic info like) -function displaySegments(bytes) - --display segment header(s) - start = 23 - index = '00' - - --repeat until last-flag ist set to 1 or segment-index has reached 126 - repeat - wrc = '' - wrp = '' - pld = '' - Seg = getSegmentData(bytes, start, index) - KGH = CheckKgh(bytes, start, (start+tonumber(Seg[4],10))) - printSegment(Seg) - - -- wrc - if (Seg[6] > 0) then - print("WRC protected area:") - -- length of wrc = wrc - for i=1, Seg[6] do - -- starts at (segment-start + segment-header + segment-crc)-1 - wrc = wrc..bytes[(start+4+1+i)-1]..' ' - end - print(wrc) - elseif (Seg[5] > 0) then - print("Remaining write protected area:") - -- length of wrp = (wrp-wrc) - for i=1, (Seg[5]-Seg[6]) do - -- starts at (segment-start + segment-header + segment-crc + wrc)-1 - wrp = wrp..bytes[(start+4+1+Seg[6]+i)-1]..' ' - end - print(wrp) - end - - -- payload - print("Remaining segment payload:") - --length of payload = segment-len - segment-header - segment-crc - wrp -wrc - for i=1, (Seg[4]-4-1-Seg[5]-Seg[6]) do - -- starts at (segment-start + segment-header + segment-crc + segment-wrp + segemnt-wrc)-1 - pld = pld..bytes[(start+4+1+Seg[5]+Seg[6]+i)-1]..' ' - end - print(pld) - if (KGH) then - print("'Kaba Group Header' detected") - end - start = start+Seg[4] - index = prepend_zero(tonumber(Seg[9])+1) - - until (Seg[3] == 1 or tonumber(Seg[9]) == 126 ) -end - --- print Segment values -function printSegment(SegmentData) - res = "\nSegment "..SegmentData[9]..": " - res = res.. "raw header="..SegmentData[0]..", " - res = res.. "flag="..SegmentData[1].." (valid="..SegmentData[2].." last="..SegmentData[3].."), " - res = res.. "len="..("%04d"):format(SegmentData[4])..", " - res = res.. "WRP="..prepend_zero(SegmentData[5])..", " - res = res.. "WRC="..prepend_zero(SegmentData[6])..", " - res = res.. "RD="..SegmentData[7]..", " - res = res.. "crc="..SegmentData[8] - print(res) -end - --- write clone-data to tag -function writeToTag(plainBytes) - local SegCrcs = {} - local output - local readbytes - if(utils.confirm("\nplace your empty tag onto the PM3 to restore the data of the input file\nthe CRCs will be calculated as needed\n confirm when ready") == false) then - return - end - - readbytes = readlegicdata(0, 4, 0x55) - -- gather MCD & MSN from new Tag - this must be enterd manually - print("\nthese are the MCD MSN0 MSN1 MSN2 from the Tag that has being read:") - - plainBytes[1] = ('%02x'):format(readbytes:byte(33)) - plainBytes[2] = ('%02x'):format(readbytes:byte(34)) - plainBytes[3] = ('%02x'):format(readbytes:byte(35)) - plainBytes[4] = ('%02x'):format(readbytes:byte(36)) - - MCD = plainBytes[1] - MSN0 = plainBytes[2] - MSN1 = plainBytes[3] - MSN2 = plainBytes[4] - -- calculate crc8 over MCD & MSN - cmd = MCD..MSN0..MSN1..MSN2 - MCC = ("%02x"):format(utils.Crc8Legic(cmd)) - print("MCD:"..MCD..", MSN:"..MSN0.." "..MSN1.." "..MSN2..", MCC:"..MCC) - - -- calculate new Segment-CRC for each valid segment - SegCrcs = getSegmentCrcBytes(plainBytes) - for i=0, (#SegCrcs-1) do - -- SegCrcs[i]-4 = address of first byte of segmentHeader (low byte segment-length) - segLen = tonumber(("%1x"):format(tonumber(bit32.extract("0x"..plainBytes[(SegCrcs[i]-3)],0,3),16))..("%02x"):format(tonumber(plainBytes[SegCrcs[i]-4],16)),16) - segStart = (SegCrcs[i]-4) - segEnd = (SegCrcs[i]-4+segLen) - KGH = CheckKgh(plainBytes,segStart,segEnd) - if (KGH) then - print("'Kaba Group Header' detected - re-calculate...") - end - cmd = MCD..MSN0..MSN1..MSN2..plainBytes[SegCrcs[i]-4]..plainBytes[SegCrcs[i]-3]..plainBytes[SegCrcs[i]-2]..plainBytes[SegCrcs[i]-1] - plainBytes[SegCrcs[i]] = ("%02x"):format(utils.Crc8Legic(cmd)) - end - - -- apply MCD & MSN to plain data - plainBytes[1] = MCD - plainBytes[2] = MSN0 - plainBytes[3] = MSN1 - plainBytes[4] = MSN2 - plainBytes[5] = MCC - - -- prepare plainBytes for writing (xor plain data with new MCC) - bytes = xorBytes(plainBytes, MCC) - - -- write data to file - if (writeOutputBytes(bytes, "myLegicClone.bin")) then - -- write pm3-buffer to Tag - cmd = ('hf legic restore f myLegicClone') - core.console(cmd) - end -end - --- main function -function main(args) - -- some variables - local i = 0 - local oldcrc, newcrc, infile, outfile - local bytes = {} - local segments = {} - - -- parse arguments for the script - for o, a in getopt.getopt(args, 'hwsdc:i:o:') do - -- output file - if o == 'o' then - outfile = a - ofs = true - if (file_check(a)) then - local answer = utils.confirm('\nthe output-file '..a..' already exists!\nthis will delete the previous content!\ncontinue?') - if (answer==false) then return oops('quiting') end - end - end - -- input file - if o == 'i' then - infile = a - if (file_check(infile)==false) then - return oops('input file: '..infile..' not found') - else - bytes = getInputBytes(infile) - oldcrc = bytes[5] - ifs = true - if (bytes == false) then return oops('couldnt get input bytes') end - end - i = i+1 - end - -- new crc - if o == 'c' then - newcrc = a:lower() - ncs = true - end - -- display segments switch - if o == 'd' then ds = true; end - -- display summary switch - if o == 's' then ss = true; end - -- write to tag switch - if o == 'w' then ws = true; end - -- help - if o == 'h' then return help() end - end - - if (not ifs) then return oops('option -i is required but missing') end - - -- bytes to plain - bytes = xorBytes(bytes, oldcrc) - - -- show segments (works only on plain bytes) - if (ds) then - print("+------------------------------------------- Segments -------------------------------------------+") - displaySegments(bytes); - end - - if (ofs and ncs) then - -- xor bytes with new crc - newBytes = xorBytes(bytes, newcrc) - -- write output - if (writeOutputBytes(newBytes, outfile)) then - -- show summary if requested - if (ss) then - -- information - res = "\n+-------------------------------------------- Summary -------------------------------------------+" - res = res .."\ncreated clone_dump from\n\t"..infile.." crc: "..oldcrc.."\ndump_file:" - res = res .."\n\t"..outfile.." crc: "..string.sub(newcrc,-2) - res = res .."\nyou may load the new file with: hf legic eload "..outfile - res = res .."\n\nif you don't write to tag immediately ('-w' switch) you will need to recalculate each segmentCRC" - res = res .."\nafter writing this dump to a tag!" - res = res .."\n\na segmentCRC gets calculated over MCD,MSN0..3,Segment-Header0..3" - res = res .."\ne.g. (based on Segment00 of the data from "..infile.."):" - res = res .."\nhf legic crc d "..bytes[1]..bytes[2]..bytes[3]..bytes[4]..bytes[23]..bytes[24]..bytes[25]..bytes[26].." u "..newcrc.." c 8" - -- this can not be calculated without knowing the new MCD, MSN0..2 - print(res) - end - end - else - if (ss) then - -- show why the output-file was not written - print("\nnew file not written - some arguments are missing ..") - print("output file: ".. (ofs and outfile or "not given")) - print("new crc: ".. (ncs and newcrc or "not given")) - end - end - -- write to tag - if (ws and ( #bytes == 1024 or #bytes == 256)) then - writeToTag(bytes) - end -end - --- call main with arguments -main(args) From 25bcd6b89cbbd091d6a81a79d57c5cfc008d48d6 Mon Sep 17 00:00:00 2001 From: Bjoern Kerler Date: Sun, 5 Apr 2020 21:33:41 +0200 Subject: [PATCH 15/31] Improve 14444-3a card detection --- client/cmdhf14a.c | 353 +++++++++++++++++++++++++++++++--------------- 1 file changed, 243 insertions(+), 110 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index a3ee49503..74260e9f6 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -1245,6 +1245,122 @@ int CmdHF14A(const char *Cmd) { return CmdsParse(CommandTable, Cmd); } +static void printTag(char *tag) { + PrintAndLogEx(SUCCESS, _YELLOW_(" %s"), tag); +} + + +typedef enum { + mtNone = 0, + mtClassic = 1, + mtMini = 2, + mtDESFire = 4, + mtPlus = 8, + mtUltralight = 16, + mtOther = 32 +} nxp_mifare_type; + +// According to NXP AN10833 Rev 3.6 MIFARE Type Identification, Table 6 +int detect_nxp_card(uint8_t sak, uint16_t atqa) { + int type = mtNone; + + if (sak == 0x00) { + printTag("MIFARE Ultralight C / Ultralight CL2"); + type = mtUltralight; + } + + if (sak == 0x01) { + printTag("TNP3xxx (Activision Game Appliance)"); + type = mtOther; + } + if ((sak & 0x04) == 0x04) { + printTag("Any MIFARE CL1"); + type |= mtDESFire; + } + if ((sak & 0x08) == 0x08) { + printTag("MIFARE Classic 1K / Classic 1K CL2"); + printTag("MIFARE Plus 2K / Plus EV1 2K"); + printTag("MIFARE Plus CL2 2K / Plus CL2 EV1 2K"); + type |= mtClassic; + type |= mtPlus; + } + if ((sak & 0x09) == 0x09) { + printTag("MIFARE Mini 0.3K / Mini CL2 0.3K"); + type |= mtMini; + } + if ((sak & 0x10) == 0x10) { + printTag("MIFARE Plus 2K / Plus CL2 2K"); + type |= mtPlus; + } + if ((sak & 0x11) == 0x11) { + printTag("MIFARE Plus 4K / Plus CL2 4K"); + type |= mtPlus; + } + if ((sak & 0x18) == 0x18) { + if (atqa == 0x0042) { + printTag("MIFARE Plus 4K / Plus EV1 4K"); + printTag("MIFARE Plus CL2 4K / Plus CL2 EV1 4K"); + type |= mtPlus; + } else { + printTag("MIFARE Classic 4K / Classic 4K CL2"); + type |= mtClassic; + } + + } + if ((sak & 0x20) == 0x20) { + if (atqa == 0x0344) { + printTag("MIFARE DESFire EV1 2K/4K/8K / DESFire EV1 CL2 2K/4K/8K"); + type |= mtDESFire; + } else { + printTag("MIFARE Plus 2K / Plus EV1 2K"); + printTag("MIFARE Plus 4K / Plus EV1 4K"); + printTag("MIFARE Plus CL2 2K / Plus CL2 EV1 4K"); + printTag("MIFARE Plus CL2 4K / Plus CL2 EV1 4K"); + type |= mtPlus; + } + } + if ((sak & 0x24) == 0x24) { + if (atqa == 0x0344) { + printTag("MIFARE DESFire CL1 / DESFire EV1 CL1"); + type |= mtDESFire; + } + } + if ((sak & 0x28) == 0x28) { + if (atqa == 0x0344) { + printTag("MIFARE DESFire CL1 / DESFire EV1 CL1"); + type |= mtDESFire; + } + } + return type; +} + +typedef struct { + uint8_t uid0; + uint8_t uid1; + char *desc; +} uidname; + +const uidname uidmap[] = { + // UID0, UID1, TEXT + {0x02, 0x03, "ST SRIX4K"}, + {0x05, 0x1E, "my-d(tm) move SLE66r01P"}, + {0x05, 0x20, "my-d(tm) move SLE66r01P"}, + {0x11, 0x22, "NTAG21x Modifiable"}, + {0x00, 0x00, "None"} +}; + +void getTagLabel(uint8_t uid0, uint8_t uid1) { + int i = 0; + while (uidmap[i].uid0 != 0x00) { + if ((uidmap[i].uid0 == uid0) && (uidmap[i].uid1 == uid1)) { + PrintAndLogEx(SUCCESS, _YELLOW_(" %s"), uidmap[i].desc); + return; + } + i += 1; + } + return; +} + int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { clearCommandBuffer(); SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0); @@ -1290,97 +1406,110 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02x [%" PRIu64 "]"), card.sak, resp.oldarg[0]); bool isMifareClassic = true; - bool isMifareDesfire = false; + bool isMifareDESFire = false; bool isMifarePlus = false; bool isMifareUltralight = false; - - switch (card.sak) { - case 0x00: - isMifareClassic = false; - - // ******** is card of the MFU type (UL/ULC/NTAG/ etc etc) - DropField(); - - uint32_t tagT = GetHF14AMfU_Type(); - if (tagT != UL_ERROR) { - ul_print_type(tagT, 0); - isMifareUltralight = true; - } else { - PrintAndLogEx(SUCCESS, "TYPE: Possible AZTEK (iso14443a compliant)"); - } - - // reconnect for further tests - clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0); - WaitForResponse(CMD_ACK, &resp); - - memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t)); - - select_status = resp.oldarg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS - - if (select_status == 0) { - DropField(); - return select_status; - } - break; - case 0x01: - PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP TNP3xxx Activision Game Appliance")); - break; - case 0x04: - PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP MIFARE (various !DESFire !DESFire EV1)")); - isMifareClassic = false; - isMifareDesfire = true; - break; - case 0x08: - PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP MIFARE CLASSIC 1k | Plus 2k SL1 | 1k Ev1")); - break; - case 0x09: - PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP MIFARE Mini 0.3k")); - break; - case 0x0A: - PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("FM11RF005SH (Shanghai Metro)")); - break; - case 0x10: - PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP MIFARE Plus 2k SL2")); - isMifarePlus = true; - break; - case 0x11: - PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP MIFARE Plus 4k SL2")); - isMifarePlus = true; - break; - case 0x18: - PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP MIFARE Classic 4k | Plus 4k SL1 | 4k Ev1")); - break; - case 0x20: - PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP MIFARE DESFire 4k | DESFire EV1 2k/4k/8k | Plus 2k/4k SL3 | JCOP 31/41")); - isMifareClassic = false; - isMifareDesfire = true; - isMifarePlus = true; - break; - case 0x24: - PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP MIFARE DESFire | DESFire EV1")); - isMifareClassic = false; - isMifareDesfire = true; - break; - case 0x28: - PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("JCOP31 or JCOP41 v2.3.1")); - break; - case 0x38: - PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("Nokia 6212 or 6131 MIFARE CLASSIC 4K")); - break; - case 0x88: - PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("Infineon MIFARE CLASSIC 1K")); - break; - case 0x98: - PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("Gemplus MPCOS")); - break; - default: - ; - } - + int nxptype = mtNone; // Double & triple sized UID, can be mapped to a manufacturer. + if (card.uidlen <= 4) { + nxptype = detect_nxp_card(card.sak, ((card.atqa[1] << 8) + card.atqa[0])); + if ((nxptype & mtClassic) == mtClassic) isMifareClassic = true; + else isMifareClassic = false; + if ((nxptype & mtDESFire) == mtDESFire) { + isMifareDESFire = true; + } else { + isMifareDESFire = false; + } + if ((nxptype & mtPlus) == mtPlus) isMifarePlus = true; + else isMifarePlus = false; + if ((nxptype & mtUltralight) == mtUltralight) isMifareUltralight = true; + else isMifareUltralight = false; + if ((nxptype & mtOther) == mtOther) isMifareClassic = true; + } if (card.uidlen > 4) { PrintAndLogEx(SUCCESS, "MANUFACTURER: " _YELLOW_("%s"), getTagInfo(card.uid[0])); + + PrintAndLogEx(SUCCESS, "Possible Type:"); + switch (card.uid[0]) { + case 0x04: // NXP + nxptype = detect_nxp_card(card.sak, ((card.atqa[1] << 8) + card.atqa[0])); + if ((nxptype & mtClassic) == mtClassic) isMifareClassic = true; + else isMifareClassic = false; + if ((nxptype & mtDESFire) == mtDESFire) { + isMifareDESFire = true; + } else { + isMifareDESFire = false; + } + if ((nxptype & mtPlus) == mtPlus) isMifarePlus = true; + else isMifarePlus = false; + if ((nxptype & mtUltralight) == mtUltralight) isMifareUltralight = true; + else isMifareUltralight = false; + if ((nxptype & mtOther) == mtOther) isMifareClassic = true; + break; + case 0x05: // Infineon + if ((card.uid[1] & 0xF0) == 0x30) { + printTag("my-d(tm) move lean SLE 66R01PN"); + } else if ((card.uid[1] & 0xF0) == 0x70) { + printTag("my-d(tm) move lean SLE 66R01L"); + } + + if (card.sak == 0x88) { + printTag("Infineon MIFARE CLASSIC 1K"); + } + getTagLabel(card.uid[0], card.uid[1]); + break; + default: + getTagLabel(card.uid[0], card.uid[1]); + switch (card.sak) { + case 0x00: + isMifareClassic = false; + + // ******** is card of the MFU type (UL/ULC/NTAG/ etc etc) + DropField(); + + uint32_t tagT = GetHF14AMfU_Type(); + if (tagT != UL_ERROR) { + ul_print_type(tagT, 0); + isMifareUltralight = true; + printTag("MIFARE Ultralight/C/NTAG Compatible"); + } else { + printTag("Possible AZTEK (iso14443a compliant)"); + } + + // reconnect for further tests + clearCommandBuffer(); + SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0); + WaitForResponse(CMD_ACK, &resp); + + memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t)); + + select_status = resp.oldarg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS + + if (select_status == 0) { + DropField(); + return select_status; + } + break; + case 0x0A: + printTag("FM11RF005SH (Shanghai Metro)"); + break; + case 0x20: + printTag("JCOP 31/41"); + break; + case 0x28: + printTag("JCOP31 or JCOP41 v2.3.1"); + break; + case 0x38: + printTag("Nokia 6212 or 6131"); + break; + case 0x98: + printTag("Gemplus MPCOS"); + break; + default: + break; + } + break; + } } // try to request ATS even if tag claims not to support it @@ -1455,12 +1584,14 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { ); pos++; } + if (tc1) { PrintAndLogEx(SUCCESS, " - TC1 : NAD is%s supported, CID is%s supported", (card.ats[pos] & 0x01) ? "" : " NOT", (card.ats[pos] & 0x02) ? "" : " NOT"); pos++; } + if (card.ats[0] > pos && card.ats[0] < card.ats_len - 2) { const char *tip = ""; if (card.ats[0] - pos >= 7) { @@ -1477,14 +1608,14 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { switch (card.ats[pos + 2] & 0xf0) { case 0x10: PrintAndLogEx(SUCCESS, " 1x -> MIFARE DESFire"); - isMifareDesfire = true; + isMifareDESFire = true; isMifareClassic = false; isMifarePlus = false; break; case 0x20: PrintAndLogEx(SUCCESS, " 2x -> MIFARE Plus"); isMifarePlus = true; - isMifareDesfire = false; + isMifareDESFire = false; isMifareClassic = false; break; } @@ -1607,37 +1738,39 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { PrintAndLogEx(INFO, "proprietary non iso14443-4 card found, RATS not supported"); } - detect_classic_magic(); - - if (isMifareClassic) { - int res = detect_classic_prng(); - if (res == 1) - PrintAndLogEx(SUCCESS, "Prng detection: " _GREEN_("weak")); - else if (res == 0) - PrintAndLogEx(SUCCESS, "Prng detection: " _YELLOW_("hard")); - else - PrintAndLogEx(FAILED, "prng detection: " _RED_("fail")); - - if (do_nack_test) - detect_classic_nackbug(false); - - res = detect_classic_static_nonce(); - if (res == 1) - PrintAndLogEx(SUCCESS, "Static nonce: " _YELLOW_("yes") ); - if (res == 2 && verbose) - PrintAndLogEx(SUCCESS, "Static nonce: " _RED_("fail")); - } - if (isMifareUltralight) { PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfu info`")); } if (isMifarePlus) { PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfp info`")); } - if (isMifareDesfire) { + if (isMifareDESFire) { PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfdes info`")); } + if (((card.sak & 0x08) == 0x08) || ((card.sak & 0x18) == 0x18)) { + detect_classic_magic(); + + if (isMifareClassic) { + int res = detect_classic_prng(); + if (res == 1) + PrintAndLogEx(SUCCESS, "Prng detection: " _GREEN_("weak")); + else if (res == 0) + PrintAndLogEx(SUCCESS, "Prng detection: " _YELLOW_("hard")); + else + PrintAndLogEx(FAILED, "prng detection: " _RED_("fail")); + + if (do_nack_test) + detect_classic_nackbug(false); + + res = detect_classic_static_nonce(); + if (res == 1) + PrintAndLogEx(SUCCESS, "Static nonce: " _YELLOW_("yes")); + if (res == 2 && verbose) + PrintAndLogEx(SUCCESS, "Static nonce: " _RED_("fail")); + + } + } return select_status; } From ca51fee02e4f7a56727752103362ee0a5dbd53cf Mon Sep 17 00:00:00 2001 From: Bjoern Kerler Date: Mon, 6 Apr 2020 00:00:53 +0200 Subject: [PATCH 16/31] Add ST uid infos --- client/cmdhf14a.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 74260e9f6..f737ff485 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -1342,9 +1342,22 @@ typedef struct { const uidname uidmap[] = { // UID0, UID1, TEXT - {0x02, 0x03, "ST SRIX4K"}, - {0x05, 0x1E, "my-d(tm) move SLE66r01P"}, - {0x05, 0x20, "my-d(tm) move SLE66r01P"}, + {0x02, 0x00, "SR176"}, + {0x02, 0x03, "SRIX4K"}, + {0x02, 0x0C, "SRT512"}, + {0x02, 0x0F, "SRI2K"}, + {0x02, 0x1B, "25TB512-AC"}, + {0x02, 0x3D, "SRIX4K"}, + {0x02, 0x3F, "25TB02K"}, + {0x02, 0x4D, "SRIX512"}, + {0x02, 0x6D, "SRI512"}, + {0x02, 0x7D, "SRI4K"}, + {0x02, 0x84, "M24SR64-Y"}, + {0x02, 0xA3, "25TA02KB-P"}, + {0x02, 0xC4, "25TA64K"}, + {0x02, 0xE3, "25TA02KB"}, + {0x02, 0xE4, "25TA512B"}, + {0x02, 0xF3, "25TA02KB-D"}, {0x11, 0x22, "NTAG21x Modifiable"}, {0x00, 0x00, "None"} }; @@ -1447,8 +1460,12 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { if ((nxptype & mtOther) == mtOther) isMifareClassic = true; break; case 0x05: // Infineon - if ((card.uid[1] & 0xF0) == 0x30) { - printTag("my-d(tm) move lean SLE 66R01PN"); + if ((card.uid[1] & 0xF0) == 0x10) { + printTag("my-d(tm) command set SLE 66R04/16/32P, SLE 66R04/16/32S"); + } else if ((card.uid[1] & 0xF0) == 0x20) { + printTag("my-d(tm) command set SLE 66R01/16/32P (Type 2 Tag)"); + } else if ((card.uid[1] & 0xF0) == 0x30) { + printTag("my-d(tm) move lean SLE 66R01P/66R01PN"); } else if ((card.uid[1] & 0xF0) == 0x70) { printTag("my-d(tm) move lean SLE 66R01L"); } From 4df7c3bf03b061cfdd1b83466c8335af5af677d7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 6 Apr 2020 06:05:02 +0200 Subject: [PATCH 17/31] coverity fixes --- client/cmdhflegic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index 69df2526c..8fc3ed357 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -1013,6 +1013,7 @@ static int CmdLegicDump(const char *Cmd) { saveFile(filename, ".bin", data, readlen); saveFileEML(filename, data, readlen, 8); saveFileJSON(filename, jsfLegic, data, readlen); + free(data); return PM3_SUCCESS; } @@ -1076,7 +1077,7 @@ static int CmdLegicRestore(const char *Cmd) { } if (card.cardsize != numofbytes) { - PrintAndLogEx(WARNING, "Fail, filesize and cardsize is not equal. [%zu != %u]", card.cardsize, numofbytes); + PrintAndLogEx(WARNING, "Fail, filesize and cardsize is not equal. [%u != %zu]", card.cardsize, numofbytes); free(data); return PM3_EFILE; } From e0ff7d03387a663852c41010a9673fd7486e451d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 6 Apr 2020 06:16:32 +0200 Subject: [PATCH 18/31] cryptorf skeleton cmds -WIP- --- client/cmdhfcryptorf.c | 449 +++++++++++++++++++++++++++++++++++++++++ client/cmdhfcryptorf.h | 20 ++ 2 files changed, 469 insertions(+) create mode 100644 client/cmdhfcryptorf.c create mode 100644 client/cmdhfcryptorf.h diff --git a/client/cmdhfcryptorf.c b/client/cmdhfcryptorf.c new file mode 100644 index 000000000..76441596f --- /dev/null +++ b/client/cmdhfcryptorf.c @@ -0,0 +1,449 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2020 iceman +// +// 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. +//----------------------------------------------------------------------------- +// High frequency CryptoRF commands (ISO14443B) +//----------------------------------------------------------------------------- + +#include "cmdhfcryptorf.h" + +#include +#include "fileutils.h" + +#include "cmdparser.h" // command_t +#include "comms.h" // clearCommandBuffer +#include "cmdtrace.h" +#include "crc16.h" +#include "cmdhf14a.h" +#include "protocols.h" // definitions of ISO14B protocol + +#define TIMEOUT 2000 +static int CmdHelp(const char *Cmd); + +static int usage_hf_cryptorf_info(void) { + PrintAndLogEx(NORMAL, "Usage: hf cryptorf info [h] [v]\n" + "Options:\n" + " h this help\n" + " v verbose\n" + "\n" + "Example:\n" + _YELLOW_(" hf cryptorf info") + ); + return PM3_SUCCESS; +} +static int usage_hf_cryptorf_reader(void) { + PrintAndLogEx(NORMAL, "Usage: hf cryptorf reader [h] [v]\n" + "Options:\n" + " h this help\n" + " v verbose\n" + "\n" + "Example:\n" + _YELLOW_(" hf cryptorf reader") + ); + return PM3_SUCCESS; +} +static int usage_hf_cryptorf_sniff(void) { + PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer\n" + "Buffer accessible from command " _YELLOW_("'hf list cryptorf'") "\n" + "Usage: hf cryptorf sniff [h]\n" + "Options:\n" + " h this help\n" + "\n" + "Example:\n" + _YELLOW_(" hf cryptorf sniff") + ); + return PM3_SUCCESS; +} +static int usage_hf_cryptorf_sim(void) { + PrintAndLogEx(NORMAL, "Emulating CryptoRF tag with 4 UID / PUPI\n" + "Usage: hf cryptorf sim [h] [u ]\n" + "Options:\n" + " h this help\n" + " u 4byte UID/PUPI\n" + "\n" + "Example:\n" + _YELLOW_(" hf cryptorf sim") + ); + return PM3_SUCCESS; +} +static int usage_hf_cryptorf_dump(void) { + PrintAndLogEx(NORMAL, "This command dumps the contents of a ISO-14443-B tag and save it to file\n" + "\n" + "Usage: hf cryptorf dump [h] [card memory] \n" + "Options:\n" + " h this help\n" + " f filename, if no UID will be used as filename\n" + "\n" + "Examples:\n" + "\thf cryptorf dump\n" + "\thf cryptorf dump f mydump"); + return PM3_SUCCESS; +} + +static int switch_off_field_cryptorf(void) { + clearCommandBuffer(); + SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_DISCONNECT, 0, 0, NULL, 0); + return PM3_SUCCESS; +} + +static int CmdHFCryptoRFList(const char *Cmd) { + (void)Cmd; // Cmd is not used so far + CmdTraceList("14b"); + return PM3_SUCCESS; +} + +static int CmdHFCryptoRFSim(const char *Cmd) { + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_hf_cryptorf_sim(); + + uint32_t pupi = 0; + if (cmdp == 'u') { + pupi = param_get32ex(Cmd, 1, 0, 16); + } + + clearCommandBuffer(); + SendCommandMIX(CMD_HF_ISO14443B_SIMULATE, pupi, 0, 0, NULL, 0); + return PM3_SUCCESS; +} + +static int CmdHF14BSniff(const char *Cmd) { + + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_hf_cryptorf_sniff(); + + clearCommandBuffer(); + SendCommandNG(CMD_HF_ISO14443B_SNIFF, NULL, 0); + return PM3_SUCCESS; +} + +static bool get_14b_UID(iso14b_card_select_t *card) { + + if (!card) + return false; + + int8_t retry = 3; + PacketResponseNG resp; + + // test for 14b SR + while (retry--) { + + clearCommandBuffer(); + SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0, NULL, 0); + if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + + uint8_t status = resp.oldarg[0]; + if (status == 0) { + memcpy(card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t)); + return true; + } + } + } // retry + + // test 14b standard + retry = 3; + while (retry--) { + + clearCommandBuffer(); + SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0); + if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + + uint8_t status = resp.oldarg[0]; + if (status == 0) { + memcpy(card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t)); + return true; + } + } + } // retry + + if (retry <= 0) + PrintAndLogEx(WARNING, "timeout while waiting for reply."); + + return false; +} + +static int CmdHFCryptoRFInfo(const char *Cmd) { + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_hf_cryptorf_info(); + + bool verbose = (cmdp == 'v'); + + int res = infoHFCryptoRF(verbose); + if (res != PM3_SUCCESS && verbose) { + PrintAndLogEx(FAILED, "no 14443-B tag found"); + } + return res; +} + +static int CmdHFCryptoRFReader(const char *Cmd) { + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_hf_cryptorf_reader(); + + bool verbose = (cmdp == 'v'); + + int res = readHFCryptoRF(verbose); + if (res != PM3_SUCCESS && verbose) { + PrintAndLogEx(FAILED, "no 14443-B tag found"); + } + return res; +} + +// need to write to file +static int CmdHFCryptoRFDump(const char *Cmd) { + + uint8_t fileNameLen = 0; + char filename[FILE_PATH_SIZE] = {0}; + char *fptr = filename; + bool errors = false; + uint8_t cmdp = 0, cardtype = 1; + uint16_t cardsize = 0; + uint8_t blocks = 0; + iso14b_card_select_t card; + + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_hf_cryptorf_dump(); + case 'f': + fileNameLen = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE); + cmdp += 2; + break; + default: + if (cmdp == 0) { + cardtype = param_get8ex(Cmd, cmdp, 1, 10); + cmdp++; + } else { + PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + } + + //Validations + if (errors) return usage_hf_cryptorf_dump(); + + switch (cardtype) { + case 2: + cardsize = (512 / 8) + 4; + blocks = 0x0F; + break; + case 1: + default: + cardsize = (4096 / 8) + 4; + blocks = 0x7F; + break; + } + + if (!get_14b_UID(&card)) { + PrintAndLogEx(WARNING, "No tag found."); + return PM3_SUCCESS; + } + + if (fileNameLen < 1) { + PrintAndLogEx(INFO, "Using UID as filename"); + fptr += sprintf(fptr, "hf-cryptorf-"); + FillFileNameByUID(fptr, card.uid, "-dump", card.uidlen); + } + + // detect blocksize from card :) + PrintAndLogEx(NORMAL, "Reading memory from tag UID %s", sprint_hex(card.uid, card.uidlen)); + + uint8_t data[cardsize]; + memset(data, 0, sizeof(data)); + + int blocknum = 0; + uint8_t *recv = NULL; + + PacketResponseNG resp; + clearCommandBuffer(); + SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR, 0, 0, NULL, 0); + + //select + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + if (resp.oldarg[0]) { + PrintAndLogEx(INFO, "failed to select %" PRId64 " | %" PRId64, resp.oldarg[0], resp.oldarg[1]); + goto out; + } + } + + uint8_t req[2] = {ISO14443B_READ_BLK}; + + for (int retry = 0; retry < 5; retry++) { + + req[1] = blocknum; + + clearCommandBuffer(); + SendCommandOLD(CMD_HF_ISO14443B_COMMAND, ISO14B_APPEND_CRC | ISO14B_RAW, 2, 0, req, sizeof(req)); + + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + + uint8_t status = resp.oldarg[0] & 0xFF; + if (status > 0) { + continue; + } + + uint16_t len = (resp.oldarg[1] & 0xFFFF); + recv = resp.data.asBytes; + + if (!check_crc(CRC_14443_B, recv, len)) { + PrintAndLogEx(FAILED, "crc fail, retrying one more time"); + continue; + } + + memcpy(data + (blocknum * 4), resp.data.asBytes, 4); + + if (blocknum == 0xFF) { + //last read. + break; + } + + + retry = 0; + blocknum++; + if (blocknum > blocks) { + // read config block + blocknum = 0xFF; + } + + printf("."); + fflush(stdout); + } + } + + if (blocknum != 0xFF) { + PrintAndLogEx(NORMAL, "\n Dump failed"); + goto out; + } + + PrintAndLogEx(NORMAL, "\n"); + PrintAndLogEx(NORMAL, "block# | data | ascii"); + PrintAndLogEx(NORMAL, "---------+--------------+----------"); + + for (int i = 0; i <= blocks; i++) { + PrintAndLogEx(NORMAL, + "%3d/0x%02X | %s | %s", + i, + i, + sprint_hex(data + (i * 4), 4), + sprint_ascii(data + (i * 4), 4) + ); + } + + PrintAndLogEx(NORMAL, "\n"); + + + size_t datalen = (blocks + 1) * 4; + saveFileEML(filename, data, datalen, 4); + saveFile(filename, ".bin", data, datalen); +out: + return switch_off_field_cryptorf(); +} + +static command_t CommandTable[] = { + {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"dump", CmdHFCryptoRFDump, IfPm3Iso14443b, "Read all memory pages of an CryptoRF tag, save to file"}, + {"info", CmdHFCryptoRFInfo, IfPm3Iso14443b, "Tag information"}, + {"list", CmdHFCryptoRFList, AlwaysAvailable, "List ISO 14443B history"}, + {"reader", CmdHFCryptoRFReader, IfPm3Iso14443b, "Act as a CryptoRF reader to identify a tag"}, + {"sim", CmdHFCryptoRFSim, IfPm3Iso14443b, "Fake CryptoRF tag"}, + {"sniff", CmdHF14BSniff, IfPm3Iso14443b, "Eavesdrop CryptoRF"}, + {NULL, NULL, NULL, NULL} +}; + +static int CmdHelp(const char *Cmd) { + (void)Cmd; // Cmd is not used so far + CmdsHelp(CommandTable); + return PM3_SUCCESS; +} + +int CmdHFCryptoRF(const char *Cmd) { + clearCommandBuffer(); + return CmdsParse(CommandTable, Cmd); +} + +// Print extented information about tag. +int infoHFCryptoRF(bool verbose) { + + int res = PM3_ESOFT; + + // 14b get and print UID only (general info) + clearCommandBuffer(); + SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0); + PacketResponseNG resp; + + if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); + switch_off_field_cryptorf(); + return false; + } + + iso14b_card_select_t card; + memcpy(&card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t)); + + uint64_t status = resp.oldarg[0]; + + switch (status) { + case 0: + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, " UID : %s", sprint_hex(card.uid, card.uidlen)); + PrintAndLogEx(SUCCESS, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb))); + PrintAndLogEx(SUCCESS, " CHIPID : %02X", card.chipid); + res = PM3_SUCCESS; + break; + case 2: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail"); + break; + case 3: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail"); + break; + default: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select failed"); + break; + } + + return res; +} + +// get and print general info cryptoRF +int readHFCryptoRF(bool verbose) { + + int res = PM3_ESOFT; + + // 14b get and print UID only (general info) + clearCommandBuffer(); + SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0); + PacketResponseNG resp; + + if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); + return PM3_ETIMEOUT; + } + + iso14b_card_select_t card; + memcpy(&card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t)); + + uint64_t status = resp.oldarg[0]; + + switch (status) { + case 0: + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, " UID : %s", sprint_hex(card.uid, card.uidlen)); + PrintAndLogEx(SUCCESS, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb))); + PrintAndLogEx(SUCCESS, " CHIPID : %02X", card.chipid); + res = PM3_SUCCESS; + break; + case 2: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail"); + break; + case 3: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail"); + break; + default: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select failed"); + break; + } + return res; +} diff --git a/client/cmdhfcryptorf.h b/client/cmdhfcryptorf.h new file mode 100644 index 000000000..82508e415 --- /dev/null +++ b/client/cmdhfcryptorf.h @@ -0,0 +1,20 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2020 iceman +// +// 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. +//----------------------------------------------------------------------------- +// High frequency CryptoRF commands (ISO14443B) +//----------------------------------------------------------------------------- + +#ifndef CMDHFCRYPTORF_H__ +#define CMDHFCRYPTORF_H__ + +#include "common.h" + +int CmdHFCryptoRF(const char *Cmd); + +int infoHFCryptoRF(bool verbose); +int readHFCryptoRF(bool verbose); +#endif From 5e9e6a9ad84e568a7c9c1063f81cb76e55306e84 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 6 Apr 2020 06:17:05 +0200 Subject: [PATCH 19/31] prepp hookup for cryptorf cmds --- client/Makefile | 1 + client/cmdhf.c | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/client/Makefile b/client/Makefile index a09a033d9..ed2491202 100644 --- a/client/Makefile +++ b/client/Makefile @@ -205,6 +205,7 @@ CMDSRCS = crapto1/crapto1.c \ cmdhffido.c \ cmdhffelica.c \ cmdhfthinfilm.c \ + cmdhfcryptorf.c \ cmdhflto.c \ cmdhw.c \ cmdlf.c \ diff --git a/client/cmdhf.c b/client/cmdhf.c index dfc2a3d47..773ffe431 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -34,6 +34,7 @@ #include "cmdhffido.h" // FIDO authenticators #include "cmdhfthinfilm.h" // Thinfilm #include "cmdhflto.h" // LTO-CM +#include "cmdhfcryptorf.h" // CryptoRF #include "cmdtrace.h" // trace list #include "ui.h" #include "cmddata.h" @@ -149,11 +150,22 @@ int CmdHFSearch(const char *Cmd) { res = PM3_SUCCESS; } } +/* + // 14b and iclass is the longest test (put last) + PROMPT_CLEARLINE; + PrintAndLogEx(INPLACE, "Searching for CryptoRF tag..."); + if (IfPm3Iso14443b()) { + if (readHFCryptoRF(false) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("CryptoRF tag") "found\n"); + res = PM3_SUCCESS; + } + } +*/ // 14b and iclass is the longest test (put last) PROMPT_CLEARLINE; PrintAndLogEx(INPLACE, "Searching for ISO14443-B tag..."); - if (IfPm3Iso14443a()) { + if (IfPm3Iso14443b()) { if (readHF14B(false) == 1) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO14443-B tag") "found\n"); res = PM3_SUCCESS; @@ -281,6 +293,7 @@ static command_t CommandTable[] = { {"14a", CmdHF14A, AlwaysAvailable, "{ ISO14443A RFIDs... }"}, {"14b", CmdHF14B, AlwaysAvailable, "{ ISO14443B RFIDs... }"}, {"15", CmdHF15, AlwaysAvailable, "{ ISO15693 RFIDs... }"}, +// {"cryptorf", CmdHFCryptoRF, AlwaysAvailable, "{ CryptoRF RFIDs... }"}, {"epa", CmdHFEPA, AlwaysAvailable, "{ German Identification Card... }"}, {"felica", CmdHFFelica, AlwaysAvailable, "{ ISO18092 / Felica RFIDs... }"}, {"fido", CmdHFFido, AlwaysAvailable, "{ FIDO and FIDO2 authenticators... }"}, From 227900efee1be6df946b722a467e840b47c88af2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 6 Apr 2020 06:54:53 +0200 Subject: [PATCH 20/31] eload/esave skeleton for cryptorf --- client/cmdhfcryptorf.c | 173 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 165 insertions(+), 8 deletions(-) diff --git a/client/cmdhfcryptorf.c b/client/cmdhfcryptorf.c index 76441596f..5767b9ed5 100644 --- a/client/cmdhfcryptorf.c +++ b/client/cmdhfcryptorf.c @@ -82,6 +82,31 @@ static int usage_hf_cryptorf_dump(void) { "\thf cryptorf dump f mydump"); return PM3_SUCCESS; } +static int usage_hf_cryptorf_eload(void) { + PrintAndLogEx(NORMAL, "It loads a binary dump into emulator memory\n" + "Usage: hf cryptorf eload [f ]\n" + "Options:\n" + " h this help\n" + " f filename, if no UID will be used as filename\n" + "\n" + "Examples:\n" + _YELLOW_(" hf cryptorf eload f filename") + ); + return PM3_SUCCESS; +} +static int usage_hf_cryptorf_esave(void) { + PrintAndLogEx(NORMAL, "It saves bin/eml/json dump file of emulator memory\n" + " Usage: hf cryptorf esave [f ]\n" + "Options:\n" + " h this help\n" + " f filename, if no UID will be used as filename\n" + "\n" + "Examples:\n" + _YELLOW_(" hf cryptorf esave ") + _YELLOW_(" hf cryptorf esave f filename") + ); + return PM3_SUCCESS; +} static int switch_off_field_cryptorf(void) { clearCommandBuffer(); @@ -109,7 +134,7 @@ static int CmdHFCryptoRFSim(const char *Cmd) { return PM3_SUCCESS; } -static int CmdHF14BSniff(const char *Cmd) { +static int CmdHFCryptoRFSniff(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_hf_cryptorf_sniff(); @@ -342,14 +367,146 @@ out: return switch_off_field_cryptorf(); } +static int CmdHFCryptoRFELoad(const char *Cmd) { + + size_t datalen = 1024; + int fileNameLen = 0; + char filename[FILE_PATH_SIZE] = {0x00}; + bool errors = false; + uint8_t cmdp = 0; + + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h' : + return usage_hf_cryptorf_eload(); + case 'f' : + fileNameLen = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE); + if (!fileNameLen) + errors = true; + if (fileNameLen > FILE_PATH_SIZE - 5) + fileNameLen = FILE_PATH_SIZE - 5; + cmdp += 2; + break; + default : + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + //Validations + if (errors || strlen(Cmd) == 0) return usage_hf_cryptorf_eload(); + + // set up buffer + uint8_t *data = calloc(datalen, sizeof(uint8_t)); + if (!data) { + PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); + return PM3_EMALLOC; + } + + if (loadFile_safe(filename, ".bin", (void **)&data, &datalen) != PM3_SUCCESS) { + free(data); + PrintAndLogEx(WARNING, "Error, reading file"); + return PM3_EFILE; + } + + PrintAndLogEx(SUCCESS, "Uploading to emulator memory"); + +/* + // fast push mode + conn.block_after_ACK = true; + + //Send to device + uint32_t bytes_sent = 0; + uint32_t bytes_remaining = bytes_read; + + while (bytes_remaining > 0) { + uint32_t bytes_in_packet = MIN(PM3_CMD_DATA_SIZE, bytes_remaining); + if (bytes_in_packet == bytes_remaining) { + // Disable fast mode on last packet + conn.block_after_ACK = false; + } + clearCommandBuffer(); + SendCommandOLD(CMD_HF_CRYPTORF_EML_MEMSET, bytes_sent, bytes_in_packet, 0, data + bytes_sent, bytes_in_packet); + bytes_remaining -= bytes_in_packet; + bytes_sent += bytes_in_packet; + } + free(data); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, "Done"); +*/ + return PM3_SUCCESS; +} + +static int CmdHFCryptoRFESave(const char *Cmd) { + + char filename[FILE_PATH_SIZE] = {0}; + char *fptr = filename; + int fileNameLen = 0; + size_t numofbytes = 1024; + bool errors = false; + uint8_t cmdp = 0; + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h' : + return usage_hf_cryptorf_esave(); + case 'f' : + fileNameLen = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE); + if (!fileNameLen) + errors = true; + if (fileNameLen > FILE_PATH_SIZE - 5) + fileNameLen = FILE_PATH_SIZE - 5; + cmdp += 2; + break; + default : + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + //Validations + if (errors || strlen(Cmd) == 0) return usage_hf_cryptorf_esave(); + + // set up buffer + uint8_t *data = calloc(numofbytes, sizeof(uint8_t)); + if (!data) { + PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); + return PM3_EMALLOC; + } + + // download emulator memory + PrintAndLogEx(SUCCESS, "Reading emulator memory..."); + if (!GetFromDevice(BIG_BUF_EML, data, numofbytes, 0, NULL, 0, NULL, 2500, false)) { + PrintAndLogEx(WARNING, "Fail, transfer from device time-out"); + free(data); + return PM3_ETIMEOUT; + } + + // user supplied filename? + if (fileNameLen < 1) { + PrintAndLogEx(INFO, "Using UID as filename"); + fptr += sprintf(fptr, "hf-cryptorf-"); + FillFileNameByUID(fptr, data, "-dump", 4); + } + + saveFile(filename, ".bin", data, numofbytes); + //needs to change + saveFileEML(filename, data, numofbytes, 8); + //needs to change + saveFileJSON(filename, jsfRaw, data, numofbytes); + return PM3_SUCCESS; +} + static command_t CommandTable[] = { - {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"dump", CmdHFCryptoRFDump, IfPm3Iso14443b, "Read all memory pages of an CryptoRF tag, save to file"}, - {"info", CmdHFCryptoRFInfo, IfPm3Iso14443b, "Tag information"}, - {"list", CmdHFCryptoRFList, AlwaysAvailable, "List ISO 14443B history"}, - {"reader", CmdHFCryptoRFReader, IfPm3Iso14443b, "Act as a CryptoRF reader to identify a tag"}, - {"sim", CmdHFCryptoRFSim, IfPm3Iso14443b, "Fake CryptoRF tag"}, - {"sniff", CmdHF14BSniff, IfPm3Iso14443b, "Eavesdrop CryptoRF"}, + {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"dump", CmdHFCryptoRFDump, IfPm3Iso14443b, "Read all memory pages of an CryptoRF tag, save to file"}, + {"info", CmdHFCryptoRFInfo, IfPm3Iso14443b, "Tag information"}, + {"list", CmdHFCryptoRFList, AlwaysAvailable, "List ISO 14443B history"}, + {"reader", CmdHFCryptoRFReader, IfPm3Iso14443b, "Act as a CryptoRF reader to identify a tag"}, + {"sim", CmdHFCryptoRFSim, IfPm3Iso14443b, "Fake CryptoRF tag"}, + {"sniff", CmdHFCryptoRFSniff, IfPm3Iso14443b, "Eavesdrop CryptoRF"}, + {"eload", CmdHFCryptoRFELoad, AlwaysAvailable, "Load binary dump to emulator memory"}, + {"esave", CmdHFCryptoRFESave, AlwaysAvailable, "Save emulator memory to binary file"}, + {NULL, NULL, NULL, NULL} }; From 961eb193d15d5d2a79d3cfe4c1306ff98d067709 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 6 Apr 2020 06:55:12 +0200 Subject: [PATCH 21/31] text --- client/cmdhffelica.c | 62 ++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 84339a05c..dc3b07a1b 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -1847,37 +1847,37 @@ int readFelicaUid(bool verbose) { } static command_t CommandTable[] = { - {"----------- General -----------", CmdHelp, IfPm3Iso14443a, ""}, - {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"list", CmdHFFelicaList, AlwaysAvailable, "List ISO 18092/FeliCa history"}, - {"reader", CmdHFFelicaReader, IfPm3Felica, "Act like an ISO18092/FeliCa reader"}, - {"sniff", CmdHFFelicaSniff, IfPm3Felica, "Sniff ISO 18092/FeliCa traffic"}, - {"raw", CmdHFFelicaCmdRaw, IfPm3Felica, "Send raw hex data to tag"}, - {"rdunencrypted", CmdHFFelicaReadWithoutEncryption, IfPm3Felica, "read Block Data from authentication-not-required Service."}, - {"wrunencrypted", CmdHFFelicaWriteWithoutEncryption, IfPm3Felica, "write Block Data to an authentication-not-required Service."}, - {"----------- FeliCa Standard -----------", CmdHelp, IfPm3Iso14443a, ""}, - //{"dump", CmdHFFelicaDump, IfPm3Felica, "Wait for and try dumping FeliCa"}, - {"rqservice", CmdHFFelicaRequestService, IfPm3Felica, "verify the existence of Area and Service, and to acquire Key Version."}, - {"rqresponse", CmdHFFelicaRequestResponse, IfPm3Felica, "verify the existence of a card and its Mode."}, - {"scsvcode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire Area Code and Service Code."}, - {"rqsyscode", CmdHFFelicaRequestSystemCode, IfPm3Felica, "acquire System Code registered to the card."}, - {"auth1", CmdHFFelicaAuthentication1, IfPm3Felica, "authenticate a card. Start mutual authentication with Auth1"}, - {"auth2", CmdHFFelicaAuthentication2, IfPm3Felica, "allow a card to authenticate a Reader/Writer. Complete mutual authentication"}, - //{"read", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."}, - //{"write", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to an authentication-required Service."}, - //{"scsvcodev2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "verify the existence of Area or Service, and to acquire Key Version."}, - //{"getsysstatus", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire the setup information in System."}, - {"rqspecver", CmdHFFelicaRequestSpecificationVersion, IfPm3Felica, "acquire the version of card OS."}, - {"resetmode", CmdHFFelicaResetMode, IfPm3Felica, "reset Mode to Mode 0."}, - //{"auth1v2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "authenticate a card."}, - //{"auth2v2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "allow a card to authenticate a Reader/Writer."}, - //{"readv2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."}, - //{"writev2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to authentication-required Service."}, - //{"uprandomid", CmdHFFelicaNotImplementedYet, IfPm3Felica, "update Random ID (IDr)."}, - {"----------- FeliCa Light -----------", CmdHelp, IfPm3Iso14443a, ""}, - {"litesim", CmdHFFelicaSimLite, IfPm3Felica, " - only reply to poll request"}, - {"litedump", CmdHFFelicaDumpLite, IfPm3Felica, "Wait for and try dumping FelicaLite"}, - // {"sim", CmdHFFelicaSim, IfPm3Felica, " -- Simulate ISO 18092/FeliCa tag"} + {"----------- General -----------", CmdHelp, AlwaysAvailable, ""}, + {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"list", CmdHFFelicaList, AlwaysAvailable, "List ISO 18092/FeliCa history"}, + {"reader", CmdHFFelicaReader, IfPm3Felica, "Act like an ISO18092/FeliCa reader"}, + {"sniff", CmdHFFelicaSniff, IfPm3Felica, "Sniff ISO 18092/FeliCa traffic"}, + {"raw", CmdHFFelicaCmdRaw, IfPm3Felica, "Send raw hex data to tag"}, + {"rdunencrypted", CmdHFFelicaReadWithoutEncryption, IfPm3Felica, "read Block Data from authentication-not-required Service."}, + {"wrunencrypted", CmdHFFelicaWriteWithoutEncryption, IfPm3Felica, "write Block Data to an authentication-not-required Service."}, + {"----------- FeliCa Standard -----------", CmdHelp, AlwaysAvailable, ""}, + //{"dump", CmdHFFelicaDump, IfPm3Felica, "Wait for and try dumping FeliCa"}, + {"rqservice", CmdHFFelicaRequestService, IfPm3Felica, "verify the existence of Area and Service, and to acquire Key Version."}, + {"rqresponse", CmdHFFelicaRequestResponse, IfPm3Felica, "verify the existence of a card and its Mode."}, + {"scsvcode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire Area Code and Service Code."}, + {"rqsyscode", CmdHFFelicaRequestSystemCode, IfPm3Felica, "acquire System Code registered to the card."}, + {"auth1", CmdHFFelicaAuthentication1, IfPm3Felica, "authenticate a card. Start mutual authentication with Auth1"}, + {"auth2", CmdHFFelicaAuthentication2, IfPm3Felica, "allow a card to authenticate a Reader/Writer. Complete mutual authentication"}, + //{"read", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."}, + //{"write", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to an authentication-required Service."}, + //{"scsvcodev2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "verify the existence of Area or Service, and to acquire Key Version."}, + //{"getsysstatus", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire the setup information in System."}, + {"rqspecver", CmdHFFelicaRequestSpecificationVersion, IfPm3Felica, "acquire the version of card OS."}, + {"resetmode", CmdHFFelicaResetMode, IfPm3Felica, "reset Mode to Mode 0."}, + //{"auth1v2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "authenticate a card."}, + //{"auth2v2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "allow a card to authenticate a Reader/Writer."}, + //{"readv2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."}, + //{"writev2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to authentication-required Service."}, + //{"uprandomid", CmdHFFelicaNotImplementedYet, IfPm3Felica, "update Random ID (IDr)."}, + {"----------- FeliCa Light -----------", CmdHelp, AlwaysAvailable, ""}, + {"litesim", CmdHFFelicaSimLite, IfPm3Felica, " - only reply to poll request"}, + {"litedump", CmdHFFelicaDumpLite, IfPm3Felica, "Wait for and try dumping FelicaLite"}, + // {"sim", CmdHFFelicaSim, IfPm3Felica, " -- Simulate ISO 18092/FeliCa tag"} {NULL, NULL, NULL, NULL} }; From a32f1520db0032f5c659029472486f1079dbc0d9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 6 Apr 2020 06:55:51 +0200 Subject: [PATCH 22/31] chg: hf legic eload/esave - always available --- client/cmdhflegic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index 8fc3ed357..f39d545f0 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -1359,8 +1359,8 @@ static command_t CommandTable[] = { {"sim", CmdLegicSim, IfPm3Legicrf, "Start tag simulator"}, {"wrbl", CmdLegicWrbl, IfPm3Legicrf, "Write data to a LEGIC Prime tag"}, {"crc", CmdLegicCalcCrc, AlwaysAvailable, "Calculate Legic CRC over given bytes"}, - {"eload", CmdLegicELoad, IfPm3Legicrf, "Load binary dump to emulator memory"}, - {"esave", CmdLegicESave, IfPm3Legicrf, "Save emulator memory to binary file"}, + {"eload", CmdLegicELoad, AlwaysAvailable, "Load binary dump to emulator memory"}, + {"esave", CmdLegicESave, AlwaysAvailable, "Save emulator memory to binary file"}, {"wipe", CmdLegicWipe, IfPm3Legicrf, "Wipe a LEGIC Prime tag"}, {NULL, NULL, NULL, NULL} }; From e1c64d3eef42cf6de1ab846bcf13aafb7959c468 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 6 Apr 2020 06:56:23 +0200 Subject: [PATCH 23/31] text --- client/cmdhfmf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 4c49187ca..e43461591 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -3712,7 +3712,7 @@ int CmdHF14AMfELoad(const char *Cmd) { } } - PrintAndLogEx(INFO, "Copying to emulator memory"); + PrintAndLogEx(INFO, "Uploading to emulator memory"); // fast push mode conn.block_after_ACK = true; From 97f06ddcfba646a59eb7b94bca15a087ea45f1cc Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 6 Apr 2020 07:15:34 +0200 Subject: [PATCH 24/31] coverity fixes --- client/cmdhflegic.c | 64 +++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index f39d545f0..1e06aba8a 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -1020,37 +1020,41 @@ static int CmdLegicDump(const char *Cmd) { static int CmdLegicRestore(const char *Cmd) { char filename[FILE_PATH_SIZE] = {0x00}; - size_t fileNlen = 0; - bool errors = false, shall_obsfuscate = false; + bool errors = false, shall_obsfuscate = false, have_filename = false; size_t numofbytes; uint8_t cmdp = 0; - memset(filename, 0, sizeof(filename)); - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': + case 'h': { errors = true; break; - case 'f': - fileNlen = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE); - if (!fileNlen) + } + case 'f': { + int len = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE); + if (!len) errors = true; + else + have_filename = true; - if (fileNlen > FILE_PATH_SIZE - 5) - fileNlen = FILE_PATH_SIZE - 5; cmdp += 2; break; - case 'x': + } + case 'x': { shall_obsfuscate = true; cmdp++; break; - default: + } + default: { PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; break; + } } } + if (have_filename == false) + errors = true; + //Validations if (errors || cmdp == 0) return usage_legic_restore(); @@ -1133,45 +1137,55 @@ static int CmdLegicRestore(const char *Cmd) { static int CmdLegicELoad(const char *Cmd) { size_t numofbytes = 256; - int fileNameLen = 0; char filename[FILE_PATH_SIZE] = {0x00}; - bool errors = false, shall_obsfuscate = false; + bool errors = false, shall_obsfuscate = false, have_filename = false; uint8_t cmdp = 0; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h' : + case 'h' : { return usage_legic_eload(); - case 'f' : - fileNameLen = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE); - if (!fileNameLen) + } + case 'f' : { + int len = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE); + if (!len) errors = true; - if (fileNameLen > FILE_PATH_SIZE - 5) - fileNameLen = FILE_PATH_SIZE - 5; + else + have_filename = true; + cmdp += 2; break; - case 'x': + } + case 'x': { shall_obsfuscate = true; cmdp++; break; - case '0' : + } + case '0' : { numofbytes = 22; cmdp++; break; - case '1' : + } + case '1' : { numofbytes = 256; cmdp++; break; - case '2' : + } + case '2' : { numofbytes = 1024; cmdp++; break; - default : + } + default : { PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; break; + } } } + if (have_filename == false) + errors = true; + //Validations if (errors || strlen(Cmd) == 0) return usage_legic_eload(); From b8bbc1d0a5faa5dd6775e4c44edbcf651b106d96 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 6 Apr 2020 07:29:12 +0200 Subject: [PATCH 25/31] filename checks --- client/cmdhflegic.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index 1e06aba8a..c6de1379d 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -1031,12 +1031,11 @@ static int CmdLegicRestore(const char *Cmd) { break; } case 'f': { - int len = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE); - if (!len) - errors = true; - else - have_filename = true; - + if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) { + PrintAndLogEx(FAILED, "Filename too long"); + break; + } + have_filename = true; cmdp += 2; break; } @@ -1147,12 +1146,11 @@ static int CmdLegicELoad(const char *Cmd) { return usage_legic_eload(); } case 'f' : { - int len = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE); - if (!len) - errors = true; - else - have_filename = true; - + if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) { + PrintAndLogEx(FAILED, "Filename too long"); + break; + } + have_filename = true; cmdp += 2; break; } From 97ef641fad7227926789f96cc27463e732cd16f7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 6 Apr 2020 07:29:39 +0200 Subject: [PATCH 26/31] coverity fix, format specifier --- client/cmdhficlass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 72a7eaad2..c3042d874 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -2050,7 +2050,7 @@ static int CmdHFiClassReadTagFile(const char *Cmd) { if (verbose) { PrintAndLogEx(INFO, "File: " _YELLOW_("%s"), filename); - PrintAndLogEx(INFO, "File size %d bytes, file blocks %d (0x%02x)", bytes_read, bytes_read >> 3, bytes_read >> 3); + PrintAndLogEx(INFO, "File size %zu bytes, file blocks %d (0x%x)", bytes_read, (uint16_t)(bytes_read >> 3), (uint16_t)(bytes_read >> 3)); PrintAndLogEx(INFO, "Printing blocks from"); PrintAndLogEx(INFO, "start " _YELLOW_("0x%02x") "end " _YELLOW_("0x%02x"), (startblock == 0) ? 6 : startblock, endblock); } From fcf7bd24a651cafffd21a0e4b9a1d01a6f49a12e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 6 Apr 2020 08:02:48 +0200 Subject: [PATCH 27/31] fix coverity 278907, 278906 --- client/cmdhfcryptorf.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/client/cmdhfcryptorf.c b/client/cmdhfcryptorf.c index 5767b9ed5..1dd555b80 100644 --- a/client/cmdhfcryptorf.c +++ b/client/cmdhfcryptorf.c @@ -372,7 +372,7 @@ static int CmdHFCryptoRFELoad(const char *Cmd) { size_t datalen = 1024; int fileNameLen = 0; char filename[FILE_PATH_SIZE] = {0x00}; - bool errors = false; + bool errors = false, has_filename = false; uint8_t cmdp = 0; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { @@ -380,11 +380,12 @@ static int CmdHFCryptoRFELoad(const char *Cmd) { case 'h' : return usage_hf_cryptorf_eload(); case 'f' : - fileNameLen = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE); - if (!fileNameLen) + if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) { + PrintAndLogEx(FAILED, "Filename too long"); errors = true; - if (fileNameLen > FILE_PATH_SIZE - 5) - fileNameLen = FILE_PATH_SIZE - 5; + break; + } + has_filename = true; cmdp += 2; break; default : @@ -393,6 +394,9 @@ static int CmdHFCryptoRFELoad(const char *Cmd) { break; } } + if (has_filename == false) + errors = true; + //Validations if (errors || strlen(Cmd) == 0) return usage_hf_cryptorf_eload(); @@ -430,11 +434,11 @@ static int CmdHFCryptoRFELoad(const char *Cmd) { bytes_remaining -= bytes_in_packet; bytes_sent += bytes_in_packet; } +*/ free(data); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(SUCCESS, "Done"); -*/ - return PM3_SUCCESS; + return PM3_SUCCESS; } static int CmdHFCryptoRFESave(const char *Cmd) { From f461a4e5fb197bea71f844f78f8cf02785d65b32 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 6 Apr 2020 08:03:30 +0200 Subject: [PATCH 28/31] fix coverity 278907, 278906 --- client/cmdhfcryptorf.c | 1 - 1 file changed, 1 deletion(-) diff --git a/client/cmdhfcryptorf.c b/client/cmdhfcryptorf.c index 1dd555b80..c6d43ff46 100644 --- a/client/cmdhfcryptorf.c +++ b/client/cmdhfcryptorf.c @@ -370,7 +370,6 @@ out: static int CmdHFCryptoRFELoad(const char *Cmd) { size_t datalen = 1024; - int fileNameLen = 0; char filename[FILE_PATH_SIZE] = {0x00}; bool errors = false, has_filename = false; uint8_t cmdp = 0; From 7b14fd7212b2e5f053b1f00dbc4b35d953c84f40 Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Mon, 6 Apr 2020 16:20:57 +1000 Subject: [PATCH 29/31] Code Clean --- client/emv/emvjson.c | 1 + client/fileutils.c | 9 ++++----- client/proxmark3.c | 7 +++---- client/settings.c | 14 ++++++-------- client/settings.h | 14 ++++++++++---- 5 files changed, 24 insertions(+), 21 deletions(-) diff --git a/client/emv/emvjson.c b/client/emv/emvjson.c index 9b86b38ca..968b51d51 100644 --- a/client/emv/emvjson.c +++ b/client/emv/emvjson.c @@ -97,6 +97,7 @@ int JsonSaveStr(json_t *root, const char *path, const char *value) { int JsonSaveBoolean(json_t *root, const char *path, bool value) { return JsonSaveJsonObject(root, path, json_boolean(value)); } + int JsonSaveBufAsHexCompact(json_t *elm, const char *path, uint8_t *data, size_t datalen) { char *msg = sprint_hex_inrow(data, datalen); if (msg && strlen(msg) && msg[strlen(msg) - 1] == ' ') diff --git a/client/fileutils.c b/client/fileutils.c index 5ce1f3a6a..50d3ca9d6 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -38,6 +38,8 @@ // this define is needed for scandir/alphasort to work #define _GNU_SOURCE #include "fileutils.h" +#include "settings.h" + #include #include @@ -52,9 +54,6 @@ #define PATH_MAX_LENGTH 200 -extern void JsonLoadSettingsCallback (json_t *root); -extern void JsonSaveSettingsCallback (json_t *root); - struct wave_info_t { char signature[4]; uint32_t filesize; @@ -429,7 +428,7 @@ int saveFileJSON(const char *preferredName, JSONFileType ftype, uint8_t *data, s } break; case jsfSettings: - JsonSaveSettingsCallback (root); + settings_save_callback (root); break; default: break; @@ -870,7 +869,7 @@ int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_ *datalen = sptr; } if (!strcmp(ctype,"settings")) { - JsonLoadSettingsCallback (root); + settings_load_callback (root); } PrintAndLogEx(SUCCESS, "loaded from JSON file " _YELLOW_("%s"), fileName); out: diff --git a/client/proxmark3.c b/client/proxmark3.c index 504ae93e5..168b5b960 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -558,7 +558,6 @@ int main(int argc, char *argv[]) { /* initialize history */ using_history(); - #ifdef RL_STATE_READCMD rl_extend_line_buffer(1024); @@ -583,9 +582,9 @@ int main(int argc, char *argv[]) { set_my_executable_path(); set_my_user_directory(); - // Settings - settingsLoad (); - settingsSave (); + // Settings Load and Test + settings_load (); + settings_save (); printf ("Ver : %s\n",mySettings.version); // End Settings diff --git a/client/settings.c b/client/settings.c index a3571c566..976121eed 100644 --- a/client/settings.c +++ b/client/settings.c @@ -43,10 +43,8 @@ #include "comms.h" #include "emv/emvjson.h" -// settings_t mySettings; - // Load all settings into memory (struct) -void settingsLoad (void) +int settings_load (void) { // loadFileJson wants these, so pass in place holder values, though not used // in settings load; @@ -79,17 +77,17 @@ void settingsLoad (void) printf (" window_hsize (int) : [%d]\n",mySettings.window_hsize); printf (" window_wsize (int) : [%d]\n",mySettings.window_wsize); + return PM3_SUCCESS; } // Save all settings from memory (struct) to file -int settingsSave (void) +int settings_save (void) { // Note sure if backup has value ? char backupFilename[500]; - // if (mySettings.loaded) snprintf (backupFilename,sizeof(backupFilename),"%s.bak",settingsFilename); - + if (fileExists (backupFilename)) { if (remove (backupFilename) != 0) { PrintAndLogEx (FAILED, "Error - could not delete old settings backup file \"%s\"",backupFilename); @@ -115,7 +113,7 @@ int settingsSave (void) return PM3_SUCCESS; } -void JsonSaveSettingsCallback (json_t *root) +void settings_save_callback (json_t *root) { // extern settings_t mySettings; @@ -141,7 +139,7 @@ void JsonSaveSettingsCallback (json_t *root) JsonSaveInt (root,"window.wsize",mySettings.window_wsize); } -void JsonLoadSettingsCallback (json_t *root) +void settings_load_callback (json_t *root) { // extern settings_t mySettings; json_error_t up_error = {0}; diff --git a/client/settings.h b/client/settings.h index f0093c207..799af7caa 100644 --- a/client/settings.h +++ b/client/settings.h @@ -8,10 +8,13 @@ //----------------------------------------------------------------------------- // Settings Functions //----------------------------------------------------------------------------- +#ifndef settings_h +#define settings_h #include "fileutils.h" #define settingsFilename "settings.json" + typedef struct { bool loaded; char version[20]; @@ -23,10 +26,13 @@ typedef struct { int window_wsize; } settings_t; +// Settings struct so as to be available to other modules by including settings.h settings_t mySettings; -void settingsLoad (void); -int settingsSave (void); +int settings_load (void); +int settings_save (void); -void JsonSaveCallback ( json_t *root); -void JsonLoadCallback ( json_t *root); +void settings_save_callback (json_t *root); +void settings_load_callback (json_t *root); + +#endif From f0b0d10ee1a67ae6de2e3d937ba3b85eee656f14 Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Mon, 6 Apr 2020 16:36:12 +1000 Subject: [PATCH 30/31] Comment out test calls --- client/fileutils.c | 1 - client/proxmark3.c | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/client/fileutils.c b/client/fileutils.c index 50d3ca9d6..05a7e8949 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -40,7 +40,6 @@ #include "fileutils.h" #include "settings.h" - #include #include diff --git a/client/proxmark3.c b/client/proxmark3.c index 168b5b960..0438f81ad 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -583,9 +583,9 @@ int main(int argc, char *argv[]) { set_my_user_directory(); // Settings Load and Test - settings_load (); - settings_save (); - printf ("Ver : %s\n",mySettings.version); + // settings_load (); + // settings_save (); + // printf ("Ver : %s\n",mySettings.version); // End Settings for (int i = 1; i < argc; i++) { From 173583a5483535cacd5f8ba95c0f514d56724092 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 6 Apr 2020 09:46:22 +0200 Subject: [PATCH 31/31] fix coverity 278900 --- client/cmdhfmfu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 7c204f861..fd3ad5aeb 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -2808,6 +2808,7 @@ static int CmdHF14MfuNDEF(const char *Cmd) { if (status == -1) { DropField(); PrintAndLogEx(ERR, "Error: tag didn't answer to READ"); + free(records); return PM3_ESOFT; } }