Merge pull request #1 from RfidResearchGroup/master

Updates
This commit is contained in:
Bjoern Kerler 2020-04-22 21:28:08 +02:00 committed by GitHub
commit 1770c1e37c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
114 changed files with 2799 additions and 963 deletions

11
.gitignore vendored
View file

@ -31,12 +31,23 @@ version.c
*.old
*.swp
*.json.bak
*.pyc
# new build file for add-ons.
Makefile.platform
# Cache for detecting platform def changes
.Makefile.options.cache
# cmake
client/build/
# Coverity
cov-int/
.coverity.conf
# profiling
*.gcno
!client/resources/hardnested/*.bin
!client/resources/hardnested_tables/*.z
client/src/ui/ui_overlays.h

View file

@ -4,29 +4,23 @@ language: c
#default linux build env is: xenial
compiler: gcc
os:
- linux
- osx
dist: xenial
osx_image: xcode11
# move some env variables to homebrew env
env:
global:
- HOMEBREW_TRAVIS_BRANCH=$TRAVIS_BRANCH
- HOMEBREW_TRAVIS_COMMIT=$TRAVIS_COMMIT
# Test on Linux and MacOS
matrix:
include:
- os: osx
osx_image: xcode11
env: MAKE_PARAMS='PLATFORM_EXTRAS='
- os: osx
osx_image: xcode11
env: MAKE_PARAMS='PLATFORM_EXTRAS=BTADDON'
- os: linux
dist: xenial
sudo: required
env: MAKE_PARAMS='PLATFORM_EXTRAS='
- os: linux
dist: xenial
sudo: required
env: MAKE_PARAMS='PLATFORM_EXTRAS=BTADDON'
jobs:
- TO_TEST=MAKEFILE MAKE_PARAMS='PLATFORM_EXTRAS='
- TO_TEST=MAKEFILE MAKE_PARAMS='PLATFORM_EXTRAS=BTADDON'
- TO_TEST=CMAKE
addons:
apt:
@ -58,13 +52,12 @@ install:
travis_terminate 1;
fi
make clean;
make all V=1 "$MAKE_PARAMS";
script:
## start and run a test script
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
./pm3test.sh;
elif [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
- if [ "$TO_TEST" = "MAKEFILE" ]; then
make clean && make V=1 "$MAKE_PARAMS";
./pm3test.sh;
fi
- if [ "$TO_TEST" = "CMAKE" ]; then
mkdir -p client/build && ( cd client/build && cmake .. && make VERBOSE=1 );
PM3BIN=./client/build/proxmark3 ./pm3test.sh client;
fi

View file

@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased]
- Added Mifare Ultralight tear off experiment (@cintainfinita and @fukmar)
- Added Mifare Desfire Read/Write/Create files/records/values functionality and several fixes to `hf mfdes` (@bkerler)
- Added CreateStdFile command to Mifare `hf mfdes` (@bkerler)
- Rework des/3des/3k3des/aes auth. Port to mbedtls crypto library on device (@bkerler)

View file

@ -28,7 +28,7 @@ POSTCOMPILE = $(MV) -f $(OBJDIR)/$*.Td $(OBJDIR)/$*.d && $(TOUCH) $@
BINDIR := .
OBJDIR := obj
MYOBJS = $(MYSRCS:%.c=$(OBJDIR)/%.o)
MYOBJS ?= $(MYSRCS:%.c=$(OBJDIR)/%.o)
CLEAN = $(foreach bin,$(MYLIBS) $(BINS) $(LIB_A),$(BINDIR)/$(bin))
all: $(foreach bin,$(MYLIBS) $(BINS) $(LIB_A),$(BINDIR)/$(bin))
@ -36,6 +36,11 @@ all: $(foreach bin,$(MYLIBS) $(BINS) $(LIB_A),$(BINDIR)/$(bin))
clean:
$(Q)$(RM) $(CLEAN)
$(Q)$(RMDIR) $(OBJDIR)
ifneq (,$(MYCLEANOLDPATH))
$(Q)$(RM) $(foreach f,$(CLEAN),$(MYCLEANOLDPATH)/$(f))
$(Q)$(RMDIR) $(MYCLEANOLDPATH)/$(OBJDIR)
$(Q)$(RMDIR_SOFT) $(MYCLEANOLDPATH) 2>/dev/null || true
endif
install: all
ifneq (,$(INSTALLTOOLS))

View file

@ -1295,7 +1295,7 @@ static void PacketReceived(PacketCommandNG *packet) {
break;
}
case CMD_HF_MFU_OTP_TEAROFF: {
MifareU_Otp_Tearoff();
MifareU_Otp_Tearoff(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
break;
}
case CMD_HF_MIFARE_STATIC_NONCE: {

View file

@ -2423,12 +2423,14 @@ void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain) {
//
// Tear-off attack against MFU.
// - Moebius et al
void MifareU_Otp_Tearoff() {
// should the
// optional time be configurable via client side?
void MifareU_Otp_Tearoff(uint8_t arg0, uint32_t arg1, uint8_t *datain) {
uint8_t blockNo = arg0;
uint32_t tearOffTime = arg1;
uint8_t data_fullwrite[4] = {0x00};
uint8_t data_testwrite[4] = {0x00};
memcpy(data_fullwrite, datain, 4);
memcpy(data_testwrite, datain + 4, 4);
// optional authentication before?
// optional data to be written?
if (DBGLEVEL >= DBG_ERROR) DbpString("Preparing OTP tear-off");
@ -2439,46 +2441,26 @@ void MifareU_Otp_Tearoff() {
StartTicks();
#define OTP_TEAR_OFF_TIME 1000
#define OTP_BLK_NO 3
// write cmd to send, include CRC
// 1b write, 1b block, 4b data, 2 crc
uint8_t cmd[] = {MIFARE_ULC_WRITE, OTP_BLK_NO, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0};
uint8_t cmd[] = {MIFARE_ULC_WRITE, blockNo, data_testwrite[0], data_testwrite[1], data_testwrite[2], data_testwrite[3], 0, 0};
// User specific data to write?
// memcpy(block + 2, blockData, 4);
MifareUWriteBlock(blockNo, 0, data_fullwrite);
AddCrc14A(cmd, sizeof(cmd) - 2);
if (DBGLEVEL >= DBG_ERROR) DbpString("Transmitting");
// anticollision / select card
if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) {
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card");
OnError(1);
return;
};
/*
// UL-EV1 / NTAG authentication
if (usePwd) {
uint8_t pwd[4] = {0x00};
memcpy(pwd, datain + 4, 4);
uint8_t pack[4] = {0, 0, 0, 0};
if (!mifare_ul_ev1_auth(pwd, pack)) {
OnError(1);
return;
}
}
*/
// send
ReaderTransmit(cmd, sizeof(cmd), NULL);
// Wait before cutting power. aka tear-off
LED_D_ON();
WaitUS(OTP_TEAR_OFF_TIME);
WaitUS(tearOffTime);
switch_off();
reply_ng(CMD_HF_MFU_OTP_TEAROFF, PM3_SUCCESS, NULL, 0);

View file

@ -59,6 +59,6 @@ void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain);
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain);
// Tear-off test for MFU
void MifareU_Otp_Tearoff();
void MifareU_Otp_Tearoff(uint8_t arg0, uint32_t arg1, uint8_t *datain);
#endif

284
client/CMakeLists.txt Normal file
View file

