Hacking A Reolink NVR

Dec 8, 2018 @ 7:38pm

So I recently saw a great Amazon deal, the Reolink NVR (RLN8-410) with 4 POE cameras was $320 so I grabbed that and 1 Amcrest 4K camera (IP8M-2493EW). I got it setup and immediately found two things, while it completely supports ONVIF (an open, XML-SOAP based protocol to communicate with security cams and NVRs), there is no web interface (they claim there is, but it's an browser addon that only works on Windows and Mac). They also have a desktop client, but surprise it too doesn't work on Linux.

I then tried getting my Amcrest camera working, and it oddly doesn't work, it sees it, and then says it's offline, and then finds it again when I hit scan, but with a different port (port 80) and refuses to connect, trying to delete it or scan again just crashes the UI. So obviously it's connecting and not working. All well.

All of this has made me determined to change the NVR software, get something open, that I can get to read my 4K camera, that will allow me to download history via Linux, and something with a functional web interface. This is going to be my story on hacking the RLN8-410

Note: If you just want to know how to root your NVR, jump to the bottom

So my first thought, check for telnet/ssh or something easy to get shell access with:

$ nmap Starting Nmap 7.70 ( https://nmap.org ) at 2018-12-08 20:14 EST Nmap scan report for Host is up (0.0020s latency). Not shown: 994 closed ports PORT STATE SERVICE 80/tcp open http 443/tcp open https 554/tcp open rtsp 6001/tcp open X11:1 8000/tcp open http-alt 9000/tcp open cslistener Nmap done: 1 IP address (1 host up) scanned in 0.10 seconds

Nope, nothing easy, but I might investigate them later.

So my next thought is these things are never designed with security in mind, so lets grab the firmware from their site, RLN8-410_180811/HI3535_NVR_8IP_REOLINK_L300_0811_4509_1606.6MP.pak, I already flashed it after buying to see if that fixed my problems, it didn't. My first thought was see if I can just unpack it (sometimes these things are tarballs that are unpacked prior to flashing).

$ file RLN8-410_180811/HI3535_NVR_8IP_REOLINK_L300_0811_4509_1606.6MP.pak RLN8-410_180811/HI3535_NVR_8IP_REOLINK_L300_0811_4509_1606.6MP.pak: data

Nope, no idea, what about hexdump?

$ hexdump -C -n100 RLN8-410_180811/HI3535_NVR_8IP_REOLINK_L300_0811_4509_1606.6MP.pak 00000000 13 59 72 32 a9 20 21 5a 02 23 00 00 75 62 6f 6f |.Yr2. !Z.#..uboo| 00000010 74 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |t1..............| 00000020 00 00 00 00 00 00 00 00 00 00 00 00 76 31 2e 30 |............v1.0| 00000030 2e 30 2e 31 00 00 00 00 00 00 00 00 00 00 00 00 |.0.1............| 00000040 00 00 00 00 84 05 00 00 d0 37 04 00 00 00 00 00 |.........7......| 00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000060 00 00 00 00 |....| 00000064

Now we are getting somewhere, uboot is a popular embedded bootloader, so can uboot read this file?

mkimage -l RLN8-410_180811/HI3535_NVR_8IP_REOLINK_L300_0811_4509_1606.6MP.pak edman007@caterpillar:~/tmp/nvr-client$

Nope, it doesn't do anything, I'm really not sure what is that (I'd assume some sort of bootloader thing, but I still don't know). I am still struggling to figure out what is at the front of this firmware file, if I want to reflash this device I need to understand the firmware, reading it isn't enough. If anyone know what this is (and more importantly, how to generate it).

My next thought was let's see if we can find anything in it, and for that there is binwalk, lets see what that does.

$ binwalk RLN8-410_180811/HI3535_NVR_8IP_REOLINK_L300_0811_4509_1606.6MP.pak DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 214960 0x347B0 CRC32 polynomial table, little endian 408916 0x63D54 uImage header, header size: 64 bytes, header CRC: 0x5B4BC1EC, created: 2015-06-24 03:30:19, image size: 2358664 bytes, Data Address: 0x80008000, Entry Point: 0x80008000, data CRC: 0x9735E1B3, OS: Linux, CPU: ARM, image type: OS Kernel Image, compression type: none, image name: "Linux-3.4.35_hi3535" 427596 0x6864C xz compressed data 2767644 0x2A3B1C CramFS filesystem, little endian, size: 4206592 version 2 sorted_dirs CRC 0x6BFDA868, edition 0, 2620 blocks, 777 files 6974236 0x6A6B1C CramFS filesystem, little endian, size: 13959168 version 2 sorted_dirs CRC 0x3906E558, edition 0, 7916 blocks, 909 files 20933404 0x13F6B1C JPEG image data, JFIF standard 1.01

Now that's helpful, the CRC32 table is checksums, if I ever want to reflash it I'll need some tool to regenerate it. The uImage header is further down in the file, and there is an xz blob, two CramFS images, and then some sort of image.

I extracted all the data (binwalk makes this easy with the -e option), and then I had something to work with.

* The xz data - That's the compressed Linux kernel (decompressing it and running strings on it makes that easy)
* The next is a CramFS filesystem, that is the root filesystem for the NVR
* The next CramFS filesystem, that's more binaries, but I don't recognize the file structure, I'll deal with it later
* An image, I extracted it to get the boot splash. Not very exciting.

Inspecting the RootFS

The rootfs provides a lot of opportunities to see any security holes. First step, /etc/passwd, and /etc/passwd- ...what is that doing there? That's an editor backup, and should never be on your released product. So far piss poor security has already been confirmed. But first the contents of /etc/passwd:


That's got a hash, john the ripper can crack it. After a night of cracking, I got a root password, 20120515. Nice and easy, but I had nowhere to use it. So I continued on.

Next step is the boot process, if I want access I need to know what it does when it boots. In linux that is init, this is the process that calls the first initscript, it's also what setups your login terminals and such. It's configuration file is /etc/inittab, so lets check that out:

$ cat cramfs-root/etc/inittab # <I snipped out some comments> ::sysinit:/etc/init.d/rcS ::sysinit:/bin/mkdir /dev/shm # <snip> # Example of how to put a getty on a serial line (for a terminal) ::respawn:/sbin/getty -L ttyS000 115200 vt100 -n root -I "Auto login as root ..." #::respawn:/sbin/getty -L ttyS1 9600 vt100 # # Example how to put a getty on a modem line. #::respawn:/sbin/getty 57600 ttyS2 # Stuff to do when restarting the init process ::restart:/sbin/init # Stuff to do before rebooting ::ctrlaltdel:/sbin/reboot ::shutdown:/bin/umount -a -r ::shutdown:/sbin/swapoff -a

So, first thing... "Auto login as root ..." What? Really? that's ttyS000, that means a root shell is just always open on it's serial port (what serial port?). So I finally broke down and opened it up, and right in the middle was an empty connector labeled "UART", which is low voltage serial. So I just need a UART device to connect to it. I looked around and I had both a BeagleBone and a Raspberry Pi near me with UART. So I grabbed the BeagleBone and pulled the front panel USB cable off the NVR (this used the same connector as the UART connector), in the process I broke the connector (it was glued in place) but that was fine. I plugged it in, use the voltmeter and checked the voltages with respect to ground (the chassis), the rear most wire was 5V (power), the front most was 0V (ground), and the middle two were 3-ish. I isolated the 5V power so as to not back power the BeagleBone's power supply and connected the rest up. It just worked, I got a "#", so I had a root shell.

# minicom -b 115200 -D /dev/ttyO1 Welcome to minicom 2.7 OPTIONS: I18n Compiled on Apr 22 2017, 09:14:19. Port /dev/ttyO1, 01:30:25 Press CTRL-A Z for help on special keys # # uname -a Linux (none) 3.4.35_hi3535 #6 SMP Wed Jun 24 11:30:14 CST 2015 armv7l GNU/Linux # cat /proc/cpuinfo Processor : ARMv7 Processor rev 1 (v7l) processor : 0 BogoMIPS : 1987.37 processor : 1 BogoMIPS : 1993.93 Features : swp half thumb fastmult edsp tls CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x4 CPU part : 0xc09 CPU revision : 1 Hardware : hi3535 Revision : 0000 Serial : 0000000000000000

And I've confirmed that it's linux, some poking around shows it's busybox (and not much else), /mnt/sda is the internal hard drive (where it saves all the videos), the root filesystem is read only (so I can't change the password or services that start on boot, not without flashing it). /mnt/app is where the second CramFS image is mounted, it appears to be the SW reolink wrote. Their application is "dvr", so /mnt/app/dvr starts up the Reolink SW. There appears to be some sort of watchdog device running as well, if I kill the dvr process the device reboots a few minutes later. I need more if I want to put my own SW on it. Though now it's not looking too bad, adding a few lines to a boot script somewhere can get me to run my own code on boot, and I can access it via /mnt/sda, I have plenty of space.

So onto boot scripts, I checkout out the rest of the boot process, in /etc/init.d, and I found more good news in /etc/init.d/S90StartSuvr .

# cat /etc/init.d/S90StartSuvr sleep 3; if [ -r /dev/usb/usbhd1 ];then mount -t vfat /dev/usb/usbhd1 /mnt/usb if [ -r /mnt/usb/autoexec.sh ];then chmod +x /mnt/usb/autoexec.sh /mnt/usb/autoexec.sh else echo "autoexec is not ready for running" fi umount -f /mnt/usb else echo "usb is not ready for autoexec" fi # <snip>

That's right, if there is a thumb drive present, formatted as vfat, it will just go ahead and run the script "autoexec.sh" on boot, as root, and let you do whatever. Now that's the lousy security I expected in this kind of device.

So now, the easy way to root this NVR:

1. Get a thumb drive, format it as FAT32 (vfat).
2. Put this script on the root of the drive, named autoexec.sh
#!/bin/sh #start telnetd telnetd

3. Put the thumb drive in and reboot
4. Login via telnet, username is root, password is 20120515

As a note, it seems to be dependent on the thumb drive a bit, my first try was an old crap thumb drive, and I guess the scripts give udev 3 seconds to find it, if it doesn't show up in 3 seconds it won't work. I ended up switching to a nicer USB microSD reader with a high speed microSD card, that works well.

My next step is going to be using debian to get some good SW on here and run whatever I want on it.


What is 4 + 7 minus one?


Feb 16 @ 4:54pm

J'ai réussi à me connecter en telnet sur mon Réolink NVR.
Je suis comme vous bloqué par le logiciel fournit par Réolink, il bloque mes caméras d'autre marque...
Avez vous une idée ?



Feb 17 @ 5:37pm
I'm actually working on getting other software working on mine, I'm planning on installing debian and some different NVR SW (probably kerberos-io) when I get it working.

As for other SW that you can try, I have found out that Reolink appears to be a rebranded dahua NVR, but I don't know if that helps. I did end up buying a dahua NVR that does work with all cameras, though it seems to have problems playing back the video from the reolink cameras.


Mar 23 @ 11:22am
If I get logged in as root, will this allow me to set the NVR to access third party cameras that support ONVIF?


Mar 23 @ 8:59pm
Getting root doesn't make stuff work, but it means the SW can be replaced. I'm currently working on doing that, I'm having some issues with drivers, but I can hopefully get those worked out and get different NVR SW running on this.

As for ONVIF, it should support them already, but at least my Amcrest 4K camera is incompatible. The HW does not appear to support 4K and the SW doesn't fall back to SW decoding.


Apr 14 @ 5:30am
I found that my firmware has a different root password although the version seems to be the same.
However, if you start telnetd with -l/bin/sh parameter you get a root shell without needing to login.

#start telnetd
telnetd -l/bin/sh


May 29 @ 12:27pm
Were you able to install debian on the NVR? Thanks.


Aug 30 @ 2:27pm
Very nice, I have a bricked reolink NVR after failed firmware update same brand I am asking for help:
can we write a script in USB drive: install nvr firmware.pak instead of starting telnet?
how to flash the firmware otherwise
thank you


Sep 11 @ 4:16pm
Awesome work, thank you.