mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-22 22:33:48 -07:00
flasher: parse ELF to check version_information and do ELF checks before looking for a proxmark3
This commit is contained in:
parent
359ca554c0
commit
0ed0735709
4 changed files with 147 additions and 16 deletions
|
@ -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,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; 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;
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue