Discos multimedia basados en Wyplayer/Firmware

Los ficheros de firmware son los que permiten al usuario actualizar éstos discos multimedia. Los suministran las casa que que venden cada dispositivo y parece que no son compatibles los de un dispositivo con los de otro.

Formato de los ficheros firmware

editar

Método de actualización

editar

Hitos en la ingeniería inversa de los ficheros de firmware

editar
  • Conocer la estructura de los fichero .wup (Hecho)
  • Conocer el formato de las partes del fichero .wup (XML y Kernel, queda el software)
  • Conocer la funcionalidad de cada parte del fichero .wup (Pendiente)
  • Actualizar los dispositivos con el firmware de otro dispositivo. (Pendiente)
  • Generar "kernel" propio e instalarlo en los dispositivos. (Pendiente)
  • Generar "software" propio e instalarlo en los dispositivos. (Pendiente)
  • Intentar obtener las clave que encripta la parte del software de los update.wup para cada dispositivo. (Pendiente)
  • Acceder al dispositivo para obtener más información durante su funcionamiento. (Pendiente)

Estructura interna de los ficheros wup

editar

Código XML

editar

Ejemplo:

<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>

Fichero de kernel

editar

Según la salida del comando file (existente en sistemas basados en *nix) el fichero de kernel es de tipo:

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

Investigando el código

editar

En el código fuente suministrado por wyplay existe el directorio uboot-<version> Investigando un poco como se complila, en uboot se ha encontrado que en el directorio board hay un sub-directorio llamado wyplay, que parecen ser las especificaciones necesarias para compilar el u-boot para las distintas placas bases de wyplay.

  • Al revisar el Makefile que se encuetra en el directorio princial uboot-<version> se puede encontrar una entrada para diferentes "boards" de wyplay.

Se está intentando configurar y compilar para wymdbox_config (wyplayer multimedia box) que se entiende que es la que corresponde con los estos discos.

Analizando el fichero kernel

editar

El magic number en la cabecera (0x270519) de este fichero indica que es del tipo u-boot. Si se analiza el resto del fichero se encuentra en el offset 352 (al menos de los analizados hasta ahora un fichero gzip, que se puede extraer con el comando:

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

Si se analiza este fichero que se ha descomprimido, se encuentra que dentro del mismo hay (al menos en la mayoría de los firmwares) otros dos ficheros comprimidos. Uno parece ser el fichero de configuración del kernel y el otro el initramfs.cpio también requerido durante la compilación (si se establece el parámetro correspondiente).

Se ha creado un nuevo script para buscar y descomprimir ficheros gzip dentro de otros ficheros. Como entrada necesita el o los ficheros (puede utilizarse algo como kernel1.2* como entrada) en los que se desean buscar fichero gzip.

#!/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 "Buscando en el fichero $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 "Falso gzip en $OFFSET."
            rm $OUT_DIR/$FILE\_$loop\_$OFFSET.uncomp
        else
            echo "Generado fichero 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 búsqueda"
done

En éste caso concreto. Se puede utilizar tanto para obtener el gzip de los ficheros de kernel, como para los ficheros gzip que están en los ficheros descomprimidos obtenidos del kernel. Para clarificar todo esto se expone a continuación la jerarquía de ficheros que se tiene ahora mismo:

update.wup (aplicar el script de extracción)

header (contiene el tamaño del fichero de kernel en sus últimos 4 bytes)
kernel (aplicar script de extracción de gzip)
kernel.uncomp (aplicar script de extracción de gzip)
config (fichero de configuración para la compilación del kernel)
initramfs.cpio (fichero necesario también en la compilación)
middle (contiene el tamaño del fichero de software en sus últimos 4 bytes)
software
footer
infoxml (información xml sobre el fichero update.wup y su dispositivo)


Notas: Hay un proyecto llamado tribbox de un media center con características similares a los nuestros (al menos el procesador) y con información de como montar el sistema operativo/etc. Puede ser util: http://www.tribbox.com/

Fichero de software

editar

Hasta el momento no se sabe exactamente cual es el formato del sistema de software, ya que el comando file da como salida para dicho fichero "data". Se conjetura que es un sistema de ficheros squashfs y que además está encriptado con un cifrado aes-cbc-plain usando una clave de 128 bits. Probablemente, la imagen es desencriptada por la interfaz dm-crypt del kernel Linux.

A partir de todas las conjeturas que se han ido haciendo, se ha creado un script que dado un fichero de software obtenido de un fichero de firmware (script de extracción) (wup) y otro fichero con una lista de contraseñas, intenta desencriptar y determinar el sistema de ficheros que hay subyacente. Hay varios problemas:

  • No se está completamente seguro del sistema que se está utilizando para encriptar, por lo que se están dando palos de ciego.
  • El script da muchos falsos positivos, ya que siempre se desencripta el sistema. Lo único que determina si ha sido correcto o no es la salida de file, de la que cabría esperar que fuera algo como squashfs filesystem o similar.

Este es solo un código didáctico y a modo de ejemplo de desencriptación en sistemas Linux de ficheros y particiones completas. Cada cual es responsable del uso que hace de él. Se recomienda revisarlo antes de hacerlo funcionar.

#! /bin/bash
# soft_decrypt
# 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

#Se comprueba la sintaxis de la llamada al script
if [ $# -lt 2 ]
then
  echo -e  "Llamada incorrecta."
  echo -e  "ej: $0 <fichero_software wup> <fichero_lista_passwords>"
  exit
fi

SOFTWARE_FILE=$1
PASSWORDS_FILE=$2

#Se configura el disposifivo /dev/loop0 para que apunte al fichero de software
losetup /dev/loop0 $SOFTWARE_FILE

#Para cada contraseña
for passwd in `cat $PASSWORDS_FILE`
do
    #echo "Probando la contraseña $passwd..."
    #Se mapea el dispositivo /dev/loop0 con la contraseña encriptada como aes-cbc-plain de 128 bits e /dev/mapper/decripted
    echo $passwd | cryptsetup -c aes-cbc-plain  -s 128 -b `blockdev --getsize /dev/loop0` create decripted /dev/loop0 2>/dev/null

    #A veces da problemas porque sigue mapeado el anterior, se reintenta "desmapear" y mapear de nuevo
    if [ ! $? -eq 0 ]
    then
        dmsetup remove decripted
        #echo -e "\tProbando de nuevo la contraseña $passwd..."
        echo $passwd | cryptsetup -c aes-cbc-plain  -s 128 -b `blockdev --getsize /dev/loop0` create decripted /dev/loop0
    fi
    
    #Se crea un pequeño fichero de muestra con el comienzo de la partición desencriptada
    dd if=/dev/mapper/decripted of=sample.img count=100 bs=1 2> /dev/null
    
    #Se comprueba el tipo de fichero. Si fuera lo que esperamo debria poner squashfs filesystem o similar
    TYPE=`file sample.img | grep -v "sample.img: data"`
    if [ $? -eq 0 ]
    then
        echo "Desencriptado como \"$TYPE\" con la contraseña $passwd"
    fi
    
    #Se intenta despamear /dev/loop0 de /dev/mapper/decripted
    cryptsetup remove decripted 2> /dev/null
    dmsetup remove decripted 2> /dev/null
    #Se espera 1 segundo
    sleep 1
done

#Se elimina la asociación del fichero_software y /dev/loop0
losetup -d /dev/loop0

Script de extracción

editar

Este script en bash/shell script permite obtener de un fichero de actualización de firmware (.wup) los ficheros correspondientes al kernel, el software y la información XML. Es completamente GPL y no hay responsabilidad ninguna sobre su uso. Quien tenga dudas sobre su funcionamiento o sus acciones que lo analice. Por supuesto, cualquier mejora, sugerencia o aportación será bienvenida.

Actualmente obtiene 6 ficheros a partir del fichero de actualización wup. Los principales son los de kernel y software, de cierto interés el infoxml y el resto (header_bytes, middle_bytes y footer_bytes) son los bytes que quedan sin identificar en distintas partes del fichero. Se ha hecho así para que uniendo todos los ficheros se obtega de nuevo el fichero original sin perder información.

header_bytes # kernel # middle_bytes # software # footer_bytes # infoxml

El script se ha probado con éxito en los últimos ficheros de actualización de MediaTitan, ZoltarTv y Wyplayer.


#! /bin/sbash
# wup_extract
# 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.2


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

FILE=$1
#Obtenemos la información XML y la almacenamos en un fichero
echo -e  "Analizando el fichero $FILE."
FILE_SIZE=`du -b $FILE | cut -f1`
LINEAS=`wc -l $FILE | cut -d' ' -f1`
ROOT_BEGIN=`grep -a -n -u "root" $FILE | head -n1 | cut -d':' -f1`


echo -e  "\t$LINEAS líneas totales. La sección root comienza en la línea $ROOT_BEGIN."

TAIL=`expr $LINEAS - $ROOT_BEGIN + 1`
tail -n $TAIL $FILE > $FILE.xml
VERSION=`cat $FILE.xml | grep version | head -n1 | cut -d'>' -f 2 | cut -d'<' -f1 | sed -e 's/^0*//' | sed -e 's/\.0*/./g'`
XML_FILE=infoxml\_$VERSION.xml
mv $FILE.xml $XML_FILE
echo -e  "\tObtenida información XML del firmware $VERSION: $XML_FILE"



#Información del kernel
KERNEL_VERSION=`cat $XML_FILE | grep -A 9 "<id>1" | grep version | head -n1 | cut -d'>' -f 2 | cut -d'<' -f1`
KERNEL_SIZE=`cat $XML_FILE | grep -A 9 "<id>1" | grep uncompressedSize | head -n1 | cut -d'>' -f 2 | cut -d'<' -f1`
KERNEL_FILE=kernel$KERNEL_VERSION\_$VERSION.bin
KERNEL_SIGNATURE=`cat $XML_FILE | grep -A 9 "<id>1" | grep signature | head -n1 | cut -d'>' -f 2 | cut -d'<' -f1`

#Información del fichero de software
SOFTWARE_FILE=software_$VERSION.bin
SOFTWARE_SIZE=`cat $XML_FILE | grep -A 9 "<id>2" | grep uncompressedSize | head -n1 | cut -d'>' -f 2 | cut -d'<' -f1`
SOFTWARE_SIGNATURE=`cat $XML_FILE | grep -A 9 "<id>2" | grep signature | head -n1 | cut -d'>' -f 2 | cut -d'<' -f1`


echo -e  "\tSección kernel en el XML. Version:$KERNEL_VERSION, Tamaño: $KERNEL_SIZE, Checksum: $KERNEL_SIGNATURE."
echo -e  "\tSección software en el XML. Tamaño: $SOFTWARE_SIZE, Checksum: $SOFTWARE_SIGNATURE."

echo -e  "Buscando offset de los ficheros kernel y software..."
for KERNEL_OFFSET in `seq 1 200`
do
  dd if=$FILE of=$KERNEL_FILE bs=1 count=200 skip=$KERNEL_OFFSET 2> /dev/null
  file $KERNEL_FILE | grep "u-boot/PPCBoot image" > /dev/null
  if [ $? -eq 0 ]
  then
    break
  else
    echo -e  "\t$KERNEL_OFFSET"
  fi
done
HEADER_BYTES=$KERNEL_OFFSET
HEADER_BYTES_FILE=header_bytes_$VERSION.bin
MIDDLE_BYTES=10
MIDDLE_BYTES_FILE=middle_bytes_$VERSION.bin
SOFTWARE_OFFSET=`expr $HEADER_BYTES + $KERNEL_SIZE + 10`
FOOTER_BYTES=`expr $(expr $(du -b $FILE | cut -f1)) - $(expr $HEADER_BYTES + $KERNEL_SIZE + $MIDDLE_BYTES + $SOFTWARE_SIZE) - $(expr $(du -b $XML_FILE | cut -f1))`
FOOTER_BYTES_FILE=footer_bytes_$VERSION.bin

echo -e  "\tEl kernel se encuentra entre los bytes $KERNEL_OFFSET y $( expr $KERNEL_OFFSET + $KERNEL_SIZE )."
echo -e  "\tEl software se encuentra entre los bytes $SOFTWARE_OFFSET y $( expr $SOFTWARE_OFFSET + $SOFTWARE_SIZE )."

echo -e  "Extrayendo bytes de la cabecera..."
dd if=$FILE of=$HEADER_BYTES_FILE bs=1 count=$HEADER_BYTES 2> /dev/null
echo -e  "\tFichero de cabecera ($HEADER_BYTES_FILE) extraido."

echo -e  "Extrayendo fichero de kernel..."
touch $SOFTWARE_FILE
dd if=$FILE of=$KERNEL_FILE bs=1 count=$KERNEL_SIZE skip=$KERNEL_OFFSET 2> /dev/null&
DIFF=`expr $KERNEL_SIZE - $( du -b $KERNEL_FILE | cut -f1 )`
while [ ! $DIFF -eq 0 ]
do
  echo -e  "\tQuedan $DIFF bytes por extraer"
  sleep 5
  DIFF=`expr $KERNEL_SIZE - $( du -b $KERNEL_FILE | cut -f1 )`
done

KERNEL_FILE_TYPE=`file $KERNEL_FILE`
MD5SUM=`md5sum $KERNEL_FILE | cut -d' ' -f1`
if [ $MD5SUM == $KERNEL_SIGNATURE ] 
then
  echo -e  "\tFichero de kernel ($KERNEL_FILE) extraido y correcto"
else
  echo -e  "ERROR: Fichero de kernel ($KERNEL_FILE) incorrecto"
fi

echo -e  "Extrayendo bytes del medio..."
dd if=$FILE of=$MIDDLE_BYTES_FILE bs=1 count=$MIDDLE_BYTES skip=`expr $HEADER_BYTES + $KERNEL_SIZE` 2> /dev/null
echo -e  "\tFichero de bytes del medio ($MIDDLE_BYTES_FILE) extraido."

echo -e  "Extrayendo fichero de software..."
touch $SOFTWARE_FILE
dd if=$FILE of=$SOFTWARE_FILE bs=1 count=$SOFTWARE_SIZE skip=$SOFTWARE_OFFSET 2> /dev/null&
DIFF=`expr $SOFTWARE_SIZE - $( du -b $SOFTWARE_FILE | cut -f1)`
while [ ! $DIFF -eq 0 ]
do
  echo -e  "\tQuedan $DIFF bytes por extraer"
  sleep 5
  DIFF=`expr $SOFTWARE_SIZE - $( du -b $SOFTWARE_FILE | cut -f1)`
done
SOFTWARE_FILE_TYPE=`file $SOFTWARE_FILE`
MD5SUM=`md5sum $SOFTWARE_FILE | cut -d' ' -f1`
if [ $MD5SUM == $SOFTWARE_SIGNATURE ] 
then
  echo -e  "\tFichero de software ($SOFTWARE_FILE) extraido y correcto"
else
  echo -e  "ERROR: Fichero de software ($SOFTWARE_FILE) incorrecto"
fi

echo -e  "Extrayendo bytes del final..."
dd if=$FILE of=$FOOTER_BYTES_FILE bs=1 count=$FOOTER_BYTES skip=`expr $HEADER_BYTES + $KERNEL_SIZE + $MIDDLE_BYTES + $SOFTWARE_SIZE` 2> /dev/null
echo -e  "\tFichero de bytes del final ($FOOTER_BYTES_FILE) extraido."

kill `pidof dd` 2> /dev/null

Actualizar un dispositivo con el firmware de otro

editar

Uno de los problemas que se están encontrando es que no se puede utilizar un firmware de uno de los dispositivos en otro dispositivo distinto. Parece ser que el motivo es que cada dispositivo tiene un identificador y además que la parte de "software" del fichero firmware está encriptada de forma distinta para cada dispositivo.

Si esto fuera simplemente así, sería teóricamente posible crear un firmware para un dispositivo al que se le cambiara la parte de kernel y aún así permitiría la actualización. Teniendo cada uno de los 6 trozos de un fichero de actualización podría construirse uno como la mezcla de varios ficheros firmware distintos.

Nota: esto no parece posible. Se ha probado un kernel de Wyplayer en un CMT2DW, escribiéndolo directamente con un comando dd, y el dispositivo no arranca. (minukab. 9-3-2010)

Script para mezclar ficheros de firmware

editar

Para probar este concepto de mezclar el contenido de dos ficheros de firmware se ha creado un script capaz de generar un nuevo fichero .wup a partir de otros dos distintos. Para ello, descompone cada uno de los dos originales (si todavía no se encuentran descompuestos en el directorio) y ofrece una serie de posibles combinaciones. Esto puede ser interesante para comprobar si alguna de ellas nos permite actualizar nuestro dispositivo. Por regla general, de todas las opciones que ofrece el script, pueden interesar aquellas que mezclan una parte de un dispositivo ajeno y el resto lo toman del propio. Y más concretamente la que toma el kernel de otro y el resto del propio. Todavía no se han puesto a pruebas los ficheros generados por este script, por lo que se recomienda cautela a la hora de utilizarlos.

IMPORTANTE: Para que el script funcione hay que cambiar el valor de la variable EXTRACT_PROGRAM y establecer la ruta completa al script de extracción.

El funcionamiento es sencillo:

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 al script de extracción
EXTRACT_PROGRAM=<PATH_COMPLETO_AL_SCRIPT_DE_EXTRACCION>/extract_xml

if [ ! -f $EXTRACT_PROGRAM ]
then
    echo "Debe establecer la variable EXTRACT_PROGRAM a la ruta completa donde se encuntra el script de extracción"
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

Generar "kernel" propio e instalarlo en los dispositivos

editar

SH4 toolchain para compilación cruzada desde 386 de 32 bits. Descargar y descomprimir en opt: http://www.megaupload.com/?d=HSV19P40

Generar "software" propio e instalarlo en los dispositivos

editar

SH4 toolchain para compilación cruzada desde 386 de 32 bits. Descargar y descomprimir en opt: http://www.megaupload.com/?d=HSV19P40

Acceso Telnet al dispositivo

editar

Para tener acceso telnet al dispositivo es necesario modificar un fichero del disco duro. Para ello será necesario sacar el disco duro y conectarlo a un PC para poder acceder a él. Para acceder al disco y poder modificar el archivo necesitamos una distro linux cualquiera. Si no se dispone de ella se puede usar un live cd de Ubuntu o cualquier otra distribución.

El archivo a modificar se encuentra en la partición 1 que es JFS. Para montarla se deben ejecutar esto comandos:

(nota: sda se debe sustituir por lo que corresponda)


$ sudo mkdir /mnt/sda1
$ sudo jfs_fsck /dev/sda1
$ sudo mount /dev/sda1 /mnt/sda1

Una vez la tenemos montada debemos modificar el archivo "local_conf.py". Abrimos el fichero con gedit (o kedit desde kde):

$ sudo gedit /mnt/sda1/local_conf.py

y añadimos las siguientes líneas al final (ojo con el "-l", es una L y no un Uno):

import os

os.system('telnetd -l /bin/ash')


Una vez hecho esto desmontamos la partición ( umount /mnt/sda1 ) y ya podemos volver a montar el disco duro en el reproductor.

A partir de este momento ya deberiamos tener acceso telnet al dispositivo: (si está conectado a la red, obviamente)

$ telnet ip_del_reproductor
Wybox Release Branch 1.3.15 (Future is Now!)
/ $

De momento, se ha comprobado que este procedimiento es valido para las siguientes versiones:

                Funciona                 No funciona
Media Titan:  7983 y anteriores            7989
Zoltar TV:    7891 y anteriores            7909
Wyplayer:     8399, 8379 y ¿anteriores?    8418                      
Mediatec:          ?                         ?

Enlaces a ficheros de firmware

editar

O2Media ZoltarTV

editar

Conceptronic MediaTitan

editar
  Para el CMT2D (sin Wi-Fi):  
     http://download.conceptronic.net/GrabnGo/CMT2D_CMT2DW/CMT2D_FW_UPD_v1.3.15.7989_(1.3R6).zip
     http://download.conceptronic.net/GrabnGo/CMT2D_CMT2DW/CMT2D_FW_UPD_v1.3.15.7984_(1.3R5).zip
     http://download.conceptronic.net/GrabnGo/CMT2D_CMT2DW/CMT2D_FW_UPD_v1.3.15.7983_(1.3R4).zip
     http://download.conceptronic.net/GrabnGo/CMT2D_CMT2DW/CMT2D_FW_UPD_v1.3.15.7963_BETA.zip
     http://download.conceptronic.net/GrabnGo/CMT2D_CMT2DW/CMT2D_FW_UPD_v1.2.14.7929.ZIP
     http://download.conceptronic.net/GrabnGo/CMT2D_CMT2DW/CMT2D_FW_UPD_v1.2.14.7926.zip
     http://download.conceptronic.net/GrabnGo/CMT2D_CMT2DW/CMT2D_FW_UPD_v1.1.13.7870.ZIP
     http://download.conceptronic.net/GrabnGo/CMT2D_CMT2DW/CMT2D_FW_v1.1.13.7860.ZIP
  Para el CMT2DW (con Wi-Fi): 
     http://download.conceptronic.net/GrabnGo/CMT2D_CMT2DW/CMT2DW_FW_UPD_v1.3.15.7989_(1.3R6).zip
     http://download.conceptronic.net/GrabnGo/CMT2D_CMT2DW/CMT2DW_FW_UPD_v1.3.15.7983_(1.3R4).zip
     http://download.conceptronic.net/GrabnGo/CMT2D_CMT2DW/CMT2DW_FW_UPD_v1.3.15.7963_BETA.zip
     http://download.conceptronic.net/GrabnGo/CMT2D_CMT2DW/CMT2DW_FW_UPD_v1.2.14.7929.ZIP
     http://download.conceptronic.net/GrabnGo/CMT2D_CMT2DW/CMT2DW_FW_UPD_v1.2.14.7926.zip
     http://download.conceptronic.net/GrabnGo/CMT2D_CMT2DW/CMT2DW_FW_UPD_v1.1.13.7870.ZIP
     http://download.conceptronic.net/GrabnGo/CMT2D_CMT2DW/CMT2DW_FW_v1.1.13.7860.ZIP

Wyplayer

editar

--- ya no aparecen en la web oficial aunque siguen funcionando: