Merge pull request #6 from RfidResearchGroup/master

Update
This commit is contained in:
Bjoern Kerler 2020-06-13 20:02:39 +02:00 committed by GitHub
commit 70933c359d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 1333 additions and 767 deletions

View file

@ -3,6 +3,10 @@ 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... 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] ## [unreleased][unreleased]
- Fix `hf mfdes` authentification issues, DES working (@bkerler)
- Add Android cross-compilation to client cmake (@dxl, @doegox)
- Fix `emv scan` - now saves in current folder and uses unique names (@iceman1001)
- Fix pm3.sh - parse COM ports larger than one digit (@doegox)
- Fix stack size and automatically use available space for BigBuf. Stack is now 5K (@slurdge) - Fix stack size and automatically use available space for BigBuf. Stack is now 5K (@slurdge)
- Added Mifare MAD Card Holder Information decoding (@lukaskuzmiak) - Added Mifare MAD Card Holder Information decoding (@lukaskuzmiak)
- Change Better precision for HF and LF voltage measurements and Add theremin.py script (@rosco) - Change Better precision for HF and LF voltage measurements and Add theremin.py script (@rosco)

View file

@ -33,7 +33,7 @@
|[Notes on external flash](/doc/ext_flash_notes.md)|[Notes on loclass](/doc/loclass_notes.md)|[Notes on Coverity Scan Config & Run](/doc/md/Development/Coverity-Scan-Config-%26-Run.md)| |[Notes on external flash](/doc/ext_flash_notes.md)|[Notes on loclass](/doc/loclass_notes.md)|[Notes on Coverity Scan Config & Run](/doc/md/Development/Coverity-Scan-Config-%26-Run.md)|
|[Notes on file formats used with Proxmark3](/doc/extensions_notes.md)|[Notes on MFU binary format](/doc/mfu_binary_format_notes.md)|[Notes on FPGA & ARM](/doc/fpga_arm_notes.md)| |[Notes on file formats used with Proxmark3](/doc/extensions_notes.md)|[Notes on MFU binary format](/doc/mfu_binary_format_notes.md)|[Notes on FPGA & ARM](/doc/fpga_arm_notes.md)|
|[Developing standalone mode](/armsrc/Standalone/readme.md)|[Wiki about standalone mode](https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode)|| |[Developing standalone mode](/armsrc/Standalone/readme.md)|[Wiki about standalone mode](https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode)||
|[Notes on Color usage](/doc/colors_notes.md)||
## Build for non-RDV4 Proxmark3 platforms ## Build for non-RDV4 Proxmark3 platforms

View file

@ -626,9 +626,8 @@ int I2C_get_version(uint8_t *maj, uint8_t *min) {
*maj = resp[0]; *maj = resp[0];
*min = resp[1]; *min = resp[1];
return PM3_SUCCESS; return PM3_SUCCESS;
} else {
return PM3_EDEVNOTSUPP;
} }
return PM3_EDEVNOTSUPP;
} }
// Will read response from smart card module, retries 3 times to get the data. // Will read response from smart card module, retries 3 times to get the data.

View file

@ -4,6 +4,13 @@
# On Proxspace 3.3 or less, you need to install cmake: # On Proxspace 3.3 or less, you need to install cmake:
# pacman -S mingw-w64-x86_64-cmake # pacman -S mingw-w64-x86_64-cmake
# /mingw64/bin/cmake -G"MSYS Makefiles" .. # /mingw64/bin/cmake -G"MSYS Makefiles" ..
#
# Android cross-compilation:
# cmake \
# -DCMAKE_TOOLCHAIN_FILE=<path-to-your-android-ndk>/build/cmake/android.toolchain.cmake \
# -DANDROID_ABI=armeabi-v7a \
# -DANDROID_NATIVE_API_LEVEL=android-19 \
# -DSKIPBT=1 -DSKIPPYTHON=1 -DSKIPPTHREAD=1 ..
cmake_minimum_required(VERSION 3.10) cmake_minimum_required(VERSION 3.10)
project(proxmark3) project(proxmark3)
@ -49,21 +56,75 @@ if (NOT SKIPPYTHON EQUAL 1)
pkg_search_module(PYTHON3EMBED QUIET python3-embed) pkg_search_module(PYTHON3EMBED QUIET python3-embed)
endif (NOT SKIPPYTHON EQUAL 1) endif (NOT SKIPPYTHON EQUAL 1)
# If build on android cross, we need to init source and build.
if (ANDROID)
set(CFLAGS_EXTERNAL_LIB CFLAGS=--target=${CMAKE_C_COMPILER_TARGET})
include(ExternalProject)
endif (ANDROID)
if (NOT SKIPREADLINE EQUAL 1) if (NOT SKIPREADLINE EQUAL 1)
if (APPLE) if (APPLE)
find_path(READLINE_INCLUDE_DIRS readline/readline.h /usr/local/opt/readline/include /opt/local/include /opt/include /usr/local/include /usr/include NO_DEFAULT_PATH) find_path(READLINE_INCLUDE_DIRS readline/readline.h /usr/local/opt/readline/include /opt/local/include /opt/include /usr/local/include /usr/include NO_DEFAULT_PATH)
endif (APPLE)
find_path(READLINE_INCLUDE_DIRS readline/readline.h)
if (APPLE)
find_library(READLINE_LIBRARIES readline /usr/local/opt/readline/lib /opt/local/lib /opt/lib /usr/local/lib /usr/lib NO_DEFAULT_PATH) find_library(READLINE_LIBRARIES readline /usr/local/opt/readline/lib /opt/local/lib /opt/lib /usr/local/lib /usr/lib NO_DEFAULT_PATH)
endif (APPLE) endif (APPLE)
if (ANDROID)
ExternalProject_Add(ncurses
URL http://ftp.gnu.org/pub/gnu/ncurses/ncurses-6.0.tar.gz
PREFIX deps/ncurses
DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/ncurses
CONFIGURE_COMMAND ./configure CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} LD=${CMAKE_C_COMPILER} AR=${CMAKE_AR} RANLIB=${CMAKE_RANLIB} ${CFLAGS_EXTERNAL_LIB} --host=arm
BUILD_IN_SOURCE ON
BUILD_COMMAND make -j2 libs
INSTALL_COMMAND ""
LOG_DOWNLOAD ON
)
ExternalProject_Add_StepTargets(ncurses configure build install)
ExternalProject_Add(readline
URL ftp://ftp.gnu.org/gnu/readline/readline-7.0.tar.gz
PREFIX deps/readline
DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/readline
CONFIGURE_COMMAND ./configure CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} LD=${CMAKE_C_COMPILER} AR=${CMAKE_AR} RANLIB=${CMAKE_RANLIB} ${CFLAGS_EXTERNAL_LIB} --host=arm --enable-static
BUILD_IN_SOURCE ON
BUILD_COMMAND make -j2
INSTALL_COMMAND ""
LOG_DOWNLOAD ON
)
ExternalProject_Add_StepTargets(readline configure build install)
set(READLINE_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}/deps/readline/src/)
set(READLINE_LIBRARIES ${CMAKE_CURRENT_BINARY_DIR}/deps/readline/src/readline/libreadline.a ${CMAKE_CURRENT_BINARY_DIR}/deps/ncurses/src/ncurses/lib/libncurses.a)
else (ANDROID)
find_path(READLINE_INCLUDE_DIRS readline/readline.h)
find_library(READLINE_LIBRARIES readline) find_library(READLINE_LIBRARIES readline)
endif (ANDROID)
if (READLINE_INCLUDE_DIRS AND READLINE_LIBRARIES) if (READLINE_INCLUDE_DIRS AND READLINE_LIBRARIES)
set(READLINE_FOUND ON) set(READLINE_FOUND ON)
endif (READLINE_INCLUDE_DIRS AND READLINE_LIBRARIES) endif (READLINE_INCLUDE_DIRS AND READLINE_LIBRARIES)
endif (NOT SKIPREADLINE EQUAL 1) endif (NOT SKIPREADLINE EQUAL 1)
if(ANDROID)
set(BZIP2_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/deps/bzip2/src/bzip2)
ExternalProject_Add(bzip2
GIT_REPOSITORY https://android.googlesource.com/platform/external/bzip2
GIT_TAG platform-tools-30.0.2
PREFIX deps/bzip2
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/bzip2
CONFIGURE_COMMAND mkdir -p ${BZIP2_BUILD_DIR} && git archive --format tar HEAD | tar -C ${BZIP2_BUILD_DIR} -x
BUILD_IN_SOURCE ON
BUILD_COMMAND make -C ${BZIP2_BUILD_DIR} -j4 CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} LD=${CMAKE_C_COMPILER} AR=${CMAKE_AR} RANLIB=${CMAKE_RANLIB} ${CFLAGS_EXTERNAL_LIB} libbz2.a
INSTALL_COMMAND ""
LOG_DOWNLOAD ON
)
ExternalProject_Add_StepTargets(bzip2 configure build install)
set(BZIP2_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}/deps/bzip2/src/bzip2)
set(BZIP2_LIBRARIES ${CMAKE_CURRENT_BINARY_DIR}/deps/bzip2/src/bzip2/libbz2.a)
else()
set(BZIP2_LIBRARIES bz2)
endif(ANDROID)
if (BZIP2_LIBRARIES)
set(BZIP2_FOUND ON)
endif (BZIP2_LIBRARIES)
add_subdirectory(${PM3_ROOT}/client/deps deps) add_subdirectory(${PM3_ROOT}/client/deps deps)
set (TARGET_SOURCES set (TARGET_SOURCES
@ -268,6 +329,12 @@ if (NOT SKIPREADLINE EQUAL 1)
set(ADDITIONAL_LNK ${READLINE_LIBRARIES} ${ADDITIONAL_LNK}) set(ADDITIONAL_LNK ${READLINE_LIBRARIES} ${ADDITIONAL_LNK})
endif (READLINE_FOUND) endif (READLINE_FOUND)
endif(NOT SKIPREADLINE EQUAL 1) endif(NOT SKIPREADLINE EQUAL 1)
if (BZIP2_FOUND)
set(ADDITIONAL_DIRS ${BZIP2_INCLUDE_DIRS} ${ADDITIONAL_DIRS})
set(ADDITIONAL_LNK ${BZIP2_LIBRARIES} ${ADDITIONAL_LNK})
else (BZIP2_FOUND)
message(FATAL_ERROR "Bzip2 not found")
endif (BZIP2_FOUND)
message("===================================================================") message("===================================================================")
if (SKIPQT EQUAL 1) if (SKIPQT EQUAL 1)
@ -320,6 +387,12 @@ add_executable(proxmark3
) )
target_compile_options(proxmark3 PUBLIC -Wall -Werror -O3) target_compile_options(proxmark3 PUBLIC -Wall -Werror -O3)
if (ANDROID)
if (NOT SKIPREADLINE EQUAL 1)
add_dependencies(proxmark3 ncurses readline)
endif (NOT SKIPREADLINE EQUAL 1)
add_dependencies(proxmark3 bzip2)
endif (ANDROID)
if (MINGW) if (MINGW)
# Mingw uses by default Microsoft printf, we want the GNU printf (e.g. for %z) # Mingw uses by default Microsoft printf, we want the GNU printf (e.g. for %z)
@ -357,7 +430,6 @@ find_library(pm3rrg_rdv4_hardnested REQUIRED)
find_library(pm3rrg_rdv4_whereami REQUIRED) find_library(pm3rrg_rdv4_whereami REQUIRED)
target_link_libraries(proxmark3 PRIVATE target_link_libraries(proxmark3 PRIVATE
bz2
m m
pm3rrg_rdv4_mbedtls pm3rrg_rdv4_mbedtls
pm3rrg_rdv4_cliparser pm3rrg_rdv4_cliparser

View file

@ -605,6 +605,7 @@ d58023ba2bdc # charlie
62ced42a6d87 # charlie 62ced42a6d87 # charlie
2548a443df28 # charlie 2548a443df28 # charlie
2ed3b15e7c0f # charlie 2ed3b15e7c0f # charlie
f66224ee1e89 # charlie
# #
60012e9ba3fa 60012e9ba3fa
# #

View file

@ -12,7 +12,7 @@
#include <stdio.h> // for Mingw readline #include <stdio.h> // for Mingw readline
#include <ctype.h> // tolower #include <ctype.h> // tolower
#ifndef ANDROID #ifdef HAVE_READLINE
#include <readline/readline.h> #include <readline/readline.h>
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -258,7 +258,7 @@ static command_t CommandTable[] = {
{"lf", CmdLF, AlwaysAvailable, "{ Low frequency commands... }"}, {"lf", CmdLF, AlwaysAvailable, "{ Low frequency commands... }"},
{"mem", CmdFlashMem, IfPm3Flash, "{ Flash Memory manipulation... }"}, {"mem", CmdFlashMem, IfPm3Flash, "{ Flash Memory manipulation... }"},
{"reveng", CmdRev, AlwaysAvailable, "{ CRC calculations from RevEng software }"}, {"reveng", CmdRev, AlwaysAvailable, "{ CRC calculations from RevEng software }"},
{"sc", CmdSmartcard, IfPm3Smartcard, "{ Smart card ISO-7816 commands... }"}, {"sc", CmdSmartcard, AlwaysAvailable, "{ Smart card ISO-7816 commands... }"},
{"script", CmdScript, AlwaysAvailable, "{ Scripting commands }"}, {"script", CmdScript, AlwaysAvailable, "{ Scripting commands }"},
{"trace", CmdTrace, AlwaysAvailable, "{ Trace manipulation... }"}, {"trace", CmdTrace, AlwaysAvailable, "{ Trace manipulation... }"},
{"usart", CmdUsart, IfPm3FpcUsartFromUsb, "{ USART commands... }"}, {"usart", CmdUsart, IfPm3FpcUsartFromUsb, "{ USART commands... }"},

View file

@ -19,7 +19,6 @@
#include <wchar.h> #include <wchar.h>
#endif #endif
#include "cmdparser.h" // command_t #include "cmdparser.h" // command_t
#include "scripting.h" #include "scripting.h"
#include "comms.h" #include "comms.h"
@ -33,6 +32,68 @@
#include "ui.h" #include "ui.h"
#include "fileutils.h" #include "fileutils.h"
#ifdef HAVE_PYTHON
// Partly ripped from PyRun_SimpleFileExFlags
// but does not terminate client on sys.exit
// and print exit code only if != 0
static int Pm3PyRun_SimpleFileNoExit(FILE *fp, const char *filename)
{
PyObject *m, *d, *v;
int set_file_name = 0, ret = -1;
m = PyImport_AddModule("__main__");
if (m == NULL)
return -1;
Py_INCREF(m);
d = PyModule_GetDict(m);
if (PyDict_GetItemString(d, "__file__") == NULL) {
PyObject *f;
f = PyUnicode_DecodeFSDefault(filename);
if (f == NULL)
goto done;
if (PyDict_SetItemString(d, "__file__", f) < 0) {
Py_DECREF(f);
goto done;
}
if (PyDict_SetItemString(d, "__cached__", Py_None) < 0) {
Py_DECREF(f);
goto done;
}
set_file_name = 1;
Py_DECREF(f);
}
v = PyRun_FileExFlags(fp, filename, Py_file_input, d, d, 1, NULL);
if (v == NULL) {
Py_CLEAR(m);
if (PyErr_ExceptionMatches(PyExc_SystemExit)) {
// PyErr_Print() exists if SystemExit so we've to handle it ourselves
PyObject *ty = 0, *er = 0, *tr = 0;
PyErr_Fetch(&ty, &er, &tr);
long err = PyLong_AsLong(er);
if (err) {
PrintAndLogEx(WARNING, "\nScript terminated by " _YELLOW_("SystemExit %li"), err);
} else {
ret = 0;
}
Py_DECREF(ty);
Py_DECREF(er);
Py_DECREF(er);
PyErr_Clear();
goto done;
} else {
PyErr_Print();
}
goto done;
}
Py_DECREF(v);
ret = 0;
done:
if (set_file_name && PyDict_DelItemString(d, "__file__"))
PyErr_Clear();
Py_XDECREF(m);
return ret;
}
#endif // HAVE_PYTHON
typedef enum { typedef enum {
PM3_UNSPECIFIED, PM3_UNSPECIFIED,
PM3_LUA, PM3_LUA,
@ -319,14 +380,18 @@ static int CmdScriptRun(const char *Cmd) {
free(script_path); free(script_path);
return PM3_ESOFT; return PM3_ESOFT;
} }
int ret = Pm3PyRun_SimpleFileNoExit(f, preferredName);
PyRun_SimpleFileExFlags(f, preferredName, 1, NULL);
Py_Finalize(); Py_Finalize();
PyMem_RawFree(program); PyMem_RawFree(program);
free(script_path); free(script_path);
if (ret) {
PrintAndLogEx(WARNING, "\nfinished " _YELLOW_("%s") " with exception", preferredName);
return PM3_ESOFT;
} else {
PrintAndLogEx(SUCCESS, "\nfinished " _YELLOW_("%s"), preferredName); PrintAndLogEx(SUCCESS, "\nfinished " _YELLOW_("%s"), preferredName);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
}
#endif #endif
// file not found, let's search again to display the error messages // file not found, let's search again to display the error messages

View file

@ -26,6 +26,7 @@
#include "dol.h" #include "dol.h"
#include "ui.h" #include "ui.h"
#include "emv_tags.h" #include "emv_tags.h"
#include "fileutils.h"
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
@ -1383,8 +1384,6 @@ static int CmdEMVScan(const char *Cmd) {
size_t ODAI_listlen = 0; size_t ODAI_listlen = 0;
uint16_t sw = 0; uint16_t sw = 0;
int res; int res;
json_t *root;
json_error_t error;
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "emv scan", CLIParserInit(&ctx, "emv scan",
@ -1426,15 +1425,19 @@ static int CmdEMVScan(const char *Cmd) {
bool GenACGPO = arg_get_lit(ctx, 9); bool GenACGPO = arg_get_lit(ctx, 9);
bool MergeJSON = arg_get_lit(ctx, 10); bool MergeJSON = arg_get_lit(ctx, 10);
EMVCommandChannel channel = ECC_CONTACTLESS; EMVCommandChannel channel = ECC_CONTACTLESS;
if (arg_get_lit(ctx, 11)) if (arg_get_lit(ctx, 11))
channel = ECC_CONTACT; channel = ECC_CONTACT;
PrintChannel(channel); PrintChannel(channel);
uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2; uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2;
uint8_t relfname[250] = {0};
char *crelfname = (char *)relfname; uint8_t filename[FILE_PATH_SIZE] = {0};
int relfnamelen = 0; int filenamelen = 0;
CLIGetStrWithReturn(ctx, 12, relfname, &relfnamelen); CLIGetStrWithReturn(ctx, 12, filename, &filenamelen);
CLIParserFree(ctx); CLIParserFree(ctx);
if (!IfPm3Smartcard()) { if (!IfPm3Smartcard()) {
@ -1446,16 +1449,13 @@ static int CmdEMVScan(const char *Cmd) {
SetAPDULogging(showAPDU); SetAPDULogging(showAPDU);
json_t *root;
json_error_t error;
// current path + file name // current path + file name
if (!strstr(crelfname, ".json"))
strcat(crelfname, ".json");
char fname[strlen(get_my_executable_directory()) + strlen(crelfname) + 1];
strcpy(fname, get_my_executable_directory());
strcat(fname, crelfname);
if (MergeJSON) { if (MergeJSON) {
root = json_load_file(fname, 0, &error);
root = json_load_file( (char*)filename, 0, &error);
if (!root) { if (!root) {
PrintAndLogEx(ERR, "Json error on line %d: %s", error.line, error.text); PrintAndLogEx(ERR, "Json error on line %d: %s", error.line, error.text);
return PM3_EFILE; return PM3_EFILE;
@ -1589,6 +1589,7 @@ static int CmdEMVScan(const char *Cmd) {
JsonSaveTLVTree(root, root, "$.Application.FCITemplate", fci); JsonSaveTLVTree(root, root, "$.Application.FCITemplate", fci);
else else
JsonSaveTLVTreeElm(root, "$.Application.FCITemplate", fci, true, true, false); JsonSaveTLVTreeElm(root, "$.Application.FCITemplate", fci, true, true, false);
tlvdb_free(fci); tlvdb_free(fci);
// create transaction parameters // create transaction parameters
@ -1746,12 +1747,24 @@ static int CmdEMVScan(const char *Cmd) {
DropFieldEx(channel); DropFieldEx(channel);
res = json_dump_file(root, fname, JSON_INDENT(2));
if (MergeJSON == false) {
// create unique new name
char *fname = newfilenamemcopy((char*)filename, ".json");
if (fname == NULL) {
return PM3_EMALLOC;
}
strcpy((char*)filename, fname);
free(fname);
}
res = json_dump_file(root, (char*)filename, JSON_INDENT(2));
if (res) { if (res) {
PrintAndLogEx(ERR, "Can't save the file: %s", fname); PrintAndLogEx(ERR, "Can't save the file: %s", filename);
return PM3_EFILE; return PM3_EFILE;
} }
PrintAndLogEx(SUCCESS, "File " _YELLOW_("`%s`") " saved.", fname);
PrintAndLogEx(SUCCESS, "File " _YELLOW_("`%s`") " saved.", filename);
// free json object // free json object
json_decref(root); json_decref(root);

View file

@ -32,8 +32,7 @@
#include "fileutils.h" #include "fileutils.h"
#include "pm3_cmd.h" #include "pm3_cmd.h"
#define BCD(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : \ #define BCD(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : -1)
-1)
#define HEX(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : \ #define HEX(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : \
((c) >= 'A' && (c) <= 'F') ? ((c) - 'A' + 10) : \ ((c) >= 'A' && (c) <= 'F') ? ((c) - 'A' + 10) : \
@ -93,7 +92,6 @@ static ssize_t emv_pk_read_ymv(char *buf, size_t buflen, unsigned *ymv) {
if (buf == NULL) if (buf == NULL)
return 0; return 0;
int i;
unsigned char temp[3]; unsigned char temp[3];
char *p = buf; char *p = buf;
@ -102,7 +100,7 @@ static ssize_t emv_pk_read_ymv(char *buf, size_t buflen, unsigned *ymv) {
while ((*p == ' ') && (p < (buf + buflen - 1))) while ((*p == ' ') && (p < (buf + buflen - 1)))
p++; p++;
for (i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
int c1, c2; int c1, c2;
c1 = BCD(*p); c1 = BCD(*p);
if (c1 == -1) if (c1 == -1)
@ -164,7 +162,6 @@ static ssize_t emv_pk_read_string(char *buf, size_t buflen, char *str, size_t si
return (p - buf); return (p - buf);
} }
struct emv_pk *emv_pk_parse_pk(char *buf, size_t buflen) { struct emv_pk *emv_pk_parse_pk(char *buf, size_t buflen) {
struct emv_pk *r = calloc(1, sizeof(*r)); struct emv_pk *r = calloc(1, sizeof(*r));
ssize_t l; ssize_t l;
@ -264,22 +261,22 @@ static size_t emv_pk_write_str(char *out, size_t outlen, const char *str) {
} }
char *emv_pk_dump_pk(const struct emv_pk *pk) { char *emv_pk_dump_pk(const struct emv_pk *pk) {
size_t outpos = 0;
size_t outsize = 1024; /* should be enough */ size_t outsize = 1024; /* should be enough */
char *out = malloc(outsize); /* should be enough */ char *out = malloc(outsize); /* should be enough */
size_t outpos = 0;
size_t rc;
if (!out) if (!out)
return NULL; return NULL;
rc = emv_pk_write_bin(out + outpos, outsize - outpos, pk->rid, 5); size_t rc = emv_pk_write_bin(out + outpos, outsize - outpos, pk->rid, 5);
if (rc == 0) if (rc == 0)
goto err; goto err;
outpos += rc; outpos += rc;
rc = emv_pk_write_bin(out + outpos, outsize - outpos, &pk->index, 1); rc = emv_pk_write_bin(out + outpos, outsize - outpos, &pk->index, 1);
if (rc == 0) if (rc == 0)
goto err; goto err;
outpos += rc; outpos += rc;
if (outpos + 7 > outsize) if (outpos + 7 > outsize)
@ -504,21 +501,23 @@ struct emv_pk *emv_pk_get_ca_pk(const unsigned char *rid, unsigned char idx) {
if (!pk) if (!pk)
return NULL; return NULL;
printf("Verifying CA PK for %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx %zu bits...", bool isok = emv_pk_verify(pk);
PrintAndLogEx(INFO, "Verifying CA PK for %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx %zu bits. ( %s )",
pk->rid[0], pk->rid[0],
pk->rid[1], pk->rid[1],
pk->rid[2], pk->rid[2],
pk->rid[3], pk->rid[3],
pk->rid[4], pk->rid[4],
pk->index, pk->index,
pk->mlen * 8); pk->mlen * 8,
(isok) ? _GREEN_("ok") : _RED_("failed")
);
if (emv_pk_verify(pk)) { if (isok) {
printf("OK\n");
return pk; return pk;
} }
printf("Failed!\n");
emv_pk_free(pk); emv_pk_free(pk);
return NULL; return NULL;
} }

View file

@ -228,17 +228,20 @@ static char *filenamemcopy(const char *preferredName, const char *suffix) {
char *newfilenamemcopy(const char *preferredName, const char *suffix) { char *newfilenamemcopy(const char *preferredName, const char *suffix) {
if (preferredName == NULL) return NULL; if (preferredName == NULL) return NULL;
if (suffix == NULL) return NULL; if (suffix == NULL) return NULL;
uint16_t preferredNameLen = strlen(preferredName);
uint16_t p_namelen = strlen(preferredName);
if (str_endswith(preferredName, suffix)) if (str_endswith(preferredName, suffix))
preferredNameLen -= strlen(suffix); p_namelen -= strlen(suffix);
char *fileName = (char *) calloc(preferredNameLen + strlen(suffix) + 1 + 10, sizeof(uint8_t)); // 10: room for filenum to ensure new filename
char *fileName = (char *) calloc(p_namelen + strlen(suffix) + 1 + 10, sizeof(uint8_t)); // 10: room for filenum to ensure new filename
if (fileName == NULL) { if (fileName == NULL) {
return NULL; return NULL;
} }
int num = 1; int num = 1;
sprintf(fileName, "%.*s%s", preferredNameLen, preferredName, suffix); sprintf(fileName, "%.*s%s", p_namelen, preferredName, suffix);
while (fileExists(fileName)) { while (fileExists(fileName)) {
sprintf(fileName, "%.*s-%d%s", preferredNameLen, preferredName, num, suffix); sprintf(fileName, "%.*s-%d%s", p_namelen, preferredName, num, suffix);
num++; num++;
} }
return fileName; return fileName;
@ -475,7 +478,7 @@ int saveFileJSONex(const char *preferredName, JSONFileType ftype, uint8_t *data,
} }
break; break;
} }
case jsfMfPlusKeys: case jsfMfPlusKeys: {
JsonSaveStr(root, "FileType", "mfp"); JsonSaveStr(root, "FileType", "mfp");
JsonSaveBufAsHexCompact(root, "$.Card.UID", &data[0], 7); JsonSaveBufAsHexCompact(root, "$.Card.UID", &data[0], 7);
JsonSaveBufAsHexCompact(root, "$.Card.SAK", &data[10], 1); JsonSaveBufAsHexCompact(root, "$.Card.SAK", &data[10], 1);
@ -503,7 +506,8 @@ int saveFileJSONex(const char *preferredName, JSONFileType ftype, uint8_t *data,
} }
} }
break; break;
case jsfMfDesfireKeys: }
case jsfMfDesfireKeys: {
JsonSaveStr(root, "FileType", "mfdes"); JsonSaveStr(root, "FileType", "mfdes");
JsonSaveBufAsHexCompact(root, "$.Card.UID", &data[0], 7); JsonSaveBufAsHexCompact(root, "$.Card.UID", &data[0], 7);
JsonSaveBufAsHexCompact(root, "$.Card.SAK", &data[10], 1); JsonSaveBufAsHexCompact(root, "$.Card.SAK", &data[10], 1);
@ -541,9 +545,11 @@ int saveFileJSONex(const char *preferredName, JSONFileType ftype, uint8_t *data,
} }
} }
break; break;
case jsfCustom: }
case jsfCustom: {
(*callback)(root); (*callback)(root);
break; break;
}
default: default:
break; break;
} }

View file

@ -28,6 +28,7 @@
#include "desfire_crypto.h" #include "desfire_crypto.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <util.h>
#include "commonutil.h" #include "commonutil.h"
#include "aes.h" #include "aes.h"
#include "des.h" #include "des.h"
@ -406,6 +407,8 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
/* pass through */ /* pass through */
case MDCM_MACED: case MDCM_MACED:
communication_settings |= NO_CRC;
switch (DESFIRE(tag)->authentication_scheme) { switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY: case AS_LEGACY:
if (!(communication_settings & MAC_COMMAND)) if (!(communication_settings & MAC_COMMAND))
@ -508,6 +511,9 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes, int communication_settings) { void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes, int communication_settings) {
void *res = data; void *res = data;
void *edata = NULL; void *edata = NULL;
tag->crypto_buffer_size = *nbytes * 2;
tag->crypto_buffer = (uint8_t *)malloc(tag->crypto_buffer_size);
uint8_t first_cmac_byte = 0x00; uint8_t first_cmac_byte = 0x00;
desfirekey_t key = DESFIRE(tag)->session_key; desfirekey_t key = DESFIRE(tag)->session_key;
@ -527,6 +533,7 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
/* pass through */ /* pass through */
case MDCM_MACED: case MDCM_MACED:
communication_settings |= NO_CRC;
switch (DESFIRE(tag)->authentication_scheme) { switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY: case AS_LEGACY:
if (communication_settings & MAC_VERIFY) { if (communication_settings & MAC_VERIFY) {
@ -540,18 +547,22 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
break; break;
} }
size_t edl = enciphered_data_length(tag, *nbytes - 1, communication_settings); size_t edl = enciphered_data_length(tag, *nbytes, communication_settings);
edata = malloc(edl); edata = malloc(edl);
memcpy(edata, data, *nbytes - 1); memcpy(edata, data, *nbytes);
memset((uint8_t *)edata + *nbytes - 1, 0, edl - *nbytes + 1); memset((uint8_t *)edata + *nbytes, 0, edl - *nbytes);
mifare_cypher_blocks_chained(tag, NULL, NULL, edata, edl, MCD_SEND, MCO_ENCYPHER); mifare_cypher_blocks_chained(tag, NULL, NULL, edata, edl, MCD_SEND, MCO_ENCYPHER);
if (0 != memcmp((uint8_t *)data + *nbytes - 1, (uint8_t *)edata + edl - 8, 4)) { if (0 != memcmp((uint8_t *)data + *nbytes, (uint8_t *)edata + edl - 8, 4)) {
#ifdef WITH_DEBUG
PrintAndLogEx(NORMAL, "Expected MAC %s", sprint_hex(data + *nbytes, key_macing_length(key)));
PrintAndLogEx(NORMAL, "Actual MAC %s", sprint_hex(edata + edl - 8, key_macing_length(key)));
#endif
#ifdef WITH_DEBUG #ifdef WITH_DEBUG
Dbprintf("MACing not verified"); Dbprintf("MACing not verified");
hexdump((uint8_t *)data + *nbytes - 1, key_macing_length(key), "Expect ", 0); hexdump((uint8_t *)data + *nbytes, key_macing_length(key), "Expect ", 0);
hexdump((uint8_t *)edata + edl - 8, key_macing_length(key), "Actual ", 0); hexdump((uint8_t *)edata + edl - 8, key_macing_length(key), "Actual ", 0);
#endif #endif
DESFIRE(tag)->last_pcd_error = CRYPTO_ERROR; DESFIRE(tag)->last_pcd_error = CRYPTO_ERROR;
@ -644,6 +655,7 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
case AS_NEW: case AS_NEW:
/* Move status between payload and CRC */ /* Move status between payload and CRC */
res = DESFIRE(tag)->crypto_buffer; res = DESFIRE(tag)->crypto_buffer;
if (res != NULL) {
memcpy(res, data, *nbytes); memcpy(res, data, *nbytes);
crc_pos = (*nbytes) - 16 - 3; crc_pos = (*nbytes) - 16 - 3;
@ -655,6 +667,7 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
((uint8_t *) res)[crc_pos] = 0x00; ((uint8_t *) res)[crc_pos] = 0x00;
crc_pos++; crc_pos++;
*nbytes += 1; *nbytes += 1;
}
break; break;
} }
@ -725,6 +738,9 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
break; break;
} }
free(tag->crypto_buffer);
tag->crypto_buffer_size = 0;
tag->crypto_buffer = NULL;
return res; return res;
} }
@ -864,3 +880,19 @@ void mifare_cypher_blocks_chained(desfiretag_t tag, desfirekey_t key, uint8_t *i
offset += block_size; offset += block_size;
} }
} }
void desfire_crc32(const uint8_t *data, const size_t len, uint8_t *crc) {
crc32_ex(data,len,crc);
}
void desfire_crc32_append(uint8_t *data, const size_t len) {
crc32_ex(data, len, data + len);
}
void iso14443a_crc_append(uint8_t *data, size_t len) {
return compute_crc(CRC_14443_A, data, len, data + len, data + len + 1);
}
void iso14443a_crc(uint8_t *data, size_t len, uint8_t *pbtCrc) {
return compute_crc(CRC_14443_A, data, len, pbtCrc, pbtCrc + 1);
}

View file

@ -129,4 +129,8 @@ size_t enciphered_data_length(const desfiretag_t tag, const size_t nbytes, int c
void cmac_generate_subkeys(desfirekey_t key); void cmac_generate_subkeys(desfirekey_t key);
void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac); void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac);
void desfire_crc32(const uint8_t *data, const size_t len, uint8_t *crc);
void desfire_crc32_append(uint8_t *data, const size_t len);
void iso14443a_crc_append(uint8_t *data, size_t len);
void iso14443a_crc(uint8_t *data, size_t len, uint8_t *pbtCrc);
#endif #endif

View file

@ -865,7 +865,7 @@ int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, uint8_
int mfCWipe(uint8_t *uid, uint8_t *atqa, uint8_t *sak) { int mfCWipe(uint8_t *uid, uint8_t *atqa, uint8_t *sak) {
uint8_t block0[16] = {0x01, 0x02, 0x03, 0x04, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xAF}; uint8_t block0[16] = {0x01, 0x02, 0x03, 0x04, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xAF};
uint8_t blockD[16] = {0x00}; //uint8_t blockD[16] = {0x00};
uint8_t blockK[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x77, 0x8F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; uint8_t blockK[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x77, 0x8F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
uint8_t params = MAGIC_SINGLE; uint8_t params = MAGIC_SINGLE;
@ -891,8 +891,8 @@ int mfCWipe(uint8_t *uid, uint8_t *atqa, uint8_t *sak) {
} else { } else {
if (mfIsSectorTrailer(blockNo)) if (mfIsSectorTrailer(blockNo))
res = mfCSetBlock(blockNo, blockK, NULL, params); res = mfCSetBlock(blockNo, blockK, NULL, params);
else // else
res = mfCSetBlock(blockNo, blockD, NULL, params); // res = mfCSetBlock(blockNo, blockD, NULL, params);
} }
if (res == PM3_SUCCESS) if (res == PM3_SUCCESS)

View file

@ -52,9 +52,7 @@ int preferences_load(void) {
session.overlay.y = 60 + session.plot.y + session.plot.h; session.overlay.y = 60 + session.plot.y + session.plot.h;
session.overlay.h = 200; session.overlay.h = 200;
session.overlay.w = session.plot.w; session.overlay.w = session.plot.w;
session.emoji_mode = ALIAS;
session.show_hints = false; session.show_hints = false;
session.supports_colors = false;
// setDefaultPath (spDefault, ""); // setDefaultPath (spDefault, "");
// setDefaultPath (spDump, ""); // setDefaultPath (spDump, "");

View file

@ -32,9 +32,6 @@
#include "flash.h" #include "flash.h"
#include "preferences.h" #include "preferences.h"
// Used to enable/disable use of preferences json file
#define USE_PREFERENCE_FILE
#define BANNERMSG1 " :snowflake: iceman@icesql.net" #define BANNERMSG1 " :snowflake: iceman@icesql.net"
#define BANNERMSG2 " https://github.com/rfidresearchgroup/proxmark3/" #define BANNERMSG2 " https://github.com/rfidresearchgroup/proxmark3/"
#define BANNERMSG3 " bleeding edge :coffee:" #define BANNERMSG3 " bleeding edge :coffee:"
@ -632,8 +629,6 @@ finish2:
return ret; return ret;
} }
#ifndef USE_PREFERENCE_FILE
// Check if windows AnsiColor Support is enabled in the registery // Check if windows AnsiColor Support is enabled in the registery
// [HKEY_CURRENT_USER\Console] // [HKEY_CURRENT_USER\Console]
// "VirtualTerminalLevel"=dword:00000001 // "VirtualTerminalLevel"=dword:00000001
@ -641,9 +636,9 @@ finish2:
// [HKEY_CURRENT_USER\Console] // [HKEY_CURRENT_USER\Console]
// "ForceV2"=dword:00000001 // "ForceV2"=dword:00000001
#if defined(_WIN32)
static bool DetectWindowsAnsiSupport(void) { static bool DetectWindowsAnsiSupport(void) {
bool ret = false; bool ret = false;
#if defined(_WIN32)
HKEY hKey = NULL; HKEY hKey = NULL;
bool virtualTerminalLevelSet = false; bool virtualTerminalLevelSet = false;
bool forceV2Set = false; bool forceV2Set = false;
@ -685,10 +680,8 @@ static bool DetectWindowsAnsiSupport(void) {
} }
// If both VirtualTerminalLevel and ForceV2 is set, AnsiColor should work // If both VirtualTerminalLevel and ForceV2 is set, AnsiColor should work
ret = virtualTerminalLevelSet && forceV2Set; ret = virtualTerminalLevelSet && forceV2Set;
#endif
return ret; return ret;
} }
#endif #endif
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
@ -733,6 +726,28 @@ int main(int argc, char *argv[]) {
set_my_executable_path(); set_my_executable_path();
set_my_user_directory(); set_my_user_directory();
// color management:
// 1. default = no color
// 2. enable colors if OS seems to support colors and if stdin/stdout aren't redirected
// 3. load prefs if available, overwrite colors choice if needed
// 4. disable colors anyway if stdin/stdout are redirected
//
// For info, grep --color=auto is doing sth like this, plus test getenv("TERM") != "dumb":
// struct stat tmp_stat;
// if ((fstat (STDOUT_FILENO, &tmp_stat) == 0) && (S_ISCHR (tmp_stat.st_mode)) && isatty(STDIN_FILENO))
session.stdinOnTTY = isatty(STDIN_FILENO);
session.stdoutOnTTY = isatty(STDOUT_FILENO);
session.supports_colors = false;
session.emoji_mode = ALTTEXT;
if (session.stdinOnTTY && session.stdoutOnTTY) {
#if defined(__linux__) || defined(__APPLE__)
session.supports_colors = true;
session.emoji_mode = EMOJI;
#elif defined(_WIN32)
session.supports_colors = DetectWindowsAnsiSupport();
session.emoji_mode = ALTTEXT;
#endif
}
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
if (argv[i][0] != '-') { if (argv[i][0] != '-') {
@ -912,7 +927,6 @@ int main(int argc, char *argv[]) {
return 1; return 1;
} }
#ifdef USE_PREFERENCE_FILE
// Load Settings and assign // Load Settings and assign
// This will allow the command line to override the settings.json values // This will allow the command line to override the settings.json values
preferences_load(); preferences_load();
@ -921,44 +935,13 @@ int main(int argc, char *argv[]) {
g_debugMode = session.client_debug_level; g_debugMode = session.client_debug_level;
// settings_save (); // settings_save ();
// End Settings // End Settings
#endif
#ifndef USE_PREFERENCE_FILE
// comment next 2 lines to use session values set from settings_load
session.supports_colors = DetectWindowsAnsiSupport();
session.emoji_mode = ALTTEXT;
#endif
session.stdinOnTTY = isatty(STDIN_FILENO);
session.stdoutOnTTY = isatty(STDOUT_FILENO);
#if defined(__linux__) || defined(__APPLE__)
// it's okay to use color if:
// * Linux or OSX
// * Not redirected to a file but printed to term
// For info, grep --color=auto is doing sth like this, plus test getenv("TERM") != "dumb":
// struct stat tmp_stat;
// if ((fstat (STDOUT_FILENO, &tmp_stat) == 0) && (S_ISCHR (tmp_stat.st_mode)) && isatty(STDIN_FILENO))
#ifdef USE_PREFERENCE_FILE
if (!session.preferences_loaded) {
if (session.stdinOnTTY && session.stdoutOnTTY) {
session.supports_colors = true;
session.emoji_mode = EMOJI;
}
} else {
// even if prefs, we disable colors if stdin or stdout is not a TTY // even if prefs, we disable colors if stdin or stdout is not a TTY
if ((! session.stdinOnTTY) || (! session.stdoutOnTTY)) { if ((! session.stdinOnTTY) || (! session.stdoutOnTTY)) {
session.supports_colors = false; session.supports_colors = false;
session.emoji_mode = ALTTEXT; session.emoji_mode = ALTTEXT;
} }
}
#else
if (session.stdinOnTTY && session.stdoutOnTTY) {
session.supports_colors = true;
session.emoji_mode = EMOJI;
}
#endif
#endif
// Let's take a baudrate ok for real UART, USB-CDC & BT don't use that info anyway // Let's take a baudrate ok for real UART, USB-CDC & BT don't use that info anyway
if (speed == 0) if (speed == 0)
speed = USART_BAUD_RATE; speed = USART_BAUD_RATE;
@ -1013,7 +996,6 @@ int main(int argc, char *argv[]) {
if (!script_cmds_file && !script_cmd && session.stdinOnTTY && session.stdoutOnTTY && !flash_mode) if (!script_cmds_file && !script_cmd && session.stdinOnTTY && session.stdoutOnTTY && !flash_mode)
showBanner(); showBanner();
#ifdef USE_PREFERENCE_FILE
// Save settings if not loaded from settings json file. // Save settings if not loaded from settings json file.
// Doing this here will ensure other checks and updates are saved to over rule default // Doing this here will ensure other checks and updates are saved to over rule default
// e.g. Linux color use check // e.g. Linux color use check
@ -1034,7 +1016,6 @@ int main(int argc, char *argv[]) {
PrintAndLogEx(WARNING,"Proxmark3 not ready to set debug level"); PrintAndLogEx(WARNING,"Proxmark3 not ready to set debug level");
} }
*/ */
#endif
#ifdef HAVE_GUI #ifdef HAVE_GUI
@ -1061,9 +1042,7 @@ int main(int argc, char *argv[]) {
CloseProxmark(); CloseProxmark();
} }
#ifdef USE_PREFERENCE_FILE
if (session.window_changed) // Plot/Overlay moved or resized if (session.window_changed) // Plot/Overlay moved or resized
preferences_save(); preferences_save();
#endif
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }

View file

@ -44,6 +44,7 @@ session_arg_t session;
double CursorScaleFactor = 1; double CursorScaleFactor = 1;
int PlotGridX = 0, PlotGridY = 0, PlotGridXdefault = 64, PlotGridYdefault = 64; int PlotGridX = 0, PlotGridY = 0, PlotGridXdefault = 64, PlotGridYdefault = 64;
uint32_t CursorCPos = 0, CursorDPos = 0; uint32_t CursorCPos = 0, CursorDPos = 0;
double GraphPixelsPerPoint = 1.f; // How many visual pixels are between each sample point (x axis)
static bool flushAfterWrite = 0; static bool flushAfterWrite = 0;
int GridOffset = 0; int GridOffset = 0;
bool GridLocked = false; bool GridLocked = false;
@ -201,34 +202,34 @@ void PrintAndLogEx(logLevel_t level, const char *fmt, ...) {
switch (level) { switch (level) {
case ERR: case ERR:
if (session.emoji_mode == EMOJI) if (session.emoji_mode == EMOJI)
strncpy(prefix, _RED_("[!!]") " :rotating_light: ", sizeof(prefix) - 1); strncpy(prefix, "[" _RED_("!!") "] :rotating_light: ", sizeof(prefix) - 1);
else else
strncpy(prefix, _RED_("[!!] "), sizeof(prefix) - 1); strncpy(prefix, "[" _RED_("!!") "] ", sizeof(prefix) - 1);
stream = stderr; stream = stderr;
break; break;
case FAILED: case FAILED:
if (session.emoji_mode == EMOJI) if (session.emoji_mode == EMOJI)
strncpy(prefix, _RED_("[-]") " :no_entry: ", sizeof(prefix) - 1); strncpy(prefix, "[" _RED_("-") "] :no_entry: ", sizeof(prefix) - 1);
else else
strncpy(prefix, _RED_("[-] "), sizeof(prefix) - 1); strncpy(prefix, "[" _RED_("-") "] ", sizeof(prefix) - 1);
break; break;
case DEBUG: case DEBUG:
strncpy(prefix, _BLUE_("[#] "), sizeof(prefix) - 1); strncpy(prefix, "[" _BLUE_("#") "] ", sizeof(prefix) - 1);
break; break;
case HINT: case HINT:
strncpy(prefix, _YELLOW_("[?] "), sizeof(prefix) - 1); strncpy(prefix, "[" _YELLOW_("?") "] ", sizeof(prefix) - 1);
break; break;
case SUCCESS: case SUCCESS:
strncpy(prefix, _GREEN_("[+] "), sizeof(prefix) - 1); strncpy(prefix, "[" _GREEN_("+") "] ", sizeof(prefix) - 1);
break; break;
case WARNING: case WARNING:
if (session.emoji_mode == EMOJI) if (session.emoji_mode == EMOJI)
strncpy(prefix, _CYAN_("[!]") " :warning: ", sizeof(prefix) - 1); strncpy(prefix, "[" _CYAN_("!") "] :warning: ", sizeof(prefix) - 1);
else else
strncpy(prefix, _CYAN_("[!] "), sizeof(prefix) - 1); strncpy(prefix, "[" _CYAN_("!") "] ", sizeof(prefix) - 1);
break; break;
case INFO: case INFO:
strncpy(prefix, _YELLOW_("[=] "), sizeof(prefix) - 1); strncpy(prefix, "[" _YELLOW_("=") "] ", sizeof(prefix) - 1);
break; break;
case INPLACE: case INPLACE:
if (session.emoji_mode == EMOJI) { if (session.emoji_mode == EMOJI) {
@ -325,9 +326,9 @@ static void fPrintAndLog(FILE *stream, const char *fmt, ...) {
} else { } else {
if (session.supports_colors) { if (session.supports_colors) {
printf(_YELLOW_("[=]") " Session log " _YELLOW_("%s") "\n", my_logfile_path); printf("["_YELLOW_("=")"] Session log " _YELLOW_("%s") "\n", my_logfile_path);
} else { } else {
printf(_YELLOW_("[=]") " Session log %s\n", my_logfile_path); printf("[=] Session log %s\n", my_logfile_path);
} }
} }

50
doc/colors_notes.md Normal file
View file

@ -0,0 +1,50 @@
<a id="Top"></a>
# Notes on Color usage.
## Table of Contents
* [style/color](#style_color)
* [Proxspace](#proxspace)
* [](#)
The client should autodetect color support when starting.
You can also use the command `pref show` to see and set your personal setting.
Why use colors in the Proxmark client? When evertyhing is white it is hard to extract the important information fast. You also need new-lines for extra space to be easier to read.
We have gradually been introducing this color scheme into the client since we got decent color support on all systems: OSX, Linux, WSL, Proxspace.
## style/color
^[Top](#top)
The following definition has be crystalized out from these experiments. Its not set in stone yet so take this document as a guideline for how to create unified system scheme.
### Definition
^[Top](#top)
- blue - system related headers, banner
- white - normal
- cyan - headers
- red - warning, error, catastrophic failures
- yellow - informative (to make things stick out from white blob)
- green - successful, (to make things stick out from white blob)
- magenta - device side messages
### Styled header
^[Top](#top)
```
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------");
PrintAndLogEx(INFO, "-------------------------------------------------------------");
```
For more examples, see also all **-h** helptext now in the LUA scripts.
For the command help texts using _YELLOW_ for the example makes it very easy to see what is the command vs the description.
### non styled header
^[Top](#top)
Most commands doesn't use a header yet. We added it to make it standout (ie: yellow, green) of the informative tidbits in the output of a command.
## Proxspace
^[Top](#top)
Proxspace has support for colors.

View file

@ -359,6 +359,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
#define MFDES_READSIG 0x3C #define MFDES_READSIG 0x3C
#define MFDES_WRITE_DATA 0x3D #define MFDES_WRITE_DATA 0x3D
#define MFDES_GET_KEY_SETTINGS 0x45 #define MFDES_GET_KEY_SETTINGS 0x45
#define MFDES_GET_UID 0x51
#define MFDES_CHANGE_KEY_SETTINGS 0x54 #define MFDES_CHANGE_KEY_SETTINGS 0x54
#define MFDES_SELECT_APPLICATION 0x5A #define MFDES_SELECT_APPLICATION 0x5A
#define MFDES_CHANGE_FILE_SETTINGS 0x5F #define MFDES_CHANGE_FILE_SETTINGS 0x5F