diff --git a/fw_updater_packer_unpacker/README.md b/fw_updater_packer_unpacker/README.md new file mode 100644 index 0000000..ae4bb57 --- /dev/null +++ b/fw_updater_packer_unpacker/README.md @@ -0,0 +1,27 @@ +# Official Version + +Only support unpacking since we don't have the encryption key to repack it. + +Usage: +``` +chmod +x official_pkg_unpacker_pkg.sh +./official_pkg_unpacker_pkg.sh +``` + +# Unofficial Version + +With modified diagnosis mode, it shall support unofficial pkg. + +Unpacker is the same as official one, except we disabled verification. + +The repacker follows a reversed procedure, but we simply use the data encryption key. + +Usage: +``` +chmod +x unofficial_pkg_unpacker_pkg.sh +chmod +x unofficial_pkg_repacker_pkg.sh + + +./unofficial_pkg_unpacker_pkg.sh +./unofficial_pkg_repacker_pkg.sh +``` \ No newline at end of file diff --git a/fw_updater_packer_unpacker/unpacker_pkg.sh b/fw_updater_packer_unpacker/official_pkg_unpacker_pkg.sh similarity index 100% rename from fw_updater_packer_unpacker/unpacker_pkg.sh rename to fw_updater_packer_unpacker/official_pkg_unpacker_pkg.sh diff --git a/fw_updater_packer_unpacker/repacker_pkg.sh b/fw_updater_packer_unpacker/unofficial_pkg_repacker.sh similarity index 94% rename from fw_updater_packer_unpacker/repacker_pkg.sh rename to fw_updater_packer_unpacker/unofficial_pkg_repacker.sh index 3c29ca4..73086d3 100755 --- a/fw_updater_packer_unpacker/repacker_pkg.sh +++ b/fw_updater_packer_unpacker/unofficial_pkg_repacker.sh @@ -37,7 +37,7 @@ INDIR=$1 # input folder TMPDIR=$INDIR PKGFILE=$1/repacked.pkg # output pkg file SHA256KEY="./key.pub" -SIGKEY="./key.private_sig" # unfortunately we do not have this +SIGKEY="./key.private" # we use data encryption key (ignored anyway) DATAKEY_D="./key.private" @@ -76,10 +76,10 @@ OFFSET_DATA=$((OFFSET_DATA + DATAKEY_E_SIZE + 4)) echo "* sign w/ private key $SIGKEY" openssl dgst -sha256 -sign $SIGKEY -out $TMPDIR/tmp.step4.1 $TMPDIR/tmp.step1 openssl dgst -sha256 -verify $SHA256KEY -signature $TMPDIR/tmp.step4.1 $TMPDIR/tmp.step1 -if [ $? -ne 0 ]; then - echo "! Err: failed to verify sha256 - highly likely $SIGKEY is wrong" - exit 0 -fi +# if [ $? -ne 0 ]; then +# echo "! Err: failed to verify sha256 - highly likely $SIGKEY is wrong" +# exit 0 +# fi SIG_SIZE=$(wc -c < $TMPDIR/tmp.step4.1) if [ $(((-(SIG_SIZE % 16)) % 16)) -gt 0 ]; then echo "! Err: not supported for SIG_SIZE not mutiple of 16" diff --git a/fw_updater_packer_unpacker/unofficial_pkg_unpacker.sh b/fw_updater_packer_unpacker/unofficial_pkg_unpacker.sh new file mode 100755 index 0000000..14be1a8 --- /dev/null +++ b/fw_updater_packer_unpacker/unofficial_pkg_unpacker.sh @@ -0,0 +1,125 @@ +#!/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 +