-
-
Save KonradIT/8527850 to your computer and use it in GitHub Desktop.
GoPro FW extractor.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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 <[email protected]> | |
* 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