Skip to content

Instantly share code, notes, and snippets.

@aSmig
Last active August 3, 2025 14:26
Show Gist options
  • Save aSmig/e50058a54ab85428915521f233ffa3d0 to your computer and use it in GitHub Desktop.
Save aSmig/e50058a54ab85428915521f233ffa3d0 to your computer and use it in GitHub Desktop.
How to get root on your K9608-2W 8-channel Network Video Recorder

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.

K9608-2W Image

How to know this will work for you

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

Hack

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
# 

Why does this work?

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.

Other suggestions

  • 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.

@TippyLion28
Copy link

I'm particularly interested in /bubble/live, jscript.cgi and debug.cgi

Bubble/live and jscript.cgi seems to hang with their responses, maybe they want specific parameters before they sends a reply.

debug.cgi is telling me username or password mismatch. even when supplying the admin username and password with the u and p parameters

@TippyLion28
Copy link

Another interesting tidbit in the same log file:

ENVIRONMENT: RtspServer default disable

Maybe there is an RTSP server, it's just disabled by default 🤔

@wes1993
Copy link

wes1993 commented Mar 19, 2021

You speak about cameras o NVR?
For cameras you should see also here:
https://gist.github.com/maxious/c8915a436b532ab09e61bf937295a5d2
I have also seen a file where we can enable the RTSP but my cameras won’t have the RTSP library... :(

Keep me updated
Best regards
Stefano

@TippyLion28
Copy link

I'm talking about the NVR. I have not been able to access the cameras via the NVR IP range. (And I don't want to connect to the cameras directly because they are already attached to the wall :D)

@TippyLion28
Copy link

I'm looking at getting dropbear running on the NVR. From what I understand, it needs to be compiled for uClibc. Still researching it :)

@wes1993
Copy link

wes1993 commented Mar 19, 2021

Keep me updated

@wes1993
Copy link

wes1993 commented Mar 19, 2021

Fo the log add this line to the app.out_chain before launch the app.out
rm -rf /media/usb1/app_*

@wes1993
Copy link

wes1993 commented Mar 19, 2021

From what i have seen the eseecloud app use the port 10000 to connect to the NVR but after that i can't find else... :-(

@TippyLion28
Copy link

Attempting to build dropbear for the NVR using my shitey Linux laptop. Takes hours to build lol. Both attempts so far have resulted in dropbear throwing a segfault when I try to launch the binary. Maybe I haven't configured my buildroot correctly?

Maybe @aSmig would be able to shine a light on this?

My current buildroot settings:

Target Architecture: ARM (little endian)
Target Binary Format: ELF
Target Architecture Variant: cortex-A7
Target ABI: I have tried both EABI and EABIhf
Floating point strategy: NEON/VFPv4
ARM instruction set: ARM

@wes1993
Copy link

wes1993 commented Mar 19, 2021

Another interesting tidbit in the same log file:

ENVIRONMENT: RtspServer default disable

Maybe there is an RTSP server, it's just disabled by default 🤔

Sorry,
Where is the path of this log?
P.s. I have also sent and email here:
[email protected]
It’s the developer of this shit... no success for me, but you could try regarding to RTSP stream he write this:

Sorry, the FTP function of the recorder has been eliminated, and the RTSP of the recorder needs to be customized

I hope you will find a way

@TippyLion28
Copy link

Damn it, that's no fun :(

With regards to the log file, I found it inside the log beginning with app_

In other news, I have managed to compile dropbear and I can verify that it prints the version string and even starts a daemon when supplied with the -R argument. However, when you try to connect it crashes with cannot resolve symbol 'getrandom'

It looks like the version of uClibc bundled with the NVR is quite old or missing some component. Perhaps there's a way I can bundle the dropbear binary with its own version of uClibc? Or maybe I need to bind-mount the newer uClibc libraries. I'll investigate :)

@wes1993
Copy link

wes1993 commented Mar 19, 2021

Thanks for the update :)
Sorry but I’m not so expert... I don’t know but we can try to copy the library to the usb?

bye
Stefano

@TippyLion28
Copy link

Please don't be mistaken, I'm not an expert either :)

Maybe we can, but first I'm trying to static link the dropbear binary, then it will not need any external library :)))

@TippyLion28
Copy link

TippyLion28 commented Mar 20, 2021

Okay, static-linking the binary worked! Now when I connect, dropbear wants to create a file inside /etc/dropbear/ but it cannot (for obvious reasons)

Do you by any chance know how to create a NEW mount point within /etc rather than binding one? Then we can redirect this folder to the USB and then dropbear should work :DDDDDD

Alternatively, I could try to modify the source code of dropbear to place the files in /tmp instead :)

@wes1993
Copy link

wes1993 commented Mar 20, 2021

I don’t know because the FS is only write, I could try with mount but from what I remember won’t work... :( i this the best thing is to redirect to /tmp

@wes1993
Copy link

wes1993 commented Mar 20, 2021

P.s. goooooooddd workkkkkk!! :)

@TippyLion28
Copy link

Okay, source code modification it is then :D

As a side note, I asked Sannce support if they could provide some technical information regarding the RTSP stream. Here's what they said:

The product manager said that the RTSP steam of the system is as below:
Mainstream: rtsp://IP:port(website port)/ch0_0.264
Substream: rtsp://IP:port(website port)/ch0_1.264

But we cannot make sure it will work stably because the engineer didn't maintain it anymore.
If you want to use it, please have a try.

This reply, and the entry we saw in the log file about the RTSP server being disabled, leads me to believe that the functionality was unmaintained/unreliable and ultimately it was switched off and is therefore not accessible.

@wes1993
Copy link

wes1993 commented Mar 20, 2021

So firt we need to know, your cameras are H265 or H264?
Because this address seems related to the cameras not the NVR.
Also have you tried to access the cameras telnet?
For access the cameras just change settings of your pc and set an IP address related to subnet of the cameras, should be:
IP: 172.14.10.0 Subnet: 255.255.0.0

@wes1993
Copy link

wes1993 commented Mar 20, 2021

Did you have telegram?

@TippyLion28
Copy link

To be honest, I haven't really looked at accessing the cameras individually. I'm more interested in accessing the NVR and getting the streams from there.

If my attempts fail, I will try to give the cameras static IP addresses and find a way to route from my LAN to the camera subnet.

I do have telegram, but I'm not going to be posting my username here for privacy reasons :)

@wes1993
Copy link

wes1993 commented Mar 20, 2021

Enter here:
https://t.me/joinchat/VTgYk81SmxQ2YTlk

@aSmig, also you if you want could enter here for help us to add RTSP ecc

@TippyLion28
Copy link

I've done it! Dropbear compiled and running on the DVR :)

I had to modify the dropbear source in order to generate hostkeys on the USB instead of /etc/dropbear

If anyone is interested how I did this, I used a buildroot package override to point to a different folder, then I copied the original source from buildroot/output/dropbear into that folder

Then I modified default_options.h and changed the default file paths to point to the USB, and built using that modified source.

When it comes to running the binary file on the DVR, simply use the -R flag, and it'll generate those keys on-the-fly :)

If anyone wants the binary, let me know and I can toss it over :)

@TippyLion28
Copy link

Update on the RTSP situation:

I was able to access the cameras directly by connecting to the NVR's WiFi, and then pointing VLC directly to the camera. Finally!

The way I did this was by logging into the NVR and doing cat /tmp/wps_ap.conf and grabbing the passphrase for the WiFi network from there.

Then I connected up my laptop and set a static IP. Each camera was exposing telnet, RTSP, a Web UI and something on port 8000 which I'm not quite sure about.

Username was admin and password was blank for the Web UI and RTSP, telnet password was j1/_7sxw as mentioned earlier in the thread.

RTSP stream URL was /ch0_0.264 as mentioned by Sannce support team (thanks guys)

My solution will probably be to build some kind of bridge between the NVR subnet and the rest of my LAN using something like a Raspberry Pi. Then I'll probably end up writing a mobile-friendly Web viewer for the streams in React :)

@wes1993
Copy link

wes1993 commented Mar 31, 2021

