Here's a brief example of reverse-engineering and a bad implementation of encryption.
My friend bought a 58" Plasma TV. He mentioned something about browsing youtube on it. This brief convo led my curiosity to their firmware download page. After downloading the self-extracting windows executable (yay for ZIP file compatibility!) and unzipping it I found a couple files.
pwillis@bobdobbs ~/Downloads/bar/T-CHE7AUSC/ :( ls -l
total 80
-rwxr-xr-x 1 pwillis pwillis 11695 2009-09-14 20:18 MicomCtrl*
-rwxr-xr-x 1 pwillis pwillis 19431 2009-09-14 20:18 crc*
-rwxr-xr-x 1 pwillis pwillis 21057 2009-09-14 20:18 ddcmp*
drwxr-xr-x 2 pwillis pwillis 4096 2010-02-12 14:09 image/
-rw-r--r-- 1 pwillis pwillis 7738 2009-09-14 20:18 run.sh.enc
pwillis@bobdobbs ~/Downloads/bar/T-CHE7AUSC/ :) ls -l image/
total 162080
-rw-r--r-- 1 pwillis pwillis 2048 2010-02-12 13:28 appdata-sample
-rw-r--r-- 1 pwillis pwillis 35663880 2010-02-12 13:54 appdata.fuck
-rw-r--r-- 1 pwillis pwillis 35663872 2009-09-14 20:18 appdata.img.enc
-rwxr-xr-x 1 pwillis pwillis 1573 2010-02-12 13:49 decrypt.pl*
-rwxr-xr-x 1 pwillis pwillis 1573 2010-02-12 13:41 decrypt.pl~*
-rw-r--r-- 1 pwillis pwillis 47304710 2010-02-12 13:50 exe.fuck
-rw-r--r-- 1 pwillis pwillis 47304704 2009-09-14 20:18 exe.img.enc
-rw-r--r-- 1 pwillis pwillis 18 2009-09-14 20:18 info.txt
-rw-r--r-- 1 pwillis pwillis 47 2009-09-14 20:18 validinfo.txt
-rw-r--r-- 1 pwillis pwillis 44 2009-09-14 20:18 version_info.txt
`file` tells us that
MicomCtrl,
crc, and
ddcmp are ELF 32-bit LSB ARM executables. I ignore these because they probably don't serve a major function and since they are plain-old unencrypted files and can be reverse-engineered with a debugger and standard development tools without much trouble.
We can see that there's obviously a shell script and two 'img' files, which are probably filesystem images, all encrypted. The question then becomes, how are they encrypted and how can we decrypt them? I start by opening up the files. The shell script appears to have a normal script-style structure, with multiple lines (sometimes repeating exactly) separated by newlines. Since it has a 'normal'-looking structure I can already guess whatever the encryption method is it isn't very good. Good encryption should give you no idea of what the data is or its form, and should have no apparent patterns in it.
When I open up one of the image files it seems pretty much like random garbage, as is expected. I don't expect to find much in them but i run them through the unix `strings` command anyway. All of a sudden, lots of series of the same ASCII characters tumble out:
"CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7AUSCT-CHE7"The first thing I think is: Holy Shit. I know immediately what i'm looking at. Since my early days experimenting with
XOR encryption I learned two simple principles: one, never repeat the key you're encrypting with, and two, never allow NULL characters in your data! The second applies because XORing anything against NULL (all 0 bits) just outputs the encryption key. As most people familiar with binary files know, they are absolutely rife with null characters, often in series and in large blocks. What I was looking at above was a huge block of the encryption key repeating over and over.
But could it really be that easy? I wrote a quick Perl script to test it.
#!/usr/bin/perl
# decrypt.pl - pwn a stupid firmware encryption
# Copyright (C) 2009 Peter Willis
#
# So here's the deal. I noticed a repeating pattern in the encrypted filesystem
# image of the firmware for this TV. One ASCII string repeating over and over,
# and only partly in other places. From experience with basic XOR encryption you
# may know that you can "encrypt" data by simply taking chunks of unencrypted
# data the same length as your encryption key and using an xor operation. The
# problem is, if there are any 'nulls' in your input data your key is going to
# be shown to the world in the output. My theory is this is what happened here.
use strict;
# This is the string that might be the encryption key. We don't know if this is
# the correct order of the key, only that these characters repeat themselves.
#my $possiblekey = "HE7AUSCT-";
#
# However, by looking at the input again, we know the repeating string is 10 chars
# long. Counting the number of bytes from the beginning of the file to this string
# 10 at a time we can assume the real string's order is:
my $possiblekey = "T-CHE7AUSC";
die "Usage: $0 FILE\nDecrypts FILE with a possible key \"$possiblekey\"\n" unless @ARGV;
$|=1;
open(FILE, "<$ARGV[0]") || die "Error: $!\n";
# Make sure we read an amount of bytes divisible by the length of the key or
# we would mess up our xors
while ( sysread(FILE, my $buffer, length($possiblekey) * 100) ) {
for ( my $i=0; $i < length($buffer); $i+= length($possiblekey) ) {
my $chunk = substr($buffer, $i, length($possiblekey));
print $chunk ^ $possiblekey;
}
}
close(FILE);
And we run it on the script to test the theory:
pwillis@bobdobbs ~/Downloads/bar/T-CHE7AUSC/ :) ./decrypt.pl run.sh.enc
#!/bin/sh
PROJECT_TAG=`cat /.info`
WRITE_IMAGE()
{
if [ -e $2 ] ; then
echo "==================================="
echo "$1 erase & extract & download!!"
echo "==================================="
$ROOT_DIR/ddcmp -d -i $2 -o $3
sync
echo "===============DONE================"
elif [ -e $2.enc ] ; then
echo "==================================="
echo "$1 erase & extract & download!![Enc]"
echo "==================================="
$ROOT_DIR/ddcmp -e $PROJECT_TAG -i $2.enc -o $3
sync
echo "===============DONE================"
fi
}
As you can see, the script decoded beautifully with this key on the first try. The other two encrypted files also decode fine. It turns out "exe.img.enc" is a FAT filesystem image with an x86 boot sector (obviously for 'dd'ing to some storage device on the TV). The "appdata.img.enc" file is a Squashfs filesystem.
It took about 20 minutes for me to download and decode this supposedly-encrypted firmware image. This is the lesson: use a real tool for encryption. Do not think you know how to do it yourself. And don't waste your time trying to obfuscate a filesystem image from me; i'll just crack open the TV and dump the flash ROM.
For extra fun: note the name of the directory the executable was originally extracted into. :-)