#!/bin/sh # Unpacker for DPT pkg # HappyZ # Thanks to anonymous contributer somewhere on earth # PKG FILE FORMAT # byte 1--4: DPUP - file recognizer # byte 5--8: data offset location A # byte 9--12: total data content size D # byte 13--16: nothing # byte 17--20: sigfile size B # byte 21--(20+B): sigfile data # byte (21+(-B%16)%16)--(25+(-B%16)%16): encrypted data aes key size (BE) C # byte (+1)--(+C): encrypted data aes key bytes # byte (+1)--(+32): initial vector --- up till now bytes shall equal to A # byte (A+1)--(A+D): encrypted data # byte (+1)--(+4): animation header size E # byte (+1)--(+4): animation data size F # byte (+1)--(+4): animation sigfile size G # byte (+1)--(+(-G%16)%16): animation sigfile --- here bytes shall be A+D+E # byte (A+D+E+1)--(A+D+E+F): animation data # zipped data format # FwUpdater # |- boot.img # |- boot.img.md5 # |- system.img # |- system.img.md5 # |- eufwupdater.sh # |- ... # params PKGFILE=$1 # pkg file OUTDIR=$2 # output folder SHA256KEY="./key.pub" DATAKEY_D="./key.private" # predefined outputs SIGFILE="$OUTDIR/signature" AESFILE="$OUTDIR/aes.key" IVFILE="$OUTDIR/init_vector" SIGFILE_ANIM="$OUTDIR/signature_animation" # commands ODUMP="od -A n -t d4 -v" # check if output folder does not exist, make one if [[ ! -d $OUTDIR ]]; then mkdir $OUTDIR; fi if [[ ! -d $OUTDIR ]]; then # check again echo "! Err: looks like we cannot create this folder" exit 0 fi echo "* file header check.." if [ $(head -c 4 $PKGFILE) != "DPUP" ]; then echo "! Err: this seems to be an invalid pkg" exit 0 fi echo "* getting data block size" OFFSET_DATA=`dd if=$PKGFILE bs=4 skip=1 count=1 2>/dev/null | $ODUMP` DATA_SIZE=`dd if=$PKGFILE bs=4 skip=2 count=1 2>/dev/null | $ODUMP` echo "* extract signature.." SIG_SIZE=`dd if=$PKGFILE bs=4 skip=4 count=1 2>/dev/null | $ODUMP` dd if=$PKGFILE of=$SIGFILE bs=1 skip=20 count=$((SIG_SIZE)) 2>/dev/null echo "* verify data with signature.." dd if=$PKGFILE bs=$((OFFSET_DATA)) skip=1 2>/dev/null | head -c $((DATA_SIZE)) | openssl dgst -sha256 -verify $SHA256KEY -signature $SIGFILE 1>/dev/null if [ $? -ne 0 ]; then echo "! Err: failed to verify data with provided signature" exit 0 fi echo "* get encrypted data aes key.." OFFSET_DATAKEY_E=$((20 + SIG_SIZE + ((-(SIG_SIZE % 16)) % 16))) DATAKEY_E_SIZE=`dd if=$PKGFILE bs=1 skip=$OFFSET_DATAKEY_E count=4 2>/dev/null | $ODUMP` OFFSET_DATAKEY_E=$((OFFSET_DATAKEY_E + 4)) echo "** decrypt it via $DATAKEY_D" dd if=$PKGFILE bs=1 skip=$OFFSET_DATAKEY_E count=$((DATAKEY_E_SIZE)) 2>/dev/null | openssl rsautl -decrypt -inkey $DATAKEY_D > $AESFILE echo "* extract 32-byte initial vector.." OFFSET_IV=$((OFFSET_DATAKEY_E + DATAKEY_E_SIZE)) dd if=$PKGFILE of=$IVFILE bs=1 skip=$OFFSET_IV count=32 2>/dev/null echo "* decrypt data to zipped tar.." dd if=$PKGFILE bs=$((OFFSET_DATA)) skip=1 2>/dev/null | head -c $((DATA_SIZE)) | openssl enc -d -aes-256-cbc -K "$(cat $AESFILE)" -iv "$(cat $IVFILE)" > $OUTDIR/decrypted_pkg.tar.gz echo "* unzip data.." tar -xzf $OUTDIR/decrypted_pkg.tar.gz -C $OUTDIR echo "* checking if animation data followed by.." OFFSET_ANIM_HEADER=$((OFFSET_DATA + DATA_SIZE)) ANIM_HEADER_SIZE=`dd if=$PKGFILE bs=1 skip=$OFFSET_ANIM_HEADER count=4 2>/dev/null | $ODUMP` if [ -z "$ANIM_HEADER_SIZE" ]; then ANIM_HEADER_SIZE=0 fi if [[ $((ANIM_HEADER_SIZE)) -gt 0 ]]; then echo "** found animation block, getting animation data size.." ANIM_DATA_SIZE=`dd if=$PKGFILE bs=1 skip=$((OFFSET_ANIM_HEADER + 4)) count=4 2>/dev/null | $ODUMP` echo "** get animation signature.." ANIM_SIG_SIZE=`dd if=$PKGFILE bs=1 skip=$((OFFSET_ANIM_HEADER + 8)) count=4 2>/dev/null | $ODUMP` dd if=$PKGFILE of=$SIGFILE_ANIM bs=1 skip=$((OFFSET_ANIM_HEADER + 12)) count=$(($ANIM_SIG_SIZE)) 2>/dev/null echo "** verify animation data with signature.." OFFSET_ANIM_DATA=$((OFFSET_ANIM_HEADER + ANIM_HEADER_SIZE)) dd if=$PKGFILE bs=$((OFFSET_ANIM_DATA)) skip=1 2>/dev/null | head -c $((ANIM_DATA_SIZE)) | openssl dgst -sha256 -verify $SHA256KEY -signature $SIGFILE_ANIM if [ $? -ne 0 ]; then echo "! Err: failed to verify animation data with provided signature" exit 0 fi echo "** dump animation data to zipped tar.." dd if=$PKGFILE bs=$((OFFSET_ANIM_DATA)) skip=1 2>/dev/null > $OUTDIR/decrypted_animation_pkg.tar.gz echo "** unzip the tar.." tar -xzf $OUTDIR/decrypted_animation_pkg.tar.gz -C $OUTDIR fi