Rooting K9608-2W
Let's say you have one of these and you want shell access for some reason, like setting the date & time programatically. By adding a couple magic files to a USB mass storage device, connecting it to your NVR and rebooting, you will be able to login via telnet.
Login to the web user interface of your NVR, go to Settings (wrench and screwdriver icon). If you see the following info listed in the DevInfo tab, then these instructions should work for you. This may work with other software versions too but no promises.
Dev model | K9608-2W |
HW version | 2.1.0 |
SW version | 2.7.13.0_22922330 |
Reldatetime | 2018/10/26 10:58 |
Grab a thumb drive or whatever USB mass storage device is handy. Make sure the partition table is simple and has fat32 as the first primary partition. This is usually the default setup for a new device so you probably don't have to do anything. Mount it and get started making the three files as below in the top level directory.
me@here:/media/me/SANDISK$ echo 1000000001 > enable_log_forever
me@here:/media/me/SANDISK$ cat <<EOF>dvr_app
#!/bin/sh
/usr/sbin/telnetd &
exec /media/usb1/dvr_app_chain "\$@"
EOF
me@here:/media/me/SANDISK$ cat <<EOF>dvr_app_chain
#!/bin/sh
umount /root/dvr_app/dvr_app
exec /root/dvr_app/dvr_app "\$@"
EOF
me@here:/media/me/SANDISK$
Unmount/eject, pop it in the NVR, reboot the NVR, wait a bit and then telnet to it using the same IP or hostname you used to get to the web interface. Login with username root and password j1/_7sxw
me@here:~$ telnet nvr-host
Trying 192.168.31.337...
Connected to nvr-host.
Escape character is '^]'.
(none) login: root
Password:
Welcome to HiLinux.
# uptime
05:42:38 up 2:35, 1 users, load average: 13.88, 12.32, 11.89
# ls /
a.out bin etc linuxrc mnt oem root sys usr
a2.out dev lib media nfsroot proc sbin tmp var
#
One of the startup scripts contains the following snippet:
if [ -e $MOUNT_DIR/enable_log_forever ];then
echo "enable log2 found."
rv=$(cat $MOUNT_DIR/enable_log_forever)
if [ "$rv" == "1000000001" ];then
if [ -e $MOUNT_DIR/dvr_app ];then
echo "mount bind dvr_app."
mount --bind $MOUNT_DIR/dvr_app /root/dvr_app/dvr_app
fi
In short, if the file enable_log_forever
exists and contains 1000000001
then bind-mount dvr_app
from the USB device over the top of the normal /root/dvr_app/dvr_app
before running it later in the same startup script.
The shell won't allow us to unmount dvr_app
from inside of the script running as that name, so we pass off execution to an arbitrary script called dvr_app_chain
directly from the USB mountpoint. From there, we can unmount our dvr_app
and run the orriginal with the arguments that were passed along the way. Any additional commands that we want to run can be added to either script.
One side effect is that logs will be written to your USB device. Rebooting without this USB device present will revert to running normally without telnetd.
- Kill run_IOTDaemon.sh. It's the script responsible for spawning IOTDaemon once a minute. This service reaches out to ngw.dvr163.com offering remote access to your video along with all sorts of other controls, including a reverse shell.
- Change the root password. Using bind-mount, you can set up a passwd file on your USB mass storage device.
- Run dropbear instead of telnetd.
- Update the squashfs with all of your changes so that you don't depend on the USB mass storage device any more. For extra credit, add an NFS mount to hold larger packages.
- Run ntpd. The clock drift on this thing is terrible. The built in mechanism for ntp is to stop recording, update clock, then start recording again. This is appropriate for a big time shift, but not so hot for regularly maintaining time sync.
Please post comments with suggestions or requests for this document. Have a device you want root on and don't mind sending one to me? Tweet at @octosavvi.
@wes1993
The dump file you uploaded didn't unpack cleanly for me using an older Binwalk v2.1.0. Based on the filename, I'm assuming you dumped twice and compared the results to make sure you got a good dump. Might be worth checking again to be sure you don't get stuck without a recovery method after some failed write attempts.
Your dump file is 16MB. The FW you downloaded is 16.25MB. Since the flash chip on your device likely holds 16MB, the download has an extra 256KB that is not going to fit in the flash. There may be a second chip on the board that gets the extra 256KB or maybe it is just ignored. I haven't dug into the stock update tool for this device so I don't know what the process looks like. But since we have your example dump to compare with, let's take a look.
My approach to lining things up is to identify a few unique segments and find the file offsets for those segments using binwalk or manual exploration:
Short story: these don't really line up. This means that the partition scheme is inconsistent between firmwares, or the update mechanism writes various blocks of the downloaded firmware per instructions in the header. Maybe even both. Looking at the uBoot env, the addresses configured by SPI Flash (sf) commands don't match between devices.
Looking closer at the first section of the downloaded image, we can see the string "UBOOTENV". 52 bytes after the start of that string is a 32-bit Little-Endian 0x00090000. The next string is "KERNEL" and 52 bytes after the start of that string is 0x00120000. Then "ROOTFS" and 0x003a0000. This all lines up perfectly with the offsets we found above. So we are definitely looking at a header section listing offsets in the file to find various important segments. The 32-bits following each file offset looks like a byte count for the data to find in that segment. Other information in the header may indicate where to write this data to on the target device. At the end of the header there is what looks like an md5sum followed by padding that ends at exactly 256KB. So that solves the extra 0.25MB mystery. And since the downloaded firmware image doesn't include a bootloader, you definitely can't just write the image byte-for-byte onto your device. You could try carving the kernel and filesystem out of the download and overwrite on your device, but there are lots of opportunities for this to fail. Especially given the Id segment in your dump telling the device that it is a K8208-W, listing the serial number, and other unique identifiers.
Random interesting thing from your dump 0x00ff2000 appears to be regex for matching MAC addresses starting with upper or lower case:
08:3A:2F Guangzhou Juan Intelligent Tech Joint Stock Co.,Ltd
9C:A3:A9 Guangzhou Juan Optical and Electronical Tech Joint Stock Co., Ltd