Skip to content

Instantly share code, notes, and snippets.

@KonradIT
Forked from nezza/gist:2394361
Created January 20, 2014 19:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KonradIT/8527850 to your computer and use it in GitHub Desktop.
Save KonradIT/8527850 to your computer and use it in GitHub Desktop.
GoPro FW extractor.
/* This tool extracts the sections of a supplied GoPro
* firmware image.
*
* It creates the following files in the current directory:
* bst.bin, bld.bin, pri.bin, rom.bin, dsp.bin
*
* It also shows the expected CRC32 checksum of the section and shows
* where it will be written on the device, you can use this address as
* ROM address and load address in IDA Pro.
*
*
* Copyright (c) 2012, Thomas Roth <code@stacksmashing.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those
* of the authors and should not be interpreted as representing official policies,
* either expressed or implied, of the FreeBSD Project.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
typedef struct {
/* According to pieces in the firmware
* (1.1.54, bld.bin, 0xc001dcfc),
* there could also be rmd, bak and pba sections.
*/
/* 0x00 */ uint32_t bst_section_start;
/* 0x04 */ uint32_t bst_section_end;
/* 0x08 */ uint32_t bld_section_start;
/* 0x0c */ uint32_t bld_section_end;
/* 0x10 */ uint32_t unknown_0;
/* 0x14 */ uint32_t unknown_1;
/* 0x18 */ uint32_t pri_section_start;
/* 0x1C */ uint32_t pri_section_end;
/* 0x20 */ uint32_t unknown_2;
/* 0x24 */ uint32_t unknown_3;
/* 0x28 */ uint32_t rom_section_start;
/* 0x2c */ uint32_t rom_section_end;
/* 0x30 */ uint32_t dsp_section_start;
/* 0x34 */ uint32_t dsp_section_end;
} gopro_fw_file_header;
typedef struct {
/* 0x00 */ uint32_t crc32;
/* 0x04 */ uint32_t version;
/* 0x08 */ uint8_t build_date_day;
/* 0x09 */ uint8_t build_date_month;
/* 0x10 */ uint16_t build_date_year;
/* 0x12 */ uint32_t length;
/* 0x16 */ uint32_t loading_address;
/* 0x20 */ uint32_t flags;
/* 0x24 */ uint32_t magic;
/* The image starts 0x100 bytes after the beginning of the header. */
} gopro_fw_section_header;
void read_bytes_from_file(void *dst, FILE *src, size_t lng) {
if(fread(dst, lng, 1, src) != 1) {
fprintf(stderr, "Failed to read 0x%08X bytes.\n", lng);
exit(EXIT_FAILURE);
}
}
void error_seek(FILE *f, size_t offset, int whence) {
if(fseek(f, offset, SEEK_SET) != 0) {
fprintf(stderr, "Failed to seek to %d\n", offset);
exit(EXIT_FAILURE);
}
}
void write_bytes_to_file(char *dst_name, FILE *src, int len) {
FILE *dst = fopen(dst_name, "w");
int bytes_remaining = len;
/* Export in 1024 byte chunks */
char tmp_buffer[1024];
while(bytes_remaining) {
int r = bytes_remaining > 1024 ? 1024 : bytes_remaining;
if(fread(tmp_buffer, r, 1, src) != 1) {
fprintf(stderr, "Failed to read section.");
exit(EXIT_FAILURE);
}
if(fwrite(tmp_buffer, r, 1, dst) != 1) {
fprintf(stderr, "Failed to write section.");
exit(EXIT_FAILURE);
}
bytes_remaining -= r;
}
}
void export_section(char *name, char *fname, FILE *src, uint32_t start, uint32_t end) {
if(start) {
printf("Exporting %s section...\n", name);
} else {
printf("No %s section found.\n", name);
return;
}
error_seek(src, start, SEEK_SET);
gopro_fw_section_header sh;
read_bytes_from_file(&sh, src, sizeof(sh));
printf("\tBeginning : %d\n", start);
printf("\tEnd : %d\n", end);
printf("\tCRC32 : 0x%08X\n", sh.crc32);
printf("\tVersion : %d.%d\n",
(sh.version >> 16),
sh.version & 0x000000FF);
printf("\tBuild date: %02d.%02d.%d\n",
sh.build_date_day,
sh.build_date_month,
sh.build_date_year);
printf("\tLength : %d (0x%08X)\n", sh.length, sh.length);
printf("\tAddress : 0x%08X\n", sh.loading_address);
printf("\tFlags : 0x%08X\n", sh.flags);
printf("\tMagic : 0x%08X\n", sh.magic);
printf("Writing to %s...\n", fname);
// Go to section start + 0x100, this is where the actual
// image contents begins.
error_seek(src, start+0x100, SEEK_SET);
write_bytes_to_file(fname, src, sh.length);
printf("Done.\n");
}
int main(int argc, char *argv[]) {
if(argc < 2) {
fprintf(
stderr,
"Usage: %s [firmware_file]\n",
argv[0]);
exit(EXIT_FAILURE);
}
FILE *firmware_file = fopen(argv[1], "r");
if(!firmware_file) {
fprintf(stderr, "Failed to open %s\n", argv[1]);
exit(EXIT_FAILURE);
}
gopro_fw_file_header fh;
read_bytes_from_file(&fh, firmware_file, sizeof(fh));
export_section(
"BST",
"bst.bin",
firmware_file,
fh.bst_section_start,
fh.bst_section_end);
export_section(
"BLD",
"bld.bin",
firmware_file,
fh.bld_section_start,
fh.bld_section_end);
export_section(
"PRI",
"pri.bin",
firmware_file,
fh.pri_section_start,
fh.pri_section_end);
export_section(
"ROM",
"rom.bin",
firmware_file,
fh.rom_section_start,
fh.rom_section_end);
export_section(
"DSP",
"dsp.bin",
firmware_file,
fh.dsp_section_start,
fh.dsp_section_end);
exit(EXIT_SUCCESS);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment