WNVR201

Night Owl DVR Reset

I recently had a friend lose access to his Night Owl WNVR201 device. He said he lost his password, and I said I'd see what I could do. Through a long day of reverse engineering it, I found out how to reset the password on the device.

My Process

I knew that I'd need to start by getting access to the operating system on the NVR. I started off by taking the top panel off of it, and removing the hard drive in it. When I connected the hard drive to my computer, I noticed that the settings are not stored on the hard drive. It looks like the hard drive is only used to store videos.

Since I didn't see any configuration or operating system files on it, I knew that somewhere on the motherboard, there had to be a flash chip of some kind to store the data.

Looking closely at the board, I saw that it had a MX25L12835FMI-10G chip on the board. This is when I knew I'd need to get my CH341A USB Programmer out of my desk to be able to dump the firmware.

 

Dumping the Firmware

Dumping the firmware is a relatively easy process. To do this, put the breakout board into the programmer with the number 1 lined up with the dot on the silkscreen diagram.

Note that in the picture, the 1 on the board is lined up with the dot on the silk screen diagram.

Plug the cable into the breakout board with the red side aligned with the 1 on the board. Next clip the connector onto the MX25L12835FMI-10G chip on the NVR board with the red cable lined up with the dot on the top of the chip. Plug the programmer into the computer, and you're ready to dump the firmware.

Now that we have the programmer connected properly, we can use flashrom to dump the firmware. Running this command was able to dump the firmware to nvr.bin

flashrom -p ch341a_spi -c "MX25L12835F/MX25L12845E/MX25L12865E" -r Documents/dev/nvr.bin

Analyzing the Firmware

Now that we have the firmware for this device, we need to be able to extract the filesystems in the firmware for analysis. We can do this with binwalk.

binwalk -Me nvr.bin

Once this is done, we can see new folders and files that were pulled out of the firmware.

We now have access to the filesystems on it.

I found a few interesting ones:

  • _nvr.rom.extracted/squashfs-root-1/ contains the applications that run on the device
  • _nvr.rom.extracted/squashfs-root-0/ and _nvr.rom.extracted/squashfs-root/ contain the operating system for the device

I found a script that runs on startup on this device in _nvr.rom.extracted/squashfs-root/root/run_app.sh

This script mounts flash drives attached to the system. Turns out that after mounting the drive, the script checks if a file called restore_factory_config_is_dangerous exists on the drive. If this file exists, it checks the contents of the file.

If the file contains solely 2012, it restores the factory configuration. If the file contains 2017, it restores the factory configuration and resets the users to the default.

Next, this script checks for the file enable_log, and if it's found, it checks if the file contains 1. If the file contains 1, then it enables logging on the device until a reboot occurs.

Next, it checks for enable_log_forever. If this file contains 1000000001, then it enables logging permanently. If dvr_app exists on the drive too, then it will execute that file. If dvr_ui_arm exists on the drive, it will also execute this file.

Next, if enable_disk_log exists on the drive, it will do something (I couldn't figure it out).

Finally, this script checks for sysztool on the drive. If this file exists and contains a1a2a3a4a5b1b2b3b4b5c1c2c3c4c5d1d2d3d4d5a1b2c3d4, then the device will enter uboot fix mode.

My Solution

To reset the password, I created a flash drive with the file restore_factory_config_is_dangerous, and put the number 2017 in it.

When I rebooted the device, I had access to it!

The File I Found

For reference, here's the file that I found on the device that gave me this information.

#!/bin/sh

#Restore machine in remote network
date
ifconfig lo up
ifconfig eth0 192.168.1.114 netmask 255.255.255.0 up
route add default gw 192.168.1.1
echo nameserver 8.8.8.8 >> /etc/resolv.conf

#Mount usb disk
MOUNT_DIR=/media/usb1

# check mount status
if [ -r $MOUNT_DIR ];then
echo "mount dir('$MOUNT_DIR') is exist now!"
else
echo "mount dir('$MOUNT_DIR') isn't exist now!"
mkdir $MOUNT_DIR
sleep 2
fi

HDISK_N='x'
HDISK_ID=0
sleep 1
for i in a b c d e f g h i j k l
do
echo "check sd$i..."
if [ -e /sys/block/sd"$i" ];then
echo "sd$i found..."
rv=$(cat /sys/block/sd"$i"/removable)
if [ "$rv" == "1" ];then
echo "usb media sd$i found..."
for n in 1 2 3 4 5 0
do
udisk_index=$n
if [ "$n" -eq "0" ];then
udisk_index="";
fi
if [ -b "/dev/sd$i$udisk_index" ];then
echo "usb media sd$i$udisk_index found..."
mount -t vfat /dev/sd"$i"$udisk_index $MOUNT_DIR
break;
else
echo "usb media sd$i$udisk_index not found..."
fi
done

break
else
if [ '$HDISK' -eq 'x' ];then
HDISK_N=$i
fi
for n in 1 2
do
if [ -b "/dev/sd$i$n" ];then
echo "disk media sd$i$n found..."
HDISK_ID=$n
break;
else
echo "disk media sd$i$n not found..."
fi
done

fi
else
echo "sd$i... not found"
fi
done

#Restore factory config for machine without keypad
if [ -e $MOUNT_DIR/restore_factory_config_is_dangerous ];then
echo "restore flag found."
rv=$(cat $MOUNT_DIR/restore_factory_config_is_dangerous)
if [ "$rv" == "2012" ];then
echo "restore factory config..."
dd if=/dev/zero of=/dev/mtdblock3 bs=1k seek=10 count=10
mv $MOUNT_DIR/restore_factory_config_is_dangerous $MOUNT_DIR/restore_factory_config_is_dangerous_disable
fi
if [ "$rv" == "2017" ];then
echo "restore factory config && clear user..."
dd if=/dev/zero of=/dev/mtdblock3 bs=1k seek=10 count=256
mv $MOUNT_DIR/restore_factory_config_is_dangerous $MOUNT_DIR/restore_factory_config_is_dangerous_disable
fi
else
echo "restore flag 1 not found."
fi

LOG_REDIRECT=0
if [ -e $MOUNT_DIR/enable_log ];then
echo "enable log found."
rv=$(cat $MOUNT_DIR/enable_log)
if [ "$rv" == "1" ];then
touch /tmp/udisk_loging
echo "enable log..."
LOG_REDIRECT=1
ulimit -c unlimited
ulimit -a
echo "$MOUNT_DIR/%e_%t.core" > /proc/sys/kernel/core_pattern
mv $MOUNT_DIR/enable_log $MOUNT_DIR/disable_log
fi
else
echo "enable log not found."
fi

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

if [ -e $MOUNT_DIR/dvr_ui_arm ];then
echo "mount bind dvr_gui."
mount --bind $MOUNT_DIR/dvr_ui_arm /root/dvr_gui/dvr_gui
fi

touch /tmp/udisk_loging
echo "enable log2..."
LOG_REDIRECT=1
ulimit -c unlimited
ulimit -a
echo "$MOUNT_DIR/%e_%t.core" > /proc/sys/kernel/core_pattern
fi
else
echo "enable log2 not found."
fi

if [ -e $MOUNT_DIR/enable_disk_log ];then
echo "enable disk log found."
if [ '$HDISK_N' -neq 'x' -a "$HDISK_ID" -neq "0" ];then
echo "enable disk log2..."
fi
else
echo "enable disk log not found."
fi

if [ -e $MOUNT_DIR/sysztool ];then
echo "sysztool found."
rv=$(cat $MOUNT_DIR/sysztool)
if [ "$rv" == "a1a2a3a4a5b1b2b3b4b5c1c2c3c4c5d1d2d3d4d5a1b2c3d4" ];then
echo "sysztool enter uboot fix mode"
rm $MOUNT_DIR/sysztool
dd if=/dev/zero of=/dev/mtdblock4 bs=1024 count=32
sleep 2
reboot
fi
fi

#ulimit -c unlimited
#echo "1" > /proc/sys/kernel/core_uses_pid
#echo "/root/rec/a1/%e-%t.core" > /proc/sys/kernel/core_pattern

echo "rmem_default:"
cat /proc/sys/net/core/rmem_default
echo "rmem_max:"
cat /proc/sys/net/core/rmem_max
echo "min_free_kbytes:"
cat /proc/sys/vm/min_free_kbytes

#echo 3000000 > /proc/sys/net/core/rmem_default
echo 3000000 > /proc/sys/net/core/rmem_max
echo 3000 > /proc/sys/vm/min_free_kbytes

# set stack size
ulimit -s 4096

cd /root/module
sh load -i

hwclock -s
echo "do you want to run app.out(y or n)?"
read -t 1 -n 1 char

cd /root/dvr_app;./dvr_resource

if [ "$char" == "n" ];then
login
fi

mount -t tmpfs none /root/rec
cd /root/dvr_app;./dvr_reset

if [ -e "/tmp/dvr_resource_dir/pre_run_app.sh" ] ;
then
echo "[pre_run_app] cp"
cp /tmp/dvr_resource_dir/pre_run_app.sh /tmp
echo "[pre_run_app] chmod"
chmod +x /tmp/pre_run_app.sh
echo "[pre_run_app] running..."
/tmp/pre_run_app.sh
echo "[pre_run_app] finish"
else
echo "[pre_run_app] not found"
fi

if [ "$?" == "0" ];then
CURTIME=`date +%y%m%d_%H%M%S`
LOG_FILE=gui_$CURTIME.log
cd /root/dvr_gui;
if [ "$LOG_REDIRECT" == "1" ];then
./dvr_gui > "$MOUNT_DIR/$LOG_FILE" 2>&1 &
else
./dvr_gui &
fi
cd /root/dvr_app;
if [ "$LOG_REDIRECT" == "1" ];then
LOG_FILE=sys_$CURTIME.log
/root/sysztool.hi 600 > "$MOUNT_DIR/$LOG_FILE" 2>&1 &
LOG_FILE=app_$CURTIME.log
./dvr_app > "$MOUNT_DIR/$LOG_FILE" 2>&1
else
./dvr_app
fi
else
echo "System reset!"
fi

Leave a Reply