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
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
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
- Find the next
- Advance 2 bytes:
- Delete until the end of the line:
- Go down a line:
- Delete until end of the file:
- Write the resulting data:
- Open the file:
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!