First part of a blog post series about our approach to reverse engineer a Philips TriMedia based IP camera.
Bonjour à tout le monde !
This is a three parts blog post series in which I'm going to talk about a barely known CPU architecture: Philips TriMedia. This is still an ongoing project in which a first version was already presented at Ekoparty 2018 and was selected for BlackHat Europe 2018. Unfortunately, I couldn't make it for BH for personal reasons but an updated version of the talk is going to be presented at Troopers19.
This first part is an introduction to the research project, the first steps that I followed when I found the device and what happened after. The second part will focus more on the architecture itself and the third part will talk about the TriMedia assembly. I hope you like it. Any feedback is welcome, just drop me a line at ncriva [at] quarkslab.com or buzz me on TW (@crackinglandia).
Tell the story, bro!
Some years ago, a co-worker, Francisco Falcon, and I did a presentation at hack.lu and Ekoparty about hacking IP cameras. That was my first contact with the embedded world. We had a lot of fun and from that moment on, IoT became a very interesting topic for me. That way, each time I got some device, I had to open it and study it.
Some months ago, I got a D-Link IP camera, specifically, a DCS-5300. It is an end user's IP camera, mostly for home users to watch what's happening in their house or work when they are not there. This is an old IP camera but it has something very interesting from the hardware perspective.
Usually, or at least from what I saw over the years, IP cameras have an ARM or MIPS CPU inside but this is not the case here. This model, and some others from the DCS-5xxx family, have a TriMedia CPU, a very old CPU. Why is this interesting? Personally, it is a new architecture for me and that's great because I can learn new things. However, there is very little documentation about TriMedia CPUs. From what I saw during this research, nobody has docs about it, nobody is allowed to speak about it, nobody is willing to share anything about it, everything seems to be a little bit "scary" and "obscure" about the TriMedia CPU. Why? Well, I really don't know. My bet is that as it is a proprietary CPU, originally from Philips, maybe it is a matter of NDAs.
In this post, we are going to talk about the first approach I took with the firmware analysis, then we'll see some analysis of the software and hardware present in the camera, and then, we'll do an introduction to the special CPU this camera has.
The first thing I do when I start to analyze a new device is to get the firmware, generally, from the vendor's site. The latest available version of the firmware is A3 1.06 (2009) but I decided to analyze the previous version v1.05, because it is the one I have installed on my camera.
I ran binwalk over the firmware image a got the following result:
fastix@fastix-virtual-machine:~/dcs-5300$ binwalk dcs5300_firmware_105.bin DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 978627 0xEEEC3 HTML document header 979192 0xEF0F8 HTML document footer 979238 0xEF126 HTML document header 995907 0xF3243 HTML document header 996327 0xF33E7 HTML document footer 997041 0xF36B1 HTML document header 997325 0xF37CD HTML document footer 998169 0xF3B19 HTML document header 1000439 0xF43F7 HTML document footer 1000448 0xF4400 HTML document header 1000689 0xF44F1 HTML document footer 1000698 0xF44FA HTML document header 1000743 0xF4527 HTML document footer 1007314 0xF5ED2 HTML document footer 1007323 0xF5EDB HTML document header 1008041 0xF61A9 HTML document footer 1010780 0xF6C5C HTML document footer 1010789 0xF6C65 HTML document header 1011723 0xF700B HTML document footer 1011737 0xF7019 HTML document header 1012801 0xF7441 HTML document header 1013342 0xF765E HTML document footer 1013438 0xF76BE HTML document header 1017960 0xF8868 HTML document footer 1017969 0xF8871 HTML document header 1018032 0xF88B0 HTML document footer 1021031 0xF9467 HTML document footer 1025042 0xFA412 HTML document footer 1030588 0xFB9BC HTML document footer 1034276 0xFC824 HTML document footer 1036344 0xFD038 HTML document footer 1038311 0xFD7E7 HTML document footer 1044539 0xFF03B HTML document footer 1046711 0xFF8B7 HTML document footer 1047499 0xFFBCB HTML document footer 1049110 0x100216 HTML document footer 1049897 0x100529 HTML document footer 1049906 0x100532 HTML document header 1050018 0x1005A2 HTML document footer 1050026 0x1005AA HTML document header 1056592 0x101F50 HTML document footer 1060214 0x102D76 HTML document header 1060247 0x102D97 HTML document footer 1060755 0x102F93 XML document, version: "1.0" 1096400 0x10BAD0 Unix path: /usr/local/etc/zoneinfo 1103113 0x10D509 Base64 standard index table 1103407 0x10D62F HTML document header 1103549 0x10D6BD HTML document footer 1103557 0x10D6C5 HTML document header 1103691 0x10D74B HTML document footer 1103699 0x10D753 HTML document header 1103857 0x10D7F1 HTML document footer 1106328 0x10E198 Microsoft Cabinet archive data, 278748 bytes, 1 file 1385220 0x152304 Certificate in DER format (x509 v3), header length: 4, sequence length: 964 1386188 0x1526CC Certificate in DER format (x509 v3), header length: 4, sequence length: 1023 1387215 0x152ACF Certificate in DER format (x509 v3), header length: 4, sequence length: 1215 1388434 0x152F92 Certificate in DER format (x509 v3), header length: 4, sequence length: 1269 1388593 0x153031 Digi International firmware, load address: 0x204D6963, entry point: 0x66742053, 1390788 0x1538C4 JPEG image data, JFIF standard 1.02 1392148 0x153E14 GIF image data, version "89a", 1 x 1 1392191 0x153E3F GIF image data, version "89a", 1022 x 124 1424806 0x15BDA6 GIF image data, version "89a", 584 x 8 1426129 0x15C2D1 GIF image data, version "89a", 96 x 96 1431469 0x15D7AD GIF image data, version "89a", 107 x 48 1432998 0x15DDA6 GIF image data, version "89a", 8 x 476 1434185 0x15E249 GIF image data, version "89a", 4 x 402 1434868 0x15E4F4 GIF image data, version "89a", 552 x 6 1436408 0x15EAF8 GIF image data, version "89a", 592 x 33 1440118 0x15F976 GIF image data, version "89a", 592 x 33 1445416 0x160E28 GIF image data, version "89a", 592 x 33 1450651 0x16229B GIF image data, version "89a", 592 x 33 1455879 0x163707 GIF image data, version "89a", 107 x 48 1457575 0x163DA7 GIF image data, version "89a", 107 x 48 1459238 0x164426 GIF image data, version "89a", 107 x 48 1461378 0x164C82 GIF image data, version "89a", 107 x 48 1463544 0x1654F8 GIF image data, version "89a", 107 x 48 1465357 0x165C0D GIF image data, version "89a", 107 x 48 1467138 0x166302 GIF image data, version "89a", 107 x 48 1468934 0x166A06 GIF image data, version "89a", 107 x 48 1470780 0x16713C GIF image data, version "89a", 107 x 48 1472975 0x1679CF GIF image data, version "89a", 107 x 48 1475212 0x16828C GIF image data, version "89a", 107 x 48 1476772 0x1688A4 GIF image data, version "89a", 107 x 48 1478325 0x168EB5 GIF image data, version "89a", 107 x 48 1480001 0x169541 GIF image data, version "89a", 107 x 48 1481655 0x169BB7 GIF image data, version "89a", 107 x 48 1483360 0x16A260 GIF image data, version "89a", 107 x 48 1485155 0x16A963 GIF image data, version "89a", 107 x 48 1486785 0x16AFC1 GIF image data, version "89a", 107 x 48 1488409 0x16B619 GIF image data, version "89a", 107 x 48 1489931 0x16BC0B GIF image data, version "89a", 107 x 48 1491372 0x16C1AC GIF image data, version "89a", 107 x 48 1493089 0x16C861 GIF image data, version "89a", 107 x 48 1494774 0x16CEF6 GIF image data, version "89a", 45 x 62 1496151 0x16D457 GIF image data, version "89a", 45 x 62 1497544 0x16D9C8 GIF image data, version "89a", 592 x 33 1502797 0x16EE4D GIF image data, version "89a", 592 x 33 1506569 0x16FD09 GIF image data, version "89a", 107 x 48 1508333 0x1703ED GIF image data, version "89a", 107 x 48 1511052 0x170E8C GIF image data, version "89a", 107 x 48 1512824 0x171578 GIF image data, version "89a", 58 x 34 1513950 0x1719DE GIF image data, version "89a", 58 x 34 1515053 0x171E2D GIF image data, version "89a", 107 x 48 1517167 0x17266F GIF image data, version "89a", 107 x 48 1519329 0x172EE1 GIF image data, version "89a", 68 x 37 1521849 0x1738B9 GIF image data, version "89a", 68 x 37 1524424 0x1742C8 GIF image data, version "89a", 37 x 37 1525605 0x174765 GIF image data, version "89a", 37 x 37 1526826 0x174C2A GIF image data, version "89a", 37 x 68 1529382 0x175626 GIF image data, version "89a", 37 x 68 1532007 0x176067 GIF image data, version "89a", 68 x 68 1536479 0x1771DF GIF image data, version "89a", 68 x 68 1540151 0x178037 GIF image data, version "89a", 37 x 68 1542697 0x178A29 GIF image data, version "89a", 37 x 68 1545300 0x179454 GIF image data, version "89a", 37 x 37 1546541 0x17992D GIF image data, version "89a", 68 x 37 1549014 0x17A2D6 GIF image data, version "89a", 68 x 37 1551567 0x17ACCF GIF image data, version "89a", 37 x 37 1553024 0x17B280 HTML document header 1555494 0x17BC26 HTML document footer 1556564 0x17C054 HTML document header 1556598 0x17C076 HTML document footer 1556607 0x17C07F HTML document header 1556720 0x17C0F0 HTML document footer 1556729 0x17C0F9 HTML document header 1557234 0x17C2F2 HTML document footer 1557742 0x17C4EE GIF image data, version "89a", 82 x 40 1559960 0x17CD98 GIF image data, version "89a", 81 x 40 1562052 0x17D5C4 GIF image data, version "89a", 54 x 40 1564516 0x17DF64 Base64 standard index table 1565332 0x17E294 Base64 standard index table
As you can see in the output, binwalk was able to recognize some HTML, XML and GIF files only. There are also some certificates of what seems to be some Base64 index tables, but there aren't any signs of a bootloader, kernel or filesystems. Generally, bootloader and kernel image tend to be at the beginning of the firmware's image file, but that's not the case.
Binwalk also identified something called "Digi International firmware" but we'll see later that is just a false positive.
For those who have not noticed, binwalk was capable of recognizing some files starting at offset 0xEEEC3, what about the rest? I assumed that the binary blob at the beginning of the file was encrypted/compressed or both, so I decided to do an entropy analysis using binwalk ("-E" and "-B -E" options):
- Entropy analysis only
- Entropy plus signature analysis
By looking at the graphs, we can see that almost the first megabyte of data has a very high entropy and looking at the variation, we can't totally be sure that it is only compressed or encrypted. Even though I tried to do a more exhaustive analysis of the entropy, I couldn't identify any known algorithm or cipher. At this point, I was sure I wasn't dealing with a common firmware image.
The last thing I tried at this point was to look at the strings (strings dcs5300_firmware_105.bin > output.txt) but I didn't find anything that could give me a clue about what I was dealing with.
So, I left this approach for a moment (we will see later what this binary blob has inside) and tried something different.
Exploring the attack surface
The next thing I tried was to start looking at different aspects of the camera in order to see if there was any vulnerability I could take advantage off in order to get access to it. At the end, we always want to get a shell. :)
I started by doing an nmap scan:
nmap -sV 192.168.1.0/24 Nmap scan report for 192.168.1.106 Host is up (0.0018s latency). Not shown: 994 closed ports PORT STATE SERVICE VERSION 21/tcp open ftp 23/tcp open telnet 80/tcp open http D-Link Internet Camera 5001/tcp open commplex-link? 5002/tcp open rfe? 5003/tcp open filemaker? 3 services unrecognized despite returning data. If you know the service/version, please submit the following fingerprints at https://nmap.org/cgi-bin/submit.cgi?new-service : ==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)============== SF-Port21-TCP:V=7.60%I=7%D=11/7%Time=5A01C181%P=i686-pc-windows-windows%r( SF:NULL,20,"220\x20DCS-5300\x20FTP\x20server\x20ready\.\r\n")%r(GenericLin SF:es,34,"220\x20DCS-5300\x20FTP\x20server\x20ready\.\r\n530\x20access\x20 SF:denied\.\r\n")%r(Help,34,"220\x20DCS-5300\x20FTP\x20server\x20ready\.\r SF:\n530\x20access\x20denied\.\r\n")%r(SMBProgNeg,34,"220\x20DCS-5300\x20F SF:TP\x20server\x20ready\.\r\n530\x20access\x20denied\.\r\n"); ==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)============== SF-Port23-TCP:V=7.60%I=7%D=11/7%Time=5A01C181%P=i686-pc-windows-windows%r( SF:NULL,26,"\xff\xfd\x18DCS-5300\x20Telnet\x20Daemon\r\nPassword\x20:\x20" SF:)%r(GenericLines,26,"\xff\xfd\x18DCS-5300\x20Telnet\x20Daemon\r\nPasswo SF:rd\x20:\x20")%r(tn3270,26,"\xff\xfd\x18DCS-5300\x20Telnet\x20Daemon\r\n SF:Password\x20:\x20")%r(GetRequest,31,"\xff\xfd\x18DCS-5300\x20Telnet\x20 SF:Daemon\r\nPassword\x20:\x20Password\x20:\x20")%r(RPCCheck,26,"\xff\xfd\ SF:x18DCS-5300\x20Telnet\x20Daemon\r\nPassword\x20:\x20")%r(Help,31,"\xff\ SF:xfd\x18DCS-5300\x20Telnet\x20Daemon\r\nPassword\x20:\x20Password\x20:\x SF:20")%r(SIPOptions,94,"\xff\xfd\x18DCS-5300\x20Telnet\x20Daemon\r\nPassw SF:ord\x20:\x20Password\x20:\x20Password\x20:\x20Password\x20:\x20Password SF:\x20:\x20Password\x20:\x20Password\x20:\x20Password\x20:\x20Password\x2 SF:0:\x20Password\x20:\x20Password\x20:\x20")%r(NCP,26,"\xff\xfd\x18DCS-53 SF:00\x20Telnet\x20Daemon\r\nPassword\x20:\x20"); ==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)============== SF-Port80-TCP:V=7.60%I=7%D=11/7%Time=5A01C181%P=i686-pc-windows-windows%r( SF:GetRequest,10D,"HTTP/1\.1\x20401\x20Unauthorized\r\nWWW-Authenticate:\x SF:20Basic\x20realm=\"DCS-5300\"\r\nContent-Type:\x20text/html\r\nServer:\ SF:x20D-Link\x20Internet\x20Camera\r\n\r\n<HTML>\n<HEAD>\n<TITLE>Protected SF:\x20Object</TITLE></HEAD><BODY>\n<H1>Protected\x20Object</H1>This\x20ob SF:ject\x20on\x20the\x20server\x20is\x20protected\.<P>\n</BODY></HTML>")%r SF:(HTTPOptions,6E,"HTTP/1\.1\x20405\x20Method\x20Not\x20Allowed\r\nAllow: SF:\x20GET,\x20HEAD,\x20POST\r\nContent-Length:\x200\r\nServer:\x20D-Link\ SF:x20Internet\x20Camera\r\n\r\n")%r(RTSPRequest,6E,"HTTP/1\.1\x20405\x20M SF:ethod\x20Not\x20Allowed\r\nAllow:\x20GET,\x20HEAD,\x20POST\r\nContent-L SF:ength:\x200\r\nServer:\x20D-Link\x20Internet\x20Camera\r\n\r\n")%r(Four SF:OhFourRequest,E8,"HTTP/1\.1\x20404\x20Not\x20Found\r\nContent-Type:\x20 SF:text/html\r\nServer:\x20D-Link\x20Internet\x20Camera\r\n\r\n<HTML>\n<HE SF:AD>\n<TITLE>Object\x20Not\x20Found</TITLE></HEAD><BODY>\n<H1>Object\x20 SF:Not\x20Found</H1>The\x20requested\x20URL\x20\x20was\x20not\x20found\x20 SF:on\x20the\x20server\.<P>\n</BODY></HTML>")%r(SIPOptions,6E,"HTTP/1\.1\x SF:20405\x20Method\x20Not\x20Allowed\r\nAllow:\x20GET,\x20HEAD,\x20POST\r\ SF:nContent-Length:\x200\r\nServer:\x20D-Link\x20Internet\x20Camera\r\n\r\ SF:n"); MAC Address: 00:0D:88:7E:35:B9 (D-Link)
We have the following services:
- HTTP server: This is used for the management of the IP camera. An HTTPS server can be enabled from the web interface but is not turned on by default.
- FTP server: This is used to access the screenshots and audio the camera can generate. It is the most comfortable way to access the multimedia files.
- Telnet server: This is used for a more "advanced" management of the camera.
There are three other services I wasn't sure at the very beginning what their function was, but after doing some Googling, I could find out something interesting about them:
Radio Free Ethernet (RFE) is a network audio broadcasting system. It consists of programs and tools that allow packets of audio data to be transmitted around a network. The system is best understood by using the analogy of traditional radio broadcasting.
The camera has an incorporated microphone so this service is probably used to broadcast the captured audio.
- The filemaker (TCP 5003) service is used to stream live video, a kind of RTP/RTSP service. With the D-ViewCam application, we can access the audio and video transmitted by the camera. The transmission is done via HTTP by requesting the video.vam file.
- The commplex-link (TCP 5001) service is used to sync up the audio and video transmitted by the camera .
All these services seem to be custom-made, I didn't find any banner of a well-known http, ftp, etc... server.
When connecting to the Telnet server, you have to specify a password. The password is 'admin' (I just tried the default ones, and guess what? I had luck) and cannot be changed by the user in the web interface nor by using the Telnet service.
If you type 'help', you get the following menu:
DCS-5300 Telnet Daemon Password : Authorized and start service Supported commands : debug : Dump debug information dinote : Dump changed input status stop : Stop dumping debug info and input status diquery : Dump current input status do1=h : Set output 1 to high do1=l : Set output 1 to low erase graph : Erase all graphics erase homepage : Erase custom homepage lock : Lock network settings unlock : Reset network settings clear : Restore factory settings reset : Restart system save : Save parameters
We have an option to reset to factory settings and one to reset network settings, another option to restart the camera, and then some debug options. For example, the 'debug' option shows the following information:
TLN: Start debugging SYS: MAC address = 00-0D-88-7E-35-B9 ETH: Activate Ethernet ETH: Ethernet link speed is 100Mbps. SYS: Ethernet is chosen SYS: -----NET INFO----- SYS: Host IP=192.168.1.106 SYS: Subnet Mask=255.255.255.0 SYS: Default gateway=192.168.1.1 SYS: Primary DNS server=126.96.36.199 SYS: Secondary DNS server=188.8.131.52 SYS: Video modulation is NTSC SYS: No logo TLN: Server starts up FTP: Server starts up SYS: No background SYS: No custom homepage H263 Encode Task start! Audio Encode Task start! comm res0:0 h263_control.dwBitRate=356000 WWW: Server starts up Reboot Timer started Reboot after 86400 sec = 1day 00hr:00min:00sec SYS: System starts at 2017/11/07 12:01:54 in local time [UPNPMiniServer] Bind at port 19815 UPnP started:0 [RpSendingServerPushResponse] TLN: Xf00b -STOP-
We have information about the network settings in the camera (MAC, IP, DNS servers), the status of the different services running, and that's it, not too much more.
Usually, there is always an option to get a shell but this is not the case. It seems to be a very limited (fake) Telnet server with just a few options. If you grep strings in the image firmware file, you'll find some interesting things:
SYS: -----NET INFO----- SYS: Host IP=%s SYS: Subnet Mask=%s SYS: Default gateway=%s SYS: Fail to set gateway SYS: Primary DNS server=%s SYS: Secondary DNS server=%s 192.168.0.99 Network Interface OK DHCP proceeding DHCP proceed failed DHCP proceed OK End of get IP loop !!!! SYS: Ethernet is chosen SYS: Jump out NetTask system.log network.log video@%04d%02d%02d%02d%02d%02d.jpg video.jpg EML: socket error 0000000%04d%02d%02d TLN: Telnet is logged in as admin TLN: Telnet rejects user reset help pass stop debug newweb Restart Web %X conn? conn%02d %d %02d %08X conn%02d %d %02d %08X mess? mess=%d lock Fail unlock save clear erase graph erase homepage dinote diquery DI1=H DI1=L setmac setlanguage iicw iicr (%02X, %01X)->%02X hang suicide fanon on ok fanoff off ok ethernet report Unknown command: -WRAPPED- -STOP- TLN: Connected by %s Telnet timeout for no action
Scrambled with some of the Telnet commands we saw, there are some strings that seem to be part of other 'undocumented' commands, for example the 'fanon' and 'fanoff', which I suppose are used to turn on and turn off, respectively, a kind of 'fan' inside the camera (this is not entirely true, if you disassemble the camera, you won't find any fan there. This fan is probably present in another device from the same family). There is another interesting command called 'suicide' that is used to reboot the camera. There is also a 'newweb' command that is used to create a new root for the web server.
There's not much else we can talk about this service.
When connecting to the FTP server (anonymous is the default connection type; we can set a user and password from the web interface), we get the following:
We get the root of the FTP server and we can't go anywhere from here. This is the only accessible folder for us. Also, as you can see, there aren't many files we can get. Most of the files are 0 sized.
We can see a file named 'flash.bin'. This file contains the file system of the camera but we can't download it, its permission is just 'w' (write), we don't have 'r' (read) access. However, we do have access to the 'config.ini' file. This file contains all the configuration from the camera, including the web interface credentials. So, assuming that we get a remote code execution vulnerability in the future, this file is the one we should get. Here's a little extract of the content of the 'config.ini' file:
DCS-5300 Initial Configuration File [SYSTEM] <reset system> Yes <host name> DCS-5300 <serial number> 000D887E35B9 <software version> PT31x2-DLNK-0105b <current date> 2017/11/07 <current time> 12:19:12 <time zone> -3 <user name> (0)admin (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) (15) (16) (17) (18) (19) (20) <user password> (0)admin
At the moment, there isn't too much else we can do with the FTP server. It is mostly used to store all the media (screenshots, audio, video) collected by the camera.
The HTTP server gives us access to a web interface via a browser:
The default administrator's user is 'admin' with blank password. As you can see, you can change it in the web interface. Also, you can add different users and restrict them to use I/O and PT functionality. One interesting thing is that there is a 'guest' account available with user 'demo' and blank password. This guest account gives us access to the video stream via snapshots. Unfortunately (from an attacker's point of view), this account is disabled by default. However, some of the cameras I found in shodan.io had the demo account enabled.
Nowadays, if you search for a DCS-5300 camera in a service like Shodan, you won't get too many results.
If you pay attention to the 'realm' used in the 'WWW-Authenticate' header from the response, you'll see that if you grep in the firmware image file, there will be a different 'User-Agent' reported by the web server:
The 'User-Agent' reported by the web server is the one used by Vivotek IP cameras, VVTK. Is it the same web server used by Vivotek? Well, I'm not sure but it could be an option ;p given that it shares almost the same CGI API that some Vivotek IP cameras. For example, this is the WEB API provided by a Vivotek PT31x4 IP camera (check the ' URL Commands of the Network Camera' section) and this is the one provided for the DCS-5300. do you see the similarities?
As in many other cases, CGI programs are a very good starting point to look for vulnerabilities. Our goal is to have unauthenticated access to the camera through the web administration interface, which tends to be the exposed part to the Internet.
The only known vulnerability until now, or at least the only one I could find, is CVE-2012-5319, a CSRF in the /setup/security.cgi app in which an authenticated can be fooled to follow a link and this way the administrator account be hijacked. Just for the records, here's the PoC for this vulnerability:
However, this vulnerability requires the user to be logged to the web administration interface. That's not what we are looking for. We need unauthenticated access. So, I decided to make a list of all the possible CGI programs listed in the documentation of the D-Link and Vivotek IP cameras:
CGIs available in the Vivotek IP camera documentation -- /cgi-bin/video.jpg requires admin access (Protected Object) /cgi-bin/getdi.cgi requires admin access (Protected Object) /cgi-bin/setdo.cgi requires admin access (Protected Object) /setup/restore.cgi requires admin access (Protected Object) /setup/reset.cgi requires admin access (Protected Object) /setup/system.cgi object not found /setup/security.cgi object not found /setup/network.cgi object not found /setup/ddns.cgi requires admin access (Protected Object) /setup/mailftp.cgi object not found /setup/video.cgi object not found /setup/ptcamera.cgi requires admin access (Protected Object) /setup/image.cgi object not found /setup/app.cgi object not found CGIs available in the D-Link IP camera documentation -- /cgi-bin/sysinfo.cgi requires admin access (Protected Object) /cgi-bin/admin/configfile.cgi requires admin access (Protected Object) /setup/setmd.cgi requires the privilege of I/O access control (Protected Object) /cgi-bin/camctrl.cgi requires camera control access privilege (Protected Object) /cgi-bin/recall.cgi requires camera control access privilege (Protected Object) /cgi-bin/senddata.cgi requires camera control access privilege (Protected Object) (Only for models with RS-485 port)
Also, the doc lists all the referenced URLs used by the CGI programs:
Homepage name Referenced URL Client settings page /client.html configuration page /setup/config.html system option /setup/system.html security option /setup/security.html network option /setup/network.html DDNS & UPnP option /setup/ddns.html audio/video option /setup/video.html camera control option /setup/ptframe.html motion detection /setup/motion.html image quality option /setup/image.html application option /setup/app.html system log /setup/logfile.html system parameters /setup/parafile.html set factory default /setup/factory.html
Most of the CGI programs listed in the Vivotek's doc aren't available in the D-Link camera and the ones available require authentication. The same happens with the ones listed in the D-Link's doc, all CGI programs require authentication. Some of these CGIs were affected by different vulnerabilities in the past in some other Vivotek IP camera models, as the ones tagged as CVE-2013-1594, getparam.cgi and the parafile.html page .
Just to be sure I didn't miss any CGI program, I did a grep over the firmware image file but it seems that I checked all:
Ok, it seems that we couldn't find any unauthenticated CGI.
Then, I spent some time playing with Burp Suite and some of the CGI programs in order to see if I could find a post-auth vulnerability, mostly a remote command execution, to have access to the internal file system and that way have access to CGI binaries. I tried the most common issues as path traversal, semicolon injection in places like the DDNS, NTP, config, but due to the lack of output I wasn't sure about the success of the commands. I needed to go deeper, it was time to open the device.
Exploring the hardware
I decided to open the camera. I was hoping to find an interface like UART or similar in order to have access to the file system through a shell. This is what I found.
The camera has two PCBs. The biggest has almost all the interesting components we can find in a device like this (CPU, RAM, Flash, etc) and the small one has some chips for the PTZ functionality.
This is a picture of the front side of the biggest PCB:
In the above picture, we can identify the following components:
We have 128 MB of RAM, WiFi/Ethernet capabilities, 16 MB of Flash, a small video decoder and an EEPROM chip.
Then, this is a picture of the back side of the PCB:
On this side, we can see that we only have a big chip identified as Philips TriMedia PNX1300EH (32-bit processor). This is the reason for this post and we'll have a specific section dedicated to it.
Finally, this is a picture of the second PCB:
As you can see, most of the hardware in this camera is what anyone expects to find in a device of this kind. There isn't anything special about it except the fact that the CPU is not what you commonly see in the IP cameras sold today, most of them use ARM or MIPS CPUs.
Before going into some details about the TriMedia CPU, let's talk a little bit about the pinout found on this device.
If you pay attention to the first picture, the one about the front side of the biggest PCB, we can see two interesting pinouts:
We have 10 pins marked with a red rectangle and 12 pins marked with a yellow rectangle. At first sight, both look promising but the 10 pins are a little bit far from the main CPU and there aren't visible traces to it. Instead, the 12 pins are really close to the main CPU and there are traces that seem to go in that direction. If we read the datasheet, specifically, the Chapter 18 "JTAG Functional Specification", we can see that the TriMedia CPU has a JTAG interface. These are good news!, but we have to identify the right pinout. This is not always an easy task, however, my first approach was trying to reverse engineer the pinout using a voltmeter as described here. After some time, I came up with the following results:
- P1: Voltage fluctuation: 0,94 - 1, 14 - 2,x - 3,46 (TX?)
- P2: Voltage fluctuation: 2,x - 3,46 (after a few seconds, remains steady at 3,46) (RX?)
- P3/P4: Fixed voltage: 3,29
- P5/P7/P11: Voltage fluctuation: 3,27 - 3,29 - 3,30
- P9: Fixed voltage: 1,79
- P6/P8/P10/P12: GND
Even though we got some information about the nature of the signals, we cannot get too much detailed information with a voltmeter in this case. The right tool we need in this case is an oscilloscope. With a scope you can check the basic nature of a signal (VCC, GND, Pulled-up line, numeric signal) and guess its parameters (max voltage, frequency, etc). At that moment, I didn't have that tool in my hands, I was armed with only a voltmeter and a Bus Pirate. Even though it's possible to build a cheap oscilloscope using a Bus Pirate, the bandwidth and sampling rate aren't good (5720 samples per second; in practice, gives a maximum measurable frequency of about 1kHz). At the end, in order to continue with this work, I bought a PicoScope 2204A but that will be a subject for another post.
Just as a side note, there exists a JTAG PCI debugger for TriMedia microprocessors offered by Monument Data Systems that can be used to debug the code running on this CPUs. I'm not sure if it is useful in this particular case, but it is good to know that we have more options.
The Philips TriMedia CPU
TriMedia microprocessors were originally manufactured by Philips, currently known as NXP (Nexperia) semiconductors (Qualcomm announced the acquisition of NXP in 2016 ). It is a family of VLIW  (Very Long Instruction Word) processors, which means they can execute a given number of instructions in parallel at the same time, with a Harvard architecture  and its main use is for DSP (Digital Signal Processing) .
At the very beginning, TriMedia processors were designated with the acronym 'PNX' and then it was changed to 'TM'.
In order to program code for TriMedia microprocessors, there is an official SDK that includes everything you need (libraries, compiler, debugger, simulator, etc) but is not available except for the big companies that sell products using TriMedia processors, D-Link and 2Wire, for example. However, there are some TriMedia compliant SDK as the one offered by Streaming Networks, known as IADK (Integrated Application Development Kit), specifically designed for the PNX1300 family series.
Also, there are some development boards equipped with TriMedia CPUs that can be acquired if you want to play with this processor, for example, the TriREF development board offered by Streaming Networks. However, this kind of board, which includes the IADK, is not cheap. In fact, I contacted Streaming Network and asked for the TriREF board and it costs around US $5,000, a lot of money that I can't afford.
At the time of this study (January 2019), I looked for other options on the market, but they did not include the SDK.
If you want to read more about TriMedia microprocessors, you can refer to its corresponding Wikipedia entry.
In this post, I'm going to refer, specifically, to the TriMedia PNX1300EH microprocessor. Hopefully, all the information provided here can help you to research other processors of the same family.
Sources of information to Reverse Engineer a TriMedia CPU
To reverse engineer a TriMedia processor is not an easy task, especially due to the lack of documentation and tools. There is a very little documentation on the Internet about the TriMedia architecture, the instruction set documentation is poor and the existing tools are private and expensive. Anyway, there are some old sources of information we can use in order to start our journey.
The first source of information to start the research is the datasheet. This document includes information about all the architecture of the processor. We can get the main idea of the different components in the chip, how they interact, the specific instruction set used by the controller, etc. If you want to start with the right foot, you MUST read the datasheet.
Another good source of information, although specifically about JTAG research, is http://hackingbtbusinesshub.wordpress.com. Even though the blog is not available anymore, there are still some copies stored in web.archive.org   . This guy did an excellent work reversing 2Wire routers, which are based on TriMedia CPUs, and creating some excellent tools as 2wiglet (based on urjtag, a JTAG wiggler tool for 2Wire routers and tm32dis), a TriMedia disassembler for the TM32 family.
Now we are talking about JTAG, in a previous section, I mentioned that there is a JTAG PCI debugger for TriMedia CPUs offered by Monument Data System. There also exist an official JTAG debugger offered by Philips but it has some peculiarities. Quoting asbokid:
The TriMedia JTAG tools are designed to work only with a proprietary JTAG cable. The ‘cable’ is actually a sophisticated piece of programming equipment. It is a USB device that connects to the PC via a NetChip NET-2282 peripheral controller. The programmer boots from its own EEPROM and is driven by a Philips PNX1502 CPU with NOR flash and DRAM memory.
Obviously, IDA can't be excluded from the list of tools. IDA has support for TriMedia CPUs since its 4.x version, specifically, its 4.21 version :
New features in version 4.21 (19/04/2002) Processors Trimedia (upon special request only) [..]
As you can read in the release notes, the processor module is only available upon special request. I requested the processor module from HexRays but they no longer offer it.
Finally, during this research I collected different kinds of information about TriMedia (doc, tools) and stored it on a github repo.
In this first part of the series, I introduced the Philips TriMedia architecture. I used the IP camera as an excuse to talk about how it is to research a TriMedia based device, what and how much public information resources are available regarding software and hardware and how to deal with its magic ASM.
In the second part I'll dig into the TriMedia architecture itself. See you later! :)
Thanks to all my Quarkslab colleagues who proofread this article and provided valuable feedback.