mirror of https://github.com/hak5/openwrt.git
fwtool: add support for extracting the truncated data part to stdout
This allows extracing the firmware + metadata from a signed firmware without altering the original image file Signed-off-by: Felix Fietkau <nbd@nbd.name>openwrt-19.07
parent
d5681e45f0
commit
8f4e31ea6e
|
@ -43,6 +43,7 @@ struct data_buf {
|
||||||
static FILE *signature_file, *metadata_file, *firmware_file;
|
static FILE *signature_file, *metadata_file, *firmware_file;
|
||||||
static int file_mode = MODE_DEFAULT;
|
static int file_mode = MODE_DEFAULT;
|
||||||
static bool truncate_file;
|
static bool truncate_file;
|
||||||
|
static bool write_truncated;
|
||||||
static bool quiet = false;
|
static bool quiet = false;
|
||||||
|
|
||||||
static uint32_t crc_table[256];
|
static uint32_t crc_table[256];
|
||||||
|
@ -64,6 +65,7 @@ usage(const char *progname)
|
||||||
" -s <file>: Extract signature file from firmware image\n"
|
" -s <file>: Extract signature file from firmware image\n"
|
||||||
" -i <file>: Extract metadata file from firmware image\n"
|
" -i <file>: Extract metadata file from firmware image\n"
|
||||||
" -t: Remove extracted chunks from firmare image (using -s, -i)\n"
|
" -t: Remove extracted chunks from firmare image (using -s, -i)\n"
|
||||||
|
" -T: Output firmware image without extracted chunks to stdout (using -s, -i)\n"
|
||||||
" -q: Quiet (suppress error messages)\n"
|
" -q: Quiet (suppress error messages)\n"
|
||||||
"\n", progname);
|
"\n", progname);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -280,8 +282,10 @@ extract_data(const char *name)
|
||||||
struct fwimage_trailer tr;
|
struct fwimage_trailer tr;
|
||||||
struct data_buf dbuf = {};
|
struct data_buf dbuf = {};
|
||||||
uint32_t crc32 = ~0;
|
uint32_t crc32 = ~0;
|
||||||
|
int data_len = 0;
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
void *buf;
|
void *buf;
|
||||||
|
bool metadata_keep = false;
|
||||||
|
|
||||||
firmware_file = open_file(name, false);
|
firmware_file = open_file(name, false);
|
||||||
if (!firmware_file) {
|
if (!firmware_file) {
|
||||||
|
@ -301,6 +305,9 @@ extract_data(const char *name)
|
||||||
do {
|
do {
|
||||||
char *tmp = dbuf.cur;
|
char *tmp = dbuf.cur;
|
||||||
|
|
||||||
|
if (write_truncated && dbuf.prev)
|
||||||
|
fwrite(dbuf.prev, 1, BUFLEN, stdout);
|
||||||
|
|
||||||
dbuf.cur = dbuf.prev;
|
dbuf.cur = dbuf.prev;
|
||||||
dbuf.prev = tmp;
|
dbuf.prev = tmp;
|
||||||
|
|
||||||
|
@ -317,7 +324,6 @@ extract_data(const char *name)
|
||||||
} while (dbuf.cur_len == BUFLEN);
|
} while (dbuf.cur_len == BUFLEN);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
int data_len;
|
|
||||||
|
|
||||||
if (extract_tail(&dbuf, &tr, sizeof(tr)))
|
if (extract_tail(&dbuf, &tr, sizeof(tr)))
|
||||||
break;
|
break;
|
||||||
|
@ -349,6 +355,7 @@ extract_data(const char *name)
|
||||||
} else if (tr.type == FWIMAGE_INFO) {
|
} else if (tr.type == FWIMAGE_INFO) {
|
||||||
if (!metadata_file) {
|
if (!metadata_file) {
|
||||||
dbuf.file_len += data_len + sizeof(tr);
|
dbuf.file_len += data_len + sizeof(tr);
|
||||||
|
metadata_keep = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,6 +375,17 @@ extract_data(const char *name)
|
||||||
if (!ret && truncate_file)
|
if (!ret && truncate_file)
|
||||||
ftruncate(fileno(firmware_file), dbuf.file_len);
|
ftruncate(fileno(firmware_file), dbuf.file_len);
|
||||||
|
|
||||||
|
if (write_truncated) {
|
||||||
|
if (dbuf.prev)
|
||||||
|
fwrite(dbuf.prev, 1, BUFLEN, stdout);
|
||||||
|
if (dbuf.cur)
|
||||||
|
fwrite(dbuf.cur, 1, dbuf.cur_len, stdout);
|
||||||
|
if (metadata_keep) {
|
||||||
|
fwrite(buf, data_len, 1, stdout);
|
||||||
|
fwrite(&tr, sizeof(tr), 1, stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
free(buf);
|
free(buf);
|
||||||
free(dbuf.cur);
|
free(dbuf.cur);
|
||||||
|
@ -392,7 +410,7 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
crc32_filltable(crc_table);
|
crc32_filltable(crc_table);
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, "i:I:qs:S:t")) != -1) {
|
while ((ch = getopt(argc, argv, "i:I:qs:S:tT")) != -1) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
switch(ch) {
|
switch(ch) {
|
||||||
case 'S':
|
case 'S':
|
||||||
|
@ -410,6 +428,9 @@ int main(int argc, char **argv)
|
||||||
case 't':
|
case 't':
|
||||||
truncate_file = true;
|
truncate_file = true;
|
||||||
break;
|
break;
|
||||||
|
case 'T':
|
||||||
|
write_truncated = true;
|
||||||
|
break;
|
||||||
case 'q':
|
case 'q':
|
||||||
quiet = true;
|
quiet = true;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue