domenica 21 febbraio 2016

Avtech DVR custom firmware - Adding features and easy flash

Author: BigNerd95 (Lorenzo Santina)


Prologue

In my previous article I showed how to extract, fix and flash the firmware with UART to make MJPEG streaming working again.
In this article I'll show you how to add features like telnet and sign the firmware to flash the DVR without opening it.

Preparing Firmware


Extracting firmware


With the last version of binwalk (and all dependences installed), to extract the firmware you only need to run:

$ binwalk -e AppImg_4.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
200           0xC8            JFFS2 filesystem, little endian
It will create a _AppImg_4.bin.extracted folder containing
  • C8.jffs2 (the payload of the firmware, a jffs2 file system)
  • jffs2-root/ (folder containing the extracted jffs2 file system)

Inside "jffs2-root" you will find a folder called "fs_1" containing the root file system.
Here is where we are going to work.

Modding firmware

Due to small size of the ROM, we can't add whatever we want directly inside the firmware image, so a solution is to use the internal Hard Drive and add only few lines of code inside the firmware to load at any boot our additional features.
(On my DVR the Hard Drive is mounted on /mnt/HDD0 and USB Drive is mounted on /mnt/usb, so I'll use these paths for install and init scripts, but with newer of different firmware this location may vary)
The main script loaded during boot is "dvrApp", it is a bash script containing a lot of commands to launch all the services for recording videos, send notifications, update DDNS and many other things.
At the end of the file, just before the "exit $RETVAL" of the "start" switch case I added the following lines:

#---- [s] EXTENSIONS ----
echo "Loading extensions..."
if [ -f /mnt/usb/avext/install.sh ] && [ ! -f /mnt/HDD0/avext/.installed ]
then
        /mnt/usb/avext/install.sh   # launched after flash to install mods on Hard Drive
fi
if [ -f /mnt/usb/avext/init_usb.sh ] && [ ! -f /mnt/HDD0/avext/.disable_init_usb ]
then
        /mnt/usb/avext/init_usb.sh  # a "backdoor" to prevent bootloop
elif [ -f /mnt/HDD0/avext/init_hdd.sh ]
then
        /mnt/HDD0/avext/init_hdd.sh # main script on internal Hard Drive launched at any boot
fi      
#/bin/sh                            # uncomment to get a command line via UART connection
#---- [e] EXTENSIONS ----
Obtaining something like this:

        [ ... ]

        cp /mnt/mtd/ReleaseResource.sh /bin
        sh /bin/ReleaseResource.sh &

        RETVAL=$?

        #---- [s] EXTENSIONS ----
        echo "Loading extensions..."
        if [ -f /mnt/usb/avext/install.sh ] && [ ! -f /mnt/HDD0/avext/.installed ]
        then
                /mnt/usb/avext/install.sh  
        fi
        if [ -f /mnt/usb/avext/init_usb.sh ] && [ ! -f /mnt/HDD0/avext/.disable_init_usb ]
        then
                /mnt/usb/avext/init_usb.sh  
        elif [ -f /mnt/HDD0/avext/init_hdd.sh ]
        then
                /mnt/HDD0/avext/init_hdd.sh 
        fi 
        #/bin/sh 
        #---- [e] EXTENSIONS ----

        exit $RETVAL
        ;;
  stop)
        echo $"Shutting down mount root file system: ---->"
        # unmount filesystems
        echo
        exit $RETVAL
        ;;
esac

Repacking firmware

Repacking the firmware is still not easy like extracting, but nothing of impossible.
The ROM of my dvr is a nand (--no-cleanmarkers) and it has an erase block size of 128k (--eraseblock=0x20000).
After you installed mtd-utils, inside "fs_1" folder run:

# mkfs.jffs2 -r . -o ../AppImg_4mod.img --eraseblock=0x20000 --little-endian --no-cleanmarkers

Signing Firmware

Inside the firmware i found an executable called "upgradeHdr", who control the firmware integrity before flash the ROM when we made a firmware upgrade from USB drive.
So I reversed it with IDA Pro and I made a set of tools in Python called Avtech-Firmware-Tools to sign, unsign and show info of the firmware on your computer (I'll extend this tool suite in the future to extract and patch the firmware automatically).
It requires python3.

Get original firmware info

Download my tool and run:

$ ./avfwtools.py info -i AppImg_4.bin
** Show firmware info **
Product: H264DVRAV76T_4
Description: img
Version: 1017
Checksum: 0x5278bd53

Sign custom firmware

With the info got from original firmware run:

$ ./avfwtools.py sign -i AppImg_4mod.img -o AppImg_4mod.bin -p H264DVRAV76T_4 -d img -v 1017mod
** Sign firmware **
Product: H264DVRAV76T_4
Description: img
Version: 1017mod
Checksum: 0x5278ce64
Firmware signed successfully
I modified version field to remind me that I have a custom firmware installed.
It's important to not modify the "Description field".
It's normal to get a different checksum, it is what DVR controls when flashing and it is calculated for the current firmware.
Now you have your signed custom firmware in AppImg_4mod.bin

Preparing USB

Now you need a FAT32 formatted USB drive to upgrade the DVR with the custom firmware and install all binaries, script and other many things you want add after flash.

Copy signed custom firmware

In the root of your USB drive copy AppImg_4mod.bin and rename it AppImg_4.bin, like the original.
The DVR checks for this file name when upgrading.

Extensions


Install script

Always in the root of the USB drive make a folder called "avext".
Inside this folder create a text file called "install.sh" with this content:

#!/bin/sh

cp -a /mnt/usb/avext/avext_hdd/ /mnt/HDD0/avext/
chmod 755 /mnt/HDD0/avext/*
touch /mnt/HDD0/avext/.installed

Init script

Inside avext folder create another folder called "avext_hdd", this will be copied in the internal Hard Drive and will contain all the extensions you want to use.
Inside avext_hdd create a text file called "init_hdd.sh" with this content:

#!/bin/sh

#enable telnet access
/mnt/HDD0/avext/busybox-complete telnetd -p 23
In this file you can add anything you want launch at any boot.

Busybox

The firmware is already provided with the busybox, but it is missing a lot of features, so let's download a complete version of the busybox.
For my DVR i downloaded busybox-armv4l but others versions may works too.
Then copy it inside avext_hdd and rename it "busybox-complete".

Final USB structure


For clarity:

- / (usb root)
  |
  |- AppImg_4.bin
  |- avext/
          |
          | - install.sh
          | - avext_hdd/
                       |
                       | - init_hdd.sh
                       | - busybox-complete

Flashing Firmware


Upgrade from USB

Finally we have all ready to install our custom firmware on the DVR.
Connect a mouse to a usb port on the DVR, right click and insert your administrator password (default: 0000 or 1234)
A menu like this will be showed.
Select SYSTEM, the icon at the top right corner.
In system menu go to TOOLS
And select SUBMIT on the right of UPGRADE.
Insert your prepared USB drive and go to take a (italian) coffee.

First boot

The extensions are installed during the first boot, so do NOT remove the USB drive until the DVR is totally booted (wait 5-10 minutes).
Then you can remove the USB drive.

Access the DVR


Telnet

If all went OK, telnet would be accessible, so try to connect.

$ telnet 192.168.2.10
Trying 192.168.2.10...
Connected to 192.168.2.10.
Escape character is '^]'.

avtech login: root
Password: 
Welcome to

        _       __       __   
       / \      \ \     / /  
      / O \      \ \   / /
     / ___ \      \ \ / /
    / /   \ \      \ V /
   /_/     \_\      \_/

For further information check:
http://www.avtech.com.tw/

[root@avtech:/root]#

Default root password of my firmware was "avtech97", cracked with John the Ripper.
If yours is different you can connect with root privileges using an high privileged account of the DVR, like "admin:admin".

Future customizations

Whenever you want add features you can go to /mnt/HDD0/avext/ and modify init_hdd.sh
For example adding:

# change root password
echo "root:pass" | /mnt/HDD0/avext/busybox-complete chpasswd

# start second web server on port 8080
/mnt/HDD0/avext/busybox-complete httpd -p 0.0.0.0:8080 -h /mnt/HDD0/avext/web/
# create a folder called "web" inside avext and put there some html files
If you break something in init_hdd.sh and your DVR stuck in boot loop, create a file called "init_usb.sh" in /avext/ folder of your USB drive and insert it during boot to try solving problem from there (for example enabling only telnet and then fixing from command line).
When things are stable, if you want disable the boot backdoor you can do it creating a file called ".disable_init_usb" inside /mnt/HDD0/avext/

Custom Boot Logo

It's possible to change the boot logo without modify the firmware image.
To change the boot logo you have to create a picture called "custom_logo.bmp" on the root of your USB drive and make the upgrade from tools menu.
custom_logo.bmp must be:
  • about 320 x 240 pixel
  • bitmap format
  • max 8 bit in depth (256 colors)
  • max 128 KB in size

You can easily create it with Paint on Windows and save as bitmap 256 colors, 16 colors or monochromatic.
If you have problem creating it, you can use this one as sample.

That's all!


Enjoy your unlocked DVR!

I hope I was clear, however for any question ask in comments.
I'm not responsible for any damage to your DVR.


6 commenti:

  1. First, I would like to thank you for the detailed info provided.
    I have followed your steps and successfully managed to enable telnet over the DVR, I just want to note about a mistake I made to be avoided.
    "binwalk -e AppImg_4.bin" (AppImg_8.bin in my case) extracted a folder named jffs2-root under it another folder named fs_1 and all the files of the AppImg are under fs_1.
    I have created the image with the fs_1 and the system didn't boot , but fortunately it gave me shell access with the UART interface that made me able to figure out the issue.
    I have transferred all the files under fs_1 to the root directory "jffs2-root" and deleted fs_1.
    Recreated the file and everything went smooth like your tutorial.
    I have found that the root password is right like you said although John the ripper didn't respond to my guess "avtech97" (Must be my problem in using John the Ripper).
    Last thing for educational reason, How did you know that the eraseblock is 0x20000 ?

    RispondiElimina
    Risposte
    1. You are right! Sorry, my mistake, I updated the article.
      I searched the datasheet of my ROM on the internet and it was written in the specifications.
      With a wrong eraseblock it seems to works correctly, but during boot (if you connect with uart) there are a lot of warning, so if in the boot log near the line "Starting run dvr applications:---->" there are no warinings, my eraseblock size shoud be correct for yours too

      Elimina
  2. Dear sir, can you please send me your email to my email (lahiru2pegasus4@gmail.com) i need your help.

    RispondiElimina
  3. Hola tengo un problema en mi dvr avtech que queda en la pantalla H.264 Iniciando y no pasa de ahi. como puedo armar un USB para reinstalar un firmware completo. gracias

    RispondiElimina
    Risposte
    1. You can flash the firmware during an hard reset.
      Extract bin files on the root of a FAT32 formatted usb drive and insert it in the lower usb port of your dvr.
      Open your dvr and make an hard reset following this guide http://soporte.tvc.mx/Ingenieria/BaseDeConocimiento/Hardware%20Reset/KPD677l_Hardware_Reset.pdf

      Elimina