Analysis Environment Build report
1. Overview
This document is a team that carried out the BoB 12th NVR Vulnability Analysis project.This is a report described by ENVY (Kim Chan-in, Park Myung-hoon, Shin Myung-jin, Yang Gang-min, Lee Yu-kyeong) on the establishment of the Hikvision analysis environment.
1.1. Necessity
Debugging the binary that is activating the service is essential to proceed with the vulnerability analysis of hikvision. Therefore, in this document, we describe how to debug watchdog by bypassing it.
2. Analysis
If you debug the "sc_hicore" binary using the gdb tool, you can see that it is output as follows.
~~~~~~~~~~~~pid (492) will exit!
~~~~~~~~~~~~FN:[fn_master_status]
~~~~~~~~~~~~iRet [-88][Session Handle Err!!]
[165249.722559] [HKBSP][hik_wdt hik_wdt.1]hik-wdt:hikwdt_isr. I'm so Sorry (>_<)…
[165249.730063] [HKBSP][hik_wdt hik_wdt.1]hik-wdt:hikwdt_isr. last_feedwdt:4311458247(jiffies64:4311461694,timeout:25)
If you look at the log, you can see that the watchdog feeding is rebooted after the timeout. The watchdog feeding timeout is set in the "hisi_watchdog_init" function of the "libplatform.so" file.
HPR_INT32 __fastcall hisi_watchdog_init(HPR_UINT32 uTimeOut)
{
HPR_UINT32 iDogTimeOut; // [sp+Ch] [bp-14h] BYREF
iDogTimeOut = uTimeOut;
if ( h_g_wdFd < 0 )
{
h_g_wdFd = open64("/dev/watchdog", 1);
if ( h_g_wdFd == -1 )
_assert("h_g_wdFd != -1", "src/hisi_bsp.c", 2480);
}
if ( call_ioctl(h_g_wdFd, 0xC0045706, &iDogTimeOut) >= 0 )
{
fprintf((FILE *)stderr, "fun:%s, line:%d ", "hisi_watchdog_init", 2491);
fprintf(
(FILE *)stderr,
"hisi_watchdog_init(%s, %d) ok iDogTimeOut:%d Sec!\n",
"/dev/watchdog",
h_g_wdFd,
iDogTimeOut);
return 0;
}
else
{
if ( util_dbg_open() )
util_debug("src/hisi_bsp.c", 2485, "hisi_watchdog_init", 2, "hisi_watchdog_init error!\n");
return -1;
}
}
When the function is decoded, it can be seen that the timeout is set as much as the "uTimeOut" variable transmitted to the factor. Therefore, it was possible to bypass the watchdog by modifying the part and increasing the time that becomes the timeout.
.text:00010F1C PUSH {R4,R5,LR}
.text:00010F20 SUB SP, SP, #0x14
.text:00010F24 LDR R4, =h_g_iopFd
.text:00010F28 MOV uTimeOut_0, #0xFFFFFFFF
.text:00010F2C LDR R3, [R4,#(h_g_wdFd - 0x49D64)]
.text:00010F30 MOV R5, R4
.text:00010F34 CMP R3, #0
.text:00010F38 BGE loc_10F68
.text:00010F3C LDR uTimeOut_0, =aDevWatchdog ; "/dev/watchdog"
.text:00010F40 MOV R1, #1
.text:00010F44 BL open64
.text:00010F48 STR R0, [R4,#(h_g_wdFd - 0x49D64)]
.text:00010F4C CMN R0, #1
.text:00010F50 BNE loc_10F68
.text:00010F54 LDR R3, =__PRETTY_FUNCTION__.24206 ; "hisi_watchdog_init"
.text:00010F58 MOV R2, #0x9B0 ; line
.text:00010F5C LDR R1, =file ; "src/hisi_bsp.c"
.text:00010F60 LDR R0, =assertion ; "h_g_wdFd != -1"
.text:00010F64 BL __assert
As in the code above, by patching the "uTimeOut" variable to allocate 0xFFFFFFFFFFFFFF, the timeout time could be increased and debugging could be performed.
3. Deploy Analytical Environment Boot Script
I will explain the boot script for increasing watchdog timeout. First of all, the contents of "start.sh " and "S90start_ubifs" were modified as follows.
#!/bin/sh
## This is a start script file for app startup.
## Modify by liweijie for DVR/NVR platform@2015-3-19
mkready_for_start_script()
{
/bin/cp /dav$1/start.sh /tmp/start.sh -f;
if [ -e /dav$1/RSA ]; then
/bin/cp /dav$1/RSA /etc/RSA -f;
/usr/bin/hrsaverify /tmp/start.sh -d
if [ $? == 0 ]; then
echo ""
else
echo "rsaverify start.sh error !!!"
if [ $1 == "0" ]; then
echo "system reboot from backup partition !!!"
elif [ $1 == "1" ]; then
echo "system reboot must after update or autoupdate !!!"
fi
[ -e /dav$1/version.bin ] && /bin/rm /dav$1/version.bin -f
/sbin/reboot
/bin/sleep 20
fi
fi
/bin/ded -d /tmp/start.sh /home/start.sh >/dev/null 2>&1
if [ $? == 0 ];then
echo ""
else
echo "ded decrypt start.sh error !!!"
if [ $1 == "0" ]; then
echo "system reboot from backup partition !!!"
elif [ $1 == "1" ]; then
echo "system reboot must after update or autoupdate !!!"
fi
[ -e /dav$1/version.bin ] && /bin/rm /dav$1/version.bin -f
/sbin/reboot
/bin/sleep 20
fi
/bin/rm /tmp/start.sh -f
/bin/chmod 777 /home/start.sh
}
if [ -e /proc/hkvs/ability ] ; then
BOOTMODE=$(/usr/bin/awk -F: "/BOOTMODE/ {print \$2}" /proc/hkvs/ability)
BOOTPART=$(/usr/bin/awk -F:0x "/BOOTPART/ {print \$2}" /proc/hkvs/ability)
HIKDEBUG=$(/usr/bin/awk -F:0x "/DEBUG/ {print \$2}" /proc/hkvs/ability)
fi
if [ "$BOOTMODE" != "ubifs" ]; then
exit 0;
fi
if [ "$BOOTPART" != "" ] ; then
[ -e /home/dav0 ] || /bin/mkdir -p /dav0
[ -e /home/dav1 ] || /bin/mkdir -p /dav1
[ -e /home/dav2 ] || /bin/mkdir -p /dav2
ENODEV=19
for partnum in 0 1 2
do
/usr/sbin/mount_ubifs $partnum
if [ "$?" == "$ENODEV" ] ; then
/bin/echo "Recovering dav"$partnum" partition ..."
/bin/echo $partnum unlock > /proc/hkvs/mtd/mtdprotect
/usr/sbin/format_ubifs $partnum
/usr/sbin/umount_ubifs $partnum
/usr/sbin/mount_ubifs $partnum
/bin/echo $partnum lock > /proc/hkvs/mtd/mtdprotect
fi
done
if [ -e /dav0/version.bin ] ; then
/bin/echo bootpart0 > /proc/hkvs/ability
BOOTPART=0
elif [ -e /dav1/version.bin ] ; then
/bin/echo bootpart1 > /proc/hkvs/ability
BOOTPART=1
else
/bin/echo bootpart0 > /proc/hkvs/ability
/bin/echo "the system is damaged ?"
fi
/bin/echo "bootpart :"$BOOTPART
if [ "$HIKDEBUG" == "1" ]; then
exit 0;
fi
if [ "$BOOTPART" == "0" ] || [ "$BOOTPART" == "1" ] ; then
mkready_for_start_script $BOOTPART;
else
/bin/echo "Boot Partition is error. Please update digicap.dav."
fi
fi
if [ "$HIKDEBUG" == "1" ]; then
exit 0;
fi
if [ -e /home/start.sh ];then
echo -e "\033[34m[ENVY] restart nfs mount\033[0m"
ifconfig lo 127.0.0.1 up
ifconfig eth0 192.168.0.104 up
route add default gw 192.168.0.1
sleep 5
mkdir /nfs
mount -t nfs -o vers=3,nolock 192.168.0.105:/volume1/nfs /nfs
echo -e "\033[34m[ENVY] nfs mount success!\033[0m"
mv /home/start.sh /tmp/start.sh
cp /nfs/booting/hikvision/start.sh /home/start.sh
/home/start.sh&
elif [ -e /home/initrun.sh ];then
/home/initrun.sh&
elif [ -e /opt/start.sh ];then
/opt/start.sh&
fi
In the case of the "S90start_ubifs" script, before executing the "start.sh " script, the network was held and nfs was added to move the modified start.sh .
#!/bin/sh
[ -e /proc/sys/vm/min_free_kbytes ] && echo 8192 > /proc/sys/vm/min_free_kbytes
#echo 1 > /proc/hkvs/ahci_scan
#�豸�����Ϣһ���
sdbg=$(/usr/bin/awk -F 'sdbg=' '{print substr($2,1,1)}' /proc/cmdline)
who=$(/usr/bin/awk -F 'who=' '{print $2}' /proc/cmdline|awk '{print $1}')
data=$(/usr/bin/awk -F 'data=' '{print $2}' /proc/cmdline|awk '{print $1}')
nfsdir=$(/usr/bin/awk -F 'nfsdir=' '{print $2}' /proc/cmdline|awk '{print $1}')
serverip=$(/usr/bin/awk -F: '{print $2}' /proc/cmdline)
gdb=$(/usr/bin/awk -F 'gdb=' '{print $2}' /proc/cmdline|awk '{print $1}')
echo "----------<1> tar all res ----------"
BOOTPART=$(/usr/bin/awk -F:0x "/BOOTPART/ {print \$2}" /proc/hkvs/ability)
/bin/echo "bootpart :"$BOOTPART
if [ "$BOOTPART" == "0" ] ; then
ded -d /dav0/sys_app.tar.lzma /home/app/sys_app.tar.lzma
/bin/tar xaf /home/app/sys_app.tar.lzma -C /home/app/
if [ $? == 0 ];then
echo "decompress sys_app done."
else
echo "decompress sys_app error !!!"
fi
rm -f /home/app/sys_app.tar.lzma
ded -d /dav0/webs.tar.lzma /home/app/webs.tar.lzma
/bin/tar xaf /home/app/webs.tar.lzma -C /home/app/
if [ $? == 0 ];then
echo "decompress webs done."
else
echo "decompress webs error !!!"
fi
rm -f /home/app/webs.tar.lzma
elif [ "$BOOTPART" == "1" ] ; then
ded -d /dav1/sys_app.tar.lzma /home/app/sys_app.tar.lzma
/bin/tar xaf /home/app/sys_app.tar.lzma -C /home/app/
if [ $? == 0 ];then
echo "decompress sys_app done."
else
echo "decompress sys_app error !!!"
fi
rm -f /home/app/sys_app.tar.lzma
ded -d /dav1/webs.tar.lzma /home/app/webs.tar.lzma
/bin/tar xaf /home/app/webs.tar.lzma -C /home/app/
if [ $? == 0 ];then
echo "decompress webs done."
else
echo "decompress webs error !!!"
fi
rm -f /home/app/webs.tar.lzma
else
/bin/echo "Boot Partition is error. Please update digicap.dav."
fi
/bin/tar xzf /home/app/exec/dvrCmd.tar.gz -C /usr/bin/
mv -f /home/app/exec/pppd /usr/bin/
mv -f /home/app/exec/pppoe /usr/bin/
mv -f /home/app/exec/ss /usr/bin/
mv -f /home/app/exec/dropbear /usr/sbin/
mv -f /home/app/exec/dropbearkey /usr/sbin/
mkdir -p /etc/dropbear && cd /etc/dropbear && dropbearkey -t rsa -f dropbear_rsa_host_key&
/bin/chmod 777 /usr/bin/dvrCmd/dvrtools
/bin/chmod 777 /dev/hikio
/bin/chmod 777 /dev/hikpse
/bin/chmod 777 /dev/rtc0
/bin/chmod 777 /dev/watchdog
/bin/chmod 777 /dev/hikstorage
/bin/chmod 777 /dev/hikbsp
/bin/chmod 777 /dev/logo
/bin/chmod 777 /dev/env
/bin/chmod 777 /dev/hikmtd
/bin/chmod 777 /dev/ttyS0
/bin/chmod 777 /dev/ttyS3
if [ "$sdbg" == "s" ] || [ "$sdbg" == "g" ];then
echo "=>Start mount rootfs:${serverip}:/${data}/${who}/nfs/${nfsdir} /tmp"
mount -t nfs -o intr,nolock,rsize=1024,wsize=1024 ${serverip}:/${data}/${who}/nfs/${nfsdir} /tmp
echo "mount over"
cp -f /tmp/sc_hicore /home/app/exec/
cp -f /tmp/hik_dsp /home/app/exec/
cp -f /tmp/hik_dsp_logo /home/app/exec/
cp -f /tmp/libhisdsp.so /home/app/lib/
if [ "$gdb" == "y" ];then
echo "================= gdbserver ===================="
cp -rf /tmp/dev_tools/gdb/hisi_3536C/bin/server /home/app/exec/
cp -rf /tmp/dev_tools/gdb/bin/server /home/app/exec/
cd /home/app/exec/server
/bin/sh run_gdbserver.sh &
cd -
fi
umount /tmp
fi
echo "----------<3> load hisi sdk ----------"
SYSTEM_DDR=`echo | awk -F: '/total_mm/{print $2}' /proc/hkvs/cpldinfo`
OS_DDR=`echo | awk -F: '/os_mm/{print $2}' /proc/hkvs/cpldinfo`
MMZ_DDR=`echo | awk -F: '/mmz_size/{print $2}' /proc/hkvs/cpldinfo`
HAVE9024=`echo | awk -F: '/SII9024/{print $2}' /proc/hkvs/cpldinfo`
HAVE8200=`echo | awk -F: '/THS8200/{print $2}' /proc/hkvs/cpldinfo`
TALKCHIP=`echo | awk -F: '/��Ƶ��������/{print $2}' /proc/hkvs/cpldinfo`
echo "The system mem size is all $SYSTEM_DDR os $OS_DDR mmz$MMZ_DDR 9024:$HAVE9024 8200:$HAVE8200"
echo "####################################load GPU_KO################################################"
mv -f /home/app/lib/* /lib/
cd /home/app/exec/gpu_ko
./loadgpu -i
#0xffea0800��ʾNAU88C10
#chip_paraΪ2����NAU88C10 ,Ϊ1����rt5616
if [ "$TALKCHIP" == "0xffea0800" ];then
chip_param="2"
else
chip_param="1"
fi
cd /home/app/hisi/modules/
/bin/chmod -Rf 777 ./
if [ "$MMZ_DDR" == "256" ]
then
/home/app/hisi/modules/load3536c -i 2 $chip_param
elif [ "$MMZ_DDR" == "384" ]
then
/home/app/hisi/modules/load3536c -i 1 $chip_param
elif [ "$MMZ_DDR" == "768" ]
then
/home/app/hisi/modules/load3536c -i 1 $chip_param
elif [ "$MMZ_DDR" == "180" ] || [ "$MMZ_DDR" == "200" ]
then
echo "MA start with MMZ $MMZ_DDR"
/home/app/hisi/modules/load3536c -i 2 0
fi
cd -
echo "####################################LOGO START################################################"
/home/app/exec/hik_dsp_logo 0 &
mv -f /home/app/lib/* /lib/
echo "load 3536 ok"
echo "----------<4> del no use res ----------"
rm -rf /home/app/hisi
rm -f /home/app/lib/*
rm -f /home/app/exec/dvrCmd.tar.gz
cd /home/app/exec
cp /sbin/vconfig /home/app/exec
/bin/chmod 777 /home/app/exec/vconfig
insmod vca_encrypt.ko
LANGUAGE=$(/usr/bin/awk -F:0x "/Id.language/ {print \$2}" /proc/hkvs/bootparam)
#�ر�TOE����Ҫ��TCP��SACK,��ֹ���绷�������µ��쳣
echo 1 > /proc/sys/net/ipv4/tcp_sack
echo "----------begain to load net filter modules--------"
cd net_filter
./load_netfiter -i
cd ../
/bin/chmod u+x ./iscsi/iscsid
./iscsi/iscsid&
./pppoed&
sleep 1
rm -f pppoed
rm -f iscsi/iscsid
echo 3 > /proc/sys/vm/drop_caches
if [ -e "/proc/sys/tnk/tnk_threshold" ];then
echo 0x100000 > /proc/sys/tnk/tnk_threshold
echo "!!! set tnk_threshold to 1M Ok !!! "
else
echo "!!! the device is not toe !!! "
fi
ulimit -n 8192
MA_RUN_SH="moviRun.sh"
if [ -f /home/app/exec/MA/$MA_RUN_SH ]; then
cd /home/app/exec/MA/
chmod 777 $MA_RUN_SH
./$MA_RUN_SH
cd -
if [ $? == 0 ];then
echo "run ma moviRun.sh ok!"
else
echo "run ma moviRun.sh error!"
fi
fi
#����/tmp/psh�ļ�,�ں˿��Ծݴ��ж��Ƿ���dt��������-psh
echo -n > /tmp/psh
echo -e "\033[34m[ENVY] convert lib!\033[0m"
mv /lib/libplatform.so /lib/libplatform.so.bak
cp /nfs/booting/hikvision/patch_file/libplatform.so /lib/libplatform.so
mv /home/app/exec/sc_hicore /tmp/sc_hicore
cp /nfs/booting/hikvision/patch_file/sc_hicore /home/app/exec/sc_hicore
echo "start to start hik_dsp"
/home/app/exec/hik_dsp &
sleep 1
echo "start to start hik_app"
/home/app/exec/netOpenProc &
chmod 777 ./GPLProc
/home/app/exec/GPLProc &
sleep 1
/home/app/exec/master -M -P /home/app/exec &
# ���������ɾ���Ŀ¼�µij����ļ�
rm -f /home/app/exec/hik_dsp*
cp /home/app/exec/dbmem.html /home/app/webs
# �����������̵Ľ�̺���Ϣд��gdb���������ļ���
if [ "$gdb" == "y" ];then
mkdir /mnt/tools
echo "=>Start mount $serverip:/${data}/${who}/nfs/${nfsdir} /mnt/tools"
mount -t nfs -o intr,nolock,rsize=1024,wsize=1024 $serverip:/${data}/${who}/nfs/${nfsdir} /mnt/tools
if [ $? -eq 0 ]; then
echo "mount over"
mkdir -p /mnt/tools/dev_tools/gdb/hisi_3536C/lib
cp -f /lib/* /mnt/tools/dev_tools/gdb/hisi_3536C/lib/
rm /mnt/tools/dev_tools/gdb/hisi_3536C/.config
sleep 1
echo "sc_hicore="`pidof sc_hicore` > /tmp/.config
echo "master="`pidof master` >> /tmp/.config
echo "dspcore="`pidof hik_dsp-1 || pidof hisi_dsp-2 || pidof hisi_dsp` >> /tmp/.config
mv /tmp/.config /mnt/tools/dev_tools/gdb/hisi_3536C/
umount /mnt/tools
fi
fi
The "start.sh" script increased the timeout by allowing the "sc_hicore" binary to run after counting nfs to change "libplatform.so " to patched "libplatform.so " and then moving the patched library to run the "sc_hicore" binary. Therefore, the full script for this is as follows.
#! /bin/sh
echo -e "\\033[34m[ENVY] Starting!\\033[0m"
cat << "EOF"
███████╗███╗ ██╗██╗ ██╗██╗ ██╗
██╔════╝████╗ ██║██║ ██║╚██╗ ██╔╝
█████╗ ██╔██╗ ██║██║ ██║ ╚████╔╝
██╔══╝ ██║╚██╗██║╚██╗ ██╔╝ ╚██╔╝
███████╗██║ ╚████║ ╚████╔╝ ██║
╚══════╝╚═╝ ╚═══╝ ╚═══╝ ╚═╝
EOF
# This is a minmal rcS file for target startup
# Make sure that /proc is mounted.
## Modify by liweijie for DVR/NVR platform @2015-3-19
# Mount device or filesystem listed in /etc/fstab.
/bin/mount -a
# Application start below.
# Show current date.
/bin/date
echo -e "\\033[34m[ENVY] start nfs mount\\033[0m"
ifconfig lo 127.0.0.1 up
ifconfig eth0 192.168.0.104 up
route add default gw 192.168.0.1
sleep 5
mkdir /nfs
mkdir /nfs2
mount -t nfs -o vers=3,nolock 192.168.0.103:/volume3/nfs /nfs
mount -t nfs -o vers=3,nolock 192.168.0.103:/volume2/nfs2 /nfs2
echo -e "\\033[34m[ENVY] nfs mount success!\\033[0m"
mv /etc/rcS.d/S90start_ubifs /tmp/S90start_ubifs
cp /nfs/booting/hikvision/S90start_ubifs /etc/rcS.d/S90start_ubifs
echo -e "\\033[34m[ENVY] convert S90start_ubifs\\033[0m"
for initscript in /etc/rcS.d/S[0-9][0-9]*
do
if [ -x $initscript ] ;
then
echo "[RCS]: $initscript"
$initscript
fi
done
export PATH=$PATH:/nfs/static_binary/bin
echo -e "\\033[34m[ENVY] run dropbear\\033[0m"
dropbear
mv /bin/psh /bin/psh_
ln -s /bin/sh /bin/psh
exit 0
Last updated