Monday, August 9, 2010

Hacking Coradir STB CDR1000D HDTV Receiver

It's been a long time since I last wrote something 'interesting' so I'll try to start doing so more often or at least to use this blog as an ideas repository instead of my never ending TODO list :)

A couple of months ago I had the opportunity to try the Set Top Box CDR1000D from Coradir (may be this procedure works for the CDR1000, too) which is an HTDV receiver being sold in Argentina and also given for free (on certain cases) by the government to impulse the
Digital Terrestrial Television initiative. The CDR1000 uses an ARM-based processor called CSM1201 produced by Celestial Semiconductor.

There are a couple of things I usually do when I get an embedded device of any kind and I'm allowed to play with it, meaning remove it's case (as opposed to what happened when I tried to open my wife's Garmin Nuvi GPS but that's another story) :
  1. Try to identify any JTAG or Serial communication port on the board.
  2. Download any available firmware at the manufacturer/vendor page and try to reverse engineer it.
  3. Identify any EPROM memory and download it's data-sheet to dump it's content.
Step 1 is the easiest one but given that at the moment there was no firmware update available on the vendor web page then I started to look at the board and proceed with step 2 to look for any pins fooling around waiting to be used.
As you can see in the picture there are a couple of candidates so I decided to start trying with the one with four pins which looks like a serial port to me... so I took my multimeter and started to try to figure out the pinout doing the following:

  1. Unplug the device or turn off the main circuit breaker before attempting anything.
  2. Set your multimeter for continuity test to identify the GND (Ground) by looking for connectivity between anyone of those pins and the outer (metallic) part of any of the connectors outside the box. Don't worry, this won't harm the device.
  3. Turn on the device.
  4. Set your multimeter to measure VCC, then connect the (usually) black cable from the multimeter to the pin previously identified as GND. Then connect the (usually) red cable from your multimeter to each of the other pins available and when you find one measuring 3.3V then you've got VCC.
  5. The two remaining are either Tx (Transmission) or Rx (Reception) and they can be easily figured out later but you can deduce that Rx won't have any activity because it's the cable where you connect the Tx end of your RS232 adapter as explained later (or the Bus Pirate through my pythom module pyBusPirate2) to transmit the data from your computer to the STB. Opposed to this, the Tx pin should have some activity in case that the device sends any information (usually during boot sequence).
Next I used my home-brew RS232 Adapter (it's just a simple TTL level converter) which is similar to the ones in this page (or you can just Google on how to create your adapter to connect your PC to a IC).
Because my adapter needs 5v I took them from the USB connector in the read of the CDR1000D (shame on me!) and connected the GND cable from the adapter to the GND pin discovered on the board and then took the Rx cable of my adapter to one of the two still mysterious pins (remember that we've already identified GND and VCC so those two remaining pins are Tx and Rx but we still don't know which one is what).

On the computer side I opened a terminal and started cu at a baud-rate of 4800 (I didn't know the correct baud-rate yet but even if it's right or wrong you should see something in the terminal is the pin where we connected the cable is the correct one (device Tx instead of RX). Of course the first try was not correct (lucky me) so I tried the other pin and some garbage started to appear on the screen so at that moment I knew the cable was correctly connected as shown bellow and garbage was due to the incorrect baud-rate of the terminal.

I began trying all the different baud-rates until I found the correct one, 115200, which was obviously the last try. Finally I used the following parameters:

me@host $ cu -l /dev/ttyUSB0 -s 115200

... and I started to receive some output from the device so I restarted it and got the following

U-Boot 1.2.0 (May 13 2010 - 14:10:45)

DRAM: 256 MB
## Unknown FLASH on Bank 1 - Size = 0x00000000 = 0 MB
Flash: 0 kB
Bad block table found at page 131040, version 0x01

Bad block table found at page 131008, version 0x01
64 MB
SPI Booting... Speed at [R:10MHz/W:5MHz] Flash Size: 1MB
Init CSM1201 I2C!
In: serial
Out: serial
Err: serial
MAC: 00:1a:cc:08:f8:cd
Hit any key to stop autoboot: 0
Init CSM1201 I2C!

EEPROM @0x50 read: addr 00001000 off 0200 count 1 ... done
Init CSM1201 I2C!

EEPROM @0x50 read: addr 00100000 off 0004 count 1 ... done
## Booting image at 34060000 ...
Bad Magic Number
USB: ERROR : No interrupt for (0xa)
Error, couldn't init Lowlevel part

NAND read: device 0 offset 0x0, size 0x200000

Reading data from 0x1ffe00 -- 100% complete.
2097152 bytes read: OK
## Booting image at 03000000 ...
Image Name: Linux-
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1586828 Bytes = 1.5 MB
Load Address: 00008000
Entry Point: 00008000

Starting kernel ...

Uncompressing Linux.................................................................................................... done, booting the kernel.
Linux version (root@localhost.localdomain) (gcc version 3.4.6) #1 Thu Apr 22 05:37:00 UTC 2010
CPU: ARM926EJ-Sid(wb) [41069265] revision 5 (ARMv5TEJ)
CPU0: D VIVT write-back cache
CPU0: I cache: 16384 bytes, associativity 4, 32 byte lines, 128 sets
CPU0: D cache: 16384 bytes, associativity 4, 32 byte lines, 128 sets
Machine: ORION
Memory policy: ECC disabled, Data cache writeback
Built 1 zonelists
Kernel command line: root=/dev/mtdblock/1 rw rootfstype=jffs2 console=ttyS0,115200 mem=64M mtdparts=ORION:2m(Part01),-(Part02) ethaddr=00:1A:CC:08:F8:CD
ORION Readed MAC:00:1a:cc:08:f8:cd
PID hash table entries: 512 (order: 9, 8192 bytes)
Console: colour dummy device 80x30
Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
Memory: 64MB = 64MB total
Memory: 61568KB available (2467K code, 645K data, 96K init)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
NET: Registered protocol family 16
SCSI subsystem initialized
Linux Kernel Card Services
options: none
usbcore: registered new driver usbfs
usbcore: registered new driver hub
NetWinder Floating Point Emulator V0.97 (extended precision)
devfs: 2004-01-31 Richard Gooch (
devfs: boot_options: 0x0
NTFS driver 2.1.22 [Flags: R/O].
JFFS2 version 2.2. (NAND) (C) 2001-2003 Red Hat, Inc.
fb0: ORION frame buffer @[0xf400000, 0xc4880000] size 0xc00000
fb1: ORION frame buffer @[0xe800000, 0xc5500000] size 0xc00000
ORION GPIO at 0x101e4000, 16 lines
ORION GPIO2 at 0x10260000, 55 lines
Smart card: base address 101f0000 map to c4866000
Orion Watchdog Timer: timer margin 40 sec
Xport: Init OK [0x0e100000].
orion_video: Orion Video driver was initialized, at address@[phyical addr = 41600000, size = 100000]
csdrv audio init ok ...
Default ORION I2C at 0x10170000, 100KHZ
orion15_df: Orion Display feeder driver was initialized, at address@[phyical addr = 41800000, size = 1000]
orion15_df: Orion TVE0 driver was initialized, at address@[phyical addr = 10168000, size = 1000]
orion15_df: Orion TVE1 driver was initialized, at address@[phyical addr = 10160000, size = 1000]
pinmux0 : 0x0, pinmux1: 0x1001
dma_pool_alloc: dma_phy_addr: 3d2a000, ttx_buf: ffc00000
Serial: 8250/16550 driver $Revision: 1.90 $ 2 ports, IRQ sharing disabled
ttyS0 at MMIO 0x101f1000 (irq = 12) is a 16550A
ttyS1 at MMIO 0x101f2000 (irq = 13) is a 16550A
io scheduler noop registered
io scheduler anticipatory registered
RAMDISK driver initialized: 1 RAM disks of 16384K size 1024 blocksize
loop: loaded (max 8 devices)
ORION eth0: 0x41400000 IRQ 24 MAC:00:1a:cc:08:f8:cd
Not SST flash.<5>physmap flash device: 800000 at 34000000
NAND device: Manufacturer ID: 0xec, Chip ID: 0x76 (Samsung NAND 64MiB 3,3V 8-bit)
Using command line partition definition
Creating 2 MTD partitions on "ORION":
0x00000000-0x00200000 : "Part01"
0x00200000-0x04000000 : "Part02"
PCMCIA: orion_pcmcia_init called!
Succesefully create pcmcia proc entry!
orion socket ci module initializing!!!
Initializing USB Mass Storage driver...
usbcore: registered new driver usb-storage
USB Mass Storage support registered.
usbcore: registered new driver usbhid
drivers/usb/input/hid-core.c: v2.01:USB HID core driver
drivers/usb/musb/musb_driver.c: Initializing MUSB Driver [npci=1][gadget=no][otg=no]
MUSB Drive version
mgc_controller_init: Driver instance data at 0xc3d3ce00
mgc_hdrc_init: MHDRC version 1.500 info: UTMI-8, dyn FIFOs, SoftConn
mgc_controller_init: End 00: FIFO TxSize=0040/RxSize=0040
mgc_controller_init: End 01: Shared FIFO TxSize=0200/RxSize=0200
mgc_controller_init: End 02: FIFO TxSize=0000/RxSize=0040
mgc_controller_init: End 03: Shared FIFO TxSize=0400/RxSize=0400
mgc_controller_init: New bus @0xc3d1a820
musb-hcd usb0: new USB bus registered, assigned bus number 1
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 1 port detected
NET: Registered protocol family 2
IP: routing cache hash table of 512 buckets, 4Kbytes
TCP established hash table entries: 4096 (order: 3, 32768 bytes)
TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
TCP: Hash tables configured (established 4096 bind 4096)
NET: Registered protocol family 1
NET: Registered protocol family 17
NET: Registered protocol family 15
Empty flash at 0x017bdca0 ends at 0x017bde00
Empty flash at 0x026427d8 ends at 0x02642800
jffs2_scan_dirent_node(): Node CRC failed on node at 0x02dd53e8: Read 0xffffffff, calculated 0xacd3f548
VFS: Mounted root (jffs2 filesystem).
Freeing init memory: 96K
Warning: unable to open an initial console.
jffs2_get_inode_nodes(): Data CRC failed on node at 0x02641db0: Read 0x3444ce97, calculated 0xf1cad815
jffs2_get_inode_nodes(): Data CRC failed on node at 0x017bd4a4: Read 0xd94d27c4, calculated 0xdebb94f3
-/bin/sh: ./test_fwdebug: not found
[1] + Done(127) ./test_fwdebug 1 1
============= SBDevFonts ============
0: rbf-fixed-rrncnn-12-24-ISO8859-1, charsetname: ISO8859-1, style: 0
========== End of SBDevFonts =========

============= MBDevFonts ============
1: rbf-fixed-rrncnn-24-24-GB2312-0, charsetname: GB2312-0, style: 0
2: rbf-fixed-rrncnn-*-*-UTF-8, charsetname: UTF-8, style: 0
3: rbf-fixed-rrncnn-*-*-UTF-16LE, charsetname: UTF-16LE, style: 0
4: rbf-fixed-rrncnn-*-*-UTF-16BE, charsetname: UTF-16BE, style: 0
========== End of MBDevFonts =========
system font 0: rbf-fixed-24-ISO8859-1
system font 1: *-fixed-24-GB2312-0
warnning: You have no fip frontpanel!
IAL: Use orionfpc engine.
MiniGUIMain 27630
default key_value = 0x1c
default key_value = 0x2 Set Led Charecters Success
Timing mode =21
loading xport firmware
write gpio 15 to 1
readed xport fw data section size =240
readed xport fw text section size =10872
loded xport firmware
CS_CRC_Init error = 1, time[28040]
CS_DB_Init error = 1, time[28110]
CS_AV_Init error = 1, time[29080]

GPIO0 Write 1 Succeed!!!
definition_index = 1
bufsize = 9437184
read_len = 2652 ,===no data
read_len = 2652 ,===no data
read_len = 2652 ,===no data
read_len = 2652 ,===no data
AspectRatio = 15
CS_AV_Play_IFrame 29980
DB_DemuxInit error = 0, time[29980]
PDmx_SFilter->pid = 0x0
PDmx_SFilter->pid = 0x2
PDmx_SFilter->pid = 0x11
PDmx_SFilter->pid = 0x10
CS_SI_Init error = 1, time[29980]
CS_DT_Init error = 1, time[29980]

GPIO6 Write 0 Succeed!!!

GPIO6 Write 1 Succeed!!!
CS_FE_Init error = 1, time[31520]
CS_INSTALL_Init error = 1, time[31520]
PDmx_SFilter->pid = 0x12
PDmx_SFilter->pid = 0x12
CS_EIT_Init error = 1, time[31530]
CS_TIMER_Init error = 1, time[31720]
PDmx_SFilter->pid = 0x14
PDmx_SFilter->pid = 0x14

GPIO0 Write 1 Succeed!!!
definition_index = 1
[USB_CON]:Creating usbcon thread.
$125336 Set Led Charecters Success MSG_CHECK_SERVICE_LOCK = 0 *****************************CS_MW_PlayServiceByIdx************************* CSDEMUX_Filter_ReadWait Timeout! CSDEMUX_Filter_ReadWait Timeout! CSDEMUX_Filter_ReadWait Timeout! CSDEMUX_Filter_ReadWait Timeout! CSDEMUX_Filter_ReadWait Timeout! CSDEMUX_Filter_ReadWait Timeout! CSDEMUX_Filter_ReadWait Timeout! CSDEMUX_Filter_ReadWait Timeout!

CSDEMUX_Filter_ReadWait Timeout!


# ls -la
drwxr-xr-x 3 528 528 0 Dec 4 2009 .
drwxr-xr-x 18 root root 0 Jan 1 00:00 ..
-rwx------ 1 root root 601945 May 14 2010 csapp.elf
-rwx------ 1 root root 127352 Jan 1 00:09 database
drwxr-xr-x 2 root root 0 May 14 2010 resource
-rwx------ 1 root root 45817 Dec 4 2009 test_fwdebug.bak
# uname -a
Linux uclibc #1 Thu Apr 22 05:37:00 UTC 2010 armv5tejl unknown
# whoami

At this point I connected an Ethernet cable from my computer to the device and issued:

# ifconfig eth0 netmask up
# ping

PING ( 56 data bytes

64 bytes from seq=0 ttl=64 time=10.000 ms

64 bytes from seq=1 ttl=64 time=0.000 ms
64 bytes from seq=2 ttl=64 time=0.000 ms
64 bytes from seq=3 ttl=64 time=0.000 ms
64 bytes from seq=4 ttl=64 time=0.000 ms

--- ping statistics ---

5 packets transmitted, 5 packets received, 0% packet loss

round-trip min/avg/max = 0.000/2.000/10.000 ms




Guill0 said...

Muy bien!!! Veo que dejaste de lado esas mariconadas del software y te esta metiendo con el hardware.

topo said...

mmm no... no dejar nada de lado es la clave del exito :)

Unknown said...

Si es la última versión del firmware, podrías subir el binario csapp.elf a megaupload para estudiarlo.

Anonymous said...

Si es la última versión del firmware estaría bueno que subas el binario csapp.elf para estudiarlo.

topo said...

Hola, no aplique el ultimo update así no lo tengo.
Si queres charlar sobre el firmware de CDR1000D mandame un mail, dale?

directv hdtv receiver said...

I just needed to say that I found your blog via Goolge and I am glad I did. Keep up the good work and I will make sure to bookmark you for when I have more free time away from the books. Thanks again!

topo said...

Hi! Thanks ... I'm glad you liked it :)

Anonymous said...

quizas te interese ver esto:

topo said...

si, lo vi y esta re bueno lo que hizo!!!
De hecho le deje un mensaje en su blog diciendole esto mismo y con un link a lo que hice yo pero creo que lo borro.

No publique el analisis del upgrade que uno baja de la pagina del fabricante, ni intente buscar/hacer un exploit remoto para esa version de Linux, etc porque lo que yo intente demostrar es un poco una metodologia que puede ser aplicable a otros dispositivos embebidos, por eso hice esto.

Sr.Televisor said...

podes capturar la salida cuando haces el upgrade de firmware y postearla? gracias!

topo said...


Preferiria no hacer el upgrade porque el aparato no es mi y quisiera retornarlo en las mismas condiciones en la que me lo dieron.

Pero tan solo de curioso, que pensas que puede haber ahi?

Alti said...

Una vez compilado, te sirve para scramblear/desescramblear depende el estado del archivo original, asi es como funciona el XOR.

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
class Program
static void Main(string[] args)
byte ckey = 0xe3;
byte ob;
Byte[] b= new byte[1];
String in_name = args[0];
String out_name = args[1];
System.Console.WriteLine("Input File: " + args[0] );
System.Console.WriteLine("Output File: " + args[1]);
FileStream infile = new FileStream(in_name, FileMode.Open, FileAccess.Read);
FileStream outfile = new FileStream(out_name, FileMode.CreateNew, FileAccess.Write);
while (infile.Read(b, 0, 1) > 0)
ob = (byte)(b[0] ^ ckey);



topo said...


Disculpame pero no entiendo a que viene esto de XORear el contenido de un archivo?

Alti said...

El upgrade de CORADIR viene xoreado con esa clave. Dentro hay una image de U-Boot con el kernel, etc, etc

topo said...


Barbaro... tambien podes de las siguietes maneras:

1) Otener la imagen dumpeando el contenido de la flash que esta en /dev

2) Con el metodo el acceso via port serie. como hice yo, podrias reiniciar el STB y frenar cuando arrancar el bootleader y dumpear memoria (y muchas cosas mas) ahi tambien.

Mi pregunta sigue siendo la miama... que crees que puede haber ahi?

Alti said...

Estabamos pensando en una manera que sea "facil" para el usuario final de patchear el STB.

Se me ocurrio que modificar la imagen del firmware poniendole lo que querramos adentro y que el usuario siga el procedimiento normal de upgrade era bastante aceptable.

Tengo armado un ambiente para cross-compilar aplicaciones desde un i386 y despues correrlas en el ARM. Mi intencion es portar algo como el mythtv para correrlo en el STB, pero todavia no estoy seguro que se pueda hacer.
Funciona bien para algunos programitas, tengo uno que te dice el codigo de tecla del control que apretaste, pero todavia no hice nada con el framebuffer (DirectFB, mux, mpg decoder, etc

Bueno, creo que aclare un poco la cosa, avisame si te interesa algun archivo, etc..


topo said...

Realmente lo unico que me interesaba era poder modificar el STB y como ya lo logre, no creo que haga mas cosas (ademas voy a tener que devolverlo en breve).

De todas formas te comento queme parece muy interesante lo que quieren hacer y si puedo darles una mano con algo puntual, no hay problema.

Respecto de modificar la imagen del upgrade quiza no dure mucho si implementan algo firmado pero hasta que no lo hagan, eso funcionaria sin problemas.

Por otro lado, se puede hacer algun exploit para la distribucion de Linux que tiene adentro y dado que no es muy nueva, deben haber mas de un exploit remoto o algun PoC para portar.

Si mal no recuerdo, vi que con Ginga hay algunas funciones interesantes que te dejan cargar modulos propios en memoria (como si fueran .dll o .so)... no estoy para nada seguro de como funciona porque lo lei a los apurones pero quiza valga la pena investigar porque se podria meter eso en un pen y explotarlo por ahi.

Me quede sin ideas :)

~saludos, topo

Anonymous said...

la idea de ver el procedimiento de upgrade es porque no puedo reconocer el formato de la imagen del update.
peor ya lo soluciono alberto con el xor.

Demian said...

No entiendo como teniendo acceso al serial quedaste como root, yo tengo otro stb, y accedo al serial, pero no me da promt ni nada y bootea normalmente y no me da ni bola.

topo said...


Porque el stdin/stdout de la shell del OS (la cual fue ejecutada como root) estaban redirigidos al los pines de Tx/Rx del serial, respectivamente.

Esto no es muy comun. Lo que normalmente se ve como output de un serial es simplemente una interfaz de logging para diagnostico pero en este caso tuvimos suerte :)

Anonymous said...

Hola Topo,
Veo que estas mas al tanto de tema hardware que yo. Tenes data o se puede hacer algo para el TC90517?
No estoy seguro, pero creo que tiene una interface en el kernel tipo V4L.

Encontre esto...


topo said...

No conozco el TC90517 :(

Anonymous said...

Che armamos una lista o algun foro que vayamos todos ahi?
yo entre al stb via telnet (usando el links para cargarlo) y medifique algunas cosas del filesystem
me interesa correr algun player de divx.
montar via nfs un directorio y reproducirlos via red.

Anonymous said...

que boludo, me olvide si me quieren contactar ftoledo (en) docksud com ar

saludos y buen hack!

topo said...

Respecto a correr binarios ahi adentro, no es nada dificil. Si lo haces a mano, es cuestion de cross-compilar GCC (previamente binutils) y listo. Incluso creo que en Ubuntu hay un paquete que se llama binutils-multiarch o algo asi y listo.

Respecto del foro, ya hay varios donde quiza sea mejor crear un thread con esta data y listo en lugar de hacer uno desde cero, no?

~saludos, topo

Anonymous said...

Topo: si, pase algunos binarios desde debian arm y andan bien el tema es qeu no hay mucho espacio en el stb asi que estoy montando un directorio via nfs
y pasar las dependencias a mano es un embole.
Estoy buscando algun player de video que use el framebuffer para poder reproducir divx. Conocen algun?
con respecto a crear una lista, claro, me referia a usar algun oforo o algo que nos podamos suscribir.
Bah.. a mi, me interesa ver peliculas via red (como hago con la ps2 y el SMS actualmente).


topo said...

Se me ocurre que ya que se pueden montar dispositivos USB, podes montar un pen-drive con el binario ahi compilado con las libs en forma estaticas asi a pesar de que va a ocupar mas, va a estar en el pen-drive y el tema espacio y dependencias no te van a joder tanto, no?

Tema Framebuffer.... Yo uso VLC y tengo entendido que usa el framebuffer (aunque no se si lo accede directamente con /dev/fb o no)... quiza podes probar con ese. Tambien se que el mplayer lo utiliza pero yo no lo uso.

El tema foro... realmente no esoy interesado en seguir haciendo cosas con el Coradir mas alla de haber logrado accederlo y modificar su firmware por motivos de seguridad, pero si crean un foro sin duda me voy a subscribir e intentare colaborar en la medida de lo posible.

~saludos, topo

Anonymous said...

Finalmente me compré uno de estos, para hacer esto. No funcó. No obtengo nada del rs232.

Usé un max232, 4 caps de 0.1uF... los 5v los saqué del panel frontal porque era más fácil que soldar donde el conector usb

Una cosa el GND en todos los diagramas yo lo mandé al - del header de 4 pines, está bien?.

No entiendo por qué no anda. Revisé todas las conexiones 20 veces.

Sólo me queda pensar q tal vez fumigué el max232 con el calor de la soldadura (debería haber usado un zócalo).

Ideas? comentarios? cómo medir si sale data por los dos pines, antes de pasar por el max232?


marigada said...

Yo pude conectar al COradir usando un cable Nokia para uno 3220. EL tema es que no entiendo porque no puedo enviar datos al equipo, posiblemente confundi algun cable pero pude ver todo el log de boot. Posiblemente te vuelva a contactar para que me des algna idea!

Unknown said...

Buenas, estoy pensando que quizás podría recuperar mi cdr1000 con error en el firmware usando JTAG. ¿Será posible?, vivo en Catamarca y no hay oficinas de coradir.