Jonathan
Jonathan Author of Robopenguins

Hacking a Yo Digital Microscope

Since the last article was on the female side of fertility why not switch to the male? Yo produces a test kit to measure sperm count. It’s main selling point is that it produces a video of the sperms swimming around.

sperm video

The kit comes with a slide, vial of dye, and the imaging device. The imaging device is a plastic box with a slot for the slide. It’s powered over USB and creates a WiFi access point. The idea is you connect to it with a phone or PC, and run their app to take an image and process the results.

yo

It seemed like a fun challenge to see what made the device tick.

Application Reverse Engineering

I downloaded the app, and looking at the install noticed it was an Electron app. A quick Google gave me a guide for how to unbundle the app https://medium.com/how-to-electron/how-to-get-source-code-of-any-electron-application-cbb5c7726c37. This let me see the javascript that made up the main app along with the other resources it came with.

The source code is minified so it looks like this:

1
["\u0275ted"](-1,null,["\n        "]))],function(e,t){var n=t.component;e(t,3,0,0==n.isShowCB_Dis(1)),e(t,6,0,1==n.isShowCB_Dis(1))},null)}function ga(e){return r["\u0275vid"](0,[(e()(),r["\u0275eld"](0,0,null,null,5,"div",[["class","check-svg"]],null,null,null,null,null)),(e()(),r["\u0275ted"](-1,null,["\n        "])),(e()(),r["\u0275ted"](-1,null,["\n        "])),(e()(),r["\u0275ted"](-1,null,["\n        "])),(e()(),r["\u0275eld"](4,0,null,null,0,"div",[["class","loader"]],null,null,null,null,null)),(e()(),r["\u0275ted"](-1,null,["\n\n      "]))],null,null)}function ya(e){return r["\u0275vid"](0,[(e()(),r["\u0275eld"](0,0,null,null,11,"div",[["class","flex-row-conn"]],null,null,null,null,null)),(e()(),r["\u0275ted"](-1,null,["\n                "])),(e()(),r["\u0275eld"](2,0,null,null,0,"img",[["class","sucess-svg"],["src","assets/videos/animations/wait/checkv.svg"]],null,null,null,null,null)),(e()()

But running it through a formatter at least makes it somewhat readable:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
(e.prototype.start = function () {
    var e = this;
    return new Promise(function (t) {
        setTimeout(function () {
            e.logger.write(ee.b.Info, "started recording"),
                e.http.get(e.starturl).subscribe(
                    function (n) {
                        e.logger.write(ee.b.Info, JSON.stringify(n)), t(n);
                    },
                    function (n) {
                        e.logger.write(ee.b.Info, JSON.stringify(n)), t(n);
                    }
                );
        }, 1e3);
    });
}),
(e.prototype.wait = function () {
    var e = this;
    return (
        this.logger.write(ee.b.Info, "waiting 50s"),
        new Promise(function (t) {
            setTimeout(function () {
                e.logger.write(ee.b.Info, "recording time finished"), t(!0);
            }, 5e4);
        })
    );
}),

Searching around the code gave me the overall process.

  1. Once the computer connects to the WiFi, the Yo microscope is reachable at the IP 192.168.0.1
  2. It creates a webserver on port 12913 that provides an API for creating a video clip
  3. This clip is then accessed from a web server running on port 80
  4. The downloaded clip is fed to a local processing algorithm

This local processing algorithm is actually an EXE bundled with the application. It appears to use openCV and appears as YOAlgorithmCalculation.exe and YOAlgorithmCalculation_old.exe

An example interaction with the web apis would be:

1
2
3
4
http://192.168.0.1:12913/startRecord -> {"status": "done", "sessionId": "eSKAW8NGdnIg0Hzp"}
http://192.168.0.1:12913/getClips -> {"clips":[{"url": "http://192.168.0.1/CYC_DV/19700101/CYC_DV_19700101-003454@041350.mp4"}]}

http://192.168.0.1:12913/takeSnapshot -> {"status": "done", "url": "http://192.168.0.1/video_encode/4.jpg"}

Trying to take pictures

I played around a bit trying to get an interesting picture using the microscope. The slides it came with were two pieces of plastic glued together, but you could pry them apart to wash and reuse them.

Unfortunately, it has a fairly small field of view, so you had to get a bit lucky unless you totally coated the slide. I managed to get a decent picture of cat hair, but pretty much everything else came out blurry.

sperm video

As a last ditch effort I tried dying some skin flecks, with food coloring, but it just ended up making a red blur.

sperm video

red blur

Getting Root Access

I could already use the web servers I found to take my own videos, but I wanted to see if I could get root access to the device.

This turned out to be way easier then I expected. Looking at the root of the port 80 web server gave a file system dump.

file server

This included the passwd file. This file stores the user accounts and passwords https://www.cyberciti.biz/faq/understanding-etcpasswd-file-format/ . This file gave the info for the root account as root:$1$4tVC7zIm$2FuuIL6P8J3H2yXRDrgZk0:0:0:99999:7::: .

I used the password cracker John the Ripper , which tries to brute force the hash. I was confused when it would immediately complete. Eventually, I realized that the root password was blank.

A port scan showed that in addition to the web servers, the box was also running an FTP and telnet server, both of which accepted the root login with a blank password.

Poking Around

Here’s some system info I got from poking around

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@anyua ~]$ uname -a
Linux anyka 3.4.35 #30 Thu Aug 13 12:25:29 UTC 2020 armv5tejl GNU/Linux

[root@anyka ~]$ cat /proc/cmdline
console=ttySAK0,115200n8 root=/dev/mtdblock4 rootfstype=squashfs init=/sbin/init mem=64M flash=SF device_id=00000000000 ethaddr=00:55:7b:b5:7d:f7 devinfo=jcoxxx memsize=64M

[root@anyka ~]$ cat /proc/mtd
dev:    size   erasesize  name
mtd0: 01000000 00001000 "spi0.0"
mtd1: 00200000 00001000 "KERNEL"
mtd2: 00001000 00001000 "MAC"
mtd3: 00001000 00001000 "ENV"
mtd4: 0015e000 00001000 "A"
mtd5: 00032000 00001000 "B"
mtd6: 003e8000 00001000 "C"
mtd7: 005dc000 00001000 "D"

[root@anyka ~]$ top
Mem: 14988K used, 11372K free, 0K shrd, 1480K buff, 4104K cached
CPU:  0.0% usr  0.7% sys  0.0% nic 99.0% idle  0.0% io  0.0% irq  0.1% sirq
Load average: 0.24 0.07 0.03 1/55 521

So it’s running a linux on an ARM processor with 25MB of RAM and a 64MB flash drive.

The script /etc/init.d/rc.local gave most of the startup process, and /mnt/anyka_cfg.ini gave what appeared to be most of the configuration.

It seemed like this system was pretty much just the demo software from the company Anyka, which make combined camera and processor modules. Aside from the configuration files, the only code that seemed to be specific to the Yo product was /usr/bin/server . This binary ran the webserver on port 12913. Dumping the strings with strings /usr/bin/server gave the URL’s from the API. It seems like they made this server to act as glue between the apps and the Anyka camera drivers.

You could make persistent changes to the flash memory, so if I really wanted, i could use this as a RaspPi substitute, or turn it into a security camera.

Tear Down

Disassembling was pretty straight forward. Top popped off, and the rest was just removing the screws for each layer.

The three most interesting chips on the top layer were the:

soc

wifi

Taking this piece off we can see the camera module on the bottom.

wifi

We can also see the Rx and Tx of what’s probably the serial UART for the console output of the processor. This would have been another way to get root access if telnet hadn’t been open.

The rest of the case wasn’t coming apart, but appeared to have a pinhole, to a lens above the slide. Presumable there was some sort of LED below as well.

wifi

Conclusions

This product basically took no efforts to lock itself down, or use any kind of obfuscation, which I appreciate. Since the device is never supposed to be connected to the internet, and is only supposed to be on for a few minutes the total lack of security isn’t really a high concern.

I’m somewhat surprised they didn’t keep their algorithms in the cloud, since it would be relatively trivial to clone their product. However, by keeping everything on your own computers and not needing a cloud component, it ensures you actually have some privacy throughout the process. I imagine they’re not too concerned, since something like this is probably more about the marketing and being able to claim your product is validated against lab results.

It’s interesting to be able to see so much into how this product was put together from it’s technical building blocks. While the algorithm part looks somewhat like it was made in house, most of the rest of the system looks like it could have been contracted out and is mostly built from existing pieces.