mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-09-28 03:06:14 +08:00
commit
1770c1e37c
11
.gitignore
vendored
11
.gitignore
vendored
|
@ -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
|
||||
|
|
43
.travis.yml
43
.travis.yml
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
284
client/CMakeLists.txt
Normal 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)
|
117
client/Makefile
117
client/Makefile
|
@ -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
168
client/cmake/FindSSE.cmake
Normal 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)
|
9
client/deps/CMakeLists.txt
Normal file
9
client/deps/CMakeLists.txt
Normal 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
18
client/deps/amiibo.cmake
Normal 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)
|
|
@ -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:
|
||||
|
|
11
client/deps/cliparser.cmake
Normal file
11
client/deps/cliparser.cmake
Normal 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)
|
11
client/deps/cliparser/Makefile
Normal file
11
client/deps/cliparser/Makefile
Normal 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
|
108
client/deps/hardnested.cmake
Normal file
108
client/deps/hardnested.cmake
Normal 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)
|
83
client/deps/hardnested/Makefile
Normal file
83
client/deps/hardnested/Makefile
Normal 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
20
client/deps/jansson.cmake
Normal 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)
|
|
@ -18,4 +18,7 @@ MYSRCS = \
|
|||
|
||||
LIB_A = libjansson.a
|
||||
|
||||
# Transition: remove old directories and objects
|
||||
MYCLEANOLDPATH = ../../jansson
|
||||
|
||||
include ../../../Makefile.host
|
||||
|
|
|
@ -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
48
client/deps/lua.cmake
Normal 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
50
client/deps/mbedtls.cmake
Normal 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
15
client/deps/reveng.cmake
Normal 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)
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
14
client/deps/tinycbor.cmake
Normal file
14
client/deps/tinycbor.cmake
Normal 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)
|
|
@ -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
14
client/deps/zlib.cmake
Normal 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)
|
44
client/dictionaries/mfdes_default_keys.dic
Normal file
44
client/dictionaries/mfdes_default_keys.dic
Normal 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
|
|
@ -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)
|
390
client/luascripts/mfc_gen3_writer.lua
Normal file
390
client/luascripts/mfc_gen3_writer.lua
Normal 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)
|
|
@ -22,7 +22,7 @@
|
|||
# endif /* STDIN_FILENO */
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#include "reveng/reveng.h"
|
||||
#include "reveng.h"
|
||||
#include "ui.h"
|
||||
#include "util.h"
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
#include "common.h"
|
||||
|
||||
#include <jansson.h>
|
||||
#include "jansson.h"
|
||||
#include "tlv.h"
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -63,6 +63,7 @@ typedef enum {
|
|||
jsfT5555,
|
||||
jsfMfPlusKeys,
|
||||
jsfSettings,
|
||||
jsfMfDesfireKeys,
|
||||
} JSONFileType;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
97
pm3
|
@ -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
|
||||
|
|
62
pm3test.sh
62
pm3test.sh
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue