Merge pull request #1610 from RfidResearchGroup/sha

version checking of firmware files and client executable
This commit is contained in:
Iceman 2022-02-25 11:55:16 +01:00 committed by GitHub
commit 680121b178
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 253 additions and 183 deletions

View file

@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased]
- Added detection of a possible mismatch between client and Proxmark3 image (@doegox)
- Changed `hf 14a info` - added a ATR historical compact TLV decoder (@iceman1001)
- Added `hf mf value` - decode a value block (@iceman1001)
- Changed `hf mf nested` - removed option `--single` redundant with usage of `--tblk` (@doegox)
@ -22,7 +23,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)
@ -37,7 +38,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Added new standalone mode `lf_em4100rsww` (@zabszk)
- Fixed `hf 15 slixdisable` wrong pass id (@r1ddl3rz)
## [Frostbit.4.14831] [2022-01-11]
## [Frostbit.4.14831][2022-01-11]
- Changed Wiegand format lookup - now case-insensitive (@iceman1001)
- Added new standalone mode `hf_15SNIFF` - Same as `hf_14ASNIFF` standalone mode for RDV4 - flashmem (@startrk1995)
- Added `hf gallagher` commands for read/writing DESFire cards (@DarkMatterMatt)

View file

@ -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 $@)
@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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;
}

View file

@ -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
)

View file

@ -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 $* = $($*)

View file

@ -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
)

View file

@ -1072,12 +1072,27 @@ void pm3_version(bool verbose, bool oneliner) {
struct p *payload = (struct p *)&resp.data.asBytes;
bool armsrc_mismatch = false;
char *ptr = strstr(payload->versionstr, " os: ");
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) {
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, "");

View file

@ -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

View file

@ -29,6 +29,7 @@
#include "at91sam7s512.h"
#include "util_posix.h"
#include "comms.h"
#include "commonutil.h"
#define FLASH_START 0x100000
@ -84,12 +85,13 @@ 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, 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;
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 +100,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;
@ -148,11 +150,7 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr_t *phdr
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) {
@ -208,7 +206,8 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr_t *phdr
}
// 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];
@ -236,92 +235,150 @@ 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) {
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 PM3_EINVARG;
} else {
return PM3_SUCCESS;
}
}
return PM3_EUNDEF;
}
// Load an ELF file for flashing
int flash_load(flash_file_t *ctx, bool force) {
FILE *fd;
Elf32_Ehdr_t ehdr;
Elf32_Phdr_t *phdrs = NULL;
uint16_t num_phdrs;
uint32_t flash_end = FLASH_START + flash_size;
Elf32_Ehdr_t *ehdr;
Elf32_Shdr_t *shdrs = NULL;
uint8_t *shstr = NULL;
struct version_information_t *vi = NULL;
int res = PM3_EUNDEF;
fd = fopen(name, "rb");
fd = fopen(ctx->filename, "rb");
if (!fd) {
PrintAndLogEx(ERR, _RED_("Could not open file") " %s >>> ", name);
PrintAndLogEx(ERR, _RED_("Could not open file") " %s >>> ", ctx->filename);
res = PM3_EFILE;
goto fail;
}
PrintAndLogEx(SUCCESS, _CYAN_("Loading ELF file") _YELLOW_(" %s"), name);
PrintAndLogEx(SUCCESS, _CYAN_("Loading ELF file") _YELLOW_(" %s"), ctx->filename);
if (fread(&ehdr, sizeof(ehdr), 1, fd) != 1) {
PrintAndLogEx(ERR, "Error while reading ELF file header");
// 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;
}
if (memcmp(ehdr.e_ident, elf_ident, sizeof(elf_ident))
|| le32(ehdr.e_version) != 1) {
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) {
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) {
if (le16(ehdr->e_machine) != EM_ARM) {
PrintAndLogEx(ERR, "Wrong ELF architecture");
res = PM3_EFILE;
goto fail;
}
if (!ehdr.e_phnum || !ehdr.e_phoff) {
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)) {
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);
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);
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;
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));
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)) {
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;
}
}
if (res == PM3_SUCCESS)
return res;
// We could not find proper version_information
if (res == PM3_EUNDEF)
PrintAndLogEx(WARNING, "Unable to check version_information");
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;
}
res = build_segs_from_phdrs(ctx, fd, phdrs, num_phdrs, flash_end);
// 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_end);
res = check_segs(ctx, can_write_bl, flash_size);
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);
return res;
}
@ -618,6 +675,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);

View file

@ -20,6 +20,7 @@
#define __FLASH_H__
#include "common.h"
#include "elf.h"
#define FLASH_MAX_FILES 4
#define ONE_KB 1024
@ -31,13 +32,17 @@ 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;
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_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);
void flash_free(flash_file_t *ctx);

View file

@ -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 <imagefile> image to flash. Can be specified several times.");
PrintAndLogEx(NORMAL, "\nExamples:");
PrintAndLogEx(NORMAL, "\n to run Proxmark3 client:\n");
@ -602,12 +603,11 @@ 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];
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,12 +627,20 @@ 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_load(&files[i], force);
if (ret != PM3_SUCCESS) {
goto finish2;
}
PrintAndLogEx(NORMAL, "");
}
if (OpenProxmark(&g_session.current_device, serial_port_name, true, 60, true, FLASHMODE_SPEED)) {
@ -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_prepare(&files[i], can_write_bl, max_allowed * ONE_KB);
if (ret != PM3_SUCCESS) {
goto finish;
}
@ -667,22 +675,22 @@ 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, "");
}
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:
for (int i = 0 ; i < num_files; ++i) {
if (filepaths[i] != NULL)
free(filepaths[i]);
flash_free(&files[i]);
}
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!");
@ -725,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];
@ -941,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) {
@ -982,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);
}

View file

@ -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);
}
/*

View file

@ -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

View file

@ -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

40
pm3
View file

@ -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

View file

@ -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 <henryk@ploetzli.ch> 2009-09-28
# Modified april 2014 because of the move to github.
# --- Martin Holst Swende <martin@swende.se>
# Modified january 2016 to work with Travis-CI
# --- iceman <iceman@iuse.se>
# 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 <<EOF
#include "common.h"
/* Generated file, do not edit */
#ifndef ON_DEVICE
#define SECTVERSINFO
#else
#define SECTVERSINFO __attribute__((section(".version_information")))
#endif
const struct version_information_t SECTVERSINFO g_version_information = {
VERSION_INFORMATION_MAGIC,
1,
1,
$clean,
"$fullgitinfo",
"$ctime",
};
EOF

View file

@ -58,6 +58,13 @@ if [ "$fullgitinfoextra" != "$fullgitinfo" ]; then
fullgitinfo46="${fullgitinfo%"${fullgitinfoextra}"}"
fullgitinfo="${fullgitinfo46}..."
fi
sha=$(
pm3path=$(dirname -- "$0")/..
cd "$pm3path" || return
# did we find the src?
[ -f armsrc/appmain.c ] || return
ls armsrc/*.[ch] common_arm/*.[ch]|grep -E -v "(disabled|version_pm3|fpga_version_info)"|xargs sha256sum|sha256sum|grep -o '^.........'
)
cat <<EOF
#include "common.h"
/* Generated file, do not edit */
@ -74,5 +81,6 @@ const struct version_information_t SECTVERSINFO g_version_information = {
$clean,
"$fullgitinfo",
"$ctime",
"$sha"
};
EOF