mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-03-23 13:37:35 +08:00
Merge pull request #1610 from RfidResearchGroup/sha
version checking of firmware files and client executable
This commit is contained in:
commit
680121b178
19 changed files with 253 additions and 183 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
||||
|
|
|
@ -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 $* = $($*)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
||||
|
|
|
@ -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, "");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
40
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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue