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.
Leave a Reply to db Cancel reply