Created
August 6, 2013 14:36
-
-
Save dev-zzo/6165053 to your computer and use it in GitHub Desktop.
version 1 of D-LINK fw image unpacker.
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
/* | |
* D-LINK products formware image unpacker tool. | |
* Written by dev_zzo for personal research. | |
* Use at your own risk. | |
*/ | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <endian.h> | |
#include <malloc.h> | |
/* | |
The firmware file consists of multiple variable-length records. | |
Each record is prefixed with a header and may contain a payload. | |
Integers in the header are in BE order. | |
*/ | |
/* Entry header. */ | |
struct header | |
{ | |
unsigned char magic[4]; | |
uint32_t headers_length; | |
uint32_t payload_length; | |
// MD5 hash, if payload_length > 0 | |
}; | |
int main (int argc, char *argv[]) | |
{ | |
FILE *fpImage; | |
int record_index = 1; | |
fpImage = fopen (argv[1], "rb"); | |
if (!fpImage) | |
{ | |
fprintf (stderr, "Failed to open the image file.\n"); | |
return 1; | |
} | |
for(;;) | |
{ | |
struct header hdr; | |
char *headers; | |
int i; | |
fprintf(stdout, "trying to read record #%d...\n", record_index); | |
if (fread (&hdr, sizeof(hdr), 1, fpImage) < 1) | |
{ | |
if (feof (fpImage)) | |
{ | |
fprintf (stderr, "EOF when reading the header, considering this done.\n"); | |
break; | |
} | |
fprintf (stderr, "Failed to read the header magic.\n"); | |
fclose (fpImage); | |
return 2; | |
} | |
if (hdr.magic[0] != 0x5EU || hdr.magic[1] != 0xA3U || hdr.magic[2] != 0xA4U || hdr.magic[3] != 0x17U) | |
{ | |
fprintf (stderr, "Header magic is invalid: %02X%02X%02X%02X.\n", | |
hdr.magic[0] & 0xFF, hdr.magic[1] & 0xFF, hdr.magic[2] & 0xFF, hdr.magic[3] & 0xFF); | |
fclose (fpImage); | |
return 2; | |
} | |
hdr.headers_length = be32toh(hdr.headers_length); | |
hdr.payload_length = be32toh(hdr.payload_length); | |
fprintf (stdout, "Headers: %u bytes.\n", hdr.headers_length); | |
fprintf (stdout, "Payload: %u bytes.\n", hdr.payload_length); | |
if (hdr.payload_length != 0) | |
{ | |
char hash[16]; | |
if (fread (hash, 16, 1, fpImage) < 1) | |
{ | |
fprintf (stderr, "Failed to read the payload hash.\n"); | |
fclose (fpImage); | |
return 2; | |
} | |
/* TODO: check the payload hash. */ | |
} | |
headers = (char *)calloc (hdr.headers_length + 1, 1); | |
if (fread (headers, hdr.headers_length, 1, fpImage) < 1) | |
{ | |
fprintf (stderr, "Failed to read headers data.\n"); | |
free (headers); | |
fclose (fpImage); | |
return 2; | |
} | |
for(i = 0; i < hdr.headers_length; ++i) | |
{ | |
if (headers[i] == 0x00) | |
headers[i] = '\n'; | |
} | |
fprintf (stdout, "%s", headers); | |
free (headers); | |
{ | |
FILE *fpOutput; | |
char output_name[256]; | |
sprintf (output_name, "section.%03d", record_index); | |
fpOutput = fopen (output_name, "wb"); | |
while (hdr.payload_length != 0) | |
{ | |
char buffer[4096]; | |
int count = hdr.payload_length > 4096 ? 4096 : hdr.payload_length; | |
fread (buffer, count, 1, fpInput); | |
fwrite (buffer, count, 1, fpOutput); | |
hdr.payload_length -= count; | |
} | |
fclose (fpOutput); | |
} | |
fseek(fpImage, hdr.payload_length, SEEK_CUR); | |
record_index++; | |
} | |
fclose (fpImage); | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment