int FlashIAP::deinit() { int ret = 0; _mutex->lock(); if (flash_free(&_flash)) { ret = -1; } delete[] _page_buf; _mutex->unlock(); return ret; }
int main(int argc, char **argv) { int can_write_bl = 0; int num_files = 0; int res; flash_file_t files[MAX_FILES]; memset(files, 0, sizeof(files)); if (argc < 2) { usage(argv[0]); return -1; } for (int i = 1; i < argc; i++) { if (argv[i][0] == '-') { if (!strcmp(argv[i], "-b")) { can_write_bl = 1; } else { usage(argv[0]); return -1; } } else { res = flash_load(&files[num_files], argv[i], can_write_bl); if (res < 0) { fprintf(stderr, "Error while loading %s\n", argv[i]); return -1; } fprintf(stderr, "\n"); num_files++; } } usb_init(); fprintf(stderr, "Waiting for Proxmark to appear on USB..."); while (!OpenProxmark(0)) { sleep(1); fprintf(stderr, "."); } fprintf(stderr, " Found.\n"); res = flash_start_flashing(can_write_bl); if (res < 0) return -1; fprintf(stderr, "\nFlashing...\n"); for (int i = 0; i < num_files; i++) { res = flash_write(&files[i]); if (res < 0) return -1; flash_free(&files[i]); fprintf(stderr, "\n"); } fprintf(stderr, "Resetting hardware...\n"); res = flash_stop_flashing(); if (res < 0) return -1; CloseProxmark(); fprintf(stderr, "All done.\n\n"); fprintf(stderr, "Have a nice day!\n"); return 0; }
// Load an ELF file and prepare it for flashing int flash_load(flash_file_t *ctx, const char *name, int can_write_bl) { FILE *fd = NULL; Elf32_Ehdr ehdr; Elf32_Phdr *phdrs = NULL; int num_phdrs; int res; fd = fopen(name, "rb"); if (!fd) { fprintf(stderr, "Could not open file '%s': ", name); perror(NULL); goto fail; } fprintf(stderr, "Loading ELF file '%s'...\n", name); if (fread(&ehdr, sizeof(ehdr), 1, fd) != 1) { fprintf(stderr, "Error while reading ELF file header\n"); goto fail; } if (memcmp(ehdr.e_ident, elf_ident, sizeof(elf_ident)) || le32(ehdr.e_version) != 1) { fprintf(stderr, "Not an ELF file or wrong ELF type\n"); goto fail; } if (le16(ehdr.e_type) != ET_EXEC) { fprintf(stderr, "ELF is not executable\n"); goto fail; } if (le16(ehdr.e_machine) != EM_ARM) { fprintf(stderr, "Wrong ELF architecture\n"); goto fail; } if (!ehdr.e_phnum || !ehdr.e_phoff) { fprintf(stderr, "ELF has no PHDRs\n"); goto fail; } if (le16(ehdr.e_phentsize) != sizeof(Elf32_Phdr)) { // could be a structure padding issue... fprintf(stderr, "Either the ELF file or this code is made of fail\n"); goto fail; } num_phdrs = le16(ehdr.e_phnum); phdrs = malloc(le16(ehdr.e_phnum) * sizeof(Elf32_Phdr)); if (!phdrs) { fprintf(stderr, "Out of memory\n"); goto fail; } if (fseek(fd, le32(ehdr.e_phoff), SEEK_SET) < 0) { fprintf(stderr, "Error while reading ELF PHDRs\n"); goto fail; } if (fread(phdrs, sizeof(Elf32_Phdr), num_phdrs, fd) != num_phdrs) { fprintf(stderr, "Error while reading ELF PHDRs\n"); goto fail; } res = build_segs_from_phdrs(ctx, fd, phdrs, num_phdrs); if (res < 0) goto fail; res = check_segs(ctx, can_write_bl); if (res < 0) goto fail; free(phdrs); fclose(fd); ctx->filename = name; return 0; fail: if (phdrs) free(phdrs); if (fd) fclose(fd); flash_free(ctx); return -1; }
int parse_flash_partition(uint8_t *data, unsigned int length, const char *partition_name, uint32_t offset, const char *filepath, int detected_device) { struct flash_file *flash; int file_device; flash = flash_create(data, length); if(!flash) { fprintf(stderr, "%s: Memory error\n", program); return 0; } switch(flash->header->magic) { case AOS_ZMfX_MAGIC: { if(verbose) printf("\t%s: Stage 2 bootloader\n", filepath); break; } case AOS_KERNEL_MAGIC: { if(verbose) printf("\t%s: Kernel (zImage+initramfs)\n", filepath); break; } case AOS_GZIP_MAGIC: { if(verbose) printf("\t%s: Boot Logo\n", filepath); break; } default: { if(offset == 0x3f8000 || offset == 0x000000) { // We know those are never signed, so we don't warn about them flash_free(flash); return 0; } printf("\t%s: Unknown magic, this is weird.\n", filepath); flash_free(flash); return 0; } } if(flash->header->magic != AOS_GZIP_MAGIC) { if(flash->header->bits != 0x400) { if(verbose) printf("\t%s: Signature is 0 bits long (SDE Firmware?).\n", filepath); } else { if(!flash_is_signed(flash)) { if(verbose) printf("\t%s: File is not signed.\n", filepath); } else { if(!flash_detect_key(flash, Bootloader_Keys, MPK_KNOWN_DEVICES, &file_device)) { printf("WARNING: %s: Signature is not valid.\n", filepath); } else { if(detected_device != file_device) { printf("WARNING: %s: The detected device type for this file does not match the .aos device type (detected %s).\n", filepath, mpk_device_type(file_device)); } else { if(verbose) printf("\t%s: Signature is valid, detected device type %s.\n", filepath, mpk_device_type(file_device)); } } } } } if(flash->header->magic == AOS_KERNEL_MAGIC) { unsigned int gz_length; uint8_t *gz_data; char *folder_name; char *device_shortname; gz_data = (uint8_t *)flash->header+flash->header->cpio; gz_length = (flash->length - flash->header->cpio); if(*(uint32_t *)gz_data == AOS_GZIP_MAGIC) { folder_name = strdup((const char *)&gz_data[10]); if(endswith(folder_name, ".cpio")) folder_name[strlen(folder_name)-strlen(".cpio")] = 0; } else if((*(uint32_t *)gz_data & AOS_GZIP_NONAME_MASK) == AOS_GZIP_NONAME_MAGIC) { folder_name = bprintf("%s", partition_name); } else { printf("error: Could not find GZIP magic at given offset in %s.\n", filepath); flash_free(flash); return 0; } switch(detected_device) { case MPK_DEVICE_A5: device_shortname = "a5"; break; case MPK_DEVICE_A5IT: device_shortname = "a5it"; break; case MPK_DEVICE_A3GP: device_shortname = "a3g"; break; default: device_shortname = "unk"; break; } // Unpack script log_write("unpack.sh", "## zImage+initramfs: %s\n", filepath); log_write("unpack.sh", "rm -f -r unpacked/%s/\n", folder_name); log_write("unpack.sh", "mkdir -p unpacked/%s/initramfs/\n", folder_name); log_write("unpack.sh", "aos-unpack %s --%s --output unpacked/%s/ --zimage zImage --initramfs initramfs.cpio.gz\n", filepath, device_shortname, folder_name); log_write("unpack.sh", "gunzip --decompress unpacked/%s/initramfs.cpio.gz\n", folder_name); log_write("unpack.sh", "(cd unpacked/%s/initramfs/ && cpio -i -d -H newc -F ../initramfs.cpio --no-absolute-filenames)\n", folder_name, folder_name); log_write("unpack.sh", "rm unpacked/%s/initramfs.cpio\n", folder_name); log_write("unpack.sh", "\n"); // Repack script log_write("repack.sh", "## zImage+initramfs: %s\n", filepath); log_write("repack.sh", "(cd unpacked/%s/initramfs/ && find . | cpio -o -H newc -F ../initramfs.cpio)\n", folder_name); log_write("repack.sh", "rm -f -r unpacked/%s/initramfs/\n", folder_name); log_write("repack.sh", "gzip --name --best unpacked/%s/initramfs.cpio\n", folder_name); log_write("repack.sh", "aos-repack --kernel --output %s --zimage unpacked/%s/zImage --initramfs unpacked/%s/initramfs.cpio.gz\n", filepath, folder_name, folder_name); log_write("repack.sh", "rm -f -r unpacked/%s/\n", folder_name); log_write("repack.sh", "\n"); free(folder_name); } else if(flash->header->magic == AOS_GZIP_MAGIC) { const char *gz_name = (const char *)&data[10]; log_write("unpack.sh", "## .gz: %s\n", filepath); log_write("unpack.sh", "mkdir -p unpacked/\n", gz_name); log_write("unpack.sh", "rm -f unpacked/%s\n", gz_name); log_write("unpack.sh", "cp %s unpacked/%s.gz\n", filepath, gz_name); log_write("unpack.sh", "gunzip -d unpacked/%s.gz\n", gz_name); log_write("unpack.sh", "\n"); log_write("repack.sh", "## .gz: %s\n", filepath); log_write("repack.sh", "gzip -N --best unpacked/%s\n", gz_name); log_write("repack.sh", "cp unpacked/%s.gz %s\n", gz_name, filepath); log_write("repack.sh", "rm -f unpacked/%s.gz\n", gz_name); log_write("repack.sh", "\n"); } flash_free(flash); return 1; }
int parse_cramfs_archive(const char *filename, uint8_t *data, unsigned int length, const char *filepath, int detected_device) { struct flash_file *flash; int file_device; char cramfs_name[2048]; flash = flash_create(data, length); if(!flash) { fprintf(stderr, "%s: Memory error\n", program); return 0; } if(flash->header->magic != AOS_CRAMFS_MAGIC) { fprintf(stderr, "%s: Invalid Cramfs magic on file.\n", filename); flash_free(flash); return 0; } if(!flash_detect_key(flash, Bootloader_Keys, MPK_KNOWN_DEVICES, &file_device)) { printf("WARNING: %s: Signature is invalid.\n", filename); } else { if(detected_device != file_device) { printf("WARNING: %s: The detected device type for this file does not match the .aos device type (detected %s).\n", filename, mpk_device_type(file_device)); } else { if(verbose) printf("\t%s: Signature is valid, detected device type %s\n", filename, mpk_device_type(file_device)); } } strcpy(cramfs_name, filename); cramfs_name[strlen(cramfs_name)-strlen(".secure")] = 0; log_write("unpack.sh", "## .cramfs.secure: %s\n", filepath); log_write("unpack.sh", "rm -f -r unpacked/%s\n", cramfs_name); log_write("unpack.sh", "mkdir -p unpacked\n"); if(*(uint32_t *)&flash->header->data[0] == 0x28cd3d45 /* CRAMFS_MAGIC */) { /* this is a cramfs with a small header (0x100 bytes), which is nonstandard for a cramfs file. */ log_write("unpack.sh", "dd if=%s of=unpacked/%s.stripped bs=256 skip=1\n", filepath, cramfs_name); log_write("unpack.sh", "(cd unpacked/ && cramfsck -v -x %s %s.stripped)\n", cramfs_name, cramfs_name); log_write("unpack.sh", "rm unpacked/%s.stripped\n", cramfs_name); } else { /* this is a cramfs file with either no header or a standard cramfs header (0x200 bytes). */ log_write("unpack.sh", "cramfsck -x unpacked/%s %s\n", cramfs_name, filepath); } log_write("unpack.sh", "\n"); log_write("repack.sh", "## .cramfs.secure: %s\n", filepath); if(*(uint32_t *)&flash->header->data[0] == 0x28cd3d45 /* CRAMFS_MAGIC */) { log_write("repack.sh", "mkcramfs unpacked/%s unpacked/%s.tmp\n", cramfs_name, cramfs_name); log_write("repack.sh", "rm -f -r unpacked/%s\n", cramfs_name); log_write("repack.sh", "aos-fix --add-header unpacked/%s.tmp\n", cramfs_name); log_write("repack.sh", "mv unpacked/%s.tmp unpacked/%s.secure\n", cramfs_name, cramfs_name); } else { // create a cramfs with padding for the header, and write the header in-place log_write("repack.sh", "mkcramfs -p unpacked/%s unpacked/%s.secure\n", cramfs_name, cramfs_name); log_write("repack.sh", "rm -f -r unpacked/%s\n", cramfs_name); log_write("repack.sh", "aos-fix --add-header --overwrite unpacked/%s.secure\n", cramfs_name); } log_write("repack.sh", "mv unpacked/%s.secure %s\n", cramfs_name, filepath); log_write("repack.sh", "\n"); flash_free(flash); return 1; }