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.

@wes1993
Copy link

wes1993 commented Nov 20, 2020

Again really thanks for all your help and patience.
I don’t think is a good idea edit the FS, I think I leave the USB :).

  1. For dropbear I will search on the web or do you have some compiled version?
  2. There is also a way to add ftp support? With my FW they have dropped the FTP and for me is useful!!
  3. Do you have some suggestion on how can I access the camera behind NVR from my lan?
    Some sort of bridging or something else? My goal is to access devices under NVR so I can take images of the cameras directly bypassing the NVR but the NVR still recording.

Thanks a lot
Stefano

@aSmig
Copy link
Author

aSmig commented Nov 20, 2020

I don't have dropbear or ftp binaries handy. But I do have some notes on pulling stills/video.

On my model, I can pull a still .jpg from Channel 1 with http://<host>/cgi-bin/snapshot.cgi?chn=0&u=<user>&p=<pass>. Channel 2 is chn=1, and so on. Computers start counting with 0 while humans are weird and start with 1. Pulling stills with this method does not impact ongoing NVR recordings.

I can pull archived .flv video with http://<host>/cgi-bin/flv.cgi?u=<user>&p=<pass>&mode=time&chn=0&begin=<start>&end=<stop> where start and stop are UTC seconds since epoch. So 2020-11-17 15:27:43 Pacific would be 1605626863. If video isn't available for a given time/channel, I get a 404.

To get stills directly from cameras shouldn't be too hard as my NVR defaults to setting up bridging between the wireless and wired networks. If I create an alias on my host connected to the same LAN with an IP like 172.20.14.123 then I can talk directly to the cameras at their IP addresses 172.20.14.32, etc. I can see a list of the IP's in the NVR management interface. Or just use a network scanner to find them.

Not having any direct experience with your NVR, I'm just speculating that it might work similarly.

@wes1993
Copy link

wes1993 commented Nov 20, 2020

Thanks again for all your help :-D
I have tried this links but won't work with my nvr..:
http:///cgi-bin/snapshot.cgi?chn=0&u=&p=
http:///cgi-bin/flv.cgi?u=&p=&mode=time&chn=0&begin=&end=
If i put the ip address i can access and ping only the nvr from 172.20.14.1 and can't reach other cameras.. :-(

Screen of my route:
image

some suggenstion?
Again thanks a lot
Stefano

@aSmig
Copy link
Author

aSmig commented Nov 21, 2020

I'm assuming that you have replaced and in the URLs above. These are the credentials used in the web interface on the NVR. For me, the default user is "admin". Leaving those blank really shouldn't work. and also can't be blank for me. To see what URL the web interface is using, start up Chrome and load the NVR webpage. When you are at a point where you can do something interesting, like request a still from a camera, press F12 to open the Developer Tools, select the Network tab, then go click the link of interest on the NVR page. In the developer tool-pannel, you should see the URLs being loaded in the File column. Right click and Copy when you find the one you want. There are frequently more parameters provided by the stock web interface than are actually required. So you can experiment with removing things to simplify the URL. Worst case, it will cause the NVR to crash/reboot. But there shouldn't be any harm in that. Maybe it is best to avoid late night tinkering when the NVR could be capturing video that you will want to review later.

Running brctl show br0 will describe the bridge Iface listed in your route output above. Based on the routing table, it appears to include the 172.20.14.0/24 and 192.168.0.0/24 networks. There may be an IP/routing issue on the source computer side. Making sure you set a static IP of 172.20.14.123 or similar and that should be all you need unless the NVR is doing some. Check for packet filtering with iptables -nvL.

There does appear to be a routing issue on the NVR where it is trying to route packets destined for unknown hosts (Internet) via two different gateways: 192.168.0.20 and 192.168.0.1 which may indicate an issue with the DHCP gateway configuration on your network. With two default routes having the same Metric, some packets may be lost if one of those gateways fails. But as previously mentioned, letting this thing talk to the internet is a risk. So broken routing doesn't need to be fixed. This won't impact hosts on the wired network claiming to be in the 172.20.14.0/24 network.

Another option for talking to cameras is to route and NAT through the NVR instead of relying on bridging.

echo 1 >/proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j SNAT --to 172.20.14.1

Then anyone in the 192.168.0.0/24 should be able to talk to a 172.20.14.23 camera by adding a static route for 172.20.14.0/24 to the 192.168.0.x address of the NVR.

To get a little more info about what hosts your NVR sees, try arp -na to list neighbor devices (cameras) that it has been talking to recently. And ifconfig will show you the 192.168.0.x IP which you probably already know.

@wes1993
Copy link

wes1993 commented Nov 22, 2020

Thanks again a lot for your help !! :-D
The first commad brctl show br0:
image
The second command told me not found iptables -nvL :-(
there is some other command to do this:

Then anyone in the 192.168.0.0/24 should be able to talk to a 172.20.14.23 camera by adding a static route for 172.20.14.0/24 to the
192.168.0.x address of the N

This is the best way for my configuration, i have also assigneed a correct ip to my pc bu i can't contact the cameras, only the NVR via 172.20.14.1.

Some other info:

image

image


Via F12 from the webpage of NVR i have only this:
F12:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link rel="icon" href="./favicon.ico" type="image/x-icon" />
  <link rel="stylesheet" href="./dist/style.css">
  <title></title>
</head>

<body>
  <div id="app"></div>
  <script type="text/javascript" src="view1.js"></script>
  <script src="./dist/build.js"></script>
  <script src="./dist/import.js"></script>
  <script src="./main.js"></script>
  <!-- <script type="text/javascript" src="xml.js"></script> -->
  <script type="text/javascript" src="swfobject.js"></script>
  <script>
  </script>
</body>

</html>

The view1.js:

//var dvr_camcnt = Cookie.get("dvr_camcnt");;
var dvr_clientport;
var dvr_ocx;
var dvr_type = "sub";;
var iSetAble, iPlayBack;
var b = true;
var osd_status;
function nvrPlayerInit_IE(dvr_usr, dvr_pwd, dvr_channel) {
	dvr_ocx = document.getElementById("client_ocx");
	try {
		if (dvr_ocx.Version && versionCompare(dvr_ocx.Version, '1, 1, 0, 4') >= 0) {
			dvr_ocx.style.height = '100%'
			document.getElementsByClassName('mask_ipcam')[0].style.display = "none"

		} else {
			document.getElementsByClassName('mask_ipcam')[0].style.display = "block"
			throw '请下载最新版本的控件!';
		}
	} catch (e) {
		b = false;
		load_attract();
	}
	dvr_ocx.m_channel = dvr_channel
	dvr_ocx.SetInfoDispMode(0);
	dvr_ocx.EnableSoundAll(false);
	// $('div.mask_ipcam').css('padding-top',$('.mask_ipcam').height()/2+'px');
	document.getElementsByClassName('mask_ipcam')[0].style['padding-top'] = document.getElementsByClassName('mask_ipcam')[0].offsetHeight / 2 + 'px'
	if (b) {
		dvr_ocx = document.getElementById("client_ocx");
		if (dvr_ocx.GetChannelNum == null) {
			// alert(language_find("alert_OCX_error"));	
			return;
		}
		console.log(window.location.hostname + "," + window.location.port+","+dvr_usr+","+dvr_pwd);
		var ret = dvr_ocx.CheckConnect(window.location.hostname, parseInt(window.location.port == "" ? "10000" : window.location.port), dvr_usr, dvr_pwd);
		console.log(ret)
		// if(ret != true)
		// {
		// 	alert("alert_Connect_error");
		// }
	}
};
function nvrPlayerInit_webKit(dvr_usr, dvr_pwd) {
	dvr_type = "sub";

	var flashvars =
		{
			player_max: 16,
			usr: dvr_usr,
			pwd: dvr_pwd
		};
	var params =
		{
			player_max: 16,
			allowFullScreen: "true"
		};
	var attributes =
		{
			id: "viewer",
			name: "viewer"
		};
	swfobject.embedSWF("JaViewer.swf?player_max=4", "flashcontent", "100%", "100%", "10.2.0", "expressinstall.swf", flashvars, params, attributes);
}

window.onunload = function () {
	dvr_ocx.CloseAll();
};
window.onbeforeunload = function () {
	dvr_ocx.CloseAll();
};


function get_file_name(full_path) {
	var arr = full_path.split("/");
	return arr[arr.length - 1];
}

function ptz_send(cmd) {
	var chn = dvr_ocx.GetSelectChl();
	if (chn == -1) {
		alert("select chn");
		return;
	}

	var xmldoc = loadXMLString("<juan ver=\"0\" squ=\"abcdef\" dir=\"0\" enc=\"1\"><ptzctrl usr=\"" + dvr_usr + "\" pwd=\"" + dvr_pwd + "\" chn=\"" + chn + "\" cmd=\"" + cmd + "\" param=\"0\" /></juan>");
	var xmlstr = toXMLString(xmldoc);
	var ptzctrl_node;
	var errno_attr;
	var errno_value;


	$.ajax({
		type: "GET",
		url: "/cgi-bin/gw.cgi",
		processData: false,
		cache: false,
		data: "xml=" + xmlstr,
		async: true,
		beforeSend: function (XMLHttpRequest) {
			//alert("beforeSend");
		},
		success: function (data, textStatus) {
			//alert("recv:" + data);
			xmldoc = loadXMLString(data);
			ptzctrl_node = xmldoc.selectSingleNode("/juan/ptzctrl");
			if (ptzctrl_node != null) {
				errno_attr = ptzctrl_node.attributes.getNamedItem("errno");
				if (errno_attr != null) {
					errno_value = errno_attr.nodeValue;
					if (errno_value != "0") {
						alert("error!errno=" + errno_value);
					}
				}
			}
		},
		complete: function (XMLHttpRequest, textStatus) {
			//alert("complete:" + textStatus);
		},
		error: function (XMLHttpRequest, textStatus, errorThrown) {
			alert(language_find("alert_Communication_error_please_refresh_or_try_again_later"));
		}
	});
}

function pic_btn_down(img) {
	 dvr_ocx = document.getElementById("client_ocx");
	var file_name = get_file_name(img.src).split("_")[0];
	img.src = "images/" + file_name + "_2.jpg";
	switch (img.id) {
		case "pb_review":
			location.href = "playback.html";
			break;
		case "pb_settings":
			location.href = "settings.html";
			break;
		case "pb_1":
			if (dvr_ocx.GetCurDiv() != 0) {
				dvr_ocx.SetDispWndDivMode(0);
			}
			else {
				dvr_ocx.ChangePage(true);
			}
			break;
		case "pb_4":
			if (dvr_ocx.GetCurDiv() != 1) {
				dvr_ocx.SetDispWndDivMode(1);
			}
			else {
				dvr_ocx.ChangePage(true);
			}
			break;
		case "pb_9":
			if (dvr_ocx.GetCurDiv() != 2) {
				dvr_ocx.SetDispWndDivMode(2);
			}
			else {
				dvr_ocx.ChangePage(true);
			}
			break;
		case "pb_16":
			if (dvr_ocx.GetCurDiv() != 3) {
				dvr_ocx.SetDispWndDivMode(3);
			}
			else {
				dvr_ocx.ChangePage(true);
			}
			break;
		case "pb_16":
			if (dvr_ocx.GetCurDiv() != 3) {
				dvr_ocx.SetDispWndDivMode(3);
			}
			else {
				dvr_ocx.ChangePage(true);
			}
			break;
		case "pb_25":
			if (dvr_ocx.GetCurDiv() != 4) {
				dvr_ocx.SetDispWndDivMode(4);
			}
			else {
				dvr_ocx.ChangePage(true);
			}
			break;
		case "pb_36":
			if (dvr_ocx.GetCurDiv() != 5) {
				dvr_ocx.SetDispWndDivMode(5);
			}
			else {
				dvr_ocx.ChangePage(true);
			}
			break;
		case "pb_ptz_up":
			ptz_send(0);
			break;
		case "pb_ptz_left":
			ptz_send(2);
			break;
		case "pb_ptz_auto":
			ptz_send(8);
			break;
		case "pb_ptz_right":
			ptz_send(3);
			break;
		case "pb_ptz_down":
			ptz_send(1);
			break;
		case "pb_ptz_zd_i":
			ptz_send(9); //PTZ_CMD_IRIS_OPEN
			break;
		case "pb_ptz_zu_i":
			ptz_send(10); //PTZ_CMD_IRIS_CLOSE
			break;
		case "pb_ptz_zd_f":
			ptz_send(14); //PTZ_CMD_FOCUS_NEAR
			break;
		case "pb_ptz_zu_f":
			ptz_send(13); //PTZ_CMD_FOCUS_FAR
			break;
		case "pb_ptz_zd_z":
			ptz_send(12); //PTZ_CMD_ZOOM_IN
			break;
		case "pb_ptz_zu_z":
			ptz_send(11); //PTZ_CMD_ZOOM_OUT
			break;
		case "pb_conn_all":
			//		dvr_ocx.OpenAll();
			for (var i = 0; i < dvr_camcnt; i++) {
				dvr_ocx.OpenStream(i, dvr_type == "main" ? 0 : 1);
			}

			break;
		case "pb_disconn_all":
			for (var i = 0; i < dvr_camcnt; i++) {
				ret = dvr_ocx.GetChannelStatus(i);
				if (ret == true) {
					//dvr_ocx.OpenChannel(i);
					dvr_ocx.CloseStream(i);
				}
			}

			break;
		default:
			var ret;
			var chn = -1;
			var prefix = "chn_status_";
			if (img.id.substring(0, prefix.length) == prefix) {
				chn = parseInt(img.id.split("_")[2], 10);
				ret = dvr_ocx.GetChannelStatus(chn);
				if (ret == true) {
					dvr_ocx.CloseStream(chn);
				}
				else {
					dvr_ocx.OpenStream(chn, dvr_type == "main" ? 0 : 1);
				}
				//dvr_ocx.OpenChannel(chn);

			}
			break;
	}
}

function pic_btn_up(img) {
	var file_name = get_file_name(img.src).split("_")[0];
	img.src = "images/" + file_name + "_3.jpg";

	switch (img.id) {
		case "pb_ptz_up":
		case "pb_ptz_left":
		case "pb_ptz_right":
		case "pb_ptz_down":
		case "pb_ptz_zd_i":
		case "pb_ptz_zu_i":
		case "pb_ptz_zd_f":
		case "pb_ptz_zu_f":
		case "pb_ptz_zd_z":
		case "pb_ptz_zu_z":
			ptz_send(15); //PTZ_CMD_STOP
			break;
		default:
			break;
	}
}

var dvr_mute_all = false;
function audio_sys() {
	dvr_mute_all = !dvr_mute_all;
	dvr_ocx.EnableSoundAll(dvr_mute_all);
	if (dvr_mute_all == false) {
		$("#pb_mute_all")[0].src = "images/audio_close.jpg";
	}
	else {
		$("#pb_mute_all")[0].src = "images/audio_open.jpg";
	}
}

function switch_stream(chs,stream) {
	// dvr_type = $("#lst_type")[0].value;
	// for (var i = 0; i < dvr_camcnt; i++) {
	// 	ret = dvr_ocx.GetChannelStatus(i);
	// 	if (ret == true) {
	// 		//dvr_ocx.OpenChannel(i);
			// dvr_ocx.CloseStream(i);
			// dvr_ocx.OpenStream(i, dvr_type == "main" ? 0 : 1);
	// 	}
	// }
	dvr_ocx.CloseStream(chs);
	dvr_ocx.OpenStream(chs, stream == 0 ? 0 : 1);

	//	location.href = "view1.html?type=" + $("#lst_type")[0].value;
}

function versionCompare(ver1, ver2) {
	ver1array = ver1.replace(/\ /g, '').split(',');
	ver2array = ver2.replace(/\ /g, '').split(',');
	sv1 = parseInt(ver1array[3]) + parseInt(ver1array[2]) * 100 + parseInt(ver1array[1]) * 10000 + parseInt(ver1array[0]) * 1000000;
	sv2 = parseInt(ver2array[3]) + parseInt(ver2array[2]) * 100 + parseInt(ver2array[1]) * 10000 + parseInt(ver2array[0]) * 1000000;
	if (sv1 > sv2) {
		return 1;
	}
	else if (sv1 == sv2) {
		return 0;
	}
	else if (sv1 < sv2) {
		return -1;
	}
}

function load_attract() {
	$('div.mask_ipcam').show();
	var btn = false;
	var timer = setInterval(function () {
		if (!btn) {
			$('a.blink').css('color', '#E6AF14');
			btn = true;
		} else {
			$('a.blink').css('color', '#666');
			btn = false;
		}
	}, 500)

}```


Thanks a lot for your help
Stefano

@wes1993
Copy link

wes1993 commented Nov 23, 2020

I have found the FW and the root password also for the IP camera.
The camera FW is here: http://help.dvr163.com/index.php/572011%E7%B3%BB%E5%88%97%E5%8D%87%E7%BA%A7%E8%BD%AF%E4%BB%B6

I can't find a rtsp or something else stream link, only this:
https://gist.github.com/maxious/c8915a436b532ab09e61bf937295a5d2
But i don't understand how ca i use the link in the wiki.
Thanks a lot
Stefano

@iotola
Copy link

iotola commented Dec 16, 2020

I found this discussion really helpful. I have pretty much done the same as wes1993.
I would like to change the root password. So I was going to bind a new shadow file but there is no passwd command implemented on mine, so I cant create the hash to put in the new shadow file.
Does either of you know how I can make a hash to replace the default root without the passed command implemented?

@aSmig
Copy link
Author

aSmig commented Dec 17, 2020

It is very strange to not have the passwd command. It is normally included in busybox, so they had to set compile options to remove it.

To generate a password hash on another system: openssl passwd -5 on any *NIX based system will ask you for a password and generate a hash based on SHA-256. This will be quite a long hash, so not very friendly to type in, but much more secure than older crypt and MD5. If you want a weaker hash that is shorter, just drop the -5.

Copy link

ghost commented Jan 10, 2021

thanks for this. I was sent a "Victure NK200 CCTV Kit" from Amazon (free for leaving a review) - kit consists of NVR and 4 cameras. The NVR is K8208-W and the IP Cameras are IPG5223-W or IPG5222-W.
Here are my app.out and app.out_chain files:

app.out:

#!/bin/sh
/usr/sbin/telnetd &
mount --bind /media/usb1/passwd /etc/passwd
mount --bind /media/usb1/dummy_daemon.sh /bin/upgrade
mount --bind /media/usb1/dummy_daemon.sh /opt/sbin/hostapd
mount --bind /media/usb1/dummy_daemon.sh /opt/bin/IOTDaemon
for pid in $(pidof iot.Daemon cmd_start.sh upgrade hostapd); do kill -9 $pid; done
exec /media/usb1/app.out_chain

app.out_chain:

#!/bin/sh
ls -l /opt/app/app.out
umount /opt/app/app.out
cd /opt/app
exec ./app.out

All is working well so far, am keeping my eye on netstat output and since the dummy daemon replacement, I see no connections to the Internet

I'm trying to gain root access to the cameras but no joy so far. Only port 80 is open. I've found a Windows App (IPCAMSUITE) that can upgrade firmware, but each time this fails - the camera does appear to take management commands by HTTP, the upgrade does start but when the device reboots, it's still on the same version and the app says failed. In preparation I have a copy of the ROM which I hacked to start a telnet daemon. Short of opening the device up to access UART, I'm out of ideas - what can I do?
This is the camera's ROM: http://download.dvr163.com/IPC/WUXIAN%20%20IPC/IPCAKV3_20200601_IPCAMERA_AK19EV3_3_3_1_57501633.zip

Thanks for all the hard work in this discussion!

@wes1993
Copy link

wes1993 commented Jan 14, 2021

thanks for this. I was sent a "Victure NK200 CCTV Kit" from Amazon (free for leaving a review) - kit consists of NVR and 4 cameras. The NVR is K8208-W and the IP Cameras are IPG5223-W or IPG5222-W.
Here are my app.out and app.out_chain files:

app.out:

#!/bin/sh
/usr/sbin/telnetd &
mount --bind /media/usb1/passwd /etc/passwd
mount --bind /media/usb1/dummy_daemon.sh /bin/upgrade
mount --bind /media/usb1/dummy_daemon.sh /opt/sbin/hostapd
mount --bind /media/usb1/dummy_daemon.sh /opt/bin/IOTDaemon
for pid in $(pidof iot.Daemon cmd_start.sh upgrade hostapd); do kill -9 $pid; done
exec /media/usb1/app.out_chain

app.out_chain:

#!/bin/sh
ls -l /opt/app/app.out
umount /opt/app/app.out
cd /opt/app
exec ./app.out

All is working well so far, am keeping my eye on netstat output and since the dummy daemon replacement, I see no connections to the Internet

I'm trying to gain root access to the cameras but no joy so far. Only port 80 is open. I've found a Windows App (IPCAMSUITE) that can upgrade firmware, but each time this fails - the camera does appear to take management commands by HTTP, the upgrade does start but when the device reboots, it's still on the same version and the app says failed. In preparation I have a copy of the ROM which I hacked to start a telnet daemon. Short of opening the device up to access UART, I'm out of ideas - what can I do?
This is the camera's ROM: http://download.dvr163.com/IPC/WUXIAN%20%20IPC/IPCAKV3_20200601_IPCAMERA_AK19EV3_3_3_1_57501633.zip

Thanks for all the hard work in this discussion!

Hello,
for access via telnet try this:
root
j1/_7sxw
I will wait your reply if work :-D
I have also some infor on how we can capture the stream of the camera
Regards
Stefano

@wes1993
Copy link

wes1993 commented Jan 14, 2021

Hello Again :-D
I have one question, did someone have foud a way to switch from 8 cams to 16 cams?
I have seen that the CPU is the same so i think it's only a software limitation.
Some suggestion?
Best Regards
Stefano

Copy link

ghost commented Jan 15, 2021

the telnet port is closed, so no telnet :(

@iotola
Copy link

iotola commented Jan 18, 2021

Mine is also a Victure NK200 CCTV, and my cameras also only seem to have port 80 open, although my cameras appear to be different to the one you listed. So no telnet on mine either.

@aSmig
Copy link
Author

aSmig commented Jan 21, 2021

@salfordfred, it looks like the TTL UART has a getty running from inittab, so you should be able to physically open up the camera and get root that way. Root password in the firmware image is j1/_7sxw as mentioned by @wes1993. Also in the firmware image you linked, I see that telnetd is available and is even started by /etc/init.d/rcS so maybe something kills it later in the boot process? Maybe try spamming connections to port 23 during boot and see if telnet is ever open. There are plenty of other issues with the firmware including custom binaries that have shell execs like /usr/bin/anyka_ipc, /usr/bin/IOTDaemon and /sbin/nk_upgrade. Not to mention all the various shell scripts running as root with unsanitized input, like DHCP lease parsers, etc. But I'm lazy, so I would just open up a camera and go straight for UART. If nothing else, this would accelerate identifying vulnerabilities which can be accessed remotely across the same model.

Other interesting strings in /usr/bin/anyka_ipc:

/mnt/tf/debug.ini
telnetd &

Which could hint that if the debug.ini file exists on the TF storage, then telnetd will be started. Does your model camera have a Micro-SD card slot? Seems likely to be a dev feature not in production, but worth checking.

Copy link

ghost commented Jan 21, 2021

Thanks for the hints, I also noticed telnetd in rcS, but of course its not running afterwards. There is no micro SD slot, perhaps internally there is? I'll see if I can crack one open without breaking it!

@TippyLion28
Copy link

I was able to use these instructions to get into a similar whitelabel DVR from Amazon https://www.amazon.co.uk/gp/aw/d/B06VTHXDY7/
branded as Sannce.

I'm looking to find the Main Stream so I can create a mobile-friendly user interface for it. The app is horrible and slow :)

Does anyone know where I might find the 1080p stream for this thing? The app uses port 10000 and the Web UI is on port 80. Haven't found anything like an RTSP stream. Just a low-quality snapshot.cgi ;)

@wes1993
Copy link

wes1993 commented Mar 18, 2021

Unfortunately for me no... :(
But if you will find a way please write here or tell me :)

Best Regards
Stefano

@TippyLion28
Copy link

Aww that's a shame... My other idea was to figure out how to get that 172 subnet routed so that devices on my LAN can access the cameras individually. And hope that the camera IP addresses stay the same :D

As you mentioned earlier, iptables doesn't exist on this box so that might prove tricky :(

@wes1993
Copy link

wes1993 commented Mar 18, 2021

The only way for me is connect the camera via the Ethernet cable so i have the IP of my lan then connect the cameras with NVR.
But you won't use the WiFi only ethernet
Bye
Stefano

@TippyLion28
Copy link

Just a thought, would it be possible to route the log files to /dev/null or something? Just to avoid the log files growing and potentially getting too big, and avoiding clutter on the USB?

@wes1993
Copy link

wes1993 commented Mar 18, 2021

For this I have created a script I will attach the script tomorrow but the root is not so useful because the NVR gui is really limited... :(

@TippyLion28
Copy link

Ah awesome cheers, that'll be handy. I think the root is very useful because it gives us an extra level of control, and it lets us poke around and look for things like stream URLs :))

I'm sure I'll think of plenty of other ways to put this root shell to good use :)

@wes1993
Copy link

wes1993 commented Mar 18, 2021

I hope you could find a way and please write here if you find something.
From what I have seen there is an app and Everything in inside this app.
I can’t find the stream etc and the software is JavaScript (shit) that works only with explorer.. I have also tried with wireshark but nothing.... only the camera I have found the stream link but with a custom html header not simple and is H265 only so you couldn’t use wit normal browser

@TippyLion28
Copy link

TippyLion28 commented Mar 19, 2021

I'll keep poking and prodding and I'll log my findings here. I've spoken to Sannce support and they have been as useful as a chocolate teapot... They said there's no way to view the stream directly in VLC... I'm still determined to find a way :D

Interesting stuff in one of the log files:

�[1;31m[     httpd.c:  43]�[0m Add a new cgi "/moo"
�[1;31m[     httpd.c:  43]�[0m Add a new cgi "/snapshot"
�[1;31m[     httpd.c:  43]�[0m Add a new cgi "/cgi-bin/flv.cgi"
�[1;31m[     httpd.c:  43]�[0m Add a new cgi "/bubble/live"
�[1;31m[     httpd.c:  43]�[0m Add a new cgi "/cgi-bin/jscript.cgi"
�[1;31m[     httpd.c:  43]�[0m Add a new cgi "/cgi-bin/gw.cgi"
�[1;31m[     httpd.c:  43]�[0m Add a new cgi "/cgi-bin/snapshot.cgi"
�[1;31m[     httpd.c:  43]�[0m Add a new cgi "/cgi-bin/sp.cgi"
�[1;31m[     httpd.c:  43]�[0m Add a new cgi "/cgi-bin/upload.cgi"
�[1;31m[     httpd.c:  43]�[0m Add a new cgi "/cgi-bin/upgrade_rate.cgi"
�[1;31m[     httpd.c:  43]�[0m Add a new cgi "/cgi-bin/online_upgrade.cgi"
�[1;31m[     httpd.c:  43]�[0m Add a new cgi "/index.cgi"
�[1;31m[     httpd.c:  43]�[0m Add a new cgi "/debug.cgi"

@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

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