Hacking the Hikvision: part 1

OK, you voted to not be lazy, and thus I've stuck to it. Where am I at with upgrading the DS-2CD2132 hikvision cameras? Well, not super far.

We ran into a snag. The new firmware only works in the chinese region. I guess I could accept that, but it does have the english strings in it, and, if i log in and unpack them in place, its correct. So lets talk about how to get there. (the 2nd reason for wanting to have persistent access is I want to run iptables on the device to prevent it from doing more than I am expecting).

OK, we got the serial attached. If you stop the boot in U-Boot (hit ^U), you get a little shell. If we then modify the bootargs to add init=/bin/sh, we end up with a real 'shell' instead of the dreaded 'psh' they use for restricted access.

So

setenv console=ttyS0 initrd=0xc0a00000,0x400000 rw root=/dev/ram dbg=0 init=/bin/sh
boot
 ...
/bin/sh: can't access tty; job control turned off
#

Now we want to run all but the last two lines of /etc/init.d/rcS

/bin/mount -t proc proc /proc
/bin/mount -t sysfs sysfs /sys
/bin/mount -t ramfs ramfs /home
/etc/S_udev

And we are in. But, how to get more software on there?
It seems the dropbear (which we can start as dropbear -R) suffers from this issue, so we can't 'ssh ... cat' to get files in and out of mtdblock.

To make dropbear more useful, lets get rid of the psh shell for root (the device has a hard-coded backdoor user of 'root' with password 'hiklinux'). PS, i decoded the password running mpirun and john-the-ripper.

# cat /etc/passwd                                                                                                
root:ToCOv8qxP13qs:0:0:root:/root/:/bin/psh

OK, lets fix that:

# echo root:ToCOv8qxP13qs:0:0:root:/root/:/bin/sh > /etc/passwd

(this is all in the initramfs, so don't worry, its not permanent yet).

I was going down the path of 'uuencode' and paste it in. Since we have awk, we can write a tiny uudecode:

$ cat uu.awk
function x(l, p) {
        n = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_";
    return index(n, substr(l, p + 1, 1));
}
/^begin/ {}
/^[^be]/ {
        len = x($0, 0);
        for(i = 1; len > 0; i += 4) {
                a = x($0, i);
                b = x($0, i + 1);
                c = x($0, i + 2);
                d = x($0, i + 3);
                printf("%c", a * 4 + b / 16);
                if(len > 1) {
                        printf("%c", b * 16 + c / 4);
                        if(len > 2) {
                                printf("%c", c * 64 + d);
                        }
                }
                len -= 3;
        }
}

However, busybox awk won't output a null:

# awk 'BEGIN {printf "%c%c", 1, 0 }' > /tmp/l
# ls -al /tmp/l
-rw-r--r--    1 root     root             1 Jan 19 00:31 /tmp/l

Making it somewhat tricky to put a new binary on there.
So, we could use echo:

# echo -n -e \\x1\\x0 > /tmp/l
# ls -l /tmp/l# echo -n -e \\x1\\x0 > /tmp/l
# ls -l /tmp/l
-rw-r--r--    1 root     root             2 Jan 19 00:32 /tmp/l

So yeah, we could write some hack that took in a binary, converted it to echo statements, and then paste that in. Let's try.

$ cat convert-to-echo.c                                                                                                     
#include                                                                                                                                            
#include 
#include <sys/types.h>
#include <sys/stat.h>
#include 

int
main(int argc, char **argv)
{
    int fd = open(argv[1], O_RDONLY, 0);
    int i, n;
    char line[16];
    if (fd < 0) { perror("open"); } while ((n = read(fd, line, sizeof(line))) > 0)
    {
        printf("echo -n -e ");
        for (i = 0; i < n; i++)
        {
            printf("\\\\x%x", line[i]);
        }
        printf("\n");
    }
}

OK, that's some good hack. And, OMG, that actually works, we can now cross-compile some new binaries to put in the initramfs (or the mount of /dav) to get us going.

We can get the 'dav' filesystem mounted (its ubifs) via this snippet from /etc/app:

# awk[\042=" \047=']
MTDDEV=`/bin/awk "\\$4==\"\042app_pri\042\" {print \\$1}" /proc/mtd`

# init env variables
APP_PRT=no
CFG_PRT=no
loop=0

if [ "$MTDDEV" == "mtd13:" ] ; then
    if [ "$KRN_PRT" = "pri" ] ; then
        # try app pri: /dev/mtd13
        /usr/sbin/mount_app pri
        APP_PRT=pri
    else # KRN_PRT == sec
        # try app second partition: /dev/mtd14
        /usr/sbin/mount_app sec
        APP_PRT=sec
    fi # end of "$KRN_PRT" == "pri"

    # process cfg partition
    cfg_pri_need_rcy=0

    # try cfg pri: /dev/mtd15
    /usr/sbin/mount_ubifs_prt.sh 15 3 /davinci
    if [ "$?" = "0" ] ; then
        /usr/sbin/check_dir /davinci
        if [ "$?" = "0" ] ; then
            CFG_PRT=pri
        else
            /usr/sbin/umount_ubifs_prt.sh /davinci 3
        fi
    fi

    if [ "$CFG_PRT" = "no" ] ; then
        /bin/echo "format cfg pri partition and mount"
        /usr/sbin/format_ubifs_prt.sh 15 3 cfg_pri
        /bin/mount -t ubifs /dev/ubi3_0 /davinci
        cfg_pri_need_rcy=1
    fi

    #process cfg sec: /dev/mtd16
    /usr/sbin/mount_ubifs_prt.sh 16 4 /config
    if [ "$?" = "0" ] ; then
        /usr/sbin/check_dir /config
        if [ "$?" = "0" ] ; then
                CFG_PRT=sec
        else
            /usr/sbin/umount_ubifs_prt.sh /config 4
        fi
    fi

    if [ "$CFG_PRT" != "sec" ] ; then
        /bin/echo "format cfg sec partition and mount"
        /usr/sbin/format_ubifs_prt.sh 16 4 cfg_sec
        /bin/mount -t ubifs /dev/ubi4_0 /config
        /bin/cp -a /davinci/* /config/
    fi

    if [ "$cfg_pri_need_rcy" = "1" ] ; then
        /bin/echo "recover cfg pri partition"
        /bin/cp -a /config/* /davinci/
    fi

    export APP_PRT
    export CFG_PRT
fi

OK, that's enough for right now, we can get stuff on there, i should be able to patch it w/o trouble now.

5 comments on “Hacking the Hikvision: part 1
  1. db KnownAroundHere says:

    “OK, but you guys said I shouldn’t be lazy.”

    But if others wanted to be lazy, there is always this :
    https://ipcamtalk.com/threads/r0-ds-2cd2x32-brickfixv2-brick-recovery-and-full-upgrade-tool-enhanced.24343/

    • db db says:

      the issue i’m trying to solve is how to make it have an upgraded dropbear and smb libraries.
      but yes, your earlier pointer did help get me going!

  2. db Piotr says:

    How we can read bootargs before modiufication ? What is setup default on cameras ?

  3. db Piotr says:

    And please help me setup console=ttyS0 it is port from my PC ? If i use windows my USB TTL is connected to port example COM3.

    • db db says:

      ttyS0 is the name of the serial port on the camera, it won’t change.
      if you use windows, find a tool like hyperterm for serial, and have it use your com3 usb ttl.

Leave a Reply

Your email address will not be published. Required fields are marked *

*