Christmas time is around the corner again and there's just no better time to play pranks on your coworkers, or is that April fools? Well, it doesn't matter, the point is, pranks are fun! Since we also enjoy hacking in all its forms, we decided to have some fun with embedded devices around the office, but we needed a more specific target.
Most of our VoIP phones barely ever ring, but one of the guys in our team seems to get harassed a lot over the phone and, at some point, he just decided to stop answering altogether. Why not try and restore his desire to answer with some Christmas magic? Maybe if we make his ringtone so annoying, he'll just pick up the phone once and for all? Or at the very least we'd get a good laugh out of it!
All Is Merry and Bright
Alright, so how do we start then? Most phones don't offer a built-in function to upload your own ringtones, but that doesn't mean it's impossible. This brings us to the best part, the teardown, and who knows, we might just get lucky. As can be seen here, this is our target, a Fortinet FON-360i.
Wow, jackpot! We have a serial console and the manufacturer even went through the trouble of soldering the header and printing UART next to it on the PCB. Let's not get excited too quickly though, first we'll go ahead and have a look with the logic analyzer.
It also turns out that the thing is relatively chatty, so we didn't even have to bother and reboot to get some good output, as can be seen on channel 0. Baud rate was also not too hard to determine, just the good old standard 115200. A good way to find out is by measuring the duration of the shortest bit sequences which normally represent a single bit, but most modern software will try and calculate it automatically. That solves the issue of the 'transmit' side, but we still need to locate the 'receive' side.
In cases like these, we like to use a very old, reliable and proven method which is called trial and error. This means we now need to switch tools and use a USB-serial cable so that we can transmit on all the pins and generate activity. Unfortunately, the UART seems to get locked at some point during the boot which refuses any input unless we provide a password.
Still, there's no way we'd let such a problem stop us at this point, we'd come way too far to give up, haven't we? So, what then? Well, most of these systems use very standard and open source bootloaders which have known behavior. Typically, they can also be interrupted in the early boot process to allow system recovery in case of major failure.
This means that we have a window of a few seconds during early boot when we can press a key and validate successful transmission. We can now begin jumping around on all the pins while rebooting until we hit the right one. As simple as that! As expected, we eventually figured out what each pin does and we made a clean picture for those who would want to repeat the experiment.
We're off to a pretty good start at this point, some would even dare to say that we are pretty much in control of the situation. As a matter of fact, these bootloaders are so powerful that we could most likely dump the whole firmware and start digging even further, but let's not get ahead of ourselves.
You Better Watch Out
All we want right now is to unlock the console - we needed a password, remember? Although we had to think about a quick way to approach this problem (after all we only had until Christmas), it eventually hit us right in the face.
At this point, we now have a root shell and all that is left to do is navigate around, locate files that resemble audio ringtones and replace them with files of our own choosing. We're not going to mention all the nitty-gritty details because this post is not meant to be a thorough analysis of the embedded device per se, although that may come as another blog post. Nevertheless, it is still interesting to mention that this machine is not built on your typical ARM, MIPS or even PowerPC SOC but rather on top of a 16-bit CR16C architecture. It also uses the BFLT file format, notable in its day for using built-in compression, thus reducing the size of most of the files and the overall filesystem.
That being said, identifying the ringtone files was relatively trivial as the directory structure is pretty straightforward.
But, since we couldn't assume anything about the file format, we decided to start by downloading all of these files via TFTP.
Shall I play for you?
We're getting close to our goal, now we need to try and figure out how the audio is encoded so that we can eventually replicate the same procedure. Unsurprisingly, we are dealing with some form of raw data, no magic numbers, no headers, nothing.
Luckily, someone on the team came to the rescue and saved us from having to play a game of "staring at the binary blob" for hours. The initial silence in the ringtone when played from the phone and the fact that this silence is encoded using a long sequence of 0xFF hinted that we are dealing with a raw file. Within minutes, we were able to identify the encoding scheme by importing it in Audacity as a mono audio channel with μ-law compression at a sample rate of 8 kHz, something fairly common in phone systems.
One last step remains: can we upload the file back and make it stick across reboots? Well, it turns out the ringtones are located in a JFFS2 partition, which means anything we upload will be written back directly to flash, no need to interact with the mtd blocks and risk partially bricking the device, nor would we have to do a custom firmware update. So we used TFTP again. This time in the other direction.
Tis' the Season to Be Jolly
We configured the phone, through its user interface, to use our newly replaced ringtone. Then, we tested out by calling ourselves: it worked!
Work well done, it's time to celebrate!
Jingle all the way
We can conclude by saying that you can customize most embedded systems as long as you have access to the underlying hardware. We hope you learned something new today, at the very least that office pranks are fun!
Merry Christmas to everyone from the GoSecure team!