diff --git a/utils/sbinfo/elf.c b/utils/sbinfo/elf.c index 0fe6792e1d..6c5ed2e762 100644 --- a/utils/sbinfo/elf.c +++ b/utils/sbinfo/elf.c @@ -57,13 +57,16 @@ void elf_add_fill_section(struct elf_params_t *params, void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user) { Elf32_Ehdr ehdr; - uint32_t phoff = sizeof(Elf32_Ehdr); - uint32_t phentsize = sizeof(Elf32_Phdr); uint32_t phnum = 0; - uint32_t shstrndx = SHN_UNDEF; struct elf_section_t *sec = params->first_section; uint32_t offset = 0; Elf32_Phdr phdr; + Elf32_Shdr shdr; + memset(&ehdr, 0, EI_NIDENT); + + uint32_t bss_strtbl = 0; + uint32_t text_strtbl = bss_strtbl + strlen(".bss") + 1; + uint32_t strtbl_size = text_strtbl + strlen(".text") + 1; while(sec) { @@ -77,7 +80,8 @@ void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user) sec = sec->next; } - memset(&ehdr, 0, EI_NIDENT); + uint32_t strtbl_offset = offset; + ehdr.e_ident[EI_MAG0] = ELFMAG0; ehdr.e_ident[EI_MAG1] = ELFMAG1; ehdr.e_ident[EI_MAG2] = ELFMAG2; @@ -91,25 +95,28 @@ void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user) ehdr.e_machine = EM_ARM; ehdr.e_version = EV_CURRENT; ehdr.e_entry = params->start_addr; - ehdr.e_phoff = phoff; - ehdr.e_shoff = 0; ehdr.e_flags = 0; if(params->has_start_addr) ehdr.e_flags |= EF_ARM_HASENTRY; ehdr.e_ehsize = sizeof ehdr; - ehdr.e_phentsize = phentsize; + ehdr.e_phentsize = sizeof phdr; ehdr.e_phnum = phnum; - ehdr.e_shentsize = 0; - ehdr.e_shnum = 0; - ehdr.e_shstrndx = shstrndx; + ehdr.e_shentsize = sizeof shdr; + ehdr.e_shnum = phnum + 1; + ehdr.e_shstrndx = ehdr.e_shnum - 1; + ehdr.e_phoff = ehdr.e_ehsize; + ehdr.e_shoff = ehdr.e_ehsize + ehdr.e_phnum * ehdr.e_phentsize; write(user, 0, &ehdr, sizeof ehdr); + uint32_t data_offset = ehdr.e_ehsize + ehdr.e_phnum * ehdr.e_phentsize + + ehdr.e_shnum * ehdr.e_shentsize; + sec = params->first_section; - offset = phoff; + offset = ehdr.e_phoff; while(sec) { - sec->offset += phoff + phnum * phentsize; + sec->offset += data_offset; phdr.p_type = PT_LOAD; if(sec->type == EST_LOAD) @@ -132,6 +139,47 @@ void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user) sec = sec->next; } + sec = params->first_section; + offset = ehdr.e_shoff; + while(sec) + { + shdr.sh_name = text_strtbl; + if(sec->type == EST_LOAD) + shdr.sh_type = SHT_PROGBITS; + else + shdr.sh_type = SHT_NOBITS; + shdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR; + shdr.sh_addr = sec->addr; + shdr.sh_offset = sec->offset; + shdr.sh_size = sec->size; + shdr.sh_link = SHN_UNDEF; + shdr.sh_info = 0; + shdr.sh_addralign = 1; + shdr.sh_entsize = 0; + + write(user, offset, &shdr, sizeof shdr); + + offset += sizeof(Elf32_Shdr); + sec = sec->next; + } + + { + shdr.sh_name = bss_strtbl; + shdr.sh_type = SHT_STRTAB; + shdr.sh_flags = 0; + shdr.sh_addr = 0; + shdr.sh_offset = strtbl_offset + data_offset; + shdr.sh_size = strtbl_size; + shdr.sh_link = SHN_UNDEF; + shdr.sh_info = 0; + shdr.sh_addralign = 1; + shdr.sh_entsize = 0; + + write(user, offset, &shdr, sizeof shdr); + + offset += sizeof(Elf32_Shdr); + } + sec = params->first_section; while(sec) { @@ -139,6 +187,8 @@ void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user) write(user, sec->offset, sec->section, sec->size); sec = sec->next; } + + write(user, strtbl_offset + data_offset, ".bss\0.text\0", strtbl_size); } bool elf_is_empty(struct elf_params_t *params) diff --git a/utils/sbinfo/elf.h b/utils/sbinfo/elf.h index eb990389d9..d2bf210c5c 100644 --- a/utils/sbinfo/elf.h +++ b/utils/sbinfo/elf.h @@ -78,6 +78,45 @@ typedef struct #define SHN_UNDEF 0 /* Undefined section */ +typedef struct +{ + Elf32_Word sh_name; /* Section name (string tbl index) */ + Elf32_Word sh_type; /* Section type */ + Elf32_Word sh_flags; /* Section flags */ + Elf32_Addr sh_addr; /* Section virtual addr at execution */ + Elf32_Off sh_offset; /* Section file offset */ + Elf32_Word sh_size; /* Section size in bytes */ + Elf32_Word sh_link; /* Link to another section */ + Elf32_Word sh_info; /* Additional section information */ + Elf32_Word sh_addralign; /* Section alignment */ + Elf32_Word sh_entsize; /* Entry size if section holds table */ +}Elf32_Shdr; + +#define SHT_NULL 0 /* Section header table entry unused */ +#define SHT_PROGBITS 1 /* Program data */ +#define SHT_SYMTAB 2 /* Symbol table */ +#define SHT_STRTAB 3 /* String table */ +#define SHT_RELA 4 /* Relocation entries with addends */ +#define SHT_HASH 5 /* Symbol hash table */ +#define SHT_DYNAMIC 6 /* Dynamic linking information */ +#define SHT_NOTE 7 /* Notes */ +#define SHT_NOBITS 8 /* Program space with no data (bss) */ +#define SHT_REL 9 /* Relocation entries, no addends */ +#define SHT_SHLIB 10 /* Reserved */ +#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ +#define SHT_INIT_ARRAY 14 /* Array of constructors */ +#define SHT_FINI_ARRAY 15 /* Array of destructors */ +#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ +#define SHT_GROUP 17 /* Section group */ +#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ +#define SHT_NUM 19 /* Number of defined types. */ + +#define SHF_WRITE (1 << 0) /* Writable */ +#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ +#define SHF_EXECINSTR (1 << 2) /* Executable */ +#define SHF_MERGE (1 << 4) /* Might be merged */ +#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ + typedef struct { Elf32_Word p_type; /* Segment type */ diff --git a/utils/sbinfo/sbinfo.c b/utils/sbinfo/sbinfo.c index d065fc9eed..710c481deb 100644 --- a/utils/sbinfo/sbinfo.c +++ b/utils/sbinfo/sbinfo.c @@ -63,8 +63,8 @@ char BLUE[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '4', 0x6d, '\0' }; /* byte swapping */ #define get32le(a) ((uint32_t) \ - ( buf[a+3] << 24 | buf[a+2] << 16 | buf[a+1] << 8 | buf[a] )) -#define get16le(a) ((uint16_t)( buf[a+1] << 8 | buf[a] )) + ( g_buf[a+3] << 24 | g_buf[a+2] << 16 | g_buf[a+1] << 8 | g_buf[a] )) +#define get16le(a) ((uint16_t)( g_buf[a+1] << 8 | g_buf[a] )) /* all blocks are sized as a multiple of 0x1ff */ #define PAD_TO_BOUNDARY(x) (((x) + 0x1ff) & ~0x1ff) @@ -74,8 +74,8 @@ char BLUE[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '4', 0x6d, '\0' }; /* globals */ -size_t sz; /* file size */ -uint8_t *buf; /* file content */ +size_t g_sz; /* file size */ +uint8_t *g_buf; /* file content */ #define PREFIX_SIZE 128 char out_prefix[PREFIX_SIZE]; const char *key_file; @@ -129,25 +129,23 @@ void *xmalloc(size_t s) /* malloc helper, used in elf.c */ static char getchr(int offset) { char c; - c = buf[offset]; + c = g_buf[offset]; return isprint(c) ? c : '_'; } static void getstrle(char string[], int offset) { int i; - for (i = 0; i < 4; i++) { + for (i = 0; i < 4; i++) string[i] = getchr(offset + 3 - i); - } string[4] = 0; } static void getstrbe(char string[], int offset) { int i; - for (i = 0; i < 4; i++) { + for (i = 0; i < 4; i++) string[i] = getchr(offset + i); - } string[4] = 0; } @@ -155,9 +153,8 @@ static void printhex(int offset, int len) { int i; - for (i = 0; i < len; i++) { - printf("%02X ", buf[offset + i]); - } + for (i = 0; i < len; i++) + printf("%02X ", g_buf[offset + i]); printf("\n"); } @@ -222,7 +219,7 @@ static key_array_t read_keys(int num_keys) bugp("key file stat() failed"); size = st.st_size; char *buf = xmalloc(size); - if(read(fd,buf,sz)!=(ssize_t)size) + if(read(fd, buf, size) != (ssize_t)size) bugp("reading key file"); close(fd); @@ -417,13 +414,13 @@ static void extract(unsigned long filesize) printf("Basic info:\n"); color(GREEN); printf("\tHeader SHA-1: "); - byte *hdr_sha1 = &buf[0]; + byte *hdr_sha1 = &g_buf[0]; color(YELLOW); print_sha1(hdr_sha1); /* Check SHA1 sum */ byte computed_sha1[20]; sha_1_init(&sha_1_params); - sha_1_update(&sha_1_params, &buf[0x14], 0x4C); + sha_1_update(&sha_1_params, &g_buf[0x14], 0x4C); sha_1_finish(&sha_1_params); sha_1_output(&sha_1_params, computed_sha1); color(RED); @@ -480,7 +477,7 @@ static void extract(unsigned long filesize) if(num_enc > 0) { keys = read_keys(num_enc); - color(BLUE), + color(BLUE); printf("Encryption data\n"); for(int i = 0; i < num_enc; i++) { @@ -492,14 +489,14 @@ static void extract(unsigned long filesize) printf("\t\tCBC-MAC of headers: "); /* copy the cbc mac */ byte hdr_cbc_mac[16]; - memcpy(hdr_cbc_mac, &buf[0x60 + 16 * num_chunks + 32 * i], 16); + memcpy(hdr_cbc_mac, &g_buf[0x60 + 16 * num_chunks + 32 * i], 16); color(YELLOW); print_key(hdr_cbc_mac); /* check it */ byte computed_cbc_mac[16]; byte zero[16]; memset(zero, 0, 16); - cbc_mac(buf, NULL, 6 + num_chunks, keys[i], zero, &computed_cbc_mac, 1); + cbc_mac(g_buf, NULL, 6 + num_chunks, keys[i], zero, &computed_cbc_mac, 1); color(RED); if(memcmp(hdr_cbc_mac, computed_cbc_mac, 16) == 0) printf(" Ok\n"); @@ -509,7 +506,7 @@ static void extract(unsigned long filesize) printf("\t\tEncrypted key : "); byte (*encrypted_key)[16]; - encrypted_key = (key_array_t)&buf[0x60 + 16 * num_chunks + 32 * i + 16]; + encrypted_key = (key_array_t)&g_buf[0x60 + 16 * num_chunks + 32 * i + 16]; color(YELLOW); print_key(*encrypted_key); printf("\n"); @@ -517,7 +514,7 @@ static void extract(unsigned long filesize) /* decrypt */ byte decrypted_key[16]; byte iv[16]; - memcpy(iv, buf, 16); /* uses the first 16-bytes of SHA-1 sig as IV */ + memcpy(iv, g_buf, 16); /* uses the first 16-bytes of SHA-1 sig as IV */ cbc_mac(*encrypted_key, decrypted_key, 1, keys[i], iv, NULL, 0); printf("\t\tDecrypted key : "); color(YELLOW); @@ -571,9 +568,9 @@ static void extract(unsigned long filesize) /* save it */ byte *sec = xmalloc(size); if(encrypted) - cbc_mac(buf + pos, sec, size / 16, real_key, buf, NULL, 0); + cbc_mac(g_buf + pos, sec, size / 16, real_key, g_buf, NULL, 0); else - memcpy(sec, buf + pos, size); + memcpy(sec, g_buf + pos, size); extract_section(data_sec, name, sec, size, "\t\t\t"); free(sec); @@ -590,16 +587,16 @@ static void extract(unsigned long filesize) printf("\t\t"); printhex(filesize - 16, 16); /* decrypt it */ - byte *encrypted_block = &buf[filesize - 32]; + byte *encrypted_block = &g_buf[filesize - 32]; byte decrypted_block[32]; - cbc_mac(encrypted_block, decrypted_block, 2, real_key, buf, NULL, 0); + cbc_mac(encrypted_block, decrypted_block, 2, real_key, g_buf, NULL, 0); color(GREEN); printf("\tDecrypted SHA-1:\n\t\t"); color(YELLOW); print_sha1(decrypted_block); /* check it */ sha_1_init(&sha_1_params); - sha_1_update(&sha_1_params, buf, filesize - 32); + sha_1_update(&sha_1_params, g_buf, filesize - 32); sha_1_finish(&sha_1_params); sha_1_output(&sha_1_params, computed_sha1); color(RED); @@ -621,17 +618,17 @@ int main(int argc, const char **argv) else strcpy(out_prefix, ""); - if( (fd = open(argv[1],O_RDONLY)) == -1 ) + if( (fd = open(argv[1], O_RDONLY)) == -1 ) bugp("opening firmware failed"); key_file = argv[2]; - if(fstat(fd,&st) == -1) + if(fstat(fd, &st) == -1) bugp("firmware stat() failed"); - sz = st.st_size; + g_sz = st.st_size; - buf=xmalloc(sz); - if(read(fd,buf,sz)!=(ssize_t)sz) /* load the whole file into memory */ + g_buf = xmalloc(g_sz); + if(read(fd, g_buf, g_sz) != (ssize_t)g_sz) /* load the whole file into memory */ bugp("reading firmware"); close(fd); @@ -641,6 +638,6 @@ int main(int argc, const char **argv) color(OFF); - free(buf); + free(g_buf); return 0; }