From d0526d3ba9afdbc641283bd2b0c5dc3e52a2c9fb Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 14 Feb 2022 02:42:40 +0100 Subject: [PATCH 01/15] Remove mkversion.pl --- armsrc/Makefile | 2 +- client/CMakeLists.txt | 2 +- client/Makefile | 4 +- client/experimental_lib/CMakeLists.txt | 2 +- common/default_version_pm3.c | 2 +- tools/mkversion.pl | 84 -------------------------- 6 files changed, 6 insertions(+), 90 deletions(-) delete mode 100755 tools/mkversion.pl diff --git a/armsrc/Makefile b/armsrc/Makefile index 968dc445d..bd311bebc 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -184,7 +184,7 @@ showinfo: # version_pm3.c should be remade on every time fullimage.stage1.elf should be remade version_pm3.c: default_version_pm3.c $(OBJDIR)/fpga_version_info.o $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ) $(info [-] GEN $@) - $(Q)$(SH) ../tools/mkversion.sh > $@ || $(PERL) ../tools/mkversion.pl > $@ || $(CP) $< $@ + $(Q)$(SH) ../tools/mkversion.sh > $@ || $(CP) $< $@ fpga_version_info.c: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR) $(info [-] GEN $@) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index f6a0c9e9f..4c5e834a1 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -358,7 +358,7 @@ set (TARGET_SOURCES add_custom_command( OUTPUT ${CMAKE_BINARY_DIR}/version_pm3.c - COMMAND sh ${PM3_ROOT}/tools/mkversion.sh > ${CMAKE_BINARY_DIR}/version_pm3.c || perl ${PM3_ROOT}/tools/mkversion.pl > ${CMAKE_BINARY_DIR}/version_pm3.c || ${CMAKE_COMMAND} -E copy ${PM3_ROOT}/common/default_version_pm3.c ${CMAKE_BINARY_DIR}/version_pm3.c + COMMAND sh ${PM3_ROOT}/tools/mkversion.sh > ${CMAKE_BINARY_DIR}/version_pm3.c || ${CMAKE_COMMAND} -E copy ${PM3_ROOT}/common/default_version_pm3.c ${CMAKE_BINARY_DIR}/version_pm3.c DEPENDS ${PM3_ROOT}/common/default_version_pm3.c ) diff --git a/client/Makefile b/client/Makefile index 4debb130f..a93ab5409 100644 --- a/client/Makefile +++ b/client/Makefile @@ -881,9 +881,9 @@ src/pm3_pywrap.c: pm3.i .PHONY: all clean install uninstall tarbin .FORCE # version_pm3.c should be remade on every compilation -src/version_pm3.c: default_version_pm3.c +src/version_pm3.c: .FORCE default_version_pm3.c $(info [=] GEN $@) - $(Q)$(SH) ../tools/mkversion.sh > $@ || $(PERL) ../tools/mkversion.pl > $@ || $(CP) $< $@ + $(Q)$(SH) ../tools/mkversion.sh > $@ || $(CP) $< $@ # easy printing of MAKE VARIABLES print-%: ; @echo $* = $($*) diff --git a/client/experimental_lib/CMakeLists.txt b/client/experimental_lib/CMakeLists.txt index 618b5af28..e82f73953 100644 --- a/client/experimental_lib/CMakeLists.txt +++ b/client/experimental_lib/CMakeLists.txt @@ -359,7 +359,7 @@ set (TARGET_SOURCES add_custom_command( OUTPUT ${CMAKE_BINARY_DIR}/version_pm3.c - COMMAND sh ${PM3_ROOT}/tools/mkversion.sh > ${CMAKE_BINARY_DIR}/version_pm3.c || perl ${PM3_ROOT}/tools/mkversion.pl > ${CMAKE_BINARY_DIR}/version_pm3.c || ${CMAKE_COMMAND} -E copy ${PM3_ROOT}/common/default_version_pm3.c ${CMAKE_BINARY_DIR}/version_pm3.c + COMMAND sh ${PM3_ROOT}/tools/mkversion.sh > ${CMAKE_BINARY_DIR}/version_pm3.c || ${CMAKE_COMMAND} -E copy ${PM3_ROOT}/common/default_version_pm3.c ${CMAKE_BINARY_DIR}/version_pm3.c DEPENDS ${PM3_ROOT}/common/default_version_pm3.c ) diff --git a/common/default_version_pm3.c b/common/default_version_pm3.c index d2a1deb83..46eac57c9 100644 --- a/common/default_version_pm3.c +++ b/common/default_version_pm3.c @@ -14,7 +14,7 @@ // See LICENSE.txt for the text of the license. //----------------------------------------------------------------------------- #include "common.h" -/* This is the default version_pm3.c file that Makefile.common falls back to if neither sh nor perl are available */ +/* This is the default version_pm3.c file that Makefile.common falls back to if sh is not available */ #ifndef ON_DEVICE #define SECTVERSINFO #else diff --git a/tools/mkversion.pl b/tools/mkversion.pl deleted file mode 100755 index 9f47a355b..000000000 --- a/tools/mkversion.pl +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/perl -w - -# Output a version_pm3.c file that includes information about the current build -# Normally a couple of lines of bash would be enough (see openpcd project, original firmware by Harald Welte and Milosch Meriac) -# but this will, at least in theory, also work on Windows with our current compile environment. -# -- Henryk Plötz 2009-09-28 -# Modified april 2014 because of the move to github. -# --- Martin Holst Swende -# Modified january 2016 to work with Travis-CI -# --- iceman - -# Clear environment locale so that git will not use localized strings -$ENV{'LC_ALL'} = "C"; -$ENV{'LANG'} = "C"; - -# if you are making your own fork, change this line to reflect your fork-name -my $fullgitinfo = 'RRG/Iceman'; -my $ctime; -# GIT status 0 = dirty, 1 = clean , 2 = undecided -my $clean = 2; -my $undecided = (defined $ARGV[0]) && ($ARGV[0] =~ '--undecided'); -# Do we have access to git command? -####### -# solves some bug on macos i.e: -## -# perl ../tools/mkversion.pl .. > version_pm3.c || cp ../common/default_version_pm3.c version_pm3.c -# /usr/bin/which: /usr/bin/which: cannot execute binary file -# fatal: No names found, cannot describe anything. -## -# anyway forcing any kind of shell is at least useless, at worst fatal. -my $commandGIT = "env which git"; - -if ( defined($commandGIT) ) { - - # this goes on Internet and cause major slowdowns on poor connections or intranets, let's comment it - #my $githistory = `git fetch --all`; - # now avoiding the "fatal: No names found, cannot describe anything." error by fallbacking to abbrev hash in such case - my $gitversion = `git describe --dirty --always`; - my $gitbranch = `git rev-parse --abbrev-ref HEAD`; - if (not $undecided) { - $clean = $gitversion =~ '-dirty' ? 0 : 1; - } - if ( defined($gitbranch) and defined($gitversion) ) { - $fullgitinfo = $fullgitinfo.'/'. $gitbranch . '/' . $gitversion; - - my @compiletime = localtime(); - $compiletime[4] += 1; - $compiletime[5] += 1900; - $ctime = sprintf("%6\$04i-%5\$02i-%4\$02i %3\$02i:%2\$02i:%1\$02i", @compiletime); - } else { - $fullgitinfo = $fullgitinfo.'/master/release (git)'; - } -} else { - $fullgitinfo = $fullgitinfo.'/master/release (no_git)'; - my @dl_time = localtime( (stat('../README.md'))[10] ); - $dl_time[4] += 1; - $dl_time[5] += 1900; - $ctime = sprintf("%6\$04i-%5\$02i-%4\$02i %3\$02i:%2\$02i:%1\$02i", @dl_time); -} - -$fullgitinfo =~ s/(\s)//g; - -# Crop so it fits within 50 characters -#$fullgitinfo =~ s/.{50}\K.*//s; -$fullgitinfo = substr $fullgitinfo, 0, 49; - -print < Date: Mon, 14 Feb 2022 02:57:10 +0100 Subject: [PATCH 02/15] Add a fingerprint of the ARM OS source files to detect when a client expects another ARM image --- CHANGELOG.md | 3 ++- client/src/cmdhw.c | 10 ++++++++++ common/commonutil.c | 2 ++ include/common.h | 1 + tools/mkversion.sh | 6 ++++++ 5 files changed, 21 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 39aba3c9b..d6546b87e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 detection of a possible mismatch between client and Proxmark3 image (@doegox) - Changed `hf mf nested`: removed option `--single` redundant with usage of `--tblk` (@doegox) - Fixed `hf mf chk` single block mode (@doegox) - Fixed `hf mf fchk/chk` internal logic to load keys (@doegox) @@ -20,7 +21,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Changed `hf_mf_uidbruteforce` - added support for S70, enhance UID length management (@cactuschibre) - Fixed build issues that may happen from building `mfd_aes_brute` (@linuxgemini) - Added silicon data parsing logic for NXP chips in `hf mfu info` (@linuxgemini) - - Addes luascript `hf_mf_em_util.lua` - Script for emulator configuration (@nisgola) + - Added luascript `hf_mf_em_util.lua` - Script for emulator configuration (@nisgola) - Fixes `hf mf restore` - now takes bin/eml/json as dump files (@iceman1001) - Fixes `script run some_python_script` segfault on armhf architecture (@doegox) - Added `trace extract` - extract authentication parts from trace (@iceman1001) diff --git a/client/src/cmdhw.c b/client/src/cmdhw.c index b228a5c91..52084cadc 100644 --- a/client/src/cmdhw.c +++ b/client/src/cmdhw.c @@ -1073,6 +1073,16 @@ void pm3_version(bool verbose, bool oneliner) { struct p *payload = (struct p *)&resp.data.asBytes; PrintAndLogEx(NORMAL, payload->versionstr); + char *ptr = strstr(payload->versionstr, " os: "); + if (ptr != NULL) { + ptr = strstr(ptr, "\n"); + if (ptr != NULL) { + if (strncmp(ptr-9, g_version_information.armsrc, 9) != 0) { + PrintAndLogEx(NORMAL, "\n:warning: " _RED_("ARM os does not match the source at the time the client was compiled") " :warning:"); + PrintAndLogEx(NORMAL, "Make sure to flash a correct and up-to-date version"); + } + } + } if (strstr(payload->versionstr, "2s30vq100") == NULL) { PrintAndLogEx(NORMAL, " FPGA firmware... %s", _RED_("chip mismatch")); } diff --git a/common/commonutil.c b/common/commonutil.c index a3e026dd1..310578233 100644 --- a/common/commonutil.c +++ b/common/commonutil.c @@ -49,6 +49,8 @@ void FormatVersionInformation(char *dst, int len, const char *prefix, void *vers strncat(dst, " ", len - strlen(dst) - 1); strncat(dst, v->buildtime, len - strlen(dst) - 1); + strncat(dst, " ", len - strlen(dst) - 1); + strncat(dst, v->armsrc, len - strlen(dst) - 1); } /* diff --git a/include/common.h b/include/common.h index 314b67b57..f8fa7e3b0 100644 --- a/include/common.h +++ b/include/common.h @@ -53,6 +53,7 @@ struct version_information_t { char clean; /* 1: Tree was clean, no local changes. 0: Tree was unclean. 2: Couldn't be determined */ char gitversion[50]; /* String with the git revision */ char buildtime[30]; /* string with the build time */ + char armsrc[10]; /* sha256sum of sha256sum of armsrc files */ } PACKED; // debug diff --git a/tools/mkversion.sh b/tools/mkversion.sh index 7f5e242b3..60c13d379 100755 --- a/tools/mkversion.sh +++ b/tools/mkversion.sh @@ -58,6 +58,11 @@ if [ "$fullgitinfoextra" != "$fullgitinfo" ]; then fullgitinfo46="${fullgitinfo%"${fullgitinfoextra}"}" fullgitinfo="${fullgitinfo46}..." fi +sha=$( + pm3path=$(dirname -- "$0")/.. + cd "$pm3path" || return + ls armsrc/*.[ch] common_arm/*.[ch]|grep -v disabled|grep -v version_pm3|xargs sha256sum|sha256sum|grep -o '^.........' +) cat < Date: Mon, 14 Feb 2022 13:37:20 +0100 Subject: [PATCH 03/15] armsrc check: skip if no src available; postpone warning --- armsrc/appmain.c | 1 + client/src/cmdhw.c | 13 +++++++++---- tools/mkversion.sh | 8 +++++--- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index afe10694c..9a61669e2 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -287,6 +287,7 @@ static void SendVersion(void) { strncat(VersionString, "\n", sizeof(VersionString) - strlen(VersionString) - 1); } + FormatVersionInformation(temp, sizeof(temp), " os: ", &g_version_information); strncat(VersionString, temp, sizeof(VersionString) - strlen(VersionString) - 1); strncat(VersionString, "\n", sizeof(VersionString) - strlen(VersionString) - 1); diff --git a/client/src/cmdhw.c b/client/src/cmdhw.c index 52084cadc..c6d4be8da 100644 --- a/client/src/cmdhw.c +++ b/client/src/cmdhw.c @@ -1072,22 +1072,27 @@ void pm3_version(bool verbose, bool oneliner) { struct p *payload = (struct p *)&resp.data.asBytes; - PrintAndLogEx(NORMAL, payload->versionstr); + bool armsrc_mismatch = false; char *ptr = strstr(payload->versionstr, " os: "); if (ptr != NULL) { ptr = strstr(ptr, "\n"); - if (ptr != NULL) { + if ((ptr != NULL) && (strlen(g_version_information.armsrc) == 9)) { if (strncmp(ptr-9, g_version_information.armsrc, 9) != 0) { - PrintAndLogEx(NORMAL, "\n:warning: " _RED_("ARM os does not match the source at the time the client was compiled") " :warning:"); - PrintAndLogEx(NORMAL, "Make sure to flash a correct and up-to-date version"); + armsrc_mismatch = true; } } } + PrintAndLogEx(NORMAL, payload->versionstr); if (strstr(payload->versionstr, "2s30vq100") == NULL) { PrintAndLogEx(NORMAL, " FPGA firmware... %s", _RED_("chip mismatch")); } lookupChipID(payload->id, payload->section_size); + if (armsrc_mismatch) { + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(WARNING, _RED_("ARM firmware does not match the source at the time the client was compiled")); + PrintAndLogEx(WARNING, "Make sure to flash a correct and up-to-date version"); + } } } PrintAndLogEx(NORMAL, ""); diff --git a/tools/mkversion.sh b/tools/mkversion.sh index 60c13d379..c20f9ba4f 100755 --- a/tools/mkversion.sh +++ b/tools/mkversion.sh @@ -59,9 +59,11 @@ if [ "$fullgitinfoextra" != "$fullgitinfo" ]; then fullgitinfo="${fullgitinfo46}..." fi sha=$( - pm3path=$(dirname -- "$0")/.. - cd "$pm3path" || return - ls armsrc/*.[ch] common_arm/*.[ch]|grep -v disabled|grep -v version_pm3|xargs sha256sum|sha256sum|grep -o '^.........' + pm3path=$(dirname -- "$0")/.. + cd "$pm3path" || return + # did we find the src? + [ -f armsrc/appmain.c ] || return + ls armsrc/*.[ch] common_arm/*.[ch]|grep -v disabled|grep -v version_pm3|xargs sha256sum|sha256sum|grep -o '^.........' ) cat < Date: Tue, 15 Feb 2022 03:05:18 +0100 Subject: [PATCH 04/15] visual clue in case of data decompression error at boot time --- armsrc/start.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/armsrc/start.c b/armsrc/start.c index 26a190d68..8e0453467 100644 --- a/armsrc/start.c +++ b/armsrc/start.c @@ -28,6 +28,7 @@ #endif #include "BigBuf.h" #include "string.h" +#include "ticks.h" extern common_area_t g_common_area; extern uint32_t __data_src_start__[], __data_start__[], __data_end__[], __bss_start__[], __bss_end__[]; @@ -40,9 +41,15 @@ static void uncompress_data_section(void) { // uncompress data segment to RAM char *p = (char *)__data_src_start__; int res = LZ4_decompress_safe(p + 4, (char *)__data_start__, avail_in, avail_out); - - if (res < 0) - return; + if (res < 0) { + while (true) { + LED_A_INV(); + LED_B_INV(); + LED_C_INV(); + LED_D_INV(); + SpinDelay(200); + } + } // save the size of the compressed data section g_common_area.arg1 = avail_in; } From 359ca554c013e8ba0585a1f0fafb9d08febf77e5 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 15 Feb 2022 03:08:13 +0100 Subject: [PATCH 05/15] Simplify firmware image generation and preserve original sections --- armsrc/Makefile | 16 ++-------------- armsrc/ldscript | 7 ++----- 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/armsrc/Makefile b/armsrc/Makefile index bd311bebc..86ac7b39f 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -210,14 +210,6 @@ $(OBJDIR)/fullimage.stage1.elf: $(VERSIONOBJ) $(OBJDIR)/fpga_all.o $(THUMBOBJ) $ $(info [=] LD $@) $(Q)$(CROSS_LD) $(CROSS_LDFLAGS) -Wl,-T,ldscript,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ $(LIBS) -$(OBJDIR)/fullimage.nodata.bin: $(OBJDIR)/fullimage.stage1.elf - $(info [-] GEN $@) - $(Q)$(CROSS_OBJCOPY) -O binary -I elf32-littlearm --remove-section .data $^ $@ - -$(OBJDIR)/fullimage.nodata.o: $(OBJDIR)/fullimage.nodata.bin - $(info [-] GEN $@) - $(Q)$(CROSS_OBJCOPY) -O elf32-littlearm -I binary -B arm --rename-section .data=stage1_image $^ $@ - $(OBJDIR)/fullimage.data.bin: $(OBJDIR)/fullimage.stage1.elf $(info [-] GEN $@) $(Q)$(CROSS_OBJCOPY) -O binary -I elf32-littlearm --only-section .data $^ $@ @@ -230,14 +222,10 @@ else $(FPGA_COMPRESSOR) $(filter %.bin,$^) $@ endif -$(OBJDIR)/fullimage.data.o: $(OBJDIR)/fullimage.data.bin.z - $(info [-] GEN $@) - $(Q)$(CROSS_OBJCOPY) -O elf32-littlearm -I binary -B arm --rename-section .data=compressed_data $^ $@ - -$(OBJDIR)/fullimage.elf: $(OBJDIR)/fullimage.nodata.o $(OBJDIR)/fullimage.data.o +$(OBJDIR)/fullimage.elf: $(OBJDIR)/fullimage.stage1.elf $(OBJDIR)/fullimage.data.bin.z ifeq (,$(findstring WITH_NO_COMPRESSION,$(APP_CFLAGS))) $(info [=] LD $@) - $(Q)$(CROSS_LD) $(CROSS_LDFLAGS) -Wl,-T,ldscript,-e,_osimage_entry,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ + $(Q)$(CROSS_OBJCOPY) -O elf32-littlearm -I elf32-littlearm --strip-all --update-section .data=$(OBJDIR)/fullimage.data.bin.z $(OBJDIR)/fullimage.stage1.elf $@ else $(Q)$(CP) $(OBJDIR)/fullimage.stage1.elf $@ endif diff --git a/armsrc/ldscript b/armsrc/ldscript index 4d48d9948..1dd09e937 100644 --- a/armsrc/ldscript +++ b/armsrc/ldscript @@ -24,7 +24,6 @@ SECTIONS } >osimage :text .text : { - KEEP(*(stage1_image)) *(.text) *(.text.*) *(.eh_frame) @@ -36,12 +35,10 @@ SECTIONS *(.rodata) *(.rodata.*) *(fpga_all_bit.data) - KEEP(*(.version_information)) . = ALIGN(8); } >osimage :text .data : { - KEEP(*(compressed_data)) *(.data) *(.data.*) *(.ramfunc) @@ -52,9 +49,9 @@ SECTIONS __data_start__ = ADDR(.data); __data_end__ = __data_start__ + SIZEOF(.data); __os_size__ = SIZEOF(.text) + SIZEOF(.data) + SIZEOF(.rodata); - + .bss : { - __bss_start__ = .; + __bss_start__ = .; *(.bss) *(.bss.*) . = ALIGN(4); From 0ed0735709aeb6cf8e8ad48ff6510aea553943da Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 15 Feb 2022 03:09:52 +0100 Subject: [PATCH 06/15] flasher: parse ELF to check version_information and do ELF checks before looking for a proxmark3 --- client/src/elf.h | 15 ++++- client/src/flash.c | 130 +++++++++++++++++++++++++++++++++++++---- client/src/flash.h | 6 +- client/src/proxmark3.c | 12 +++- 4 files changed, 147 insertions(+), 16 deletions(-) diff --git a/client/src/elf.h b/client/src/elf.h index c05a48018..f79675cfb 100644 --- a/client/src/elf.h +++ b/client/src/elf.h @@ -48,9 +48,22 @@ typedef struct { uint16_t e_phnum; uint16_t e_shentsize; uint16_t e_shnum; - uint16_t e_shtrndx; + uint16_t e_shstrndx; } PACKED Elf32_Ehdr_t; +typedef struct { + uint32_t sh_name; // Section name, index in string tbl + uint32_t sh_type; // Type of section + uint32_t sh_flags; // Miscellaneous section attributes + uint32_t sh_addr; // Section virtual addr at execution + uint32_t sh_offset; // Section file offset + uint32_t sh_size; // Size of section in bytes + uint32_t sh_link; // Index of another section + uint32_t sh_info; // Additional section information + uint32_t sh_addralign; // Section alignment + uint32_t sh_entsize; // Entry size if section holds table +} PACKED Elf32_Shdr_t; + #define PT_NULL 0 #define PT_LOAD 1 #define PT_DYNAMIC 2 diff --git a/client/src/flash.c b/client/src/flash.c index 5bc6fbcab..78365c940 100644 --- a/client/src/flash.c +++ b/client/src/flash.c @@ -29,6 +29,7 @@ #include "at91sam7s512.h" #include "util_posix.h" #include "comms.h" +#include "commonutil.h" #define FLASH_START 0x100000 @@ -84,12 +85,12 @@ static int chipid_to_mem_avail(uint32_t iChipID) { // Turn PHDRs into flasher segments, checking for PHDR sanity and merging adjacent // unaligned segments if needed -static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr_t *phdrs, uint16_t num_phdrs, uint32_t flash_end) { - Elf32_Phdr_t *phdr = phdrs; +static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, uint32_t flash_end) { + Elf32_Phdr_t *phdr = ctx->phdrs; flash_seg_t *seg; uint32_t last_end = 0; - ctx->segments = calloc(sizeof(flash_seg_t) * num_phdrs, sizeof(uint8_t)); + ctx->segments = calloc(sizeof(flash_seg_t) * ctx->num_phdrs, sizeof(uint8_t)); if (!ctx->segments) { PrintAndLogEx(ERR, "Out of memory"); return PM3_EMALLOC; @@ -98,7 +99,7 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr_t *phdr seg = ctx->segments; PrintAndLogEx(SUCCESS, "Loading usable ELF segments:"); - for (int i = 0; i < num_phdrs; i++) { + for (int i = 0; i < ctx->num_phdrs; i++) { if (le32(phdr->p_type) != PT_LOAD) { phdr++; continue; @@ -236,13 +237,16 @@ static int check_segs(flash_file_t *ctx, int can_write_bl, uint32_t flash_end) { return PM3_SUCCESS; } -// Load an ELF file and prepare it for flashing -int flash_load(flash_file_t *ctx, const char *name, int can_write_bl, int flash_size) { +// Read an ELF file and do some checks +int flash_check(flash_file_t *ctx, const char *name) { FILE *fd; Elf32_Ehdr_t ehdr; Elf32_Phdr_t *phdrs = NULL; + Elf32_Shdr_t *shdrs = NULL; uint16_t num_phdrs; - uint32_t flash_end = FLASH_START + flash_size; + uint16_t num_shdrs; + uint8_t *shstr = NULL; + struct version_information_t *vi = NULL; int res = PM3_EUNDEF; fd = fopen(name, "rb"); @@ -305,21 +309,118 @@ int flash_load(flash_file_t *ctx, const char *name, int can_write_bl, int flash_ goto fail; } - res = build_segs_from_phdrs(ctx, fd, phdrs, num_phdrs, flash_end); + num_shdrs = le16(ehdr.e_shnum); + + shdrs = calloc(le16(ehdr.e_shnum) * sizeof(Elf32_Shdr_t), sizeof(uint8_t)); + if (!shdrs) { + PrintAndLogEx(ERR, "Out of memory"); + res = PM3_EMALLOC; + goto fail; + } + if (fseek(fd, le32(ehdr.e_shoff), SEEK_SET) < 0) { + PrintAndLogEx(ERR, "Error while reading ELF SHDRs"); + res = PM3_EFILE; + goto fail; + } + if (fread(shdrs, sizeof(Elf32_Shdr_t), num_shdrs, fd) != num_shdrs) { + res = PM3_EFILE; + PrintAndLogEx(ERR, "Error while reading ELF SHDRs"); + goto fail; + } + + shstr = calloc(shdrs[ehdr.e_shstrndx].sh_size, sizeof(uint8_t)); + if (!shstr) { + PrintAndLogEx(ERR, "Out of memory"); + res = PM3_EMALLOC; + goto fail; + } + if (fseek(fd, le32(shdrs[ehdr.e_shstrndx].sh_offset), SEEK_SET) < 0) { + PrintAndLogEx(ERR, "Error while reading ELF section string table"); + res = PM3_EFILE; + goto fail; + } + if (fread(shstr, shdrs[ehdr.e_shstrndx].sh_size, 1, fd) != 1) { + res = PM3_EFILE; + PrintAndLogEx(ERR, "Error while reading ELF section string table"); + goto fail; + } + + for(uint16_t i=0; iarmsrc, g_version_information.armsrc, 9) != 0) { + PrintAndLogEx(WARNING, _RED_("ARM firmware does not match the source at the time the client was compiled")); + PrintAndLogEx(WARNING, "Make sure to flash a correct and up-to-date version"); +// TODO: prompt user to continue or abort + } + } + free(vi); + } + } + + free(shdrs); + free(shstr); + fclose(fd); + ctx->filename = name; + ctx->phdrs = phdrs; + ctx->num_phdrs = num_phdrs; + return PM3_SUCCESS; + +fail: + if (phdrs) + free(phdrs); + if (shdrs) + free(shdrs); + if (shstr) + free(shstr); + if (vi) + free(vi); + if (fd) + fclose(fd); + flash_free(ctx); + return res; +} + +// Load an ELF file and prepare it for flashing +int flash_load(flash_file_t *ctx, int can_write_bl, int flash_size) { + FILE *fd; + uint32_t flash_end = FLASH_START + flash_size; + int res = PM3_EUNDEF; + + fd = fopen(ctx->filename, "rb"); + if (!fd) { + PrintAndLogEx(ERR, _RED_("Could not open file") " %s >>> ", ctx->filename); + res = PM3_EFILE; + goto fail; + } + + res = build_segs_from_phdrs(ctx, fd, flash_end); if (res != PM3_SUCCESS) goto fail; res = check_segs(ctx, can_write_bl, flash_end); if (res != PM3_SUCCESS) goto fail; - free(phdrs); fclose(fd); - ctx->filename = name; return PM3_SUCCESS; fail: - if (phdrs) - free(phdrs); if (fd) fclose(fd); flash_free(ctx); @@ -625,6 +726,11 @@ void flash_free(flash_file_t *ctx) { ctx->segments = NULL; ctx->num_segs = 0; } + if (ctx->phdrs) { + free(ctx->phdrs); + ctx->phdrs = NULL; + ctx->num_phdrs = 0; + } } // just reset the unit diff --git a/client/src/flash.h b/client/src/flash.h index 518027b4f..beb994c6a 100644 --- a/client/src/flash.h +++ b/client/src/flash.h @@ -20,6 +20,7 @@ #define __FLASH_H__ #include "common.h" +#include "elf.h" #define FLASH_MAX_FILES 4 #define ONE_KB 1024 @@ -32,12 +33,15 @@ typedef struct { typedef struct { const char *filename; + Elf32_Phdr_t *phdrs; + uint16_t num_phdrs; int can_write_bl; int num_segs; flash_seg_t *segments; } flash_file_t; -int flash_load(flash_file_t *ctx, const char *name, int can_write_bl, int flash_size); +int flash_check(flash_file_t *ctx, const char *name); +int flash_load(flash_file_t *ctx, int can_write_bl, int flash_size); int flash_start_flashing(int enable_bl_writes, char *serial_port_name, uint32_t *max_allowed); int flash_write(flash_file_t *ctx); void flash_free(flash_file_t *ctx); diff --git a/client/src/proxmark3.c b/client/src/proxmark3.c index f9e101469..2b0f0ac6d 100644 --- a/client/src/proxmark3.c +++ b/client/src/proxmark3.c @@ -635,6 +635,14 @@ static int flash_pm3(char *serial_port_name, uint8_t num_files, char *filenames[ PrintAndLogEx(SUCCESS, " "_YELLOW_("%s"), filepaths[i]); } + for (int i = 0 ; i < num_files; ++i) { + ret = flash_check(&files[i], filepaths[i]); + if (ret != PM3_SUCCESS) { + goto finish; + } + PrintAndLogEx(NORMAL, ""); + } + if (OpenProxmark(&g_session.current_device, serial_port_name, true, 60, true, FLASHMODE_SPEED)) { PrintAndLogEx(NORMAL, _GREEN_(" found")); } else { @@ -653,7 +661,7 @@ static int flash_pm3(char *serial_port_name, uint8_t num_files, char *filenames[ goto finish; for (int i = 0 ; i < num_files; ++i) { - ret = flash_load(&files[i], filepaths[i], can_write_bl, max_allowed * ONE_KB); + ret = flash_load(&files[i], can_write_bl, max_allowed * ONE_KB); if (ret != PM3_SUCCESS) { goto finish; } @@ -667,7 +675,6 @@ static int flash_pm3(char *serial_port_name, uint8_t num_files, char *filenames[ if (ret != PM3_SUCCESS) { goto finish; } - flash_free(&files[i]); PrintAndLogEx(NORMAL, ""); } @@ -678,6 +685,7 @@ finish: CloseProxmark(g_session.current_device); finish2: for (int i = 0 ; i < num_files; ++i) { + flash_free(&files[i]); if (filepaths[i] != NULL) free(filepaths[i]); } From 2a705d3a44c8e0d24da0c3a71940711ce18e0014 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 15 Feb 2022 03:14:06 +0100 Subject: [PATCH 07/15] make style --- client/src/cmdhw.c | 2 +- client/src/flash.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/src/cmdhw.c b/client/src/cmdhw.c index c6d4be8da..a29338d24 100644 --- a/client/src/cmdhw.c +++ b/client/src/cmdhw.c @@ -1077,7 +1077,7 @@ void pm3_version(bool verbose, bool oneliner) { if (ptr != NULL) { ptr = strstr(ptr, "\n"); if ((ptr != NULL) && (strlen(g_version_information.armsrc) == 9)) { - if (strncmp(ptr-9, g_version_information.armsrc, 9) != 0) { + if (strncmp(ptr - 9, g_version_information.armsrc, 9) != 0) { armsrc_mismatch = true; } } diff --git a/client/src/flash.c b/client/src/flash.c index 78365c940..7da19840f 100644 --- a/client/src/flash.c +++ b/client/src/flash.c @@ -345,8 +345,8 @@ int flash_check(flash_file_t *ctx, const char *name) { goto fail; } - for(uint16_t i=0; iarmsrc, g_version_information.armsrc, 9) != 0) { - PrintAndLogEx(WARNING, _RED_("ARM firmware does not match the source at the time the client was compiled")); - PrintAndLogEx(WARNING, "Make sure to flash a correct and up-to-date version"); + PrintAndLogEx(WARNING, _RED_("ARM firmware does not match the source at the time the client was compiled")); + PrintAndLogEx(WARNING, "Make sure to flash a correct and up-to-date version"); // TODO: prompt user to continue or abort } } From 72f7bc762d8480fecdbcea1a1ec243d2e2a4b728 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 16 Feb 2022 01:03:32 +0100 Subject: [PATCH 08/15] Flasher: read the firmware file in one go --- client/src/flash.c | 293 ++++++++++++++++------------------------- client/src/flash.h | 7 +- client/src/proxmark3.c | 11 +- 3 files changed, 120 insertions(+), 191 deletions(-) diff --git a/client/src/flash.c b/client/src/flash.c index 7da19840f..6bd525ce0 100644 --- a/client/src/flash.c +++ b/client/src/flash.c @@ -85,7 +85,8 @@ static int chipid_to_mem_avail(uint32_t iChipID) { // Turn PHDRs into flasher segments, checking for PHDR sanity and merging adjacent // unaligned segments if needed -static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, uint32_t flash_end) { +static int build_segs_from_phdrs(flash_file_t *ctx, uint32_t flash_size) { + uint32_t flash_end = FLASH_START + flash_size; Elf32_Phdr_t *phdr = ctx->phdrs; flash_seg_t *seg; uint32_t last_end = 0; @@ -149,11 +150,7 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, uint32_t flash_end PrintAndLogEx(ERR, "Error: Out of memory"); return PM3_EMALLOC; } - if (fseek(fd, offset, SEEK_SET) < 0 || fread(data, 1, filesz, fd) != filesz) { - PrintAndLogEx(ERR, "Error while reading PHDR payload"); - free(data); - return PM3_EFILE; - } + memcpy(data, ctx->elf + offset, filesz); uint32_t block_offset = paddr & (BLOCK_SIZE - 1); if (block_offset) { @@ -209,7 +206,8 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, uint32_t flash_end } // Sanity check segments and check for bootloader writes -static int check_segs(flash_file_t *ctx, int can_write_bl, uint32_t flash_end) { +static int check_segs(flash_file_t *ctx, int can_write_bl, uint32_t flash_size) { + uint32_t flash_end = FLASH_START + flash_size; for (int i = 0; i < ctx->num_segs; i++) { flash_seg_t *seg = &ctx->segments[i]; @@ -237,170 +235,13 @@ static int check_segs(flash_file_t *ctx, int can_write_bl, uint32_t flash_end) { return PM3_SUCCESS; } -// Read an ELF file and do some checks -int flash_check(flash_file_t *ctx, const char *name) { +// Load an ELF file for flashing +int flash_load(flash_file_t *ctx) { FILE *fd; - Elf32_Ehdr_t ehdr; - Elf32_Phdr_t *phdrs = NULL; + Elf32_Ehdr_t *ehdr; Elf32_Shdr_t *shdrs = NULL; - uint16_t num_phdrs; - uint16_t num_shdrs; uint8_t *shstr = NULL; - struct version_information_t *vi = NULL; - int res = PM3_EUNDEF; - - fd = fopen(name, "rb"); - if (!fd) { - PrintAndLogEx(ERR, _RED_("Could not open file") " %s >>> ", name); - res = PM3_EFILE; - goto fail; - } - - PrintAndLogEx(SUCCESS, _CYAN_("Loading ELF file") _YELLOW_(" %s"), name); - - if (fread(&ehdr, sizeof(ehdr), 1, fd) != 1) { - PrintAndLogEx(ERR, "Error while reading ELF file header"); - res = PM3_EFILE; - goto fail; - } - if (memcmp(ehdr.e_ident, elf_ident, sizeof(elf_ident)) - || le32(ehdr.e_version) != 1) { - PrintAndLogEx(ERR, "Not an ELF file or wrong ELF type"); - res = PM3_EFILE; - goto fail; - } - if (le16(ehdr.e_type) != ET_EXEC) { - PrintAndLogEx(ERR, "ELF is not executable"); - res = PM3_EFILE; - goto fail; - } - if (le16(ehdr.e_machine) != EM_ARM) { - PrintAndLogEx(ERR, "Wrong ELF architecture"); - res = PM3_EFILE; - goto fail; - } - if (!ehdr.e_phnum || !ehdr.e_phoff) { - PrintAndLogEx(ERR, "ELF has no PHDRs"); - res = PM3_EFILE; - goto fail; - } - if (le16(ehdr.e_phentsize) != sizeof(Elf32_Phdr_t)) { - // could be a structure padding issue... - PrintAndLogEx(ERR, "Either the ELF file or this code is made of fail"); - res = PM3_EFILE; - goto fail; - } - num_phdrs = le16(ehdr.e_phnum); - - phdrs = calloc(le16(ehdr.e_phnum) * sizeof(Elf32_Phdr_t), sizeof(uint8_t)); - if (!phdrs) { - PrintAndLogEx(ERR, "Out of memory"); - res = PM3_EMALLOC; - goto fail; - } - if (fseek(fd, le32(ehdr.e_phoff), SEEK_SET) < 0) { - PrintAndLogEx(ERR, "Error while reading ELF PHDRs"); - res = PM3_EFILE; - goto fail; - } - if (fread(phdrs, sizeof(Elf32_Phdr_t), num_phdrs, fd) != num_phdrs) { - res = PM3_EFILE; - PrintAndLogEx(ERR, "Error while reading ELF PHDRs"); - goto fail; - } - - num_shdrs = le16(ehdr.e_shnum); - - shdrs = calloc(le16(ehdr.e_shnum) * sizeof(Elf32_Shdr_t), sizeof(uint8_t)); - if (!shdrs) { - PrintAndLogEx(ERR, "Out of memory"); - res = PM3_EMALLOC; - goto fail; - } - if (fseek(fd, le32(ehdr.e_shoff), SEEK_SET) < 0) { - PrintAndLogEx(ERR, "Error while reading ELF SHDRs"); - res = PM3_EFILE; - goto fail; - } - if (fread(shdrs, sizeof(Elf32_Shdr_t), num_shdrs, fd) != num_shdrs) { - res = PM3_EFILE; - PrintAndLogEx(ERR, "Error while reading ELF SHDRs"); - goto fail; - } - - shstr = calloc(shdrs[ehdr.e_shstrndx].sh_size, sizeof(uint8_t)); - if (!shstr) { - PrintAndLogEx(ERR, "Out of memory"); - res = PM3_EMALLOC; - goto fail; - } - if (fseek(fd, le32(shdrs[ehdr.e_shstrndx].sh_offset), SEEK_SET) < 0) { - PrintAndLogEx(ERR, "Error while reading ELF section string table"); - res = PM3_EFILE; - goto fail; - } - if (fread(shstr, shdrs[ehdr.e_shstrndx].sh_size, 1, fd) != 1) { - res = PM3_EFILE; - PrintAndLogEx(ERR, "Error while reading ELF section string table"); - goto fail; - } - - for (uint16_t i = 0; i < ehdr.e_shnum; i++) { - if (strcmp(((char *)shstr) + shdrs[i].sh_name, ".version_information") == 0) { - vi = calloc(shdrs[i].sh_size, sizeof(uint8_t)); - if (!vi) { - PrintAndLogEx(ERR, "Out of memory"); - res = PM3_EMALLOC; - goto fail; - } - if (fseek(fd, le32(shdrs[i].sh_offset), SEEK_SET) < 0) { - PrintAndLogEx(ERR, "Error while reading ELF version_information section"); - res = PM3_EFILE; - goto fail; - } - if (fread(vi, shdrs[i].sh_size, 1, fd) != 1) { - res = PM3_EFILE; - PrintAndLogEx(ERR, "Error while reading ELF version_information section"); - goto fail; - } - if (strlen(g_version_information.armsrc) == 9) { - if (strncmp(vi->armsrc, g_version_information.armsrc, 9) != 0) { - PrintAndLogEx(WARNING, _RED_("ARM firmware does not match the source at the time the client was compiled")); - PrintAndLogEx(WARNING, "Make sure to flash a correct and up-to-date version"); -// TODO: prompt user to continue or abort - } - } - free(vi); - } - } - - free(shdrs); - free(shstr); - fclose(fd); - ctx->filename = name; - ctx->phdrs = phdrs; - ctx->num_phdrs = num_phdrs; - return PM3_SUCCESS; - -fail: - if (phdrs) - free(phdrs); - if (shdrs) - free(shdrs); - if (shstr) - free(shstr); - if (vi) - free(vi); - if (fd) - fclose(fd); - flash_free(ctx); - return res; -} - -// Load an ELF file and prepare it for flashing -int flash_load(flash_file_t *ctx, int can_write_bl, int flash_size) { - FILE *fd; - uint32_t flash_end = FLASH_START + flash_size; + struct version_information_t *vi = NULL; int res = PM3_EUNDEF; fd = fopen(ctx->filename, "rb"); @@ -410,19 +251,104 @@ int flash_load(flash_file_t *ctx, int can_write_bl, int flash_size) { goto fail; } - res = build_segs_from_phdrs(ctx, fd, flash_end); - if (res != PM3_SUCCESS) - goto fail; - res = check_segs(ctx, can_write_bl, flash_end); - if (res != PM3_SUCCESS) - goto fail; + PrintAndLogEx(SUCCESS, _CYAN_("Loading ELF file") _YELLOW_(" %s"), ctx->filename); + // get filesize in order to malloc memory + fseek(fd, 0, SEEK_END); + long fsize = ftell(fd); + fseek(fd, 0, SEEK_SET); + + if (fsize <= 0) { + PrintAndLogEx(ERR, "Error, when getting filesize"); + res = PM3_EFILE; + fclose(fd); + goto fail; + } + + ctx->elf = calloc(fsize, sizeof(uint8_t)); + if (!ctx->elf) { + PrintAndLogEx(ERR, "Error, cannot allocate memory"); + res = PM3_EMALLOC; + fclose(fd); + goto fail; + } + + size_t bytes_read = fread(ctx->elf, 1, fsize, fd); fclose(fd); + + if (bytes_read != fsize) { + PrintAndLogEx(ERR, "Error, bytes read mismatch file size"); + res = PM3_EFILE; + goto fail; + } + + ehdr = (Elf32_Ehdr_t *)ctx->elf; + if (memcmp(ehdr->e_ident, elf_ident, sizeof(elf_ident)) + || le32(ehdr->e_version) != 1) { + PrintAndLogEx(ERR, "Not an ELF file or wrong ELF type"); + res = PM3_EFILE; + goto fail; + } + if (le16(ehdr->e_type) != ET_EXEC) { + PrintAndLogEx(ERR, "ELF is not executable"); + res = PM3_EFILE; + goto fail; + } + if (le16(ehdr->e_machine) != EM_ARM) { + PrintAndLogEx(ERR, "Wrong ELF architecture"); + res = PM3_EFILE; + goto fail; + } + if (!ehdr->e_phnum || !ehdr->e_phoff) { + PrintAndLogEx(ERR, "ELF has no PHDRs"); + res = PM3_EFILE; + goto fail; + } + if (le16(ehdr->e_phentsize) != sizeof(Elf32_Phdr_t)) { + // could be a structure padding issue... + PrintAndLogEx(ERR, "Either the ELF file or this code is made of fail"); + res = PM3_EFILE; + goto fail; + } + ctx->num_phdrs = le16(ehdr->e_phnum); + ctx->phdrs = (Elf32_Phdr_t *)(ctx->elf + le32(ehdr->e_phoff)); + shdrs = (Elf32_Shdr_t *)(ctx->elf + le32(ehdr->e_shoff)); + shdrs = (Elf32_Shdr_t *)(ctx->elf + le32(ehdr->e_shoff)); + shstr = ctx->elf + le32(shdrs[ehdr->e_shstrndx].sh_offset); + + for (uint16_t i = 0; i < le16(ehdr->e_shnum); i++) { + if (strcmp(((char *)shstr) + shdrs[i].sh_name, ".version_information") == 0) { + vi = (struct version_information_t *)(ctx->elf + le32(shdrs[i].sh_offset)); + if (strlen(g_version_information.armsrc) == 9) { + if (strncmp(vi->armsrc, g_version_information.armsrc, 9) != 0) { + PrintAndLogEx(WARNING, _RED_("ARM firmware does not match the source at the time the client was compiled")); + PrintAndLogEx(WARNING, "Make sure to flash a correct and up-to-date version"); +// TODO: prompt user to continue or abort + } + } + } + } + return PM3_SUCCESS; + +fail: + flash_free(ctx); + return res; +} + +// Prepare an ELF file for flashing +int flash_prepare(flash_file_t *ctx, int can_write_bl, int flash_size) { + int res = PM3_EUNDEF; + + res = build_segs_from_phdrs(ctx, flash_size); + if (res != PM3_SUCCESS) + goto fail; + res = check_segs(ctx, can_write_bl, flash_size); + if (res != PM3_SUCCESS) + goto fail; + return PM3_SUCCESS; fail: - if (fd) - fclose(fd); flash_free(ctx); return res; } @@ -719,6 +645,16 @@ int flash_write(flash_file_t *ctx) { void flash_free(flash_file_t *ctx) { if (!ctx) return; + if (ctx->filename != NULL) { + free(ctx->filename); + ctx->filename = NULL; + } + if (ctx->elf) { + free(ctx->elf); + ctx->elf = NULL; + ctx->phdrs = NULL; + ctx->num_phdrs = 0; + } if (ctx->segments) { for (int i = 0; i < ctx->num_segs; i++) free(ctx->segments[i].data); @@ -726,11 +662,6 @@ void flash_free(flash_file_t *ctx) { ctx->segments = NULL; ctx->num_segs = 0; } - if (ctx->phdrs) { - free(ctx->phdrs); - ctx->phdrs = NULL; - ctx->num_phdrs = 0; - } } // just reset the unit diff --git a/client/src/flash.h b/client/src/flash.h index beb994c6a..b4cac2e2a 100644 --- a/client/src/flash.h +++ b/client/src/flash.h @@ -32,7 +32,8 @@ typedef struct { } flash_seg_t; typedef struct { - const char *filename; + char *filename; + uint8_t *elf; Elf32_Phdr_t *phdrs; uint16_t num_phdrs; int can_write_bl; @@ -40,8 +41,8 @@ typedef struct { flash_seg_t *segments; } flash_file_t; -int flash_check(flash_file_t *ctx, const char *name); -int flash_load(flash_file_t *ctx, int can_write_bl, int flash_size); +int flash_load(flash_file_t *ctx); +int flash_prepare(flash_file_t *ctx, int can_write_bl, int flash_size); int flash_start_flashing(int enable_bl_writes, char *serial_port_name, uint32_t *max_allowed); int flash_write(flash_file_t *ctx); void flash_free(flash_file_t *ctx); diff --git a/client/src/proxmark3.c b/client/src/proxmark3.c index 2b0f0ac6d..1fce51cd8 100644 --- a/client/src/proxmark3.c +++ b/client/src/proxmark3.c @@ -607,7 +607,6 @@ static int flash_pm3(char *serial_port_name, uint8_t num_files, char *filenames[ int ret = PM3_EUNDEF; flash_file_t files[FLASH_MAX_FILES]; memset(files, 0, sizeof(files)); - char *filepaths[FLASH_MAX_FILES] = {0}; if (serial_port_name == NULL) { PrintAndLogEx(ERR, "You must specify a port.\n"); @@ -627,16 +626,16 @@ static int flash_pm3(char *serial_port_name, uint8_t num_files, char *filenames[ if (ret != PM3_SUCCESS) { goto finish2; } - filepaths[i] = path; + files[i].filename = path; } PrintAndLogEx(SUCCESS, "About to use the following file%s:", num_files > 1 ? "s" : ""); for (int i = 0 ; i < num_files; ++i) { - PrintAndLogEx(SUCCESS, " "_YELLOW_("%s"), filepaths[i]); + PrintAndLogEx(SUCCESS, " "_YELLOW_("%s"), files[i].filename); } for (int i = 0 ; i < num_files; ++i) { - ret = flash_check(&files[i], filepaths[i]); + ret = flash_load(&files[i]); if (ret != PM3_SUCCESS) { goto finish; } @@ -661,7 +660,7 @@ static int flash_pm3(char *serial_port_name, uint8_t num_files, char *filenames[ goto finish; for (int i = 0 ; i < num_files; ++i) { - ret = flash_load(&files[i], can_write_bl, max_allowed * ONE_KB); + ret = flash_prepare(&files[i], can_write_bl, max_allowed * ONE_KB); if (ret != PM3_SUCCESS) { goto finish; } @@ -686,8 +685,6 @@ finish: finish2: for (int i = 0 ; i < num_files; ++i) { flash_free(&files[i]); - if (filepaths[i] != NULL) - free(filepaths[i]); } if (ret == PM3_SUCCESS) PrintAndLogEx(SUCCESS, _CYAN_("All done")); From 5997f231395a25dc52b2965ed5a5c5cedaa18589 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 16 Feb 2022 01:38:44 +0100 Subject: [PATCH 09/15] flasher: ask confirmation if fw mismatch, fix segfault on abort --- client/src/flash.c | 9 +++++++-- client/src/proxmark3.c | 6 ++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/client/src/flash.c b/client/src/flash.c index 6bd525ce0..076b4859e 100644 --- a/client/src/flash.c +++ b/client/src/flash.c @@ -322,8 +322,13 @@ int flash_load(flash_file_t *ctx) { if (strlen(g_version_information.armsrc) == 9) { if (strncmp(vi->armsrc, g_version_information.armsrc, 9) != 0) { PrintAndLogEx(WARNING, _RED_("ARM firmware does not match the source at the time the client was compiled")); - PrintAndLogEx(WARNING, "Make sure to flash a correct and up-to-date version"); -// TODO: prompt user to continue or abort + PrintAndLogEx(INFO, "Make sure to flash a correct and up-to-date version"); + PrintAndLogEx(NORMAL, "Do you want to flash the current image? (yes/no)"); + char answer[10]; + if ((fgets (answer, sizeof(answer), stdin) == NULL) || (strncmp(answer, "yes", 3) != 0)) { + res = PM3_EOPABORTED; + goto fail; + } } } } diff --git a/client/src/proxmark3.c b/client/src/proxmark3.c index 1fce51cd8..2a3d3befa 100644 --- a/client/src/proxmark3.c +++ b/client/src/proxmark3.c @@ -637,7 +637,7 @@ static int flash_pm3(char *serial_port_name, uint8_t num_files, char *filenames[ for (int i = 0 ; i < num_files; ++i) { ret = flash_load(&files[i]); if (ret != PM3_SUCCESS) { - goto finish; + goto finish2; } PrintAndLogEx(NORMAL, ""); } @@ -679,7 +679,7 @@ static int flash_pm3(char *serial_port_name, uint8_t num_files, char *filenames[ finish: if (ret != PM3_SUCCESS) - PrintAndLogEx(INFO, "The flashing procedure failed, follow the suggested steps!"); + PrintAndLogEx(WARNING, "The flashing procedure failed, follow the suggested steps!"); ret = flash_stop_flashing(); CloseProxmark(g_session.current_device); finish2: @@ -688,6 +688,8 @@ finish2: } if (ret == PM3_SUCCESS) PrintAndLogEx(SUCCESS, _CYAN_("All done")); + else if (ret == PM3_EOPABORTED) + PrintAndLogEx(FAILED, "Aborted by user"); else PrintAndLogEx(ERR, "Aborted on error"); PrintAndLogEx(INFO, "\nHave a nice day!"); From bfffea6e6ccaa43abaf1aa473caa50e8828c2cfb Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 16 Feb 2022 01:58:58 +0100 Subject: [PATCH 10/15] Flasher: show the detailed firmware version --- client/src/flash.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/src/flash.c b/client/src/flash.c index 076b4859e..44ed6f446 100644 --- a/client/src/flash.c +++ b/client/src/flash.c @@ -319,6 +319,9 @@ int flash_load(flash_file_t *ctx) { for (uint16_t i = 0; i < le16(ehdr->e_shnum); i++) { if (strcmp(((char *)shstr) + shdrs[i].sh_name, ".version_information") == 0) { vi = (struct version_information_t *)(ctx->elf + le32(shdrs[i].sh_offset)); + char temp[PM3_CMD_DATA_SIZE - 12]; // same limit as for ARM image + FormatVersionInformation(temp, sizeof(temp), "", vi); + PrintAndLogEx(SUCCESS, _CYAN_("ELF file version") _YELLOW_(" %s"), temp); if (strlen(g_version_information.armsrc) == 9) { if (strncmp(vi->armsrc, g_version_information.armsrc, 9) != 0) { PrintAndLogEx(WARNING, _RED_("ARM firmware does not match the source at the time the client was compiled")); From 3cbf64c894733eaf23f23d664e11b0663882f16d Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 16 Feb 2022 02:51:29 +0100 Subject: [PATCH 11/15] Flasher: display and check bootloader elf as well --- client/src/flash.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/client/src/flash.c b/client/src/flash.c index 44ed6f446..843597b50 100644 --- a/client/src/flash.c +++ b/client/src/flash.c @@ -316,10 +316,35 @@ int flash_load(flash_file_t *ctx) { shdrs = (Elf32_Shdr_t *)(ctx->elf + le32(ehdr->e_shoff)); shstr = ctx->elf + le32(shdrs[ehdr->e_shstrndx].sh_offset); + char temp[PM3_CMD_DATA_SIZE - 12]; // same limit as for ARM image for (uint16_t i = 0; i < le16(ehdr->e_shnum); i++) { if (strcmp(((char *)shstr) + shdrs[i].sh_name, ".version_information") == 0) { vi = (struct version_information_t *)(ctx->elf + le32(shdrs[i].sh_offset)); - char temp[PM3_CMD_DATA_SIZE - 12]; // same limit as for ARM image + FormatVersionInformation(temp, sizeof(temp), "", vi); + PrintAndLogEx(SUCCESS, _CYAN_("ELF file version") _YELLOW_(" %s"), temp); + if (strlen(g_version_information.armsrc) == 9) { + if (strncmp(vi->armsrc, g_version_information.armsrc, 9) != 0) { + PrintAndLogEx(WARNING, _RED_("ARM firmware does not match the source at the time the client was compiled")); + PrintAndLogEx(INFO, "Make sure to flash a correct and up-to-date version"); + PrintAndLogEx(NORMAL, "Do you want to flash the current image? (yes/no)"); + char answer[10]; + if ((fgets (answer, sizeof(answer), stdin) == NULL) || (strncmp(answer, "yes", 3) != 0)) { + res = PM3_EOPABORTED; + goto fail; + } + } + } + } + if (strcmp(((char *)shstr) + shdrs[i].sh_name, ".bootphase1") == 0) { + uint32_t offset = *(uint32_t*)(ctx->elf + le32(shdrs[i].sh_offset) + le32(shdrs[i].sh_size) - 4); + if (offset < le32(shdrs[i].sh_addr)) + continue; + offset -= le32(shdrs[i].sh_addr); + if (offset >= le32(shdrs[i].sh_size)) + continue; + vi = (struct version_information_t *)(ctx->elf + le32(shdrs[i].sh_offset) + offset); + if (vi->magic != VERSION_INFORMATION_MAGIC) + continue; FormatVersionInformation(temp, sizeof(temp), "", vi); PrintAndLogEx(SUCCESS, _CYAN_("ELF file version") _YELLOW_(" %s"), temp); if (strlen(g_version_information.armsrc) == 9) { From 6ead44933ac50a263c0e36c9b312e350d6147202 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 16 Feb 2022 03:32:59 +0100 Subject: [PATCH 12/15] Flasher: factorize and prompt also wehn we can't check the version --- client/src/flash.c | 82 +++++++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/client/src/flash.c b/client/src/flash.c index 843597b50..4231b82a9 100644 --- a/client/src/flash.c +++ b/client/src/flash.c @@ -235,6 +235,34 @@ static int check_segs(flash_file_t *ctx, int can_write_bl, uint32_t flash_size) return PM3_SUCCESS; } +static int ask_confirmation(void) { + PrintAndLogEx(INFO, "Make sure to flash a correct and up-to-date version"); + PrintAndLogEx(NORMAL, "Do you want to flash the current image? (yes/no)"); + char answer[10]; + if ((fgets (answer, sizeof(answer), stdin) == NULL) || (strncmp(answer, "yes", 3) != 0)) { + return PM3_EOPABORTED; + } else { + return PM3_SUCCESS; + } +} + +static int print_and_validate_version(struct version_information_t *vi) { + if (vi->magic != VERSION_INFORMATION_MAGIC) + return PM3_EFILE; + char temp[PM3_CMD_DATA_SIZE - 12]; // same limit as for ARM image + FormatVersionInformation(temp, sizeof(temp), "", vi); + PrintAndLogEx(SUCCESS, _CYAN_("ELF file version") _YELLOW_(" %s"), temp); + if (strlen(g_version_information.armsrc) == 9) { + if (strncmp(vi->armsrc, g_version_information.armsrc, 9) != 0) { + PrintAndLogEx(WARNING, _RED_("ARM firmware does not match the source at the time the client was compiled")); + return ask_confirmation(); + } else { + return PM3_SUCCESS; + } + } + return PM3_EUNDEF; +} + // Load an ELF file for flashing int flash_load(flash_file_t *ctx) { FILE *fd; @@ -316,53 +344,33 @@ int flash_load(flash_file_t *ctx) { shdrs = (Elf32_Shdr_t *)(ctx->elf + le32(ehdr->e_shoff)); shstr = ctx->elf + le32(shdrs[ehdr->e_shstrndx].sh_offset); - char temp[PM3_CMD_DATA_SIZE - 12]; // same limit as for ARM image for (uint16_t i = 0; i < le16(ehdr->e_shnum); i++) { if (strcmp(((char *)shstr) + shdrs[i].sh_name, ".version_information") == 0) { vi = (struct version_information_t *)(ctx->elf + le32(shdrs[i].sh_offset)); - FormatVersionInformation(temp, sizeof(temp), "", vi); - PrintAndLogEx(SUCCESS, _CYAN_("ELF file version") _YELLOW_(" %s"), temp); - if (strlen(g_version_information.armsrc) == 9) { - if (strncmp(vi->armsrc, g_version_information.armsrc, 9) != 0) { - PrintAndLogEx(WARNING, _RED_("ARM firmware does not match the source at the time the client was compiled")); - PrintAndLogEx(INFO, "Make sure to flash a correct and up-to-date version"); - PrintAndLogEx(NORMAL, "Do you want to flash the current image? (yes/no)"); - char answer[10]; - if ((fgets (answer, sizeof(answer), stdin) == NULL) || (strncmp(answer, "yes", 3) != 0)) { - res = PM3_EOPABORTED; - goto fail; - } - } - } + res = print_and_validate_version(vi); + break; } if (strcmp(((char *)shstr) + shdrs[i].sh_name, ".bootphase1") == 0) { uint32_t offset = *(uint32_t*)(ctx->elf + le32(shdrs[i].sh_offset) + le32(shdrs[i].sh_size) - 4); - if (offset < le32(shdrs[i].sh_addr)) - continue; - offset -= le32(shdrs[i].sh_addr); - if (offset >= le32(shdrs[i].sh_size)) - continue; - vi = (struct version_information_t *)(ctx->elf + le32(shdrs[i].sh_offset) + offset); - if (vi->magic != VERSION_INFORMATION_MAGIC) - continue; - FormatVersionInformation(temp, sizeof(temp), "", vi); - PrintAndLogEx(SUCCESS, _CYAN_("ELF file version") _YELLOW_(" %s"), temp); - if (strlen(g_version_information.armsrc) == 9) { - if (strncmp(vi->armsrc, g_version_information.armsrc, 9) != 0) { - PrintAndLogEx(WARNING, _RED_("ARM firmware does not match the source at the time the client was compiled")); - PrintAndLogEx(INFO, "Make sure to flash a correct and up-to-date version"); - PrintAndLogEx(NORMAL, "Do you want to flash the current image? (yes/no)"); - char answer[10]; - if ((fgets (answer, sizeof(answer), stdin) == NULL) || (strncmp(answer, "yes", 3) != 0)) { - res = PM3_EOPABORTED; - goto fail; - } + if (offset >= le32(shdrs[i].sh_addr)) { + offset -= le32(shdrs[i].sh_addr); + if (offset < le32(shdrs[i].sh_size)) { + vi = (struct version_information_t *)(ctx->elf + le32(shdrs[i].sh_offset) + offset); + res = print_and_validate_version(vi); } } + break; } } - return PM3_SUCCESS; - + if (res == PM3_SUCCESS) + return res; + if (res == PM3_EOPABORTED) + goto fail; + // We could not find proper version_information, so we ask for confirmation + PrintAndLogEx(WARNING, "Unable to check version_information"); + res = ask_confirmation(); + if (res == PM3_SUCCESS) + return res; fail: flash_free(ctx); return res; From cb209a9b4778320b416aa040836912b71e31a1e1 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 25 Feb 2022 00:01:09 +0100 Subject: [PATCH 13/15] mkversion: ignore fpga_version_info as it might be unavailable when mkversion is called by client compilation --- tools/mkversion.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/mkversion.sh b/tools/mkversion.sh index c20f9ba4f..31a1dd121 100755 --- a/tools/mkversion.sh +++ b/tools/mkversion.sh @@ -63,7 +63,7 @@ sha=$( cd "$pm3path" || return # did we find the src? [ -f armsrc/appmain.c ] || return - ls armsrc/*.[ch] common_arm/*.[ch]|grep -v disabled|grep -v version_pm3|xargs sha256sum|sha256sum|grep -o '^.........' + ls armsrc/*.[ch] common_arm/*.[ch]|grep -E -v "(disabled|version_pm3|fpga_version_info)"|xargs sha256sum|sha256sum|grep -o '^.........' ) cat < Date: Fri, 25 Feb 2022 00:35:30 +0100 Subject: [PATCH 14/15] flasher: add option --force rather than interactive prompt --- client/src/flash.c | 29 +++++++++-------------------- client/src/flash.h | 2 +- client/src/proxmark3.c | 16 ++++++++++++---- pm3 | 40 +++++++++++++++++++++++++++++++++++++--- 4 files changed, 59 insertions(+), 28 deletions(-) diff --git a/client/src/flash.c b/client/src/flash.c index 4231b82a9..b8e5d602b 100644 --- a/client/src/flash.c +++ b/client/src/flash.c @@ -235,17 +235,6 @@ static int check_segs(flash_file_t *ctx, int can_write_bl, uint32_t flash_size) return PM3_SUCCESS; } -static int ask_confirmation(void) { - PrintAndLogEx(INFO, "Make sure to flash a correct and up-to-date version"); - PrintAndLogEx(NORMAL, "Do you want to flash the current image? (yes/no)"); - char answer[10]; - if ((fgets (answer, sizeof(answer), stdin) == NULL) || (strncmp(answer, "yes", 3) != 0)) { - return PM3_EOPABORTED; - } else { - return PM3_SUCCESS; - } -} - static int print_and_validate_version(struct version_information_t *vi) { if (vi->magic != VERSION_INFORMATION_MAGIC) return PM3_EFILE; @@ -255,7 +244,7 @@ static int print_and_validate_version(struct version_information_t *vi) { if (strlen(g_version_information.armsrc) == 9) { if (strncmp(vi->armsrc, g_version_information.armsrc, 9) != 0) { PrintAndLogEx(WARNING, _RED_("ARM firmware does not match the source at the time the client was compiled")); - return ask_confirmation(); + return PM3_EINVARG; } else { return PM3_SUCCESS; } @@ -264,7 +253,7 @@ static int print_and_validate_version(struct version_information_t *vi) { } // Load an ELF file for flashing -int flash_load(flash_file_t *ctx) { +int flash_load(flash_file_t *ctx, bool force) { FILE *fd; Elf32_Ehdr_t *ehdr; Elf32_Shdr_t *shdrs = NULL; @@ -364,13 +353,13 @@ int flash_load(flash_file_t *ctx) { } if (res == PM3_SUCCESS) return res; - if (res == PM3_EOPABORTED) - goto fail; - // We could not find proper version_information, so we ask for confirmation - PrintAndLogEx(WARNING, "Unable to check version_information"); - res = ask_confirmation(); - if (res == PM3_SUCCESS) - return res; + // We could not find proper version_information + if (res == PM3_EUNDEF) + PrintAndLogEx(WARNING, "Unable to check version_information"); + PrintAndLogEx(INFO, "Make sure to flash a correct and up-to-date version"); + PrintAndLogEx(INFO, "You can force flashing this firmware by using the option '--force'"); + if (force) + return PM3_SUCCESS; fail: flash_free(ctx); return res; diff --git a/client/src/flash.h b/client/src/flash.h index b4cac2e2a..5c2535620 100644 --- a/client/src/flash.h +++ b/client/src/flash.h @@ -41,7 +41,7 @@ typedef struct { flash_seg_t *segments; } flash_file_t; -int flash_load(flash_file_t *ctx); +int flash_load(flash_file_t *ctx, bool force); int flash_prepare(flash_file_t *ctx, int can_write_bl, int flash_size); int flash_start_flashing(int enable_bl_writes, char *serial_port_name, uint32_t *max_allowed); int flash_write(flash_file_t *ctx); diff --git a/client/src/proxmark3.c b/client/src/proxmark3.c index 2a3d3befa..26062f9d7 100644 --- a/client/src/proxmark3.c +++ b/client/src/proxmark3.c @@ -576,7 +576,8 @@ static void show_help(bool showFullHelp, char *exec_name) { PrintAndLogEx(NORMAL, " --incognito do not use history, prefs file nor log files"); PrintAndLogEx(NORMAL, "\nOptions in flasher mode:"); PrintAndLogEx(NORMAL, " --flash flash Proxmark3, requires at least one --image"); - PrintAndLogEx(NORMAL, " --unlock-bootloader Enable flashing of bootloader area *DANGEROUS* (need --flash or --flash-info)"); + PrintAndLogEx(NORMAL, " --unlock-bootloader Enable flashing of bootloader area *DANGEROUS* (need --flash)"); + PrintAndLogEx(NORMAL, " --force Enable flashing even if firmware seems to not match client version"); PrintAndLogEx(NORMAL, " --image image to flash. Can be specified several times."); PrintAndLogEx(NORMAL, "\nExamples:"); PrintAndLogEx(NORMAL, "\n to run Proxmark3 client:\n"); @@ -602,7 +603,7 @@ static void show_help(bool showFullHelp, char *exec_name) { } } -static int flash_pm3(char *serial_port_name, uint8_t num_files, char *filenames[FLASH_MAX_FILES], bool can_write_bl) { +static int flash_pm3(char *serial_port_name, uint8_t num_files, char *filenames[FLASH_MAX_FILES], bool can_write_bl, bool force) { int ret = PM3_EUNDEF; flash_file_t files[FLASH_MAX_FILES]; @@ -635,7 +636,7 @@ static int flash_pm3(char *serial_port_name, uint8_t num_files, char *filenames[ } for (int i = 0 ; i < num_files; ++i) { - ret = flash_load(&files[i]); + ret = flash_load(&files[i], force); if (ret != PM3_SUCCESS) { goto finish2; } @@ -732,6 +733,7 @@ int main(int argc, char *argv[]) { bool flash_mode = false; bool flash_can_write_bl = false; + bool flash_force = false; bool debug_mode_forced = false; int flash_num_files = 0; char *flash_filenames[FLASH_MAX_FILES]; @@ -948,6 +950,12 @@ int main(int argc, char *argv[]) { continue; } + // force flash even if firmware seems to not match client version + if (strcmp(argv[i], "--force") == 0) { + flash_force = true; + continue; + } + // flash file if (strcmp(argv[i], "--image") == 0) { if (flash_num_files == FLASH_MAX_FILES) { @@ -989,7 +997,7 @@ int main(int argc, char *argv[]) { speed = USART_BAUD_RATE; if (flash_mode) { - flash_pm3(port, flash_num_files, flash_filenames, flash_can_write_bl); + flash_pm3(port, flash_num_files, flash_filenames, flash_can_write_bl, flash_force); exit(EXIT_SUCCESS); } diff --git a/pm3 b/pm3 index ab2d9e3b7..e4469cd29 100755 --- a/pm3 +++ b/pm3 @@ -288,6 +288,8 @@ elif [ "$SCRIPT" = "pm3-flash" ]; then while [ "$1" != "" ]; do if [ "$1" == "-b" ]; then ARGS+=("--unlock-bootloader") + elif [ "$1" == "--force" ]; then + ARGS+=("--force") else ARGS+=("--image" "$1") fi @@ -320,7 +322,19 @@ elif [ "$SCRIPT" = "pm3-flash-all" ]; then FINDBTDONGLE=false FINDBTRFCOMM=false FINDBTDIRECT=false - CMD() { $CLIENT "--port" "$1" "--flash" "--unlock-bootloader" "--image" "$BOOTIMAGE" "--image" "$FULLIMAGE"; } + + + CMD() { + ARGS=("--port" "$1" "--flash" "--unlock-bootloader" "--image" "$BOOTIMAGE" "--image" "$FULLIMAGE") + shift; + while [ "$1" != "" ]; do + if [ "$1" == "--force" ]; then + ARGS+=("--force") + fi + shift; + done + $CLIENT "${ARGS[@]}"; + } HELP() { cat << EOF Quick helper script for flashing a Proxmark device via USB @@ -340,7 +354,17 @@ elif [ "$SCRIPT" = "pm3-flash-fullimage" ]; then FINDBTDONGLE=false FINDBTRFCOMM=false FINDBTDIRECT=false - CMD() { $CLIENT "--port" "$1" "--flash" "--image" "$FULLIMAGE"; } + CMD() { + ARGS=("--port" "$1" "--flash" "--image" "$FULLIMAGE") + shift; + while [ "$1" != "" ]; do + if [ "$1" == "--force" ]; then + ARGS+=("--force") + fi + shift; + done + $CLIENT "${ARGS[@]}"; + } HELP() { cat << EOF Quick helper script for flashing a Proxmark device via USB @@ -360,7 +384,17 @@ elif [ "$SCRIPT" = "pm3-flash-bootrom" ]; then FINDBTDONGLE=false FINDBTRFCOMM=false FINDBTDIRECT=false - CMD() { $CLIENT "--port" "$1" "--flash" "--unlock-bootloader" "--image" "$BOOTIMAGE"; } + CMD() { + ARGS=("--port" "$1" "--flash" "--unlock-bootloader" "--image" "$BOOTIMAGE") + shift; + while [ "$1" != "" ]; do + if [ "$1" == "--force" ]; then + ARGS+=("--force") + fi + shift; + done + $CLIENT "${ARGS[@]}"; + } HELP() { cat << EOF Quick helper script for flashing a Proxmark device via USB From 21089fc346eee954509d96e051f07937c04a37ac Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 25 Feb 2022 00:37:54 +0100 Subject: [PATCH 15/15] flasher: skip msg about --force when --force is used --- client/src/flash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/flash.c b/client/src/flash.c index b8e5d602b..bf1b0d3ec 100644 --- a/client/src/flash.c +++ b/client/src/flash.c @@ -356,10 +356,10 @@ int flash_load(flash_file_t *ctx, bool force) { // We could not find proper version_information if (res == PM3_EUNDEF) PrintAndLogEx(WARNING, "Unable to check version_information"); - PrintAndLogEx(INFO, "Make sure to flash a correct and up-to-date version"); - PrintAndLogEx(INFO, "You can force flashing this firmware by using the option '--force'"); if (force) return PM3_SUCCESS; + PrintAndLogEx(INFO, "Make sure to flash a correct and up-to-date version"); + PrintAndLogEx(INFO, "You can force flashing this firmware by using the option '--force'"); fail: flash_free(ctx); return res;