Reverse Engineering My WiFi Endoscope Part 4
Tags:
Bottom Line: I got root on a WiFi Endoscope.
- Part 1: Introduction and Serial Debug Port to Get WiFi Password
- Part 2: Reading Flash to Get Telnet Password
- Part 3: Using WireShark to Decode UDP Protocol
- Part 4: Using Netcat to Decode Video Protocol
Part 4: Using Netcat to Decode Video Protocol
Part 3 review: I used WireShark to figure out the UDP protocol that the WiFi endoscope uses to configure its password and access point name, among other settings.
My primary objective with this project was to ensure that I could continue to use the endoscope even if the iOS app went unmaintained; after figuring out how to configure the endoscope’s settings, the last thing I needed was to be able to view the video feed without the app.
I’ve mentioned a few times that nmap showed port 7060 to be open, and that I suspected this was the video feed based on the fact that connecting to it yielded an unending stream of data.
Inspecting 30 seconds or so of its data, I found a few points of interest:
$ netcat 192.168.10.123 7060 > netcat_out
$ strings netcat_out | head
BoundaryS
JFIF
(:3=<9387@H\N@DWE78PmQW_bghg>Mqypdx\egc
/cB8Bcccccccccccccccccccccccccccccccccccccccccccccccccc
$3br
%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz
&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz
1L@E
,%!4
Z@-8t
Some
Googling
of those strings led me to believe it was using a JFIF image format (especially
since it includes JFIF
in the content). Eventually, I found a super helpful
SO answer suggesting that I
should look for FFD8
to start and FFD9
to end an image in the feed.
As a test, I tried to snip out a single image:
- Open the binary file in neovim:
nvim "+:setlocal display=uhex" netcat_out
- Delete until
ffd8
:d/\%xff\%xd8
- Find the next
ffd9
:/\%xff\%xd9
- Advance 2 bytes:
ll
- Delete until the end of the line:
d$
- Go down a line:
j
- Delete until end of the file:
dG
- Write the resulting data:
:w netcat_endoscope.jpg
- Open the file:
!open netcat_endoscope.jpg
The resulting file:
Clearly I was correct, this stream is the image data.
I tried a number of ways of viewing this stream in the browser without success, but I eventually found a Python method leveraging OpenCV that worked great. Below, I’m using OpenCV 4.0.1 installed via Homebrew and python 3.7.2.
import cv2
cap = cv2.VideoCapture("http://192.168.10.123:7060")
while True:
ret, frame = cap.read()
cv2.imshow('Video', frame)
if cv2.waitKey(1) == 27:
exit(0)
The stream does have a strange line through the middle (like the image shown above), but other than that it seems to work well. If you have other suggestions on how to view this stream (especially if it gets rid of this artifact), feel free to let me know in the comments!
At this point, having read the firmware flash, discovered the telnet password for an administrative account, figured out how to configure the endoscope by sending commands over UDP, and figured out how to stream the video feed without requiring the app, I consider this project wrapped up. I hope you’ve enjoyed this writeup of my first adventure in reverse engineering an electronic device!
UPDATE 20190328
After many hours of fiddling, I finally figured out how to stream the video through VLC, and how to record video through ffmpeg, both of which may be more user-friendly than the python / opencv solution presented above.
After lots of experimenting with --codec=mjpeg
and --demux=mjpeg
and
http://
vs tcp://
, based on this SO
answer I finally came up with a
VLC command that works:
$ vlc 'tcp://192.168.10.123:7060/stream.mjpeg'
Instead of /stream.mjpeg
, you can use /file.mjpeg
or even just /.mjpeg
if
you want, the .mjpeg
just seems to be the prompting that VLC needs to get the
filetype right.
Alternatively, using the VLC GUI you can go to File
-> Open Network
and
paste in tcp://192.168.10.123:7060/stream.mjpeg
.
To record to the file out.mov
instead, this seems to work:
$ ffmpeg -i 'tcp://192.168.10.123:7060' -c:v copy out.mov
UPDATE 20200204
A couple months ago, Matthew Plough emailed me to share further work he’s done with the video stream of a similar IOT device; notably, he’s found ways to clear up the video stream and has open-sourced code to help others do so. His write-up is a pleasure to read, fascinating, and demonstrates much better technical knowledge of this territory than I possess. I highly encourage you to read it!