mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 13:53:55 -07:00
commit
70933c359d
20 changed files with 1333 additions and 767 deletions
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -605,6 +605,7 @@ d58023ba2bdc # charlie
|
||||||
62ced42a6d87 # charlie
|
62ced42a6d87 # charlie
|
||||||
2548a443df28 # charlie
|
2548a443df28 # charlie
|
||||||
2ed3b15e7c0f # charlie
|
2ed3b15e7c0f # charlie
|
||||||
|
f66224ee1e89 # charlie
|
||||||
#
|
#
|
||||||
60012e9ba3fa
|
60012e9ba3fa
|
||||||
#
|
#
|
||||||
|
|
|
@ -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
|
@ -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... }"},
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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, "");
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
50
doc/colors_notes.md
Normal 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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue