TL;DR?
Click here to jump directly to the decoding website:
Preamble
So I have this Triax-Hirschmann S-930 DVB-S2 satellite television receiver. It has a feature that allows exporting the channel list to a USB-Drive which will generate a file called OHS1720IR_Channel.OCH
on said drive.
Sadly I wasn’t able to find any documentation about this .OCH file format whatsoever.
What’s in it?
Opening the file in a normal hex editor doesn’t really tell us anything useful with a short look. However when we use the awesome tool binwalk
to analyse the file, we get the following output:
$ binwalk OHS1720IR_Channel.OCH
DECIMAL HEXADECIMAL DESCRIPTION
---------------------------------------------------------------------
96 0x60 Zlib compressed data, compressed
This tells us that there is some Zlib compressed data starting at byte 96
(hex 0x60
). We can use dd
to remove the first 96 bytes from the file so it starts with our Zlib data:
$ dd if=OHS1720IR_Channel.OCH bs=96 skip=1 of=OHS1720IR_Channel.gz
6143+0 records in
6143+0 records out
589728 bytes (590 kB, 576 KiB) copied, 0.0423137 s, 13.9 MB/s
Thanks to the magic of the StackExchange we find out how to decompress this data:
Edit: A friend told me I could have just used binwalk -e
instead…
$ printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" | cat - OHS1720IR_Channel.gz | gzip -dc >OHS1720IR_Channel.bin
gzip: stdin: invalid compressed data--crc error
gzip: stdin: invalid compressed data--length error
Because there is still some other data at the end of the file, this will spit out a warning, but it still gives us the output file we need as OHS1720IR_Channel.bin
.
Let’s see what we’ve got using hexdump
:
$ hd OHS1720IR_Channel.bin | head
00000000 53 69 72 69 75 73 32 2c 33 00 00 00 00 00 00 00 |Sirius2,3.......|
00000010 00 01 16 26 68 29 00 00 22 00 00 00 00 00 00 00 |...&h)..".......|
00000020 00 00 00 00 32 00 00 00 00 00 00 00 45 75 74 65 |....2.......Eute|
00000030 6c 73 61 74 20 57 33 41 00 00 00 00 00 01 16 26 |lsat W3A.......&|
00000040 68 29 23 00 39 00 00 00 00 00 00 00 00 00 00 00 |h)#.9...........|
00000050 46 00 00 00 00 00 00 00 45 75 74 65 6c 73 61 74 |F.......Eutelsat|
00000060 20 57 31 00 00 00 00 00 00 01 16 26 68 29 3a 00 | W1........&h):.|
00000070 4d 00 00 00 00 00 00 00 00 00 00 00 64 00 00 00 |M...........d...|
00000080 00 00 00 00 48 6f 74 62 69 72 64 32 2c 36 2c 37 |....Hotbird2,6,7|
00000090 41 2c 38 00 00 01 16 26 68 29 4e 00 bb 00 00 00 |A,8....&h)N.....|
That looks like a list of satellites. Bingo!
Using emacs
in hex-editor mode (or any other hex editor) we can take a closer look at the file. And sure enough, by searching the text for our first channel’s name, we can see the start of our channel list at decimal 100400
:
00018830: 4f52 4631 2048 4400 0000 0000 0000 0000 ORF1 HD.........
00018840: 0000 0000 0000 0000 3701 6b00 2f13 8127 ........7.k./..'
00018850: 8227 ff1f ff1f ff1f ff1f 8027 8007 8507 .'.........'....
00018860: 0000 0100 1f15 0001 0000 0000 0000 0000 ................
00018870: c100 0000 0100 ff3f 0000 0000 4f52 4632 .......?....ORF2
00018880: 5720 4844 0000 0000 0000 0000 0000 0000 W HD............
00018890: 0000 0000 3701 6c00 3013 692b 6a2b ff1f ....7.l.0.i+j+..
000188a0: ff1f ff1f ff1f 682b 680b 6d0b 0000 0700 ......h+h.m.....
000188b0: 1f15 0001 0000 0000 0000 0000 c100 0000 ................
000188c0: 0200 ff3f 0000 0000 4154 5600 0000 0000 ...?....ATV....
What I figured out is that channels seem to start at decimal 100400
and are always 76
bytes apart from each other.
Sorting
Although on first sight the channels appear to be in the correct order, they are actually arranged in the order they were found ignoring any customisations.
To find out how the actual position is determined, we switch two channels and then compare these files. For this example I moved BCC World from position 46 to position 45 where CNBC Europe used to be.
Binwalk again saves the day with its awesome binary diff tool that we can get using the -W
argument. By adding --red
to the command, we can see only the lines where something was changed.
$ binwalk -W OHS1720IR_Channel.bin OHS1720IR_Channel_bbc.bin --red
Because we swapped two channels, what we’re looking for is two numbers that swapped. In the very last line, at 0x00087DD0
(decimal 556496
) we can see two numbers that swapped places, spaced between other incrementing 16 bit, least significant byte first, numbers. That looks very much like a sorting grid to me. And indeed, after inspecting that space further, there appears to be a sorting grid, starting at decimal 556400
in which the index determines the channel number (as entered with the remote) and the value (two bytes) determines the position in the channel list (described above).
Radio and TV
Both the sorting table and the channel list are for both radio and TV channels even though the receiver doesn’t mix them together and instead has separate modes and channel numbers for those. While the sorting table did give us the correct order, because radio channels were mixed with the TV channels, the numbers didn’t line up correctly when we both count them from one starting point. Thus we need to find a way to determine whether a channel is a radio or a TV channel. I did this by copying the full, hex encoded, data from some of each type and checking them for similarities.
TV:
4d44 5220 5361 6368 7365 6e20 4844 0000 0000 0000 0000 0000 c304 c814 7028 d414 d514 d834 ff1f ff1f ff1f d334 d314 d614 0000 9b05 0016 0001 0000 0000 0000 0000 c104 0000 e02e 0000 0000 0000
8544 6973 6e65 7920 4368 616e 6e65 6c00 0000 0000 0000 0000 1d01 7300 0107 0008 0328 ff1f ff1f ff1f ff1f ff07 ff07 2400 0000 8b00 0014 0001 0000 0000 0000 0000 2100 0000 5f00 ff3f 0000 0000
8586 4e61 7487 696f 6e61 6c20 8647 656f 8767 7261 7000 0000 0801 6b00 0d00 ff1f ff1f ff1f ff1f ff1f ff1f ff2b ff0b 2000 0000 a800 1f11 0001 0000 0000 0000 0000 0100 0000 a800 e02e 0000 0000
RADIO:
4f45 3100 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 2701 6104 4133 a501 ff1f ff1f ff1f ff1f ff1f 0000 a501 0000 0000 2000 0012 0001 0000 0000 0000 0000 0100 0000 2000 ff3f 0000 0000
464d 3400 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 2701 6e04 4e33 b201 0000 0000 0000 0000 0000 0000 b201 0000 0000 c800 0002 0001 0000 0000 0000 0000 0100 0000 c800 ff3f 0000 0000
8652 4f43 4b20 414e 5487 454e 4e45 0000 0000 0000 0000 0001 0d01 6500 a000 3001 0000 0000 0000 0000 0000 0000 3001 0000 0000 6402 0002 0001 0000 0000 0000 0000 0100 0000 6402 ff3f 0000 0000
||
24th byte is here
We see that all radio channels have the 24th
byte (index 23
) set, while all TV channels don’t.
Online Decoder
Based on that knowledge, I was able to build a very crude web-based decoder that you can use here:
If you wish to use it on a separate tab, use this link: https://jsfiddle.net/Himbeer/94pL2sbj/embedded/result/
You may also see the website with (bad) code here: https://jsfiddle.net/Himbeer/94pL2sbj/
Epilogue
I sadly didn’t have time to reverse engineer the full protocol properly (nor do I need or want to, because I just wanted to know the number for each channel so I can print the list).
0 Comments