@aSmig
Hello again aSmig, i need your help again :-(
I have bought another NVR same Chinese stuff (Because i don't want to change the cameras) and i can't manage to use your script.
If i put enable_log_forever i could have telnet (also if i just put enable_log_forever) but won't mount dvr_app, in serial console i have this log:

check sda...
sda found...
usb media sda found...
usb media sda1 found...
restore flag 1 not found.
enable log not found.
enable log2 found.
mount bind dvr_app.
mount: mounting /media/usb1/dvr_app on /root/dvr_app/dvr_app failed: No such file or directory
enable log2...

Did you have some suggestion?
the file dvr_app it's clear nothing there is inside.

Best Regards
Stefano

@wes1993
Copy link

wes1993 commented Apr 1, 2021

News:
I have found a way to access the video stream of the NVR:
You need to use this info here:
https://gist.github.com/maxious/c8915a436b532ab09e61bf937295a5d2

The admin password must be empty (If someone could help me to send also the password it's awesome)

the link is:
http://:/bubble/live?ch=0&stream=0

@quinn-madson
Copy link

@TippyLion28 could you make the dropbear binary available please?

@TippyLion28
Copy link

@quinn-madson I've uploaded a zip here

Use at your own risk, I was having stability issues with my NVR kit while I had the USB plugged in. I'm not sure if that was caused by debug mode or the dropbear binary.

I can't remember if the conf file was neccesary. I believe I copied it from an openwrt ipk while I was fiddling with the NVR kit. It's probably fine to leave that off the stick.

@quinn-madson
Copy link

@TippyLion28 Thank you!

@wes1993
Copy link

wes1993 commented May 17, 2021

@aSmig

Hi wes1993, I took a look at your firmware. It is using a trivial XOR obfuscation. The repeating 64 bytes at the end of the file can be used as the key, starting with 0x5090, ending with 0x8040. Once you remove the XOR layer, you can use binwalk to extract the image normally. Your version of run_app.sh does a bind map on "app.out" to "/opt/app/app.out" instead of "dvr_app". With a few updates to the above, this should get you a root shell.

me@here:/media/me/SANDISK$ echo 1000000001 > enable_log_forever
me@here:/media/me/SANDISK$ cat <<EOF>app.out
#!/bin/sh
/usr/sbin/telnetd &
echo 'toor::0:0:root:/root:/bin/sh' >> /etc/passwd
exec /media/usb1/app.out_chain "\$@"
EOF
me@here:/media/me/SANDISK$ cat <<EOF>app.out_chain
#!/bin/sh
umount /opt/app/app.out
exec /opt/app/app.out "\$@"
EOF
me@here:/media/me/SANDISK$ 

Since the shadow file matches, you might want to check out the Giovision GV-SNVR section of this DEFCON 26 IoT village writeup. I did a quick check with openssl passwd -1 -salt 0dJv11NZ '' and didn't get a match, so adding the alternate password-less root account "toor" above seemed like a good measure. This is obviously not a good long-term method, but should get you in the door.

Drop a comment to let us know how it goes!

Hello again :-D
I have one question, could you help me to decrypt this FW file?
http://download.dvr163.com/NVR/normal--NVR/16lu%20NVR/FWHI3616N6_20200708_NVR_N8216-2_2_8_9_13_23D22310.rar

I'm trying to install the FW via flash programmer but i think that the .ROM i different from .BIN that i have exported from the chip.

And could you help me to know how can i do the decrypt?
Best regards
Stefano

@aSmig
Copy link
Author

aSmig commented May 18, 2021

@wes1993

I have one question, could you help me to decrypt this FW file?
http://download.dvr163.com/NVR/normal--NVR/16lu%20NVR/FWHI3616N6_20200708_NVR_N8216-2_2_8_9_13_23D22310.rar

It doesn't look like there is any crypto or even encoding on that one. After RAR extracting, it looks like a standard image.

I'm trying to install the FW via flash programmer but i think that the .ROM i different from .BIN that i have exported from the chip.

Have a look at the first few bytes of the image you extracted and compare to the .rom to see if a header has been added. It is a fairly common practice for some bytes at the beginning of the image to designate what hardware the following image can run on. If 48 bytes into the .rom looks about the same as the .bin you captured, then just trim off those bytes with something like this: dd if=downloaded.rom of=toflash.bin iflag=skip_bytes skip=48

Good luck!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment