Quelle:
h**ps://www.ip-phone-forum.de/threads/wie-funktioniert-eigentlich-das-signieren-der-avm-firmware.286213/post-2449730
, wenn man eine originale Firmware für die 7530 überprüfen läßt. wissen wir, wie der von AVM ermittelte Hash über die zu signierenden Daten aussieht:
" ... ermittle die aktuelle TTY
tty is "/dev/pts/0"
Console Ausgaben auf dieses Terminal umgelenkt
disable start/stop characters and flowcontrol
# tr069fwupdate packet file:///var/media/ftp/USB-DISKPro-01/729/FRITZ.Box_7530-07.29.image /var/media/ftp/USB-DISKPro-01/729 ; echo rc=$?
rc=3
# cat /var/tmp/fwsign.log
public num='00a199d98aaa5ff1a8f9a9f8f956930470ae533fd6a4731468acf686cd2234a6ba4ae17798ec93a5862a56baf1ff3741ea13c4fb35a4ca76df9be66eb0b2c0d3d7f271cc061f394f201b62290d8a9d8695735aa3dafb54a43e3521b4df42c5e52188228b8e133079872bdd7357ceb7379336715e9b50f2d2e678dc79e90c231d8f'
public exp='010001'
# cat /var/tmp/firmware_stream_result .."
total=
30709760 ret=0 sub_ret=0 sigcrc=
1bbe7981136d832bb7a52fcd7d5d4b85
" ... Zuerst legen wir ... für diesen Test irgendein temporäres Verzeichnis an, damit wir alles das, was im Laufe der Aktion an Dateien anfällt, auch einfach wieder entsorgen können. Anschließend definieren wir ein paar Funktionen, ..
Code:
~> mkdir 7530_test
~> cd 7530_test/
~/7530_test> get_image_name() { [ -n "$1" ] && wget -q -O - https://ftp.avm.de/fritzbox/fritzbox-$1/deutschland/fritz.os | sed -n -e "s/.*<a href=\"\(FR[^\"]*\)\".*/\1/p"; }
~/7530_test> get_image() { [ -t 1 ] && return; [ -n "$(get_image_name "$1")" ] && wget -O - "https://ftp.avm.de/fritzbox/fritzbox-$1/deutschland/fritz.os/$(get_image_name "$1")" || printf "Download failed.\n\a" 1>&2; }
..
~/7530_test> get_image 7530 > avm.image
~/7530_test> grep -abo "./var/signature" avm.image
~/7530_test> dd if=avm.image of=avm.data bs=512 count=$(( 30708736 / 512 )) 2>/dev/null
~/7530_test> ls -l
:~/7530_test> md5sum avm.*
a36571c24a65937a82ae265a3dc250b1 avm.data
8938d11f232876c3bd1af641a4a271f0 avm.image
~/7530_test>
DAS ist also noch nicht die Datei, die am Ende von der Signaturprüfung im FRITZ!OS verwendet wurde - aber auch die "vollkommen originale" Datei ergibt einen anderen MD5-Hash.
Um das jetzt jeweils um 512 Bytes mit Nullen zu "verlängern", kopieren wir einfach immer wieder die passende Anzahl von Bytes aus
/dev/null /dev/
zero (nur "virtuell" in einer Pipe, die gleich das Hashen am anderen Ende hat), bis der MD5-Hash mit dem Wert von AVM übereinstimmt. Dazu brauchen wir auch erst einmal eine Funktion, welche die Ausgabe von md5sum so aufbereitet, daß tatsächlich nur der Hash-Wert übrig bleibt. Um zu verhindern, daß der Test zu weit geht, wenn keine Übereinstimmung beim Hash gefunden wird, begrenzen wir das Ganze aber auf max. 20 Runden (20 x 512 Byte = 10240 Byte, also ein physischer Block bei unterstellter Blocksize von 10 KB):
Code:
~/7530_test> hexdump -C avm.image | sed -n -e "/^$(printf "%08x" "30708736")/,\$p"
01d49400 2e 2f 76 61 72 2f 73 69 67 6e 61 74 75 72 65 00 |./var/signature.|
01d49410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
* ..
01d49680 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
01d49800
~/7530_test>
, dann kommt danach wirklich nicht mehr ein einziger kompletter Block mit binären Nullen, während das TAR-Format davon aber wenigstens zwei (mit jeweils 512 Byte) erfordern würde:
Sie müssen registriert sein, um Links zu sehen.
At the end of the archive file there are two 512-byte blocks filled with binary zeros as an end-of-file marker.
Das ist also erneut mal wieder einer der Fälle, wo ein AVM-Image zwar das TAR-Format verwendet, aber sich nicht an den Standard hält.
Nur so zum Spaß kann man ja mal hingehen und die anderen aktuellen Release-Versionen auf diese Merkwürdigkeit untersuchen (auch wenn das in der Ausführung etwas dauert)
Code:
~/7530_test> empty_blocks() { fo=0; so=0; [ -n "$1" ] && eval $(hexdump -C "$1" | tail -n 3 | sed -e "2d" | sed -n -e "1s/^\([^ ]*\).*/fo=\$(( 0x\1 ))/p" -e "2s/^\([^ ]*\).*/so=\$(( 0x\1 ))/p"); printf "bytes=%u blocks=%u\n" "$(( so - fo ))" "$(( ( so - fo ) / 512 ))"; }
~/7530_test> for model in 7490 7520 7530 7590 7590-ax; do get_image $model 2>/dev/null > tmp.image; printf "%s: " "$model"; empty_blocks tmp.image; done
7490: bytes=1920 blocks=3
7520: bytes=8576 blocks=16
7530: bytes=384 blocks=0
7590: bytes=2432 blocks=4
7590-ax: bytes=4480 blocks=8
~/7530_test>
Die 7530 ist also (aus den getesteten Modellen) im Moment die einzige Box, bei der die Firmware-Datei mit dem TAR-Standard kollidiert - die anderen haben mind. zwei Null-Blöcke am Ende. ...
Was kann man - wenn man eine Datei zur Verfügung hat, die vom FRITZ!OS abgelehnt wird - jetzt als Nächstes testen? Nun, man kann diese nicht akzeptierte Datei noch einmal durch die Prüfung jagen und sich dabei den Hash-Wert, den das FRITZ!OS dabei errechnet (in der firmware_stream_result) notieren, so wie ich das am Anfang des Beitrags gezeigt habe.
Dann geht man mit dieser Datei wiederum hin und behandelt sie so, wie ich es oben mit dem AVM-Image gemacht habe (alles Unwesentliche hinten abschneiden und dann so lange Null-Blöcke anhängen, bis man den AVM-Hash (der sich natürlich von dem unterscheidet, den ich oben verwendet habe) gefunden hat). Danach weiß man dann, wie AVM die angebotene Image-Datei verändert hat bei der eigenen Berechnung des Hash-Wertes - und daraus kann man dann wieder Schlüsse ziehen, wie man die eigene Datei so aufbauen kann, daß sie von der AVM-Firmware auch verifiziert werden kann. .."