Introduction and Story
I remember, more then a year ago I watched this fantastic video from stacksmashing about reverse engineering and rebuilding a custom firmware for a webcam. I was absolutely stunned that this is possibile and thought about to try this some time on a device I have at home.
As usual, time passes and I stuck on many other projects and learning topics so I completely forgot about this project until I watched the recently released talks from the OffensiveCon22. More or less by a random pick I watched this interesting talk about pwning routers via the internet. Triggered again by the topic of hacking hardware devices I decided to give this a try.
This is a three part long story
- RE: DC-932L Hacking a Webcam Part 1 – Getting a Shell
- RE: DC-932L Hacking a Webcam Part 2 – Extracting the Firmware
- RE: DC-932L Hacking a Webcam Part 3 – Building the Firmware
First of all I wanted to get a shell on my device. I checked out the YT channel of the Flashback Team and found this very good video about how to get a shell via the UART port.
I instantly started to disassemble some of my IoT devices and searched for a UART port. Although my desired target was another, more up to date device, I decided to start with something where already some resources are online available. This leads me to the D-Link DCS-932L web cam.
After some Google-Fu I found a very on point video and tutorial about how to use the UART Port to get a shell.
UART
I ordered this (no affiliate) TTL Serial Adapter and followed the instructions from the YT video. Unfortunately there where no pin holes on my model so I was forced to solder some contacts to it.
Although it was a little bit fiddly it was not to hard.
![](https://secure77.de/wp-content/uploads/2022/05/image.png)
Connected the wires to the TTL and plugin the USB to my laptop.
![](https://secure77.de/wp-content/uploads/2022/05/image-1.png)
On the laptop we can check if the TTL is recognized correctly
lsusb
![](https://secure77.de/wp-content/uploads/2022/05/image-2-1024x161.png)
now we need to find the tty interface for it
ls /dev | grep USB
![](https://secure77.de/wp-content/uploads/2022/05/image-3.png)
finally we can connect to the tty with screen and the desired baud rate, there a couple of ways to figure out the correct one, as there only a few possible, the fastes way is maybe to try and error it.
screen /dev/ttyUSB0 57600
finally we can boot up the device and bingo, I got my first direct device output 🙂
![](https://secure77.de/wp-content/uploads/2022/05/image-4.png)
Yea 🎉 with the username admin and your configured web password (empty by default) we can logon to the shell
![](https://secure77.de/wp-content/uploads/2022/05/image-5.png)
Well this was easier then expected! I started to look around in the system, tried to spawn a reverse shell (you can do this via openSSL), but this busy box environment is pretty cut off, no curl, no wget, no ncat, only a few commands are possible but at least you can start a telnet server with the command and connect to it from remote.
telnetd
Now we can look for some more interesting stuff like reading sensitive information out of the nvram
/bin/ralink_init rt2860_nvram_show
![](https://secure77.de/wp-content/uploads/2022/05/Pasted-image-20220503232907.png)
reading a specific setting is also possible
nvram_get 2860 SSID
![](https://cdn.discordapp.com/attachments/971216041067823124/972821961342320671/unknown.png)
we can also change the settings in the nvram
nvram_set AdminPassword 123
CVE-2019-10999
Googling a litte bit more about the device I finally found an already disclosed exploit for some DS models.
You need to provide credentials but with this exploit you might be able to start a telnet server via a HTTP get call. The exploit uses a buffer overflow vulnerability in the alphap webserver which is running on the device so you don’t need to open and solder to get a shell.
I can really recommend to read the blog post about the finding (at the end of the readme).
I cloned the repository and tried to exploit my webcam but unfortunately it seams my model is not implemented in the POC, also my firmware is a really old one.
![](https://secure77.de/wp-content/uploads/2022/05/Pasted-image-20220503181506-1024x290.png)
So I started to analyse the exploit code and tried to find a way to extend the POC to my model and version
In the source code we can see the error message comes from this block
![](https://secure77.de/wp-content/uploads/2022/05/Pasted-image-20220503181735-1024x852.png)
It seams that the module for the file is missing. I created a new file DCS-932L.py
in the folder CVE-2019-10999\DlinkExploit\overflows
first with the same content as the file DCS-932LB1.py has and created a function for the version number too. But the exploit failed, the server crashed and there was no code execution. From the blog post about the exploit I learned that we need to provide the correct base address of libc. I connected to the UART Shell again and checked the libc file mapping.
![](https://secure77.de/wp-content/uploads/2022/05/Pasted-image-20220503181110.png)
I adjusted the libc_base address but the exploit still failed. Well there are some other offsets defined for the ROP gadgets for the different models, but to figure these out I would need debug the alphap webserver and with setup the emulating MIPS architecture this was a step I don´t wanted to do. As a final approach I checked the other model scripts and figured out, that these libc base address as also defined in the DCS-930L.py
I copied the file, adjusted the version number and filename and tried the exploit again.
from . import overflow
class Overflow(overflow.Overflow):
def __init__(self):
"""
----------------------------------------------------------------
| Gadget Name | Gadget Offset | Gadget Summary |
----------------------------------------------------------------
| ROP1 | 0x00050DE4 | addiu $s2, $sp, 0x1E8+var_F8 |
| | | move $a0, $s2 |
| | | move $t9, $s0 |
| | | jalr $t9 |
----------------------------------------------------------------
"""
super(Overflow, self).__init__()
self.padding_after_ra = 0x4
self.distance_to_s0 = 0x10
self.s0 = 0x4BD20 # Offset of system in libuClibc-0.9.28.s0
self.ra = 0x50DE4
self.rop_padding = 0x1E8 - 0xF8
def _1_16_4(self):
self.libc_base = 0x2AAEF000
And yes! The exploit now also works for my model and firmware version, the webserver crashes (it will restart after a minute or so by default) and a telnet server will spawn on port 5555 🎉
![](https://secure77.de/wp-content/uploads/2022/05/Pasted-image-20220503181213-1024x254.png)
I created this pull request for the original POC but you can also find the extended POC on my github.
Follow my next post where I extracting the firmware: RE: DC-932L Hacking a Webcam Part 2 – Extracting the Firmware