Firmware CH613/614 entpacken

Antworten
meetzee
Neues Mitglied
Beiträge: 19
Registriert: Mi 11. Feb 2015, 22:28

Firmware CH613/614 entpacken

#1

Beitrag von meetzee »

Hallo,

die Firmware für 613 beginnt mit einem SHA256-Hash, der mit einem mit einem mir unbekannten Schlüssel verschlüsselt ist.

Alles, was danach kommt, ist allerdings unverschlüsselt. Hier ist Beispielcode zum entpacken der pUSB-Datei. Getestet mit MGF613_614_V2.11G_rel_upd_encrypted.pUSB, erhältlich unter http://www.metz-ce.de/de/fernseher/firm ... loads.html.

Code: Alles auswählen

#include <endian.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct section_header_ch613 {
	char name[9];
	unsigned int offset;
	unsigned int size;
	unsigned int crc32;
	char version[11];
};

static unsigned int le32tohp(const void *ptr)
{
	return le32toh(*(const unsigned int *)ptr);
}

static unsigned int crc32_be(const unsigned char *p, size_t len)
{
	unsigned int crc = ~0;
	size_t i;

	while (len--) {
		crc ^= *p++ << 24;
		for (i = 0; i < 8; i++)
			crc = (crc << 1) ^ ((crc & 0x80000000) ? 0x04c11db7 : 0);
	}

	return crc;
}

static void rtrim(char *str, size_t n)
{
	while (n > 0) {
		n--;
		if (str[n] != ' ')
			break;
		str[n] = '\0';
	}
}

static int process_file_ch613(FILE *f)
{
	unsigned char csum[0x20];
	char file_header[0x10];
	unsigned char section_header[0x40];
	struct section_header_ch613 sh;
	unsigned int i;

	if (!fread(csum, sizeof(csum), 1, f)) {
		printf("Can't read checksum\n");
		return 1;
	}

	if (!fread(file_header, sizeof(file_header), 1, f)) {
		printf("Can't read header\n");
		return 1;
	}

	rtrim(&file_header[0], 8);
	rtrim(&file_header[8], 8);

	printf("File header:\n");
	printf("  hardware:  '%.8s'\n", &file_header[0]);
	printf("  version:   '%.8s'\n", &file_header[8]);
	printf("\n");

	for (i = 0; ; i++) {
		fseek(f, 0x30 + (i * 0x40), SEEK_SET);
		if (!fread(section_header, sizeof(section_header), 1, f)) {
			printf("Cannot read section header\n");
			return 1;
		}

		memcpy(sh.name, &section_header[0], 8);
		sh.offset = le32tohp(&section_header[8]) + 0x20;
		sh.size = le32tohp(&section_header[12]);
		sh.crc32 = le32tohp(&section_header[16]);
		memcpy(sh.version, &section_header[20], 10);

		if (!(sh.offset && sh.size))
			break;

		rtrim(sh.name, 8);
		rtrim(sh.version, 10);

		printf("Section %u:\n", i);
		printf("  name: '%s'\n", sh.name);
		printf("  version: '%s'\n", sh.version);
		printf("  offset: %#x (%u)\n", sh.offset, sh.offset);
		printf("  size: %#x (%u)\n", sh.size, sh.size);
		printf("  crc32: %#x\n", sh.crc32);
		printf("\n");

		unsigned char *buf = malloc(sh.size);
		fseek(f, sh.offset, SEEK_SET);
		if (!fread(buf, sh.size, 1, f)) {
			printf("Cannot read section %s\n", sh.name);
			free(buf);
			return 1;
		}

		if (crc32_be(buf, sh.size) != sh.crc32) {
			printf("CRC32 mismatch at section %s\n", sh.name);
			free(buf);
			return 1;
		}

		char filename[FILENAME_MAX];
		snprintf(filename, FILENAME_MAX, "%s.%s", sh.name, strcmp(sh.name, "PACKET") ? "bin" : "tgz");
		FILE *o = fopen(filename, "w");
		if (o) {
			fwrite(buf, sh.size, 1, o);
			fclose(o);
		}

		free(buf);
	}

	return 0;
}

int main(int argc, char *argv[])
{
	FILE *f;
	int ret;

	if (argc != 2) {
		printf("Need exactly one filename!\n");
		return 1;
	}

	f = fopen(argv[1], "rb");
	if (f == NULL) {
		perror(argv[1]);
		return 1;
	}

	ret = process_file_ch613(f);
	fclose(f);
	return ret;
}
Liebe Grüße
meetzee
Antworten