@ -0,0 +1,284 @@
cmake_minimum_required(VERSION 3.10)
project(proxmark3)
if(CMAKE_VERSION VERSION_LESS "3.7.0")
set(CMAKE_INCLUDE_CURRENT_DIR ON)
endif()
set(CMAKE_CXX_STANDARD 14)
if(APPLE AND EXISTS /usr/local/opt/qt5)
# Homebrew installs Qt5 (up to at least 5.11.0) in
# /usr/local/qt5. Ensure that it can be found by CMake
# since it is not in the default /usr/local prefix.
# Add it to PATHS so that it doesn't override the
# CMAKE_PREFIX_PATH environment variable.
# QT_FIND_PACKAGE_OPTIONS should be passed to find_package,
# e.g. find_package(Qt5Core ${QT_FIND_PACKAGE_OPTIONS})
list(APPEND QT_FIND_PACKAGE_OPTIONS PATHS /usr/local/opt/qt5)
endif()
set(QT_PACKAGELIST
Qt5Core
Qt5Widgets
Qt5Gui
)
set(Qt5_FOUND ON)
foreach(_qt_package IN LISTS QT_PACKAGELIST)
find_package(${_qt_package} QUIET ${QT_FIND_PACKAGE_OPTIONS})
if(NOT ${_qt_package}_FOUND)
set(Qt5_FOUND OFF)
endif(NOT ${_qt_package}_FOUND)
endforeach()
SET (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
INCLUDE(FindSSE)
if(NOT SSE2_FOUND)
MESSAGE(STATUS "Could not find hardware support for SSE2 on this machine.")
endif(NOT SSE2_FOUND)
if(NOT SSE3_FOUND)
MESSAGE(STATUS "Could not find hardware support for SSE3 on this machine.")
endif(NOT SSE3_FOUND)
if(NOT SSSE3_FOUND)
MESSAGE(STATUS "Could not find hardware support for SSSE3 on this machine.")
endif(NOT SSSE3_FOUND)
if(NOT SSE4_1_FOUND)
MESSAGE(STATUS "Could not find hardware support for SSE4.1 on this machine.")
endif(NOT SSE4_1_FOUND)
if(NOT AVX_FOUND)
MESSAGE(STATUS "Could not find hardware support for AVX on this machine.")
endif(NOT AVX_FOUND)
if(NOT AVX2_FOUND)
MESSAGE(STATUS "Could not find hardware support for AVX2 on this machine.")
endif(NOT AVX2_FOUND)
if(NOT AVX512_FOUND)
MESSAGE(STATUS "Could not find hardware support for AVX512 on this machine.")
endif(NOT AVX512_FOUND)
add_subdirectory(deps)
set (TARGET_SOURCES
src/proxmark3.c
../common/commonutil.c
../common/util_posix.c
../common/parity.c
../common/bucketsort.c
../common/crapto1/crapto1.c
../common/crapto1/crypto1.c
../common/crc.c
../common/crc16.c
../common/crc32.c
../common/crc64.c
../common/lfdemod.c
../common/legic_prng.c
../common/iso15693tools.c
../common/cardhelper.c
../common/generator.c
src/crypto/asn1dump.c
src/crypto/asn1utils.c
src/crypto/libpcrypto.c
src/emv/test/cda_test.c
src/emv/test/crypto_test.c
src/emv/test/cryptotest.c
src/emv/test/dda_test.c
src/emv/test/sda_test.c
src/emv/apduinfo.c
src/emv/cmdemv.c
src/emv/crypto.c
src/emv/crypto_polarssl.c
src/emv/dol.c
src/emv/dump.c
src/emv/emv_pk.c
src/emv/emv_pki.c
src/emv/emv_pki_priv.c
src/emv/emv_roca.c
src/emv/emv_tags.c
src/emv/emvcore.c
src/emv/emvjson.c
src/emv/tlv.c
src/fido/additional_ca.c
src/fido/cbortools.c
src/fido/cose.c
src/fido/fidocore.c
src/loclass/cipher.c
src/loclass/cipherutils.c
src/loclass/elite_crack.c
src/loclass/hash1_brute.c
src/loclass/ikeys.c
src/mifare/mad.c
src/mifare/mfkey.c
src/mifare/mifare4.c
src/mifare/mifaredefault.c
src/mifare/mifarehost.c
src/mifare/ndef.c
src/mifare/desfire_crypto.c
src/uart/uart_posix.c
src/uart/uart_win32.c
src/ui/overlays.ui
src/aidsearch.c
src/cmdanalyse.c
src/cmdcrc.c
src/cmddata.c
src/cmdflashmem.c
src/cmdflashmemspiffs.c
src/cmdhf.c
src/cmdhf14a.c
src/cmdhf14b.c
src/cmdhf15.c
src/cmdhfcryptorf.c
src/cmdhfepa.c
src/cmdhffelica.c
src/cmdhffido.c
src/cmdhficlass.c
src/cmdhflegic.c
src/cmdhflist.c
src/cmdhflto.c
src/cmdhfmf.c
src/cmdhfmfdes.c
src/cmdhfmfhard.c
src/cmdhfmfp.c
src/cmdhfmfu.c
src/cmdhfthinfilm.c
src/cmdhftopaz.c
src/cmdhw.c
src/cmdlf.c
src/cmdlfawid.c
src/cmdlfcotag.c
src/cmdlfem4x.c
src/cmdlffdx.c
src/cmdlfgallagher.c
src/cmdlfguard.c
src/cmdlfhid.c
src/cmdlfhitag.c
src/cmdlfindala.c
src/cmdlfio.c
src/cmdlfjablotron.c
src/cmdlfkeri.c
src/cmdlfmotorola.c
src/cmdlfnedap.c
src/cmdlfnexwatch.c
src/cmdlfnoralsy.c
src/cmdlfpac.c
src/cmdlfparadox.c
src/cmdlfpcf7931.c
src/cmdlfpresco.c
src/cmdlfpyramid.c
src/cmdlfsecurakey.c
src/cmdlft55xx.c
src/cmdlfti.c
src/cmdlfverichip.c
src/cmdlfviking.c
src/cmdlfvisa2000.c
src/cmdmain.c
src/cmdparser.c
src/cmdscript.c
src/cmdsmartcard.c
src/cmdtrace.c
src/cmdusart.c
src/cmdwiegand.c
src/comms.c
src/fileutils.c
src/flash.c
src/graph.c
src/preferences.c
src/pm3_binlib.c
src/pm3_bitlib.c
src/prng.c
src/scandir.c
src/scripting.c
src/tea.c
src/ui.c
src/util.c
src/whereami.c
src/wiegand_formats.c
src/wiegand_formatutils.c
)
set(ADDITIONAL_SRC "")
set(ADDITIONAL_LNK "")
set(X86_CPUS x86 x86_64 i686)
message(STATUS "CMAKE_SYSTEM_PROCESSOR := ${CMAKE_SYSTEM_PROCESSOR}")
if (APPLE)
message("Apple device detected.")
set(ADDITIONAL_SRC src/util_darwin.h src/util_darwin.m ${ADDITIONAL_SRC})
set(ADDITIONAL_LNK "-framework Foundation" "-framework AppKit")
endif (APPLE)
if (MINGW)
set(CMAKE_CXX_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_CXX_FLAGS}")
endif (MINGW)
if (Qt5_FOUND)
message("Qt5 library found, building gui :)")
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
set (TARGET_SOURCES
src/proxgui.cpp
src/proxguiqt.cpp
${TARGET_SOURCES})
add_definitions("-DHAVE_GUI")
set(ADDITIONAL_LNK Qt5::Core Qt5::Widgets Qt5::Gui ${ADDITIONAL_LNK})
else (Qt5_FOUND)
message("Qt5 library not found, not building gui")
set(TARGET_SOURCES
src/guidummy.cpp
${TARGET_SOURCES})
endif (Qt5_FOUND)
add_executable(
proxmark3
${TARGET_SOURCES}
${ADDITIONAL_SRC}
)
target_compile_options(proxmark3 PUBLIC -Wall -Werror -O3)
target_include_directories(proxmark3 PRIVATE
../common
../common_fpga
../include
src
)
if (APPLE)
set_target_properties(proxmark3 PROPERTIES LINK_FLAGS "-Wl,-F/Library/Frameworks, -L/usr/local/opt/readline/lib")
set_target_properties(proxmark3 PROPERTIES COMPILE_FLAGS "-I/usr/local/opt/readline/include")
else (APPLE)
# required for Raspberry Pi, but breaks with clang (OSX). Need to be at the end of the linker line.
set(ADDITIONAL_LNK ${ADDITIONAL_LNK} -Wl,--as-needed -latomic -Wl,--no-as-needed)
endif (APPLE)
find_library(cliparser REQUIRED)
find_library(jansson REQUIRED)
find_library(tinycbor REQUIRED)
find_library(lua REQUIRED)
find_library(mbedtls REQUIRED)
find_library(reveng REQUIRED)
find_library(z REQUIRED)
find_library(hardnested REQUIRED)
target_link_libraries(proxmark3 PRIVATE readline pthread m mbedtls cliparser jansson lua tinycbor amiibo reveng z hardnested ${ADDITIONAL_LNK})
install(TARGETS proxmark3 DESTINATION "bin")
install(DIRECTORY cmdscripts lualibs luascripts resources dictionaries DESTINATION "share/proxmark3")
add_custom_command(OUTPUT lualibs/pm3_cmd.lua
COMMAND "awk -f pm3_cmd_h2lua.awk ../include/pm3_cmd.h > lualibs/pm3_cmd.lua"
COMMENT "Creating lualibs/pm3_cmd.lua"
)
add_custom_command(OUTPUT lualibs/mfc_default_keys.lua
COMMAND "awk -f default_keys_dic2lua.awk mfc_default_keys.dic > lualibs/mfc_default_keys.lua"
COMMENT "Creating lualibs/mfc_default_keys.lua"
)
#"make package" will trigger this
SET(CPACK_GENERATOR "DEB")
SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Iceman")
INCLUDE(CPack)

View file

@ -17,7 +17,7 @@ include ../Makefile.defs
INSTALLBIN = proxmark3
INSTALLSHARE = cmdscripts lualibs luascripts resources dictionaries
VPATH = ../common src/uart src deps
VPATH = ../common src
vpath %.dic dictionaries
OBJDIR = obj
@ -42,6 +42,10 @@ REVENGPATH = ./deps/reveng
REVENGLIB = $(REVENGPATH)/libreveng.a
AMIIBOLIBPATH = ./deps/amiitool
AMIIBOLIB = $(AMIIBOLIBPATH)/libamiibo.a
HARDNESTEDPATH = ./deps/hardnested
HARDNESTEDLIB = $(HARDNESTEDPATH)/libhardnested.a
CLIPARSERPATH = ./deps/cliparser
CLIPARSERLIB = $(CLIPARSERPATH)/libcliparser.a
# common libraries
MBEDTLSLIBPATH = ../common/mbedtls
@ -49,17 +53,19 @@ MBEDTLSLIB = $(OBJDIR)/libmbedtls.a
ZLIBPATH = ../common/zlib
ZLIB = $(OBJDIR)/libz.a
LIBS = -I$(LUALIBPATH) -I$(MBEDTLSLIBPATH) -I$(JANSSONLIBPATH) -I$(CBORLIBPATH) -I$(ZLIBPATH) -I$(REVENGPATH) -I$(AMIIBOLIBPATH)
INCLUDES_CLIENT = -I./src -I./deps -I../include -I../common -I./deps/cliparser -I./src/uart $(LIBS)
CFLAGS ?= -Wall -Werror -g -O3
LIBS = -I$(LUALIBPATH) -I$(MBEDTLSLIBPATH) -I$(JANSSONLIBPATH) -I$(CBORLIBPATH) -I$(ZLIBPATH) -I$(REVENGPATH) -I$(AMIIBOLIBPATH) -I$(HARDNESTEDPATH) -I$(CLIPARSERPATH)
INCLUDES_CLIENT = -I./src -I../include -I../common -I../common_fpga $(LIBS)
CFLAGS ?= -Wall -Werror -O3
# We cannot just use CFLAGS+=... because it has impact on sub-makes if CFLAGS is defined in env:
PM3CFLAGS = $(CFLAGS) -std=c99 -D_ISOC99_SOURCE $(INCLUDES_CLIENT)
# WIP Testing
#PM3CFLAGS = $(CFLAGS) -std=c11 -pedantic $(INCLUDES_CLIENT)
PREFIX ?= /usr/local
ifneq (,$(findstring MINGW,$(platform)))
PM3CFLAGS += -mno-ms-bitfields -fexec-charset=cp850
endif
CXXFLAGS ?= -Wall -Werror -O3
PM3CXXFLAGS = $(CXXFLAGS) -I../include -I/.deps/cliparser
PM3CXXFLAGS = $(CXXFLAGS) -I../include
LUAPLATFORM = generic
ifneq (,$(findstring MINGW,$(platform)))
@ -112,6 +118,7 @@ ifneq ($(QTLDLIBS),)
QTGUISRCS = proxgui.cpp proxguiqt.cpp proxguiqt.moc.cpp
QTGUIOBJS = $(OBJDIR)/proxgui.o $(OBJDIR)/proxguiqt.o $(OBJDIR)/proxguiqt.moc.o
PM3CFLAGS += -DHAVE_GUI
PM3CXXFLAGS += -DQT_NO_DEBUG
else
QTGUISRCS = guidummy.cpp
QTGUIOBJS = $(OBJDIR)/guidummy.o
@ -122,8 +129,8 @@ DEPFLAGS = -MT $@ -MMD -MP -MF $(OBJDIR)/$*.Td
# make temporary to final dependency files after successful compilation
POSTCOMPILE = $(MV) -f $(OBJDIR)/$*.Td $(OBJDIR)/$*.d && $(TOUCH) $@
CORESRCS = uart_posix.c \
uart_win32.c \
CORESRCS = uart/uart_posix.c \
uart/uart_win32.c \
ui.c \
commonutil.c \
util.c \
@ -145,8 +152,6 @@ CMDSRCS = crapto1/crapto1.c \
crypto/asn1dump.c \
crypto/libpcrypto.c\
crypto/asn1utils.c\
cliparser/argtable3.c\
cliparser/cliparser.c\
loclass/cipher.c \
loclass/cipherutils.c \
loclass/ikeys.c \
@ -201,7 +206,6 @@ CMDSRCS = crapto1/crapto1.c \
cmdhfmfu.c \
cmdhfmfp.c \
cmdhfmfhard.c \
deps/hardnested/hardnested_bruteforce.c \
cmdhfmfdes.c \
cmdhftopaz.c \
cmdhffido.c \
@ -257,48 +261,16 @@ CMDSRCS = crapto1/crapto1.c \
cardhelper.c \
preferences.c
cpu_arch = $(shell uname -m)
ifneq ($(findstring 86, $(cpu_arch)), )
MULTIARCHSRCS = deps/hardnested/hardnested_bf_core.c deps/hardnested/hardnested_bitarray_core.c
endif
ifneq ($(findstring amd64, $(cpu_arch)), )
MULTIARCHSRCS = deps/hardnested/hardnested_bf_core.c deps/hardnested/hardnested_bitarray_core.c
endif
ifeq ($(MULTIARCHSRCS), )
CMDSRCS += deps/hardnested/hardnested_bf_core.c deps/hardnested/hardnested_bitarray_core.c
endif
COREOBJS = $(CORESRCS:%.c=$(OBJDIR)/%.o)
CMDOBJS = $(CMDSRCS:%.c=$(OBJDIR)/%.o)
OBJCOBJS = $(OBJCSRCS:%.m=$(OBJDIR)/%.o)
MULTIARCHOBJS = $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_NOSIMD.o) \
$(MULTIARCHSRCS:%.c=$(OBJDIR)/%_MMX.o) \
$(MULTIARCHSRCS:%.c=$(OBJDIR)/%_SSE2.o) \
$(MULTIARCHSRCS:%.c=$(OBJDIR)/%_AVX.o) \
$(MULTIARCHSRCS:%.c=$(OBJDIR)/%_AVX2.o)
SUPPORTS_AVX512 := $(shell echo | gcc -E -mavx512f - > /dev/null 2>&1 && echo "True" )
HARD_SWITCH_NOSIMD = -mno-mmx -mno-sse2 -mno-avx -mno-avx2
HARD_SWITCH_MMX = -mmmx -mno-sse2 -mno-avx -mno-avx2
HARD_SWITCH_SSE2 = -mmmx -msse2 -mno-avx -mno-avx2
HARD_SWITCH_AVX = -mmmx -msse2 -mavx -mno-avx2
HARD_SWITCH_AVX2 = -mmmx -msse2 -mavx -mavx2
HARD_SWITCH_AVX512 = -mmmx -msse2 -mavx -mavx2 -mavx512f
ifeq "$(SUPPORTS_AVX512)" "True"
HARD_SWITCH_NOSIMD += -mno-avx512f
HARD_SWITCH_MMX += -mno-avx512f
HARD_SWITCH_SSE2 += -mno-avx512f
HARD_SWITCH_AVX += -mno-avx512f
HARD_SWITCH_AVX2 += -mno-avx512f
MULTIARCHOBJS += $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_AVX512.o)
endif
BINS = proxmark3
CLEAN = $(BINS) *.moc.cpp ui/ui_overlays.h lualibs/pm3_cmd.lua lualibs/mfc_default_keys.lua
# transition: make sure old flasher is gone too
CLEAN += flasher
CLEAN = $(BINS) src/*.moc.cpp src/ui/ui_overlays.h lualibs/pm3_cmd.lua lualibs/mfc_default_keys.lua
# transition: cleaning also old path stuff
CLEAN += flasher *.moc.cpp ui/ui_overlays.h
# need to assign dependancies to build these first...
all: $(BINS)
@ -306,10 +278,10 @@ all: $(BINS)
all-static: LDLIBS:=-static $(LDLIBS)
all-static: $(BINS)
proxmark3: LDLIBS+=$(LUALIB) $(JANSSONLIB) $(MBEDTLSLIB) $(CBORLIB) $(ZLIB) $(REVENGLIB) $(AMIIBOLIB) $(QTLDLIBS)
proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(LUALIB) $(JANSSONLIB) $(CBORLIB) $(REVENGLIB) $(MBEDTLSLIB) $(ZLIB) $(AMIIBOLIB) lualibs/pm3_cmd.lua lualibs/mfc_default_keys.lua
proxmark3: LDLIBS+=$(LUALIB) $(JANSSONLIB) $(MBEDTLSLIB) $(CBORLIB) $(ZLIB) $(REVENGLIB) $(AMIIBOLIB) $(HARDNESTEDLIB) $(CLIPARSERLIB) $(QTLDLIBS)
proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(LUALIB) $(JANSSONLIB) $(CBORLIB) $(REVENGLIB) $(MBEDTLSLIB) $(ZLIB) $(AMIIBOLIB) $(HARDNESTEDLIB) $(CLIPARSERLIB) lualibs/pm3_cmd.lua lualibs/mfc_default_keys.lua
$(info [=] LD $@)
$(Q)$(LD) $(LDFLAGS) $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(LDLIBS) -o $@
$(Q)$(LD) $(LDFLAGS) $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(LDLIBS) -o $@
src/proxgui.cpp: src/ui/ui_overlays.h
@ -337,6 +309,8 @@ clean:
$(Q)$(MAKE) --no-print-directory -C $(CBORLIBPATH) clean
$(Q)$(MAKE) --no-print-directory -C $(REVENGPATH) clean
$(Q)$(MAKE) --no-print-directory -C $(AMIIBOLIBPATH) clean
$(Q)$(MAKE) --no-print-directory -C $(HARDNESTEDPATH) clean
$(Q)$(MAKE) --no-print-directory -C $(CLIPARSERPATH) clean
install: all
$(info [@] Installing client to $(DESTDIR)$(PREFIX)...)
@ -381,10 +355,18 @@ $(REVENGLIB):
$(info [*] MAKE reveng)
$(Q)$(MAKE) --no-print-directory -C $(REVENGPATH) all
$(HARDNESTEDLIB):
$(info [*] MAKE hardnested)
$(Q)$(MAKE) --no-print-directory -C $(HARDNESTEDPATH) all
$(AMIIBOLIB):
$(info [*] MAKE amiibo)
$(Q)$(MAKE) --no-print-directory -C $(AMIIBOLIBPATH) all
$(CLIPARSERLIB):
$(info [*] MAKE cliparser)
$(Q)$(MAKE) --no-print-directory -C $(CLIPARSERPATH) all
# common libraries:
$(MBEDTLSLIB):
$(info [*] MAKE mbedtls)
@ -399,42 +381,6 @@ $(ZLIB):
# easy printing of MAKE VARIABLES
print-%: ; @echo $* = $($*)
$(OBJDIR)/%_NOSIMD.o : %.c $(OBJDIR)/%_NOSIMD.d
$(info [-] CC(NOSIMD) $<)
$(Q)$(MKDIR) $(dir $@)
$(Q)$(CC) $(DEPFLAGS:%.Td=%_NOSIMD.Td) $(PM3CFLAGS) $(HARD_SWITCH_NOSIMD) -c -o $@ $<
$(Q)$(MV) -f $(OBJDIR)/$*_NOSIMD.Td $(OBJDIR)/$*_NOSIMD.d && $(TOUCH) $@
$(OBJDIR)/%_MMX.o : %.c $(OBJDIR)/%_MMX.d
$(info [-] CC(MMX) $<)
$(Q)$(MKDIR) $(dir $@)
$(Q)$(CC) $(DEPFLAGS:%.Td=%_MMX.Td) $(PM3CFLAGS) $(HARD_SWITCH_MMX) -c -o $@ $<
$(Q)$(MV) -f $(OBJDIR)/$*_MMX.Td $(OBJDIR)/$*_MMX.d && $(TOUCH) $@
$(OBJDIR)/%_SSE2.o : %.c $(OBJDIR)/%_SSE2.d
$(info [-] CC(SSE2) $<)
$(Q)$(MKDIR) $(dir $@)
$(Q)$(CC) $(DEPFLAGS:%.Td=%_SSE2.Td) $(PM3CFLAGS) $(HARD_SWITCH_SSE2) -c -o $@ $<
$(Q)$(MV) -f $(OBJDIR)/$*_SSE2.Td $(OBJDIR)/$*_SSE2.d && $(TOUCH) $@
$(OBJDIR)/%_AVX.o : %.c $(OBJDIR)/%_AVX.d
$(info [-] CC(AVX) $<)
$(Q)$(MKDIR) $(dir $@)
$(Q)$(CC) $(DEPFLAGS:%.Td=%_AVX.Td) $(PM3CFLAGS) $(HARD_SWITCH_AVX) -c -o $@ $<
$(Q)$(MV) -f $(OBJDIR)/$*_AVX.Td $(OBJDIR)/$*_AVX.d && $(TOUCH) $@
$(OBJDIR)/%_AVX2.o : %.c $(OBJDIR)/%_AVX2.d
$(info [-] CC(AVX2) $<)
$(Q)$(MKDIR) $(dir $@)
$(Q)$(CC) $(DEPFLAGS:%.Td=%_AVX2.Td) $(PM3CFLAGS) $(HARD_SWITCH_AVX2) -c -o $@ $<
$(Q)$(MV) -f $(OBJDIR)/$*_AVX2.Td $(OBJDIR)/$*_AVX2.d && $(TOUCH) $@
$(OBJDIR)/%_AVX512.o : %.c $(OBJDIR)/%_AVX512.d
$(info [-] CC(AVX512) $<)
$(Q)$(MKDIR) $(dir $@)
$(Q)$(CC) $(DEPFLAGS:%.Td=%_AVX512.Td) $(PM3CFLAGS) $(HARD_SWITCH_AVX512) -c -o $@ $<
$(Q)$(MV) -f $(OBJDIR)/$*_AVX512.Td $(OBJDIR)/$*_AVX512.d && $(TOUCH) $@
%.o: %.c
$(OBJDIR)/%.o : %.c $(OBJDIR)/%.d
$(info [-] CC $<)
@ -456,8 +402,7 @@ $(OBJDIR)/%.o : %.m $(OBJDIR)/%.d
$(Q)$(CC) $(DEPFLAGS) $(PM3CFLAGS) -c -o $@ $<
$(Q)$(POSTCOMPILE)
DEPENDENCY_FILES = $(patsubst %.c, $(OBJDIR)/%.d, $(CORESRCS) $(CMDSRCS) $(REVENGSRCS)) \
$(patsubst %.o, %.d, $(MULTIARCHOBJS)) \
DEPENDENCY_FILES = $(patsubst %.c, $(OBJDIR)/%.d, $(CORESRCS) $(CMDSRCS)) \
$(patsubst %.cpp, $(OBJDIR)/%.d, $(QTGUISRCS)) \
$(patsubst %.m, $(OBJDIR)/%.d, $(OBJCSRCS)) \
$(OBJDIR)/proxmark3.d

168
client/cmake/FindSSE.cmake Normal file
View file

@ -0,0 +1,168 @@
# Check if SSE/AVX instructions are available on the machine where
# the project is compiled.
IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
EXEC_PROGRAM(cat ARGS "/proc/cpuinfo" OUTPUT_VARIABLE CPUINFO)
STRING(REGEX REPLACE "^.*(sse2).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "sse2" "${SSE_THERE}" SSE2_TRUE)
IF (SSE2_TRUE)
set(SSE2_FOUND true CACHE BOOL "SSE2 available on host")
ELSE (SSE2_TRUE)
set(SSE2_FOUND false CACHE BOOL "SSE2 available on host")
ENDIF (SSE2_TRUE)
# /proc/cpuinfo apparently omits sse3 :(
STRING(REGEX REPLACE "^.*[^s](sse3).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "sse3" "${SSE_THERE}" SSE3_TRUE)
IF (NOT SSE3_TRUE)
STRING(REGEX REPLACE "^.*(T2300).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "T2300" "${SSE_THERE}" SSE3_TRUE)
ENDIF (NOT SSE3_TRUE)
STRING(REGEX REPLACE "^.*(ssse3).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "ssse3" "${SSE_THERE}" SSSE3_TRUE)
IF (SSE3_TRUE OR SSSE3_TRUE)
set(SSE3_FOUND true CACHE BOOL "SSE3 available on host")
ELSE (SSE3_TRUE OR SSSE3_TRUE)
set(SSE3_FOUND false CACHE BOOL "SSE3 available on host")
ENDIF (SSE3_TRUE OR SSSE3_TRUE)
IF (SSSE3_TRUE)
set(SSSE3_FOUND true CACHE BOOL "SSSE3 available on host")
ELSE (SSSE3_TRUE)
set(SSSE3_FOUND false CACHE BOOL "SSSE3 available on host")
ENDIF (SSSE3_TRUE)
STRING(REGEX REPLACE "^.*(sse4_1).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "sse4_1" "${SSE_THERE}" SSE41_TRUE)
IF (SSE41_TRUE)
set(SSE4_1_FOUND true CACHE BOOL "SSE4.1 available on host")
ELSE (SSE41_TRUE)
set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host")
ENDIF (SSE41_TRUE)
STRING(REGEX REPLACE "^.*(avx).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "avx" "${SSE_THERE}" AVX_TRUE)
IF (AVX_TRUE)
set(AVX_FOUND true CACHE BOOL "AVX available on host")
ELSE (AVX_TRUE)
set(AVX_FOUND false CACHE BOOL "AVX available on host")
ENDIF (AVX_TRUE)
STRING(REGEX REPLACE "^.*(avx2).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "avx2" "${SSE_THERE}" AVX2_TRUE)
IF (AVX2_TRUE)
set(AVX2_FOUND true CACHE BOOL "AVX2 available on host")
ELSE (AVX2_TRUE)
set(AVX2_FOUND false CACHE BOOL "AVX2 available on host")
ENDIF (AVX2_TRUE)
STRING(REGEX REPLACE "^.*(avx512).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "avx512" "${SSE_THERE}" AVX2_TRUE)
IF (AVX512_TRUE)
set(AVX512_FOUND true CACHE BOOL "AVX512 available on host")
ELSE (AVX2_TRUE)
set(AVX512_FOUND false CACHE BOOL "AVX512 available on host")
ENDIF (AVX512_TRUE)
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Darwin")
EXEC_PROGRAM("/usr/sbin/sysctl -n machdep.cpu.features" OUTPUT_VARIABLE
CPUINFO)
STRING(REGEX REPLACE "^.*[^S](SSE2).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "SSE2" "${SSE_THERE}" SSE2_TRUE)
IF (SSE2_TRUE)
set(SSE2_FOUND true CACHE BOOL "SSE2 available on host")
ELSE (SSE2_TRUE)
set(SSE2_FOUND false CACHE BOOL "SSE2 available on host")
ENDIF (SSE2_TRUE)
STRING(REGEX REPLACE "^.*[^S](SSE3).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "SSE3" "${SSE_THERE}" SSE3_TRUE)
IF (SSE3_TRUE)
set(SSE3_FOUND true CACHE BOOL "SSE3 available on host")
ELSE (SSE3_TRUE)
set(SSE3_FOUND false CACHE BOOL "SSE3 available on host")
ENDIF (SSE3_TRUE)
STRING(REGEX REPLACE "^.*(SSSE3).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "SSSE3" "${SSE_THERE}" SSSE3_TRUE)
IF (SSSE3_TRUE)
set(SSSE3_FOUND true CACHE BOOL "SSSE3 available on host")
ELSE (SSSE3_TRUE)
set(SSSE3_FOUND false CACHE BOOL "SSSE3 available on host")
ENDIF (SSSE3_TRUE)
STRING(REGEX REPLACE "^.*(SSE4.1).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "SSE4.1" "${SSE_THERE}" SSE41_TRUE)
IF (SSE41_TRUE)
set(SSE4_1_FOUND true CACHE BOOL "SSE4.1 available on host")
ELSE (SSE41_TRUE)
set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host")
ENDIF (SSE41_TRUE)
STRING(REGEX REPLACE "^.*(AVX).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "AVX" "${SSE_THERE}" AVX_TRUE)
IF (AVX_TRUE)
set(AVX_FOUND true CACHE BOOL "AVX available on host")
ELSE (AVX_TRUE)
set(AVX_FOUND false CACHE BOOL "AVX available on host")
ENDIF (AVX_TRUE)
STRING(REGEX REPLACE "^.*(AVX2).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "AVX2" "${SSE_THERE}" AVX2_TRUE)
IF (AVX2_TRUE)
set(AVX2_FOUND true CACHE BOOL "AVX2 available on host")
ELSE (AVX2_TRUE)
set(AVX2_FOUND false CACHE BOOL "AVX2 available on host")
ENDIF (AVX2_TRUE)
STRING(REGEX REPLACE "^.*(AVX512).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "AVX512" "${SSE_THERE}" AVX2_TRUE)
IF (AVX2_TRUE)
set(AVX2_FOUND true CACHE BOOL "AVX512 available on host")
ELSE (AVX2_TRUE)
set(AVX2_FOUND false CACHE BOOL "AVX512 available on host")
ENDIF (AVX2_TRUE)
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Windows")
# TODO
set(SSE2_FOUND true CACHE BOOL "SSE2 available on host")
set(SSE3_FOUND false CACHE BOOL "SSE3 available on host")
set(SSSE3_FOUND false CACHE BOOL "SSSE3 available on host")
set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host")
set(AVX_FOUND false CACHE BOOL "AVX available on host")
set(AVX2_FOUND false CACHE BOOL "AVX2 available on host")
set(AVX512_FOUND false CACHE BOOL "AVX512 available on host")
ELSE(CMAKE_SYSTEM_NAME MATCHES "Linux")
set(SSE2_FOUND true CACHE BOOL "SSE2 available on host")
set(SSE3_FOUND false CACHE BOOL "SSE3 available on host")
set(SSSE3_FOUND false CACHE BOOL "SSSE3 available on host")
set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host")
set(AVX_FOUND false CACHE BOOL "AVX available on host")
set(AVX2_FOUND false CACHE BOOL "AVX2 available on host")
set(AVX512_FOUND false CACHE BOOL "AVX512 available on host")
ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux")
if(NOT SSE2_FOUND)
MESSAGE(STATUS "Could not find hardware support for SSE2 on this machine.")
endif(NOT SSE2_FOUND)
if(NOT SSE3_FOUND)
MESSAGE(STATUS "Could not find hardware support for SSE3 on this machine.")
endif(NOT SSE3_FOUND)
if(NOT SSSE3_FOUND)
MESSAGE(STATUS "Could not find hardware support for SSSE3 on this machine.")
endif(NOT SSSE3_FOUND)
if(NOT SSE4_1_FOUND)
MESSAGE(STATUS "Could not find hardware support for SSE4.1 on this machine.")
endif(NOT SSE4_1_FOUND)
if(NOT AVX_FOUND)
MESSAGE(STATUS "Could not find hardware support for AVX on this machine.")
endif(NOT AVX_FOUND)
if(NOT AVX2_FOUND)
MESSAGE(STATUS "Could not find hardware support for AVX2 on this machine.")
endif(NOT AVX2_FOUND)
if(NOT AVX512_FOUND)
MESSAGE(STATUS "Could not find hardware support for AVX512 on this machine.")
endif(NOT AVX512_FOUND)
mark_as_advanced(SSE2_FOUND SSE3_FOUND SSSE3_FOUND SSE4_1_FOUND, AVX_FOUND, AVX2_FOUND)

View file

@ -0,0 +1,9 @@
include(cliparser.cmake)
include(tinycbor.cmake)
include(jansson.cmake)
include(lua.cmake)
include(mbedtls.cmake)
include(amiibo.cmake)
include(reveng.cmake)
include(zlib.cmake)
include(hardnested.cmake)

18
client/deps/amiibo.cmake Normal file
View file

@ -0,0 +1,18 @@
# just for testing amiitool before complete migration into a lib:
#amiitool:
#gcc $(CFLAGS) \
#amiitool.c $(MYSRCS) ../../../../common/../../commonutil.c ../ui.c -lreadline -lm ../../../../common/mbedtls/libmbedtls.a \
#-o amiitool
set_property(SOURCE PROPERTY C_STANDARD 99)
add_library(amiibo STATIC
amiitool/amiibo.c
amiitool/drbg.c
amiitool/keygen.c
)
target_include_directories(amiibo PRIVATE ../../include ../../common)
target_include_directories(amiibo INTERFACE amiitool)
target_compile_options(amiibo PRIVATE -Wall -Werror -O3)

View file

@ -9,6 +9,9 @@ MYSRCS = \
LIB_A = libamiibo.a
# Transition: remove old directories and objects
MYCLEANOLDPATH = ../../amiitool
include ../../../Makefile.host
# just for testing amiitool before complete migration into a lib:

View file

@ -0,0 +1,11 @@
add_library(cliparser STATIC
cliparser/argtable3.c
cliparser/cliparser.c
)
target_include_directories(cliparser PRIVATE
../../common
../../include
../src)
target_include_directories(cliparser INTERFACE cliparser)
target_compile_options(cliparser PRIVATE -Wall -Werror -O3)

View file

@ -0,0 +1,11 @@
MYSRCPATHS =
MYINCLUDES = -I../../../common -I../../../include -I../../src
MYCFLAGS = -std=c99 -D_ISOC99_SOURCE
MYDEFS =
MYSRCS = \
argtable3.c \
cliparser.c
LIB_A = libcliparser.a
include ../../../Makefile.host

View file

@ -0,0 +1,108 @@
set_property(SOURCE PROPERTY C_STANDARD 99)
## CPU-specific code
## These are mostly for x86-based architectures, which is not useful for many Android devices.
add_library(hardnested_nosimd OBJECT
hardnested/hardnested_bf_core.c
hardnested/hardnested_bitarray_core.c)
target_include_directories(hardnested_nosimd PRIVATE
../../common
../../include)
target_compile_options(hardnested_nosimd PRIVATE -Wall -Werror -O3)
set(X86_CPUS x86 x86_64 i686)
message(STATUS "CMAKE_SYSTEM_PROCESSOR := ${CMAKE_SYSTEM_PROCESSOR}")
if ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST X86_CPUS)
message(STATUS "Building optimised x86/x86_64 binaries")
target_compile_options(hardnested_nosimd BEFORE PRIVATE
-mno-mmx -mno-sse2 -mno-avx -mno-avx2 -mno-avx512f)
## x86 / MMX
add_library(hardnested_mmx OBJECT
hardnested/hardnested_bf_core.c
hardnested/hardnested_bitarray_core.c)
target_compile_options(hardnested_mmx PRIVATE -Wall -Werror -O3)
target_compile_options(hardnested_mmx BEFORE PRIVATE
-mmmx -mno-sse2 -mno-avx -mno-avx2 -mno-avx512f)
target_include_directories(hardnested_mmx PRIVATE
../../common
../../include)
## x86 / SSE2
add_library(hardnested_sse2 OBJECT
hardnested/hardnested_bf_core.c
hardnested/hardnested_bitarray_core.c)
target_compile_options(hardnested_sse2 PRIVATE -Wall -Werror -O3)
target_compile_options(hardnested_sse2 BEFORE PRIVATE
-mmmx -msse2 -mno-avx -mno-avx2 -mno-avx512f)
target_include_directories(hardnested_sse2 PRIVATE
../../common
../../include)
## x86 / AVX
add_library(hardnested_avx OBJECT
hardnested/hardnested_bf_core.c
hardnested/hardnested_bitarray_core.c)
target_compile_options(hardnested_avx PRIVATE -Wall -Werror -O3)
target_compile_options(hardnested_avx BEFORE PRIVATE
-mmmx -msse2 -mavx -mno-avx2 -mno-avx512f)
target_include_directories(hardnested_avx PRIVATE
../../common
../../include)
## x86 / AVX2
add_library(hardnested_avx2 OBJECT
hardnested/hardnested_bf_core.c
hardnested/hardnested_bitarray_core.c)
target_compile_options(hardnested_avx2 PRIVATE -Wall -Werror -O3)
target_compile_options(hardnested_avx2 BEFORE PRIVATE
-mmmx -msse2 -mavx -mavx2 -mno-avx512f)
target_include_directories(hardnested_avx2 PRIVATE
../../common
../../include)
## x86 / AVX512
add_library(hardnested_avx512 OBJECT
hardnested/hardnested_bf_core.c
hardnested/hardnested_bitarray_core.c)
target_compile_options(hardnested_avx512 PRIVATE -Wall -Werror -O3)
target_compile_options(hardnested_avx512 BEFORE PRIVATE
-mmmx -msse2 -mavx -mavx2 -mavx512f)
target_include_directories(hardnested_avx512 PRIVATE
../../common
../../include)
set(SIMD_TARGETS
$<TARGET_OBJECTS:hardnested_mmx>
$<TARGET_OBJECTS:hardnested_sse2>
$<TARGET_OBJECTS:hardnested_avx>
$<TARGET_OBJECTS:hardnested_avx2>
$<TARGET_OBJECTS:hardnested_avx512>)
else ()
message(STATUS "Not building optimised targets")
set(SIMD_TARGETS)
endif ()
add_library(hardnested STATIC
hardnested/hardnested_bruteforce.c
$<TARGET_OBJECTS:hardnested_nosimd>
${SIMD_TARGETS})
target_include_directories(hardnested PRIVATE
../../common
../../include
../src
jansson)
target_include_directories(hardnested INTERFACE hardnested)

View file

@ -0,0 +1,83 @@
MYSRCPATHS =
MYINCLUDES = -I../../../common -I../../../include -I../../src -I../jansson
MYCFLAGS = -std=c99 -D_ISOC99_SOURCE
MYDEFS =
MYSRCS = hardnested_bruteforce.c
cpu_arch = $(shell uname -m)
ifneq ($(findstring 86, $(cpu_arch)), )
MULTIARCHSRCS = hardnested_bf_core.c hardnested_bitarray_core.c
endif
ifneq ($(findstring amd64, $(cpu_arch)), )
MULTIARCHSRCS = hardnested_bf_core.c hardnested_bitarray_core.c
endif
ifeq ($(MULTIARCHSRCS), )
MYSRCS += hardnested_bf_core.c hardnested_bitarray_core.c
endif
LIB_A = libhardnested.a
MYOBJS = $(MYSRCS:%.c=$(OBJDIR)/%.o)
MYOBJS += $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_NOSIMD.o) \
$(MULTIARCHSRCS:%.c=$(OBJDIR)/%_MMX.o) \
$(MULTIARCHSRCS:%.c=$(OBJDIR)/%_SSE2.o) \
$(MULTIARCHSRCS:%.c=$(OBJDIR)/%_AVX.o) \
$(MULTIARCHSRCS:%.c=$(OBJDIR)/%_AVX2.o)
SUPPORTS_AVX512 := $(shell echo | gcc -E -mavx512f - > /dev/null 2>&1 && echo "True" )
HARD_SWITCH_NOSIMD = -mno-mmx -mno-sse2 -mno-avx -mno-avx2
HARD_SWITCH_MMX = -mmmx -mno-sse2 -mno-avx -mno-avx2
HARD_SWITCH_SSE2 = -mmmx -msse2 -mno-avx -mno-avx2
HARD_SWITCH_AVX = -mmmx -msse2 -mavx -mno-avx2
HARD_SWITCH_AVX2 = -mmmx -msse2 -mavx -mavx2
HARD_SWITCH_AVX512 = -mmmx -msse2 -mavx -mavx2 -mavx512f
ifeq "$(SUPPORTS_AVX512)" "True"
HARD_SWITCH_NOSIMD += -mno-avx512f
HARD_SWITCH_MMX += -mno-avx512f
HARD_SWITCH_SSE2 += -mno-avx512f
HARD_SWITCH_AVX += -mno-avx512f
HARD_SWITCH_AVX2 += -mno-avx512f
MYOBJS += $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_AVX512.o)
endif
include ../../../Makefile.host
$(OBJDIR)/%_NOSIMD.o : %.c $(OBJDIR)/%_NOSIMD.d
$(info DEBUG $<)
$(OBJDIR)/%_NOSIMD.o : %.c $(OBJDIR)/%_NOSIMD.d
$(info [-] CC(NOSIMD) $<)
$(Q)$(MKDIR) $(dir $@)
$(Q)$(CC) $(DEPFLAGS:%.Td=%_NOSIMD.Td) $(CFLAGS) $(HARD_SWITCH_NOSIMD) -c -o $@ $<
$(Q)$(MV) -f $(OBJDIR)/$*_NOSIMD.Td $(OBJDIR)/$*_NOSIMD.d && $(TOUCH) $@
$(OBJDIR)/%_MMX.o : %.c $(OBJDIR)/%_MMX.d
$(info [-] CC(MMX) $<)
$(Q)$(MKDIR) $(dir $@)
$(Q)$(CC) $(DEPFLAGS:%.Td=%_MMX.Td) $(CFLAGS) $(HARD_SWITCH_MMX) -c -o $@ $<
$(Q)$(MV) -f $(OBJDIR)/$*_MMX.Td $(OBJDIR)/$*_MMX.d && $(TOUCH) $@
$(OBJDIR)/%_SSE2.o : %.c $(OBJDIR)/%_SSE2.d
$(info [-] CC(SSE2) $<)
$(Q)$(MKDIR) $(dir $@)
$(Q)$(CC) $(DEPFLAGS:%.Td=%_SSE2.Td) $(CFLAGS) $(HARD_SWITCH_SSE2) -c -o $@ $<
$(Q)$(MV) -f $(OBJDIR)/$*_SSE2.Td $(OBJDIR)/$*_SSE2.d && $(TOUCH) $@
$(OBJDIR)/%_AVX.o : %.c $(OBJDIR)/%_AVX.d
$(info [-] CC(AVX) $<)
$(Q)$(MKDIR) $(dir $@)
$(Q)$(CC) $(DEPFLAGS:%.Td=%_AVX.Td) $(CFLAGS) $(HARD_SWITCH_AVX) -c -o $@ $<
$(Q)$(MV) -f $(OBJDIR)/$*_AVX.Td $(OBJDIR)/$*_AVX.d && $(TOUCH) $@
$(OBJDIR)/%_AVX2.o : %.c $(OBJDIR)/%_AVX2.d
$(info [-] CC(AVX2) $<)
$(Q)$(MKDIR) $(dir $@)
$(Q)$(CC) $(DEPFLAGS:%.Td=%_AVX2.Td) $(CFLAGS) $(HARD_SWITCH_AVX2) -c -o $@ $<
$(Q)$(MV) -f $(OBJDIR)/$*_AVX2.Td $(OBJDIR)/$*_AVX2.d && $(TOUCH) $@
$(OBJDIR)/%_AVX512.o : %.c $(OBJDIR)/%_AVX512.d
$(info [-] CC(AVX512) $<)
$(Q)$(MKDIR) $(dir $@)
$(Q)$(CC) $(DEPFLAGS:%.Td=%_AVX512.Td) $(CFLAGS) $(HARD_SWITCH_AVX512) -c -o $@ $<
$(Q)$(MV) -f $(OBJDIR)/$*_AVX512.Td $(OBJDIR)/$*_AVX512.d && $(TOUCH) $@

20
client/deps/jansson.cmake Normal file
View file

@ -0,0 +1,20 @@
set_property(SOURCE PROPERTY C_STANDARD 99)
add_library(jansson STATIC
jansson/dump.c
jansson/error.c
jansson/hashtable.c
jansson/hashtable_seed.c
jansson/load.c
jansson/memory.c
jansson/pack_unpack.c
jansson/strbuffer.c
jansson/strconv.c
jansson/utf.c
jansson/path.c
jansson/value.c
)
target_compile_definitions(jansson PRIVATE HAVE_STDINT_H)
target_include_directories(jansson INTERFACE jansson)
target_compile_options(jansson PRIVATE -Wall -Werror -Wno-unused-function -O3)

View file

@ -18,4 +18,7 @@ MYSRCS = \
LIB_A = libjansson.a
# Transition: remove old directories and objects
MYCLEANOLDPATH = ../../jansson
include ../../../Makefile.host

View file

@ -14,6 +14,9 @@ SYSCFLAGS=
LIB_A= liblua.a
# Transition: remove old directories and objects
MYCLEANOLDPATH = ../../liblua
# Your platform. See PLATS for possible values.
PLAT= none

48
client/deps/lua.cmake Normal file
View file

@ -0,0 +1,48 @@
add_library(lua STATIC
liblua/lapi.c
liblua/lcode.c
liblua/lctype.c
liblua/ldebug.c
liblua/ldo.c
liblua/ldump.c
liblua/lfunc.c
liblua/lgc.c
liblua/llex.c
liblua/lmem.c
liblua/lobject.c
liblua/lopcodes.c
liblua/lparser.c
liblua/lstate.c
liblua/lstring.c
liblua/ltable.c
liblua/ltm.c
liblua/lundump.c
liblua/lvm.c
liblua/lzio.c
liblua/lauxlib.c
liblua/lbaselib.c
liblua/lbitlib.c
liblua/lcorolib.c
liblua/ldblib.c
liblua/liolib.c
liblua/lmathlib.c
liblua/loslib.c
liblua/lstrlib.c
liblua/ltablib.c
liblua/loadlib.c
liblua/linit.c
)
target_compile_definitions(lua PRIVATE LUA_COMPAT_ALL)
if (NOT MINGW)
if (APPLE)
target_compile_definitions(lua PRIVATE LUA_USE_MACOSX)
else (APPLE)
target_compile_definitions(lua PRIVATE LUA_USE_LINUX)
target_link_libraries(lua INTERFACE dl)
endif (APPLE)
endif (NOT MINGW)
target_include_directories(lua INTERFACE liblua)
target_compile_options(lua PRIVATE -Wall -Werror -O3)

50
client/deps/mbedtls.cmake Normal file
View file

@ -0,0 +1,50 @@
set_property(SOURCE PROPERTY C_STANDARD 99)
add_library(mbedtls STATIC
../../common/mbedtls/aes.c
../../common/mbedtls/asn1parse.c
../../common/mbedtls/asn1write.c
../../common/mbedtls/base64.c
../../common/mbedtls/bignum.c
../../common/mbedtls/ctr_drbg.c
../../common/mbedtls/entropy_poll.c
../../common/mbedtls/entropy.c
../../common/mbedtls/error.c
../../common/mbedtls/timing.c
../../common/mbedtls/ecp.c
../../common/mbedtls/ecp_curves.c
../../common/mbedtls/certs.c
../../common/mbedtls/camellia.c
../../common/mbedtls/blowfish.c
../../common/mbedtls/cipher_wrap.c
../../common/mbedtls/cipher.c
../../common/mbedtls/cmac.c
../../common/mbedtls/des.c
../../common/mbedtls/ecdsa.c
../../common/mbedtls/md.c
../../common/mbedtls/md_wrap.c
../../common/mbedtls/md5.c
../../common/mbedtls/oid.c
../../common/mbedtls/pem.c
../../common/mbedtls/arc4.c
../../common/mbedtls/pk.c
../../common/mbedtls/pk_wrap.c
../../common/mbedtls/pkwrite.c
../../common/mbedtls/pkcs5.c
../../common/mbedtls/pkcs12.c
../../common/mbedtls/pkparse.c
../../common/mbedtls/platform.c
../../common/mbedtls/platform_util.c
../../common/mbedtls/rsa.c
../../common/mbedtls/rsa_internal.c
../../common/mbedtls/sha1.c
../../common/mbedtls/sha256.c
../../common/mbedtls/sha512.c
../../common/mbedtls/threading.c
../../common/mbedtls/x509.c
../../common/mbedtls/x509_crl.c
../../common/mbedtls/x509_crt.c
)
target_include_directories(mbedtls PRIVATE ../../common)
target_compile_options(mbedtls PRIVATE -Wall -Werror -O3)

15
client/deps/reveng.cmake Normal file
View file

@ -0,0 +1,15 @@
set_property(SOURCE PROPERTY C_STANDARD 99)
add_library(reveng STATIC
reveng/bmpbit.c
reveng/cli.c
reveng/model.c
reveng/poly.c
reveng/preset.c
reveng/reveng.c
)
target_compile_definitions(reveng PRIVATE PRESETS)
target_include_directories(reveng PRIVATE ../cliparser)
target_include_directories(reveng INTERFACE reveng)
target_compile_options(reveng PRIVATE -Wall -Werror -O3)

View file

@ -4,13 +4,12 @@
# Add -DPRESETS to compile with preset models (edit config.h)
MYSRCPATHS =
MYINCLUDES = -I. -I..
MYINCLUDES = -I../cliparser
MYCFLAGS = -std=c99 -D_ISOC99_SOURCE
MYDEFS = -DPRESETS
MYSRCS = \
bmpbit.c \
cli.c \
getopt.c \
model.c \
poly.c \
preset.c \
@ -18,6 +17,9 @@ MYSRCS = \
LIB_A = libreveng.a
# Transition: remove old directories and objects
MYCLEANOLDPATH = ../../reveng
include ../../../Makefile.host
CLEAN += bmptst

View file

@ -53,7 +53,7 @@
#include <stdio.h>
#include <stdlib.h>
#include "cliparser/getopt.h"
#include "getopt.h"
#ifdef _WIN32
# include <io.h>
# include <fcntl.h>

View file

@ -1,80 +0,0 @@
/*----------------------------------------------------------------------
Replacement for Unix "getopt()", for DOS/Windows/etc.
getopt.c 1.3 2003/09/17 16:17:59
Copyright (C) 1998, 2003 by David A. Hinds -- All Rights Reserved
This file is part of ASPEX.
ASPEX is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
ASPEX is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with ASPEX; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
----------------------------------------------------------------------*/
#include <string.h>
#include <stdio.h>
#include "getopt.h"
char *optarg;
int optind = 1, opterr, optopt;
int pos = 0;
int getopt(int argc, char *argv[], const char *optstring) {
//static int pos = 0;
char *str;
if (pos == 0) {
if ((optind >= argc) || (*argv[optind] != '-'))
return EOF;
pos = 1;
if (argv[optind][pos] == '\0')
return EOF;
}
str = strchr(optstring, argv[optind][pos]);
if (str == NULL) {
optopt = argv[optind][pos];
if (opterr)
fprintf(stderr, "%s: illegal option -- %c\n", argv[0],
optopt);
return '?';
}
if (str[1] == ':') {
if (argv[optind][pos + 1] != '\0') {
optarg = &argv[optind][pos + 1];
return *str;
}
optind++;
if (optind >= argc) {
optopt = *str;
if (opterr)
fprintf(stderr, "%s: option requires an argument -- %c\n",
argv[0], optopt);
return '?';
}
optarg = argv[optind];
optind++;
pos = 0;
return *str;
} else {
pos++;
if (argv[optind][pos] == '\0') {
optind++;
pos = 0;
}
return *str;
}
}

View file

@ -1,30 +0,0 @@
/*
getopt.h 1.2 2003/09/17 16:17:59
Copyright (C) 1998, 2003 by David A. Hinds -- All Rights Reserved
This file is part of ASPEX.
ASPEX is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
ASPEX is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with ASPEX; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __GETOPT_H
#define __GETOPT_H
extern char *optarg;
extern int optind, opterr, optopt, pos;
int getopt(int argc, char *argv[], const char *optstring);
#endif

View file

@ -0,0 +1,14 @@
add_library(tinycbor STATIC
tinycbor/cborencoder.c
tinycbor/cborencoder_close_container_checked.c
tinycbor/cborerrorstrings.c
tinycbor/cborparser.c
tinycbor/cborparser_dup_string.c
tinycbor/cborpretty.c
tinycbor/cbortojson.c
tinycbor/cborvalidation.c
)
target_include_directories(tinycbor INTERFACE tinycbor)
# Strange errors on Mingw when compiling with -O3
target_compile_options(tinycbor PRIVATE -Wall -Werror -O2)

View file

@ -16,6 +16,9 @@ MYSRCS = \
LIB_A = tinycbor.a
# Transition: remove old directories and objects
MYCLEANOLDPATH = ../../tinycbor
# Strange errors on Mingw when compiling with -O3
CFLAGS ?= -Wall -Werror -O2

14
client/deps/zlib.cmake Normal file
View file

@ -0,0 +1,14 @@
set_property(SOURCE PROPERTY C_STANDARD 99)
add_library(z STATIC
../../common/zlib/deflate.c
../../common/zlib/adler32.c
../../common/zlib/trees.c
../../common/zlib/zutil.c
../../common/zlib/inflate.c
../../common/zlib/inffast.c
../../common/zlib/inftrees.c
)
target_compile_definitions(z PRIVATE Z_SOLO NO_GZIP ZLIB_PM3_TUNED)
target_compile_options(z PRIVATE -Wall -Werror -O3)

View file

@ -0,0 +1,44 @@
0000000000000000 #NXP Default DES
7544d1652bc9bd43
00000000000000000000000000000000 #NXP Default 3DES/AES
000000000000000000000000000000000000000000000000 #NXP Default 3K3DES
00112233445566778899AABBCCDDEEFF #TI TRF7970A sloa213
79702553797025537970255379702553 #TI TRF7970A sloa213
4E617468616E2E4C6920546564647920
43464F494D48504E4C4359454E528841 #NHIF
6AC292FAA1315B4D858AB3A3D7D5933A
404142434445464748494a4b4c4d4e4f
00112233445566778899aabbccddeeff
2b7e151628aed2a6abf7158809cf4f3c
fbeed618357133667c85e08f7236a8de
f7ddac306ae266ccf90bc11ee46d513b
54686973206973206D79206B65792020
ffffffffffffffffffffffffffffffff
a0a1a2a3a4a5a6a7a0a1a2a3a4a5a6a7
b0b1b2b3b4b5b6b7b0b1b2b3b4b5b6b7
b0b1b2b3b4b5b6b7b8b9babbbcbdbebf
d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7
11111111111111111111111111111111
22222222222222222222222222222222
33333333333333333333333333333333
44444444444444444444444444444444
55555555555555555555555555555555
66666666666666666666666666666666
77777777777777777777777777777777
88888888888888888888888888888888
99999999999999999999999999999999
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
cccccccccccccccccccccccccccccccc
dddddddddddddddddddddddddddddddd
eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
000102030405060708090a0b0c0d0e0f
0102030405060708090a0b0c0d0e0f10
00010203040506070809101112131415
01020304050607080910111213141516
16151413121110090807060504030201
15141312111009080706050403020100
0f0e0d0c0b0a09080706050403020100
100f0e0d0c0b0a090807060504030201
404142434445464748494a4b4c4d4e4f
303132333435363738393a3b3c3d3e3f

View file

@ -1,231 +0,0 @@
local utils = require('utils')
local getopt = require('getopt')
local read14a = require('read14a')
--[[
---Suggestions of improvement:
--- Add support another types of dumps: BIN, JSON
--- Maybe it will be not only as `mfc_gen3_writer`, like a universal dump manager.
--- Add undependence from the operation system. At the moment code not working in Linux.
--- Add more chinesse backdoors RAW commands for UID changing (find RAW for the 4 byte familiar chinese card, from native it soft: http://bit.ly/39VIDsU)
--- Hide system messages when you writing a dumps, replace it to some of like [#####----------] 40%
-- iceman notes:
-- doesn't take consideration filepaths for dump files.
-- doesn't allow A keys for authenticating when writing
-- doesn't verify that card is magic gen3.
-- doesn't take several versions of same dump ( -1, -2, -3 ) styles.
--]]
copyright = ''
author = 'Winds'
version = 'v1.0.0'
desc = [[
The script gives you a easy way to write your *.eml dumps onto normal MFC and magic Gen3 cards.
Works with both 4 and 7 bytes NXP MIFARE Classic 1K cards.
The script also has the possibility to change UID and permanent lock uid on magic Gen3 cards.
It supports the following functionality.
1. Write it to the same of current card UID.
2. Write it to magic Gen3 card.
3. Change uid to match dump on magic Gen3 card.
4. Permanent lock UID on magic Gen3 card.
5. Erase all data at the card and set the FF FF FF FF FF FF keys, and Access Conditions to 78778800.
Script works in a wizard styled way.
]]
example = [[
1. script run mfc_gen3_writer
]]
usage = [[
Select your *.eml dump from list to write to the card.
]]
-- Some globals
local DEBUG = false -- the debug flag
-------------------------------
-- Some utilities
-------------------------------
---
-- A debug printout-function
local function dbg(args)
if not DEBUG then return end
if type(args) == 'table' then
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print('###', args)
end
end
---
-- This is only meant to be used when errors occur
local function oops(err)
print('ERROR:', err)
core.clearCommandBuffer()
return nil, err
end
---
-- Usage help
local function help()
print(copyright)
print(author)
print(version)
print(desc)
print('Example usage')
print(example)
print(usage)
end
---
-- GetUID
local function GetUID()
return read14a.read(true, true).uid
end
---
--
local function dropfield()
read14a.disconnect()
core.clearCommandBuffer()
end
---
-- Wait for tag (MFC)
local function wait()
read14a.waitFor14443a()
end
---
--
local function main(args)
-- Arguments for the script
for o, a in getopt.getopt(args, 'hd') do
if o == 'h' then return help() end
if o == 'd' then DEBUG = true end
end
local files = {} -- Array for eml files
local b_keys = {} -- Array for B keys
local eml = {} -- Array for data in block 32
local num_dumps = 0 -- num of found eml dump files
local tab = string.rep('-', 64)
--
wait()
print(tab)
local length = 25
local e = 16
-- Detect 7 byte card
if string.len(GetUID()) == 14 then
length = 31
e = 22
end
dropfield()
---List all EML files in /client
local dumpEML = "find '.' -iname '*dump.eml' -type f"
local p = assert(io.popen(dumpEML))
for _ in p:lines() do
-- The length of eml file
if string.len(_) == length then
num_dumps = num_dumps + 1
-- cut UID from eml file
files[num_dumps] = string.sub(_, 9, e)
print(' '..num_dumps..' | '..files[num_dumps])
end
end
p.close()
if num_dumps == 0 then return oops("Didn't find any dump files") end
print(tab)
print(' Your card has UID '..GetUID())
print('')
print(' Select which dump to write (1 until '..num_dumps..')')
print(tab)
io.write(' --> ')
local no = tonumber(io.read())
print(tab)
print(' You have been selected card dump ' .. no .. ', with UID : '..files[no])
--- Load eml file
local dumpfile = assert(io.open('./hf-mf-' .. files[no] .. '-dump.eml', 'r'))
for _ in dumpfile:lines() do table.insert(eml, _); end
dumpfile.close()
--- Extract B key from EML file
local b = 0
for i = 1, #eml do
if (i % 4 == 0) then
repeat
b = b + 1
-- Cut key from block
b_keys[b] = string.sub(eml[i], (#eml[i] - 11), #eml[i])
until b % 4 == 0
end
end
print(tab)
dbg(b_keys)
dbg(eml)
--- Change UID on certain version of magic Gen3 card.
if (utils.confirm(' Change UID ?') == true) then
wait()
--core.console('hf 14a raw -s -c -t 2000 90f0cccc10'..tostring(eml[1]))
print('hf 14a raw -s -c -t 2000 90f0cccc10'..tostring(eml[1]))
print(tab)
print(' The new card UID : ' .. GetUID())
end
print(tab)
--- Lock UID
if (utils.confirm(' Permanent lock UID ? (card can never change uid again) ') == true) then
wait()
core.console('hf 14a raw -s -c -t 2000 90fd111100')
end
print(tab)
--- Writing blocks
local default_key = 'FFFFFFFFFFFF'
local default_key_blk = 'FFFFFFFFFFFF78778800FFFFFFFFFFFF'
local empty = string.rep('0', 32)
local cmd_wrbl = 'hf mf wrbl %d B %s %s'
if (utils.confirm(' Are you using a empty card with default key?') == true) then
wait()
for i = 1, #eml do
core.console(string.format(cmd_wrbl, (i-1), default_key, eml[i]))
end
else
print(tab)
if (utils.confirm(' Delete ALL data and write all keys to 0x'..default_key..' ?') == true) then
wait()
for i = 1, #eml do
if (i % 4 == 0) then
core.console(string.format(cmd_wrbl, (i-1), b_keys[i], default_key_blk))
else
core.console(string.format(cmd_wrbl, (i-1), b_keys[i], empty))
end
end
else
print(tab)
print('Writing to card')
wait()
for i = 1, #eml do
core.console(string.format(cmd_wrbl, (i-1), b_keys[i], eml[i]))
end
end
end
dropfield()
print(tab)
print('Done')
end
main(args)

View file

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

View file

@ -22,7 +22,7 @@
# endif /* STDIN_FILENO */
#endif /* _WIN32 */
#include "reveng/reveng.h"
#include "reveng.h"
#include "ui.h"
#include "util.h"

View file

@ -21,11 +21,11 @@
#include "graph.h" // for graph data
#include "comms.h"
#include "lfdemod.h" // for demod code
#include "../loclass/cipherutils.h" // for decimating samples in getsamples
#include "loclass/cipherutils.h" // for decimating samples in getsamples
#include "cmdlfem4x.h" // askem410xdecode
#include "fileutils.h" // searchFile
#include "mifare/ndef.h"
#include "cliparser/cliparser.h"
#include "cliparser.h"
uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
size_t DemodBufferLen = 0;

View file

@ -16,7 +16,7 @@
#include <ctype.h> // tolower
#include "cmdparser.h" // command_t
#include "cliparser/cliparser.h" // parse
#include "cliparser.h" // parse
#include "comms.h" // clearCommandBuffer
#include "lfdemod.h" // computeSignalProperties
#include "cmdhf14a.h" // ISO14443-A
@ -39,7 +39,7 @@
#include "ui.h"
#include "cmddata.h"
#include "graph.h"
#include "../../common_fpga/fpga.h"
#include "fpga.h"
static int CmdHelp(const char *Cmd);

View file

@ -19,7 +19,7 @@
#include "commonutil.h" // ARRAYLEN
#include "comms.h" // clearCommandBuffer
#include "cmdtrace.h"
#include "cliparser/cliparser.h"
#include "cliparser.h"
#include "cmdhfmf.h"
#include "cmdhfmfu.h"
#include "emv/emvcore.h"

View file

@ -29,7 +29,7 @@
#include "comms.h" // clearCommandBuffer
#include "cmdtrace.h"
#include "iso15693tools.h"
#include "../crypto/libpcrypto.h"
#include "crypto/libpcrypto.h"
#include "graph.h"
#include "crc16.h" // iso15 crc
#include "cmddata.h" // getsamples
@ -928,7 +928,7 @@ static int CmdHF15Info(const char *Cmd) {
memcpy(uid, recv + 2, sizeof(uid));
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") "---------");
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------");
PrintAndLogEx(INFO, "-------------------------------------------------------------");
PrintAndLogEx(SUCCESS, " TYPE: " _YELLOW_("%s"), getTagInfo_15(recv + 2));
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), iso15693_sprintUID(NULL, uid));

View file

@ -30,9 +30,9 @@
#include "proxmark3.h"
#include "emv/emvcore.h"
#include "emv/emvjson.h"
#include "cliparser/cliparser.h"
#include "../crypto/asn1utils.h"
#include "../crypto/libpcrypto.h"
#include "cliparser.h"
#include "crypto/asn1utils.h"
#include "crypto/libpcrypto.h"
#include "fido/cbortools.h"
#include "fido/fidocore.h"
#include "emv/dump.h"

View file

@ -19,10 +19,10 @@
#include "util_posix.h"
#include "comms.h"
#include "mbedtls/des.h"
#include "../loclass/cipherutils.h"
#include "../loclass/cipher.h"
#include "../loclass/ikeys.h"
#include "../loclass/elite_crack.h"
#include "loclass/cipherutils.h"
#include "loclass/cipher.h"
#include "loclass/ikeys.h"
#include "loclass/elite_crack.h"
#include "fileutils.h"
#include "protocols.h"
#include "cardhelper.h"

View file

@ -19,8 +19,8 @@
#include "cmdtrace.h"
#include "emv/dump.h"
#include "mifare/mifaredefault.h" // mifare default key array
#include "cliparser/cliparser.h" // argtable
#include "hardnested/hardnested_bf_core.h" // SetSIMDInstr
#include "cliparser.h" // argtable
#include "hardnested_bf_core.h" // SetSIMDInstr
#include "mifare/mad.h"
#include "mifare/ndef.h"
#include "protocols.h"

View file

@ -16,21 +16,21 @@
#include "cmdparser.h" // command_t
#include "comms.h"
#include "ui.h"
#include "cmdhw.h"
#include "cmdhf14a.h"
#include "mbedtls/des.h"
#include "mbedtls/aes.h"
#include "../crypto/libpcrypto.h"
#include "crypto/libpcrypto.h"
#include "protocols.h"
#include "mifare.h" // desfire raw command options
#include "cmdtrace.h"
#include "cliparser/cliparser.h"
#include "cliparser.h"
#include "emv/apduinfo.h" // APDU manipulation / errorcodes
#include "emv/emvcore.h" // APDU logging
#include "util_posix.h" // msleep
#include "mifare/mifare4.h" // MIFARE Authenticate / MAC
#include "mifare/desfire_crypto.h"
#include "crapto1/crapto1.h"
#include "fileutils.h"
#define MAX_KEY_LEN 24
#define MAX_KEYS_LIST_LEN 1024
struct desfire_key defaultkey = {0};
static desfirekey_t sessionkey = &defaultkey;
@ -175,17 +175,11 @@ static char *cluster_to_text(uint8_t cluster) {
case CL_ADMIN:
return "card administration";
case CL_MISC1:
return "miscellaneous applications";
case CL_MISC2:
return "miscellaneous applications";
case CL_MISC3:
return "miscellaneous applications";
case CL_MISC4:
return "miscellaneous applications";
case CL_MISC5:
return "miscellaneous applications";
case CL_MISC6:
return "miscellaneous applications";
case CL_MISC7:
return "miscellaneous applications";
case CL_AIRLINES:
@ -219,7 +213,6 @@ static char *cluster_to_text(uint8_t cluster) {
case CL_CITYCARD:
return "city card services";
case CL_ACCESS_CONTROL_1:
return "access control & security";
case CL_ACCESS_CONTROL_2:
return "access control & security";
case CL_VIGIK:
@ -289,19 +282,12 @@ static char *cluster_to_text(uint8_t cluster) {
case CL_MAIL:
return "mail";
case CL_AMISC:
return "miscellaneous applications";
case CL_AMISC1:
return "miscellaneous applications";
case CL_AMISC2:
return "miscellaneous applications";
case CL_AMISC3:
return "miscellaneous applications";
case CL_AMISC4:
return "miscellaneous applications";
case CL_AMISC5:
return "miscellaneous applications";
case CL_AMISC6:
return "miscellaneous applications";
case CL_AMISC7:
return "miscellaneous applications";
default:
@ -311,7 +297,7 @@ static char *cluster_to_text(uint8_t cluster) {
}
typedef enum {
UNKNOWN = 0,
DESFIRE_UNKNOWN = 0,
DESFIRE_MF3ICD40,
DESFIRE_EV1,
DESFIRE_EV2,
@ -653,7 +639,7 @@ static nxp_cardtype_t getCardType(uint8_t major, uint8_t minor) {
if (major == 0x11 && minor == 0x00)
return PLUS_EV1;
return UNKNOWN;
return DESFIRE_UNKNOWN;
}
int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload, bool defaultkey) {
@ -736,8 +722,7 @@ int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload,
sAPDU apdu = {0x90, subcommand, 0x00, 0x00, 0x01, data};
int res = send_desfire_cmd(&apdu, false, recv_data, &recv_len, &sw, 0, false);
if (res != PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, "Sending auth command %02X " _RED_("failed"), subcommand);
return PM3_ESOFT;
return 1;
}
} else if (payload->mode == MFDES_AUTH_PICC) {
/*cmd[0] = AUTHENTICATE;
@ -747,13 +732,11 @@ int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload,
}
if (!recv_len) {
PrintAndLogEx(ERR, "Authentication failed. Card timeout.");
return PM3_ESOFT;
return 2;
}
if (sw != status(MFDES_ADDITIONAL_FRAME)) {
PrintAndLogEx(ERR, "Authentication failed. Invalid key number.");
return PM3_ESOFT;
return 3;
}
int expectedlen = 8;
@ -762,8 +745,7 @@ int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload,
}
if (recv_len != expectedlen) {
PrintAndLogEx(ERR, "Authentication failed. Length of answer %d doesn't match algo length %d.", recv_len, expectedlen);
return PM3_ESOFT;
return 4;
}
int rndlen = recv_len;
@ -778,8 +760,7 @@ int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload,
// Part 3
if (payload->algo == MFDES_ALGO_AES) {
if (mbedtls_aes_setkey_dec(&ctx, key->data, 128) != 0) {
PrintAndLogEx(ERR, "mbedtls_aes_setkey_dec failed");
return PM3_ESOFT;
return 5;
}
mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, rndlen, IV, encRndB, RndB);
} else if (payload->algo == MFDES_ALGO_DES)
@ -848,8 +829,7 @@ int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload,
}
if (payload->algo == MFDES_ALGO_AES) {
if (mbedtls_aes_setkey_enc(&ctx, key->data, 128) != 0) {
PrintAndLogEx(ERR, "mbedtls_aes_setkey_enc failed");
return PM3_ESOFT;
return 6;
}
mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, 32, IV, tmp, both);
if (g_debugMode > 1) {
@ -866,8 +846,7 @@ int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload,
sAPDU apdu = {0x90, MFDES_ADDITIONAL_FRAME, 0x00, 0x00, bothlen, both};
int res = send_desfire_cmd(&apdu, false, recv_data, &recv_len, &sw, 0, false);
if (res != PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, "Sending auth command %02X " _RED_("failed"), subcommand);
return PM3_ESOFT;
return 7;
}
} else {
/*cmd[0] = ADDITIONAL_FRAME;
@ -881,14 +860,12 @@ int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload,
}
if (!recv_len) {
PrintAndLogEx(ERR, "Authentication failed. Card timeout.");
return PM3_ESOFT;
return 8;
}
if (payload->mode != MFDES_AUTH_PICC) {
if (sw != status(MFDES_S_OPERATION_OK)) {
PrintAndLogEx(ERR, "Authentication failed.");
return PM3_ESOFT;
return 9;
}
} else {
/*if (resp[1] != 0x00) {
@ -915,8 +892,7 @@ int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload,
tdes_nxp_receive(encRndA, encRndA, rndlen, key->data, IV, 3);
} else if (payload->mode == MFDES_AUTH_AES) {
if (mbedtls_aes_setkey_dec(&ctx, key->data, 128) != 0) {
PrintAndLogEx(ERR, "mbedtls_aes_setkey_dec failed");
return PM3_ESOFT;
return 10;
}
mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, rndlen, IV, encRndA, encRndA);
}
@ -924,12 +900,11 @@ int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload,
rol(RndA, rndlen);
for (int x = 0; x < rndlen; x++) {
if (RndA[x] != encRndA[x]) {
PrintAndLogEx(ERR, "Authentication failed. Cannot verify Session Key.");
if (g_debugMode > 1) {
PrintAndLogEx(INFO, "Expected_RndA : %s", sprint_hex(RndA, rndlen));
PrintAndLogEx(INFO, "Generated_RndA : %s", sprint_hex(encRndA, rndlen));
}
return PM3_ESOFT;
return 11;
}
}
@ -938,6 +913,45 @@ int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload,
return PM3_SUCCESS;
}
void AuthToError(int error) {
switch (error) {
case 1:
PrintAndLogEx(SUCCESS, "Sending auth command failed");
break;
case 2:
PrintAndLogEx(ERR, "Authentication failed. No data received");
break;
case 3:
PrintAndLogEx(ERR, "Authentication failed. Invalid key number.");
break;
case 4:
PrintAndLogEx(ERR, "Authentication failed. Length of answer %d doesn't match algo length %d.");
break;
case 5:
PrintAndLogEx(ERR, "mbedtls_aes_setkey_dec failed");
break;
case 6:
PrintAndLogEx(ERR, "mbedtls_aes_setkey_enc failed");
break;
case 7:
PrintAndLogEx(SUCCESS, "Sending auth command failed");
break;
case 8:
PrintAndLogEx(ERR, "Authentication failed. Card timeout.");
break;
case 9:
PrintAndLogEx(ERR, "Authentication failed.");
break;
case 10:
PrintAndLogEx(ERR, "mbedtls_aes_setkey_dec failed");
break;
case 11:
PrintAndLogEx(ERR, "Authentication failed. Cannot verify Session Key.");
break;
default:
break;
}
}
// -- test if card supports 0x0A
static int test_desfire_authenticate() {
uint8_t data[] = {0x00};
@ -3051,6 +3065,149 @@ static int DecodeFileSettings(uint8_t *src, int src_len, int maclen) {
return PM3_ESOFT;
}
static int CmdHF14ADesDump(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
DropField();
uint8_t aid[3] = {0};
uint8_t app_ids[78] = {0};
uint8_t app_ids_len = 0;
uint8_t file_ids[33] = {0};
uint8_t file_ids_len = 0;
dfname_t dfnames[255];
uint8_t dfname_count = 0;
int res = 0;
if (handler_desfire_appids(app_ids, &app_ids_len) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Can't get list of applications on tag");
DropField();
return PM3_ESOFT;
}
if (handler_desfire_dfnames(dfnames, &dfname_count) != PM3_SUCCESS) {
PrintAndLogEx(WARNING, _RED_("Can't get DF Names"));
DropField();
return PM3_ESOFT;
}
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "-- Mifare DESFire Dump ----------------------");
PrintAndLogEx(INFO, "-------------------------------------------------------------");
for (int i = 0; i < app_ids_len; i += 3) {
aid[0] = app_ids[i];
aid[1] = app_ids[i + 1];
aid[2] = app_ids[i + 2];
PrintAndLogEx(SUCCESS, " AID : " _GREEN_("%02X%02X%02X"), aid[2], aid[1], aid[0]);
PrintAndLogEx(SUCCESS, " AID Function Cluster 0x%02X: " _YELLOW_("%s"), aid[2], cluster_to_text(aid[2]));
for (int m = 0; m < dfname_count; m++) {
if (dfnames[m].aid[0] == aid[0] && dfnames[m].aid[1] == aid[1] && dfnames[m].aid[2] == aid[2]) {
PrintAndLogEx(SUCCESS, " - DF " _YELLOW_("%02X%02X") " Name : " _YELLOW_("%s"), dfnames[m].fid[1], dfnames[m].fid[0], dfnames[m].name);
}
}
uint8_t num_keys = 0;
uint8_t key_setting = 0;
res = handler_desfire_keysettings(&key_setting, &num_keys);
if (res != PM3_SUCCESS) return res;
res = handler_desfire_select_application(aid);
if (handler_desfire_fileids(file_ids, &file_ids_len) == PM3_SUCCESS) {
for (int j = file_ids_len - 1; j >= 0; j--) {
PrintAndLogEx(SUCCESS, "\n\n Fileid %d (0x%02x)", file_ids[j], file_ids[j]);
uint8_t filesettings[20] = {0};
int fileset_len = 0;
int res = handler_desfire_filesettings(file_ids[j], filesettings, &fileset_len);
int maclen = 0; // To be implemented
if (res == PM3_SUCCESS) {
//if (DecodeFileSettings(filesettings, fileset_len, maclen) != PM3_SUCCESS) {
if (fileset_len == 1 + 1 + 2 + 3 + maclen) {
int filesize = (filesettings[6] << 16) + (filesettings[5] << 8) + filesettings[4];
mfdes_data_t fdata;
fdata.fileno = file_ids[j];
memset(fdata.offset, 0, 3);
//memcpy(fdata.length,&filesettings[4],3);
memset(fdata.length, 0, 3);
uint8_t *data = (uint8_t *)malloc(filesize);
fdata.data = data;
if (data) {
res = handler_desfire_readdata(&fdata, MFDES_DATA_FILE);
if (res == PM3_SUCCESS) {
PrintAndLogEx(NORMAL, "\nOffset | Data | Ascii");
PrintAndLogEx(NORMAL, "----------------------------------------------------------------------------");
int len = le24toh(fdata.length);
for (int i = 0; i < len; i += 16) {
PrintAndLogEx(NORMAL, "%02d/0x%02X | %s| %s", i, i, sprint_hex(&fdata.data[i], len > 16 ? 16 : len), sprint_ascii(&fdata.data[i], len > 16 ? 16 : len));
}
free(data);
} else {
PrintAndLogEx(ERR, "Couldn't read value. Error %d", res);
res = handler_desfire_select_application(aid);
}
}
} else if (fileset_len == 1 + 1 + 2 + 4 + 4 + 4 + 1 + maclen) {
PrintAndLogEx(NORMAL, "\n\nValue file: 0x%0x", file_ids[j]);
mfdes_value_t value;
value.fileno = file_ids[j];
int len = 0;
res = handler_desfire_getvalue(&value, &len);
if (res == PM3_SUCCESS) {
PrintAndLogEx(NORMAL, "\nOffset | Value | Ascii");
PrintAndLogEx(NORMAL, "----------------------------------------------------------------------------");
for (int i = 0; i < len; i += 16) {
PrintAndLogEx(NORMAL, "%02d/0x%02X | %s| %s", i, i, sprint_hex(&value.value[i], len > 16 ? 16 : len), sprint_ascii(&value.value[i], len > 16 ? 16 : len));
}
} else {
PrintAndLogEx(ERR, "Couldn't read value. Error %d", res);
res = handler_desfire_select_application(aid);
}
} else if (fileset_len == 1 + 1 + 2 + 3 + 3 + 3 + maclen) {
int maxrecords = (filesettings[9] << 16) + (filesettings[8] << 8) + filesettings[7];
int filesize = (filesettings[6] << 16) + (filesettings[5] << 8) + filesettings[4];
mfdes_data_t fdata;
fdata.fileno = file_ids[j];
memset(fdata.length, 0, 3);
//memcpy(fdata.length,&filesettings[4],3);
uint8_t *data = (uint8_t *)malloc(filesize);
fdata.data = data;
if (data) {
for (int offset = 0; offset < maxrecords; offset++) {
PrintAndLogEx(NORMAL, "\n\nRecord offset: %024x", offset);
memset(data, 0, filesize);
fdata.offset[0] = offset & 0xFF;
fdata.offset[1] = (offset >> 8) & 0xFF;
fdata.offset[2] = (offset >> 16) & 0xFF;
res = handler_desfire_readdata(&fdata, MFDES_RECORD_FILE);
if (res == PM3_SUCCESS) {
PrintAndLogEx(NORMAL, "\nOffset | Data | Ascii");
PrintAndLogEx(NORMAL, "----------------------------------------------------------------------------");
int len = le24toh(fdata.length);
for (int i = 0; i < len; i += 16) {
PrintAndLogEx(NORMAL, "%02d/0x%02X | %s| %s", i, i, sprint_hex(&fdata.data[i], len > 16 ? 16 : len), sprint_ascii(&fdata.data[i], len > 16 ? 16 : len));
}
} else {
res = handler_desfire_select_application(aid);
}
}
free(data);
}
}
}
}
}
}
PrintAndLogEx(INFO, "-------------------------------------------------------------");
DropField();
return PM3_SUCCESS;
}
static int CmdHF14ADesEnumApplications(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
DropField();
@ -3305,17 +3462,523 @@ static int CmdHF14ADesAuth(const char *Cmd) {
}
*/
mfdes_auth_res_t rpayload;
if (handler_desfire_auth(&payload, &rpayload, usedefaultkey) == PM3_SUCCESS) {
int error = handler_desfire_auth(&payload, &rpayload, usedefaultkey);
if (error == PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, " Key : " _GREEN_("%s"), sprint_hex(key, keylength));
PrintAndLogEx(SUCCESS, " SESSION : " _GREEN_("%s"), sprint_hex(rpayload.sessionkey, keylength));
PrintAndLogEx(INFO, "-------------------------------------------------------------");
} else {
AuthToError(error);
return PM3_ESOFT;
}
PrintAndLogEx(INFO, "-------------------------------------------------------------");
return PM3_SUCCESS;
}
void DesFill2bPattern(uint8_t deskeyList[MAX_KEYS_LIST_LEN][8], size_t *deskeyListLen, uint8_t aeskeyList[MAX_KEYS_LIST_LEN][16], size_t *aeskeyListLen, uint8_t k3kkeyList[MAX_KEYS_LIST_LEN][24], size_t *k3kkeyListLen, uint32_t *startPattern) {
for (uint32_t pt = *startPattern; pt < 0x10000; pt++) {
if (*deskeyListLen != MAX_KEYS_LIST_LEN) {
deskeyList[*deskeyListLen][0] = (pt >> 8) & 0xff;
deskeyList[*deskeyListLen][1] = pt & 0xff;
memcpy(&deskeyList[*deskeyListLen][2], &deskeyList[*deskeyListLen][0], 2);
memcpy(&deskeyList[*deskeyListLen][4], &deskeyList[*deskeyListLen][0], 4);
(*deskeyListLen)++;
}
if (*aeskeyListLen != MAX_KEYS_LIST_LEN) {
aeskeyList[*aeskeyListLen][0] = (pt >> 8) & 0xff;
aeskeyList[*aeskeyListLen][1] = pt & 0xff;
memcpy(&aeskeyList[*aeskeyListLen][2], &aeskeyList[*aeskeyListLen][0], 2);
memcpy(&aeskeyList[*aeskeyListLen][4], &aeskeyList[*aeskeyListLen][0], 4);
memcpy(&aeskeyList[*aeskeyListLen][8], &aeskeyList[*aeskeyListLen][0], 8);
(*aeskeyListLen)++;
}
if (*k3kkeyListLen != MAX_KEYS_LIST_LEN) {
k3kkeyList[*k3kkeyListLen][0] = (pt >> 8) & 0xff;
k3kkeyList[*k3kkeyListLen][1] = pt & 0xff;
memcpy(&k3kkeyList[*k3kkeyListLen][2], &k3kkeyList[*k3kkeyListLen][0], 2);
memcpy(&k3kkeyList[*k3kkeyListLen][4], &k3kkeyList[*k3kkeyListLen][0], 4);
memcpy(&k3kkeyList[*k3kkeyListLen][8], &k3kkeyList[*k3kkeyListLen][0], 8);
memcpy(&k3kkeyList[*k3kkeyListLen][16], &k3kkeyList[*k3kkeyListLen][0], 4);
(*k3kkeyListLen)++;
}
*startPattern = pt;
if ((*deskeyListLen == MAX_KEYS_LIST_LEN) && (*aeskeyListLen == MAX_KEYS_LIST_LEN) && (*k3kkeyListLen == MAX_KEYS_LIST_LEN))
break;
}
(*startPattern)++;
}
static int AuthCheckDesfire(uint8_t *aid, uint8_t deskeyList[MAX_KEYS_LIST_LEN][8], size_t deskeyListLen, uint8_t aeskeyList[MAX_KEYS_LIST_LEN][16], size_t aeskeyListLen, uint8_t k3kkeyList[MAX_KEYS_LIST_LEN][24], size_t k3kkeyListLen, uint8_t foundKeys[4][0xE][24 + 1], bool *result) {
int res = handler_desfire_select_application(aid);
if (res != PM3_SUCCESS) {
PrintAndLogEx(ERR, "AID %X does not exist.");
return res;
}
int usedkeys[0xF] = {0};
bool des = false;
bool tdes = false;
bool aes = false;
bool k3kdes = false;
if (memcmp(aid, "\x00\x00\x00", 3) != 0) {
uint8_t file_ids[33] = {0};
uint8_t file_ids_len = 0;
// Get File IDs
if (handler_desfire_fileids(file_ids, &file_ids_len) == PM3_SUCCESS) {
for (int j = file_ids_len - 1; j >= 0; j--) {
uint8_t filesettings[20] = {0};
int fileset_len = 0;
res = handler_desfire_filesettings(file_ids[j], filesettings, &fileset_len);
if (res == PM3_SUCCESS) {
uint16_t accrights = (filesettings[3] << 8) + filesettings[2];
int change_access_rights = accrights & 0xF;
int read_write_access = (accrights >> 4) & 0xF;
int write_access = (accrights >> 8) & 0xF;
int read_access = (accrights >> 12) & 0xF;
if (change_access_rights == 0xE) change_access_rights = 0x0;
if (read_write_access == 0xE) read_write_access = 0x0;
if (write_access == 0xE) write_access = 0x0;
if (read_access == 0xE) read_access = 0x0;
usedkeys[change_access_rights] = 1;
usedkeys[read_write_access] = 1;
usedkeys[write_access] = 1;
usedkeys[read_access] = 1;
if (res == PM3_SUCCESS) {
switch (fileset_len >> 6) {
case 0:
des = true;
tdes = true;
break;
case 1:
k3kdes = true;
break;
case 2:
aes = true;
break;
default:
break;
}
}
}
}
if (file_ids_len == 0) {
for (int z = 0; z < 0xE; z++) {
usedkeys[z] = 1;
des = true;
tdes = true;
aes = true;
k3kdes = true;
}
}
}
} else des = true;
int error = PM3_SUCCESS;
bool badlen = false;
mfdes_authinput_t payload;
uint32_t curaid = (aid[0] & 0xFF) + ((aid[1] & 0xFF) << 8) + ((aid[2] & 0xFF) << 16);
if (des) {
for (int keyno = 0; keyno < 0xE; keyno++)
if (usedkeys[keyno] == 1 && foundKeys[0][keyno][0] == 0) {
for (int curkey = 0; curkey < deskeyListLen; curkey++) {
payload.keylen = 8;
memcpy(payload.key, deskeyList[curkey], 8);
payload.mode = MFDES_AUTH_DES;
payload.algo = MFDES_ALGO_DES;
payload.keyno = keyno;
mfdes_auth_res_t rpayload;
error = handler_desfire_auth(&payload, &rpayload, false);
if (error == PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, "AID 0x%06X, Found DES Key %d : " _GREEN_("%s"), curaid, keyno, sprint_hex(deskeyList[curkey], 8));
foundKeys[0][keyno][0] = 0x01;
*result = true;
memcpy(&foundKeys[0][keyno][1], deskeyList[curkey], 8);
break;
} else if (error < 7) {
badlen = true;
DropField();
res = handler_desfire_select_application(aid);
if (res != PM3_SUCCESS) {
PrintAndLogEx(ERR, "AID %X does not exist.");
return res;
}
break;
}
}
if (badlen == true) {
badlen = false;
break;
}
}
}
if (tdes) {
for (int keyno = 0; keyno < 0xE; keyno++)
if (usedkeys[keyno] == 1 && foundKeys[1][keyno][0] == 0) {
for (int curkey = 0; curkey < aeskeyListLen; curkey++) {
payload.keylen = 16;
memcpy(payload.key, aeskeyList[curkey], 16);
payload.mode = MFDES_AUTH_DES;
payload.algo = MFDES_ALGO_3DES;
payload.keyno = keyno;
mfdes_auth_res_t rpayload;
error = handler_desfire_auth(&payload, &rpayload, false);
if (error == PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, "AID 0x%06X, Found 3DES Key %d : " _GREEN_("%s"), curaid, keyno, sprint_hex(aeskeyList[curkey], 16));
foundKeys[1][keyno][0] = 0x01;
*result = true;
memcpy(&foundKeys[1][keyno][1], aeskeyList[curkey], 16);
break;
} else if (error < 7) {
badlen = true;
DropField();
res = handler_desfire_select_application(aid);
if (res != PM3_SUCCESS) {
PrintAndLogEx(ERR, "AID %X does not exist.");
return res;
}
break;
}
}
if (badlen == true) {
badlen = false;
break;
}
}
}
if (aes) {
for (int keyno = 0; keyno < 0xE; keyno++)
if (usedkeys[keyno] == 1 && foundKeys[2][keyno][0] == 0) {
for (int curkey = 0; curkey < aeskeyListLen; curkey++) {
payload.keylen = 16;
memcpy(payload.key, aeskeyList[curkey], 16);
payload.mode = MFDES_AUTH_AES;
payload.algo = MFDES_ALGO_AES;
payload.keyno = keyno;
mfdes_auth_res_t rpayload;
error = handler_desfire_auth(&payload, &rpayload, false);
if (error == PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, "AID 0x%06X, Found AES Key %d : " _GREEN_("%s"), curaid, keyno, sprint_hex(aeskeyList[curkey], 16));
foundKeys[2][keyno][0] = 0x01;
*result = true;
memcpy(&foundKeys[2][keyno][1], aeskeyList[curkey], 16);
break;
} else if (error < 7) {
badlen = true;
DropField();
res = handler_desfire_select_application(aid);
if (res != PM3_SUCCESS) {
PrintAndLogEx(ERR, "AID %X does not exist.");
return res;
}
break;
}
}
if (badlen == true) {
badlen = false;
break;
}
}
}
if (k3kdes) {
for (int keyno = 0; keyno < 0xE; keyno++)
if (usedkeys[keyno] == 1 && foundKeys[3][keyno][0] == 0) {
for (int curkey = 0; curkey < k3kkeyListLen; curkey++) {
payload.keylen = 24;
memcpy(payload.key, k3kkeyList[curkey], 24);
payload.mode = MFDES_AUTH_ISO;
payload.algo = MFDES_ALGO_3K3DES;
payload.keyno = keyno;
mfdes_auth_res_t rpayload;
error = handler_desfire_auth(&payload, &rpayload, false);
if (error == PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, "AID 0x%06X, Found 3K3 Key %d : " _GREEN_("%s"), curaid, keyno, sprint_hex(k3kkeyList[curkey], 24));
foundKeys[3][keyno][0] = 0x01;
*result = true;
memcpy(&foundKeys[3][keyno][1], k3kkeyList[curkey], 16);
break;
} else if (error < 7) {
badlen = true;
DropField();
res = handler_desfire_select_application(aid);
if (res != PM3_SUCCESS) {
PrintAndLogEx(ERR, "AID %X does not exist.");
return res;
}
break;
}
}
if (badlen == true) {
badlen = false;
break;
}
}
}
DropField();
return PM3_SUCCESS;
}
static int CmdHF14aDesChk(const char *Cmd) {
int res;
uint8_t deskeyList[MAX_KEYS_LIST_LEN][8] = {{0}};
uint8_t aeskeyList[MAX_KEYS_LIST_LEN][16] = {{0}};
uint8_t k3kkeyList[MAX_KEYS_LIST_LEN][MAX_KEY_LEN] = {{0}};
size_t deskeyListLen = 0;
size_t aeskeyListLen = 0;
size_t k3kkeyListLen = 0;
uint8_t foundKeys[4][0xE][24 + 1] = {{{0}}};
CLIParserInit("hf mfdes chk",
"Checks keys with Mifare Desfire card.",
"Usage:\n"
" hf mfdes chk -a 123456 -k 000102030405060708090a0b0c0d0e0f -> check key on aid 0x123456\n"
" hf mfdes chk -d mfdes_default_keys -> check keys from dictionary against all existing aid on card\n"
" hf mfdes chk -d mfdes_default_keys -a 123456 -> check keys from dictionary against aid 0x123456\n"
" hf mfdes chk -a 123456 --pattern1b -j keys -> check all 1-byte keys pattern on aid 0x123456 and save found keys to json\n"
" hf mfdes chk -a 123456 --pattern2b --startp2b FA00 -> check all 2-byte keys pattern on aid 0x123456. Start from key FA00FA00...FA00\n");
void *argtable[] = {
arg_param_begin,
arg_strx0("aA", "aid", "<aid>", "Use specific AID (3 hex bytes, big endian)"),
arg_str0("kK", "key", "<Key>", "Key for checking (HEX 16 bytes)"),
arg_str0("dD", "dict", "<file>", "File with keys dictionary"),
arg_lit0(NULL, "pattern1b", "Check all 1-byte combinations of key (0000...0000, 0101...0101, 0202...0202, ...)"),
arg_lit0(NULL, "pattern2b", "Check all 2-byte combinations of key (0000...0000, 0001...0001, 0002...0002, ...)"),
arg_str0(NULL, "startp2b", "<Pattern>", "Start key (2-byte HEX) for 2-byte search (use with `--pattern2b`)"),
arg_str0("jJ", "json", "<file>", "Json file to save keys"),
arg_lit0("vV", "verbose", "Verbose mode."),
arg_param_end
};
CLIExecWithReturn(Cmd, argtable, false);
int aidlength = 0;
uint8_t aid[3] = {0};
CLIGetHexWithReturn(1, aid, &aidlength);
swap24(aid);
uint8_t vkey[16] = {0};
int vkeylen = 0;
CLIGetHexWithReturn(2, vkey, &vkeylen);
if (vkeylen > 0) {
if (vkeylen == 8) {
memcpy(&deskeyList[deskeyListLen], vkey, 8);
deskeyListLen++;
} else if (vkeylen == 16) {
memcpy(&aeskeyList[aeskeyListLen], vkey, 16);
aeskeyListLen++;
} else if (vkeylen == 24) {
memcpy(&k3kkeyList[k3kkeyListLen], vkey, 16);
k3kkeyListLen++;
} else {
PrintAndLogEx(ERR, "Specified key must have 8, 16 or 24 bytes length.");
CLIParserFree();
return PM3_EINVARG;
}
}
uint8_t dict_filename[FILE_PATH_SIZE + 2] = {0};
int dict_filenamelen = 0;
if (CLIParamStrToBuf(arg_get_str(3), dict_filename, FILE_PATH_SIZE, &dict_filenamelen)) {
PrintAndLogEx(FAILED, "File name too long or invalid.");
CLIParserFree();
return PM3_EINVARG;
}
bool pattern1b = arg_get_lit(4);
bool pattern2b = arg_get_lit(5);
if (pattern1b && pattern2b) {
PrintAndLogEx(ERR, "Pattern search mode must be 2-byte or 1-byte only.");
CLIParserFree();
return PM3_EINVARG;
}
if (dict_filenamelen && (pattern1b || pattern2b)) {
PrintAndLogEx(ERR, "Pattern search mode and dictionary mode can't be used in one command.");
CLIParserFree();
return PM3_EINVARG;
}
uint32_t startPattern = 0x0000;
uint8_t vpattern[2];
int vpatternlen = 0;
CLIGetHexWithReturn(6, vpattern, &vpatternlen);
if (vpatternlen > 0) {
if (vpatternlen > 0 && vpatternlen <= 2) {
startPattern = (vpattern[0] << 8) + vpattern[1];
} else {
PrintAndLogEx(ERR, "Pattern must be 2-byte length.");
CLIParserFree();
return PM3_EINVARG;
}
if (!pattern2b)
PrintAndLogEx(WARNING, "Pattern entered, but search mode not is 2-byte search.");
}
uint8_t jsonname[250] = {0};
int jsonnamelen = 0;
if (CLIParamStrToBuf(arg_get_str(7), jsonname, sizeof(jsonname), &jsonnamelen)) {
PrintAndLogEx(ERR, "Invalid json name.");
CLIParserFree();
return PM3_EINVARG;
}
jsonname[jsonnamelen] = 0;
bool verbose = arg_get_lit(8);
CLIParserFree();
// 1-byte pattern search mode
if (pattern1b) {
for (int i = 0; i < 0x100; i++)
memset(aeskeyList[i], i, 16);
for (int i = 0; i < 0x100; i++)
memset(deskeyList[i], i, 8);
for (int i = 0; i < 0x100; i++)
memset(k3kkeyList[i], i, 24);
aeskeyListLen = 0x100;
deskeyListLen = 0x100;
k3kkeyListLen = 0x100;
}
// 2-byte pattern search mode
if (pattern2b) {
DesFill2bPattern(deskeyList, &deskeyListLen, aeskeyList, &aeskeyListLen, k3kkeyList, &k3kkeyListLen, &startPattern);
}
// dictionary mode
size_t endFilePosition = 0;
if (dict_filenamelen) {
uint16_t keycnt = 0;
res = loadFileDICTIONARYEx((char *)dict_filename, deskeyList, sizeof(deskeyList), NULL, 8, &keycnt, 0, &endFilePosition, true);
deskeyListLen = keycnt;
if (endFilePosition)
PrintAndLogEx(SUCCESS, "First part of des dictionary successfully loaded.");
endFilePosition = 0;
res = loadFileDICTIONARYEx((char *)dict_filename, aeskeyList, sizeof(aeskeyList), NULL, 16, &keycnt, 0, &endFilePosition, true);
aeskeyListLen = keycnt;
if (endFilePosition)
PrintAndLogEx(SUCCESS, "First part of aes dictionary successfully loaded.");
endFilePosition = 0;
res = loadFileDICTIONARYEx((char *)dict_filename, k3kkeyList, sizeof(k3kkeyList), NULL, 24, &keycnt, 0, &endFilePosition, true);
k3kkeyListLen = keycnt;
if (endFilePosition)
PrintAndLogEx(SUCCESS, "First part of k3kdes dictionary successfully loaded.");
endFilePosition = 0;
if (endFilePosition)
PrintAndLogEx(SUCCESS, "First part of dictionary successfully loaded.");
}
if (aeskeyListLen == 0) {
PrintAndLogEx(ERR, "Aes key list is empty. Nothing to check.");
return PM3_EINVARG;
} else {
PrintAndLogEx(INFO, "Loaded " _YELLOW_("%zu") " aes keys", aeskeyListLen);
}
if (deskeyListLen == 0) {
PrintAndLogEx(ERR, "Des key list is empty. Nothing to check.");
return PM3_EINVARG;
} else {
PrintAndLogEx(INFO, "Loaded " _YELLOW_("%zu") " des keys", deskeyListLen);
}
if (k3kkeyListLen == 0) {
PrintAndLogEx(ERR, "K3k key list is empty. Nothing to check.");
return PM3_EINVARG;
} else {
PrintAndLogEx(INFO, "Loaded " _YELLOW_("%zu") " k3kdes keys", k3kkeyListLen);
}
if (!verbose)
printf("Search keys:\n");
bool result = false;
uint8_t app_ids[78] = {0};
uint8_t app_ids_len = 0;
if (handler_desfire_appids(app_ids, &app_ids_len) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Can't get list of applications on tag");
DropField();
return PM3_ESOFT;
}
if (aidlength != 0) {
memcpy(&app_ids[0], aid, 3);
app_ids_len = 1;
}
for (int x = 0; x < app_ids_len / 3; x++) {
uint32_t curaid = (app_ids[x * 3] & 0xFF) + ((app_ids[(x * 3) + 1] & 0xFF) << 8) + ((app_ids[(x * 3) + 2] & 0xFF) << 16);
PrintAndLogEx(ERR, "Checking aid 0x%06X...", curaid);
res = AuthCheckDesfire(&app_ids[x * 3], deskeyList, deskeyListLen, aeskeyList, aeskeyListLen, k3kkeyList, k3kkeyListLen, foundKeys, &result);
if (res == PM3_EOPABORTED) {
break;
}
if (pattern2b && startPattern < 0x10000) {
if (!verbose)
printf("p");
aeskeyListLen = 0;
deskeyListLen = 0;
k3kkeyListLen = 0;
DesFill2bPattern(deskeyList, &deskeyListLen, aeskeyList, &aeskeyListLen, k3kkeyList, &k3kkeyListLen, &startPattern);
continue;
}
if (dict_filenamelen && endFilePosition) {
if (!verbose)
printf("d");
uint16_t keycnt = 0;
res = loadFileDICTIONARYEx((char *)dict_filename, deskeyList, sizeof(deskeyList), NULL, 16, &keycnt, endFilePosition, &endFilePosition, false);
deskeyListLen = keycnt;
keycnt = 0;
res = loadFileDICTIONARYEx((char *)dict_filename, aeskeyList, sizeof(aeskeyList), NULL, 16, &keycnt, endFilePosition, &endFilePosition, false);
aeskeyListLen = keycnt;
keycnt = 0;
res = loadFileDICTIONARYEx((char *)dict_filename, k3kkeyList, sizeof(k3kkeyList), NULL, 16, &keycnt, endFilePosition, &endFilePosition, false);
k3kkeyListLen = keycnt;
continue;
}
}
if (!verbose)
printf("\n");
// save keys to json
if ((jsonnamelen > 0) && result) {
// Mifare Desfire info
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
PacketResponseNG resp;
WaitForResponse(CMD_ACK, &resp);
iso14a_card_select_t card;
memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
uint64_t select_status = resp.oldarg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
uint8_t data[10 + 1 + 2 + 1 + 256 + (4 * 0xE * (24 + 1))] = {0};
uint8_t atslen = 0;
if (select_status == 1 || select_status == 2) {
memcpy(data, card.uid, card.uidlen);
data[10] = card.sak;
data[11] = card.atqa[1];
data[12] = card.atqa[0];
atslen = card.ats_len;
data[13] = atslen;
memcpy(&data[14], card.ats, atslen);
}
// length: UID(10b)+SAK(1b)+ATQA(2b)+ATSlen(1b)+ATS(atslen)+foundKeys[2][64][AES_KEY_LEN + 1]
memcpy(&data[14 + atslen], foundKeys, 4 * 0xE * (24 + 1));
saveFileJSON((char *)jsonname, jsfMfDesfireKeys, data, 0xE);
}
return PM3_SUCCESS;
}
static int CmdHF14ADesList(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
return CmdTraceList("des");
@ -3364,6 +4027,8 @@ static command_t CommandTable[] = {
{"getvalue", CmdHF14ADesGetValueData, IfPm3Iso14443a, "Get value of file"},
{"changevalue", CmdHF14ADesChangeValue, IfPm3Iso14443a, "Write value of a value file (credit/debit/clear)"},
{"formatpicc", CmdHF14ADesFormatPICC, IfPm3Iso14443a, "Format PICC"},
{"dump", CmdHF14ADesDump, IfPm3Iso14443a, "Dump all files"},
{"chk", CmdHF14aDesChk, IfPm3Iso14443a, "Check keys"},
/*
ToDo:

View file

@ -32,10 +32,10 @@
#include "util_posix.h"
#include "crapto1/crapto1.h"
#include "parity.h"
#include "hardnested/hardnested_bruteforce.h"
#include "hardnested/hardnested_bf_core.h"
#include "hardnested/hardnested_bitarray_core.h"
#include "zlib.h"
#include "hardnested_bruteforce.h"
#include "hardnested_bf_core.h"
#include "hardnested_bitarray_core.h"
#include "zlib/zlib.h"
#include "fileutils.h"
#define NUM_CHECK_BITFLIPS_THREADS (num_CPUs())

View file

@ -19,13 +19,13 @@
#include "mifare/mifare4.h"
#include "mifare/mad.h"
#include "mifare/ndef.h"
#include "cliparser/cliparser.h"
#include "cliparser.h"
#include "emv/dump.h"
#include "mifare/mifaredefault.h"
#include "util_posix.h"
#include "fileutils.h"
#include "protocols.h"
#include "../crypto/libpcrypto.h"
#include "crypto/libpcrypto.h"
static const uint8_t DefaultKey[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
uint16_t CardAddresses[] = {0x9000, 0x9001, 0x9002, 0x9003, 0x9004, 0xA000, 0xA001, 0xA080, 0xA081, 0xC000, 0xC001};

View file

@ -11,7 +11,7 @@
#include <ctype.h>
#include "cmdparser.h"
#include "commonutil.h"
#include "../crypto/libpcrypto.h"
#include "crypto/libpcrypto.h"
#include "mbedtls/des.h"
#include "cmdhfmf.h"
#include "cmdhf14a.h"
@ -20,7 +20,7 @@
#include "protocols.h"
#include "generator.h"
#include "mifare/ndef.h"
#include "cliparser/cliparser.h"
#include "cliparser.h"
#define MAX_UL_BLOCKS 0x0F
@ -235,13 +235,21 @@ static int usage_hf_mfu_pwdgen(void) {
}
static int usage_hf_mfu_otp_tearoff(void) {
PrintAndLogEx(NORMAL, "Tear-off test against OTP block on MFU tags.");
PrintAndLogEx(NORMAL, "Usage: hf mfu otptear [h]");
PrintAndLogEx(NORMAL, "Tear-off test against OTP block (no 3) on MFU tags - More help sooner or later\n");
PrintAndLogEx(NORMAL, "Usage: hf mfu otptear b <block number> i <intervalTime> l <limitTime> s <startTime> d <data before> t <data after>\n");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : this help");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu otptear"));
PrintAndLogEx(NORMAL, " b <no> : (optional) block to run the test - default block: 8 (not OTP for safety)");
PrintAndLogEx(NORMAL, " i <time> : (optional) time interval to increase in each test - default 500 us");
PrintAndLogEx(NORMAL, " l <time> : (optional) limit time to run the test - default 3000 us");
PrintAndLogEx(NORMAL, " s <time> : (optional) start time to run the test - default 0 us");
PrintAndLogEx(NORMAL, " d <data> : (optional) data to full-write before trying the OTP test - default 0x00");
PrintAndLogEx(NORMAL, " t <data> : (optional) data to write while running the OTP test - default 0x00");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " hf mfu otptear b 3");
PrintAndLogEx(NORMAL, " hf mfu otptear b 8 i 100 l 3000 s 1000");
PrintAndLogEx(NORMAL, " hf mfu otptear b 3 i 1 l 200");
PrintAndLogEx(NORMAL, " hf mfu otptear b 3 i 100 l 2500 s 200 d FFFFFFFF t EEEEEEEE");
return PM3_SUCCESS;
}
@ -1187,7 +1195,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
if (tagtype == UL_ERROR) return PM3_ESOFT;
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") "---------");
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " --------------------------");
PrintAndLogEx(INFO, "-------------------------------------------------------------");
ul_print_type(tagtype, 6);
@ -2683,29 +2691,133 @@ static int CmdHF14AMfUPwdGen(const char *Cmd) {
// Moebius et al
//
static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
uint8_t blockNoUint = 8;
uint8_t cmdp = 0;
bool errors = 0;
uint32_t len = strtol(Cmd, NULL, 0);
uint8_t data[PM3_CMD_DATA_SIZE] = {0};
uint8_t teardata[8] = {0x00};
uint32_t interval = 500; // time in us
uint32_t timeLimit = 3000; // time in us
uint32_t startTime = 0; // time in us
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_hf_mfu_otp_tearoff();
case 'b':
blockNoUint = param_get8(Cmd, cmdp + 1);
if (blockNoUint < 0) {
PrintAndLogEx(WARNING, "Wrong block number");
errors = true;
}
cmdp += 2;
break;
case 'i':
interval = param_get32ex(Cmd, cmdp + 1, interval, 10);
if (interval <= 0) {
PrintAndLogEx(WARNING, "Wrong interval number");
errors = true;
}
cmdp += 2;
break;
case 'l':
timeLimit = param_get32ex(Cmd, cmdp + 1, timeLimit, 10);
if (timeLimit < interval) {
PrintAndLogEx(WARNING, "Wrong time limit number");
errors = true;
}
cmdp += 2;
break;
case 's':
startTime = param_get32ex(Cmd, cmdp + 1, 0, 10);
if (startTime > (timeLimit - interval)) {
PrintAndLogEx(WARNING, "Wrong start time number");
errors = true;
}
cmdp += 2;
break;
case 'd':
if (param_gethex(Cmd, cmdp + 1, teardata, 8)) {
PrintAndLogEx(WARNING, "Block data must include 8 HEX symbols");
errors = true;
}
cmdp += 2;
break;
case 't':
if (param_gethex(Cmd, cmdp + 1, teardata + 4, 8)) {
PrintAndLogEx(WARNING, "Block data must include 8 HEX symbols");
errors = true;
}
cmdp += 2;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
}
if (errors) return usage_hf_mfu_otp_tearoff();
uint32_t actualTime = startTime;
printf("\nStarting TearOff test - Selected Block no: %d ...\n", blockNoUint);
while (actualTime <= (timeLimit - interval)) {
printf("\nTrying attack at: %d us\n", actualTime);
printf("\n.....\n");
printf("\nReading block before attack: \n");
clearCommandBuffer();
SendCommandNG(CMD_HF_MFU_OTP_TEAROFF, data, len);
SendCommandOLD(CMD_HF_MIFAREU_READBL, blockNoUint, 0, 0, NULL, 0);
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
uint8_t isOK = resp.oldarg[0] & 0xff;
if (isOK) {
uint8_t *d = resp.data.asBytes;
PrintAndLogEx(NORMAL, "\nBlock# | Data | Ascii");
PrintAndLogEx(NORMAL, "-----------------------------");
PrintAndLogEx(NORMAL, "%02d/0x%02X | %s| %s\n", blockNoUint, blockNoUint, sprint_hex(d, 4), sprint_ascii(d, 4));
}
}
printf("\n.....\n");
clearCommandBuffer();
SendCommandOLD(CMD_HF_MFU_OTP_TEAROFF, blockNoUint, actualTime, 0, teardata, 8);
if (!WaitForResponseTimeout(CMD_HF_MFU_OTP_TEAROFF, &resp, 4000)) {
PrintAndLogEx(WARNING, "Failed");
return PM3_ESOFT;
}
printf("\nReading block after attack: \n");
clearCommandBuffer();
SendCommandOLD(CMD_HF_MIFAREU_READBL, blockNoUint, 0, 0, NULL, 0);
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
uint8_t isOK = resp.oldarg[0] & 0xff;
if (isOK) {
uint8_t *d = resp.data.asBytes;
PrintAndLogEx(NORMAL, "\nBlock# | Data | Ascii");
PrintAndLogEx(NORMAL, "-----------------------------");
PrintAndLogEx(NORMAL, "%02d/0x%02X | %s| %s\n", blockNoUint, blockNoUint, sprint_hex(d, 4), sprint_ascii(d, 4));
}
}
/* TEMPORALLY DISABLED
uint8_t d0, d1, d2, d3;
d0 = *resp.data.asBytes;
d1 = *(resp.data.asBytes + 1);
d2 = *(resp.data.asBytes + 2);
d3 = *(resp.data.asBytes + 3);
if ((d0 != 0xFF) || (d1 != 0xFF) || (d2 != 0xFF) || (d3 = ! 0xFF)) {
PrintAndLogEx(NORMAL, "---------------------------------");
PrintAndLogEx(NORMAL, " EFFECT AT: %d us", actualTime);
PrintAndLogEx(NORMAL, "---------------------------------\n");
}
*/
actualTime += interval;
}
return PM3_SUCCESS;
}

View file

@ -19,7 +19,7 @@
#include "cmdparser.h" // command_t
#include "comms.h"
#include "graph.h"
#include "cliparser/cliparser.h"
#include "cliparser.h"
#include "commonutil.h"
#include "ui.h" // PrintAndLog
#include "lfdemod.h" // parityTest, bitbytes_to_byte

View file

@ -23,7 +23,7 @@
#include "protocols.h" // t55xx defines
#include "cmdlft55xx.h" // clone..
#include "cmdlf.h" // cmdlfconfig
#include "cliparser/cliparser.h" // cli parse input
#include "cliparser.h" // cli parse input
static int CmdHelp(const char *Cmd);

View file

@ -19,7 +19,7 @@
#include "proxmark3.h"
#include "comms.h" // getfromdevice
#include "emv/emvcore.h" // decodeTVL
#include "../crypto/libpcrypto.h" // sha512hash
#include "crypto/libpcrypto.h" // sha512hash
#include "emv/dump.h"
#include "ui.h"
#include "fileutils.h"

View file

@ -15,7 +15,7 @@
#include <string.h>
#include <stdio.h>
#include "uart.h"
#include "uart/uart.h"
#include "ui.h"
#include "crc16.h"
#include "util_posix.h" // msclock

View file

@ -17,7 +17,7 @@
#include "cmdtrace.h"
#include "emvjson.h"
#include "test/cryptotest.h"
#include "cliparser/cliparser.h"
#include "cliparser.h"
#include "cmdparser.h"
#include "proxmark3.h"
#include "emv_roca.h"

View file

@ -92,7 +92,7 @@ int JsonSaveInt(json_t *root, const char *path, int value) {
int JsonSaveStr(json_t *root, const char *path, const char *value) {
return JsonSaveJsonObject(root, path, json_string(value));
};
}
int JsonSaveBoolean(json_t *root, const char *path, bool value) {
return JsonSaveJsonObject(root, path, json_boolean(value));
@ -298,7 +298,7 @@ int JsonLoadBufAsHex(json_t *elm, const char *path, uint8_t *data, size_t maxbuf
return 2;
return 0;
};
}
bool ParamLoadFromJson(struct tlvdb *tlv) {
json_t *root;

View file

@ -12,7 +12,7 @@
#include "common.h"
#include <jansson.h>
#include "jansson.h"
#include "tlv.h"
typedef struct {

View file

@ -387,7 +387,7 @@ CborError CborGetArrayBinStringValueEx(CborValue *elm, uint8_t *data, size_t max
*datalen = totallen;
return CborNoError;
};
}
CborError CborGetBinStringValue(CborValue *elm, uint8_t *data, size_t maxdatalen, size_t *datalen) {
if (datalen)
@ -402,7 +402,7 @@ CborError CborGetBinStringValue(CborValue *elm, uint8_t *data, size_t maxdatalen
*datalen = slen;
return CborNoError;
};
}
CborError CborGetArrayStringValue(CborValue *elm, char *data, size_t maxdatalen, size_t *datalen, char *delimiter) {
CborValue array;
@ -435,7 +435,7 @@ CborError CborGetArrayStringValue(CborValue *elm, char *data, size_t maxdatalen,
*datalen = totallen;
return CborNoError;
};
}
CborError CborGetStringValue(CborValue *elm, char *data, size_t maxdatalen, size_t *datalen) {
if (datalen)
@ -450,14 +450,14 @@ CborError CborGetStringValue(CborValue *elm, char *data, size_t maxdatalen, size
*datalen = slen;
return CborNoError;
};
}
CborError CborGetStringValueBuf(CborValue *elm) {
static char stringBuf[2048];
memset(stringBuf, 0x00, sizeof(stringBuf));
return CborGetStringValue(elm, stringBuf, sizeof(stringBuf), NULL);
};
}
int CBOREncodeElm(json_t *root, const char *rootElmId, CborEncoder *encoder) {
json_t *elm = NULL;

View file

@ -426,6 +426,44 @@ int saveFileJSON(const char *preferredName, JSONFileType ftype, uint8_t *data, s
}
}
break;
case jsfMfDesfireKeys:
JsonSaveStr(root, "FileType", "mfdes");
JsonSaveBufAsHexCompact(root, "$.Card.UID", &data[0], 7);
JsonSaveBufAsHexCompact(root, "$.Card.SAK", &data[10], 1);
JsonSaveBufAsHexCompact(root, "$.Card.ATQA", &data[11], 2);
uint8_t datslen = data[13];
if (datslen > 0)
JsonSaveBufAsHexCompact(root, "$.Card.ATS", &data[14], datslen);
uint8_t dvdata[4][0xE][24 + 1] = {{{0}}};
memcpy(dvdata, &data[14 + datslen], 4 * 0xE * (24 + 1));
for (int i = 0; i < (int)datalen; i++) {
char path[PATH_MAX_LENGTH] = {0};
if (dvdata[0][i][0]) {
memset(path, 0x00, sizeof(path));
sprintf(path, "$.DES.%d.Key", i);
JsonSaveBufAsHexCompact(root, path, &dvdata[0][i][1], 8);
}
if (dvdata[1][i][0]) {
memset(path, 0x00, sizeof(path));
sprintf(path, "$.3DES.%d.Key", i);
JsonSaveBufAsHexCompact(root, path, &dvdata[1][i][1], 16);
}
if (dvdata[2][i][0]) {
memset(path, 0x00, sizeof(path));
sprintf(path, "$.AES.%d.Key", i);
JsonSaveBufAsHexCompact(root, path, &dvdata[2][i][1], 16);
}
if (dvdata[3][i][0]) {
memset(path, 0x00, sizeof(path));
sprintf(path, "$.K3KDES.%d.Key", i);
JsonSaveBufAsHexCompact(root, path, &dvdata[3][i][1], 24);
}
}
break;
case jsfSettings:
preferences_save_callback(root);
break;

View file

@ -63,6 +63,7 @@ typedef enum {
jsfT5555,
jsfMfPlusKeys,
jsfSettings,
jsfMfDesfireKeys,
} JSONFileType;
typedef enum {

View file

@ -4,9 +4,6 @@
#include "common.h"
#include "mifare.h" // structs
#include "crc32.h"
//#include "../../armsrc/printf.h"
//#include "../../armsrc/desfire.h"
//#include "../../armsrc/iso14443a.h"
#define MAX_CRYPTO_BLOCK_SIZE 16

View file

@ -236,7 +236,7 @@ int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) {
};
return 0;
};
}
int MAD2DecodeAndPrint(uint8_t *sector, bool verbose) {
PrintAndLogEx(NORMAL, "16 MAD2");
@ -255,4 +255,4 @@ int MAD2DecodeAndPrint(uint8_t *sector, bool verbose) {
};
return 0;
};
}

View file

@ -88,7 +88,7 @@ const char *mfGetAccessConditionsDesc(uint8_t blockn, uint8_t *data) {
};
return StaticNone;
};
}
/*
static int CalculateEncIVCommand(mf4Session_t *session, uint8_t *iv, bool verbose) {
memcpy(&iv[0], &session->TI, 4);

View file

@ -219,7 +219,7 @@ static int ndefDecodeSig1(uint8_t *sig, size_t siglen) {
}
return PM3_SUCCESS;
};
}
// https://github.com/nfcpy/ndeflib/blob/master/src/ndef/signature.py#L292
static int ndefDecodeSig2(uint8_t *sig, size_t siglen) {
@ -283,7 +283,7 @@ static int ndefDecodeSig2(uint8_t *sig, size_t siglen) {
}
return PM3_SUCCESS;
};
}
static int ndefDecodeSig(uint8_t *sig, size_t siglen) {
PrintAndLogEx(SUCCESS, "\tsignature version : \t" _GREEN_("0x%02x"), sig[0]);

View file

@ -113,15 +113,22 @@ static void showBanner(void) {
g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG;
}
static const char *prompt_dev = "";
static const char *prompt_ctx = "";
static void prompt_compose(char *buf, size_t buflen, const char *prompt_ctx, const char *prompt_dev) {
snprintf(buf, buflen-1, PROXPROMPT_COMPOSE, prompt_dev, prompt_ctx);
}
static int check_comm(void) {
// If communications thread goes down. Device disconnected then this should hook up PM3 again.
if (IsCommunicationThreadDead() && session.pm3_present) {
if (session.supports_colors)
rl_set_prompt(PROXPROMPT_OFFLINE_COLOR);
else
rl_set_prompt(PROXPROMPT_OFFLINE);
prompt_dev = PROXPROMPT_DEV_OFFLINE;
char prompt[PROXPROMPT_MAX_SIZE] = {0};
prompt_compose(prompt, sizeof(prompt), prompt_ctx, prompt_dev);
char prompt_filtered[PROXPROMPT_MAX_SIZE] = {0};
memcpy_filter_ansi(prompt_filtered, prompt, sizeof(prompt_filtered), !session.supports_colors);
rl_set_prompt(prompt_filtered);
rl_forced_update_display();
CloseProxmark();
PrintAndLogEx(INFO, "Running in " _YELLOW_("OFFLINE") " mode. Use "_YELLOW_("\"hw connect\"") " to reconnect\n");
@ -213,7 +220,14 @@ main_loop(char *script_cmds_file, char *script_cmd, bool stayInCommandLoop) {
// loops every time enter is pressed...
while (1) {
bool printprompt = false;
const char *prompt = (session.supports_colors) ? PROXPROMPT_CON_COLOR : PROXPROMPT_CON;
if (session.pm3_present) {
if (conn.send_via_fpc_usart == false)
prompt_dev = PROXPROMPT_DEV_USB;
else
prompt_dev = PROXPROMPT_DEV_FPC;
} else {
prompt_dev = PROXPROMPT_DEV_OFFLINE;
}
check_script:
// If there is a script file
@ -228,7 +242,7 @@ check_script:
break;
goto check_script;
} else {
prompt_ctx = PROXPROMPT_CTX_SCRIPTFILE;
// remove linebreaks
strcleanrn(script_cmd_buf, sizeof(script_cmd_buf));
@ -239,6 +253,7 @@ check_script:
} else {
// If there is a script command
if (execCommand) {
prompt_ctx = PROXPROMPT_CTX_SCRIPTCMD;
cmd = str_dup(script_cmd);
if (cmd != NULL)
@ -258,6 +273,7 @@ check_script:
// if there is a pipe from stdin
if (stdinOnPipe) {
prompt_ctx = PROXPROMPT_CTX_STDIN;
// clear array
memset(script_cmd_buf, 0, sizeof(script_cmd_buf));
@ -274,16 +290,13 @@ check_script:
printprompt = true;
} else {
prompt_ctx = PROXPROMPT_CTX_INTERACTIVE;
rl_event_hook = check_comm;
if (session.pm3_present) {
if (conn.send_via_fpc_usart == false)
prompt = (session.supports_colors) ? PROXPROMPT_USB_COLOR : PROXPROMPT_USB;
else
prompt = (session.supports_colors) ? PROXPROMPT_FPC_COLOR : PROXPROMPT_FPC;
} else {
prompt = (session.supports_colors) ? PROXPROMPT_OFFLINE_COLOR : PROXPROMPT_OFFLINE;
}
cmd = readline(prompt);
char prompt[PROXPROMPT_MAX_SIZE] = {0};
prompt_compose(prompt, sizeof(prompt), prompt_ctx, prompt_dev);
char prompt_filtered[PROXPROMPT_MAX_SIZE] = {0};
memcpy_filter_ansi(prompt_filtered, prompt, sizeof(prompt_filtered), !session.supports_colors);
cmd = readline(prompt_filtered);
fflush(NULL);
}
}
@ -313,6 +326,8 @@ check_script:
if (!printprompt) {
g_printAndLog = PRINTANDLOG_LOG;
}
char prompt[PROXPROMPT_MAX_SIZE] = {0};
prompt_compose(prompt, sizeof(prompt), prompt_ctx, prompt_dev);
PrintAndLogEx(NORMAL, "%s%s", prompt, cmd);
g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG;

View file

@ -14,17 +14,19 @@
#include "common.h"
#define PROXPROMPT_CON "[con] pm3 --> "
#define PROXPROMPT_CON_COLOR "[\001\033[1;32m\002con\001\033[0m\002] pm3 --> "
#define PROXPROMPT_MAX_SIZE 255
#define PROXPROMPT_USB "[usb] pm3 --> "
#define PROXPROMPT_USB_COLOR "[\001\033[1;32m\002usb\001\033[0m\002] pm3 --> "
#define PROXPROMPT_COMPOSE "[" "%s%s" "] pm3 --> "
#define PROXPROMPT_FPC "[fpc] pm3 --> "
#define PROXPROMPT_FPC_COLOR "[\001\033[1;32m\002fpc\001\033[0m\002] pm3 --> "
#define PROXPROMPT_CTX_SCRIPTFILE "|" _GREEN_("script")
#define PROXPROMPT_CTX_SCRIPTCMD "|" _GREEN_("script")
#define PROXPROMPT_CTX_STDIN "|" _GREEN_("script")
#define PROXPROMPT_CTX_INTERACTIVE ""
#define PROXPROMPT_DEV_USB _BOLD_GREEN_("usb")
#define PROXPROMPT_DEV_FPC _BOLD_GREEN_("fpc")
#define PROXPROMPT_DEV_OFFLINE _BOLD_RED_("offline")
#define PROXPROMPT_OFFLINE "[offline] pm3 --> "
#define PROXPROMPT_OFFLINE_COLOR "[\001\033[1;31m\002offline\001\033[0m\002] pm3 --> "
#define PROXHISTORY "history.txt"
#define PROXLOG "log_%Y%m%d.txt"

View file

@ -941,7 +941,7 @@ char *str_ndup(const char *src, size_t len) {
* Returns the number of nibbles (4 bits) entered.
*/
int hexstring_to_u96(uint32_t *hi2, uint32_t *hi, uint32_t *lo, const char *str) {
int n = 0, i = 0;
unsigned int n = 0, i = 0;
while (sscanf(&str[i++], "%1x", &n) == 1) {
*hi2 = (*hi2 << 4) | (*hi >> 28);

View file

@ -5,7 +5,7 @@
//-----------------------------------------------------------------------------
// parity functions (all defined in parity.h)
//-----------------------------------------------------------------------------
#include <parity.h>
#include "parity.h"
const uint8_t OddByteParity[256] = {
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,

View file

@ -5,7 +5,9 @@
#define _BLUE_(s) "\x1b[34m" s AEND
#define _RED_(s) "\x1b[31m" s AEND
#define _BOLD_RED_(s) "\x1b[1;31m" s AEND
#define _GREEN_(s) "\x1b[32m" s AEND
#define _BOLD_GREEN_(s) "\x1b[1;32m" s AEND
#define _YELLOW_(s) "\x1b[33m" s AEND
#define _MAGENTA_(s) "\x1b[35m" s AEND
#define _CYAN_(s) "\x1b[36m" s AEND

97
pm3
View file

@ -2,6 +2,12 @@
# Usage: run option -h to get help
# BT auto detection: only working under Linux at the moment
# Shall we look for white HC-06-USB dongle ?
FINDBTDONGLE=true
# Shall we look for rfcomm interface ?
FINDBTDIRECT=true
PM3PATH=$(dirname "$0")
FULLIMAGE="fullimage.elf"
BOOTIMAGE="bootrom.elf"
@ -17,30 +23,68 @@ else
fi
PM3LIST=()
SHOWLIST=false
function get_pm3_list_Linux {
N=$1
PM3LIST=()
for DEV in $(find /dev/ttyACM* 2>/dev/null); do
if udevadm info -q property -n "$DEV" |grep -q "ID_VENDOR=proxmark.org"; then
PM3LIST+=("$DEV")
if [ ${#PM3LIST[*]} -ge $N ]; then
return
fi
fi
done
if $FINDBTDONGLE; then
# check if the HC-06-USB white dongle is present (still, that doesn't tell us if it's paired with a Proxmark3...)
for DEV in $(find /dev/ttyUSB* 2>/dev/null); do
if udevadm info -q property -n "$DEV" |grep -q "ID_MODEL=CP2104_USB_to_UART_Bridge_Controller"; then
PM3LIST+=("$DEV")
if [ ${#PM3LIST[*]} -ge $N ]; then
return
fi
fi
done
fi
if $FINDBTDIRECT; then
# check if the MAC of a Proxmark3 was bound to a local rfcomm interface
for DEVMAC in $(rfcomm -a|grep " 20:19:0[45]"|sed 's/^\(.*\): \([0-9:]*\) .*/\1@\2/'); do
DEV=${DEVMAC/@*/}
MAC=${DEVMAC/*@/}
# check if Proxmark3 is actually present
if hcitool name "$MAC" | grep -q "PM3"; then
PM3LIST+=("/dev/$DEV")
if [ ${#PM3LIST[*]} -ge $N ]; then
return
fi
fi
done
fi
}
function get_pm3_list_macOS {
N=$1
PM3LIST=()
for DEV in $(ioreg -r -c "IOUSBHostDevice" -l|awk -F '"' '
$2=="USB Vendor Name"{b=($4=="proxmark.org")}
b==1 && $2=="IODialinDevice"{print $4}'); do
PM3LIST+=("$DEV")
if [ ${#PM3LIST[*]} -ge $N ]; then
return
fi
done
}
function get_pm3_list_Windows {
N=$1
PM3LIST=()
for DEV in $(wmic path Win32_SerialPort where "PNPDeviceID like '%VID_9AC4&PID_4B8F%'" get DeviceID,PNPDeviceID 2>/dev/null|awk '/^COM/{print $1}'); do
DEV=${DEV/ */}
PM3LIST+=("$DEV")
if [ ${#PM3LIST[*]} -ge $N ]; then
return
fi
done
}
@ -56,6 +100,9 @@ function get_pm3_list_WSL {
echo "[!!] Let's give users read/write access to $DEV"
sudo chmod 666 "$DEV"
fi
if [ ${#PM3LIST[*]} -ge $N ]; then
return
fi
fi
done
}
@ -74,14 +121,18 @@ Description:
* the script will wait for a Proxmark to be connected (same as option -w of the client).
You can also specify a first option -n N to access the Nth Proxmark3 connected on USB.
Don't use this script if you want to work offline or with the BT addon.
To see a list of available ports, use --list.
Usage:
$SCRIPT [-n <N>] [-f] [-c <command>]|[-l <lua_script_file>]|[-s <cmd_script_file>] [-i]
$SCRIPT --list
See "$CLIENT -h" for more details on options.
EOF
}
elif [ "$SCRIPT" = "pm3-flash" ]; then
FINDBTDONGLE=false
FINDBTDIRECT=false
CMD() {
ARGS=("--port" "$1" "--flash")
shift;
@ -103,9 +154,11 @@ Description:
The usage is similar to the old proxmark3-flasher binary, except that the correct port name will be automatically guessed.
You can also specify a first option -n N to access the Nth Proxmark3 connected on USB.
If this doesn't work, you'll have to use manually the proxmark3 client, see "$CLIENT -h".
To see a list of available ports, use --list.
Usage:
$SCRIPT [-n <N>] [-b] image.elf [image.elf...]
$SCRIPT --list
Options:
-b Enable flashing of bootloader area (DANGEROUS)
@ -115,6 +168,8 @@ Example:
EOF
}
elif [ "$SCRIPT" = "pm3-flash-all" ]; then
FINDBTDONGLE=false
FINDBTDIRECT=false
CMD() { $CLIENT "--port" "$1" "--flash" "--unlock-bootloader" "--image" "$BOOTIMAGE" "--image" "$FULLIMAGE"; }
HELP() {
cat << EOF
@ -124,12 +179,16 @@ Description:
The correct port name will be automatically guessed and the stock bootloader and firmware image will be flashed.
You can also specify a first option -n N to access the Nth Proxmark3 connected on USB.
If this doesn't work, you'll have to use manually the proxmark3 client, see "$CLIENT -h".
To see a list of available ports, use --list.
Usage:
$SCRIPT [-n <N>]
$SCRIPT --list
EOF
}
elif [ "$SCRIPT" = "pm3-flash-fullimage" ]; then
FINDBTDONGLE=false
FINDBTDIRECT=false
CMD() { $CLIENT "--port" "$1" "--flash" "--image" "$FULLIMAGE"; }
HELP() {
cat << EOF
@ -139,12 +198,16 @@ Description:
The correct port name will be automatically guessed and the stock firmware image will be flashed.
You can also specify a first option -n N to access the Nth Proxmark3 connected on USB.
If this doesn't work, you'll have to use manually the proxmark3 client, see "$CLIENT -h".
To see a list of available ports, use --list.
Usage:
$SCRIPT [-n <N>]
$SCRIPT --list
EOF
}
elif [ "$SCRIPT" = "pm3-flash-bootrom" ]; then
FINDBTDONGLE=false
FINDBTDIRECT=false
CMD() { $CLIENT "--port" "$1" "--flash" "--unlock-bootloader" "--image" "$BOOTIMAGE"; }
HELP() {
cat << EOF
@ -154,9 +217,11 @@ Description:
The correct port name will be automatically guessed and the stock bootloader will be flashed.
You can also specify a first option -n N to access the Nth Proxmark3 connected on USB.
If this doesn't work, you'll have to use manually the proxmark3 client, see "$CLIENT -h".
To see a list of available ports, use --list.
Usage:
$SCRIPT [-n <N>]
$SCRIPT --list
EOF
}
else
@ -176,6 +241,15 @@ for ARG in "$@"; do
fi
done
if [ "$1" == "--list" ]; then
shift
if [ "$1" != "" ]; then
echo "Option --list must be used alone"
exit 1
fi
SHOWLIST=true
fi
# Number of the proxmark3 we're interested in
N=1
if [ "$1" == "-n" ]; then
@ -189,7 +263,6 @@ if [ "$1" == "-n" ]; then
fi
fi
echo >&2 "[=] Waiting for Proxmark3 to appear..."
HOSTOS=$(uname | awk '{print toupper($0)}')
if [ "$HOSTOS" = "LINUX" ]; then
if uname -a|grep -q Microsoft; then
@ -212,13 +285,33 @@ else
exit 1
fi
if $SHOWLIST; then
# Probe for up to 9 devs
$GETPM3LIST 9
if [ ${#PM3LIST} -lt 1 ]; then
echo "[!!] No port found"
exit 0
fi
n=1
for DEV in ${PM3LIST[@]}
do
echo "$n: $DEV"
n=$((n+1))
done
exit 0
fi
# Wait till we get at least N proxmark3 devices
while true; do
$GETPM3LIST $N
if [ ${#PM3LIST} -lt $N ]; then
echo >&2 "[=] Waiting for Proxmark3 to appear..."
fi
while true; do
if [ ${#PM3LIST[*]} -ge $N ]; then
break
fi
sleep .1
$GETPM3LIST $N
done
if [ ${#PM3LIST} -lt $N ]; then

View file

@ -3,7 +3,16 @@
PM3PATH=$(dirname "$0")
cd "$PM3PATH" || exit 1
if [ "$1" == "client" ]; then
shift
TESTDEVICE=false
TESTTOOLS=false
else
TESTDEVICE=true
TESTTOOLS=true
fi
if [ "$1" == "long" ]; then
shift
SLOWTESTS=true
else
SLOWTESTS=false
@ -66,6 +75,7 @@ printf "\n${C_BLUE}RRG/Iceman Proxmark3 test tool ${C_NC}\n\n"
printf "work directory: "
pwd
printf "client ${PM3BIN:="./client/proxmark3"}\n"
if [ "$TRAVIS_COMMIT" ]; then
if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
@ -83,34 +93,37 @@ echo ""
while true; do
printf "\n${C_BLUE}Testing files:${C_NC}\n"
if ! CheckFileExist "proxmark3 exists" "./client/proxmark3"; then break; fi
if ! CheckFileExist "proxmark3 exists" "$PM3BIN"; then break; fi
if ! CheckFileExist "hardnested tables exists" "./client/resources/hardnested_tables/*.z"; then break; fi
if $TESTDEVICE; then
if ! CheckFileExist "arm image exists" "./armsrc/obj/fullimage.elf"; then break; fi
if ! CheckFileExist "bootrom exists" "./bootrom/obj/bootrom.elf"; then break; fi
if ! CheckFileExist "hardnested tables exists" "./client/resources/hardnested_tables/*.z"; then break; fi
printf "\n${C_BLUE}Testing basic help:${C_NC}\n"
if ! CheckExecute "proxmark help" "./client/proxmark3 -h" "wait"; then break; fi
if ! CheckExecute "proxmark help text ISO7816" "./client/proxmark3 -t 2>&1" "ISO7816"; then break; fi
if ! CheckExecute "proxmark help text hardnested" "./client/proxmark3 -t 2>&1" "hardnested"; then break; fi
printf "\n${C_BLUE}Testing data manipulation:${C_NC}\n"
if ! CheckExecute "reveng test" "./client/proxmark3 -c 'reveng -w 8 -s 01020304e3 010204039d'" "CRC-8/SMBUS"; then break; fi
if ! CheckExecute "mfu pwdgen test" "./client/proxmark3 -c 'hf mfu pwdgen t'" "Selftest OK"; then break; fi
printf "\n${C_BLUE}Testing LF:${C_NC}\n"
if ! CheckExecute "lf em4x05 test" "./client/proxmark3 -c 'data load traces/em4x05.pm3;lf search'" "FDX-B ID found"; then break; fi
printf "\n${C_BLUE}Testing HF:${C_NC}\n"
if ! CheckExecute "hf mf offline text" "./client/proxmark3 -c 'hf mf'" "at_enc"; then break; fi
if $SLOWTESTS; then
if ! CheckExecute "hf mf hardnested test" "./client/proxmark3 -c 'hf mf hardnested t 1 000000000000'" "found:" "repeat" "ignore"; then break; fi
if ! CheckExecute "hf iclass test" "./client/proxmark3 -c 'hf iclass loclass t l'" "verified ok"; then break; fi
if ! CheckExecute "emv test" "./client/proxmark3 -c 'emv test -l'" "Test(s) \[ OK"; then break; fi
else
if ! CheckExecute "hf iclass test" "./client/proxmark3 -c 'hf iclass loclass t'" "OK!"; then break; fi
if ! CheckExecute "emv test" "./client/proxmark3 -c 'emv test'" "Test(s) \[ OK"; then break; fi
fi
printf "\n${C_BLUE}Testing basic help:${C_NC}\n"
if ! CheckExecute "proxmark help" "$PM3BIN -h" "wait"; then break; fi
if ! CheckExecute "proxmark help text ISO7816" "$PM3BIN -t 2>&1" "ISO7816"; then break; fi
if ! CheckExecute "proxmark help text hardnested" "$PM3BIN -t 2>&1" "hardnested"; then break; fi
printf "\n${C_BLUE}Testing data manipulation:${C_NC}\n"
if ! CheckExecute "reveng test" "$PM3BIN -c 'reveng -w 8 -s 01020304e3 010204039d'" "CRC-8/SMBUS"; then break; fi
if ! CheckExecute "mfu pwdgen test" "$PM3BIN -c 'hf mfu pwdgen t'" "Selftest OK"; then break; fi
printf "\n${C_BLUE}Testing LF:${C_NC}\n"
if ! CheckExecute "lf em4x05 test" "$PM3BIN -c 'data load traces/em4x05.pm3;lf search'" "FDX-B ID found"; then break; fi
printf "\n${C_BLUE}Testing HF:${C_NC}\n"
if ! CheckExecute "hf mf offline text" "$PM3BIN -c 'hf mf'" "at_enc"; then break; fi
if $SLOWTESTS; then
if ! CheckExecute "hf mf hardnested test" "$PM3BIN -c 'hf mf hardnested t 1 000000000000'" "found:" "repeat" "ignore"; then break; fi
if ! CheckExecute "hf iclass test" "$PM3BIN -c 'hf iclass loclass t l'" "verified ok"; then break; fi
if ! CheckExecute "emv test" "$PM3BIN -c 'emv test -l'" "Test(s) \[ OK"; then break; fi
else
if ! CheckExecute "hf iclass test" "$PM3BIN -c 'hf iclass loclass t'" "OK!"; then break; fi
if ! CheckExecute "emv test" "$PM3BIN -c 'emv test'" "Test(s) \[ OK"; then break; fi
fi
if $TESTTOOLS; then
printf "\n${C_BLUE}Testing tools:${C_NC}\n"
# Need a decent example for mfkey32...
if ! CheckExecute "mfkey32v2 test" "tools/mfkey/mfkey32v2 12345678 1AD8DF2B 1D316024 620EF048 30D6CB07 C52077E2 837AC61A" "Found Key: \[a0a1a2a3a4a5\]"; then break; fi
@ -121,6 +134,7 @@ while true; do
if ! CheckExecute "findbits test" "tools/findbits.py 73 0110010101110011" "Match at bit 9: 011001010"; then break; fi
if ! CheckExecute "findbits_test test" "tools/findbits_test.py 2>&1" "OK"; then break; fi
if ! CheckExecute "pm3_eml_mfd test" "tools/pm3_eml_mfd_test.py 2>&1" "OK"; then break; fi
fi
printf "\n${C_GREEN}Tests [OK]${C_NC}\n\n"
exit 0