Disque dur multimédia Wyplayer/Firmware


Format des fichiers de firmware

modifier

Actualisation du firmware

modifier

Les buts sur la connaissance du firmware

modifier
  • Connaitre la structure du fichier .wup (Fait)
  • Connaitre les formats des parties du fichier .wup (XML et Kermel ok, reste le logiciel)
  • Connaitre la fonctionnalité de chaque partie du fichier .wup (en cours...)
  • Actualiser un boitier avec le firmware d'un de ses clones (en cours...)
  • Générer son propre Kermel et l'installer dans le boitier (en cours...)
  • Générer son propre logiciel et l'installer dans le boitier (en cours...)
  • Obtenir la clé d'encryptage de la partie logiciel de chaque boitier (en cours...)
  • Accéder au logiciel pour comprendre le fonctionnement du boitier (en cours...)

Structure du fichier .wup

modifier

Exemple: <root>

       <specVersion>                                                                                                                 
               <major>1</major>                                                                                                      
               <minor>1</minor>                                                                                                      
       </specVersion>                                                                                                                
       <update>                                                                                                                      
               <version>001.002.00014.0000007929</version>                                                                           
               <displayName>Grab'n'GO Wireless Media Titan</displayName>
               <description>-----</description>
               <target>WBD000930AA</target>
               <targetList>
                       <target>WBD000930AB</target>
               </targetList>
               <level>0</level>
               <provider>-----</provider>
               <generationDatetime>2009-02-09T10:22:13+0100Z</generationDatetime>
               <uri>announce</uri>
               <signature/>
               <partList>
                       <part>
                               <id>1</id>
                               <displayName>Kernel</displayName>
                               <version>2.6.17.14.617</version>
                               <type>kernel</type>
                               <uri>kernel</uri>
                               <compression>none</compression>
                               <parent>1</parent>
                               <generationDatetime>2009-02-09T10:22:09+0100Z</generationDatetime>
                               <uncompressedSize>1962745</uncompressedSize>
                               <signature>ddbeb13f573a12c880b1d971ff25949b</signature>
                       </part>
                       <part>
                               <id>2</id>
                               <displayName>Software</displayName>
                               <version>001.002.00014.0000007929</version>
                               <type>core</type>
                               <uri>core</uri>
                               <compression>none</compression>
                               <parent>2</parent>
                               <generationDatetime>2009-02-09T10:22:09+0100Z</generationDatetime>
                               <uncompressedSize>121692160</uncompressedSize>
                               <signature>1afb31cdc482ce22c1ae0406ee55161f</signature>
                       </part>
               </partList>
       </update>

</root>

Infos sur le fichier Kermel

modifier
  • System:$ file kernel2.6.17.14.617_1.2.14.7929.bin
  • kernel2.6.17.14.617_1.2.14.7929.bin: u-boot/PPCBoot image

Analyse du fichier Kermel

modifier

Le nombre magique dans le kermel est (0x270519), il indique que le fichier est de type u-boot. Si on veut analyser le reste du fichier on va à l'offset 352 (on a analysé jusqu'à présent sous la forme d'un fichier gzip que l'on extrait avec la commande suivante:

dd if=kernel.bin bs=352 skip=1 | gzip -d > kernel.ucompressed

L'analyse de ce fichier décompressé montre qu'à l'intérieur il y a deux autres fichiers compressés. L'un permet la configuration du kermel, l'autre est l' l'initramfs.cpio .

Un nouveau script a été créé afin de décompresser un fichier gzip à l'intérieur d'un autre fichier.

#!/bin/bash
# search_gzip
# Copyright (C) 2008, 2009, 20010
# Free Software Foundation, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
# Original Author: Orensbruli (Esteban Martinena Guerrero)
# Current Version: 0.1

PATTERN=1f8b0800
P_LEFT=`echo $PATTERN | cut -b1`
P_RIGHT=`echo $PATTERN | cut -b2-`



for FILE in $@
do
    loop=1
    OFFSET=$(expr `xxd -p $FILE | tr -d '\n' | sed -e "s/$P_LEFT\($P_RIGHT\)/p\1/g" | cut -d'p' -f1-$loop | wc -c` / 2)
    LAST_OFFSET="_"
    OUT_DIR=uncompressed
    if [ ! -d $OUT_DIR ]
    then
        mkdir $OUT_DIR
    fi
    echo "En cherchant dans le fichier $FILE..."
    while [ ! $OFFSET == $LAST_OFFSET ]
    do
        dd if=$FILE bs=1 skip=$OFFSET 2>/dev/null | gzip -dc 2>/dev/null > $OUT_DIR/$FILE\_$loop\_$OFFSET.uncomp
        if [ $? -eq 1 ]
        then
            echo "Faux gzip dans $OFFSET."
            rm $OUT_DIR/$FILE\_$loop\_$OFFSET.uncomp
        else
            echo "Générer le fichier gzip: $OUT_DIR/$FILE\\_$loop\\_$OFFSET.uncomp"
        fi
        loop=$(expr $loop + 1)
        LAST_OFFSET=$OFFSET
        OFFSET=$(expr `xxd -p $FILE | tr -d '\n' | sed -e 's/1f8b/pqrs/g' | cut -d'p' -f1-$loop | wc -c` / 2)
    done
    echo "Fin de la recherche"
done

Dans ce cas concret, on peut obtenir le gzip contenu dans le fichier Kermel mais aussi les fichiers contenus dans le fichier Kermel décompressés. Pour clarifier, voilà comment se découpe le fichier:

  • update.wup (applique le script d'extraction)
    header (contient le fichier Kermel dans ces 4 derniers bit)
    kernel (applique le script d'extraction du gzip)
    kernel.uncomp (applique le script d'extraction du gzip)
    config (fichier de configuration pour la compilation du kermel)
    initramfs.cpio (fichier nécessaire à la compilation)
    middle (contient le fichier logiciel dans ces 4 derniers bit)
    software
    footer
    infoxml (information xml sur le fichierupdate.wup et le boitier)

Note: il y a un projet tribox avec des caractéristiques identiques au notre (même processeur) et ils ont pas mal d'infos sur le montage du système. Plus d'infos ici:http://www.tribbox.com/

Actualiser le firmware avec le firmware d'un autre boitier

modifier

Aujourd'hui il est impossible d'actualiser un clone par le firmware du wyplayer. Chaque boitier possède sa propre identification et la partie "logiciel" du firmware est cryptée de manière différente pour chaque boitier. En théorie, il serait possible de mélanger les firmwares entre eux afin de trouver un firmware alternatif. Il suffirait de prendre le kermel d'un boitier pour le mettre dans le firmware qui nous intéresse pour actualiser le boitier. On connait les 6 parties du firmware, il doit donc être possible de créer un firmware alternatif.

Script pour créer un firmware alternatif

modifier

Pour essayer de créer ce firmware alternatif, on a essayé de créer un script qui mélange les parties de 2 firmwares distincts afin de créer un fichier.wup valide pour actualiser le boitier. Toutes les combinaisons sont possibles, les fichiers créés par ce script n'étant pas tous testés, il est important de prendre des précautions avec cette actualisation.

IMPORTANT: pour que le script fonctionne, il faut changer la valeur de EXTRACT_PROGRAM et écrire la route pour le script d'extraction.

Le fonctionnement est simple:

wup_mix <fichero_actualización1> <fichero_de_actualización2>
#! /bin/bash
# wup_mix
# Copyright (C) 2008, 2009, 20010
# Free Software Foundation, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
# Original Author: Orensbruli (Esteban Martinena Guerrero)
# Current Version: 0.1

#PATH le script d'extraction
EXTRACT_PROGRAM=<PATH_COMPLETO_AL_SCRIPT_DE_EXTRACCION>/extract_xml

if [ ! -f $EXTRACT_PROGRAM ]
then
    echo "Etablir la variable EXTRACT_PROGRAM avec le chemin complet pour trouver le script d'extraction"
fi

#Es necesario el fichero como parametro de entrada
if [ $# -lt 2 ]
then
  echo -e  "Llamada incorrecta."
  echo -e  "ej: $0 <fichero_actualizacion_1.wup> <fichero_actualizacion_2.wup>"
  exit
fi

UPDATE_FILE1=$1
UPDATE_FILE2=$2

if [ $UPDATE_FILE1 == $UPDATE_FILE2 ]
then
    echo "No se pueden llamar igual los dos ficheros aunque estén en diferentes directorios."
    echo "Intente renombrar uno de ellos (ej. mv update.wup update1.wup)."
    exit
fi


echo -e  "Comprobando si se puede hacer la mezcla de los dos ficheros."
UPDATE_FILE1_SIZE=`du -b $UPDATE_FILE1 | cut -f1`
LINEAS1=`wc -l $UPDATE_FILE1 | cut -d' ' -f1`
ROOT_BEGIN1=`grep -a -n -u "root" $UPDATE_FILE1 | head -n1 | cut -d':' -f1`
TAIL1=`expr $LINEAS1 - $ROOT_BEGIN1 + 1`
tail -n $TAIL1 $UPDATE_FILE1 > $UPDATE_FILE1.xml
VERSION1=`cat $UPDATE_FILE1.xml | grep version | head -n1 | cut -d'>' -f 2 | cut -d'<' -f1 | sed -e 's/^0*//' | sed -e 's/\.0*/./g'`


UPDATE_FILE2_SIZE=`du -b $UPDATE_FILE2 | cut -f1`
LINEAS2=`wc -l $UPDATE_FILE2 | cut -d' ' -f1`
ROOT_BEGIN2=`grep -a -n -u "root" $UPDATE_FILE2 | head -n1 | cut -d':' -f1`
TAIL2=`expr $LINEAS2 - $ROOT_BEGIN2 + 1`
tail -n $TAIL2 $UPDATE_FILE2 > $UPDATE_FILE2.xml
VERSION2=`cat $UPDATE_FILE2.xml | grep version | head -n1 | cut -d'>' -f 2 | cut -d'<' -f1 | sed -e 's/^0*//' | sed -e 's/\.0*/./g'`
DATE_KERNEL1=`cat $UPDATE_FILE1.xml | grep -i generationDatetime | tail -n2 | head -n1 | cut -d'>' -f 2 | cut -d'<' -f1`
DATE_KERNEL2=`cat $UPDATE_FILE2.xml | grep -i generationDatetime | tail -n2 | head -n1 | cut -d'>' -f 2 | cut -d'<' -f1`
DATE_SOFTWARE1=`cat $UPDATE_FILE1.xml | grep -i generationDatetime | tail -n1 | cut -d'>' -f 2 | cut -d'<' -f1`
DATE_SOFTWARE2=`cat $UPDATE_FILE2.xml | grep -i generationDatetime | tail -n1 | cut -d'>' -f 2 | cut -d'<' -f1`
SIGNATURE_KERNEL1=`cat $UPDATE_FILE1.xml | grep -i signature | tail -n2 | head -n1 | cut -d'>' -f 2 | cut -d'<' -f1`
SIGNATURE_KERNEL2=`cat $UPDATE_FILE2.xml | grep -i signature | tail -n2 | head -n1 | cut -d'>' -f 2 | cut -d'<' -f1`
SIGNATURE_SOFTWARE1=`cat $UPDATE_FILE1.xml | grep -i signature | tail -n1 | cut -d'>' -f 2 | cut -d'<' -f1`
SIGNATURE_SOFTWARE2=`cat $UPDATE_FILE2.xml | grep -i signature | tail -n1 | cut -d'>' -f 2 | cut -d'<' -f1`
SIZE_KERNEL1=`cat $UPDATE_FILE1.xml | grep -i uncompressedSize | tail -n2 | head -n1 | cut -d'>' -f 2 | cut -d'<' -f1`
SIZE_KERNEL2=`cat $UPDATE_FILE2.xml | grep -i uncompressedSize | tail -n2 | head -n1 | cut -d'>' -f 2 | cut -d'<' -f1`
SIZE_SOFTWARE1=`cat $UPDATE_FILE1.xml | grep -i uncompressedSize | tail -n1 | cut -d'>' -f 2 | cut -d'<' -f1`
SIZE_SOFTWARE2=`cat $UPDATE_FILE2.xml | grep -i uncompressedSize | tail -n1 | cut -d'>' -f 2 | cut -d'<' -f1`
NAME1=`cat $UPDATE_FILE1.xml | grep -i displayName | head -n1| cut -d'>' -f 2 | cut -d'<' -f1`
NAME2=`cat $UPDATE_FILE2.xml | grep -i displayName | head -n1| cut -d'>' -f 2 | cut -d'<' -f1`

if [ $VERSION1 == $VERSION2 ]
then
    echo "Los dos ficheros de actualización son de la misma versión. Deben ser de versiones distintas para poder mezclarlos."
    rm $UPDATE_FILE1.xml
    rm $UPDATE_FILE2.xml
    exit
else
    echo "Correcto."
fi

rm $UPDATE_FILE1.xml
rm $UPDATE_FILE2.xml

bash $EXTRACT_PROGRAM $UPDATE_FILE1
bash $EXTRACT_PROGRAM $UPDATE_FILE2

echo "Introduzca el número correspondiente a la operación a realizar:"
select OPCION in cabecera$NAME1$VERSION1+resto$NAME2$VERSION2 kernel$NAME1$VERSION1+resto$NAME2$VERSION2 middle$NAME1$VERSION1+resto$NAME2$VERSION2 software$NAME1$VERSION1+resto$NAME2$VERSION2 footer$NAME1$VERSION1+resto$NAME2$VERSION2 xml$NAME1$VERSION1+resto$NAME2$VERSION2 cabecera$NAME2$VERSION2+resto$NAME1$VERSION1 kernel$NAME2$VERSION2+resto$NAME1$VERSION1 middle$NAME2$VERSION2+resto$NAME1$VERSION1 software$NAME2$VERSION2+resto$NAME1$VERSION1 footer$NAME2$VERSION2+resto$NAME1$VERSION1 xml$NAME2$VERSION2+resto$NAME1$VERSION1
do
    NEW_NAME=$OPCION.wup
    case $OPCION in
          cabecera$NAME1$VERSION1+Resto$NAME2$VERSION2)
              PARTS[0]=`ls -1 header_bytes*$VERSION1.bin | head -n1`
              PARTS[1]=`ls -1 kernel*$VERSION2.bin | head -n1`
              PARTS[2]=`ls -1 middle_bytes*$VERSION2.bin | head -n1`
              PARTS[3]=`ls -1 software*$VERSION2.bin | head -n1`
              PARTS[4]=`ls -1 footer_bytes*$VERSION2.bin | head -n1`
              PARTS[5]=`ls -1 infoxml*$VERSION2.xml | head -n1`
              ;;
          cabecera$NAME2$VERSION2+resto$NAME1$VERSION1)
              PARTS[0]=`ls -1 header_bytes*$VERSION2.bin | head -n1`
              PARTS[1]=`ls -1 kernel*$VERSION1.bin | head -n1`
              PARTS[2]=`ls -1 middle_bytes*$VERSION1.bin | head -n1`
              PARTS[3]=`ls -1 software*$VERSION1.bin | head -n1`
              PARTS[4]=`ls -1 footer_bytes*$VERSION1.bin | head -n1`
              PARTS[5]=`ls -1 infoxml*$VERSION1.xml | head -n1`
              ;;
          kernel$NAME1$VERSION1+resto$NAME2$VERSION2)
              PARTS[0]=`ls -1 header_bytes*$VERSION2.bin | head -n1`
              PARTS[1]=`ls -1 kernel*$VERSION1.bin | head -n1`
              PARTS[2]=`ls -1 middle_bytes*$VERSION2.bin | head -n1`
              PARTS[3]=`ls -1 software*$VERSION2.bin | head -n1`
              PARTS[4]=`ls -1 footer_bytes*$VERSION2.bin | head -n1`
              PARTS[5]=`ls -1 infoxml*$VERSION2.xml | head -n1`
              cp ${PARTS[5]} ${PARTS[5]}.aux
              PARTS[5]=${PARTS[5]}.aux
              sed -i -e "s/$SIZE_KERNEL2/$SIZE_KERNEL1/g" -e "s/$SIGNATURE_KERNEL2/$SIGNATURE_KERNEL1/g" -e "s/$DATE_KERNEL2/$DATE_KERNEL1/g" ${PARTS[5]}
              
              ;;
          kernel$NAME2$VERSION2+resto$NAME1$VERSION1)
              PARTS[0]=`ls -1 header_bytes*$VERSION1.bin | head -n1`
              PARTS[1]=`ls -1 kernel*$VERSION2.bin | head -n1`
              PARTS[2]=`ls -1 middle_bytes*$VERSION1.bin | head -n1`
              PARTS[3]=`ls -1 software*$VERSION1.bin | head -n1`
              PARTS[4]=`ls -1 footer_bytes*$VERSION1.bin | head -n1`
              PARTS[5]=`ls -1 infoxml*$VERSION1.xml | head -n1`
              cp ${PARTS[5]} ${PARTS[5]}.aux
              PARTS[5]=${PARTS[5]}.aux
              sed -i -e "s/$SIZE_KERNEL1/$SIZE_KERNEL2/g" -e "s/$SIGNATURE_KERNEL1/$SIGNATURE_KERNEL2/g" -e "s/$DATE_KERNEL1/$DATE_KERNEL2/g" ${PARTS[5]}
              ;;
          middle$NAME1$VERSION1+resto$NAME2$VERSION2)
              PARTS[0]=`ls -1 header_bytes*$VERSION2.bin | head -n1`
              PARTS[1]=`ls -1 kernel*$VERSION2.bin | head -n1`
              PARTS[2]=`ls -1 middle_bytes*$VERSION1.bin | head -n1`
              PARTS[3]=`ls -1 software*$VERSION2.bin | head -n1`
              PARTS[4]=`ls -1 footer_bytes*$VERSION2.bin | head -n1`
              PARTS[5]=`ls -1 infoxml*$VERSION2.xml | head -n1`
              ;;
          middle$NAME2$VERSION2+resto$NAME1$VERSION1)
              PARTS[0]=`ls -1 header_bytes*$VERSION1.bin | head -n1`
              PARTS[1]=`ls -1 kernel*$VERSION1.bin | head -n1`
              PARTS[2]=`ls -1 middle_bytes*$VERSION2.bin | head -n1`
              PARTS[3]=`ls -1 software*$VERSION1.bin | head -n1`
              PARTS[4]=`ls -1 footer_bytes*$VERSION1.bin | head -n1`
              PARTS[5]=`ls -1 infoxml*$VERSION1.xml | head -n1`
              ;;
          software$NAME1$VERSION1+resto$NAME2$VERSION2)
              PARTS[0]=`ls -1 header_bytes*$VERSION2.bin | head -n1`
              PARTS[1]=`ls -1 kernel*$VERSION2.bin | head -n1`
              PARTS[2]=`ls -1 middle_bytes*$VERSION2.bin | head -n1`
              PARTS[3]=`ls -1 software*$VERSION1.bin | head -n1`
              PARTS[4]=`ls -1 footer_bytes*$VERSION2.bin | head -n1`
              PARTS[5]=`ls -1 infoxml*$VERSION2.xml | head -n1`
              cp ${PARTS[5]} ${PARTS[5]}.aux
              PARTS[5]=${PARTS[5]}.aux
              sed -i -e "s/$SIZE_SOFTWARE2/$SIZE_SOFTWARE1/g" -e "s/$SIGNATURE_SOFTWARE2/$SIGNATURE_SOFTWARE1/g" -e "s/$DATE_SOFTWARE2/$DATE_SOFTWARE1/g" ${PARTS[5]}
              ;;
          software$NAME2$VERSION2+resto$NAME1$VERSION1)
              PARTS[0]=`ls -1 header_bytes*$VERSION1.bin | head -n1`
              PARTS[1]=`ls -1 kernel*$VERSION1.bin | head -n1`
              PARTS[2]=`ls -1 middle_bytes*$VERSION1.bin | head -n1`
              PARTS[3]=`ls -1 software*$VERSION2.bin | head -n1`
              PARTS[4]=`ls -1 footer_bytes*$VERSION1.bin | head -n1`
              PARTS[5]=`ls -1 infoxml*$VERSION1.xml | head -n1`
              cp ${PARTS[5]} ${PARTS[5]}.aux
              PARTS[5]=${PARTS[5]}.aux
              sed -i -e "s/$SIZE_SOFTWARE1/$SIZE_SOFTWARE2/g" -e "s/$SIGNATURE_SOFTWARE1/$SIGNATURE_SOFTWARE2/g" -e "s/$DATE_SOFTWARE1/$DATE_SOFTWARE2/g" ${PARTS[5]}
              ;;
          footer$NAME1$VERSION1+resto$NAME2$VERSION2)
              PARTS[0]=`ls -1 header_bytes*$VERSION2.bin | head -n1`
              PARTS[1]=`ls -1 kernel*$VERSION2.bin | head -n1`
              PARTS[2]=`ls -1 middle_bytes*$VERSION2.bin | head -n1`
              PARTS[3]=`ls -1 software*$VERSION2.bin | head -n1`
              PARTS[4]=`ls -1 footer_bytes*$VERSION1.bin | head -n1`
              PARTS[5]=`ls -1 infoxml*$VERSION2.xml | head -n1`
              ;;
          footer$NAME2$VERSION2+resto$NAME1$VERSION1)
              PARTS[0]=`ls -1 header_bytes*$VERSION1.bin | head -n1`
              PARTS[1]=`ls -1 kernel*$VERSION1.bin | head -n1`
              PARTS[2]=`ls -1 middle_bytes*$VERSION1.bin | head -n1`
              PARTS[3]=`ls -1 software*$VERSION1.bin | head -n1`
              PARTS[4]=`ls -1 footer_bytes*$VERSION2.bin | head -n1`
              PARTS[5]=`ls -1 infoxml*$VERSION1.xml | head -n1`
              ;;
          xml$NAME1$VERSION1+resto$NAME2$VERSION2)
              PARTS[0]=`ls -1 header_bytes*$VERSION2.bin | head -n1`
              PARTS[1]=`ls -1 kernel*$VERSION2.bin | head -n1`
              PARTS[2]=`ls -1 middle_bytes*$VERSION2.bin | head -n1`
              PARTS[3]=`ls -1 software*$VERSION2.bin | head -n1`
              PARTS[4]=`ls -1 footer_bytes*$VERSION2.bin | head -n1`
              PARTS[5]=`ls -1 infoxml*$VERSION1.xml | head -n1`
              ;;
          xml$NAME2$VERSION2+resto$NAME1$VERSION1)
              PARTS[0]=`ls -1 header_bytes*$VERSION1.bin | head -n1`
              PARTS[1]=`ls -1 kernel*$VERSION1.bin | head -n1`
              PARTS[2]=`ls -1 middle_bytes*$VERSION1.bin | head -n1`
              PARTS[3]=`ls -1 software*$VERSION1.bin | head -n1`
              PARTS[4]=`ls -1 footer_bytes*$VERSION1.bin | head -n1`
              PARTS[5]=`ls -1 infoxml*$VERSION2.xml | head -n1`
              ;;
          *)
              continue
              ;;
      esac
      echo "Creando fichero mixto..."
      touch $NEW_NAME
      for part in $( seq 0 `expr ${#PARTS[*]} - 1` )
      do
          echo -e "\tAñadiendo ${PARTS[$part]} al nuevo fichero $NEW_NAME..."
          dd if=${PARTS[$part]} of=$NEW_NAME bs=1 seek=`du -b $NEW_NAME | cut -f1` 2>/dev/null
      done
      echo "Hecho."
      break
done